Last active
August 29, 2015 14:05
-
-
Save vitalyrotari/f07e8e42afb16df5860f to your computer and use it in GitHub Desktop.
jQuery Panes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Modernizr 2.8.2 (Custom Build) | MIT & BSD | |
* Build: http://modernizr.com/download/#-backgroundsize-rgba-cssanimations-csstransforms-csstransforms3d-csstransitions-touch-shiv-cssclasses-prefixed-teststyles-testprop-testallprops-prefixes-domprefixes-css_positionsticky-requestanimationframe | |
*/ | |
; | |
window.Modernizr = (function( window, document, undefined ) { | |
var version = '2.8.2', | |
Modernizr = {}, | |
enableClasses = true, | |
docElement = document.documentElement, | |
mod = 'modernizr', | |
modElem = document.createElement(mod), | |
mStyle = modElem.style, | |
inputElem , | |
toString = {}.toString, | |
prefixes = ' -webkit- -moz- -o- -ms- '.split(' '), | |
omPrefixes = 'Webkit Moz O ms', | |
cssomPrefixes = omPrefixes.split(' '), | |
domPrefixes = omPrefixes.toLowerCase().split(' '), | |
tests = {}, | |
inputs = {}, | |
attrs = {}, | |
classes = [], | |
slice = classes.slice, | |
featureName, | |
injectElementWithStyles = function( rule, callback, nodes, testnames ) { | |
var style, ret, node, docOverflow, | |
div = document.createElement('div'), | |
body = document.body, | |
fakeBody = body || document.createElement('body'); | |
if ( parseInt(nodes, 10) ) { | |
while ( nodes-- ) { | |
node = document.createElement('div'); | |
node.id = testnames ? testnames[nodes] : mod + (nodes + 1); | |
div.appendChild(node); | |
} | |
} | |
style = ['­','<style id="s', mod, '">', rule, '</style>'].join(''); | |
div.id = mod; | |
(body ? div : fakeBody).innerHTML += style; | |
fakeBody.appendChild(div); | |
if ( !body ) { | |
fakeBody.style.background = ''; | |
fakeBody.style.overflow = 'hidden'; | |
docOverflow = docElement.style.overflow; | |
docElement.style.overflow = 'hidden'; | |
docElement.appendChild(fakeBody); | |
} | |
ret = callback(div, rule); | |
if ( !body ) { | |
fakeBody.parentNode.removeChild(fakeBody); | |
docElement.style.overflow = docOverflow; | |
} else { | |
div.parentNode.removeChild(div); | |
} | |
return !!ret; | |
}, | |
_hasOwnProperty = ({}).hasOwnProperty, hasOwnProp; | |
if ( !is(_hasOwnProperty, 'undefined') && !is(_hasOwnProperty.call, 'undefined') ) { | |
hasOwnProp = function (object, property) { | |
return _hasOwnProperty.call(object, property); | |
}; | |
} | |
else { | |
hasOwnProp = function (object, property) { | |
return ((property in object) && is(object.constructor.prototype[property], 'undefined')); | |
}; | |
} | |
if (!Function.prototype.bind) { | |
Function.prototype.bind = function bind(that) { | |
var target = this; | |
if (typeof target != "function") { | |
throw new TypeError(); | |
} | |
var args = slice.call(arguments, 1), | |
bound = function () { | |
if (this instanceof bound) { | |
var F = function(){}; | |
F.prototype = target.prototype; | |
var self = new F(); | |
var result = target.apply( | |
self, | |
args.concat(slice.call(arguments)) | |
); | |
if (Object(result) === result) { | |
return result; | |
} | |
return self; | |
} else { | |
return target.apply( | |
that, | |
args.concat(slice.call(arguments)) | |
); | |
} | |
}; | |
return bound; | |
}; | |
} | |
function setCss( str ) { | |
mStyle.cssText = str; | |
} | |
function setCssAll( str1, str2 ) { | |
return setCss(prefixes.join(str1 + ';') + ( str2 || '' )); | |
} | |
function is( obj, type ) { | |
return typeof obj === type; | |
} | |
function contains( str, substr ) { | |
return !!~('' + str).indexOf(substr); | |
} | |
function testProps( props, prefixed ) { | |
for ( var i in props ) { | |
var prop = props[i]; | |
if ( !contains(prop, "-") && mStyle[prop] !== undefined ) { | |
return prefixed == 'pfx' ? prop : true; | |
} | |
} | |
return false; | |
} | |
function testDOMProps( props, obj, elem ) { | |
for ( var i in props ) { | |
var item = obj[props[i]]; | |
if ( item !== undefined) { | |
if (elem === false) return props[i]; | |
if (is(item, 'function')){ | |
return item.bind(elem || obj); | |
} | |
return item; | |
} | |
} | |
return false; | |
} | |
function testPropsAll( prop, prefixed, elem ) { | |
var ucProp = prop.charAt(0).toUpperCase() + prop.slice(1), | |
props = (prop + ' ' + cssomPrefixes.join(ucProp + ' ') + ucProp).split(' '); | |
if(is(prefixed, "string") || is(prefixed, "undefined")) { | |
return testProps(props, prefixed); | |
} else { | |
props = (prop + ' ' + (domPrefixes).join(ucProp + ' ') + ucProp).split(' '); | |
return testDOMProps(props, prefixed, elem); | |
} | |
} tests['touch'] = function() { | |
var bool; | |
if(('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) { | |
bool = true; | |
} else { | |
injectElementWithStyles(['@media (',prefixes.join('touch-enabled),('),mod,')','{#modernizr{top:9px;position:absolute}}'].join(''), function( node ) { | |
bool = node.offsetTop === 9; | |
}); | |
} | |
return bool; | |
}; tests['rgba'] = function() { | |
setCss('background-color:rgba(150,255,150,.5)'); | |
return contains(mStyle.backgroundColor, 'rgba'); | |
}; | |
tests['backgroundsize'] = function() { | |
return testPropsAll('backgroundSize'); | |
}; | |
tests['cssanimations'] = function() { | |
return testPropsAll('animationName'); | |
}; | |
tests['csstransforms'] = function() { | |
return !!testPropsAll('transform'); | |
}; | |
tests['csstransforms3d'] = function() { | |
var ret = !!testPropsAll('perspective'); | |
if ( ret && 'webkitPerspective' in docElement.style ) { | |
injectElementWithStyles('@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}', function( node, rule ) { | |
ret = node.offsetLeft === 9 && node.offsetHeight === 3; | |
}); | |
} | |
return ret; | |
}; | |
tests['csstransitions'] = function() { | |
return testPropsAll('transition'); | |
}; | |
for ( var feature in tests ) { | |
if ( hasOwnProp(tests, feature) ) { | |
featureName = feature.toLowerCase(); | |
Modernizr[featureName] = tests[feature](); | |
classes.push((Modernizr[featureName] ? '' : 'no-') + featureName); | |
} | |
} | |
Modernizr.addTest = function ( feature, test ) { | |
if ( typeof feature == 'object' ) { | |
for ( var key in feature ) { | |
if ( hasOwnProp( feature, key ) ) { | |
Modernizr.addTest( key, feature[ key ] ); | |
} | |
} | |
} else { | |
feature = feature.toLowerCase(); | |
if ( Modernizr[feature] !== undefined ) { | |
return Modernizr; | |
} | |
test = typeof test == 'function' ? test() : test; | |
if (typeof enableClasses !== "undefined" && enableClasses) { | |
docElement.className += ' ' + (test ? '' : 'no-') + feature; | |
} | |
Modernizr[feature] = test; | |
} | |
return Modernizr; | |
}; | |
setCss(''); | |
modElem = inputElem = null; | |
;(function(window, document) { | |
var version = '3.7.0'; | |
var options = window.html5 || {}; | |
var reSkip = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i; | |
var saveClones = /^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i; | |
var supportsHtml5Styles; | |
var expando = '_html5shiv'; | |
var expanID = 0; | |
var expandoData = {}; | |
var supportsUnknownElements; | |
(function() { | |
try { | |
var a = document.createElement('a'); | |
a.innerHTML = '<xyz></xyz>'; | |
supportsHtml5Styles = ('hidden' in a); | |
supportsUnknownElements = a.childNodes.length == 1 || (function() { | |
(document.createElement)('a'); | |
var frag = document.createDocumentFragment(); | |
return ( | |
typeof frag.cloneNode == 'undefined' || | |
typeof frag.createDocumentFragment == 'undefined' || | |
typeof frag.createElement == 'undefined' | |
); | |
}()); | |
} catch(e) { | |
supportsHtml5Styles = true; | |
supportsUnknownElements = true; | |
} | |
}()); | |
function addStyleSheet(ownerDocument, cssText) { | |
var p = ownerDocument.createElement('p'), | |
parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement; | |
p.innerHTML = 'x<style>' + cssText + '</style>'; | |
return parent.insertBefore(p.lastChild, parent.firstChild); | |
} | |
function getElements() { | |
var elements = html5.elements; | |
return typeof elements == 'string' ? elements.split(' ') : elements; | |
} | |
function getExpandoData(ownerDocument) { | |
var data = expandoData[ownerDocument[expando]]; | |
if (!data) { | |
data = {}; | |
expanID++; | |
ownerDocument[expando] = expanID; | |
expandoData[expanID] = data; | |
} | |
return data; | |
} | |
function createElement(nodeName, ownerDocument, data){ | |
if (!ownerDocument) { | |
ownerDocument = document; | |
} | |
if(supportsUnknownElements){ | |
return ownerDocument.createElement(nodeName); | |
} | |
if (!data) { | |
data = getExpandoData(ownerDocument); | |
} | |
var node; | |
if (data.cache[nodeName]) { | |
node = data.cache[nodeName].cloneNode(); | |
} else if (saveClones.test(nodeName)) { | |
node = (data.cache[nodeName] = data.createElem(nodeName)).cloneNode(); | |
} else { | |
node = data.createElem(nodeName); | |
} | |
return node.canHaveChildren && !reSkip.test(nodeName) && !node.tagUrn ? data.frag.appendChild(node) : node; | |
} | |
function createDocumentFragment(ownerDocument, data){ | |
if (!ownerDocument) { | |
ownerDocument = document; | |
} | |
if(supportsUnknownElements){ | |
return ownerDocument.createDocumentFragment(); | |
} | |
data = data || getExpandoData(ownerDocument); | |
var clone = data.frag.cloneNode(), | |
i = 0, | |
elems = getElements(), | |
l = elems.length; | |
for(;i<l;i++){ | |
clone.createElement(elems[i]); | |
} | |
return clone; | |
} | |
function shivMethods(ownerDocument, data) { | |
if (!data.cache) { | |
data.cache = {}; | |
data.createElem = ownerDocument.createElement; | |
data.createFrag = ownerDocument.createDocumentFragment; | |
data.frag = data.createFrag(); | |
} | |
ownerDocument.createElement = function(nodeName) { | |
if (!html5.shivMethods) { | |
return data.createElem(nodeName); | |
} | |
return createElement(nodeName, ownerDocument, data); | |
}; | |
ownerDocument.createDocumentFragment = Function('h,f', 'return function(){' + | |
'var n=f.cloneNode(),c=n.createElement;' + | |
'h.shivMethods&&(' + | |
getElements().join().replace(/[\w\-]+/g, function(nodeName) { | |
data.createElem(nodeName); | |
data.frag.createElement(nodeName); | |
return 'c("' + nodeName + '")'; | |
}) + | |
');return n}' | |
)(html5, data.frag); | |
} | |
function shivDocument(ownerDocument) { | |
if (!ownerDocument) { | |
ownerDocument = document; | |
} | |
var data = getExpandoData(ownerDocument); | |
if (html5.shivCSS && !supportsHtml5Styles && !data.hasCSS) { | |
data.hasCSS = !!addStyleSheet(ownerDocument, | |
'article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}' + | |
'mark{background:#FF0;color:#000}' + | |
'template{display:none}' | |
); | |
} | |
if (!supportsUnknownElements) { | |
shivMethods(ownerDocument, data); | |
} | |
return ownerDocument; | |
} | |
var html5 = { | |
'elements': options.elements || 'abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output progress section summary template time video', | |
'version': version, | |
'shivCSS': (options.shivCSS !== false), | |
'supportsUnknownElements': supportsUnknownElements, | |
'shivMethods': (options.shivMethods !== false), | |
'type': 'default', | |
'shivDocument': shivDocument, | |
createElement: createElement, | |
createDocumentFragment: createDocumentFragment | |
}; | |
window.html5 = html5; | |
shivDocument(document); | |
}(this, document)); | |
Modernizr._version = version; | |
Modernizr._prefixes = prefixes; | |
Modernizr._domPrefixes = domPrefixes; | |
Modernizr._cssomPrefixes = cssomPrefixes; | |
Modernizr.testProp = function(prop){ | |
return testProps([prop]); | |
}; | |
Modernizr.testAllProps = testPropsAll; | |
Modernizr.testStyles = injectElementWithStyles; | |
Modernizr.prefixed = function(prop, obj, elem){ | |
if(!obj) { | |
return testPropsAll(prop, 'pfx'); | |
} else { | |
return testPropsAll(prop, obj, elem); | |
} | |
}; | |
docElement.className = docElement.className.replace(/(^|\s)no-js(\s|$)/, '$1$2') + | |
(enableClasses ? ' js ' + classes.join(' ') : ''); | |
return Modernizr; | |
})(this, this.document); | |
// requestAnimationFrame | |
// Offload animation repainting to browser for optimized performance. | |
// http://dvcs.w3.org/hg/webperf/raw-file/tip/specs/RequestAnimationFrame/Overview.html | |
// By Addy Osmani | |
Modernizr.addTest('raf', !!Modernizr.prefixed('requestAnimationFrame', window));// Sticky positioning - constrains an element to be positioned inside the | |
// intersection of its container box, and the viewport. | |
Modernizr.addTest('csspositionsticky', function () { | |
var prop = 'position:'; | |
var value = 'sticky'; | |
var el = document.createElement('modernizr'); | |
var mStyle = el.style; | |
mStyle.cssText = prop + Modernizr._prefixes.join(value + ';' + prop).slice(0, -prop.length); | |
return mStyle.position.indexOf(value) !== -1; | |
}); | |
; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @version 1.0.0 | |
* @copyright 2014, TerraNet [All Rights Reserved] | |
* @license MIT License | |
* @website http://terranet.md | |
*/ | |
(function ($) { | |
'use strict'; | |
var CSS_TRANSITION_PROP = Modernizr.prefixed('transition'); | |
var CSS_TRANSFORM_PROP = Modernizr.prefixed('transform'); | |
var CSS_TRANSFORM_PROP_HYPHENATED = CSS_TRANSFORM_PROP ? hyphenated(CSS_TRANSFORM_PROP) : false; | |
var EVENT_TRANSITION_END = { | |
'WebkitTransition': 'webkitTransitionEnd', | |
'MozTransition': 'transitionend', | |
'OTransition': 'oTransitionEnd otransitionend', | |
'msTransition': 'MSTransitionEnd', | |
'transition': 'transitionend' | |
}[Modernizr.prefixed('transition')]; | |
var requestAnimFrame = Modernizr.prefixed('requestAnimationFrame', window) | |
|| function( callback ){ | |
window.setTimeout(callback, 1000 / 60); | |
}; | |
/** | |
* @param {String} | |
* @returns {String} | |
*/ | |
function hyphenated(str) { | |
return str.replace(/([A-Z])/g, function(str,m1){ return '-' + m1.toLowerCase(); }).replace(/^ms-/,'-ms-'); | |
} | |
/** | |
* @param {Event} event | |
*/ | |
function eventStop(event) { | |
event && event.preventDefault(); | |
} | |
/** | |
* @param {Event} event | |
* @param {Number?} speed | |
* @returns {Number} | |
*/ | |
function eventWheelDelta(event, speed) { | |
var e = event.originalEvent ? event.originalEvent : window.event; | |
var delta = 0; | |
if (!isNum(speed)) { | |
speed = 20; | |
} | |
if ('deltaX' in e) { | |
var multiply = (e.deltaMode === 1) ? speed : 1; | |
delta = -e.deltaY * multiply; | |
} else if ('wheelDeltaX' in e) { | |
delta = e.wheelDeltaY / 120 * speed; | |
} else if ('wheelDelta' in e) { | |
delta = e.wheelDelta / 120 * speed; | |
} else if ('detail' in e) { | |
delta = -e.detail / 3 * speed; | |
} | |
return delta; | |
} | |
/** | |
* @param {HTMLElement} el | |
* @param {Object} exceptions | |
* @returns {boolean} | |
*/ | |
function preventDefaultException(el, exceptions) { | |
for (var i in exceptions) { | |
if (exceptions.hasOwnProperty(i) && exceptions[i].test(el[i])) { | |
return true; | |
} | |
} | |
return false; | |
} | |
/** | |
* @param {Event} event | |
* @param {String?} eventName | |
*/ | |
function dispatchEventTap(event, eventName) { | |
var newEvent = document.createEvent('Event'); | |
newEvent.initEvent(eventName || 'tap', true, true); | |
newEvent.pageX = event.pageX; | |
newEvent.pageY = event.pageY; | |
event.target.dispatchEvent(newEvent); | |
} | |
/** | |
* @param {Event} event | |
*/ | |
function dispatchEventClick(event) { | |
var target = event.target; | |
var newEvent; | |
if ( !(/(SELECT|INPUT|TEXTAREA)/i).test(target.tagName) ) { | |
newEvent = document.createEvent('MouseEvents'); | |
newEvent.initMouseEvent('click', true, true, event.view, 1, | |
target.screenX, target.screenY, target.clientX, target.clientY, | |
event.ctrlKey, event.altKey, event.shiftKey, event.metaKey, | |
0, null); | |
newEvent._constructed = true; | |
target.dispatchEvent(newEvent); | |
} | |
} | |
/** | |
* @param {*} n | |
* @returns {boolean} | |
*/ | |
function isNum(n) { | |
return typeof n === 'number' && !isNaN(n); | |
} | |
// | |
var REGEXP_UP_KEYS = /33|36|38/; | |
var REGEXP_DOWN_KEYS = /32|34|35|40/; | |
var REGEXP_INPUTS = /input|textarea/i; | |
var CLASS_CURRENT = 'pane-current'; | |
var CLASS_SCROLLABLE = 'pane-scrollable'; | |
var CLASS_TOP = 'pane-top'; | |
var CLASS_MOVE = 'pane-move'; | |
var isBadAndroid = /Android /.test(window.navigator.appVersion) && !(/Chrome\/\d/.test(window.navigator.appVersion)); | |
function attachIScroll(Panes, el, options) { | |
var scroll = new IScroll(el, options); | |
scroll.on('scrollStart', function() { | |
Panes.onScrollStart(this); | |
}); | |
scroll.on('scrollEnd', function() { | |
Panes.onScrollEnd(this); | |
}); | |
return scroll; | |
} | |
var Panes = $.Panes = {}; | |
/** | |
* Default options | |
* | |
* @type {{wheel: {enabled: boolean, quietPeriod: number}, scroll: {bounceEasing: string, bounceTime: number, click: boolean, disableMouse: boolean, mouseWheel: boolean, scrollbars: string, resizeScrollbars: boolean}}} | |
*/ | |
Panes.options = { | |
wheel: { | |
enabled: true, | |
quietPeriod: 400 | |
}, | |
scroll: { | |
bounceEasing: 'back', | |
bounceTime: 500, | |
click: true, | |
disableMouse: true, | |
mouseWheel: true, | |
scrollbars: 'custom', | |
resizeScrollbars: true, | |
keyBindings: { | |
pageUp: 33, | |
pageDown: 34, | |
end: 35, | |
home: 36, | |
left: 37, | |
up: 38, | |
right: 39, | |
down: 40, | |
space: 32 | |
} | |
}, | |
preventDefaultException: { | |
tagName: /^(INPUT|TEXTAREA|BUTTON|SELECT)$/ | |
} | |
}; | |
Panes.isBlocked_ = false; | |
Panes.scroll_ = {}; | |
Panes.touch_ = { | |
start: {}, | |
delta: {}, | |
pending: undefined, | |
moved: false | |
}; | |
Panes.init = function() { | |
this.$pane = $('.panes'); | |
this.$panes = this.$pane.children('.pane'); | |
var len = this.$panes.length; | |
if (!len) { | |
return; | |
} | |
this.isPending = false; | |
this.last = len-1; | |
this.paneStyles_ = new Array(len); | |
this.panePositions_ = new Array(len); | |
this.paneScrolls_ = new Array(len); | |
this.$panes.each(function(index, el) { | |
var $el = $(el); | |
if ($el.hasClass(CLASS_CURRENT)) { | |
this.current = index; | |
} | |
this.paneStyles_[index] = $el.attr('style'); | |
this.paneScrolls_[index] = $el.hasClass(CLASS_SCROLLABLE) | |
? attachIScroll(this, el, this.options.scroll) | |
: undefined; | |
}.bind(this)); | |
if (!isNum(this.current)) { | |
this.current = 0; | |
this.$panes | |
.eq(this.current) | |
.addClass(CLASS_CURRENT) | |
.trigger('pane:in', [this.current, this]) | |
.trigger('pane:on', [this.current, this]); | |
} | |
this.updatePaneSize(); | |
this.updatePanesPositions(); | |
this.attachEventListeners_(); | |
}; | |
Panes.block = function() { | |
this.isBlocked_ = true; | |
}; | |
Panes.unblock = function() { | |
this.isBlocked_ = false; | |
}; | |
Panes.isBlocked = function() { | |
return this.isBlocked_; | |
}; | |
Panes.updatePaneSize = function() { | |
var $pane = this.$panes.eq(0); | |
this.paneSize_ = { | |
x: $pane.width(), | |
y: $pane.height() | |
}; | |
}; | |
Panes.updatePanesPositions = function() { | |
this.$panes.each(function(index) { | |
this.panePositions_[index] = this.current === index | |
? 0 | |
: this.current < index ? this.paneSize_.y : -this.paneSize_.y; | |
}.bind(this)); | |
}; | |
Panes.next = function(event) { | |
if (!this.isLast() && !this.isBlocked()) { | |
var index = this.current+1; | |
if (!this.hasIScroll(index)) { | |
eventStop(event); | |
} | |
this.move(index, this.panePositions_[index], 50); | |
} | |
}; | |
Panes.prev = function(event) { | |
if (!this.isFirst() && !this.isBlocked()) { | |
var index = this.current-1; | |
if (!this.hasIScroll(index)) { | |
eventStop(event); | |
} | |
this.move(index, this.panePositions_[index], 50); | |
} | |
}; | |
/** | |
* @param {Number} index | |
*/ | |
Panes.to = function(index) { | |
if (!this.isCurrent(index) && !this.isBlocked()) { | |
this.move(index, this.panePositions_[index], 50); | |
} | |
}; | |
/** | |
* @param {Number} index | |
* @param {Number?} dist | |
* @param {Number?} delay | |
*/ | |
Panes.move = function(index, dist, delay) { | |
if (this.isPending || this.isBlocked() || index < 0 || index > this.last) { | |
return; | |
} | |
this.isPending = true; | |
this.previous = this.current; | |
this.current = index; | |
var $prev = this.$panes.eq(this.previous); | |
var $current = this.$panes.eq(this.current) | |
.addClass(CLASS_CURRENT + ' ' + CLASS_TOP); | |
var jobs = 0; | |
var timer; | |
var complete = function() { | |
jobs++; | |
if (jobs < 2) { | |
return; | |
} | |
if (this.scroll) { | |
this.scroll.scrollTo(0, this.current > this.previous ? this.scroll.maxScrollY : 0, 0); | |
} | |
$prev.removeClass(CLASS_CURRENT).trigger('pane:off', [this.previous, this]); | |
$current.trigger('pane:on', [this.current, this]); | |
timer = setTimeout(function() { | |
this.isPending = false; | |
}.bind(this), 0); | |
}.bind(this); | |
var animate = function() { | |
$prev.trigger('pane:out', [this.previous, this]); | |
$current.trigger('pane:in', [this.current, this]); | |
this.translate(this.current, 0, 600, 'ease', 0, complete); | |
this.translate(this.previous, this.previous < this.current ? -this.paneSize_.y : this.paneSize_.y, 600, 'ease', delay || 0, complete); | |
this.updatePanesPositions(); | |
}.bind(this); | |
if (isNum(dist)) { | |
if (Modernizr.cssanimations) { | |
if (Modernizr.csstransforms3d) { | |
var transform = 'translate3d(0,' + dist + 'px,0)'; | |
} else { | |
transform = 'translateY(' + dist + 'px) translateZ(0)'; | |
} | |
$current.css(CSS_TRANSFORM_PROP, transform); | |
} else { | |
$current.css('top', dist + 'px'); | |
} | |
requestAnimFrame(animate) | |
} else { | |
animate(); | |
} | |
}; | |
/** | |
* @param {Number} index | |
* @param {Number} dist | |
* @param {Number?} speed | |
* @param {String?} easing | |
* @param {Number?} delay | |
* @param {Function?} callback | |
*/ | |
Panes.translate = function(index, dist, speed, easing, delay, callback) { | |
var $pane = this.$panes.eq(index); | |
var transform; | |
if (!$pane.length) { | |
return; | |
} | |
if (speed) { | |
var complete = function() { | |
this.lastMoveIndex_ = undefined; | |
$pane.removeClass(CLASS_MOVE + ' ' + CLASS_TOP); | |
var styles = this.paneStyles_[index]; | |
if (styles) { | |
$pane.attr('style', styles); | |
} else { | |
$pane.removeAttr('style'); | |
} | |
if ($.isFunction(callback)) { | |
callback(); | |
} | |
}.bind(this); | |
if (Modernizr.cssanimations) { | |
var props = {}; | |
if (Modernizr.csstransforms3d) { | |
transform = 'translate3d(0,' + dist + 'px,0)'; | |
} else { | |
transform = 'translateY(' + dist + 'px) translateZ(0)'; | |
} | |
props[CSS_TRANSFORM_PROP] = transform; | |
props[CSS_TRANSITION_PROP] = CSS_TRANSFORM_PROP_HYPHENATED + | |
' ' + (speed / 1000) + 's' + | |
' ' + (easing || 'ease'); | |
if (delay > 0) { | |
props[CSS_TRANSITION_PROP] += ' ' + (delay / 1000) + 's'; | |
} | |
$pane.one(EVENT_TRANSITION_END, complete); | |
requestAnimFrame(function() { | |
$pane.css(props); | |
}); | |
} else { | |
if (!$.easing[easing]) { | |
easing = 'swing'; | |
} | |
if (delay > 0) { | |
$pane.delay(delay); | |
} | |
$pane.animate({ top: dist + 'px' }, speed, easing, complete); | |
} | |
} else { | |
if (Modernizr.csstransforms) { | |
if (Modernizr.csstransforms3d) { | |
transform = 'translate3d(0,' + dist + 'px, 0)'; | |
} else { | |
transform = 'translateY(' + dist + 'px) translateZ(0)'; | |
} | |
$pane.css(CSS_TRANSFORM_PROP, transform); | |
} else { | |
$pane.css('top', dist + 'px'); | |
} | |
if ($.isFunction(callback)) { | |
callback(); | |
} | |
} | |
}; | |
/** | |
* @returns {boolean} | |
*/ | |
Panes.isCurrent = function(index) { | |
return index === this.current; | |
}; | |
/** | |
* @returns {boolean} | |
*/ | |
Panes.isFirst = function() { | |
return this.current === 0; | |
}; | |
/** | |
* @returns {boolean} | |
*/ | |
Panes.isLast = function() { | |
return this.current === this.last; | |
}; | |
/** | |
* @param {Number} index | |
* @returns {boolean} | |
*/ | |
Panes.hasIScroll = function(index) { | |
return (window.IScroll && this.paneScrolls_[index] instanceof IScroll); | |
}; | |
/** | |
* | |
* @param {Number} index | |
* @returns {IScroll} | |
*/ | |
Panes.getIScroll = function(index) { | |
return this.paneScrolls_[index]; | |
}; | |
/** | |
* | |
* @param {TouchEvent} event | |
*/ | |
Panes.onTouchStart = function(event) { | |
if (!this.scroll | |
&& !isBadAndroid | |
&& !preventDefaultException(event.target, this.options.preventDefaultException)) { | |
event.preventDefault(); | |
} | |
var touches = event.touches[0]; | |
this.touch_.start = { | |
x: touches.pageX, | |
y: touches.pageY, | |
time: +new Date | |
}; | |
this.touch_.moved = false; | |
this.touch_.pending = undefined; | |
}; | |
/** | |
* @param {TouchEvent} event | |
*/ | |
Panes.onTouchMove = function(event) { | |
var isValid; | |
this.touch_.moved = true; | |
if (this.scroll) { | |
isValid = (this.scroll_.dirY < 0 && this.scroll_.y === 0) | |
|| (this.scroll_.dirY > 0 && this.scroll_.y === this.scroll_.maxY); | |
if (!isValid) { | |
return; | |
} | |
} else { | |
if (event.touches.length > 1 || event.scale && event.scale !== 1) { | |
return; | |
} | |
} | |
var touches = event.touches[0]; | |
var delta = this.touch_.delta = { | |
x: touches.pageX - this.touch_.start.x, | |
y: touches.pageY - this.touch_.start.y | |
}; | |
var distanceX = Math.abs(delta.x); | |
var distanceY = Math.abs(delta.y); | |
// determine if scrolling test has run - one time test | |
if (!this.touch_.pending) { | |
this.touch_.pending = !!(this.touch_.pending || distanceY < distanceX); | |
} | |
if (!this.touch_.pending) { | |
if (!this.scroll) { | |
event.preventDefault(); | |
} | |
delta.y = | |
delta.y / | |
((!this.current && delta.y > 0 // if first slide and sliding left | |
|| this.current === this.last // or if last slide and sliding right | |
&& delta.y < 0 // and if sliding at all | |
) ? | |
(distanceY / this.paneSize_.y + 1) // determine resistance level | |
: 1); // no resistance if false | |
isValid = !(delta.y < 0 ? this.isLast() : this.isFirst()); | |
var next = delta.y < 0 ? this.current+1 : this.current-1; | |
if (!isValid) { | |
return; | |
} | |
if (next !== this.lastMoveIndex_) { | |
this.$panes.eq(next).addClass(CLASS_MOVE); | |
} | |
this.translate(next, this.panePositions_[next] + delta.y, 0); | |
if (!this.scroll) { | |
this.translate(this.current, (delta.y / 2), 0); | |
} | |
this.lastMoveIndex_ = next; | |
} | |
}; | |
/** | |
* @param {TouchEvent} event | |
*/ | |
Panes.onTouchEnd = function(event) { | |
if (!this.touch_.moved) { | |
dispatchEventTap(event, 'tap'); | |
dispatchEventClick(event); | |
return; | |
} | |
if (!this.touch_.delta.y) { | |
return; | |
} | |
var duration = +new Date - this.touch_.start.time; | |
var delta = this.touch_.delta; | |
var dist = Math.abs(delta.y); | |
var isValidSlide = | |
Number(duration) < 250 // if slide duration is less than 250ms | |
&& dist > 20 // and if slide amt is greater than 20px | |
|| dist > this.paneSize_.y / 2; // or if slide amt is greater than half the width | |
if (!this.touch_.pending) { | |
var direction = delta.y < 0; | |
if (isValidSlide) { | |
if (direction) { | |
if (!this.isLast()) { | |
this.move(this.current+1); | |
} | |
} else { | |
if (!this.isFirst()) { | |
this.move(this.current-1); | |
} | |
} | |
} else { | |
var index = direction ? this.current+1 : this.current-1; | |
this.translate(index, this.panePositions_[index], 700); | |
if (!this.scroll) { | |
this.translate(this.current, this.panePositions_[this.current], 600); | |
} | |
} | |
} | |
this.lastMoveIndex_ = undefined; | |
this.touch_.delta = {}; | |
}; | |
/** | |
* @param {IScroll} event | |
*/ | |
Panes.onScrollStart = function(event) { | |
this.scroll_ = { | |
x: event.x, | |
y: event.y, | |
maxY: event.maxScrollY, | |
dirX: event.directionX, | |
dirY: event.directionY | |
}; | |
}; | |
/** | |
* @param event | |
*/ | |
Panes.onScrollEnd = function(event) { | |
if (event.isMouseWheel) { | |
var isValid = (event.directionY < 0 && this.scroll_.y === 0) | |
|| (event.directionY > 0 && this.scroll_.y === event.maxScrollY); | |
if (isValid) { | |
if (event.directionY < 0) { | |
this.prev(); | |
} else { | |
this.next(); | |
} | |
} | |
} | |
}; | |
Panes.attachEventListeners_ = function() { | |
this.$pane.on('pane:on', '.pane', function(event, index) { | |
this.scroll = this.paneScrolls_[index] || undefined; | |
}.bind(this)); | |
var $body = $('body'); | |
$body.on('keypress keydown', function(event) { | |
var isFormElement = REGEXP_INPUTS.test(event.target.tagName); | |
var key = event.which; | |
if (isFormElement && /32|38|40/.test(key)) { | |
return; | |
} | |
if (REGEXP_UP_KEYS.test(key)) { // Up | |
if (this.scroll) { | |
if (this.scroll.y >= 0) { | |
this.prev(event); | |
} | |
} else { | |
this.prev(event); | |
} | |
} else if (REGEXP_DOWN_KEYS.test(key)) { // Down | |
if (this.scroll) { | |
if (Math.abs(this.scroll.y) >= Math.abs(this.scroll.maxScrollY)) { | |
this.next(event); | |
} | |
} else { | |
this.next(event); | |
} | |
} | |
}.bind(this)); | |
if (Panes.options.wheel.enabled) { | |
$body.on('wheel mousewheel DOMMouseScroll', function(event) { | |
if (this.scroll) { | |
return; | |
} | |
var now = new Date().getTime(); | |
if (this.options.wheel.quietPeriod > 0 && (now - this.wheelLastSeen_ < this.options.wheel.quietPeriod)) { | |
eventStop(event); | |
} else { | |
var delta = eventWheelDelta(event); | |
if (delta < 0) { // Down | |
this.next(event); | |
} else if (delta > 0) { // Up | |
this.prev(event); | |
} | |
this.wheelLastSeen_ = now; | |
} | |
}.bind(this)); | |
} | |
$(document).on('touchstart touchmove touchend touchcancel', function(event) { | |
var originalEvent = event.originalEvent ? event.originalEvent : event; | |
if (this.isPending) { | |
originalEvent.preventDefault(); | |
return; | |
} | |
switch (event.type) { | |
case 'touchstart': | |
this.onTouchStart(originalEvent); | |
break; | |
case 'touchmove': | |
this.onTouchMove(originalEvent); | |
break; | |
case 'touchend': | |
case 'touchcancel': | |
this.onTouchEnd(originalEvent); | |
break; | |
} | |
}.bind(this)); | |
}; | |
}(jQuery)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment