├── index.html ├── demo ├── img │ ├── image-1.jpg │ ├── image-2.jpg │ └── image-4.jpg ├── demo.css └── index.html ├── images ├── sy-loader.gif └── arrows.svg ├── .travis.yml ├── .jshintrc ├── .gitignore ├── config.rb ├── package.json ├── bower.json ├── LICENSE ├── README.md ├── Gruntfile.js ├── src ├── slippry.scss └── slippry.js └── dist ├── slippry.css └── slippry.min.js /index.html: -------------------------------------------------------------------------------- 1 | Slippry Slider 2 | -------------------------------------------------------------------------------- /demo/img/image-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/booncon/slippry/HEAD/demo/img/image-1.jpg -------------------------------------------------------------------------------- /demo/img/image-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/booncon/slippry/HEAD/demo/img/image-2.jpg -------------------------------------------------------------------------------- /demo/img/image-4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/booncon/slippry/HEAD/demo/img/image-4.jpg -------------------------------------------------------------------------------- /images/sy-loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/booncon/slippry/HEAD/images/sy-loader.gif -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - '0.10' 4 | before_script: 5 | - npm install -g bower 6 | - bower install 7 | notifications: 8 | email: false 9 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "bitwise": true, 3 | "browser": true, 4 | "curly": true, 5 | "eqeqeq": true, 6 | "eqnull": true, 7 | "esnext": true, 8 | "immed": true, 9 | "jquery": true, 10 | "latedef": true, 11 | "newcap": true, 12 | "noarg": true, 13 | "node": true, 14 | "strict": false, 15 | "trailing": true 16 | } 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by http://gitignore.io 2 | 3 | ### OSX ### 4 | .DS_Store 5 | .AppleDouble 6 | .LSOverride 7 | Icon 8 | 9 | # Thumbnails 10 | ._* 11 | 12 | # Files that might appear on external disk 13 | .Spotlight-V100 14 | .Trashes 15 | 16 | ### SASS ### 17 | ### SASS Ignores - "Sassy CSS" http://sass-lang.com/ 18 | *.sass-cache 19 | 20 | node_modules 21 | source 22 | build 23 | bower_components -------------------------------------------------------------------------------- /demo/demo.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | font-family: 'source-sans-pro', Helvetica, Arial, sans-serif; 5 | font-size: 14px; 6 | } 7 | .demo_wrapper { 8 | width: 50%; 9 | margin: 0 auto; 10 | } 11 | @media only screen and (max-device-width: 800px), screen and (max-width: 800px) { 12 | .demo_wrapper { 13 | width: 80%; 14 | } 15 | } 16 | .demo_block { 17 | width: 100%; 18 | } 19 | -------------------------------------------------------------------------------- /config.rb: -------------------------------------------------------------------------------- 1 | # Require any additional compass plugins here. 2 | 3 | # Set this to the root of your project when deployed: 4 | http_path = "/" 5 | css_dir = "dist" 6 | sass_dir = "src" 7 | images_dir = "src/img" 8 | javascripts_dir = "src" 9 | 10 | # You can select your preferred output style here (can be overridden via the command line): 11 | # output_style = :expanded or :nested or :compact or :compressed 12 | 13 | # To enable relative paths to assets via compass helper functions. Uncomment: 14 | # relative_assets = true 15 | 16 | # To disable debugging comments that display the original location of your selectors. Uncomment: 17 | # line_comments = false 18 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "slippry", 3 | "version": "v1.4.0", 4 | "author": "Lukas Jakob Hafner ", 5 | "homepage": "http://slippry.com", 6 | "repository": { 7 | "type": "git", 8 | "url": "git://github.com/booncon/slippry.git" 9 | }, 10 | "bugs": { 11 | "url": "https://github.com/booncon/slippry/issues" 12 | }, 13 | "license": "MIT", 14 | "engines": { 15 | "node": ">= 0.10.0" 16 | }, 17 | "devDependencies": { 18 | "grunt": "~0.4.2", 19 | "grunt-autoprefixer": "^3.0.4", 20 | "grunt-contrib-clean": "~0.5.0", 21 | "grunt-contrib-jshint": "~0.6.4", 22 | "grunt-contrib-less": "~0.8.1", 23 | "grunt-contrib-sass": "~0.7.3", 24 | "grunt-contrib-uglify": "~0.4.0", 25 | "grunt-contrib-watch": "~0.5.3" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "slippry", 3 | "version": "v1.4.0", 4 | "homepage": "http://slippry.com", 5 | "authors": [ 6 | "Lukas Jakob Hafner - @saftsaak", 7 | "Thomas Hurd - @SeenNotHurd" 8 | ], 9 | "description": "Responsive content slider for jQuery", 10 | "main": [ 11 | "dist/slippry.min.js", 12 | "dist/slippry.css", 13 | "images/arrows.svg", 14 | "images/sy-loader.gif" 15 | ], 16 | "keywords": [ 17 | "content", 18 | "slider", 19 | "responsive", 20 | "picture", 21 | "carousel", 22 | "html5" 23 | ], 24 | "license": "MIT", 25 | "ignore": [ 26 | "demo", 27 | "node_modules", 28 | ".gitignore", 29 | ".jshintrc", 30 | "config.rb", 31 | "Gruntfile.js", 32 | "index.html", 33 | "package.json" 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /images/arrows.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 8 | 10 | 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 booncon PIXELS oy, http://pixels.fi 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Slippry ![Slippry build status](https://travis-ci.org/booncon/slippry.svg?branch=dev) [![CDNJS version](https://img.shields.io/cdnjs/v/slippry.svg)](https://cdnjs.com/libraries/slippry) 2 | 3 | Responsive slider plugin for jQuery. 4 | Intrinsic trick to enable responsive resizing without js! 5 | 6 | ## Responsive 7 | ### Buzzword? Yes. Important? Very. 8 | We got frustrated at the lack of free, responsive sliders, so we wrote our own. Sure, there are some out there, but we found out the hard way, they have two settings or they use soon-to-be-deprecated functions. 9 | 10 | Oops. 11 | 12 | 13 | ## Modern 14 | ### HTML5 + CSS3 + jQuery 15 | Slippry is written with the future in mind, not the past. We wrote it to work on the latest jQuery functions, CSS3 tricks and HTML5 elements. We support death with dignity for technology. 16 | 17 | But don't worry, it still downgrades gracefully. 18 | 19 | 20 | ## Simple 21 | ### Or complex. You choose. 22 | Isn't it great when you just need a simple slider? How about when the design needs captions in random places, Reeeeaaallllyyyy slooowwwww speeds or an annoying pop-up each time you change slide? Yeah, not so great. 23 | 24 | Slippry offers a heap of settings you actually need, and with the included CSS and Sass you can make Slippry look just how you need it. 25 | 26 | Check it out at http://slippry.com 27 | -------------------------------------------------------------------------------- /demo/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | slippry demo 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 25 |
26 | 27 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | module.exports = function(grunt) { 3 | grunt.initConfig({ 4 | pkg: grunt.file.readJSON('package.json'), 5 | jshint: { 6 | options: { 7 | jshintrc: '.jshintrc' 8 | }, 9 | all: [ 10 | 'Gruntfile.js', 11 | 'src/slippry.js' 12 | ] 13 | }, 14 | autoprefixer: { 15 | options: { 16 | browsers: ['last 2 versions', 'ie 8', 'ie 9', 'android 2.3', 'android 4', 'opera 12'] 17 | }, 18 | all: { 19 | src: 'dist/slippry.css' 20 | } 21 | }, 22 | sass: { 23 | dist: { 24 | options: { 25 | style: 'nested', 26 | compass: true, 27 | 'sourcemap=none': true 28 | }, 29 | files: { 30 | 'dist/slippry.css': [ 31 | 'src/slippry.scss' 32 | ] 33 | } 34 | } 35 | }, 36 | uglify: { 37 | dist: { 38 | files: { 39 | 'dist/slippry.min.js': [ 40 | 'src/slippry.js' 41 | ] 42 | }, 43 | options: { 44 | sourceMap: false, 45 | preserveComments: 'some' 46 | } 47 | } 48 | }, 49 | watch: { 50 | sass: { 51 | options: { 52 | style: 'nested', 53 | compass: true, 54 | 'sourcemap=none': true 55 | }, 56 | files: [ 57 | 'src/*.scss' 58 | ], 59 | tasks: ['sass', 'autoprefixer'], 60 | }, 61 | js: { 62 | files: [ 63 | '<%= jshint.all %>' 64 | ], 65 | tasks: ['jshint', 'uglify'] 66 | }, 67 | livereload: { 68 | options: { 69 | livereload: true 70 | }, 71 | files: [ 72 | 'dist/slippry.css', 73 | 'dist/slippry.min.js', 74 | 'demo/index.html' 75 | ] 76 | } 77 | }, 78 | clean: { 79 | dist: [ 80 | 'assets/css/main.min.css', 81 | 'assets/js/scripts.min.js' 82 | ] 83 | } 84 | }); 85 | 86 | // Load tasks 87 | grunt.loadNpmTasks('grunt-contrib-clean'); 88 | grunt.loadNpmTasks('grunt-contrib-jshint'); 89 | grunt.loadNpmTasks('grunt-contrib-uglify'); 90 | grunt.loadNpmTasks('grunt-contrib-watch'); 91 | grunt.loadNpmTasks('grunt-contrib-sass'); 92 | grunt.loadNpmTasks('grunt-autoprefixer'); 93 | 94 | // Register tasks 95 | grunt.registerTask('default', [ 96 | 'clean', 97 | 'sass', 98 | 'autoprefixer', 99 | 'uglify' 100 | ]); 101 | grunt.registerTask('dev', [ 102 | 'watch' 103 | ]); 104 | }; 105 | -------------------------------------------------------------------------------- /src/slippry.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * slippry v1.4.0 - Responsive content slider for jQuery 4 | * http://slippry.com 5 | * 6 | * Authors: Lukas Jakob Hafner - @saftsaak 7 | * Thomas Hurd - @SeenNotHurd 8 | * 9 | * Copyright 2016, booncon oy - http://booncon.com 10 | * 11 | * 12 | * Released under the MIT license - http://opensource.org/licenses/MIT 13 | */ 14 | 15 | $color_high: #e24b70 !default; // highlight colour 16 | $color_gray: #ccc !default; // neutral colour 17 | $controls_size: 2.8em !default; // size of the next/ prev buttons 18 | $pager_size: 1.2em !default; // size of the pager bubbles 19 | $trans_ease: ease !default; // easing for the transitions 20 | $mobile_break: 600px !default; // breakpoint to use some special mobile styling 21 | $spinner_url: '/images/sy-loader.gif' !default; 22 | $arrows_url: '/images/arrows.svg' !default; 23 | 24 | @mixin animation ($animation) { 25 | animation-name: $animation; 26 | animation-fill-mode: forwards; 27 | } 28 | 29 | /* kenBurns animations, very basic */ 30 | @keyframes left-right { 31 | 0% { 32 | transform: translateY(-20%) translateX(-10%); 33 | } 34 | 100% { 35 | transform: translateY(0%) translateX(10%); 36 | } 37 | } 38 | @keyframes right-left { 39 | 0% { 40 | transform: translateY(0%) translateX(10%); 41 | } 42 | 100% { 43 | transform: translateY(-20%) translateX(-10%); 44 | } 45 | } 46 | 47 | /* added to the original element calling slippry */ 48 | .sy-box { 49 | &.sy-loading { 50 | .sy-slides-wrap, .sy-pager { 51 | visibility: hidden; 52 | } 53 | background: url($spinner_url) 50% 50% no-repeat; 54 | background-size: 32px; 55 | min-height: 40px; 56 | } 57 | } 58 | /* element that wraps the slides */ 59 | .sy-slides-wrap { 60 | position: relative; 61 | height: 100%; 62 | width: 100%; 63 | &:hover { 64 | .sy-controls { 65 | display: block; 66 | } 67 | } 68 | } 69 | /* element that crops the visible area to the slides */ 70 | .sy-slides-crop { 71 | height: 100%; 72 | width: 100%; 73 | position: absolute; 74 | overflow: hidden; 75 | } 76 | /* list containing the slides */ 77 | .sy-list { 78 | &.horizontal { 79 | transition: left $trans_ease; 80 | } 81 | &.vertical { 82 | transition: top $trans_ease; 83 | } 84 | width: 100%; 85 | height: 100%; 86 | list-style: none; 87 | margin: 0; 88 | padding: 0; 89 | position: absolute; 90 | } 91 | /* single slide */ 92 | .sy-slide { 93 | position: absolute; 94 | width: 100%; 95 | z-index: 2; 96 | &.kenburns { 97 | width: 140%; 98 | left: -20%; 99 | &.useCSS { 100 | &.sy-ken { 101 | &:nth-child(1n) { 102 | @include animation(left-right); 103 | } 104 | &:nth-child(2n) { 105 | @include animation(right-left); 106 | } 107 | } 108 | transition-property: opacity; 109 | } 110 | } 111 | &.sy-active { 112 | z-index: 3; 113 | } 114 | > img { // with one image as content -> full size 115 | margin: 0; 116 | padding: 0; 117 | display: block; 118 | width: 100%; 119 | border: 0; 120 | } 121 | > a { // styling for link on whole slide 122 | margin: 0; 123 | padding: 0; 124 | display: block; 125 | width: 100%; 126 | > img { // with one image as content -> full size 127 | margin: 0; 128 | padding: 0; 129 | display: block; 130 | width: 100%; 131 | border: 0; 132 | } 133 | } 134 | } 135 | /* next/ prev buttons, with arrows and clickable area a lot larger than the visible buttons */ 136 | .sy-controls { 137 | display: none; 138 | list-style: none; 139 | height: 100%; 140 | width: 100%; 141 | position: absolute; 142 | padding: 0; 143 | margin: 0; 144 | li { 145 | position: absolute; 146 | width: 10%; 147 | min-width: $controls_size * 1.5; 148 | height: 100%; 149 | z-index: 33; 150 | &.sy-prev { 151 | left: 0; 152 | top: 0; 153 | a { 154 | &:after { 155 | background-position: -5% 0; 156 | } 157 | } 158 | } 159 | &.sy-next { 160 | right: 0; 161 | top: 0; 162 | a { 163 | &:after { 164 | background-position: 105% 0; 165 | } 166 | } 167 | } 168 | a { 169 | position: relative; 170 | width: 100%; 171 | height: 100%; 172 | display: block; 173 | text-indent: -9999px; 174 | &:link, &:visited { 175 | opacity: 0.4; 176 | } 177 | &:hover, &:focus { 178 | opacity: 0.8; 179 | outline: none; 180 | } 181 | &:after { 182 | content: ""; 183 | background-image: url($arrows_url); 184 | background-repeat: no-repeat; 185 | background-size: cover; 186 | text-align: center; 187 | text-indent: 0; 188 | line-height: $controls_size; 189 | color: #111; 190 | font-weight: 800; 191 | position: absolute; 192 | background-color: #fff; 193 | width: $controls_size; 194 | height: $controls_size; 195 | left: 50%; 196 | top: 50%; 197 | margin-top: -$controls_size / 2; 198 | margin-left: -$controls_size / 2; 199 | border-radius: 50%; 200 | } 201 | } 202 | } 203 | @media only screen and (max-device-width : $mobile_break) { 204 | display: block; 205 | $controls_size: $controls_size / 2; 206 | li { 207 | min-width: $controls_size * 1.5; 208 | a { 209 | &:after { 210 | width: $controls_size; 211 | height: $controls_size; 212 | margin-top: -$controls_size / 2; 213 | margin-left: -$controls_size / 2; 214 | } 215 | } 216 | } 217 | } 218 | } 219 | /* captions, styled fo the overlay variant */ 220 | .sy-caption-wrap { 221 | position: absolute; 222 | bottom: 2em; 223 | z-index: 12; 224 | left: 50%; 225 | .sy-caption { 226 | position: relative; 227 | left: -50%; 228 | background-color: rgba(0,0,0,0.54); 229 | color: #fff; 230 | padding: 0.4em 1em; 231 | border-radius: 1.2em; 232 | a { 233 | &:link, &:visited { 234 | color: $color_high; 235 | font-weight: 600; 236 | text-decoration: none; 237 | } 238 | &:hover, &:focus { 239 | text-decoration: underline; 240 | } 241 | } 242 | } 243 | @media only screen and (max-device-width : $mobile_break), screen and (max-width : $mobile_break) { 244 | left: 0; 245 | bottom: 0.4em; 246 | .sy-caption { 247 | left: 0; 248 | padding: 0.2em 0.4em; 249 | font-size: 0.92em; 250 | border-radius: 0; 251 | } 252 | } 253 | } 254 | /* pager bubbles */ 255 | .sy-pager { 256 | clear: both; 257 | display: block; 258 | width: 100%; 259 | margin: 1em 0 0; 260 | padding: 0; 261 | list-style: none; 262 | text-align: center; 263 | li { 264 | display: inline-block; 265 | width: $pager_size; 266 | height: $pager_size; 267 | margin: 0 1em 0 0; 268 | border-radius: 50%; 269 | &.sy-active { 270 | a { 271 | background-color: $color_high; 272 | } 273 | } 274 | a { 275 | width: 100%; 276 | height: 100%; 277 | display: block; 278 | background-color: $color_gray; 279 | text-indent: -9999px; 280 | &:link, &:visited { 281 | opacity: 1.0; 282 | } 283 | &:hover, &:focus { 284 | opacity: 0.6; 285 | } 286 | background-size: 2em; 287 | border-radius: 50%; 288 | } 289 | } 290 | } 291 | /* element to "keep/ fill" the space of the content, gets intrinsic height via js */ 292 | .sy-filler { 293 | width: 100%; 294 | &.ready { 295 | transition: padding 600ms ease; 296 | } 297 | } 298 | -------------------------------------------------------------------------------- /dist/slippry.css: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * slippry v1.4.0 - Responsive content slider for jQuery 4 | * http://slippry.com 5 | * 6 | * Authors: Lukas Jakob Hafner - @saftsaak 7 | * Thomas Hurd - @SeenNotHurd 8 | * 9 | * Copyright 2016, booncon oy - http://booncon.com 10 | * 11 | * 12 | * Released under the MIT license - http://opensource.org/licenses/MIT 13 | */ 14 | /* kenBurns animations, very basic */ 15 | @-webkit-keyframes left-right { 16 | 0% { 17 | -webkit-transform: translateY(-20%) translateX(-10%); 18 | transform: translateY(-20%) translateX(-10%); } 19 | 100% { 20 | -webkit-transform: translateY(0%) translateX(10%); 21 | transform: translateY(0%) translateX(10%); } } 22 | @-o-keyframes left-right { 23 | 0% { 24 | -o-transform: translateY(-20%) translateX(-10%); 25 | transform: translateY(-20%) translateX(-10%); } 26 | 100% { 27 | -o-transform: translateY(0%) translateX(10%); 28 | transform: translateY(0%) translateX(10%); } } 29 | @keyframes left-right { 30 | 0% { 31 | -webkit-transform: translateY(-20%) translateX(-10%); 32 | -o-transform: translateY(-20%) translateX(-10%); 33 | transform: translateY(-20%) translateX(-10%); } 34 | 100% { 35 | -webkit-transform: translateY(0%) translateX(10%); 36 | -o-transform: translateY(0%) translateX(10%); 37 | transform: translateY(0%) translateX(10%); } } 38 | @-webkit-keyframes right-left { 39 | 0% { 40 | -webkit-transform: translateY(0%) translateX(10%); 41 | transform: translateY(0%) translateX(10%); } 42 | 100% { 43 | -webkit-transform: translateY(-20%) translateX(-10%); 44 | transform: translateY(-20%) translateX(-10%); } } 45 | @-o-keyframes right-left { 46 | 0% { 47 | -o-transform: translateY(0%) translateX(10%); 48 | transform: translateY(0%) translateX(10%); } 49 | 100% { 50 | -o-transform: translateY(-20%) translateX(-10%); 51 | transform: translateY(-20%) translateX(-10%); } } 52 | @keyframes right-left { 53 | 0% { 54 | -webkit-transform: translateY(0%) translateX(10%); 55 | -o-transform: translateY(0%) translateX(10%); 56 | transform: translateY(0%) translateX(10%); } 57 | 100% { 58 | -webkit-transform: translateY(-20%) translateX(-10%); 59 | -o-transform: translateY(-20%) translateX(-10%); 60 | transform: translateY(-20%) translateX(-10%); } } 61 | /* added to the original element calling slippry */ 62 | .sy-box.sy-loading { 63 | background: url("/images/sy-loader.gif") 50% 50% no-repeat; 64 | -webkit-background-size: 32px 32px; 65 | background-size: 32px; 66 | min-height: 40px; } 67 | .sy-box.sy-loading .sy-slides-wrap, .sy-box.sy-loading .sy-pager { 68 | visibility: hidden; } 69 | 70 | /* element that wraps the slides */ 71 | .sy-slides-wrap { 72 | position: relative; 73 | height: 100%; 74 | width: 100%; } 75 | .sy-slides-wrap:hover .sy-controls { 76 | display: block; } 77 | 78 | /* element that crops the visible area to the slides */ 79 | .sy-slides-crop { 80 | height: 100%; 81 | width: 100%; 82 | position: absolute; 83 | overflow: hidden; } 84 | 85 | /* list containing the slides */ 86 | .sy-list { 87 | width: 100%; 88 | height: 100%; 89 | list-style: none; 90 | margin: 0; 91 | padding: 0; 92 | position: absolute; } 93 | .sy-list.horizontal { 94 | -webkit-transition: left ease; 95 | -o-transition: left ease; 96 | transition: left ease; } 97 | .sy-list.vertical { 98 | -webkit-transition: top ease; 99 | -o-transition: top ease; 100 | transition: top ease; } 101 | 102 | /* single slide */ 103 | .sy-slide { 104 | position: absolute; 105 | width: 100%; 106 | z-index: 2; } 107 | .sy-slide.kenburns { 108 | width: 140%; 109 | left: -20%; } 110 | .sy-slide.kenburns.useCSS { 111 | -webkit-transition-property: opacity; 112 | -o-transition-property: opacity; 113 | transition-property: opacity; } 114 | .sy-slide.kenburns.useCSS.sy-ken:nth-child(1n) { 115 | -webkit-animation-name: left-right; 116 | -o-animation-name: left-right; 117 | animation-name: left-right; 118 | -webkit-animation-fill-mode: forwards; 119 | -o-animation-fill-mode: forwards; 120 | animation-fill-mode: forwards; } 121 | .sy-slide.kenburns.useCSS.sy-ken:nth-child(2n) { 122 | -webkit-animation-name: right-left; 123 | -o-animation-name: right-left; 124 | animation-name: right-left; 125 | -webkit-animation-fill-mode: forwards; 126 | -o-animation-fill-mode: forwards; 127 | animation-fill-mode: forwards; } 128 | .sy-slide.sy-active { 129 | z-index: 3; } 130 | .sy-slide > img { 131 | margin: 0; 132 | padding: 0; 133 | display: block; 134 | width: 100%; 135 | border: 0; } 136 | .sy-slide > a { 137 | margin: 0; 138 | padding: 0; 139 | display: block; 140 | width: 100%; } 141 | .sy-slide > a > img { 142 | margin: 0; 143 | padding: 0; 144 | display: block; 145 | width: 100%; 146 | border: 0; } 147 | 148 | /* next/ prev buttons, with arrows and clickable area a lot larger than the visible buttons */ 149 | .sy-controls { 150 | display: none; 151 | list-style: none; 152 | height: 100%; 153 | width: 100%; 154 | position: absolute; 155 | padding: 0; 156 | margin: 0; } 157 | .sy-controls li { 158 | position: absolute; 159 | width: 10%; 160 | min-width: 4.2em; 161 | height: 100%; 162 | z-index: 33; } 163 | .sy-controls li.sy-prev { 164 | left: 0; 165 | top: 0; } 166 | .sy-controls li.sy-prev a:after { 167 | background-position: -5% 0; } 168 | .sy-controls li.sy-next { 169 | right: 0; 170 | top: 0; } 171 | .sy-controls li.sy-next a:after { 172 | background-position: 105% 0; } 173 | .sy-controls li a { 174 | position: relative; 175 | width: 100%; 176 | height: 100%; 177 | display: block; 178 | text-indent: -9999px; } 179 | .sy-controls li a:link, .sy-controls li a:visited { 180 | opacity: 0.4; } 181 | .sy-controls li a:hover, .sy-controls li a:focus { 182 | opacity: 0.8; 183 | outline: none; } 184 | .sy-controls li a:after { 185 | content: ""; 186 | background-image: url("/images/arrows.svg"); 187 | background-repeat: no-repeat; 188 | -webkit-background-size: cover; 189 | background-size: cover; 190 | text-align: center; 191 | text-indent: 0; 192 | line-height: 2.8em; 193 | color: #111; 194 | font-weight: 800; 195 | position: absolute; 196 | background-color: #fff; 197 | width: 2.8em; 198 | height: 2.8em; 199 | left: 50%; 200 | top: 50%; 201 | margin-top: -1.4em; 202 | margin-left: -1.4em; 203 | border-radius: 50%; } 204 | @media only screen and (max-device-width: 600px) { 205 | .sy-controls { 206 | display: block; } 207 | .sy-controls li { 208 | min-width: 2.1em; } 209 | .sy-controls li a:after { 210 | width: 1.4em; 211 | height: 1.4em; 212 | margin-top: -0.7em; 213 | margin-left: -0.7em; } } 214 | 215 | /* captions, styled fo the overlay variant */ 216 | .sy-caption-wrap { 217 | position: absolute; 218 | bottom: 2em; 219 | z-index: 12; 220 | left: 50%; } 221 | .sy-caption-wrap .sy-caption { 222 | position: relative; 223 | left: -50%; 224 | background-color: rgba(0, 0, 0, 0.54); 225 | color: #fff; 226 | padding: 0.4em 1em; 227 | border-radius: 1.2em; } 228 | .sy-caption-wrap .sy-caption a:link, .sy-caption-wrap .sy-caption a:visited { 229 | color: #e24b70; 230 | font-weight: 600; 231 | text-decoration: none; } 232 | .sy-caption-wrap .sy-caption a:hover, .sy-caption-wrap .sy-caption a:focus { 233 | text-decoration: underline; } 234 | @media only screen and (max-device-width: 600px), screen and (max-width: 600px) { 235 | .sy-caption-wrap { 236 | left: 0; 237 | bottom: 0.4em; } 238 | .sy-caption-wrap .sy-caption { 239 | left: 0; 240 | padding: 0.2em 0.4em; 241 | font-size: 0.92em; 242 | border-radius: 0; } } 243 | 244 | /* pager bubbles */ 245 | .sy-pager { 246 | clear: both; 247 | display: block; 248 | width: 100%; 249 | margin: 1em 0 0; 250 | padding: 0; 251 | list-style: none; 252 | text-align: center; } 253 | .sy-pager li { 254 | display: inline-block; 255 | width: 1.2em; 256 | height: 1.2em; 257 | margin: 0 1em 0 0; 258 | border-radius: 50%; } 259 | .sy-pager li.sy-active a { 260 | background-color: #e24b70; } 261 | .sy-pager li a { 262 | width: 100%; 263 | height: 100%; 264 | display: block; 265 | background-color: #ccc; 266 | text-indent: -9999px; 267 | -webkit-background-size: 2em 2em; 268 | background-size: 2em; 269 | border-radius: 50%; } 270 | .sy-pager li a:link, .sy-pager li a:visited { 271 | opacity: 1.0; } 272 | .sy-pager li a:hover, .sy-pager li a:focus { 273 | opacity: 0.6; } 274 | 275 | /* element to "keep/ fill" the space of the content, gets intrinsic height via js */ 276 | .sy-filler { 277 | width: 100%; } 278 | .sy-filler.ready { 279 | -webkit-transition: padding 600ms ease; 280 | -o-transition: padding 600ms ease; 281 | transition: padding 600ms ease; } 282 | -------------------------------------------------------------------------------- /dist/slippry.min.js: -------------------------------------------------------------------------------- 1 | /** @preserve 2 | * 3 | * slippry v1.4.0 - Responsive content slider for jQuery 4 | * http://slippry.com 5 | * 6 | * Authors: Lukas Jakob Hafner - @saftsaak 7 | * Thomas Hurd - @SeenNotHurd 8 | * 9 | * Copyright 2016, booncon oy - http://booncon.com 10 | * 11 | * 12 | * Released under the MIT license - http://opensource.org/licenses/MIT 13 | */ 14 | !function(a){"use strict";var b;b={slippryWrapper:'
',slideWrapper:'
',slideCrop:'
',boxClass:"sy-list",elements:"li",activeClass:"sy-active",fillerClass:"sy-filler",loadingClass:"sy-loading",adaptiveHeight:!0,start:1,loop:!0,captionsSrc:"img",captions:"overlay",captionsEl:".sy-caption",initSingle:!0,responsive:!0,preload:"visible",pager:!0,pagerClass:"sy-pager",controls:!0,controlClass:"sy-controls",prevClass:"sy-prev",prevText:"Previous",nextClass:"sy-next",nextText:"Next",hideOnEnd:!0,transition:"fade",kenZoom:120,slideMargin:0,transClass:"transition",speed:800,easing:"swing",continuous:!0,useCSS:!0,auto:!0,autoDirection:"next",autoHover:!0,autoHoverDelay:100,autoDelay:500,pause:4e3,onSliderLoad:function(){return this},onSlideBefore:function(){return this},onSlideAfter:function(){return this}},a.fn.slippry=function(c){var d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A;return e=this,0===e.length?this:e.length>1?(e.each(function(){a(this).slippry(c)}),this):(d={},d.vars={},n=function(){var a,b,c;b=document.createElement("div"),c={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",MSTransition:"msTransitionEnd",OTransition:"oTransitionEnd",transition:"transitionEnd transitionend"};for(a in c)if(void 0!==b.style[a])return c[a]},w=function(){var a=document.createElement("div"),b=["Khtml","Ms","O","Moz","Webkit"],c=b.length;return function(d){if(d in a.style)return!0;for(d=d.replace(/^[a-z]/,function(a){return a.toUpperCase()});c--;)if(b[c]+d in a.style)return!0;return!1}}(),z=function(b,c){var d,e,f,g;return d=c.split("."),e=a(b),f="",g="",a.each(d,function(a,b){b.indexOf("#")>=0?f+=b.replace(/^#/,""):g+=b+" "}),f.length&&e.attr("id",f),g.length&&e.attr("class",a.trim(g)),e},A=function(){var a,b,c,e;c={},e={},a=100-d.settings.kenZoom,e.width=d.settings.kenZoom+"%",d.vars.active.index()%2===0?(e.left=a+"%",e.top=a+"%",c.left="0%",c.top="0%"):(e.left="0%",e.top="0%",c.left=a+"%",c.top=a+"%"),b=d.settings.pause+2*d.settings.speed,d.vars.active.css(e),d.vars.active.animate(c,{duration:b,easing:d.settings.easing,queue:!1})},l=function(){d.vars.fresh?(d.vars.slippryWrapper.removeClass(d.settings.loadingClass),d.vars.fresh=!1,d.settings.auto&&e.startAuto(),d.settings.useCSS||"kenburns"!==d.settings.transition||A(),d.settings.onSliderLoad.call(void 0,d.vars.active.index())):a("."+d.settings.fillerClass,d.vars.slideWrapper).addClass("ready")},q=function(b,c){var e,f,g;e=b/c,f=1/e*100+"%",g=a("."+d.settings.fillerClass,d.vars.slideWrapper),g.css({paddingTop:f}),l()},g=function(b){var c,d;void 0!==a("img",b).attr("src")?a("").on("load",function(){c=b.width(),d=b.height(),q(c,d)}).attr("src",a("img",b).attr("src")):(c=b.width(),d=b.height(),q(c,d))},f=function(){if(0===a("."+d.settings.fillerClass,d.vars.slideWrapper).length&&d.vars.slideWrapper.append(a('
')),d.settings.adaptiveHeight===!0)g(a("."+d.settings.activeClass,e));else{var b,c,f;c=0,f=0,a(d.vars.slides).each(function(){a(this).height()>c&&(b=a(this),c=b.height()),f+=1,f===d.vars.count&&(void 0===b&&(b=a(a(d.vars.slides)[0])),g(b))})}},p=function(){d.settings.pager&&(a("."+d.settings.pagerClass+" li",d.vars.slippryWrapper).removeClass(d.settings.activeClass),a(a("."+d.settings.pagerClass+" li",d.vars.slippryWrapper)[d.vars.active.index()]).addClass(d.settings.activeClass))},u=function(){!d.settings.loop&&d.settings.hideOnEnd&&(a("."+d.settings.prevClass,d.vars.slippryWrapper)[d.vars.first?"hide":"show"](),a("."+d.settings.nextClass,d.vars.slippryWrapper)[d.vars.last?"hide":"show"]())},i=function(){var b,c;d.settings.captions!==!1&&(b="img"!==d.settings.captionsSrc?d.vars.active.attr("title"):void 0!==a("img",d.vars.active).attr("title")?a("img",d.vars.active).attr("title"):a("img",d.vars.active).attr("alt"),c="custom"!==d.settings.captions?a(d.settings.captionsEl,d.vars.slippryWrapper):a(d.settings.captionsEl),void 0!==b&&""!==b?c.html(b).show():c.hide())},e.startAuto=function(){void 0===d.vars.timer&&void 0===d.vars.delay&&(d.vars.delay=window.setTimeout(function(){d.vars.autodelay=!1,d.vars.timer=window.setInterval(function(){d.vars.trigger="auto",t(d.settings.autoDirection)},d.settings.pause)},d.vars.autodelay?d.settings.autoHoverDelay:d.settings.autoDelay),d.settings.autoHover&&d.vars.slideWrapper.unbind("mouseenter").unbind("mouseleave").bind("mouseenter",function(){void 0!==d.vars.timer?(d.vars.hoverStop=!0,e.stopAuto()):d.vars.hoverStop=!1}).bind("mouseleave",function(){d.vars.hoverStop&&(d.vars.autodelay=!0,e.startAuto())}))},e.stopAuto=function(){window.clearInterval(d.vars.timer),d.vars.timer=void 0,window.clearTimeout(d.vars.delay),d.vars.delay=void 0},e.refresh=function(){d.vars.slides.removeClass(d.settings.activeClass),d.vars.active.addClass(d.settings.activeClass),d.settings.responsive?f():l(),u(),p(),i()},s=function(){e.refresh()},m=function(){d.vars.moving=!1,d.vars.active.removeClass(d.settings.transClass),d.vars.fresh||d.vars.old.removeClass("sy-ken"),d.vars.old.removeClass(d.settings.transClass),d.settings.onSlideAfter.call(void 0,d.vars.active,d.vars.old.index(),d.vars.active.index()),d.settings.auto&&(d.vars.hoverStop&&void 0!==d.vars.hoverStop||e.startAuto())},r=function(){var b,c,f,g,h,i,j;d.settings.onSlideBefore.call(void 0,d.vars.active,d.vars.old.index(),d.vars.active.index()),d.settings.transition!==!1?(d.vars.moving=!0,"fade"===d.settings.transition||"kenburns"===d.settings.transition?(d.vars.fresh?(d.settings.useCSS?d.vars.slides.css({transitionDuration:d.settings.speed+"ms",opacity:0}):d.vars.slides.css({opacity:0}),d.vars.active.css("opacity",1),"kenburns"===d.settings.transition&&d.settings.useCSS&&(h=d.settings.pause+2*d.settings.speed,d.vars.slides.css({animationDuration:h+"ms"}),d.vars.active.addClass("sy-ken")),m()):d.settings.useCSS?(d.vars.old.addClass(d.settings.transClass).css("opacity",0),d.vars.active.addClass(d.settings.transClass).css("opacity",1),"kenburns"===d.settings.transition&&d.vars.active.addClass("sy-ken"),a(window).off("focus").on("focus",function(){d.vars.moving&&d.vars.old.trigger(d.vars.transition)}),d.vars.old.one(d.vars.transition,function(){return m(),this})):("kenburns"===d.settings.transition&&A(),d.vars.old.addClass(d.settings.transClass).animate({opacity:0},d.settings.speed,d.settings.easing,function(){m()}),d.vars.active.addClass(d.settings.transClass).css("opacity",0).animate({opacity:1},d.settings.speed,d.settings.easing)),s()):("horizontal"===d.settings.transition||"vertical"===d.settings.transition)&&(i="horizontal"===d.settings.transition?"left":"top",b="-"+d.vars.active.index()*(100+d.settings.slideMargin)+"%",d.vars.fresh?(e.css(i,b),m()):(j={},d.settings.continuous&&(!d.vars.jump||"controls"!==d.vars.trigger&&"auto"!==d.vars.trigger||(c=!0,g=b,d.vars.first?(f=0,d.vars.active.css(i,d.vars.count*(100+d.settings.slideMargin)+"%"),b="-"+d.vars.count*(100+d.settings.slideMargin)+"%"):(f=(d.vars.count-1)*(100+d.settings.slideMargin)+"%",d.vars.active.css(i,-(100+d.settings.slideMargin)+"%"),b=100+d.settings.slideMargin+"%"))),d.vars.active.addClass(d.settings.transClass),d.settings.useCSS?(j[i]=b,j.transitionDuration=d.settings.speed+"ms",e.addClass(d.settings.transition),e.css(j),a(window).off("focus").on("focus",function(){d.vars.moving&&e.trigger(d.vars.transition)}),e.one(d.vars.transition,function(){return e.removeClass(d.settings.transition),c&&(d.vars.active.css(i,f),j[i]=g,j.transitionDuration="0ms",e.css(j)),m(),this})):(j[i]=b,e.stop().animate(j,d.settings.speed,d.settings.easing,function(){return c&&(d.vars.active.css(i,f),e.css(i,g)),m(),this}))),s())):(s(),m())},v=function(a){d.vars.first=d.vars.last=!1,"prev"===a||0===a?d.vars.first=!0:("next"===a||a===d.vars.count-1)&&(d.vars.last=!0)},t=function(b){var c,f;d.vars.moving||("auto"!==d.vars.trigger&&e.stopAuto(),c=d.vars.active.index(),"prev"===b?(f=b,c>0?b=c-1:d.settings.loop&&(b=d.vars.count-1)):"next"===b?(f=b,cb?"prev":"next"),d.vars.jump=!1,"prev"===b||"next"===b||b===c&&!d.vars.fresh||(v(b),d.vars.old=d.vars.active,d.vars.active=a(d.vars.slides[b]),(0===c&&"prev"===f||c===d.vars.count-1&&"next"===f)&&(d.vars.jump=!0),r()))},e.goToSlide=function(a){d.vars.trigger="external",t(a)},e.goToNextSlide=function(){d.vars.trigger="external",t("next")},e.goToPrevSlide=function(){d.vars.trigger="external",t("prev")},j=function(){if(d.settings.pager&&d.vars.count>1){var b,c,e;for(b=d.vars.slides.length,e=a('
    '),c=1;b+1>c;c+=1)e.append(a("
  • ").append(a(''+c+"")));d.vars.slippryWrapper.append(e),a("."+d.settings.pagerClass+" a",d.vars.slippryWrapper).click(function(){return d.vars.trigger="pager",t(parseInt(this.hash.split("#")[1],10)),!1}),p()}},k=function(){d.settings.controls&&d.vars.count>1&&(d.vars.slideWrapper.append(a('
      ').append('
    • '+d.settings.prevText+"
    • ").append('
    • '+d.settings.nextText+"
    • ")),a("."+d.settings.controlClass+" a",d.vars.slippryWrapper).click(function(){return d.vars.trigger="controls",t(this.hash.split("#")[1]),!1}),u())},o=function(){d.settings.captions!==!1&&("overlay"===d.settings.captions?d.vars.slideWrapper.append(a('
      ').html(z("
      ",d.settings.captionsEl))):"below"===d.settings.captions&&d.vars.slippryWrapper.append(a('
      ').html(z("
      ",d.settings.captionsEl))))},y=function(){t(d.vars.active.index()+1)},x=function(b){var c,e,f,g;return g="all"===d.settings.preload?b:d.vars.active,f=a("img, iframe",g),c=f.length,0===c?void y():(e=0,void f.each(function(){a(this).one("load error",function(){++e===c&&y()}).each(function(){this.complete&&a(this).trigger("load")})}))},e.getCurrentSlide=function(){return d.vars.active},e.getSlideCount=function(){return d.vars.count},e.destroySlider=function(){d.vars.fresh===!1&&(e.stopAuto(),d.vars.moving=!1,d.vars.slides.each(function(){void 0!==a(this).data("sy-cssBckup")?a(this).attr("style",a(this).data("sy-cssBckup")):a(this).removeAttr("style"),void 0!==a(this).data("sy-classBckup")?a(this).attr("class",a(this).data("sy-classBckup")):a(this).removeAttr("class")}),void 0!==e.data("sy-cssBckup")?e.attr("style",e.data("sy-cssBckup")):e.removeAttr("style"),void 0!==e.data("sy-classBckup")?e.attr("class",e.data("sy-classBckup")):e.removeAttr("class"),d.vars.slippryWrapper.before(e),d.vars.slippryWrapper.remove(),d.vars.fresh=void 0)},e.reloadSlider=function(){e.destroySlider(),h()},h=function(){var f;return d.settings=a.extend({},b,c),d.vars.slides=a(d.settings.elements,e),d.vars.count=d.vars.slides.length,d.settings.useCSS&&(w("transition")||(d.settings.useCSS=!1),d.vars.transition=n()),e.data("sy-cssBckup",e.attr("style")),e.data("sy-classBackup",e.attr("class")),e.addClass(d.settings.boxClass).wrap(d.settings.slippryWrapper).wrap(d.settings.slideWrapper).wrap(d.settings.slideCrop),d.vars.slideWrapper=e.parent().parent(),d.vars.slippryWrapper=d.vars.slideWrapper.parent().addClass(d.settings.loadingClass),d.vars.fresh=!0,d.vars.slides.each(function(){a(this).addClass("sy-slide "+d.settings.transition),d.settings.useCSS&&a(this).addClass("useCSS"),"horizontal"===d.settings.transition?a(this).css("left",a(this).index()*(100+d.settings.slideMargin)+"%"):"vertical"===d.settings.transition&&a(this).css("top",a(this).index()*(100+d.settings.slideMargin)+"%")}),d.vars.count>1||d.settings.initSingle?(-1===a("."+d.settings.activeClass,e).index()?(f="random"===d.settings.start?Math.round(Math.random()*(d.vars.count-1)):d.settings.start>0&&d.settings.start<=d.vars.count?d.settings.start-1:0,d.vars.active=a(d.vars.slides[f]).addClass(d.settings.activeClass)):d.vars.active=a("."+d.settings.activeClass,e),k(),j(),o(),x(d.vars.slides),void 0):this},h(),this)}}(jQuery); -------------------------------------------------------------------------------- /src/slippry.js: -------------------------------------------------------------------------------- 1 | /** @preserve 2 | * 3 | * slippry v1.4.0 - Responsive content slider for jQuery 4 | * http://slippry.com 5 | * 6 | * Authors: Lukas Jakob Hafner - @saftsaak 7 | * Thomas Hurd - @SeenNotHurd 8 | * 9 | * Copyright 2016, booncon oy - http://booncon.com 10 | * 11 | * 12 | * Released under the MIT license - http://opensource.org/licenses/MIT 13 | */ 14 | 15 | (function ($) { 16 | "use strict"; 17 | var defaults; 18 | 19 | defaults = { 20 | // general elements & wrapper 21 | slippryWrapper: '
      ', // wrapper to wrap everything, including pager 22 | slideWrapper: '
      ', // wrapper to wrap sildes & controls 23 | slideCrop: '
      ', //additional wrapper around just the slides 24 | boxClass: 'sy-list', // class that goes to original element 25 | elements: 'li', // elments cointaining slide content 26 | activeClass: 'sy-active', // class for current slide 27 | fillerClass: 'sy-filler', // class for element that acts as intrinsic placholder 28 | loadingClass: 'sy-loading', 29 | 30 | // options 31 | adaptiveHeight: true, // height of the sliders adapts to current slide 32 | start: 1, // num (starting from 1), random 33 | loop: true, // first -> last & last -> first arrows 34 | captionsSrc: 'img', // img, el [img takes caption from alt or title, el from title of slide element] 35 | captions: 'overlay', // Position: overlay, below, custom, false 36 | captionsEl: '.sy-caption', // $ selector for captions wrapper 37 | initSingle: true, // initialise even if there is only one slide 38 | responsive: true, 39 | preload: 'visible', // visible, all | resources to wait for until showing slider 40 | 41 | // pager 42 | pager: true, 43 | pagerClass: 'sy-pager', 44 | 45 | // controls 46 | controls: true, 47 | controlClass: 'sy-controls', 48 | prevClass: 'sy-prev', 49 | prevText: 'Previous', 50 | nextClass: 'sy-next', 51 | nextText: 'Next', 52 | hideOnEnd: true, 53 | 54 | // transitions 55 | transition: 'fade', // fade, horizontal, vertical, kenburns, false 56 | kenZoom: 120, // max zoom for kenburns (in %) 57 | slideMargin: 0, // spacing between slides (in %) 58 | transClass: 'transition', // [Class applied to [element] while a transition is taking place.] 59 | speed: 800, // time the transition takes (ms) 60 | easing: 'swing', // easing to use in the animation [(see... [jquery www])] 61 | continuous: true, // seamless first/ last transistion, only works with loop 62 | useCSS: true, // true, false -> fallback to js if no browser support 63 | 64 | //slideshow 65 | auto: true, 66 | autoDirection: 'next', 67 | autoHover: true, 68 | autoHoverDelay: 100, 69 | autoDelay: 500, 70 | pause: 4000, 71 | 72 | // callback functions 73 | onSliderLoad: function () { // when slider loaded 74 | return this; 75 | }, 76 | onSlideBefore: function () { // before page transition starts 77 | return this; 78 | }, 79 | onSlideAfter: function () { // after page transition happened 80 | return this; 81 | } 82 | }; 83 | 84 | $.fn.slippry = function (options) { 85 | var slip, el, prepareFiller, getFillerProportions, init, updateCaption, initPager, initControls, ready, transitionDone, whichTransitionEvent, 86 | initCaptions, updatePager, setFillerProportions, doTransition, updateSlide, openSlide, updateControls, updatePos, supports, preload, start, elFromSel, doKens; 87 | 88 | // reference to the object calling the function 89 | el = this; 90 | 91 | // if no elements just stop 92 | if (el.length === 0) { 93 | return this; 94 | } 95 | // support mutltiple elements 96 | if (el.length > 1) { 97 | el.each(function () { 98 | $(this).slippry(options); 99 | }); 100 | return this; 101 | } 102 | 103 | // variable to access the slider settings across the plugin 104 | slip = {}; 105 | slip.vars = {}; 106 | 107 | whichTransitionEvent = function () { // Thanks! http://stackoverflow.com/a/18672988 108 | var t, div, transitions; 109 | div = document.createElement('div'); 110 | transitions = { 111 | 'WebkitTransition' : 'webkitTransitionEnd', 112 | 'MozTransition' : 'transitionend', 113 | 'MSTransition' : 'msTransitionEnd', 114 | 'OTransition' : 'oTransitionEnd', 115 | 'transition' : 'transitionEnd transitionend' 116 | }; 117 | for (t in transitions) { 118 | if (div.style[t] !== undefined) { 119 | return transitions[t]; 120 | } 121 | } 122 | }; 123 | 124 | supports = (function () { // Thanks! http://net.tutsplus.com/tutorials/html-css-techniques/quick-tip-detect-css-support-in-browsers-with-javascript/ 125 | var div = document.createElement('div'), 126 | vendors = ['Khtml', 'Ms', 'O', 'Moz', 'Webkit'], 127 | len = vendors.length; 128 | return function (prop) { 129 | if (prop in div.style) { 130 | return true; 131 | } 132 | prop = prop.replace(/^[a-z]/, function (val) { 133 | return val.toUpperCase(); 134 | }); 135 | while (len--) { 136 | if (vendors[len] + prop in div.style) { 137 | return true; 138 | } 139 | } 140 | return false; 141 | }; 142 | }()); 143 | 144 | elFromSel = function (sel, prop) { 145 | var props, newelement, id, className; 146 | props = prop.split('.'); 147 | newelement = $(sel); 148 | id = ''; 149 | className = ''; 150 | $.each(props, function (i, val) { 151 | if (val.indexOf('#') >= 0) { 152 | id += val.replace(/^#/, ''); 153 | } else { 154 | className += val + ' '; 155 | } 156 | }); 157 | if (id.length) { 158 | newelement.attr('id', id); 159 | } 160 | if (className.length) { 161 | newelement.attr('class', $.trim(className)); 162 | } 163 | return newelement; 164 | }; 165 | 166 | doKens = function () { 167 | var kenStart, kenTime, animProp, cssProp; 168 | animProp = {}; 169 | cssProp = {}; 170 | kenStart = 100 - slip.settings.kenZoom; 171 | cssProp.width = slip.settings.kenZoom + '%'; 172 | if (slip.vars.active.index() % 2 === 0) { 173 | cssProp.left = kenStart + '%'; 174 | cssProp.top = kenStart + '%'; 175 | animProp.left = '0%'; 176 | animProp.top = '0%'; 177 | } else { 178 | cssProp.left = '0%'; 179 | cssProp.top = '0%'; 180 | animProp.left = kenStart + '%'; 181 | animProp.top = kenStart + '%'; 182 | } 183 | kenTime = slip.settings.pause + slip.settings.speed * 2; 184 | slip.vars.active.css(cssProp); 185 | slip.vars.active.animate(animProp, {duration: kenTime, easing: slip.settings.easing, queue: false}); 186 | }; 187 | 188 | ready = function () { 189 | if (slip.vars.fresh) { 190 | slip.vars.slippryWrapper.removeClass(slip.settings.loadingClass); 191 | slip.vars.fresh = false; 192 | if (slip.settings.auto) { 193 | el.startAuto(); 194 | } 195 | if (!slip.settings.useCSS && slip.settings.transition === 'kenburns') { 196 | doKens(); 197 | } 198 | slip.settings.onSliderLoad.call(undefined, slip.vars.active.index()); 199 | } else { 200 | $('.' + slip.settings.fillerClass, slip.vars.slideWrapper).addClass('ready'); 201 | } 202 | }; 203 | 204 | setFillerProportions = function (width, height) { 205 | var ratio, p_top, $filler; 206 | ratio = width / height; 207 | p_top = 1 / ratio * 100 + '%'; //cool intrinsic trick: http://alistapart.com/article/creating-intrinsic-ratios-for-video 208 | $filler = $('.' + slip.settings.fillerClass, slip.vars.slideWrapper); 209 | $filler.css({paddingTop: p_top}); // resizing without the need of js, true responsiveness :) 210 | ready(); 211 | }; 212 | 213 | // gets the aspect ratio of the filler element 214 | getFillerProportions = function ($slide) { 215 | var width, height; 216 | if (($('img', $slide).attr("src") !== undefined)) { 217 | $("").on("load", function () { 218 | width = $slide.width(); 219 | height = $slide.height(); 220 | setFillerProportions(width, height); 221 | }).attr("src", $('img', $slide).attr("src")); 222 | } else { 223 | width = $slide.width(); 224 | height = $slide.height(); 225 | setFillerProportions(width, height); 226 | } 227 | }; 228 | 229 | // prepares a div to occupy the needed space 230 | prepareFiller = function () { 231 | if ($('.' + slip.settings.fillerClass, slip.vars.slideWrapper).length === 0) { 232 | slip.vars.slideWrapper.append($('
      ')); 233 | } 234 | if (slip.settings.adaptiveHeight === true) { // if the slides shoud alwas adapt to their content 235 | getFillerProportions($('.' + slip.settings.activeClass, el)); // set the filler height on the active element 236 | } else { // otherwise get the highest element 237 | var $highest, height, loop; 238 | height = 0; 239 | loop = 0; 240 | $(slip.vars.slides).each(function () { 241 | if ($(this).height() > height) { 242 | $highest = $(this); 243 | height = $highest.height(); 244 | } 245 | loop = loop + 1; 246 | if (loop === slip.vars.count) { 247 | if ($highest === undefined) { 248 | $highest = $($(slip.vars.slides)[0]); 249 | } 250 | getFillerProportions($highest); 251 | } 252 | }); 253 | } 254 | }; 255 | 256 | updatePager = function () { 257 | if (slip.settings.pager) { 258 | $('.' + slip.settings.pagerClass + ' li', slip.vars.slippryWrapper).removeClass(slip.settings.activeClass); 259 | $($('.' + slip.settings.pagerClass + ' li', slip.vars.slippryWrapper)[slip.vars.active.index()]).addClass(slip.settings.activeClass); 260 | } 261 | }; 262 | 263 | updateControls = function () { 264 | if (!slip.settings.loop && slip.settings.hideOnEnd) { 265 | $('.' + slip.settings.prevClass, slip.vars.slippryWrapper)[slip.vars.first ? 'hide' : 'show'](); 266 | $('.' + slip.settings.nextClass, slip.vars.slippryWrapper)[slip.vars.last ? 'hide' : 'show'](); 267 | } 268 | }; 269 | 270 | updateCaption = function () { 271 | var caption, wrapper; 272 | if (slip.settings.captions !== false) { 273 | if (slip.settings.captionsSrc !== 'img') { 274 | caption = slip.vars.active.attr('title'); 275 | } else { 276 | caption = $('img', slip.vars.active).attr('title') !== undefined ? $('img', slip.vars.active).attr('title') : $('img', slip.vars.active).attr('alt'); 277 | } 278 | if (slip.settings.captions !== 'custom') { 279 | wrapper = $(slip.settings.captionsEl, slip.vars.slippryWrapper); 280 | } else { 281 | wrapper = $(slip.settings.captionsEl); 282 | } 283 | if ((caption !== undefined) && (caption !== '')) { 284 | wrapper.html(caption).show(); 285 | } else { 286 | wrapper.hide(); 287 | } 288 | } 289 | }; 290 | 291 | el.startAuto = function () { 292 | if ((slip.vars.timer === undefined) && (slip.vars.delay === undefined)) { 293 | slip.vars.delay = window.setTimeout(function () { 294 | slip.vars.autodelay = false; 295 | slip.vars.timer = window.setInterval(function () { 296 | slip.vars.trigger = 'auto'; 297 | openSlide(slip.settings.autoDirection); 298 | }, slip.settings.pause); 299 | }, slip.vars.autodelay ? slip.settings.autoHoverDelay : slip.settings.autoDelay); 300 | if (slip.settings.autoHover) { 301 | slip.vars.slideWrapper.unbind('mouseenter').unbind('mouseleave').bind('mouseenter', function () { 302 | if (slip.vars.timer !== undefined) { 303 | slip.vars.hoverStop = true; 304 | el.stopAuto(); 305 | } else { 306 | slip.vars.hoverStop = false; 307 | } 308 | }).bind('mouseleave', function () { 309 | if (slip.vars.hoverStop) { 310 | slip.vars.autodelay = true; 311 | el.startAuto(); 312 | } 313 | }); 314 | } 315 | } 316 | }; 317 | 318 | el.stopAuto = function () { 319 | window.clearInterval(slip.vars.timer); 320 | slip.vars.timer = undefined; 321 | window.clearTimeout(slip.vars.delay); 322 | slip.vars.delay = undefined; 323 | }; 324 | 325 | // refreshes the already initialised slider 326 | el.refresh = function () { 327 | slip.vars.slides.removeClass(slip.settings.activeClass); 328 | slip.vars.active.addClass(slip.settings.activeClass); 329 | if (slip.settings.responsive) { 330 | prepareFiller(); 331 | } else { 332 | ready(); 333 | } 334 | updateControls(); 335 | updatePager(); 336 | updateCaption(); 337 | }; 338 | 339 | updateSlide = function () { 340 | el.refresh(); 341 | }; 342 | 343 | transitionDone = function () { 344 | slip.vars.moving = false; 345 | slip.vars.active.removeClass(slip.settings.transClass); 346 | if (!slip.vars.fresh) { 347 | slip.vars.old.removeClass('sy-ken'); 348 | } 349 | slip.vars.old.removeClass(slip.settings.transClass); 350 | slip.settings.onSlideAfter.call(undefined, slip.vars.active, slip.vars.old.index(), slip.vars.active.index()); 351 | if (slip.settings.auto) { 352 | if (!slip.vars.hoverStop || slip.vars.hoverStop === undefined){ 353 | el.startAuto(); 354 | } 355 | } 356 | }; 357 | 358 | doTransition = function () { 359 | var pos, jump, old_left, old_pos, kenTime, ref, cssProp; 360 | slip.settings.onSlideBefore.call(undefined, slip.vars.active, slip.vars.old.index(), slip.vars.active.index()); 361 | if (slip.settings.transition !== false) { 362 | slip.vars.moving = true; 363 | if ((slip.settings.transition === 'fade') || (slip.settings.transition === 'kenburns')) { 364 | if (slip.vars.fresh) { 365 | if (slip.settings.useCSS) { 366 | slip.vars.slides.css({transitionDuration: slip.settings.speed + 'ms', opacity: 0}); 367 | } else { 368 | slip.vars.slides.css({opacity: 0}); 369 | } 370 | slip.vars.active.css('opacity', 1); 371 | if (slip.settings.transition === 'kenburns') { 372 | if (slip.settings.useCSS) { 373 | kenTime = slip.settings.pause + slip.settings.speed * 2; 374 | slip.vars.slides.css({animationDuration: kenTime + 'ms'}); 375 | slip.vars.active.addClass('sy-ken'); 376 | } 377 | } 378 | transitionDone(); 379 | } else { 380 | if (slip.settings.useCSS) { 381 | slip.vars.old.addClass(slip.settings.transClass).css('opacity', 0); 382 | slip.vars.active.addClass(slip.settings.transClass).css('opacity', 1); 383 | if (slip.settings.transition === 'kenburns') { 384 | slip.vars.active.addClass('sy-ken'); 385 | } 386 | $(window).off('focus').on('focus', function () { // bugfix for safari 7 which doesn't always trigger ontransitionend when switching tab 387 | if (slip.vars.moving) { 388 | slip.vars.old.trigger(slip.vars.transition); 389 | } 390 | }); 391 | slip.vars.old.one(slip.vars.transition, function () { 392 | transitionDone(); 393 | return this; 394 | }); 395 | } else { 396 | if (slip.settings.transition === 'kenburns') { 397 | doKens(); 398 | } 399 | slip.vars.old.addClass(slip.settings.transClass).animate({ 400 | opacity: 0 401 | }, slip.settings.speed, slip.settings.easing, function () { 402 | transitionDone(); 403 | }); 404 | slip.vars.active.addClass(slip.settings.transClass).css('opacity', 0).animate({ 405 | opacity: 1 406 | }, slip.settings.speed, slip.settings.easing); 407 | } 408 | } 409 | updateSlide(); 410 | } else if ((slip.settings.transition === 'horizontal') || (slip.settings.transition === 'vertical')) { 411 | ref = (slip.settings.transition === 'horizontal') ? 'left' : 'top'; 412 | pos = '-' + slip.vars.active.index() * (100 + slip.settings.slideMargin) + '%'; 413 | if (slip.vars.fresh) { 414 | el.css(ref, pos); 415 | transitionDone(); 416 | } else { 417 | cssProp = {}; 418 | if (slip.settings.continuous) { 419 | if (slip.vars.jump && ((slip.vars.trigger === 'controls') || (slip.vars.trigger === 'auto'))) { 420 | jump = true; 421 | old_pos = pos; 422 | if (slip.vars.first) { 423 | old_left = 0; 424 | slip.vars.active.css(ref, slip.vars.count * (100 + slip.settings.slideMargin) + '%'); 425 | pos = '-' + slip.vars.count * (100 + slip.settings.slideMargin) + '%'; 426 | } else { 427 | old_left = (slip.vars.count - 1) * (100 + slip.settings.slideMargin) + '%'; 428 | slip.vars.active.css(ref, -(100 + slip.settings.slideMargin) + '%'); 429 | pos = (100 + slip.settings.slideMargin) + '%'; 430 | } 431 | } 432 | } 433 | slip.vars.active.addClass(slip.settings.transClass); 434 | if (slip.settings.useCSS) { 435 | cssProp[ref] = pos; 436 | cssProp.transitionDuration = slip.settings.speed + 'ms'; 437 | el.addClass(slip.settings.transition); 438 | el.css(cssProp); 439 | $(window).off('focus').on('focus', function () { // bugfix for safari 7 which doesn't always trigger ontransitionend when switching tab 440 | if (slip.vars.moving) { 441 | el.trigger(slip.vars.transition); 442 | } 443 | }); 444 | el.one(slip.vars.transition, function () { 445 | el.removeClass(slip.settings.transition); 446 | if (jump) { 447 | slip.vars.active.css(ref, old_left); 448 | cssProp[ref] = old_pos; 449 | cssProp.transitionDuration = '0ms'; 450 | el.css(cssProp); 451 | } 452 | transitionDone(); 453 | return this; 454 | }); 455 | } else { 456 | cssProp[ref] = pos; 457 | el.stop().animate(cssProp, slip.settings.speed, slip.settings.easing, function () { 458 | if (jump) { 459 | slip.vars.active.css(ref, old_left); 460 | el.css(ref, old_pos); 461 | } 462 | transitionDone(); 463 | return this; 464 | }); 465 | } 466 | } 467 | updateSlide(); 468 | } 469 | } else { 470 | updateSlide(); 471 | transitionDone(); 472 | } 473 | }; 474 | 475 | updatePos = function (slide) { 476 | slip.vars.first = slip.vars.last = false; 477 | if ((slide === 'prev') || (slide === 0)) { 478 | slip.vars.first = true; 479 | } else if ((slide === 'next') || (slide === slip.vars.count - 1)) { 480 | slip.vars.last = true; 481 | } 482 | }; 483 | 484 | openSlide = function (slide) { 485 | var current, direction; 486 | if (!slip.vars.moving) { 487 | if (slip.vars.trigger !== 'auto') { 488 | el.stopAuto(); 489 | } 490 | current = slip.vars.active.index(); 491 | if (slide === 'prev') { 492 | direction = slide; 493 | if (current > 0) { 494 | slide = current - 1; 495 | } else if (slip.settings.loop) { 496 | slide = slip.vars.count - 1; 497 | } 498 | } else if (slide === 'next') { 499 | direction = slide; 500 | if (current < slip.vars.count - 1) { 501 | slide = current + 1; 502 | } else if (slip.settings.loop) { 503 | slide = 0; 504 | } 505 | } else { 506 | slide = slide - 1; 507 | direction = slide < current ? 'prev' : 'next'; 508 | } 509 | slip.vars.jump = false; 510 | if ((slide !== 'prev') && (slide !== 'next') && ((slide !== current) || (slip.vars.fresh))) { 511 | updatePos(slide); 512 | slip.vars.old = slip.vars.active; 513 | slip.vars.active = $(slip.vars.slides[slide]); 514 | if (((current === 0) && (direction === 'prev')) || ((current === slip.vars.count - 1) && (direction === 'next'))) { 515 | slip.vars.jump = true; 516 | } 517 | doTransition(); 518 | } 519 | } 520 | }; 521 | 522 | el.goToSlide = function (slide) { 523 | slip.vars.trigger = 'external'; 524 | openSlide(slide); 525 | }; 526 | 527 | el.goToNextSlide = function () { 528 | slip.vars.trigger = 'external'; 529 | openSlide('next'); 530 | }; 531 | 532 | el.goToPrevSlide = function () { 533 | slip.vars.trigger = 'external'; 534 | openSlide('prev'); 535 | }; 536 | 537 | initPager = function () { 538 | if ((slip.settings.pager) && (slip.vars.count > 1)) { 539 | var count, loop, pager; 540 | count = slip.vars.slides.length; 541 | pager = $('
        '); 542 | for (loop = 1; loop < count + 1; loop = loop + 1) { 543 | pager.append($('
      • ').append($('' + loop + ''))); 544 | } 545 | slip.vars.slippryWrapper.append(pager); 546 | $('.' + slip.settings.pagerClass + ' a', slip.vars.slippryWrapper).click(function () { 547 | slip.vars.trigger = 'pager'; 548 | openSlide(parseInt(this.hash.split('#')[1], 10)); 549 | return false; 550 | }); 551 | updatePager(); 552 | } 553 | }; 554 | 555 | initControls = function () { 556 | if ((slip.settings.controls) && (slip.vars.count > 1)) { 557 | slip.vars.slideWrapper.append( 558 | $('
          ') 559 | .append('
        • ' + slip.settings.prevText + '
        • ') 560 | .append('
        • ' + slip.settings.nextText + '
        • ') 561 | ); 562 | $('.' + slip.settings.controlClass + ' a', slip.vars.slippryWrapper).click(function () { 563 | slip.vars.trigger = 'controls'; 564 | openSlide(this.hash.split('#')[1]); 565 | return false; 566 | }); 567 | updateControls(); 568 | } 569 | }; 570 | 571 | initCaptions = function () { 572 | if (slip.settings.captions !== false) { 573 | if (slip.settings.captions === 'overlay') { 574 | slip.vars.slideWrapper.append($('
          ').html(elFromSel('
          ', slip.settings.captionsEl))); 575 | } else if (slip.settings.captions === 'below') { 576 | slip.vars.slippryWrapper.append($('
          ').html(elFromSel('
          ', slip.settings.captionsEl))); 577 | } 578 | } 579 | }; 580 | 581 | // actually show the first slide 582 | start = function () { 583 | openSlide(slip.vars.active.index() + 1); 584 | }; 585 | 586 | // wait for images, iframes to be loaded 587 | preload = function (slides) { 588 | var count, loop, elements, container; 589 | container = (slip.settings.preload === 'all') ? slides : slip.vars.active; 590 | elements = $('img, iframe', container); 591 | count = elements.length; 592 | if (count === 0) { 593 | start(); 594 | return; 595 | } 596 | loop = 0; 597 | elements.each(function () { 598 | $(this).one('load error', function () { 599 | if (++loop === count) { 600 | start(); 601 | } 602 | }).each(function () { 603 | if (this.complete) { 604 | $(this).trigger('load'); 605 | } 606 | }); 607 | }); 608 | }; 609 | 610 | el.getCurrentSlide = function () { 611 | return slip.vars.active; 612 | }; 613 | 614 | el.getSlideCount = function () { 615 | return slip.vars.count; 616 | }; 617 | 618 | el.destroySlider = function () { 619 | if (slip.vars.fresh === false) { 620 | el.stopAuto(); 621 | slip.vars.moving = false; 622 | slip.vars.slides.each(function () { 623 | if ($(this).data("sy-cssBckup") !== undefined) { 624 | $(this).attr("style", $(this).data("sy-cssBckup")); 625 | } else { 626 | $(this).removeAttr('style'); 627 | } 628 | if ($(this).data("sy-classBckup") !== undefined) { 629 | $(this).attr("class", $(this).data("sy-classBckup")); 630 | } else { 631 | $(this).removeAttr('class'); 632 | } 633 | }); 634 | if (el.data("sy-cssBckup") !== undefined) { 635 | el.attr("style", el.data("sy-cssBckup")); 636 | } else { 637 | el.removeAttr('style'); 638 | } 639 | if (el.data("sy-classBckup") !== undefined) { 640 | el.attr("class", el.data("sy-classBckup")); 641 | } else { 642 | el.removeAttr('class'); 643 | } 644 | slip.vars.slippryWrapper.before(el); 645 | slip.vars.slippryWrapper.remove(); 646 | slip.vars.fresh = undefined; 647 | } 648 | }; 649 | 650 | el.reloadSlider = function () { 651 | el.destroySlider(); 652 | init(); 653 | }; 654 | 655 | // initialises the slider, creates needed markup 656 | init = function () { 657 | var first; 658 | slip.settings = $.extend({}, defaults, options); 659 | slip.vars.slides = $(slip.settings.elements, el); 660 | slip.vars.count = slip.vars.slides.length; 661 | if (slip.settings.useCSS) { // deactivate css transitions on unsupported browsers 662 | if (!supports('transition')) { 663 | slip.settings.useCSS = false; 664 | } 665 | slip.vars.transition = whichTransitionEvent(); 666 | } 667 | el.data('sy-cssBckup', el.attr('style')); 668 | el.data('sy-classBackup', el.attr('class')); 669 | el.addClass(slip.settings.boxClass).wrap(slip.settings.slippryWrapper).wrap(slip.settings.slideWrapper).wrap(slip.settings.slideCrop); 670 | slip.vars.slideWrapper = el.parent().parent(); 671 | slip.vars.slippryWrapper = slip.vars.slideWrapper.parent().addClass(slip.settings.loadingClass); 672 | slip.vars.fresh = true; 673 | slip.vars.slides.each(function () { 674 | $(this).addClass('sy-slide ' + slip.settings.transition); 675 | if (slip.settings.useCSS) { 676 | $(this).addClass('useCSS'); 677 | } 678 | if (slip.settings.transition === 'horizontal') { 679 | $(this).css('left', $(this).index() * (100 + slip.settings.slideMargin) + '%'); 680 | } else if (slip.settings.transition === 'vertical') { 681 | $(this).css('top', $(this).index() * (100 + slip.settings.slideMargin) + '%'); 682 | } 683 | }); 684 | if ((slip.vars.count > 1) || (slip.settings.initSingle)) { 685 | if ($('.' + slip.settings.activeClass, el).index() === -1) { 686 | if (slip.settings.start === 'random') { 687 | first = Math.round(Math.random() * (slip.vars.count - 1)); 688 | } else if (slip.settings.start > 0 && slip.settings.start <= slip.vars.count) { 689 | first = slip.settings.start - 1; 690 | } else { 691 | first = 0; 692 | } 693 | slip.vars.active = $(slip.vars.slides[first]).addClass(slip.settings.activeClass); 694 | } else { 695 | slip.vars.active = $('.' + slip.settings.activeClass, el); 696 | } 697 | initControls(); 698 | initPager(); 699 | initCaptions(); 700 | preload(slip.vars.slides); 701 | } else { 702 | return this; 703 | } 704 | }; 705 | 706 | init(); // on startup initialise the slider 707 | 708 | return this; 709 | }; 710 | }(jQuery)); 711 | --------------------------------------------------------------------------------