mirror of
				https://github.com/telekom-security/tpotce.git
				synced 2025-10-26 02:04:42 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			785 lines
		
	
	
	
		
			32 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
			
		
		
	
	
			785 lines
		
	
	
	
		
			32 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
| /*! Snap.js v2.0.0-rc1 */
 | |
| (function(win, doc) {
 | |
| 
 | |
|     'use strict';
 | |
| 
 | |
|     // Our export
 | |
|     var Namespace = 'Snap';
 | |
| 
 | |
|     // Our main toolbelt
 | |
|     var utils = {
 | |
| 
 | |
|         /**
 | |
|          * Deeply extends two objects
 | |
|          * @param  {Object} destination The destination object
 | |
|          * @param  {Object} source      The custom options to extend destination by
 | |
|          * @return {Object}             The desination object
 | |
|          */
 | |
|         extend: function(destination, source) {
 | |
|             var property;
 | |
|             for (property in source) {
 | |
|                 if (source[property] && source[property].constructor && source[property].constructor === Object) {
 | |
|                     destination[property] = destination[property] || {};
 | |
|                     utils.extend(destination[property], source[property]);
 | |
|                 } else {
 | |
|                     destination[property] = source[property];
 | |
|                 }
 | |
|             }
 | |
|             return destination;
 | |
|         }
 | |
|     };
 | |
| 
 | |
|     /**
 | |
|      * Our Snap global that initializes our instance
 | |
|      * @param {Object} opts The custom Snap.js options
 | |
|      */
 | |
|     var Core = function( opts ) {
 | |
| 
 | |
|         var self = this;
 | |
| 
 | |
|         /**
 | |
|          * Our default settings for a Snap instance
 | |
|          * @type {Object}
 | |
|          */
 | |
|         var settings = self.settings = {
 | |
|             element: null,
 | |
|             dragger: null,
 | |
|             disable: 'none',
 | |
|             addBodyClasses: true,
 | |
|             hyperextensible: true,
 | |
|             resistance: 0.5,
 | |
|             flickThreshold: 50,
 | |
|             transitionSpeed: 0.3,
 | |
|             easing: 'ease',
 | |
|             maxPosition: 266,
 | |
|             minPosition: -266,
 | |
|             tapToClose: true,
 | |
|             touchToDrag: true,
 | |
|             clickToDrag: true,
 | |
|             slideIntent: 40, // degrees
 | |
|             minDragDistance: 5
 | |
|         };
 | |
| 
 | |
|         /**
 | |
|          * Stores internally global data
 | |
|          * @type {Object}
 | |
|          */
 | |
|         var cache = self.cache = {
 | |
|             isDragging: false,
 | |
|             simpleStates: {
 | |
|                 opening: null,
 | |
|                 towards: null,
 | |
|                 hyperExtending: null,
 | |
|                 halfway: null,
 | |
|                 flick: null,
 | |
|                 translation: {
 | |
|                     absolute: 0,
 | |
|                     relative: 0,
 | |
|                     sinceDirectionChange: 0,
 | |
|                     percentage: 0
 | |
|                 }
 | |
|             }
 | |
|         };
 | |
| 
 | |
|         var eventList = self.eventList = {};
 | |
| 
 | |
|         utils.extend(utils, {
 | |
| 
 | |
|             /**
 | |
|              * Determines if we are interacting with a touch device
 | |
|              * @type {Boolean}
 | |
|              */
 | |
|             hasTouch: ('ontouchstart' in doc.documentElement || win.navigator.msPointerEnabled),
 | |
| 
 | |
|             /**
 | |
|              * Returns the appropriate event type based on whether we are a touch device or not
 | |
|              * @param  {String} action The "action" event you're looking for: up, down, move, out
 | |
|              * @return {String}        The browsers supported event name
 | |
|              */
 | |
|             eventType: function(action) {
 | |
|                 var eventTypes = {
 | |
|                     down: (utils.hasTouch ? 'touchstart' : settings.clickToDrag ? 'mousedown' : ''),
 | |
|                     move: (utils.hasTouch ? 'touchmove' : settings.clickToDrag ? 'mousemove' : ''),
 | |
|                     up: (utils.hasTouch ? 'touchend' : settings.clickToDrag ? 'mouseup': ''),
 | |
|                     out: (utils.hasTouch ? 'touchcancel' : settings.clickToDrag ? 'mouseout' : '')
 | |
|                 };
 | |
|                 return eventTypes[action];
 | |
|             },
 | |
| 
 | |
|             /**
 | |
|              * Returns the correct "cursor" position on both browser and mobile
 | |
|              * @param  {String} t The coordinate to retrieve, either "X" or "Y"
 | |
|              * @param  {Object} e The event object being triggered
 | |
|              * @return {Number}   The desired coordiante for the events interaction
 | |
|              */
 | |
|             page: function(t, e){
 | |
|                 return (utils.hasTouch && e.touches.length && e.touches[0]) ? e.touches[0]['page'+t] : e['page'+t];
 | |
|             },
 | |
| 
 | |
| 
 | |
|             klass: {
 | |
| 
 | |
|                 /**
 | |
|                  * Checks if an element has a class name
 | |
|                  * @param  {Object}  el   The element to check
 | |
|                  * @param  {String}  name The class name to search for
 | |
|                  * @return {Boolean}      Returns true if the class exists
 | |
|                  */
 | |
|                 has: function(el, name){
 | |
|                     return (el.className).indexOf(name) !== -1;
 | |
|                 },
 | |
| 
 | |
|                 /**
 | |
|                  * Adds a class name to an element
 | |
|                  * @param  {Object}  el   The element to add to
 | |
|                  * @param  {String}  name The class name to add
 | |
|                  */
 | |
|                 add: function(el, name){
 | |
|                     if(!utils.klass.has(el, name) && settings.addBodyClasses){
 | |
|                         el.className += " "+name;
 | |
|                     }
 | |
|                 },
 | |
| 
 | |
|                 /**
 | |
|                  * Removes a class name
 | |
|                  * @param  {Object} el   The element to remove from
 | |
|                  * @param  {String} name The class name to remove
 | |
|                  */
 | |
|                 remove: function(el, name){
 | |
|                     if(utils.klass.has(el, name) && settings.addBodyClasses){
 | |
|                         el.className = (el.className).replace(name, "").replace(/^\s+|\s+$/g, '');
 | |
|                     }
 | |
|                 }
 | |
|             },
 | |
| 
 | |
|             /**
 | |
|              * Dispatch a custom Snap.js event
 | |
|              * @param  {String} type The event name
 | |
|              */
 | |
|             dispatchEvent: function(type) {
 | |
|                 if( typeof eventList[type] === 'function') {
 | |
|                     return eventList[type].apply();
 | |
|                 }
 | |
|             },
 | |
| 
 | |
|             /**
 | |
|              * Determines the browsers vendor prefix for CSS3
 | |
|              * @return {String} The browsers vendor prefix
 | |
|              */
 | |
|             vendor: function(){
 | |
|                 var tmp = doc.createElement("div"),
 | |
|                     prefixes = 'webkit Moz O ms'.split(' '),
 | |
|                     i;
 | |
|                 for (i in prefixes) {
 | |
|                     if (typeof tmp.style[prefixes[i] + 'Transition'] !== 'undefined') {
 | |
|                         return prefixes[i];
 | |
|                     }
 | |
|                 }
 | |
|             },
 | |
| 
 | |
|             /**
 | |
|              * Determines the browsers vendor prefix for transition callback events
 | |
|              * @return {String} The event name
 | |
|              */
 | |
|             transitionCallback: function(){
 | |
|                 return (cache.vendor==='Moz' || cache.vendor==='ms') ? 'transitionend' : cache.vendor+'TransitionEnd';
 | |
|             },
 | |
| 
 | |
|             /**
 | |
|              * Determines if the users browser supports CSS3 transformations
 | |
|              * @return {[type]} [description]
 | |
|              */
 | |
|             canTransform: function(){
 | |
|                 return typeof settings.element.style[cache.vendor+'Transform'] !== 'undefined';
 | |
|             },
 | |
| 
 | |
|             /**
 | |
|              * Determines an angle between two points
 | |
|              * @param  {Number} x The X coordinate
 | |
|              * @param  {Number} y The Y coordinate
 | |
|              * @return {Number}   The number of degrees between the two points
 | |
|              */
 | |
|             angleOfDrag: function(x, y) {
 | |
|                 var degrees, theta;
 | |
|                 // Calc Theta
 | |
|                 theta = Math.atan2(-(cache.startDragY - y), (cache.startDragX - x));
 | |
|                 if (theta < 0) {
 | |
|                     theta += 2 * Math.PI;
 | |
|                 }
 | |
|                 // Calc Degrees
 | |
|                 degrees = Math.floor(theta * (180 / Math.PI) - 180);
 | |
|                 if (degrees < 0 && degrees > -180) {
 | |
|                     degrees = 360 - Math.abs(degrees);
 | |
|                 }
 | |
|                 return Math.abs(degrees);
 | |
|             },
 | |
| 
 | |
| 
 | |
|             events: {
 | |
| 
 | |
|                 /**
 | |
|                  * Adds an event to an element
 | |
|                  * @param {Object} element   Element to add event to
 | |
|                  * @param {String} eventName The event name
 | |
|                  * @param {Function} func      Callback function
 | |
|                  */
 | |
|                 addEvent: function addEvent(element, eventName, func) {
 | |
|                     if (element.addEventListener) {
 | |
|                         return element.addEventListener(eventName, func, false);
 | |
|                     } else if (element.attachEvent) {
 | |
|                         return element.attachEvent("on" + eventName, func);
 | |
|                     }
 | |
|                 },
 | |
| 
 | |
|                 /**
 | |
|                  * Removes an event to an element
 | |
|                  * @param {Object} element   Element to remove event from
 | |
|                  * @param {String} eventName The event name
 | |
|                  * @param {Function} func      Callback function
 | |
|                  */
 | |
|                 removeEvent: function addEvent(element, eventName, func) {
 | |
|                     if (element.addEventListener) {
 | |
|                         return element.removeEventListener(eventName, func, false);
 | |
|                     } else if (element.attachEvent) {
 | |
|                         return element.detachEvent("on" + eventName, func);
 | |
|                     }
 | |
|                 },
 | |
| 
 | |
|                 /**
 | |
|                  * Prevents the default event
 | |
|                  * @param  {Object} e The event object
 | |
|                  */
 | |
|                 prevent: function(e) {
 | |
|                     if (e.preventDefault) {
 | |
|                         e.preventDefault();
 | |
|                     } else {
 | |
|                         e.returnValue = false;
 | |
|                     }
 | |
|                 }
 | |
|             },
 | |
| 
 | |
|             /**
 | |
|              * Searches the parent element until a specified attribute has been matched
 | |
|              * @param  {Object} el   The element to search from
 | |
|              * @param  {String} attr The attribute to search for
 | |
|              * @return {Object|null}      Returns a matched element if it exists, else, null
 | |
|              */
 | |
|             parentUntil: function(el, attr) {
 | |
|                 var isStr = typeof attr === 'string';
 | |
|                 while (el.parentNode) {
 | |
|                     if (isStr && el.getAttribute && el.getAttribute(attr)){
 | |
|                         return el;
 | |
|                     } else if(!isStr && el === attr){
 | |
|                         return el;
 | |
|                     }
 | |
|                     el = el.parentNode;
 | |
|                 }
 | |
|                 return null;
 | |
|             }
 | |
|         });
 | |
| 
 | |
| 
 | |
|         var action = self.action = {
 | |
| 
 | |
|             /**
 | |
|              * Handles translating the elements position
 | |
|              * @type {Object}
 | |
|              */
 | |
|             translate: {
 | |
|                 get: {
 | |
| 
 | |
|                     /**
 | |
|                      * Returns the amount an element is translated
 | |
|                      * @param  {Number} index The index desired from the CSS3 values of translate3d
 | |
|                      * @return {Number}       The amount of pixels an element is translated
 | |
|                      */
 | |
|                     matrix: function(index) {
 | |
| 
 | |
|                         if( !cache.canTransform ){
 | |
|                             return parseInt(settings.element.style.left, 10);
 | |
|                         } else {
 | |
|                             var matrix = win.getComputedStyle(settings.element)[cache.vendor+'Transform'].match(/\((.*)\)/),
 | |
|                                 ieOffset = 8;
 | |
|                             if (matrix) {
 | |
|                                 matrix = matrix[1].split(',');
 | |
| 
 | |
|                                 // Internet Explorer likes to give us 16 fucking values
 | |
|                                 if(matrix.length===16){
 | |
|                                     index+=ieOffset;
 | |
|                                 }
 | |
|                                 return parseInt(matrix[index], 10);
 | |
|                             }
 | |
|                             return 0;
 | |
|                         }
 | |
|                     }
 | |
|                 },
 | |
| 
 | |
|                 /**
 | |
|                  * Called when the element has finished transitioning
 | |
|                  */
 | |
|                 easeCallback: function(fn){
 | |
|                     settings.element.style[cache.vendor+'Transition'] = '';
 | |
|                     cache.translation = action.translate.get.matrix(4);
 | |
|                     cache.easing = false;
 | |
| 
 | |
|                     if(cache.easingTo===0){
 | |
|                         utils.klass.remove(doc.body, 'snapjs-right');
 | |
|                         utils.klass.remove(doc.body, 'snapjs-left');
 | |
|                     }
 | |
| 
 | |
|                     if( cache.once ){
 | |
|                         cache.once.call(self, self.state());
 | |
|                         delete cache.once;
 | |
|                     }
 | |
| 
 | |
|                     utils.dispatchEvent('animated');
 | |
|                     utils.events.removeEvent(settings.element, utils.transitionCallback(), action.translate.easeCallback);
 | |
| 
 | |
|                 },
 | |
| 
 | |
|                 /**
 | |
|                  * Animates the pane by the specified amount of pixels
 | |
|                  * @param  {Number} n The amount of pixels to move the pane
 | |
|                  */
 | |
|                 easeTo: function(n, cb) {
 | |
| 
 | |
|                     if( !cache.canTransform ){
 | |
|                         cache.translation = n;
 | |
|                         action.translate.x(n);
 | |
|                     } else {
 | |
|                         cache.easing = true;
 | |
|                         cache.easingTo = n;
 | |
| 
 | |
|                         settings.element.style[cache.vendor+'Transition'] = 'all ' + settings.transitionSpeed + 's ' + settings.easing;
 | |
| 
 | |
|                         cache.once = cb;
 | |
| 
 | |
|                         utils.events.addEvent(settings.element, utils.transitionCallback(), action.translate.easeCallback);
 | |
|                         action.translate.x(n);
 | |
|                     }
 | |
|                     if(n===0){
 | |
|                         settings.element.style[cache.vendor+'Transform'] = '';
 | |
|                     }
 | |
|                 },
 | |
| 
 | |
|                 /**
 | |
|                  * Immediately translates the element on its X axis
 | |
|                  * @param  {Number} n Amount of pixels to translate
 | |
|                  */
 | |
|                 x: function(n) {
 | |
|                     if( (settings.disable==='left' && n>0) ||
 | |
|                         (settings.disable==='right' && n<0)
 | |
|                     ){ return; }
 | |
| 
 | |
|                     if( !settings.hyperextensible ){
 | |
|                         if( n===settings.maxPosition || n>settings.maxPosition ){
 | |
|                             n=settings.maxPosition;
 | |
|                         } else if( n===settings.minPosition || n<settings.minPosition ){
 | |
|                             n=settings.minPosition;
 | |
|                         }
 | |
|                     }
 | |
| 
 | |
|                     n = parseInt(n, 10);
 | |
|                     if(isNaN(n)){
 | |
|                         n = 0;
 | |
|                     }
 | |
| 
 | |
|                     if( cache.canTransform ){
 | |
|                         var theTranslate = 'translate3d(' + n + 'px, 0,0)';
 | |
|                         settings.element.style[cache.vendor+'Transform'] = theTranslate;
 | |
|                     } else {
 | |
|                         settings.element.style.width = (win.innerWidth || doc.documentElement.clientWidth)+'px';
 | |
| 
 | |
|                         settings.element.style.left = n+'px';
 | |
|                         settings.element.style.right = '';
 | |
|                     }
 | |
|                 }
 | |
|             },
 | |
| 
 | |
|             /**
 | |
|              * Handles all the events that interface with dragging
 | |
|              * @type {Object}
 | |
|              */
 | |
|             drag: {
 | |
| 
 | |
|                 /**
 | |
|                  * Begins listening for drag events on our element
 | |
|                  */
 | |
|                 listen: function() {
 | |
|                     cache.translation = 0;
 | |
|                     cache.easing = false;
 | |
|                     utils.events.addEvent(self.settings.element, utils.eventType('down'), action.drag.startDrag);
 | |
|                     utils.events.addEvent(self.settings.element, utils.eventType('move'), action.drag.dragging);
 | |
|                     utils.events.addEvent(self.settings.element, utils.eventType('up'), action.drag.endDrag);
 | |
|                 },
 | |
| 
 | |
|                 /**
 | |
|                  * Stops listening for drag events on our element
 | |
|                  */
 | |
|                 stopListening: function() {
 | |
|                     utils.events.removeEvent(settings.element, utils.eventType('down'), action.drag.startDrag);
 | |
|                     utils.events.removeEvent(settings.element, utils.eventType('move'), action.drag.dragging);
 | |
|                     utils.events.removeEvent(settings.element, utils.eventType('up'), action.drag.endDrag);
 | |
|                 },
 | |
| 
 | |
|                 /**
 | |
|                  * Fired immediately when the user begins to drag the content pane
 | |
|                  * @param  {Object} e Event object
 | |
|                  */
 | |
|                 startDrag: function(e) {
 | |
|                     // No drag on ignored elements
 | |
|                     var target = e.target ? e.target : e.srcElement,
 | |
|                         ignoreParent = utils.parentUntil(target, 'data-snap-ignore');
 | |
| 
 | |
|                     if (ignoreParent) {
 | |
|                         utils.dispatchEvent('ignore');
 | |
|                         return;
 | |
|                     }
 | |
| 
 | |
| 
 | |
|                     if(settings.dragger){
 | |
|                         var dragParent = utils.parentUntil(target, settings.dragger);
 | |
| 
 | |
|                         // Only use dragger if we're in a closed state
 | |
|                         if( !dragParent &&
 | |
|                             (cache.translation !== settings.minPosition &&
 | |
|                             cache.translation !== settings.maxPosition
 | |
|                         )){
 | |
|                             return;
 | |
|                         }
 | |
|                     }
 | |
| 
 | |
|                     utils.dispatchEvent('start');
 | |
|                     settings.element.style[cache.vendor+'Transition'] = '';
 | |
|                     cache.isDragging = true;
 | |
| 
 | |
|                     cache.intentChecked = false;
 | |
|                     cache.startDragX = utils.page('X', e);
 | |
|                     cache.startDragY = utils.page('Y', e);
 | |
|                     cache.dragWatchers = {
 | |
|                         current: 0,
 | |
|                         last: 0,
 | |
|                         hold: 0,
 | |
|                         state: ''
 | |
|                     };
 | |
|                     cache.simpleStates = {
 | |
|                         opening: null,
 | |
|                         towards: null,
 | |
|                         hyperExtending: null,
 | |
|                         halfway: null,
 | |
|                         flick: null,
 | |
|                         translation: {
 | |
|                             absolute: 0,
 | |
|                             relative: 0,
 | |
|                             sinceDirectionChange: 0,
 | |
|                             percentage: 0
 | |
|                         }
 | |
|                     };
 | |
|                 },
 | |
| 
 | |
|                 /**
 | |
|                  * Fired while the user is moving the content pane
 | |
|                  * @param  {Object} e Event object
 | |
|                  */
 | |
|                 dragging: function(e) {
 | |
| 
 | |
|                     if (cache.isDragging && settings.touchToDrag) {
 | |
| 
 | |
|                         var thePageX = utils.page('X', e),
 | |
|                             thePageY = utils.page('Y', e),
 | |
|                             translated = cache.translation,
 | |
|                             absoluteTranslation = action.translate.get.matrix(4),
 | |
|                             whileDragX = thePageX - cache.startDragX,
 | |
|                             openingLeft = absoluteTranslation > 0,
 | |
|                             translateTo = whileDragX,
 | |
|                             diff;
 | |
| 
 | |
|                         // Shown no intent already
 | |
|                         if((cache.intentChecked && !cache.hasIntent)){
 | |
|                             return;
 | |
|                         }
 | |
| 
 | |
|                         if(settings.addBodyClasses){
 | |
|                             if((absoluteTranslation)>0){
 | |
|                                 utils.klass.add(doc.body, 'snapjs-left');
 | |
|                                 utils.klass.remove(doc.body, 'snapjs-right');
 | |
|                             } else if((absoluteTranslation)<0){
 | |
|                                 utils.klass.add(doc.body, 'snapjs-right');
 | |
|                                 utils.klass.remove(doc.body, 'snapjs-left');
 | |
|                             }
 | |
|                         }
 | |
| 
 | |
|                         if (cache.hasIntent === false || cache.hasIntent === null) {
 | |
| 
 | |
|                             var deg = utils.angleOfDrag(thePageX, thePageY),
 | |
|                                 inRightRange = (deg >= 0 && deg <= settings.slideIntent) || (deg <= 360 && deg > (360 - settings.slideIntent)),
 | |
|                                 inLeftRange = (deg >= 180 && deg <= (180 + settings.slideIntent)) || (deg <= 180 && deg >= (180 - settings.slideIntent));
 | |
|                             if (!inLeftRange && !inRightRange) {
 | |
|                                 cache.hasIntent = false;
 | |
|                             } else {
 | |
|                                 cache.hasIntent = true;
 | |
|                             }
 | |
|                             cache.intentChecked = true;
 | |
|                         }
 | |
| 
 | |
|                         if (
 | |
|                             (settings.minDragDistance>=Math.abs(thePageX-cache.startDragX)) || // Has user met minimum drag distance?
 | |
|                             (cache.hasIntent === false)
 | |
|                         ) {
 | |
|                             return;
 | |
|                         }
 | |
| 
 | |
|                         utils.events.prevent(e);
 | |
|                         utils.dispatchEvent('drag');
 | |
| 
 | |
|                         cache.dragWatchers.current = thePageX;
 | |
| 
 | |
|                         // Determine which direction we are going
 | |
|                         if (cache.dragWatchers.last > thePageX) {
 | |
|                             if (cache.dragWatchers.state !== 'left') {
 | |
|                                 cache.dragWatchers.state = 'left';
 | |
|                                 cache.dragWatchers.hold = thePageX;
 | |
|                             }
 | |
|                             cache.dragWatchers.last = thePageX;
 | |
|                         } else if (cache.dragWatchers.last < thePageX) {
 | |
|                             if (cache.dragWatchers.state !== 'right') {
 | |
|                                 cache.dragWatchers.state = 'right';
 | |
|                                 cache.dragWatchers.hold = thePageX;
 | |
|                             }
 | |
|                             cache.dragWatchers.last = thePageX;
 | |
|                         }
 | |
|                         if (openingLeft) {
 | |
|                             // Pulling too far to the right
 | |
|                             if (settings.maxPosition < absoluteTranslation) {
 | |
|                                 diff = (absoluteTranslation - settings.maxPosition) * settings.resistance;
 | |
|                                 translateTo = whileDragX - diff;
 | |
|                             }
 | |
|                             cache.simpleStates = {
 | |
|                                 opening: 'left',
 | |
|                                 towards: cache.dragWatchers.state,
 | |
|                                 hyperExtending: settings.maxPosition < absoluteTranslation,
 | |
|                                 halfway: absoluteTranslation > (settings.maxPosition / 2),
 | |
|                                 flick: Math.abs(cache.dragWatchers.current - cache.dragWatchers.hold) > settings.flickThreshold,
 | |
|                                 translation: {
 | |
|                                     absolute: absoluteTranslation,
 | |
|                                     relative: whileDragX,
 | |
|                                     sinceDirectionChange: (cache.dragWatchers.current - cache.dragWatchers.hold),
 | |
|                                     percentage: (absoluteTranslation/settings.maxPosition)*100
 | |
|                                 }
 | |
|                             };
 | |
|                         } else {
 | |
|                             // Pulling too far to the left
 | |
|                             if (settings.minPosition > absoluteTranslation) {
 | |
|                                 diff = (absoluteTranslation - settings.minPosition) * settings.resistance;
 | |
|                                 translateTo = whileDragX - diff;
 | |
|                             }
 | |
|                             cache.simpleStates = {
 | |
|                                 opening: 'right',
 | |
|                                 towards: cache.dragWatchers.state,
 | |
|                                 hyperExtending: settings.minPosition > absoluteTranslation,
 | |
|                                 halfway: absoluteTranslation < (settings.minPosition / 2),
 | |
|                                 flick: Math.abs(cache.dragWatchers.current - cache.dragWatchers.hold) > settings.flickThreshold,
 | |
|                                 translation: {
 | |
|                                     absolute: absoluteTranslation,
 | |
|                                     relative: whileDragX,
 | |
|                                     sinceDirectionChange: (cache.dragWatchers.current - cache.dragWatchers.hold),
 | |
|                                     percentage: (absoluteTranslation/settings.minPosition)*100
 | |
|                                 }
 | |
|                             };
 | |
|                         }
 | |
|                         action.translate.x(translateTo + translated);
 | |
|                     }
 | |
|                 },
 | |
| 
 | |
|                 /**
 | |
|                  * Fired when the user releases the content pane
 | |
|                  * @param  {Object} e Event object
 | |
|                  */
 | |
|                 endDrag: function(e) {
 | |
|                     if (cache.isDragging) {
 | |
|                         utils.dispatchEvent('end');
 | |
|                         var translated = action.translate.get.matrix(4);
 | |
| 
 | |
|                         // Tap Close
 | |
|                         if (cache.dragWatchers.current === 0 && translated !== 0 && settings.tapToClose) {
 | |
|                             utils.dispatchEvent('close');
 | |
|                             utils.events.prevent(e);
 | |
|                             action.translate.easeTo(0);
 | |
|                             cache.isDragging = false;
 | |
|                             cache.startDragX = 0;
 | |
|                             return;
 | |
|                         }
 | |
| 
 | |
|                         // Revealing Left
 | |
|                         if (cache.simpleStates.opening === 'left') {
 | |
|                             // Halfway, Flicking, or Too Far Out
 | |
|                             if ((cache.simpleStates.halfway || cache.simpleStates.hyperExtending || cache.simpleStates.flick)) {
 | |
|                                 if (cache.simpleStates.flick && cache.simpleStates.towards === 'left') { // Flicking Closed
 | |
|                                     action.translate.easeTo(0);
 | |
|                                 } else if (
 | |
|                                     (cache.simpleStates.flick && cache.simpleStates.towards === 'right') || // Flicking Open OR
 | |
|                                     (cache.simpleStates.halfway || cache.simpleStates.hyperExtending) // At least halfway open OR hyperextending
 | |
|                                 ) {
 | |
|                                     action.translate.easeTo(settings.maxPosition); // Open Left
 | |
|                                 }
 | |
|                             } else {
 | |
|                                 action.translate.easeTo(0); // Close Left
 | |
|                             }
 | |
|                             // Revealing Right
 | |
|                         } else if (cache.simpleStates.opening === 'right') {
 | |
|                             // Halfway, Flicking, or Too Far Out
 | |
|                             if ((cache.simpleStates.halfway || cache.simpleStates.hyperExtending || cache.simpleStates.flick)) {
 | |
|                                 if (cache.simpleStates.flick && cache.simpleStates.towards === 'right') { // Flicking Closed
 | |
|                                     action.translate.easeTo(0);
 | |
|                                 } else if (
 | |
|                                     (cache.simpleStates.flick && cache.simpleStates.towards === 'left') || // Flicking Open OR
 | |
|                                     (cache.simpleStates.halfway || cache.simpleStates.hyperExtending) // At least halfway open OR hyperextending
 | |
|                                 ) {
 | |
|                                     action.translate.easeTo(settings.minPosition); // Open Right
 | |
|                                 }
 | |
|                             } else {
 | |
|                                 action.translate.easeTo(0); // Close Right
 | |
|                             }
 | |
|                         }
 | |
|                         cache.isDragging = false;
 | |
|                         cache.startDragX = utils.page('X', e);
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|         };
 | |
| 
 | |
| 
 | |
|         // Initialize
 | |
|         if (opts.element) {
 | |
|             utils.extend(settings, opts);
 | |
|             cache.vendor = utils.vendor();
 | |
|             cache.canTransform = utils.canTransform();
 | |
|             action.drag.listen();
 | |
|         }
 | |
|     };
 | |
| 
 | |
| 
 | |
|     utils.extend(Core.prototype, {
 | |
| 
 | |
|         /**
 | |
|          * Opens the specified side menu
 | |
|          * @param  {String} side Must be "left" or "right"
 | |
|          */
 | |
|         open: function(side, cb) {
 | |
|             utils.dispatchEvent('open');
 | |
|             utils.klass.remove(doc.body, 'snapjs-expand-left');
 | |
|             utils.klass.remove(doc.body, 'snapjs-expand-right');
 | |
| 
 | |
|             if (side === 'left') {
 | |
|                 this.cache.simpleStates.opening = 'left';
 | |
|                 this.cache.simpleStates.towards = 'right';
 | |
|                 utils.klass.add(doc.body, 'snapjs-left');
 | |
|                 utils.klass.remove(doc.body, 'snapjs-right');
 | |
|                 this.action.translate.easeTo(this.settings.maxPosition, cb);
 | |
|             } else if (side === 'right') {
 | |
|                 this.cache.simpleStates.opening = 'right';
 | |
|                 this.cache.simpleStates.towards = 'left';
 | |
|                 utils.klass.remove(doc.body, 'snapjs-left');
 | |
|                 utils.klass.add(doc.body, 'snapjs-right');
 | |
|                 this.action.translate.easeTo(this.settings.minPosition, cb);
 | |
|             }
 | |
|         },
 | |
| 
 | |
|         /**
 | |
|          * Closes the pane
 | |
|          */
 | |
|         close: function(cb) {
 | |
|             utils.dispatchEvent('close');
 | |
|             this.action.translate.easeTo(0, cb);
 | |
|         },
 | |
| 
 | |
|         /**
 | |
|          * Hides the content pane completely allowing for full menu visibility
 | |
|          * @param  {String} side Must be "left" or "right"
 | |
|          */
 | |
|         expand: function(side){
 | |
|             var to = win.innerWidth || doc.documentElement.clientWidth;
 | |
| 
 | |
|             if(side==='left'){
 | |
|                 utils.dispatchEvent('expandLeft');
 | |
|                 utils.klass.add(doc.body, 'snapjs-expand-left');
 | |
|                 utils.klass.remove(doc.body, 'snapjs-expand-right');
 | |
|             } else {
 | |
|                 utils.dispatchEvent('expandRight');
 | |
|                 utils.klass.add(doc.body, 'snapjs-expand-right');
 | |
|                 utils.klass.remove(doc.body, 'snapjs-expand-left');
 | |
|                 to *= -1;
 | |
|             }
 | |
|             this.action.translate.easeTo(to);
 | |
|         },
 | |
| 
 | |
|         /**
 | |
|          * Listen in to custom Snap events
 | |
|          * @param  {String}   evt The snap event name
 | |
|          * @param  {Function} fn  Callback function
 | |
|          * @return {Object}       Snap instance
 | |
|          */
 | |
|         on: function(evt, fn) {
 | |
|             this.eventList[evt] = fn;
 | |
|             return this;
 | |
|         },
 | |
| 
 | |
|         /**
 | |
|          * Stops listening to custom Snap events
 | |
|          * @param  {String} evt The snap event name
 | |
|          */
 | |
|         off: function(evt) {
 | |
|             if (this.eventList[evt]) {
 | |
|                 this.eventList[evt] = false;
 | |
|             }
 | |
|         },
 | |
| 
 | |
|         /**
 | |
|          * Enables Snap.js events
 | |
|          */
 | |
|         enable: function() {
 | |
|             utils.dispatchEvent('enable');
 | |
|             this.action.drag.listen();
 | |
|         },
 | |
| 
 | |
|         /**
 | |
|          * Disables Snap.js events
 | |
|          */
 | |
|         disable: function() {
 | |
|             utils.dispatchEvent('disable');
 | |
|             this.action.drag.stopListening();
 | |
|         },
 | |
| 
 | |
|         /**
 | |
|          * Updates the instances settings
 | |
|          * @param  {Object} opts The Snap options to set
 | |
|          */
 | |
|         settings: function(opts){
 | |
|             utils.extend(this.settings, opts);
 | |
|         },
 | |
| 
 | |
|         /**
 | |
|          * Returns information about the state of the content pane
 | |
|          * @return {Object} Information regarding the state of the pane
 | |
|          */
 | |
|         state: function() {
 | |
|             var state,
 | |
|                 fromLeft = this.action.translate.get.matrix(4);
 | |
|             if (fromLeft === this.settings.maxPosition) {
 | |
|                 state = 'left';
 | |
|             } else if (fromLeft === this.settings.minPosition) {
 | |
|                 state = 'right';
 | |
|             } else {
 | |
|                 state = 'closed';
 | |
|             }
 | |
|             return {
 | |
|                 state: state,
 | |
|                 info: this.cache.simpleStates
 | |
|             };
 | |
|         }
 | |
|     });
 | |
| 
 | |
|     // Assign to the global namespace
 | |
|     this[Namespace] = Core;
 | |
| 
 | |
| }).call(this, window, document);
 | 
