Chapter is quite ok
ajax loaded content graphics ok interactivity ok remains the video interactions
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"name": "Peppermint",
|
||||
"version": "1.3.7",
|
||||
"homepage": "http://wd.dizaina.net/en/scripts/peppermint/",
|
||||
"authors": [
|
||||
"Oleg Korsunsky <wd@dizaina.net>"
|
||||
],
|
||||
"description": "Responsive touch-enabled slider. Tiny, supports mouse and all sorts of touch, library agnostic.",
|
||||
"main": [
|
||||
"dist/peppermint.min.js",
|
||||
"dist/peppermint.suggested.css"
|
||||
],
|
||||
"keywords": [
|
||||
"touch",
|
||||
"touch-events",
|
||||
"pointer-events",
|
||||
"mouse-events",
|
||||
"slider",
|
||||
"carousel",
|
||||
"gallery",
|
||||
"vanilla-js",
|
||||
"framework-agnostic",
|
||||
"library-agnostic"
|
||||
],
|
||||
"license": "MIT",
|
||||
"ignore": [
|
||||
"**/.*",
|
||||
"node_modules",
|
||||
"bower_components",
|
||||
"test"
|
||||
],
|
||||
"_release": "1.3.7",
|
||||
"_resolution": {
|
||||
"type": "version",
|
||||
"tag": "1.3.7",
|
||||
"commit": "cec00832caa3a1940801a0b20f84c8b9c8518b1f"
|
||||
},
|
||||
"_source": "git://github.com/wilddeer/Peppermint.git",
|
||||
"_target": "~1.3.7",
|
||||
"_originalSource": "Peppermint",
|
||||
"_direct": true
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
/*global module */
|
||||
module.exports = function(grunt) {
|
||||
'use strict';
|
||||
|
||||
grunt.initConfig({
|
||||
pkg: grunt.file.readJSON('package.json'),
|
||||
banner: '/*!\n * Peppermint touch slider\n * v. <%= pkg.version %> | <%= pkg.homepage %>\n * Copyright <%= pkg.author.name %> | <%= pkg.author.url %>\n *\n * Depends on Event Burrito (included) | https://github.com/wilddeer/Event-Burrito\n * MIT License\n */\n',
|
||||
bannerPure: '/*!\n * Peppermint touch slider\n * v. <%= pkg.version %> | <%= pkg.homepage %>\n * Copyright <%= pkg.author.name %> | <%= pkg.author.url %>\n *\n * Depends on Event Burrito | https://github.com/wilddeer/Event-Burrito\n * MIT License\n */\n',
|
||||
uglify: {
|
||||
options: {
|
||||
mangle: {
|
||||
except: ['Peppermint', '$', 'jQuery', 'EventBurrito']
|
||||
}
|
||||
},
|
||||
peppermint: {
|
||||
files: {
|
||||
'temp/peppermint.min.js': ['src/peppermint.js']
|
||||
}
|
||||
},
|
||||
burrito: {
|
||||
files: {
|
||||
'temp/eventburrito.min.js': ['src/burrito/eventburrito.js']
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
concat: {
|
||||
options: {
|
||||
banner: '<%= banner %>',
|
||||
separator: '\n'
|
||||
},
|
||||
full: {
|
||||
src: ['src/peppermint.js','src/burrito/eventburrito.js'],
|
||||
dest: 'dist/peppermint.js',
|
||||
},
|
||||
min: {
|
||||
src: ['temp/peppermint.min.js','temp/eventburrito.min.js'],
|
||||
dest: 'dist/peppermint.min.js',
|
||||
},
|
||||
pureFull: {
|
||||
options: {
|
||||
banner: '<%= bannerPure %>'
|
||||
},
|
||||
src: ['src/peppermint.js'],
|
||||
dest: 'dist/pure/peppermint.pure.js'
|
||||
},
|
||||
pureMin: {
|
||||
options: {
|
||||
banner: '<%= bannerPure %>'
|
||||
},
|
||||
src: ['temp/peppermint.min.js'],
|
||||
dest: 'dist/pure/peppermint.pure.min.js'
|
||||
},
|
||||
cssRequired: {
|
||||
options: {
|
||||
banner: '/* Peppermint minimal required styles */\n\n'
|
||||
},
|
||||
src: ['src/peppermint.required.css'],
|
||||
dest: 'dist/peppermint.required.css'
|
||||
},
|
||||
cssSuggested: {
|
||||
options: {
|
||||
banner: '/* Peppermint required styles + default appearance styles */\n\n',
|
||||
separator: '\n\n/* default appearance styles */\n'
|
||||
},
|
||||
src: ['src/peppermint.required.css', 'src/peppermint.appearance.css'],
|
||||
dest: 'dist/peppermint.suggested.css'
|
||||
}
|
||||
},
|
||||
|
||||
bump: {
|
||||
options: {
|
||||
files: ['package.json', 'bower.json'],
|
||||
updateConfigs: ['pkg'],
|
||||
commit: true,
|
||||
commitMessage: 'tagging v. %VERSION%',
|
||||
commitFiles: ['.'],
|
||||
createTag: true,
|
||||
tagName: '%VERSION%',
|
||||
tagMessage: 'tagging v. %VERSION%',
|
||||
push: false
|
||||
}
|
||||
},
|
||||
|
||||
shell: {
|
||||
push: {
|
||||
command: 'git push'
|
||||
},
|
||||
|
||||
pushTags: {
|
||||
command: 'git push --tags'
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
files: ['src/**/*.js', 'src/**/*.css', 'package.json'],
|
||||
tasks: ['build']
|
||||
},
|
||||
});
|
||||
|
||||
// build
|
||||
grunt.loadNpmTasks('grunt-contrib-uglify');
|
||||
grunt.loadNpmTasks('grunt-contrib-concat');
|
||||
grunt.loadNpmTasks('grunt-contrib-watch');
|
||||
grunt.loadNpmTasks('grunt-bump');
|
||||
grunt.loadNpmTasks('grunt-shell');
|
||||
grunt.registerTask('build', ['uglify', 'concat']);
|
||||
grunt.registerTask('release', ['bump-only:patch', 'uglify', 'concat', 'bump-commit', 'shell:push', 'shell:pushTags']);
|
||||
grunt.registerTask('w', ['build', 'watch']);
|
||||
grunt.registerTask('default', 'build');
|
||||
};
|
||||
@@ -0,0 +1,224 @@
|
||||
#Peppermint touch slider
|
||||
|
||||
[Check out the demo](http://wd.dizaina.net/en/scripts/peppermint/)
|
||||
|
||||
Yet another touch slider. Only better.
|
||||
|
||||
- Works with mouse, [Touch Events](http://www.w3.org/TR/touch-events/), [Pointer Events](http://www.w3.org/TR/pointerevents/), old [IE10 Pointer Events](http://msdn.microsoft.com/en-us/library/ie/hh673557\(v=vs.85\).aspx)
|
||||
- Responsive, works on iPhones, Androids, Windows Phones, Blackberries, Windows 8 devices
|
||||
- IE7+ compatible
|
||||
- Library agnostic. If jQuery is available, registers itself as a plugin.
|
||||
- Uses CSS3 transforms & animations, falls back to timer animations when necessary
|
||||
- Only 7.7 Kb minified
|
||||
- Perfomance-optimized `touch` functions
|
||||
- API and callback functions for extensibility
|
||||
- [Doesn't break](http://wd.dizaina.net/en/internet-maintenance/js-sliders-and-the-tab-key/) when <kbd>tab</kbd>’bing
|
||||
|
||||
##Kit
|
||||
|
||||
- **[peppermint.min.js](https://raw.github.com/wilddeer/Peppermint/master/dist/peppermint.min.js)** – minified production script
|
||||
- **[peppermint.required.css](https://raw.github.com/wilddeer/Peppermint/master/dist/peppermint.required.css)** – styles required for proper functioning
|
||||
- **[peppermint.suggested.css](https://raw.github.com/wilddeer/Peppermint/master/dist/peppermint.suggested.css)** – default styles to start with (required styles included)
|
||||
|
||||
Also available in [Bower](http://bower.io):
|
||||
|
||||
```
|
||||
bower install Peppermint --save
|
||||
```
|
||||
|
||||
##Usage
|
||||
|
||||
HTML markup:
|
||||
|
||||
```html
|
||||
<div class="peppermint peppermint-inactive" id="peppermint">
|
||||
<figure> ... </figure>
|
||||
|
||||
<figure> ... </figure>
|
||||
|
||||
<figure> ... </figure>
|
||||
</div>
|
||||
```
|
||||
|
||||
Javascript:
|
||||
|
||||
```javascript
|
||||
var slider = Peppermint(document.getElementById('peppermint'));
|
||||
```
|
||||
|
||||
Or javascript + jQuery:
|
||||
|
||||
```javascript
|
||||
$('.peppermint').Peppermint();
|
||||
```
|
||||
|
||||
`peppermint-inactive` class is not required. It is replaced with `peppermint-active` during setup.
|
||||
|
||||
You are free to use any other tag instead of `figure`. When using `figure`, don't forget to include [html5shiv](https://github.com/aFarkas/html5shiv), otherwise it won't work in old IEs.
|
||||
|
||||
Place anything you want within the slides.
|
||||
|
||||
##Settings
|
||||
|
||||
Peppermint can take settings object as an optional second parameter (first when using jQuery). Default settings:
|
||||
|
||||
```javascript
|
||||
{
|
||||
//transition time when changing slides, ms
|
||||
speed: 300,
|
||||
|
||||
//transition time when changing slides after touch, ms
|
||||
touchSpeed: 300,
|
||||
|
||||
//slideshow enabled
|
||||
slideshow: false,
|
||||
|
||||
//slideshow interval, ms
|
||||
slideshowInterval: 4000,
|
||||
|
||||
//stop slideshow after user interacts with the slider
|
||||
stopSlideshowAfterInteraction: false,
|
||||
|
||||
//slide number to start with
|
||||
startSlide: 0,
|
||||
|
||||
//use mouse to drag the slider
|
||||
mouseDrag: true,
|
||||
|
||||
//don't initialize Peppermint if there's only one slide
|
||||
disableIfOneSlide: true,
|
||||
|
||||
//Prefix to be used with Peppermint classes,
|
||||
//such as `inactive`, `active`, `mouse`, `drag`, etc.
|
||||
//Don't forget to change the stylesheet appropriately!
|
||||
cssPrefix: 'peppermint-',
|
||||
|
||||
//show dots
|
||||
dots: false,
|
||||
|
||||
//prepend dots to dotsContainer (default is append)
|
||||
dotsPrepend: false,
|
||||
|
||||
//Element to contain dots, defaults to Peppermint's root element.
|
||||
//Can be anywhere on the page.
|
||||
dotsContainer: undefined,
|
||||
|
||||
//element containing slides, defaults to Peppermint's root element
|
||||
slidesContainer: undefined,
|
||||
|
||||
//Callback function, runs at slide change.
|
||||
//Receives slide number as a parameter.
|
||||
onSlideChange: undefined,
|
||||
|
||||
//Callback function, runs at setup end.
|
||||
//Receives total number of slides as a parameter.
|
||||
onSetup: undefined
|
||||
}
|
||||
```
|
||||
|
||||
####Examples
|
||||
|
||||
JS:
|
||||
|
||||
```javascript
|
||||
var slider = Peppermint(document.getElementById('peppermint'), {
|
||||
dots: true,
|
||||
slideshow: true,
|
||||
speed: 500,
|
||||
slideshowInterval: 5000,
|
||||
stopSlideshowAfterInteraction: true,
|
||||
onSetup: function(n) {
|
||||
console.log('Peppermint setup done. Slides found: ' + n);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
JS + jQuery:
|
||||
|
||||
```javascript
|
||||
$('.peppermint').Peppermint({
|
||||
dots: true,
|
||||
slideshow: true,
|
||||
speed: 500,
|
||||
slideshowInterval: 5000,
|
||||
stopSlideshowAfterInteraction: true,
|
||||
onSetup: function(n) {
|
||||
console.log('Peppermint setup done. Slides found: ' + n);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
##API
|
||||
|
||||
Peppermint exposes a set of functions upon installation. These functions can be used to controll the slider externally:
|
||||
|
||||
`slideTo(n)` – change active slide to `n`;
|
||||
|
||||
`next()` – next slide;
|
||||
|
||||
`prev()` – previous slide;
|
||||
|
||||
`start()` – start slideshow;
|
||||
|
||||
`stop()` – stop slideshow;
|
||||
|
||||
`pause()` – pause slideshow until the next slide change;
|
||||
|
||||
`getCurrentPos()` – get current slide number;
|
||||
|
||||
`getSlidesNumber()` – get total number of slides;
|
||||
|
||||
`recalcWidth()` – recalculate slider's and slides' widths. Usefull when the container width is changed. Width recalculation runs automatically on window resize and device orientation change.
|
||||
|
||||
####Examples
|
||||
|
||||
JS:
|
||||
|
||||
```javascript
|
||||
//init Peppermint and save the API object
|
||||
var slider = Peppermint(document.getElementById('peppermint')),
|
||||
//save links to HTML nodes
|
||||
rightArr = document.getElementById('right-arr'),
|
||||
leftArr = document.getElementById('left-arr'),
|
||||
getSlidesNumberButton = document.getElementById('getslidesnumber');
|
||||
|
||||
//click `#right-arr` to go to the next slide
|
||||
rightArr.addEventListener('click', slider.next, false);
|
||||
|
||||
//click `#left-arr` to go to the previous slide
|
||||
leftArr.addEventListener('click', slider.prev, false);
|
||||
|
||||
//click `#getslidesnumber` to alert total number of slides
|
||||
getSlidesNumberButton.addEventListener('click', function() {
|
||||
alert('There are ' + slider.getSlidesNumber() + ' slides');
|
||||
}, false);
|
||||
```
|
||||
|
||||
JS + jQuery:
|
||||
|
||||
```javascript
|
||||
//save jQuery link to slider's block
|
||||
var slider = $('#peppermint');
|
||||
|
||||
//init Peppermint
|
||||
slider.Peppermint();
|
||||
|
||||
//click `#right-arr` to go to the next slide
|
||||
$('#right-arr').click(slider.data('Peppermint').next);
|
||||
|
||||
//click `#left-arr` to go to the previous slide
|
||||
$('#left-arr').click(slider.data('Peppermint').prev);
|
||||
|
||||
//click `#getslidesnumber` to alert total number of slides
|
||||
$('#getslidesnumber').click(function() {
|
||||
alert('There are ' + slider.data('Peppermint').getSlidesNumber() + ' slides');
|
||||
});
|
||||
```
|
||||
|
||||
##Using Peppermint?
|
||||
|
||||
Drop me a link → [:envelope: wd@dizaina.net](mailto:wd@dizaina.net).
|
||||
|
||||
##License
|
||||
|
||||
[MIT license](http://opensource.org/licenses/MIT).
|
||||
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"name": "Peppermint",
|
||||
"version": "1.3.7",
|
||||
"homepage": "http://wd.dizaina.net/en/scripts/peppermint/",
|
||||
"authors": [
|
||||
"Oleg Korsunsky <wd@dizaina.net>"
|
||||
],
|
||||
"description": "Responsive touch-enabled slider. Tiny, supports mouse and all sorts of touch, library agnostic.",
|
||||
"main": [
|
||||
"dist/peppermint.min.js",
|
||||
"dist/peppermint.suggested.css"
|
||||
],
|
||||
"keywords": [
|
||||
"touch",
|
||||
"touch-events",
|
||||
"pointer-events",
|
||||
"mouse-events",
|
||||
"slider",
|
||||
"carousel",
|
||||
"gallery",
|
||||
"vanilla-js",
|
||||
"framework-agnostic",
|
||||
"library-agnostic"
|
||||
],
|
||||
"license": "MIT",
|
||||
"ignore": [
|
||||
"**/.*",
|
||||
"node_modules",
|
||||
"bower_components",
|
||||
"test"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,716 @@
|
||||
/*!
|
||||
* Peppermint touch slider
|
||||
* v. 1.3.7 | https://github.com/wilddeer/Peppermint
|
||||
* Copyright Oleg Korsunsky | http://wd.dizaina.net/
|
||||
*
|
||||
* Depends on Event Burrito (included) | https://github.com/wilddeer/Event-Burrito
|
||||
* MIT License
|
||||
*/
|
||||
function Peppermint(_this, options) {
|
||||
var slider = {
|
||||
slides: [],
|
||||
dots: [],
|
||||
left: 0
|
||||
},
|
||||
slidesNumber,
|
||||
flickThreshold = 200, //Flick threshold (ms)
|
||||
activeSlide = 0,
|
||||
slideWidth,
|
||||
dotBlock,
|
||||
slideBlock,
|
||||
slideshowTimeoutId,
|
||||
slideshowActive,
|
||||
animationTimer;
|
||||
|
||||
//default options
|
||||
var o = {
|
||||
speed: 300, //transition between slides in ms
|
||||
touchSpeed: 300, //transition between slides in ms after touch
|
||||
slideshow: false, //launch slideshow at start
|
||||
slideshowInterval: 4000,
|
||||
stopSlideshowAfterInteraction: false, //stop slideshow after user interaction
|
||||
startSlide: 0, //first slide to show
|
||||
mouseDrag: true, //enable mouse drag
|
||||
disableIfOneSlide: true,
|
||||
cssPrefix: 'peppermint-',
|
||||
dots: false, //show dots
|
||||
dotsPrepend: false, //dots before slides
|
||||
dotsContainer: undefined,
|
||||
slidesContainer: undefined,
|
||||
onSlideChange: undefined, //slide change callback
|
||||
onSetup: undefined //setup callback
|
||||
};
|
||||
|
||||
//merge user options into defaults
|
||||
options && mergeObjects(o, options);
|
||||
|
||||
var classes = {
|
||||
inactive: o.cssPrefix + 'inactive',
|
||||
active: o.cssPrefix + 'active',
|
||||
mouse: o.cssPrefix + 'mouse',
|
||||
drag: o.cssPrefix + 'drag',
|
||||
slides: o.cssPrefix + 'slides',
|
||||
dots: o.cssPrefix + 'dots',
|
||||
activeDot: o.cssPrefix + 'active-dot',
|
||||
mouseClicked: o.cssPrefix + 'mouse-clicked'
|
||||
};
|
||||
|
||||
//feature detects
|
||||
var support = {
|
||||
transforms: testProp('transform'),
|
||||
transitions: testProp('transition')
|
||||
};
|
||||
|
||||
function mergeObjects(targetObj, sourceObject) {
|
||||
for (var key in sourceObject) {
|
||||
if (sourceObject.hasOwnProperty(key)) {
|
||||
targetObj[key] = sourceObject[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function testProp(prop) {
|
||||
var prefixes = ['Webkit', 'Moz', 'O', 'ms'],
|
||||
block = document.createElement('div');
|
||||
|
||||
if (block.style[prop] !== undefined) return true;
|
||||
|
||||
prop = prop.charAt(0).toUpperCase() + prop.slice(1);
|
||||
for (var i in prefixes) {
|
||||
if (block.style[prefixes[i]+prop] !== undefined) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function addClass(el, cl) {
|
||||
if (!new RegExp('(\\s|^)'+cl+'(\\s|$)').test(el.className)) {
|
||||
el.className += ' ' + cl;
|
||||
}
|
||||
}
|
||||
|
||||
function removeClass(el, cl) {
|
||||
el.className = el.className.replace(new RegExp('(\\s+|^)'+cl+'(\\s+|$)', 'g'), ' ').replace(/^\s+|\s+$/g, '');
|
||||
}
|
||||
|
||||
//n - slide number (starting from 0)
|
||||
//speed - transition in ms, can be omitted
|
||||
function changeActiveSlide(n, speed) {
|
||||
if (n<0) {
|
||||
n = 0;
|
||||
}
|
||||
else if (n>slidesNumber-1) {
|
||||
n = slidesNumber-1;
|
||||
}
|
||||
|
||||
//change active dot
|
||||
for (var i = slider.dots.length - 1; i >= 0; i--) {
|
||||
removeClass(slider.dots[i], classes.activeDot);
|
||||
}
|
||||
|
||||
addClass(slider.dots[n], classes.activeDot);
|
||||
|
||||
activeSlide = n;
|
||||
|
||||
changePos(-n*slider.width, (speed===undefined?o.speed:speed));
|
||||
|
||||
//reset slideshow timeout whenever active slide is changed for whatever reason
|
||||
stepSlideshow();
|
||||
|
||||
//API callback
|
||||
o.onSlideChange && o.onSlideChange(n);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
//changes position of the slider (in px) with given speed (in ms)
|
||||
function changePos(pos, speed) {
|
||||
var time = speed?speed+'ms':'';
|
||||
|
||||
slideBlock.style.webkitTransitionDuration =
|
||||
slideBlock.style.MozTransitionDuration =
|
||||
slideBlock.style.msTransitionDuration =
|
||||
slideBlock.style.OTransitionDuration =
|
||||
slideBlock.style.transitionDuration = time;
|
||||
|
||||
setPos(pos);
|
||||
}
|
||||
|
||||
//fallback to `setInterval` animations for UAs with no CSS transitions
|
||||
function changePosFallback(pos, speed) {
|
||||
animationTimer && clearInterval(animationTimer);
|
||||
|
||||
if (!speed) {
|
||||
setPos(pos);
|
||||
return;
|
||||
}
|
||||
|
||||
var startTime = +new Date,
|
||||
startPos = slider.left;
|
||||
|
||||
animationTimer = setInterval(function() {
|
||||
//rough bezier emulation
|
||||
var diff, y,
|
||||
elapsed = +new Date - startTime,
|
||||
f = elapsed / speed,
|
||||
bezier = [0, 0.7, 1, 1];
|
||||
|
||||
function getPoint(p1, p2) {
|
||||
return (p2-p1)*f + p1;
|
||||
}
|
||||
|
||||
if (f >= 1) {
|
||||
setPos(pos);
|
||||
clearInterval(animationTimer);
|
||||
return;
|
||||
}
|
||||
|
||||
diff = pos - startPos;
|
||||
|
||||
y = getPoint(
|
||||
getPoint(getPoint(bezier[0], bezier[1]), getPoint(bezier[1], bezier[2])),
|
||||
getPoint(getPoint(bezier[1], bezier[2]), getPoint(bezier[2], bezier[3]))
|
||||
);
|
||||
|
||||
setPos(Math.floor(y*diff + startPos));
|
||||
}, 15);
|
||||
}
|
||||
|
||||
//sets position of the slider (in px)
|
||||
function setPos(pos) {
|
||||
slideBlock.style.webkitTransform = 'translate('+pos+'px,0) translateZ(0)';
|
||||
slideBlock.style.msTransform =
|
||||
slideBlock.style.MozTransform =
|
||||
slideBlock.style.OTransform =
|
||||
slideBlock.style.transform = 'translateX('+pos+'px)';
|
||||
|
||||
slider.left = pos;
|
||||
}
|
||||
|
||||
//`setPos` fallback for UAs with no CSS transforms support
|
||||
function setPosFallback(pos) {
|
||||
slideBlock.style.left = pos+'px';
|
||||
|
||||
slider.left = pos;
|
||||
}
|
||||
|
||||
function nextSlide() {
|
||||
var n = activeSlide + 1;
|
||||
|
||||
if (n > slidesNumber - 1) {
|
||||
n = 0;
|
||||
}
|
||||
|
||||
return changeActiveSlide(n);
|
||||
}
|
||||
|
||||
function prevSlide() {
|
||||
var n = activeSlide - 1;
|
||||
|
||||
if (n < 0) {
|
||||
n = slidesNumber - 1;
|
||||
}
|
||||
|
||||
return changeActiveSlide(n);
|
||||
}
|
||||
|
||||
function startSlideshow() {
|
||||
slideshowActive = true;
|
||||
stepSlideshow();
|
||||
}
|
||||
|
||||
//sets or resets timeout before switching to the next slide
|
||||
function stepSlideshow() {
|
||||
if (slideshowActive) {
|
||||
slideshowTimeoutId && clearTimeout(slideshowTimeoutId);
|
||||
|
||||
slideshowTimeoutId = setTimeout(function() {
|
||||
nextSlide();
|
||||
},
|
||||
o.slideshowInterval);
|
||||
}
|
||||
}
|
||||
|
||||
//pauses slideshow until `stepSlideshow` is invoked
|
||||
function pauseSlideshow() {
|
||||
slideshowTimeoutId && clearTimeout(slideshowTimeoutId);
|
||||
}
|
||||
|
||||
function stopSlideshow() {
|
||||
slideshowActive = false;
|
||||
slideshowTimeoutId && clearTimeout(slideshowTimeoutId);
|
||||
}
|
||||
|
||||
//this should be invoked when the width of the slider is changed
|
||||
function onWidthChange() {
|
||||
slider.width = _this.offsetWidth;
|
||||
|
||||
//have to do this in `px` because of webkit's rounding errors :-(
|
||||
slideBlock.style.width = slider.width*slidesNumber+'px';
|
||||
for (var i = 0; i < slidesNumber; i++) {
|
||||
slider.slides[i].style.width = slider.width+'px';
|
||||
}
|
||||
changePos(-activeSlide*slider.width);
|
||||
}
|
||||
|
||||
function addEvent(el, event, func, bool) {
|
||||
if (!event) return;
|
||||
|
||||
el.addEventListener? el.addEventListener(event, func, !!bool): el.attachEvent('on'+event, func);
|
||||
}
|
||||
|
||||
//init touch events
|
||||
function touchInit() {
|
||||
EventBurrito(slideBlock, {
|
||||
mouse: o.mouseDrag,
|
||||
start: function(event, start) {
|
||||
//firefox doesn't want to apply cursor from `:active` CSS rule, have to add a class :-/
|
||||
addClass(_this, classes.drag);
|
||||
},
|
||||
move: function(event, start, diff, speed) {
|
||||
pauseSlideshow(); //pause the slideshow when touch is in progress
|
||||
|
||||
//if it's first slide and moving left or last slide and moving right -- resist!
|
||||
diff.x =
|
||||
diff.x /
|
||||
(
|
||||
(!activeSlide && diff.x > 0
|
||||
|| activeSlide == slidesNumber - 1 && diff.x < 0)
|
||||
?
|
||||
(Math.abs(diff.x)/slider.width*2 + 1)
|
||||
:
|
||||
1
|
||||
);
|
||||
|
||||
//change position of the slider appropriately
|
||||
changePos(diff.x - slider.width*activeSlide);
|
||||
},
|
||||
end: function(event, start, diff, speed) {
|
||||
if (diff.x) {
|
||||
var ratio = Math.abs(diff.x)/slider.width,
|
||||
//How many slides to skip. Remainder > 0.25 counts for one slide.
|
||||
skip = Math.floor(ratio) + (ratio - Math.floor(ratio) > 0.25?1:0),
|
||||
//Super-duper formula to detect a flick.
|
||||
//First, it's got to be fast enough.
|
||||
//Second, if `skip==0`, 20px move is enough to switch to the next slide.
|
||||
//If `skip>0`, it's enough to slide to the middle of the slide minus `slider.width/9` to skip even further.
|
||||
flick = diff.time < flickThreshold+flickThreshold*skip/1.8 && Math.abs(diff.x) - skip*slider.width > (skip?-slider.width/9:20);
|
||||
|
||||
skip += (flick?1:0);
|
||||
|
||||
if (diff.x < 0) {
|
||||
changeActiveSlide(activeSlide+skip, o.touchSpeed);
|
||||
}
|
||||
else {
|
||||
changeActiveSlide(activeSlide-skip, o.touchSpeed);
|
||||
}
|
||||
|
||||
o.stopSlideshowAfterInteraction && stopSlideshow();
|
||||
}
|
||||
|
||||
//remove the drag class
|
||||
removeClass(_this, classes.drag);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function setup() {
|
||||
var slideSource = o.slidesContainer || _this,
|
||||
dotsTarget = o.dotsContainer || _this;
|
||||
|
||||
if (o.disableIfOneSlide && slideSource.children.length <= 1) return;
|
||||
|
||||
//If current UA doesn't support css transforms or transitions -- use fallback functions.
|
||||
//(Using separate functions instead of checks for better performance)
|
||||
if (!support.transforms || !!window.opera) setPos = setPosFallback;
|
||||
if (!support.transitions || !!window.opera) changePos = changePosFallback;
|
||||
|
||||
slideBlock = o.slidesContainer || document.createElement('div');
|
||||
addClass(slideBlock, classes.slides);
|
||||
|
||||
//get slides & generate dots
|
||||
for (var i = 0, l = slideSource.children.length; i < l; i++) {
|
||||
var slide = slideSource.children[i],
|
||||
dot = document.createElement('li');
|
||||
|
||||
slider.slides.push(slide);
|
||||
|
||||
//`tabindex` makes dots tabbable
|
||||
dot.setAttribute('tabindex', '0');
|
||||
dot.setAttribute('role', 'button');
|
||||
|
||||
dot.innerHTML = '<span></span>';
|
||||
|
||||
(function(x, dotClosure) {
|
||||
//bind events to dots
|
||||
addEvent(dotClosure, 'click', function(event) {
|
||||
changeActiveSlide(x);
|
||||
o.stopSlideshowAfterInteraction && stopSlideshow();
|
||||
});
|
||||
|
||||
//Bind the same function to Enter key except for the `blur` part -- I dont't want
|
||||
//the focus to be lost when the user is using his keyboard to navigate.
|
||||
addEvent(dotClosure, 'keyup', function(event) {
|
||||
if (event.keyCode == 13) {
|
||||
changeActiveSlide(x);
|
||||
o.stopSlideshowAfterInteraction && stopSlideshow();
|
||||
}
|
||||
});
|
||||
|
||||
//Don't want to disable outlines completely for accessibility reasons.
|
||||
//Instead, add class with `outline: 0` on mouseup and remove it on blur.
|
||||
addEvent(dotClosure, 'mouseup', function(event) {
|
||||
addClass(dotClosure, classes.mouseClicked);
|
||||
});
|
||||
|
||||
//capturing fixes IE bug
|
||||
addEvent(dotClosure, 'blur', function(){
|
||||
removeClass(dotClosure, classes.mouseClicked);
|
||||
}, true);
|
||||
|
||||
//This solves tabbing problems:
|
||||
//When an element inside a slide catches focus we switch to that slide
|
||||
//and reset `scrollLeft` of the slider block.
|
||||
//`SetTimeout` solves Chrome's bug.
|
||||
//Event capturing is used to catch events on the slide level.
|
||||
//Since older IEs don't have capturing, `onfocusin` is used as a fallback.
|
||||
addEvent(slide, 'focus', slide.onfocusin = function(e) {
|
||||
_this.scrollLeft = 0;
|
||||
setTimeout(function() {
|
||||
_this.scrollLeft = 0;
|
||||
}, 0);
|
||||
changeActiveSlide(x);
|
||||
}, true);
|
||||
})(i, dot)
|
||||
|
||||
slider.dots.push(dot);
|
||||
}
|
||||
|
||||
slidesNumber = slider.slides.length;
|
||||
|
||||
slideWidth = 100/slidesNumber;
|
||||
|
||||
addClass(_this, classes.active);
|
||||
removeClass(_this, classes.inactive);
|
||||
o.mouseDrag && addClass(_this, classes.mouse);
|
||||
|
||||
slider.width = _this.offsetWidth;
|
||||
|
||||
//had to do this in `px` because of webkit's rounding errors :-(
|
||||
slideBlock.style.width = slider.width*slidesNumber+'px';
|
||||
for (var i = 0; i < slidesNumber; i++) {
|
||||
slider.slides[i].style.width = slider.width+'px';
|
||||
slideBlock.appendChild(slider.slides[i]);
|
||||
}
|
||||
|
||||
if (!o.slidesContainer) _this.appendChild(slideBlock);
|
||||
|
||||
//append dots
|
||||
if (o.dots && slidesNumber > 1) {
|
||||
dotBlock = document.createElement('ul');
|
||||
addClass(dotBlock, classes.dots);
|
||||
|
||||
for (var i = 0, l = slider.dots.length; i < l; i++) {
|
||||
dotBlock.appendChild(slider.dots[i]);
|
||||
}
|
||||
|
||||
if (o.dotsPrepend) {
|
||||
dotsTarget.insertBefore(dotBlock,dotsTarget.firstChild);
|
||||
}
|
||||
else {
|
||||
dotsTarget.appendChild(dotBlock);
|
||||
}
|
||||
}
|
||||
|
||||
//watch for slider width changes
|
||||
addEvent(window, 'resize', onWidthChange);
|
||||
addEvent(window, 'orientationchange', onWidthChange);
|
||||
|
||||
//init first slide, timeout to expose the API first
|
||||
setTimeout(function() {
|
||||
changeActiveSlide(o.startSlide, 0);
|
||||
}, 0);
|
||||
|
||||
//init slideshow
|
||||
if (o.slideshow) startSlideshow();
|
||||
|
||||
touchInit();
|
||||
|
||||
//API callback, timeout to expose the API first
|
||||
setTimeout(function() {
|
||||
o.onSetup && o.onSetup(slidesNumber);
|
||||
}, 0);
|
||||
}
|
||||
|
||||
//Init
|
||||
setup();
|
||||
|
||||
//expose the API
|
||||
return {
|
||||
slideTo: function(slide) {
|
||||
return changeActiveSlide(parseInt(slide, 10));
|
||||
},
|
||||
|
||||
next: nextSlide,
|
||||
|
||||
prev: prevSlide,
|
||||
|
||||
//start slideshow
|
||||
start: startSlideshow,
|
||||
|
||||
//stop slideshow
|
||||
stop: stopSlideshow,
|
||||
|
||||
//pause slideshow until the next slide change
|
||||
pause: pauseSlideshow,
|
||||
|
||||
//get current slide number
|
||||
getCurrentPos: function() {
|
||||
return activeSlide;
|
||||
},
|
||||
|
||||
//get total number of slides
|
||||
getSlidesNumber: function() {
|
||||
return slidesNumber;
|
||||
},
|
||||
|
||||
//invoke this when the slider's width is changed
|
||||
recalcWidth: onWidthChange
|
||||
};
|
||||
};
|
||||
|
||||
//if jQuery is present -- create a plugin
|
||||
if (window.jQuery) {
|
||||
(function($) {
|
||||
$.fn.Peppermint = function(options) {
|
||||
this.each(function() {
|
||||
$(this).data('Peppermint', Peppermint(this, options));
|
||||
});
|
||||
|
||||
return this;
|
||||
};
|
||||
})(window.jQuery);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Event Burrito is a touch / mouse / pointer event unifier
|
||||
* https://github.com/wilddeer/Event-Burrito
|
||||
* Copyright Oleg Korsunsky | http://wd.dizaina.net/
|
||||
*
|
||||
* MIT License
|
||||
*/
|
||||
function EventBurrito(_this, options) {
|
||||
|
||||
var noop = function() {},
|
||||
o = {
|
||||
preventDefault: true,
|
||||
clickTolerance: 0,
|
||||
preventScroll: false,
|
||||
mouse: true,
|
||||
start: noop,
|
||||
move: noop,
|
||||
end: noop,
|
||||
click: noop
|
||||
};
|
||||
|
||||
//merge user options into defaults
|
||||
options && mergeObjects(o, options);
|
||||
|
||||
var support = {
|
||||
pointerEvents: !!window.navigator.pointerEnabled,
|
||||
msPointerEvents: !!window.navigator.msPointerEnabled
|
||||
},
|
||||
start = {},
|
||||
diff = {},
|
||||
speed = {},
|
||||
stack = [],
|
||||
listeners = [],
|
||||
isScrolling,
|
||||
eventType,
|
||||
clicksAllowed = true, //flag allowing default click actions (e.g. links)
|
||||
eventModel = (support.pointerEvents? 1 : (support.msPointerEvents? 2 : 0)),
|
||||
events = [
|
||||
['touchstart', 'touchmove', 'touchend', 'touchcancel'], //touch events
|
||||
['pointerdown', 'pointermove', 'pointerup', 'pointercancel'], //pointer events
|
||||
['MSPointerDown', 'MSPointerMove', 'MSPointerUp', 'MSPointerCancel'], //IE10 pointer events
|
||||
['mousedown', 'mousemove', 'mouseup', false] //mouse events
|
||||
],
|
||||
//some checks for different event types
|
||||
checks = [
|
||||
//touch events
|
||||
function(e) {
|
||||
//skip the event if it's multitouch or pinch move
|
||||
return (e.touches && e.touches.length > 1) || (e.scale && e.scale !== 1);
|
||||
},
|
||||
//pointer events
|
||||
function(e) {
|
||||
//Skip it, if:
|
||||
//1. event is not primary (other pointers during multitouch),
|
||||
//2. left mouse button is not pressed,
|
||||
//3. mouse drag is disabled and event is not touch
|
||||
return !e.isPrimary || (e.buttons && e.buttons !== 1) || (!o.mouse && e.pointerType !== 'touch' && e.pointerType !== 'pen');
|
||||
},
|
||||
//IE10 pointer events
|
||||
function(e) {
|
||||
//same checks as in pointer events
|
||||
return !e.isPrimary || (e.buttons && e.buttons !== 1) || (!o.mouse && e.pointerType !== e.MSPOINTER_TYPE_TOUCH && e.pointerType !== e.MSPOINTER_TYPE_PEN);
|
||||
},
|
||||
//mouse events
|
||||
function(e) {
|
||||
//skip the event if left mouse button is not pressed
|
||||
//in IE7-8 `buttons` is not defined, in IE9 LMB is 0
|
||||
return (e.buttons && e.buttons !== 1);
|
||||
}
|
||||
];
|
||||
|
||||
function mergeObjects(targetObj, sourceObject) {
|
||||
for (var key in sourceObject) {
|
||||
if (sourceObject.hasOwnProperty(key)) {
|
||||
targetObj[key] = sourceObject[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function addEvent(el, event, func, bool) {
|
||||
if (!event) return;
|
||||
|
||||
el.addEventListener? el.addEventListener(event, func, !!bool): el.attachEvent('on'+event, func);
|
||||
|
||||
//return event remover to easily remove anonymous functions later
|
||||
return {
|
||||
remove: function() {
|
||||
removeEvent(el, event, func, bool);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function removeEvent(el, event, func, bool) {
|
||||
if (!event) return;
|
||||
|
||||
el.removeEventListener? el.removeEventListener(event, func, !!bool): el.detachEvent('on'+event, func);
|
||||
}
|
||||
|
||||
function preventDefault(event) {
|
||||
event.preventDefault? event.preventDefault() : event.returnValue = false;
|
||||
}
|
||||
|
||||
function getDiff(event) {
|
||||
diff = {
|
||||
x: (eventType? event.clientX : event.touches[0].clientX) - start.x,
|
||||
y: (eventType? event.clientY : event.touches[0].clientY) - start.y,
|
||||
|
||||
time: Number(new Date) - start.time
|
||||
};
|
||||
|
||||
if (diff.time - stack[stack.length - 1].time) {
|
||||
for (var i = 0; i < stack.length - 1 && diff.time - stack[i].time > 80; i++);
|
||||
|
||||
speed = {
|
||||
x: (diff.x - stack[i].x) / (diff.time - stack[i].time),
|
||||
y: (diff.y - stack[i].y) / (diff.time - stack[i].time)
|
||||
};
|
||||
|
||||
if (stack.length >= 5) stack.shift();
|
||||
stack.push({x: diff.x, y: diff.y, time: diff.time});
|
||||
}
|
||||
}
|
||||
|
||||
function tStart(event, eType) {
|
||||
clicksAllowed = true;
|
||||
eventType = eType; //leak event type
|
||||
|
||||
if (checks[eventType](event)) return;
|
||||
|
||||
//attach event listeners to the document, so that the slider
|
||||
//will continue to recieve events wherever the pointer is
|
||||
addEvent(document, events[eventType][1], tMove);
|
||||
addEvent(document, events[eventType][2], tEnd);
|
||||
addEvent(document, events[eventType][3], tEnd);
|
||||
|
||||
//fixes WebKit's cursor while dragging
|
||||
if (o.preventDefault && eventType) preventDefault(event);
|
||||
|
||||
//remember starting time and position
|
||||
start = {
|
||||
x: eventType? event.clientX : event.touches[0].clientX,
|
||||
y: eventType? event.clientY : event.touches[0].clientY,
|
||||
|
||||
time: Number(new Date)
|
||||
};
|
||||
|
||||
//reset
|
||||
isScrolling = undefined;
|
||||
diff = {x:0, y:0, time: 0};
|
||||
speed = {x:0, y:0};
|
||||
stack = [{x:0, y:0, time: 0}];
|
||||
|
||||
o.start(event, start);
|
||||
}
|
||||
|
||||
function tMove(event) {
|
||||
//if user is trying to scroll vertically -- do nothing
|
||||
if ((!o.preventScroll && isScrolling) || checks[eventType](event)) return;
|
||||
|
||||
getDiff(event);
|
||||
|
||||
if (Math.abs(diff.x) > o.clickTolerance || Math.abs(diff.y) > o.clickTolerance) clicksAllowed = false; //if there was a move -- deny all the clicks before the next touchstart
|
||||
|
||||
//check whether the user is trying to scroll vertically
|
||||
if (isScrolling === undefined && eventType !== 3) {
|
||||
//assign and check `isScrolling` at the same time
|
||||
if (isScrolling = (Math.abs(diff.x) < Math.abs(diff.y)) && !o.preventScroll) return;
|
||||
}
|
||||
|
||||
if (o.preventDefault) preventDefault(event); //Prevent scrolling
|
||||
|
||||
o.move(event, start, diff, speed);
|
||||
}
|
||||
|
||||
function tEnd(event) {
|
||||
eventType && getDiff(event);
|
||||
|
||||
//IE likes to focus links after touchend.
|
||||
//Since we don't want to disable link outlines completely for accessibility reasons,
|
||||
//we just defocus it after touch and disable the outline for `:active` links in css.
|
||||
//This way the outline will remain visible when using keyboard.
|
||||
!clicksAllowed && event.target && event.target.blur && event.target.blur();
|
||||
|
||||
//detach event listeners from the document
|
||||
removeEvent(document, events[eventType][1], tMove);
|
||||
removeEvent(document, events[eventType][2], tEnd);
|
||||
removeEvent(document, events[eventType][3], tEnd);
|
||||
|
||||
o.end(event, start, diff, speed);
|
||||
}
|
||||
|
||||
function init() {
|
||||
//bind touchstart
|
||||
listeners.push(addEvent(_this, events[eventModel][0], function(e) {tStart(e, eventModel);}));
|
||||
//prevent stuff from dragging when using mouse
|
||||
listeners.push(addEvent(_this, 'dragstart', preventDefault));
|
||||
|
||||
//bind mousedown if necessary
|
||||
if (o.mouse && !eventModel) {
|
||||
listeners.push(addEvent(_this, events[3][0], function(e) {tStart(e, 3);}));
|
||||
}
|
||||
|
||||
//No clicking during touch
|
||||
listeners.push(addEvent(_this, 'click', function(event) {
|
||||
clicksAllowed? o.click(event): preventDefault(event);
|
||||
}));
|
||||
}
|
||||
|
||||
init();
|
||||
|
||||
//expose the API
|
||||
return {
|
||||
getClicksAllowed: function() {
|
||||
return clicksAllowed;
|
||||
},
|
||||
kill: function() {
|
||||
for (var i = listeners.length - 1; i >= 0; i--) {
|
||||
listeners[i].remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
/*!
|
||||
* Peppermint touch slider
|
||||
* v. 1.3.7 | https://github.com/wilddeer/Peppermint
|
||||
* Copyright Oleg Korsunsky | http://wd.dizaina.net/
|
||||
*
|
||||
* Depends on Event Burrito (included) | https://github.com/wilddeer/Event-Burrito
|
||||
* MIT License
|
||||
*/
|
||||
function Peppermint(a,b){function c(a,b){for(var c in b)b.hasOwnProperty(c)&&(a[c]=b[c])}function d(a){var b=["Webkit","Moz","O","ms"],c=document.createElement("div");if(void 0!==c.style[a])return!0;a=a.charAt(0).toUpperCase()+a.slice(1);for(var d in b)if(void 0!==c.style[b[d]+a])return!0;return!1}function e(a,b){new RegExp("(\\s|^)"+b+"(\\s|$)").test(a.className)||(a.className+=" "+b)}function f(a,b){a.className=a.className.replace(new RegExp("(\\s+|^)"+b+"(\\s+|$)","g")," ").replace(/^\s+|\s+$/g,"")}function g(a,b){0>a?a=0:a>v-1&&(a=v-1);for(var c=C.dots.length-1;c>=0;c--)f(C.dots[c],G.activeDot);return e(C.dots[a],G.activeDot),E=a,h(-a*C.width,void 0===b?F.speed:b),o(),F.onSlideChange&&F.onSlideChange(a),a}function h(a,b){var c=b?b+"ms":"";y.style.webkitTransitionDuration=y.style.MozTransitionDuration=y.style.msTransitionDuration=y.style.OTransitionDuration=y.style.transitionDuration=c,j(a)}function i(a,b){if(B&&clearInterval(B),!b)return void j(a);var c=+new Date,d=C.left;B=setInterval(function(){function e(a,b){return(b-a)*i+a}var f,g,h=+new Date-c,i=h/b,k=[0,.7,1,1];return i>=1?(j(a),void clearInterval(B)):(f=a-d,g=e(e(e(k[0],k[1]),e(k[1],k[2])),e(e(k[1],k[2]),e(k[2],k[3]))),void j(Math.floor(g*f+d)))},15)}function j(a){y.style.webkitTransform="translate("+a+"px,0) translateZ(0)",y.style.msTransform=y.style.MozTransform=y.style.OTransform=y.style.transform="translateX("+a+"px)",C.left=a}function k(a){y.style.left=a+"px",C.left=a}function l(){var a=E+1;return a>v-1&&(a=0),g(a)}function m(){var a=E-1;return 0>a&&(a=v-1),g(a)}function n(){A=!0,o()}function o(){A&&(z&&clearTimeout(z),z=setTimeout(function(){l()},F.slideshowInterval))}function p(){z&&clearTimeout(z)}function q(){A=!1,z&&clearTimeout(z)}function r(){C.width=a.offsetWidth,y.style.width=C.width*v+"px";for(var b=0;v>b;b++)C.slides[b].style.width=C.width+"px";h(-E*C.width)}function s(a,b,c,d){b&&(a.addEventListener?a.addEventListener(b,c,!!d):a.attachEvent("on"+b,c))}function t(){EventBurrito(y,{mouse:F.mouseDrag,start:function(){e(a,G.drag)},move:function(a,b,c){p(),c.x=c.x/(!E&&c.x>0||E==v-1&&c.x<0?Math.abs(c.x)/C.width*2+1:1),h(c.x-C.width*E)},end:function(b,c,d){if(d.x){var e=Math.abs(d.x)/C.width,h=Math.floor(e)+(e-Math.floor(e)>.25?1:0),i=d.time<D+D*h/1.8&&Math.abs(d.x)-h*C.width>(h?-C.width/9:20);h+=i?1:0,d.x<0?g(E+h,F.touchSpeed):g(E-h,F.touchSpeed),F.stopSlideshowAfterInteraction&&q()}f(a,G.drag)}})}function u(){var b=F.slidesContainer||a,c=F.dotsContainer||a;if(!(F.disableIfOneSlide&&b.children.length<=1)){(!H.transforms||window.opera)&&(j=k),(!H.transitions||window.opera)&&(h=i),y=F.slidesContainer||document.createElement("div"),e(y,G.slides);for(var d=0,l=b.children.length;l>d;d++){var m=b.children[d],o=document.createElement("li");C.slides.push(m),o.setAttribute("tabindex","0"),o.setAttribute("role","button"),o.innerHTML="<span></span>",function(b,c){s(c,"click",function(){g(b),F.stopSlideshowAfterInteraction&&q()}),s(c,"keyup",function(a){13==a.keyCode&&(g(b),F.stopSlideshowAfterInteraction&&q())}),s(c,"mouseup",function(){e(c,G.mouseClicked)}),s(c,"blur",function(){f(c,G.mouseClicked)},!0),s(m,"focus",m.onfocusin=function(){a.scrollLeft=0,setTimeout(function(){a.scrollLeft=0},0),g(b)},!0)}(d,o),C.dots.push(o)}v=C.slides.length,w=100/v,e(a,G.active),f(a,G.inactive),F.mouseDrag&&e(a,G.mouse),C.width=a.offsetWidth,y.style.width=C.width*v+"px";for(var d=0;v>d;d++)C.slides[d].style.width=C.width+"px",y.appendChild(C.slides[d]);if(F.slidesContainer||a.appendChild(y),F.dots&&v>1){x=document.createElement("ul"),e(x,G.dots);for(var d=0,l=C.dots.length;l>d;d++)x.appendChild(C.dots[d]);F.dotsPrepend?c.insertBefore(x,c.firstChild):c.appendChild(x)}s(window,"resize",r),s(window,"orientationchange",r),setTimeout(function(){g(F.startSlide,0)},0),F.slideshow&&n(),t(),setTimeout(function(){F.onSetup&&F.onSetup(v)},0)}}var v,w,x,y,z,A,B,C={slides:[],dots:[],left:0},D=200,E=0,F={speed:300,touchSpeed:300,slideshow:!1,slideshowInterval:4e3,stopSlideshowAfterInteraction:!1,startSlide:0,mouseDrag:!0,disableIfOneSlide:!0,cssPrefix:"peppermint-",dots:!1,dotsPrepend:!1,dotsContainer:void 0,slidesContainer:void 0,onSlideChange:void 0,onSetup:void 0};b&&c(F,b);var G={inactive:F.cssPrefix+"inactive",active:F.cssPrefix+"active",mouse:F.cssPrefix+"mouse",drag:F.cssPrefix+"drag",slides:F.cssPrefix+"slides",dots:F.cssPrefix+"dots",activeDot:F.cssPrefix+"active-dot",mouseClicked:F.cssPrefix+"mouse-clicked"},H={transforms:d("transform"),transitions:d("transition")};return u(),{slideTo:function(a){return g(parseInt(a,10))},next:l,prev:m,start:n,stop:q,pause:p,getCurrentPos:function(){return E},getSlidesNumber:function(){return v},recalcWidth:r}}window.jQuery&&!function($){$.fn.Peppermint=function(a){return this.each(function(){$(this).data("Peppermint",Peppermint(this,a))}),this}}(window.jQuery);
|
||||
function EventBurrito(a,b){function c(a,b){for(var c in b)b.hasOwnProperty(c)&&(a[c]=b[c])}function d(a,b,c,d){return b?(a.addEventListener?a.addEventListener(b,c,!!d):a.attachEvent("on"+b,c),{remove:function(){e(a,b,c,d)}}):void 0}function e(a,b,c,d){b&&(a.removeEventListener?a.removeEventListener(b,c,!!d):a.detachEvent("on"+b,c))}function f(a){a.preventDefault?a.preventDefault():a.returnValue=!1}function g(a){if(r={x:(o?a.clientX:a.touches[0].clientX)-q.x,y:(o?a.clientY:a.touches[0].clientY)-q.y,time:Number(new Date)-q.time},r.time-t[t.length-1].time){for(var b=0;b<t.length-1&&r.time-t[b].time>80;b++);s={x:(r.x-t[b].x)/(r.time-t[b].time),y:(r.y-t[b].y)/(r.time-t[b].time)},t.length>=5&&t.shift(),t.push({x:r.x,y:r.y,time:r.time})}}function h(a,b){v=!0,o=b,y[o](a)||(d(document,x[o][1],i),d(document,x[o][2],j),d(document,x[o][3],j),m.preventDefault&&o&&f(a),q={x:o?a.clientX:a.touches[0].clientX,y:o?a.clientY:a.touches[0].clientY,time:Number(new Date)},n=void 0,r={x:0,y:0,time:0},s={x:0,y:0},t=[{x:0,y:0,time:0}],m.start(a,q))}function i(a){!m.preventScroll&&n||y[o](a)||(g(a),(Math.abs(r.x)>m.clickTolerance||Math.abs(r.y)>m.clickTolerance)&&(v=!1),void 0===n&&3!==o&&(n=Math.abs(r.x)<Math.abs(r.y)&&!m.preventScroll)||(m.preventDefault&&f(a),m.move(a,q,r,s)))}function j(a){o&&g(a),!v&&a.target&&a.target.blur&&a.target.blur(),e(document,x[o][1],i),e(document,x[o][2],j),e(document,x[o][3],j),m.end(a,q,r,s)}function k(){u.push(d(a,x[w][0],function(a){h(a,w)})),u.push(d(a,"dragstart",f)),m.mouse&&!w&&u.push(d(a,x[3][0],function(a){h(a,3)})),u.push(d(a,"click",function(a){v?m.click(a):f(a)}))}var l=function(){},m={preventDefault:!0,clickTolerance:0,preventScroll:!1,mouse:!0,start:l,move:l,end:l,click:l};b&&c(m,b);var n,o,p={pointerEvents:!!window.navigator.pointerEnabled,msPointerEvents:!!window.navigator.msPointerEnabled},q={},r={},s={},t=[],u=[],v=!0,w=p.pointerEvents?1:p.msPointerEvents?2:0,x=[["touchstart","touchmove","touchend","touchcancel"],["pointerdown","pointermove","pointerup","pointercancel"],["MSPointerDown","MSPointerMove","MSPointerUp","MSPointerCancel"],["mousedown","mousemove","mouseup",!1]],y=[function(a){return a.touches&&a.touches.length>1||a.scale&&1!==a.scale},function(a){return!a.isPrimary||a.buttons&&1!==a.buttons||!m.mouse&&"touch"!==a.pointerType&&"pen"!==a.pointerType},function(a){return!a.isPrimary||a.buttons&&1!==a.buttons||!m.mouse&&a.pointerType!==a.MSPOINTER_TYPE_TOUCH&&a.pointerType!==a.MSPOINTER_TYPE_PEN},function(a){return a.buttons&&1!==a.buttons}];return k(),{getClicksAllowed:function(){return v},kill:function(){for(var a=u.length-1;a>=0;a--)u[a].remove()}}}
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
/* Peppermint minimal required styles */
|
||||
|
||||
.peppermint.peppermint-active {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
.peppermint.peppermint-active .peppermint-slides {
|
||||
position: relative;
|
||||
overflow: hidden; /* clearfix */
|
||||
-ms-touch-action: pan-y;
|
||||
touch-action: pan-y;
|
||||
}
|
||||
|
||||
.peppermint.peppermint-active .peppermint-slides > * {
|
||||
float: left;
|
||||
margin: 0;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
tap-highlight-color: transparent;
|
||||
}
|
||||
|
||||
.peppermint.peppermint-active .peppermint-slides a:active,
|
||||
.peppermint.peppermint-active .peppermint-slides a:active img {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.peppermint.peppermint-active,
|
||||
.peppermint.peppermint-active .peppermint-dots,
|
||||
.peppermint.peppermint-active .peppermint-slides,
|
||||
.peppermint.peppermint-active .peppermint-slides > * {
|
||||
-webkit-transform: translate3d(0,0,0);
|
||||
-ms-transform: translate3d(0,0,0);
|
||||
-moz-transform: translate3d(0,0,0);
|
||||
transform: translate3d(0,0,0);
|
||||
-webkit-backface-visibility: hidden;
|
||||
-moz-backface-visibility: hidden;
|
||||
-ms-backface-visibility: hidden;
|
||||
backface-visibility: hidden;
|
||||
}
|
||||
|
||||
.peppermint.peppermint-mouse .peppermint-slides {
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
cursor: move;
|
||||
cursor: -webkit-grab;
|
||||
cursor: -moz-grab;
|
||||
cursor: grab;
|
||||
}
|
||||
|
||||
.peppermint.peppermint-mouse.peppermint-drag .peppermint-slides * {
|
||||
cursor: move;
|
||||
cursor: -webkit-grabbing;
|
||||
cursor: -moz-grabbing;
|
||||
cursor: grabbing;
|
||||
}
|
||||
+154
@@ -0,0 +1,154 @@
|
||||
/* Peppermint required styles + default appearance styles */
|
||||
|
||||
.peppermint.peppermint-active {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
.peppermint.peppermint-active .peppermint-slides {
|
||||
position: relative;
|
||||
overflow: hidden; /* clearfix */
|
||||
-ms-touch-action: pan-y;
|
||||
touch-action: pan-y;
|
||||
}
|
||||
|
||||
.peppermint.peppermint-active .peppermint-slides > * {
|
||||
float: left;
|
||||
margin: 0;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
tap-highlight-color: transparent;
|
||||
}
|
||||
|
||||
.peppermint.peppermint-active .peppermint-slides a:active,
|
||||
.peppermint.peppermint-active .peppermint-slides a:active img {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.peppermint.peppermint-active,
|
||||
.peppermint.peppermint-active .peppermint-dots,
|
||||
.peppermint.peppermint-active .peppermint-slides,
|
||||
.peppermint.peppermint-active .peppermint-slides > * {
|
||||
-webkit-transform: translate3d(0,0,0);
|
||||
-ms-transform: translate3d(0,0,0);
|
||||
-moz-transform: translate3d(0,0,0);
|
||||
transform: translate3d(0,0,0);
|
||||
-webkit-backface-visibility: hidden;
|
||||
-moz-backface-visibility: hidden;
|
||||
-ms-backface-visibility: hidden;
|
||||
backface-visibility: hidden;
|
||||
}
|
||||
|
||||
.peppermint.peppermint-mouse .peppermint-slides {
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
cursor: move;
|
||||
cursor: -webkit-grab;
|
||||
cursor: -moz-grab;
|
||||
cursor: grab;
|
||||
}
|
||||
|
||||
.peppermint.peppermint-mouse.peppermint-drag .peppermint-slides * {
|
||||
cursor: move;
|
||||
cursor: -webkit-grabbing;
|
||||
cursor: -moz-grabbing;
|
||||
cursor: grabbing;
|
||||
}
|
||||
|
||||
/* default appearance styles */
|
||||
.peppermint {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.peppermint figure {
|
||||
margin: 0 0 1.5em 0;
|
||||
}
|
||||
|
||||
.peppermint figure img {
|
||||
vertical-align: top;
|
||||
max-width: 100%;
|
||||
-webkit-box-shadow: 0 1px 5px rgba(0, 0, 0, 0.2);
|
||||
box-shadow: 0 1px 5px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.peppermint figure figcaption {
|
||||
font-style: italic;
|
||||
color: #787575;
|
||||
font-size: 0.8em;
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
|
||||
.peppermint.peppermint-active {
|
||||
margin-bottom: 1.5em;
|
||||
}
|
||||
|
||||
.peppermint-slides {
|
||||
padding-top: 0.5em;
|
||||
padding-bottom: 0.5em;
|
||||
}
|
||||
|
||||
/* dots */
|
||||
ul.peppermint-dots {
|
||||
margin: 0.6em 0;
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
.peppermint.peppermint-active ul.peppermint-dots {
|
||||
margin: 0 0 0.6em 0;
|
||||
}
|
||||
|
||||
.peppermint.peppermint-active .peppermint-slides + ul.peppermint-dots {
|
||||
margin: 0.6em 0 0 0;
|
||||
}
|
||||
|
||||
ul.peppermint-dots > li {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
padding: 0.5em 0.6em;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
/* ie7 fallback */
|
||||
*display: inline;
|
||||
*zoom: 1;
|
||||
}
|
||||
|
||||
ul.peppermint-dots > li.peppermint-mouse-clicked,
|
||||
ul.peppermint-dots > li:active {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
ul.peppermint-dots > li > span {
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
margin: -4px 0 0 -4px;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 50%;
|
||||
background: #9b9890;
|
||||
}
|
||||
|
||||
ul.peppermint-dots > li.peppermint-active-dot > span {
|
||||
margin: -6px 0 0 -6px;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border: 1px solid #9b9890;
|
||||
background: transparent;
|
||||
}
|
||||
+493
@@ -0,0 +1,493 @@
|
||||
/*!
|
||||
* Peppermint touch slider
|
||||
* v. 1.3.7 | https://github.com/wilddeer/Peppermint
|
||||
* Copyright Oleg Korsunsky | http://wd.dizaina.net/
|
||||
*
|
||||
* Depends on Event Burrito | https://github.com/wilddeer/Event-Burrito
|
||||
* MIT License
|
||||
*/
|
||||
function Peppermint(_this, options) {
|
||||
var slider = {
|
||||
slides: [],
|
||||
dots: [],
|
||||
left: 0
|
||||
},
|
||||
slidesNumber,
|
||||
flickThreshold = 200, //Flick threshold (ms)
|
||||
activeSlide = 0,
|
||||
slideWidth,
|
||||
dotBlock,
|
||||
slideBlock,
|
||||
slideshowTimeoutId,
|
||||
slideshowActive,
|
||||
animationTimer;
|
||||
|
||||
//default options
|
||||
var o = {
|
||||
speed: 300, //transition between slides in ms
|
||||
touchSpeed: 300, //transition between slides in ms after touch
|
||||
slideshow: false, //launch slideshow at start
|
||||
slideshowInterval: 4000,
|
||||
stopSlideshowAfterInteraction: false, //stop slideshow after user interaction
|
||||
startSlide: 0, //first slide to show
|
||||
mouseDrag: true, //enable mouse drag
|
||||
disableIfOneSlide: true,
|
||||
cssPrefix: 'peppermint-',
|
||||
dots: false, //show dots
|
||||
dotsPrepend: false, //dots before slides
|
||||
dotsContainer: undefined,
|
||||
slidesContainer: undefined,
|
||||
onSlideChange: undefined, //slide change callback
|
||||
onSetup: undefined //setup callback
|
||||
};
|
||||
|
||||
//merge user options into defaults
|
||||
options && mergeObjects(o, options);
|
||||
|
||||
var classes = {
|
||||
inactive: o.cssPrefix + 'inactive',
|
||||
active: o.cssPrefix + 'active',
|
||||
mouse: o.cssPrefix + 'mouse',
|
||||
drag: o.cssPrefix + 'drag',
|
||||
slides: o.cssPrefix + 'slides',
|
||||
dots: o.cssPrefix + 'dots',
|
||||
activeDot: o.cssPrefix + 'active-dot',
|
||||
mouseClicked: o.cssPrefix + 'mouse-clicked'
|
||||
};
|
||||
|
||||
//feature detects
|
||||
var support = {
|
||||
transforms: testProp('transform'),
|
||||
transitions: testProp('transition')
|
||||
};
|
||||
|
||||
function mergeObjects(targetObj, sourceObject) {
|
||||
for (var key in sourceObject) {
|
||||
if (sourceObject.hasOwnProperty(key)) {
|
||||
targetObj[key] = sourceObject[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function testProp(prop) {
|
||||
var prefixes = ['Webkit', 'Moz', 'O', 'ms'],
|
||||
block = document.createElement('div');
|
||||
|
||||
if (block.style[prop] !== undefined) return true;
|
||||
|
||||
prop = prop.charAt(0).toUpperCase() + prop.slice(1);
|
||||
for (var i in prefixes) {
|
||||
if (block.style[prefixes[i]+prop] !== undefined) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function addClass(el, cl) {
|
||||
if (!new RegExp('(\\s|^)'+cl+'(\\s|$)').test(el.className)) {
|
||||
el.className += ' ' + cl;
|
||||
}
|
||||
}
|
||||
|
||||
function removeClass(el, cl) {
|
||||
el.className = el.className.replace(new RegExp('(\\s+|^)'+cl+'(\\s+|$)', 'g'), ' ').replace(/^\s+|\s+$/g, '');
|
||||
}
|
||||
|
||||
//n - slide number (starting from 0)
|
||||
//speed - transition in ms, can be omitted
|
||||
function changeActiveSlide(n, speed) {
|
||||
if (n<0) {
|
||||
n = 0;
|
||||
}
|
||||
else if (n>slidesNumber-1) {
|
||||
n = slidesNumber-1;
|
||||
}
|
||||
|
||||
//change active dot
|
||||
for (var i = slider.dots.length - 1; i >= 0; i--) {
|
||||
removeClass(slider.dots[i], classes.activeDot);
|
||||
}
|
||||
|
||||
addClass(slider.dots[n], classes.activeDot);
|
||||
|
||||
activeSlide = n;
|
||||
|
||||
changePos(-n*slider.width, (speed===undefined?o.speed:speed));
|
||||
|
||||
//reset slideshow timeout whenever active slide is changed for whatever reason
|
||||
stepSlideshow();
|
||||
|
||||
//API callback
|
||||
o.onSlideChange && o.onSlideChange(n);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
//changes position of the slider (in px) with given speed (in ms)
|
||||
function changePos(pos, speed) {
|
||||
var time = speed?speed+'ms':'';
|
||||
|
||||
slideBlock.style.webkitTransitionDuration =
|
||||
slideBlock.style.MozTransitionDuration =
|
||||
slideBlock.style.msTransitionDuration =
|
||||
slideBlock.style.OTransitionDuration =
|
||||
slideBlock.style.transitionDuration = time;
|
||||
|
||||
setPos(pos);
|
||||
}
|
||||
|
||||
//fallback to `setInterval` animations for UAs with no CSS transitions
|
||||
function changePosFallback(pos, speed) {
|
||||
animationTimer && clearInterval(animationTimer);
|
||||
|
||||
if (!speed) {
|
||||
setPos(pos);
|
||||
return;
|
||||
}
|
||||
|
||||
var startTime = +new Date,
|
||||
startPos = slider.left;
|
||||
|
||||
animationTimer = setInterval(function() {
|
||||
//rough bezier emulation
|
||||
var diff, y,
|
||||
elapsed = +new Date - startTime,
|
||||
f = elapsed / speed,
|
||||
bezier = [0, 0.7, 1, 1];
|
||||
|
||||
function getPoint(p1, p2) {
|
||||
return (p2-p1)*f + p1;
|
||||
}
|
||||
|
||||
if (f >= 1) {
|
||||
setPos(pos);
|
||||
clearInterval(animationTimer);
|
||||
return;
|
||||
}
|
||||
|
||||
diff = pos - startPos;
|
||||
|
||||
y = getPoint(
|
||||
getPoint(getPoint(bezier[0], bezier[1]), getPoint(bezier[1], bezier[2])),
|
||||
getPoint(getPoint(bezier[1], bezier[2]), getPoint(bezier[2], bezier[3]))
|
||||
);
|
||||
|
||||
setPos(Math.floor(y*diff + startPos));
|
||||
}, 15);
|
||||
}
|
||||
|
||||
//sets position of the slider (in px)
|
||||
function setPos(pos) {
|
||||
slideBlock.style.webkitTransform = 'translate('+pos+'px,0) translateZ(0)';
|
||||
slideBlock.style.msTransform =
|
||||
slideBlock.style.MozTransform =
|
||||
slideBlock.style.OTransform =
|
||||
slideBlock.style.transform = 'translateX('+pos+'px)';
|
||||
|
||||
slider.left = pos;
|
||||
}
|
||||
|
||||
//`setPos` fallback for UAs with no CSS transforms support
|
||||
function setPosFallback(pos) {
|
||||
slideBlock.style.left = pos+'px';
|
||||
|
||||
slider.left = pos;
|
||||
}
|
||||
|
||||
function nextSlide() {
|
||||
var n = activeSlide + 1;
|
||||
|
||||
if (n > slidesNumber - 1) {
|
||||
n = 0;
|
||||
}
|
||||
|
||||
return changeActiveSlide(n);
|
||||
}
|
||||
|
||||
function prevSlide() {
|
||||
var n = activeSlide - 1;
|
||||
|
||||
if (n < 0) {
|
||||
n = slidesNumber - 1;
|
||||
}
|
||||
|
||||
return changeActiveSlide(n);
|
||||
}
|
||||
|
||||
function startSlideshow() {
|
||||
slideshowActive = true;
|
||||
stepSlideshow();
|
||||
}
|
||||
|
||||
//sets or resets timeout before switching to the next slide
|
||||
function stepSlideshow() {
|
||||
if (slideshowActive) {
|
||||
slideshowTimeoutId && clearTimeout(slideshowTimeoutId);
|
||||
|
||||
slideshowTimeoutId = setTimeout(function() {
|
||||
nextSlide();
|
||||
},
|
||||
o.slideshowInterval);
|
||||
}
|
||||
}
|
||||
|
||||
//pauses slideshow until `stepSlideshow` is invoked
|
||||
function pauseSlideshow() {
|
||||
slideshowTimeoutId && clearTimeout(slideshowTimeoutId);
|
||||
}
|
||||
|
||||
function stopSlideshow() {
|
||||
slideshowActive = false;
|
||||
slideshowTimeoutId && clearTimeout(slideshowTimeoutId);
|
||||
}
|
||||
|
||||
//this should be invoked when the width of the slider is changed
|
||||
function onWidthChange() {
|
||||
slider.width = _this.offsetWidth;
|
||||
|
||||
//have to do this in `px` because of webkit's rounding errors :-(
|
||||
slideBlock.style.width = slider.width*slidesNumber+'px';
|
||||
for (var i = 0; i < slidesNumber; i++) {
|
||||
slider.slides[i].style.width = slider.width+'px';
|
||||
}
|
||||
changePos(-activeSlide*slider.width);
|
||||
}
|
||||
|
||||
function addEvent(el, event, func, bool) {
|
||||
if (!event) return;
|
||||
|
||||
el.addEventListener? el.addEventListener(event, func, !!bool): el.attachEvent('on'+event, func);
|
||||
}
|
||||
|
||||
//init touch events
|
||||
function touchInit() {
|
||||
EventBurrito(slideBlock, {
|
||||
mouse: o.mouseDrag,
|
||||
start: function(event, start) {
|
||||
//firefox doesn't want to apply cursor from `:active` CSS rule, have to add a class :-/
|
||||
addClass(_this, classes.drag);
|
||||
},
|
||||
move: function(event, start, diff, speed) {
|
||||
pauseSlideshow(); //pause the slideshow when touch is in progress
|
||||
|
||||
//if it's first slide and moving left or last slide and moving right -- resist!
|
||||
diff.x =
|
||||
diff.x /
|
||||
(
|
||||
(!activeSlide && diff.x > 0
|
||||
|| activeSlide == slidesNumber - 1 && diff.x < 0)
|
||||
?
|
||||
(Math.abs(diff.x)/slider.width*2 + 1)
|
||||
:
|
||||
1
|
||||
);
|
||||
|
||||
//change position of the slider appropriately
|
||||
changePos(diff.x - slider.width*activeSlide);
|
||||
},
|
||||
end: function(event, start, diff, speed) {
|
||||
if (diff.x) {
|
||||
var ratio = Math.abs(diff.x)/slider.width,
|
||||
//How many slides to skip. Remainder > 0.25 counts for one slide.
|
||||
skip = Math.floor(ratio) + (ratio - Math.floor(ratio) > 0.25?1:0),
|
||||
//Super-duper formula to detect a flick.
|
||||
//First, it's got to be fast enough.
|
||||
//Second, if `skip==0`, 20px move is enough to switch to the next slide.
|
||||
//If `skip>0`, it's enough to slide to the middle of the slide minus `slider.width/9` to skip even further.
|
||||
flick = diff.time < flickThreshold+flickThreshold*skip/1.8 && Math.abs(diff.x) - skip*slider.width > (skip?-slider.width/9:20);
|
||||
|
||||
skip += (flick?1:0);
|
||||
|
||||
if (diff.x < 0) {
|
||||
changeActiveSlide(activeSlide+skip, o.touchSpeed);
|
||||
}
|
||||
else {
|
||||
changeActiveSlide(activeSlide-skip, o.touchSpeed);
|
||||
}
|
||||
|
||||
o.stopSlideshowAfterInteraction && stopSlideshow();
|
||||
}
|
||||
|
||||
//remove the drag class
|
||||
removeClass(_this, classes.drag);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function setup() {
|
||||
var slideSource = o.slidesContainer || _this,
|
||||
dotsTarget = o.dotsContainer || _this;
|
||||
|
||||
if (o.disableIfOneSlide && slideSource.children.length <= 1) return;
|
||||
|
||||
//If current UA doesn't support css transforms or transitions -- use fallback functions.
|
||||
//(Using separate functions instead of checks for better performance)
|
||||
if (!support.transforms || !!window.opera) setPos = setPosFallback;
|
||||
if (!support.transitions || !!window.opera) changePos = changePosFallback;
|
||||
|
||||
slideBlock = o.slidesContainer || document.createElement('div');
|
||||
addClass(slideBlock, classes.slides);
|
||||
|
||||
//get slides & generate dots
|
||||
for (var i = 0, l = slideSource.children.length; i < l; i++) {
|
||||
var slide = slideSource.children[i],
|
||||
dot = document.createElement('li');
|
||||
|
||||
slider.slides.push(slide);
|
||||
|
||||
//`tabindex` makes dots tabbable
|
||||
dot.setAttribute('tabindex', '0');
|
||||
dot.setAttribute('role', 'button');
|
||||
|
||||
dot.innerHTML = '<span></span>';
|
||||
|
||||
(function(x, dotClosure) {
|
||||
//bind events to dots
|
||||
addEvent(dotClosure, 'click', function(event) {
|
||||
changeActiveSlide(x);
|
||||
o.stopSlideshowAfterInteraction && stopSlideshow();
|
||||
});
|
||||
|
||||
//Bind the same function to Enter key except for the `blur` part -- I dont't want
|
||||
//the focus to be lost when the user is using his keyboard to navigate.
|
||||
addEvent(dotClosure, 'keyup', function(event) {
|
||||
if (event.keyCode == 13) {
|
||||
changeActiveSlide(x);
|
||||
o.stopSlideshowAfterInteraction && stopSlideshow();
|
||||
}
|
||||
});
|
||||
|
||||
//Don't want to disable outlines completely for accessibility reasons.
|
||||
//Instead, add class with `outline: 0` on mouseup and remove it on blur.
|
||||
addEvent(dotClosure, 'mouseup', function(event) {
|
||||
addClass(dotClosure, classes.mouseClicked);
|
||||
});
|
||||
|
||||
//capturing fixes IE bug
|
||||
addEvent(dotClosure, 'blur', function(){
|
||||
removeClass(dotClosure, classes.mouseClicked);
|
||||
}, true);
|
||||
|
||||
//This solves tabbing problems:
|
||||
//When an element inside a slide catches focus we switch to that slide
|
||||
//and reset `scrollLeft` of the slider block.
|
||||
//`SetTimeout` solves Chrome's bug.
|
||||
//Event capturing is used to catch events on the slide level.
|
||||
//Since older IEs don't have capturing, `onfocusin` is used as a fallback.
|
||||
addEvent(slide, 'focus', slide.onfocusin = function(e) {
|
||||
_this.scrollLeft = 0;
|
||||
setTimeout(function() {
|
||||
_this.scrollLeft = 0;
|
||||
}, 0);
|
||||
changeActiveSlide(x);
|
||||
}, true);
|
||||
})(i, dot)
|
||||
|
||||
slider.dots.push(dot);
|
||||
}
|
||||
|
||||
slidesNumber = slider.slides.length;
|
||||
|
||||
slideWidth = 100/slidesNumber;
|
||||
|
||||
addClass(_this, classes.active);
|
||||
removeClass(_this, classes.inactive);
|
||||
o.mouseDrag && addClass(_this, classes.mouse);
|
||||
|
||||
slider.width = _this.offsetWidth;
|
||||
|
||||
//had to do this in `px` because of webkit's rounding errors :-(
|
||||
slideBlock.style.width = slider.width*slidesNumber+'px';
|
||||
for (var i = 0; i < slidesNumber; i++) {
|
||||
slider.slides[i].style.width = slider.width+'px';
|
||||
slideBlock.appendChild(slider.slides[i]);
|
||||
}
|
||||
|
||||
if (!o.slidesContainer) _this.appendChild(slideBlock);
|
||||
|
||||
//append dots
|
||||
if (o.dots && slidesNumber > 1) {
|
||||
dotBlock = document.createElement('ul');
|
||||
addClass(dotBlock, classes.dots);
|
||||
|
||||
for (var i = 0, l = slider.dots.length; i < l; i++) {
|
||||
dotBlock.appendChild(slider.dots[i]);
|
||||
}
|
||||
|
||||
if (o.dotsPrepend) {
|
||||
dotsTarget.insertBefore(dotBlock,dotsTarget.firstChild);
|
||||
}
|
||||
else {
|
||||
dotsTarget.appendChild(dotBlock);
|
||||
}
|
||||
}
|
||||
|
||||
//watch for slider width changes
|
||||
addEvent(window, 'resize', onWidthChange);
|
||||
addEvent(window, 'orientationchange', onWidthChange);
|
||||
|
||||
//init first slide, timeout to expose the API first
|
||||
setTimeout(function() {
|
||||
changeActiveSlide(o.startSlide, 0);
|
||||
}, 0);
|
||||
|
||||
//init slideshow
|
||||
if (o.slideshow) startSlideshow();
|
||||
|
||||
touchInit();
|
||||
|
||||
//API callback, timeout to expose the API first
|
||||
setTimeout(function() {
|
||||
o.onSetup && o.onSetup(slidesNumber);
|
||||
}, 0);
|
||||
}
|
||||
|
||||
//Init
|
||||
setup();
|
||||
|
||||
//expose the API
|
||||
return {
|
||||
slideTo: function(slide) {
|
||||
return changeActiveSlide(parseInt(slide, 10));
|
||||
},
|
||||
|
||||
next: nextSlide,
|
||||
|
||||
prev: prevSlide,
|
||||
|
||||
//start slideshow
|
||||
start: startSlideshow,
|
||||
|
||||
//stop slideshow
|
||||
stop: stopSlideshow,
|
||||
|
||||
//pause slideshow until the next slide change
|
||||
pause: pauseSlideshow,
|
||||
|
||||
//get current slide number
|
||||
getCurrentPos: function() {
|
||||
return activeSlide;
|
||||
},
|
||||
|
||||
//get total number of slides
|
||||
getSlidesNumber: function() {
|
||||
return slidesNumber;
|
||||
},
|
||||
|
||||
//invoke this when the slider's width is changed
|
||||
recalcWidth: onWidthChange
|
||||
};
|
||||
};
|
||||
|
||||
//if jQuery is present -- create a plugin
|
||||
if (window.jQuery) {
|
||||
(function($) {
|
||||
$.fn.Peppermint = function(options) {
|
||||
this.each(function() {
|
||||
$(this).data('Peppermint', Peppermint(this, options));
|
||||
});
|
||||
|
||||
return this;
|
||||
};
|
||||
})(window.jQuery);
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
/*!
|
||||
* Peppermint touch slider
|
||||
* v. 1.3.7 | https://github.com/wilddeer/Peppermint
|
||||
* Copyright Oleg Korsunsky | http://wd.dizaina.net/
|
||||
*
|
||||
* Depends on Event Burrito | https://github.com/wilddeer/Event-Burrito
|
||||
* MIT License
|
||||
*/
|
||||
function Peppermint(a,b){function c(a,b){for(var c in b)b.hasOwnProperty(c)&&(a[c]=b[c])}function d(a){var b=["Webkit","Moz","O","ms"],c=document.createElement("div");if(void 0!==c.style[a])return!0;a=a.charAt(0).toUpperCase()+a.slice(1);for(var d in b)if(void 0!==c.style[b[d]+a])return!0;return!1}function e(a,b){new RegExp("(\\s|^)"+b+"(\\s|$)").test(a.className)||(a.className+=" "+b)}function f(a,b){a.className=a.className.replace(new RegExp("(\\s+|^)"+b+"(\\s+|$)","g")," ").replace(/^\s+|\s+$/g,"")}function g(a,b){0>a?a=0:a>v-1&&(a=v-1);for(var c=C.dots.length-1;c>=0;c--)f(C.dots[c],G.activeDot);return e(C.dots[a],G.activeDot),E=a,h(-a*C.width,void 0===b?F.speed:b),o(),F.onSlideChange&&F.onSlideChange(a),a}function h(a,b){var c=b?b+"ms":"";y.style.webkitTransitionDuration=y.style.MozTransitionDuration=y.style.msTransitionDuration=y.style.OTransitionDuration=y.style.transitionDuration=c,j(a)}function i(a,b){if(B&&clearInterval(B),!b)return void j(a);var c=+new Date,d=C.left;B=setInterval(function(){function e(a,b){return(b-a)*i+a}var f,g,h=+new Date-c,i=h/b,k=[0,.7,1,1];return i>=1?(j(a),void clearInterval(B)):(f=a-d,g=e(e(e(k[0],k[1]),e(k[1],k[2])),e(e(k[1],k[2]),e(k[2],k[3]))),void j(Math.floor(g*f+d)))},15)}function j(a){y.style.webkitTransform="translate("+a+"px,0) translateZ(0)",y.style.msTransform=y.style.MozTransform=y.style.OTransform=y.style.transform="translateX("+a+"px)",C.left=a}function k(a){y.style.left=a+"px",C.left=a}function l(){var a=E+1;return a>v-1&&(a=0),g(a)}function m(){var a=E-1;return 0>a&&(a=v-1),g(a)}function n(){A=!0,o()}function o(){A&&(z&&clearTimeout(z),z=setTimeout(function(){l()},F.slideshowInterval))}function p(){z&&clearTimeout(z)}function q(){A=!1,z&&clearTimeout(z)}function r(){C.width=a.offsetWidth,y.style.width=C.width*v+"px";for(var b=0;v>b;b++)C.slides[b].style.width=C.width+"px";h(-E*C.width)}function s(a,b,c,d){b&&(a.addEventListener?a.addEventListener(b,c,!!d):a.attachEvent("on"+b,c))}function t(){EventBurrito(y,{mouse:F.mouseDrag,start:function(){e(a,G.drag)},move:function(a,b,c){p(),c.x=c.x/(!E&&c.x>0||E==v-1&&c.x<0?Math.abs(c.x)/C.width*2+1:1),h(c.x-C.width*E)},end:function(b,c,d){if(d.x){var e=Math.abs(d.x)/C.width,h=Math.floor(e)+(e-Math.floor(e)>.25?1:0),i=d.time<D+D*h/1.8&&Math.abs(d.x)-h*C.width>(h?-C.width/9:20);h+=i?1:0,d.x<0?g(E+h,F.touchSpeed):g(E-h,F.touchSpeed),F.stopSlideshowAfterInteraction&&q()}f(a,G.drag)}})}function u(){var b=F.slidesContainer||a,c=F.dotsContainer||a;if(!(F.disableIfOneSlide&&b.children.length<=1)){(!H.transforms||window.opera)&&(j=k),(!H.transitions||window.opera)&&(h=i),y=F.slidesContainer||document.createElement("div"),e(y,G.slides);for(var d=0,l=b.children.length;l>d;d++){var m=b.children[d],o=document.createElement("li");C.slides.push(m),o.setAttribute("tabindex","0"),o.setAttribute("role","button"),o.innerHTML="<span></span>",function(b,c){s(c,"click",function(){g(b),F.stopSlideshowAfterInteraction&&q()}),s(c,"keyup",function(a){13==a.keyCode&&(g(b),F.stopSlideshowAfterInteraction&&q())}),s(c,"mouseup",function(){e(c,G.mouseClicked)}),s(c,"blur",function(){f(c,G.mouseClicked)},!0),s(m,"focus",m.onfocusin=function(){a.scrollLeft=0,setTimeout(function(){a.scrollLeft=0},0),g(b)},!0)}(d,o),C.dots.push(o)}v=C.slides.length,w=100/v,e(a,G.active),f(a,G.inactive),F.mouseDrag&&e(a,G.mouse),C.width=a.offsetWidth,y.style.width=C.width*v+"px";for(var d=0;v>d;d++)C.slides[d].style.width=C.width+"px",y.appendChild(C.slides[d]);if(F.slidesContainer||a.appendChild(y),F.dots&&v>1){x=document.createElement("ul"),e(x,G.dots);for(var d=0,l=C.dots.length;l>d;d++)x.appendChild(C.dots[d]);F.dotsPrepend?c.insertBefore(x,c.firstChild):c.appendChild(x)}s(window,"resize",r),s(window,"orientationchange",r),setTimeout(function(){g(F.startSlide,0)},0),F.slideshow&&n(),t(),setTimeout(function(){F.onSetup&&F.onSetup(v)},0)}}var v,w,x,y,z,A,B,C={slides:[],dots:[],left:0},D=200,E=0,F={speed:300,touchSpeed:300,slideshow:!1,slideshowInterval:4e3,stopSlideshowAfterInteraction:!1,startSlide:0,mouseDrag:!0,disableIfOneSlide:!0,cssPrefix:"peppermint-",dots:!1,dotsPrepend:!1,dotsContainer:void 0,slidesContainer:void 0,onSlideChange:void 0,onSetup:void 0};b&&c(F,b);var G={inactive:F.cssPrefix+"inactive",active:F.cssPrefix+"active",mouse:F.cssPrefix+"mouse",drag:F.cssPrefix+"drag",slides:F.cssPrefix+"slides",dots:F.cssPrefix+"dots",activeDot:F.cssPrefix+"active-dot",mouseClicked:F.cssPrefix+"mouse-clicked"},H={transforms:d("transform"),transitions:d("transition")};return u(),{slideTo:function(a){return g(parseInt(a,10))},next:l,prev:m,start:n,stop:q,pause:p,getCurrentPos:function(){return E},getSlidesNumber:function(){return v},recalcWidth:r}}window.jQuery&&!function($){$.fn.Peppermint=function(a){return this.each(function(){$(this).data("Peppermint",Peppermint(this,a))}),this}}(window.jQuery);
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"name": "Peppermint",
|
||||
"version": "1.3.7",
|
||||
"license": "MIT",
|
||||
"homepage": "https://github.com/wilddeer/Peppermint",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/wilddeer/Peppermint.git"
|
||||
},
|
||||
"author": {
|
||||
"name": "Oleg Korsunsky",
|
||||
"url": "http://wd.dizaina.net/"
|
||||
},
|
||||
"devDependencies": {
|
||||
"grunt": "~0.4.1",
|
||||
"grunt-contrib-uglify": "~0.2.5",
|
||||
"grunt-contrib-concat": "~0.3.0",
|
||||
"grunt-contrib-watch": "~0.5.3",
|
||||
"grunt-bump": "0.0.14",
|
||||
"grunt-shell": "~0.7.0"
|
||||
}
|
||||
}
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
.peppermint {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.peppermint figure {
|
||||
margin: 0 0 1.5em 0;
|
||||
}
|
||||
|
||||
.peppermint figure img {
|
||||
vertical-align: top;
|
||||
max-width: 100%;
|
||||
-webkit-box-shadow: 0 1px 5px rgba(0, 0, 0, 0.2);
|
||||
box-shadow: 0 1px 5px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.peppermint figure figcaption {
|
||||
font-style: italic;
|
||||
color: #787575;
|
||||
font-size: 0.8em;
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
|
||||
.peppermint.peppermint-active {
|
||||
margin-bottom: 1.5em;
|
||||
}
|
||||
|
||||
.peppermint-slides {
|
||||
padding-top: 0.5em;
|
||||
padding-bottom: 0.5em;
|
||||
}
|
||||
|
||||
/* dots */
|
||||
ul.peppermint-dots {
|
||||
margin: 0.6em 0;
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
.peppermint.peppermint-active ul.peppermint-dots {
|
||||
margin: 0 0 0.6em 0;
|
||||
}
|
||||
|
||||
.peppermint.peppermint-active .peppermint-slides + ul.peppermint-dots {
|
||||
margin: 0.6em 0 0 0;
|
||||
}
|
||||
|
||||
ul.peppermint-dots > li {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
padding: 0.5em 0.6em;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
/* ie7 fallback */
|
||||
*display: inline;
|
||||
*zoom: 1;
|
||||
}
|
||||
|
||||
ul.peppermint-dots > li.peppermint-mouse-clicked,
|
||||
ul.peppermint-dots > li:active {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
ul.peppermint-dots > li > span {
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
margin: -4px 0 0 -4px;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 50%;
|
||||
background: #9b9890;
|
||||
}
|
||||
|
||||
ul.peppermint-dots > li.peppermint-active-dot > span {
|
||||
margin: -6px 0 0 -6px;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border: 1px solid #9b9890;
|
||||
background: transparent;
|
||||
}
|
||||
@@ -0,0 +1,485 @@
|
||||
function Peppermint(_this, options) {
|
||||
var slider = {
|
||||
slides: [],
|
||||
dots: [],
|
||||
left: 0
|
||||
},
|
||||
slidesNumber,
|
||||
flickThreshold = 200, //Flick threshold (ms)
|
||||
activeSlide = 0,
|
||||
slideWidth,
|
||||
dotBlock,
|
||||
slideBlock,
|
||||
slideshowTimeoutId,
|
||||
slideshowActive,
|
||||
animationTimer;
|
||||
|
||||
//default options
|
||||
var o = {
|
||||
speed: 300, //transition between slides in ms
|
||||
touchSpeed: 300, //transition between slides in ms after touch
|
||||
slideshow: false, //launch slideshow at start
|
||||
slideshowInterval: 4000,
|
||||
stopSlideshowAfterInteraction: false, //stop slideshow after user interaction
|
||||
startSlide: 0, //first slide to show
|
||||
mouseDrag: true, //enable mouse drag
|
||||
disableIfOneSlide: true,
|
||||
cssPrefix: 'peppermint-',
|
||||
dots: false, //show dots
|
||||
dotsPrepend: false, //dots before slides
|
||||
dotsContainer: undefined,
|
||||
slidesContainer: undefined,
|
||||
onSlideChange: undefined, //slide change callback
|
||||
onSetup: undefined //setup callback
|
||||
};
|
||||
|
||||
//merge user options into defaults
|
||||
options && mergeObjects(o, options);
|
||||
|
||||
var classes = {
|
||||
inactive: o.cssPrefix + 'inactive',
|
||||
active: o.cssPrefix + 'active',
|
||||
mouse: o.cssPrefix + 'mouse',
|
||||
drag: o.cssPrefix + 'drag',
|
||||
slides: o.cssPrefix + 'slides',
|
||||
dots: o.cssPrefix + 'dots',
|
||||
activeDot: o.cssPrefix + 'active-dot',
|
||||
mouseClicked: o.cssPrefix + 'mouse-clicked'
|
||||
};
|
||||
|
||||
//feature detects
|
||||
var support = {
|
||||
transforms: testProp('transform'),
|
||||
transitions: testProp('transition')
|
||||
};
|
||||
|
||||
function mergeObjects(targetObj, sourceObject) {
|
||||
for (var key in sourceObject) {
|
||||
if (sourceObject.hasOwnProperty(key)) {
|
||||
targetObj[key] = sourceObject[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function testProp(prop) {
|
||||
var prefixes = ['Webkit', 'Moz', 'O', 'ms'],
|
||||
block = document.createElement('div');
|
||||
|
||||
if (block.style[prop] !== undefined) return true;
|
||||
|
||||
prop = prop.charAt(0).toUpperCase() + prop.slice(1);
|
||||
for (var i in prefixes) {
|
||||
if (block.style[prefixes[i]+prop] !== undefined) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function addClass(el, cl) {
|
||||
if (!new RegExp('(\\s|^)'+cl+'(\\s|$)').test(el.className)) {
|
||||
el.className += ' ' + cl;
|
||||
}
|
||||
}
|
||||
|
||||
function removeClass(el, cl) {
|
||||
el.className = el.className.replace(new RegExp('(\\s+|^)'+cl+'(\\s+|$)', 'g'), ' ').replace(/^\s+|\s+$/g, '');
|
||||
}
|
||||
|
||||
//n - slide number (starting from 0)
|
||||
//speed - transition in ms, can be omitted
|
||||
function changeActiveSlide(n, speed) {
|
||||
if (n<0) {
|
||||
n = 0;
|
||||
}
|
||||
else if (n>slidesNumber-1) {
|
||||
n = slidesNumber-1;
|
||||
}
|
||||
|
||||
//change active dot
|
||||
for (var i = slider.dots.length - 1; i >= 0; i--) {
|
||||
removeClass(slider.dots[i], classes.activeDot);
|
||||
}
|
||||
|
||||
addClass(slider.dots[n], classes.activeDot);
|
||||
|
||||
activeSlide = n;
|
||||
|
||||
changePos(-n*slider.width, (speed===undefined?o.speed:speed));
|
||||
|
||||
//reset slideshow timeout whenever active slide is changed for whatever reason
|
||||
stepSlideshow();
|
||||
|
||||
//API callback
|
||||
o.onSlideChange && o.onSlideChange(n);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
//changes position of the slider (in px) with given speed (in ms)
|
||||
function changePos(pos, speed) {
|
||||
var time = speed?speed+'ms':'';
|
||||
|
||||
slideBlock.style.webkitTransitionDuration =
|
||||
slideBlock.style.MozTransitionDuration =
|
||||
slideBlock.style.msTransitionDuration =
|
||||
slideBlock.style.OTransitionDuration =
|
||||
slideBlock.style.transitionDuration = time;
|
||||
|
||||
setPos(pos);
|
||||
}
|
||||
|
||||
//fallback to `setInterval` animations for UAs with no CSS transitions
|
||||
function changePosFallback(pos, speed) {
|
||||
animationTimer && clearInterval(animationTimer);
|
||||
|
||||
if (!speed) {
|
||||
setPos(pos);
|
||||
return;
|
||||
}
|
||||
|
||||
var startTime = +new Date,
|
||||
startPos = slider.left;
|
||||
|
||||
animationTimer = setInterval(function() {
|
||||
//rough bezier emulation
|
||||
var diff, y,
|
||||
elapsed = +new Date - startTime,
|
||||
f = elapsed / speed,
|
||||
bezier = [0, 0.7, 1, 1];
|
||||
|
||||
function getPoint(p1, p2) {
|
||||
return (p2-p1)*f + p1;
|
||||
}
|
||||
|
||||
if (f >= 1) {
|
||||
setPos(pos);
|
||||
clearInterval(animationTimer);
|
||||
return;
|
||||
}
|
||||
|
||||
diff = pos - startPos;
|
||||
|
||||
y = getPoint(
|
||||
getPoint(getPoint(bezier[0], bezier[1]), getPoint(bezier[1], bezier[2])),
|
||||
getPoint(getPoint(bezier[1], bezier[2]), getPoint(bezier[2], bezier[3]))
|
||||
);
|
||||
|
||||
setPos(Math.floor(y*diff + startPos));
|
||||
}, 15);
|
||||
}
|
||||
|
||||
//sets position of the slider (in px)
|
||||
function setPos(pos) {
|
||||
slideBlock.style.webkitTransform = 'translate('+pos+'px,0) translateZ(0)';
|
||||
slideBlock.style.msTransform =
|
||||
slideBlock.style.MozTransform =
|
||||
slideBlock.style.OTransform =
|
||||
slideBlock.style.transform = 'translateX('+pos+'px)';
|
||||
|
||||
slider.left = pos;
|
||||
}
|
||||
|
||||
//`setPos` fallback for UAs with no CSS transforms support
|
||||
function setPosFallback(pos) {
|
||||
slideBlock.style.left = pos+'px';
|
||||
|
||||
slider.left = pos;
|
||||
}
|
||||
|
||||
function nextSlide() {
|
||||
var n = activeSlide + 1;
|
||||
|
||||
if (n > slidesNumber - 1) {
|
||||
n = 0;
|
||||
}
|
||||
|
||||
return changeActiveSlide(n);
|
||||
}
|
||||
|
||||
function prevSlide() {
|
||||
var n = activeSlide - 1;
|
||||
|
||||
if (n < 0) {
|
||||
n = slidesNumber - 1;
|
||||
}
|
||||
|
||||
return changeActiveSlide(n);
|
||||
}
|
||||
|
||||
function startSlideshow() {
|
||||
slideshowActive = true;
|
||||
stepSlideshow();
|
||||
}
|
||||
|
||||
//sets or resets timeout before switching to the next slide
|
||||
function stepSlideshow() {
|
||||
if (slideshowActive) {
|
||||
slideshowTimeoutId && clearTimeout(slideshowTimeoutId);
|
||||
|
||||
slideshowTimeoutId = setTimeout(function() {
|
||||
nextSlide();
|
||||
},
|
||||
o.slideshowInterval);
|
||||
}
|
||||
}
|
||||
|
||||
//pauses slideshow until `stepSlideshow` is invoked
|
||||
function pauseSlideshow() {
|
||||
slideshowTimeoutId && clearTimeout(slideshowTimeoutId);
|
||||
}
|
||||
|
||||
function stopSlideshow() {
|
||||
slideshowActive = false;
|
||||
slideshowTimeoutId && clearTimeout(slideshowTimeoutId);
|
||||
}
|
||||
|
||||
//this should be invoked when the width of the slider is changed
|
||||
function onWidthChange() {
|
||||
slider.width = _this.offsetWidth;
|
||||
|
||||
//have to do this in `px` because of webkit's rounding errors :-(
|
||||
slideBlock.style.width = slider.width*slidesNumber+'px';
|
||||
for (var i = 0; i < slidesNumber; i++) {
|
||||
slider.slides[i].style.width = slider.width+'px';
|
||||
}
|
||||
changePos(-activeSlide*slider.width);
|
||||
}
|
||||
|
||||
function addEvent(el, event, func, bool) {
|
||||
if (!event) return;
|
||||
|
||||
el.addEventListener? el.addEventListener(event, func, !!bool): el.attachEvent('on'+event, func);
|
||||
}
|
||||
|
||||
//init touch events
|
||||
function touchInit() {
|
||||
EventBurrito(slideBlock, {
|
||||
mouse: o.mouseDrag,
|
||||
start: function(event, start) {
|
||||
//firefox doesn't want to apply cursor from `:active` CSS rule, have to add a class :-/
|
||||
addClass(_this, classes.drag);
|
||||
},
|
||||
move: function(event, start, diff, speed) {
|
||||
pauseSlideshow(); //pause the slideshow when touch is in progress
|
||||
|
||||
//if it's first slide and moving left or last slide and moving right -- resist!
|
||||
diff.x =
|
||||
diff.x /
|
||||
(
|
||||
(!activeSlide && diff.x > 0
|
||||
|| activeSlide == slidesNumber - 1 && diff.x < 0)
|
||||
?
|
||||
(Math.abs(diff.x)/slider.width*2 + 1)
|
||||
:
|
||||
1
|
||||
);
|
||||
|
||||
//change position of the slider appropriately
|
||||
changePos(diff.x - slider.width*activeSlide);
|
||||
},
|
||||
end: function(event, start, diff, speed) {
|
||||
if (diff.x) {
|
||||
var ratio = Math.abs(diff.x)/slider.width,
|
||||
//How many slides to skip. Remainder > 0.25 counts for one slide.
|
||||
skip = Math.floor(ratio) + (ratio - Math.floor(ratio) > 0.25?1:0),
|
||||
//Super-duper formula to detect a flick.
|
||||
//First, it's got to be fast enough.
|
||||
//Second, if `skip==0`, 20px move is enough to switch to the next slide.
|
||||
//If `skip>0`, it's enough to slide to the middle of the slide minus `slider.width/9` to skip even further.
|
||||
flick = diff.time < flickThreshold+flickThreshold*skip/1.8 && Math.abs(diff.x) - skip*slider.width > (skip?-slider.width/9:20);
|
||||
|
||||
skip += (flick?1:0);
|
||||
|
||||
if (diff.x < 0) {
|
||||
changeActiveSlide(activeSlide+skip, o.touchSpeed);
|
||||
}
|
||||
else {
|
||||
changeActiveSlide(activeSlide-skip, o.touchSpeed);
|
||||
}
|
||||
|
||||
o.stopSlideshowAfterInteraction && stopSlideshow();
|
||||
}
|
||||
|
||||
//remove the drag class
|
||||
removeClass(_this, classes.drag);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function setup() {
|
||||
var slideSource = o.slidesContainer || _this,
|
||||
dotsTarget = o.dotsContainer || _this;
|
||||
|
||||
if (o.disableIfOneSlide && slideSource.children.length <= 1) return;
|
||||
|
||||
//If current UA doesn't support css transforms or transitions -- use fallback functions.
|
||||
//(Using separate functions instead of checks for better performance)
|
||||
if (!support.transforms || !!window.opera) setPos = setPosFallback;
|
||||
if (!support.transitions || !!window.opera) changePos = changePosFallback;
|
||||
|
||||
slideBlock = o.slidesContainer || document.createElement('div');
|
||||
addClass(slideBlock, classes.slides);
|
||||
|
||||
//get slides & generate dots
|
||||
for (var i = 0, l = slideSource.children.length; i < l; i++) {
|
||||
var slide = slideSource.children[i],
|
||||
dot = document.createElement('li');
|
||||
|
||||
slider.slides.push(slide);
|
||||
|
||||
//`tabindex` makes dots tabbable
|
||||
dot.setAttribute('tabindex', '0');
|
||||
dot.setAttribute('role', 'button');
|
||||
|
||||
dot.innerHTML = '<span></span>';
|
||||
|
||||
(function(x, dotClosure) {
|
||||
//bind events to dots
|
||||
addEvent(dotClosure, 'click', function(event) {
|
||||
changeActiveSlide(x);
|
||||
o.stopSlideshowAfterInteraction && stopSlideshow();
|
||||
});
|
||||
|
||||
//Bind the same function to Enter key except for the `blur` part -- I dont't want
|
||||
//the focus to be lost when the user is using his keyboard to navigate.
|
||||
addEvent(dotClosure, 'keyup', function(event) {
|
||||
if (event.keyCode == 13) {
|
||||
changeActiveSlide(x);
|
||||
o.stopSlideshowAfterInteraction && stopSlideshow();
|
||||
}
|
||||
});
|
||||
|
||||
//Don't want to disable outlines completely for accessibility reasons.
|
||||
//Instead, add class with `outline: 0` on mouseup and remove it on blur.
|
||||
addEvent(dotClosure, 'mouseup', function(event) {
|
||||
addClass(dotClosure, classes.mouseClicked);
|
||||
});
|
||||
|
||||
//capturing fixes IE bug
|
||||
addEvent(dotClosure, 'blur', function(){
|
||||
removeClass(dotClosure, classes.mouseClicked);
|
||||
}, true);
|
||||
|
||||
//This solves tabbing problems:
|
||||
//When an element inside a slide catches focus we switch to that slide
|
||||
//and reset `scrollLeft` of the slider block.
|
||||
//`SetTimeout` solves Chrome's bug.
|
||||
//Event capturing is used to catch events on the slide level.
|
||||
//Since older IEs don't have capturing, `onfocusin` is used as a fallback.
|
||||
addEvent(slide, 'focus', slide.onfocusin = function(e) {
|
||||
_this.scrollLeft = 0;
|
||||
setTimeout(function() {
|
||||
_this.scrollLeft = 0;
|
||||
}, 0);
|
||||
changeActiveSlide(x);
|
||||
}, true);
|
||||
})(i, dot)
|
||||
|
||||
slider.dots.push(dot);
|
||||
}
|
||||
|
||||
slidesNumber = slider.slides.length;
|
||||
|
||||
slideWidth = 100/slidesNumber;
|
||||
|
||||
addClass(_this, classes.active);
|
||||
removeClass(_this, classes.inactive);
|
||||
o.mouseDrag && addClass(_this, classes.mouse);
|
||||
|
||||
slider.width = _this.offsetWidth;
|
||||
|
||||
//had to do this in `px` because of webkit's rounding errors :-(
|
||||
slideBlock.style.width = slider.width*slidesNumber+'px';
|
||||
for (var i = 0; i < slidesNumber; i++) {
|
||||
slider.slides[i].style.width = slider.width+'px';
|
||||
slideBlock.appendChild(slider.slides[i]);
|
||||
}
|
||||
|
||||
if (!o.slidesContainer) _this.appendChild(slideBlock);
|
||||
|
||||
//append dots
|
||||
if (o.dots && slidesNumber > 1) {
|
||||
dotBlock = document.createElement('ul');
|
||||
addClass(dotBlock, classes.dots);
|
||||
|
||||
for (var i = 0, l = slider.dots.length; i < l; i++) {
|
||||
dotBlock.appendChild(slider.dots[i]);
|
||||
}
|
||||
|
||||
if (o.dotsPrepend) {
|
||||
dotsTarget.insertBefore(dotBlock,dotsTarget.firstChild);
|
||||
}
|
||||
else {
|
||||
dotsTarget.appendChild(dotBlock);
|
||||
}
|
||||
}
|
||||
|
||||
//watch for slider width changes
|
||||
addEvent(window, 'resize', onWidthChange);
|
||||
addEvent(window, 'orientationchange', onWidthChange);
|
||||
|
||||
//init first slide, timeout to expose the API first
|
||||
setTimeout(function() {
|
||||
changeActiveSlide(o.startSlide, 0);
|
||||
}, 0);
|
||||
|
||||
//init slideshow
|
||||
if (o.slideshow) startSlideshow();
|
||||
|
||||
touchInit();
|
||||
|
||||
//API callback, timeout to expose the API first
|
||||
setTimeout(function() {
|
||||
o.onSetup && o.onSetup(slidesNumber);
|
||||
}, 0);
|
||||
}
|
||||
|
||||
//Init
|
||||
setup();
|
||||
|
||||
//expose the API
|
||||
return {
|
||||
slideTo: function(slide) {
|
||||
return changeActiveSlide(parseInt(slide, 10));
|
||||
},
|
||||
|
||||
next: nextSlide,
|
||||
|
||||
prev: prevSlide,
|
||||
|
||||
//start slideshow
|
||||
start: startSlideshow,
|
||||
|
||||
//stop slideshow
|
||||
stop: stopSlideshow,
|
||||
|
||||
//pause slideshow until the next slide change
|
||||
pause: pauseSlideshow,
|
||||
|
||||
//get current slide number
|
||||
getCurrentPos: function() {
|
||||
return activeSlide;
|
||||
},
|
||||
|
||||
//get total number of slides
|
||||
getSlidesNumber: function() {
|
||||
return slidesNumber;
|
||||
},
|
||||
|
||||
//invoke this when the slider's width is changed
|
||||
recalcWidth: onWidthChange
|
||||
};
|
||||
};
|
||||
|
||||
//if jQuery is present -- create a plugin
|
||||
if (window.jQuery) {
|
||||
(function($) {
|
||||
$.fn.Peppermint = function(options) {
|
||||
this.each(function() {
|
||||
$(this).data('Peppermint', Peppermint(this, options));
|
||||
});
|
||||
|
||||
return this;
|
||||
};
|
||||
})(window.jQuery);
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
.peppermint.peppermint-active {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
.peppermint.peppermint-active .peppermint-slides {
|
||||
position: relative;
|
||||
overflow: hidden; /* clearfix */
|
||||
-ms-touch-action: pan-y;
|
||||
touch-action: pan-y;
|
||||
}
|
||||
|
||||
.peppermint.peppermint-active .peppermint-slides > * {
|
||||
float: left;
|
||||
margin: 0;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
tap-highlight-color: transparent;
|
||||
}
|
||||
|
||||
.peppermint.peppermint-active .peppermint-slides a:active,
|
||||
.peppermint.peppermint-active .peppermint-slides a:active img {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.peppermint.peppermint-active,
|
||||
.peppermint.peppermint-active .peppermint-dots,
|
||||
.peppermint.peppermint-active .peppermint-slides,
|
||||
.peppermint.peppermint-active .peppermint-slides > * {
|
||||
-webkit-transform: translate3d(0,0,0);
|
||||
-ms-transform: translate3d(0,0,0);
|
||||
-moz-transform: translate3d(0,0,0);
|
||||
transform: translate3d(0,0,0);
|
||||
-webkit-backface-visibility: hidden;
|
||||
-moz-backface-visibility: hidden;
|
||||
-ms-backface-visibility: hidden;
|
||||
backface-visibility: hidden;
|
||||
}
|
||||
|
||||
.peppermint.peppermint-mouse .peppermint-slides {
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
cursor: move;
|
||||
cursor: -webkit-grab;
|
||||
cursor: -moz-grab;
|
||||
cursor: grab;
|
||||
}
|
||||
|
||||
.peppermint.peppermint-mouse.peppermint-drag .peppermint-slides * {
|
||||
cursor: move;
|
||||
cursor: -webkit-grabbing;
|
||||
cursor: -moz-grabbing;
|
||||
cursor: grabbing;
|
||||
}
|
||||
Reference in New Issue
Block a user