PageSourceSearch

https://julietroha.com/wp-content/themes/tower/js/snap.js?ver=1

js julietroha.com collected 2026-10-10 01:58:36 UTC 25,731 bytes, 568 lines download raw bytes

1/*
2 * Snap.js
3 *
4 * Copyright 2013, Jacob Kelley - http://jakiestfu.com/
5 * Released under the MIT Licence
6 * http://opensource.org/licenses/MIT
7 *
8 * Github:  http://github.com/jakiestfu/Snap.js/
9 * Version: 1.9.3
10 */
11/*jslint browser: true*/
12/*global define, module, ender*/
13(function(win, doc) {
14    'use strict';
15    var Snap = Snap || function(userOpts) {
16        var settings = {
17            element: null,
18            dragger: null,
19            disable: 'none',
20            addBodyClasses: true,
21            hyperextensible: true,
22            resistance: 0.5,
23            flickThreshold: 50,
24            transitionSpeed: 0.3,
25            easing: 'ease',
26            maxPosition: 266,
27            minPosition: -266,
28            tapToClose: true,
29            touchToDrag: true,
30            slideIntent: 40, // degrees
31            minDragDistance: 5
32        },
33        cache = {
34            simpleStates: {
35                opening: null,
36                towards: null,
37                hyperExtending: null,
38                halfway: null,
39                flick: null,
40                translation: {
41                    absolute: 0,
42                    relative: 0,
43                    sinceDirectionChange: 0,
44                    percentage: 0
45                }
46            }
47        },
48        eventList = {},
49        utils = {
50            hasTouch: ('ontouchstart' in doc.documentElement || win.navigator.msPointerEnabled),
51            eventType: function(action) {
52                var eventTypes = {
53                        down: (utils.hasTouch ? 'touchstart' : 'mousedown'),
54                        move: (utils.hasTouch ? 'touchmove' : 'mousemove'),
55                        up: (utils.hasTouch ? 'touchend' : 'mouseup'),
56                        out: (utils.hasTouch ? 'touchcancel' : 'mouseout')
57                    };
58                return eventTypes[action];
59            },
60            page: function(t, e){
61                return (utils.hasTouch && e.touches.length && e.touches[0]) ? e.touches[0]['page'+t] : e['page'+t];
62            },
63            klass: {
64                has: function(el, name){
65                    return (el.className).indexOf(name) !== -1;
66                },
67                add: function(el, name){
68                    if(!utils.klass.has(el, name) && settings.addBodyClasses){
69                        el.className += " "+name;
70                    }
71                },
72                remove: function(el, name){
73                    if(settings.addBodyClasses){
74                        el.className = (el.className).replace(name, "").replace(/^\s+|\s+$/g, '');
75                    }
76                }
77            },
78            dispatchEvent: function(type) {
79                if (typeof eventList[type] === 'function') {
80                    return eventList[type].call();
81                }
82            },
83            vendor: function(){
84                var tmp = doc.createElement("div"),
85                    prefixes = 'webkit Moz O ms'.split(' '),
86                    i;
87                for (i in prefixes) {
88                    if (typeof tmp.style[prefixes[i] + 'Transition'] !== 'undefined') {
89                        return prefixes[i];
90                    }
91                }
92            },
93            transitionCallback: function(){
94                return (cache.vendor==='Moz' || cache.vendor==='ms') ? 'transitionend' : cache.vendor+'TransitionEnd';
95            },
96            canTransform: function(){
97                return typeof settings.element.style[cache.vendor+'Transform'] !== 'undefined';
98            },
99            deepExtend: function(destination, source) {
100                var property;
101                for (property in source) {
102                    if (source[property] && source[property].constructor && source[property].constructor === Object) {
103                        destination[property] = destination[property] || {};
104                        utils.deepExtend(destination[property], source[property]);
105                    } else {
106                        destination[property] = source[property];
107                    }
108                }
109                return destination;
110            },
111            angleOfDrag: function(x, y) {
112                var degrees, theta;
113                // Calc Theta
114                theta = Math.atan2(-(cache.startDragY - y), (cache.startDragX - x));
115                if (theta < 0) {
116                    theta += 2 * Math.PI;
117                }
118                // Calc Degrees
119                degrees = Math.floor(theta * (180 / Math.PI) - 180);
120                if (degrees < 0 && degrees > -180) {
121                    degrees = 360 - Math.abs(degrees);
122                }
123                return Math.abs(degrees);
124            },
125            events: {
126                addEvent: function addEvent(element, eventName, func) {
127                    if (element.addEventListener) {
128                        return element.addEventListener(eventName, func, false);
129                    } else if (element.attachEvent) {
130                        return element.attachEvent("on" + eventName, func);
131                    }
132                },
133                removeEvent: function addEvent(element, eventName, func) {
134                    if (element.addEventListener) {
135                        return element.removeEventListener(eventName, func, false);
136                    } else if (element.attachEvent) {
137                        return element.detachEvent("on" + eventName, func);
138                    }
139                },
140                prevent: function(e) {
141                    if (e.preventDefault) {
142                        e.preventDefault();
143                    } else {
144                        e.returnValue = false;
145                    }
146                }
147            },
148            parentUntil: function(el, attr) {
149                var isStr = typeof attr === 'string';
150                while (el.parentNode) {
151                    if (isStr && el.getAttribute && el.getAttribute(attr)){
152                        return el;
153                    } else if(!isStr && el === attr){
154                        return el;
155                    }
156                    el = el.parentNode;
157                }
158                return null;
159            }
160        },
161        action = {
162            translate: {
163                get: {
164                    matrix: function(index) {
165
166                        if( !utils.canTransform() ){
167                            return parseInt(settings.element.style.left, 10);
168                        } else {
169                            var matrix = win.getComputedStyle(settings.element)[cache.vendor+'Transform'].match(/\((.*)\)/),
170                                ieOffset = 8;
171                            if (matrix) {
172                                matrix = matrix[1].split(',');
173                                if(matrix.length===16){
174                                    index+=ieOffset;
175                                }
176                                return parseInt(matrix[index], 10);
177                            }
178                            return 0;
179                        }
180                    }
181                },
182                easeCallback: function(){
183                    settings.element.style[cache.vendor+'Transition'] = '';
184                    cache.translation = action.translate.get.matrix(4);
185                    cache.easing = false;
186                    clearInterval(cache.animatingInterval);
187
188                    if(cache.easingTo===0){
189                        utils.klass.remove(doc.body, 'snapjs-right');
190                        utils.klass.remove(doc.body, 'snapjs-left');
191                    }
192
193                    utils.dispatchEvent('animated');
194                    utils.events.removeEvent(settings.element, utils.transitionCallback(), action.translate.easeCallback);
195                },
196                easeTo: function(n) {
197
198                    if( !utils.canTransform() ){
199                        cache.translation = n;
200                        action.translate.x(n);
201                    } else {
202                        cache.easing = true;
203                        cache.easingTo = n;
204
205                        settings.element.style[cache.vendor+'Transition'] = 'all ' + settings.transitionSpeed + 's ' + settings.easing;
206
207                        cache.animatingInterval = setInterval(function() {
208                            utils.dispatchEvent('animating');
209                        }, 1);
210                        
211                        utils.events.addEvent(settings.element, utils.transitionCallback(), action.translate.easeCallback);
212                        action.translate.x(n);
213                    }
214                    if(n===0){
215                           settings.element.style[cache.vendor+'Transform'] = '';
216                       }
217                },
218                x: function(n) {
219                    if( (settings.disable==='left' && n>0) ||
220                        (settings.disable==='right' && n<0)
221                    ){ return; }
222                    
223                    if( !settings.hyperextensible ){
224                        if( n===settings.maxPosition || n>settings.maxPosition ){
225                            n=settings.maxPosition;
226                        } else if( n===settings.minPosition || n<settings.minPosition ){
227                            n=settings.minPosition;
228                        }
229                    }
230                    
231                    n = parseInt(n, 10);
232                    if(isNaN(n)){
233                        n = 0;
234                    }
235
236                    if( utils.canTransform() ){
237                        var theTranslate = 'translate3d(' + n + 'px, 0,0)';
238                        settings.element.style[cache.vendor+'Transform'] = theTranslate;
239                    } else {
240                        settings.element.style.width = (win.innerWidth || doc.documentElement.clientWidth)+'px';
241
242                        settings.element.style.left = n+'px';
243                        settings.element.style.right = '';
244                    }
245                }
246            },
247            drag: {
248                listen: function() {
249                    cache.translation = 0;
250                    cache.easing = false;
251                    utils.events.addEvent(settings.element, utils.eventType('down'), action.drag.startDrag);
252                    utils.events.addEvent(settings.element, utils.eventType('move'), action.drag.dragging);
253                    utils.events.addEvent(settings.element, utils.eventType('up'), action.drag.endDrag);
254                },
255                stopListening: function() {
256                    utils.events.removeEvent(settings.element, utils.eventType('down'), action.drag.startDrag);
257                    utils.events.removeEvent(settings.element, utils.eventType('move'), action.drag.dragging);
258                    utils.events.removeEvent(settings.element, utils.eventType('up'), action.drag.endDrag);
259                },
260                startDrag: function(e) {
261                    // No drag on ignored elements
262                    var target = e.target ? e.target : e.srcElement,
263                        ignoreParent = utils.parentUntil(target, 'data-snap-ignore');
264                    
265                    if (ignoreParent) {
266                        utils.dispatchEvent('ignore');
267                        return;
268                    }
269                    
270                    
271                    if(settings.dragger){
272                        var dragParent = utils.parentUntil(target, settings.dragger);
273                        
274                        // Only use dragger if we're in a closed state
275                        if( !dragParent && 
276                            (cache.translation !== settings.minPosition && 
277                            cache.translation !== settings.maxPosition
278                        )){
279                            return;
280                        }
281                    }
282                    
283                    utils.dispatchEvent('start');
284                    settings.element.style[cache.vendor+'Transition'] = '';
285                    cache.isDragging = true;
286                    cache.hasIntent = null;
287                    cache.intentChecked = false;
288                    cache.startDragX = utils.page('X', e);
289                    cache.startDragY = utils.page('Y', e);
290                    cache.dragWatchers = {
291                        current: 0,
292                        last: 0,
293                        hold: 0,
294                        state: ''
295                    };
296                    cache.simpleStates = {
297                        opening: null,
298                        towards: null,
299                        hyperExtending: null,
300                        halfway: null,
301                        flick: null,
302                        translation: {
303                            absolute: 0,
304                            relative: 0,
305                            sinceDirectionChange: 0,
306                            percentage: 0
307                        }
308                    };
309                },
310                dragging: function(e) {
311                    if (cache.isDragging && settings.touchToDrag) {
312
313                        var thePageX = utils.page('X', e),
314                            thePageY = utils.page('Y', e),
315                            translated = cache.translation,
316                            absoluteTranslation = action.translate.get.matrix(4),
317                            whileDragX = thePageX - cache.startDragX,
318                            openingLeft = absoluteTranslation > 0,
319                            translateTo = whileDragX,
320                            diff;
321
322                        // Shown no intent already
323                        if((cache.intentChecked && !cache.hasIntent)){
324                            return;
325                        }
326
327                        if(settings.addBodyClasses){
328                            if((absoluteTranslation)>0){
329                                utils.klass.add(doc.body, 'snapjs-left');
330                                utils.klass.remove(doc.body, 'snapjs-right');
331                            } else if((absoluteTranslation)<0){
332                                utils.klass.add(doc.body, 'snapjs-right');
333                                utils.klass.remove(doc.body, 'snapjs-left');
334                            }
335                        }
336
337                        if (cache.hasIntent === false || cache.hasIntent === null) {
338                            var deg = utils.angleOfDrag(thePageX, thePageY),
339                                inRightRange = (deg >= 0 && deg <= settings.slideIntent) || (deg <= 360 && deg > (360 - settings.slideIntent)),
340                                inLeftRange = (deg >= 180 && deg <= (180 + settings.slideIntent)) || (deg <= 180 && deg >= (180 - settings.slideIntent));
341                            if (!inLeftRange && !inRightRange) {
342                                cache.hasIntent = false;
343                            } else {
344                                cache.hasIntent = true;
345                            }
346                            cache.intentChecked = true;
347                        }
348
349                        if (
350                            (settings.minDragDistance>=Math.abs(thePageX-cache.startDragX)) || // Has user met minimum drag distance?
351                            (cache.hasIntent === false)
352                        ) {
353                            return;
354                        }
355
356                        utils.events.prevent(e);
357                        utils.dispatchEvent('drag');
358
359                        cache.dragWatchers.current = thePageX;
360                        // Determine which direction we are going
361                        if (cache.dragWatchers.last > thePageX) {
362                            if (cache.dragWatchers.state !== 'left') {
363                                cache.dragWatchers.state = 'left';
364                                cache.dragWatchers.hold = thePageX;
365                            }
366                            cache.dragWatchers.last = thePageX;
367                        } else if (cache.dragWatchers.last < thePageX) {
368                            if (cache.dragWatchers.state !== 'right') {
369                                cache.dragWatchers.state = 'right';
370                                cache.dragWatchers.hold = thePageX;
371                            }
372                            cache.dragWatchers.last = thePageX;
373                        }
374                        if (openingLeft) {
375                            // Pulling too far to the right
376                            if (settings.maxPosition < absoluteTranslation) {
377                                diff = (absoluteTranslation - settings.maxPosition) * settings.resistance;
378                                translateTo = whileDragX - diff;
379                            }
380                            cache.simpleStates = {
381                                opening: 'left',
382                                towards: cache.dragWatchers.state,
383                                hyperExtending: settings.maxPosition < absoluteTranslation,
384                                halfway: absoluteTranslation > (settings.maxPosition / 2),
385                                flick: Math.abs(cache.dragWatchers.current - cache.dragWatchers.hold) > settings.flickThreshold,
386                                translation: {
387                                    absolute: absoluteTranslation,
388                                    relative: whileDragX,
389                                    sinceDirectionChange: (cache.dragWatchers.current - cache.dragWatchers.hold),
390                                    percentage: (absoluteTranslation/settings.maxPosition)*100
391                                }
392                            };
393                        } else {
394                            // Pulling too far to the left
395                            if (settings.minPosition > absoluteTranslation) {
396                                diff = (absoluteTranslation - settings.minPosition) * settings.resistance;
397                                translateTo = whileDragX - diff;
398                            }
399                            cache.simpleStates = {
400                                opening: 'right',
401                                towards: cache.dragWatchers.state,
402                                hyperExtending: settings.minPosition > absoluteTranslation,
403                                halfway: absoluteTranslation < (settings.minPosition / 2),
404                                flick: Math.abs(cache.dragWatchers.current - cache.dragWatchers.hold) > settings.flickThreshold,
405                                translation: {
406                                    absolute: absoluteTranslation,
407                                    relative: whileDragX,
408                                    sinceDirectionChange: (cache.dragWatchers.current - cache.dragWatchers.hold),
409                                    percentage: (absoluteTranslation/settings.minPosition)*100
410                                }
411                            };
412                        }
413                        action.translate.x(translateTo + translated);
414                    }
415                },
416                endDrag: function(e) {
417                    if (cache.isDragging) {
418                        utils.dispatchEvent('end');
419                        var translated = action.translate.get.matrix(4);
420
421                        // Tap Close
422                        if (cache.dragWatchers.current === 0 && translated !== 0 && settings.tapToClose) {
423                            utils.dispatchEvent('close');
424                            utils.events.prevent(e);
425                            action.translate.easeTo(0);
426                            cache.isDragging = false;
427                            cache.startDragX = 0;
428                            return;
429                        }
430
431                        // Revealing Left
432                        if (cache.simpleStates.opening === 'left') {
433                            // Halfway, Flicking, or Too Far Out
434                            if ((cache.simpleStates.halfway || cache.simpleStates.hyperExtending || cache.simpleStates.flick)) {
435                                if (cache.simpleStates.flick && cache.simpleStates.towards === 'left') { // Flicking Closed
436                                    action.translate.easeTo(0);
437                                } else if (
438                                    (cache.simpleStates.flick && cache.simpleStates.towards === 'right') || // Flicking Open OR
439                                    (cache.simpleStates.halfway || cache.simpleStates.hyperExtending) // At least halfway open OR hyperextending
440                                ) {
441                                    action.translate.easeTo(settings.maxPosition); // Open Left
442                                }
443                            } else {
444                                action.translate.easeTo(0); // Close Left
445                            }
446                            // Revealing Right
447                        } else if (cache.simpleStates.opening === 'right') {
448                            // Halfway, Flicking, or Too Far Out
449                            if ((cache.simpleStates.halfway || cache.simpleStates.hyperExtending || cache.simpleStates.flick)) {
450                                if (cache.simpleStates.flick && cache.simpleStates.towards === 'right') { // Flicking Closed
451                                    action.translate.easeTo(0);
452                                } else if (
453                                    (cache.simpleStates.flick && cache.simpleStates.towards === 'left') || // Flicking Open OR
454                                    (cache.simpleStates.halfway || cache.simpleStates.hyperExtending) // At least halfway open OR hyperextending
455                                ) {
456                                    action.translate.easeTo(settings.minPosition); // Open Right
457                                }
458                            } else {
459                                action.translate.easeTo(0); // Close Right
460                            }
461                        }
462                        cache.isDragging = false;
463                        cache.startDragX = utils.page('X', e);
464                    }
465                }
466            }
467        },
468        init = function(opts) {
469            if (opts.element) {
470                utils.deepExtend(settings, opts);
471                cache.vendor = utils.vendor();
472                action.drag.listen();
473            }
474        };
475        /*
476         * Public
477         */
478        this.open = function(side) {
479            utils.dispatchEvent('open');
480            utils.klass.remove(doc.body, 'snapjs-expand-left');
481            utils.klass.remove(doc.body, 'snapjs-expand-right');
482
483            if (side === 'left') {
484                cache.simpleStates.opening = 'left';
485                cache.simpleStates.towards = 'right';
486                utils.klass.add(doc.body, 'snapjs-left');
487                utils.klass.remove(doc.body, 'snapjs-right');
488                action.translate.easeTo(settings.maxPosition);
489            } else if (side === 'right') {
490                cache.simpleStates.opening = 'right';
491                cache.simpleStates.towards = 'left';
492                utils.klass.remove(doc.body, 'snapjs-left');
493                utils.klass.add(doc.body, 'snapjs-right');
494                action.translate.easeTo(settings.minPosition);
495            }
496        };
497        this.close = function() {
498            utils.dispatchEvent('close');
499            action.translate.easeTo(0);
500        };
501        this.expand = function(side){
502            var to = win.innerWidth || doc.documentElement.clientWidth;
503
504            if(side==='left'){
505                utils.dispatchEvent('expandLeft');
506                utils.klass.add(doc.body, 'snapjs-expand-left');
507                utils.klass.remove(doc.body, 'snapjs-expand-right');
508            } else {
509                utils.dispatchEvent('expandRight');
510                utils.klass.add(doc.body, 'snapjs-expand-right');
511                utils.klass.remove(doc.body, 'snapjs-expand-left');
512                to *= -1;
513            }
514            action.translate.easeTo(to);
515        };
516
517        this.on = function(evt, fn) {
518            eventList[evt] = fn;
519            return this;
520        };
521        this.off = function(evt) {
522            if (eventList[evt]) {
523                eventList[evt] = false;
524            }
525        };
526
527        this.enable = function() {
528            utils.dispatchEvent('enable');
529            action.drag.listen();
530        };
531        this.disable = function() {
532            utils.dispatchEvent('disable');
533            action.drag.stopListening();
534        };
535
536        this.settings = function(opts){
537            utils.deepExtend(settings, opts);
538        };
539
540        this.state = function() {
541            var state,
542                fromLeft = action.translate.get.matrix(4);
543            if (fromLeft === settings.maxPosition) {
544                state = 'left';
545            } else if (fromLeft === settings.minPosition) {
546                state = 'right';
547            } else {
548                state = 'closed';
549            }
550            return {
551                state: state,
552                info: cache.simpleStates
553            };
554        };
555        init(userOpts);
556    };
557    if ((typeof module !== 'undefined') && module.exports) {
558        module.exports = Snap;
559    }
560    if (typeof ender === 'undefined') {
561        this.Snap = Snap;
562    }
563    if ((typeof define === "function") && define.amd) {
564        define("snap", [], function() {
565            return Snap;
566        });
567    }
568}).call(this, window, document);

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.