Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*!
- * Snap.js
- *
- * Copyright 2013, Jacob Kelley – http://jakiestfu.com/
- * Released under the MIT Licence
- * http://opensource.org/licenses/MIT
- *
- * Github: https://github.com/jakiestfu/Snap.js/
- * Version: 1.9.3
- */
- /*jslint browser: true*/
- /*global define, module, ender*/
- (function(win, doc) {
- ‘use strict';
- var Snap = Snap || function(userOpts) {
- var 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,
- slideIntent: 40, // degrees
- minDragDistance: 5
- },
- cache = {
- simpleStates: {
- opening: null,
- towards: null,
- hyperExtending: null,
- halfway: null,
- flick: null,
- translation: {
- absolute: 0,
- relative: 0,
- sinceDirectionChange: 0,
- percentage: 0
- }
- }
- },
- eventList = {},
- utils = {
- hasTouch: (‘ontouchstart’ in doc.documentElement || win.navigator.msPointerEnabled),
- eventType: function(action) {
- var eventTypes = {
- down: (utils.hasTouch ? ‘touchstart’ : ‘mousedown’),
- move: (utils.hasTouch ? ‘touchmove’ : ‘mousemove’),
- up: (utils.hasTouch ? ‘touchend’ : ‘mouseup’),
- out: (utils.hasTouch ? ‘touchcancel’ : ‘mouseout’)
- };
- return eventTypes[action];
- },
- page: function(t, e){
- return (utils.hasTouch && e.touches.length && e.touches[0]) ? e.touches[0][‘page’+t] : e[‘page’+t];
- },
- klass: {
- has: function(el, name){
- return (el.className).indexOf(name) !== -1;
- },
- add: function(el, name){
- if(!utils.klass.has(el, name) && settings.addBodyClasses){
- el.className += ” “+name;
- }
- },
- remove: function(el, name){
- if(settings.addBodyClasses){
- el.className = (el.className).replace(name, “”).replace(/^\s+|\s+$/g, ”);
- }
- }
- },
- dispatchEvent: function(type) {
- if (typeof eventList[type] === ‘function’) {
- return eventList[type].call();
- }
- },
- 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];
- }
- }
- },
- transitionCallback: function(){
- return (cache.vendor===’Moz’ || cache.vendor===’ms’) ? ‘transitionend’ : cache.vendor+’TransitionEnd';
- },
- canTransform: function(){
- return typeof settings.element.style[cache.vendor+’Transform’] !== ‘undefined';
- },
- deepExtend: function(destination, source) {
- var property;
- for (property in source) {
- if (source[property] && source[property].constructor && source[property].constructor === Object) {
- destination[property] = destination[property] || {};
- utils.deepExtend(destination[property], source[property]);
- } else {
- destination[property] = source[property];
- }
- }
- return destination;
- },
- 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: {
- 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);
- }
- },
- 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);
- }
- },
- prevent: function(e) {
- if (e.preventDefault) {
- e.preventDefault();
- } else {
- e.returnValue = false;
- }
- }
- },
- 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;
- }
- },
- action = {
- translate: {
- get: {
- matrix: function(index) {
- if( !utils.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(‘,’);
- if(matrix.length===16){
- index+=ieOffset;
- }
- return parseInt(matrix[index], 10);
- }
- return 0;
- }
- }
- },
- easeCallback: function(){
- settings.element.style[cache.vendor+’Transition’] = ”;
- cache.translation = action.translate.get.matrix(4);
- cache.easing = false;
- clearInterval(cache.animatingInterval);
- if(cache.easingTo===0){
- utils.klass.remove(doc.body, ‘snapjs-left’);
- utils.klass.remove(doc.body, ‘snapjs-right’);
- }
- utils.dispatchEvent(‘animated’);
- utils.events.removeEvent(settings.element, utils.transitionCallback(), action.translate.easeCallback);
- },
- easeTo: function(n) {
- if( !utils.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.animatingInterval = setInterval(function() {
- utils.dispatchEvent(‘animating’);
- }, 1);
- utils.events.addEvent(settings.element, utils.transitionCallback(), action.translate.easeCallback);
- action.translate.x(n);
- }
- if(n===0){
- settings.element.style[cache.vendor+’Transform’] = ”;
- }
- },
- x: function(n) {
- if( (settings.disable===’right’ && n>0) ||
- (settings.disable===’left’ && 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( utils.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.right = n+’px';
- settings.element.style.left = ”;
- }
- }
- },
- drag: {
- listen: function() {
- cache.translation = 0;
- cache.easing = false;
- utils.events.addEvent(settings.element, utils.eventType(‘down’), action.drag.startDrag);
- utils.events.addEvent(settings.element, utils.eventType(‘move’), action.drag.dragging);
- utils.events.addEvent(settings.element, utils.eventType(‘up’), action.drag.endDrag);
- },
- 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);
- },
- 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.hasIntent = null;
- 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
- }
- };
- },
- 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-right’);
- utils.klass.remove(doc.body, ‘snapjs-left’);
- } else if((absoluteTranslation)<0){
- utils.klass.add(doc.body, ‘snapjs-left’);
- utils.klass.remove(doc.body, ‘snapjs-right’);
- }
- }
- 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 !== ‘right’) {
- cache.dragWatchers.state = ‘right';
- cache.dragWatchers.hold = thePageX;
- }
- cache.dragWatchers.last = thePageX;
- } else if (cache.dragWatchers.last < thePageX) {
- if (cache.dragWatchers.state !== ‘left’) {
- cache.dragWatchers.state = ‘left';
- 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);
- }
- },
- 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 === ‘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.maxPosition); // Open Left
- }
- } else {
- action.translate.easeTo(0); // Close Left
- }
- // Revealing Right
- } else 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.minPosition); // Open Right
- }
- } else {
- action.translate.easeTo(0); // Close Right
- }
- }
- cache.isDragging = false;
- cache.startDragX = utils.page(‘X’, e);
- }
- }
- }
- },
- init = function(opts) {
- if (opts.element) {
- utils.deepExtend(settings, opts);
- cache.vendor = utils.vendor();
- action.drag.listen();
- }
- };
- /*
- * Public
- */
- this.open = function(side) {
- utils.dispatchEvent(‘open’);
- utils.klass.remove(doc.body, ‘snapjs-expand-right’);
- utils.klass.remove(doc.body, ‘snapjs-expand-left’);
- if (side === ‘right’) {
- cache.simpleStates.opening = ‘right';
- cache.simpleStates.towards = ‘left';
- utils.klass.add(doc.body, ‘snapjs-right’);
- utils.klass.remove(doc.body, ‘snapjs-left’);
- action.translate.easeTo(settings.maxPosition);
- } else if (side === ‘left’) {
- cache.simpleStates.opening = ‘left';
- cache.simpleStates.towards = ‘right';
- utils.klass.remove(doc.body, ‘snapjs-right’);
- utils.klass.add(doc.body, ‘snapjs-left’);
- action.translate.easeTo(settings.minPosition);
- }
- };
- this.close = function() {
- utils.dispatchEvent(‘close’);
- action.translate.easeTo(0);
- };
- this.expand = function(side){
- var to = win.innerWidth || doc.documentElement.clientWidth;
- if(side===’right’){
- utils.dispatchEvent(‘expandRight’);
- utils.klass.add(doc.body, ‘snapjs-expand-right’);
- utils.klass.remove(doc.body, ‘snapjs-expand-left’);
- } else {
- utils.dispatchEvent(‘expandLeft’);
- utils.klass.add(doc.body, ‘snapjs-expand-left’);
- utils.klass.remove(doc.body, ‘snapjs-expand-right’);
- to *= -1;
- }
- action.translate.easeTo(to);
- };
- this.on = function(evt, fn) {
- eventList[evt] = fn;
- return this;
- };
- this.off = function(evt) {
- if (eventList[evt]) {
- eventList[evt] = false;
- }
- };
- this.enable = function() {
- utils.dispatchEvent(‘enable’);
- action.drag.listen();
- };
- this.disable = function() {
- utils.dispatchEvent(‘disable’);
- action.drag.stopListening();
- };
- this.settings = function(opts){
- utils.deepExtend(settings, opts);
- };
- this.state = function() {
- var state,
- fromLeft = action.translate.get.matrix(4);
- if (fromLeft === settings.maxPosition) {
- state = ‘right';
- } else if (fromLeft === settings.minPosition) {
- state = ‘left';
- } else {
- state = ‘closed';
- }
- return {
- state: state,
- info: cache.simpleStates
- };
- };
- init(userOpts);
- };
- if ((typeof module !== ‘undefined’) && module.exports) {
- module.exports = Snap;
- }
- if (typeof ender === ‘undefined’) {
- this.Snap = Snap;
- }
- if ((typeof define === “function”) && define.amd) {
- define(“snap”, [], function() {
- return Snap;
- });
- }
- }).call(this, window, document);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement