├── .gitignore ├── .nodemonignore ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── RELEASENOTES.md ├── bower.json ├── build.js ├── build ├── iscroll-infinite.js ├── iscroll-lite.js ├── iscroll-probe.js ├── iscroll-zoom.js └── iscroll.js ├── demos ├── 2d-scroll │ └── index.html ├── barebone │ └── index.html ├── bounce-easing │ └── index.html ├── carousel │ ├── gaugin.jpg │ ├── giotto.jpg │ ├── index.html │ ├── leonardo.jpg │ └── warhol.jpg ├── click │ └── index.html ├── demoUtils.js ├── event-passthrough │ └── index.html ├── forms │ └── index.html ├── horizontal │ └── index.html ├── infinite │ ├── dataset.php │ └── index.html ├── key-bindings │ └── index.html ├── minimap │ ├── ermine.jpg │ └── index.html ├── no-transition │ └── index.html ├── parallax │ ├── galaxies1.png │ ├── galaxies2.png │ ├── index.html │ └── stars.jpg ├── probe │ └── index.html ├── scroll-to-element │ └── index.html ├── scrollbars │ └── index.html ├── simple │ └── index.html ├── snap │ └── index.html ├── styled-scrollbars │ └── index.html ├── tap │ └── index.html └── zoom │ └── index.html ├── package.json └── src ├── close.js ├── core.js ├── default ├── _animate.js └── handleEvent.js ├── indicator ├── _initIndicators.js ├── _transitionTime.js ├── _transitionTimingFunction.js ├── _translate.js ├── build.json └── indicator.js ├── infinite ├── build.json ├── infinite.js └── refresh.js ├── keys ├── build.json └── keys.js ├── open.js ├── probe ├── _animate.js ├── _move.js ├── build.json ├── indicator._move.js └── probe.js ├── snap ├── _end.js ├── build.json ├── refresh.js └── snap.js ├── utils.js ├── wheel ├── build.json └── wheel.js └── zoom ├── build.json ├── handleEvent.js ├── refresh.js └── zoom.js /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | ._* 3 | node_modules 4 | dist -------------------------------------------------------------------------------- /.nodemonignore: -------------------------------------------------------------------------------- 1 | /build/* 2 | /dist/* 3 | /demos/* 4 | *.md 5 | *.tmp -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to iScroll / FAQ 2 | 3 | You are very welcome to collaborate, all changes to the code will be released under an MIT license. 4 | 5 | By submitting a pull request you implicitly agree to give rights of your code to the project authors. Your contribution will always be released under the same MIT license. 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2008-2013 Matteo Spinelli, http://cubiq.org 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /RELEASENOTES.md: -------------------------------------------------------------------------------- 1 | # Release notes for iScroll 2 | 3 | --- 4 | 5 | ## Version 5.2.0 - 2016.04.05 6 | 7 | ### Fixes 8 | * Fixes weird scrolling in Chrome (#760, #441, #943, #927, #780) 9 | * [#1009](https://github.com/cubiq/iscroll/issues/1009) fixes utils.prefixPointerEvent method 10 | * [#1018](https://github.com/cubiq/iscroll/issues/1018), [#652](https://github.com/cubiq/iscroll/issues/652) fixes directionX/Y when scrolling with mouse 11 | * [#924](https://github.com/cubiq/iscroll/issues/924), [#950](https://github.com/cubiq/iscroll/issues/950) clean up timer on destroy 12 | * [#949](https://github.com/cubiq/iscroll/issues/949) removes unnecesary style values on wrapper when useTransition option is 'false' 13 | * [#361](https://github.com/cubiq/iscroll/issues/361) fixes two click/tap events issue 14 | * [#980](https://github.com/cubiq/iscroll/issues/980) fixes event propagation for wheel event 15 | * [#768](https://github.com/cubiq/iscroll/issues/768) fixes indicators 16 | * [#761](https://github.com/cubiq/iscroll/issues/761) fixes two scrollEnd events issue 17 | * Fixes 'click' event is not fired when iScroll is disabled 18 | 19 | ### Changes 20 | * Added AMD support 21 | * Changed default value of disableMouse/disableTouch/disablePointer options 22 | * Removed CLA non-sense 23 | 24 | --- 25 | 26 | ## Version 5.1.3 - 2014.09.19 27 | 28 | ### Fixes 29 | * [#577](https://github.com/cubiq/iscroll/issues/577) fixes scrolling in Firefox 30 | 31 | --- 32 | 33 | ## Version 5.1.2 - 2014.06.02 34 | 35 | ### Fixes 36 | * [#707](https://github.com/cubiq/iscroll/pull/707) fixes build fail when dist folder does not exist 37 | * [#713](https://github.com/cubiq/iscroll/pull/713) Adds W3C pointer support and fixes issue with `MSPointerEvent` detection 38 | 39 | --- 40 | 41 | ## Version 5.1.1 - 2014.01.10 42 | 43 | ### Fixes 44 | * Infinite scroll now switch from `transform` to `top/left` based on `useTransform` option 45 | * [#555](https://github.com/cubiq/iscroll/issues/555) removed unused variable 46 | * [#372](https://github.com/cubiq/iscroll/issues/372) case insensitive check on tag names 47 | 48 | ### New features 49 | * New `off` method to unload custom events 50 | * Added `options.deceleration` to alter the momentum duration/speed 51 | * Added release notes file 52 | 53 | --- 54 | 55 | ## Version 5.1.0 - 2014.01.09 56 | 57 | ### Fixes 58 | * [#558](https://github.com/cubiq/iscroll/issues/558) false positive for `isBadAndroid` 59 | 60 | ### New features 61 | * Infinite scrolling 62 | * Documentation 63 | * `_execEvent` supports arguments 64 | 65 | ### Changes 66 | * dist/minified files are no longer pushed to the main repo 67 | 68 | --- 69 | 70 | *I started collecting release notes from version 5.1.0* 71 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "iscroll", 3 | "description": "Smooth scrolling for the web", 4 | "main": [ 5 | "build/iscroll.js" 6 | ], 7 | "moduleType": [ 8 | "amd", 9 | "node", 10 | "globals" 11 | ], 12 | "keywords": [ 13 | "scrolling", 14 | "carousel", 15 | "zoom", 16 | "iphone", 17 | "android", 18 | "mobile", 19 | "desktop" 20 | ], 21 | "authors": [ 22 | "Matteo Spinelli <matteo@cubiq.org> (http://cubiq.org)" 23 | ], 24 | "license": "MIT", 25 | "repository": { 26 | "type": "git", 27 | "url": "https://github.com/cubiq/iscroll.git" 28 | }, 29 | "homepage": "http://iscrolljs.com", 30 | "ignore": [ 31 | "**/.*", 32 | "build/*", 33 | "dist/*", 34 | "demos/*", 35 | "*.md", 36 | "*.tmp", 37 | "build.js", 38 | "package.json" 39 | ] 40 | } 41 | -------------------------------------------------------------------------------- /build.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var pkg = require('./package.json'); 4 | var fs = require('fs'); 5 | var hint = require("jshint").JSHINT; 6 | var uglify = require('uglify-js'); 7 | 8 | var banner = '/*! iScroll v' + pkg.version + ' ~ (c) 2008-' + (new Date().getFullYear()) + ' Matteo Spinelli ~ http://cubiq.org/license */\n'; 9 | 10 | var releases = { 11 | lite: { 12 | files: [ 13 | 'default/_animate.js', 14 | 'default/handleEvent.js' 15 | ] 16 | }, 17 | 18 | iscroll: { 19 | files: [ 20 | 'indicator/_initIndicators.js', 21 | 'wheel/wheel.js', 22 | 'snap/snap.js', 23 | 'keys/keys.js', 24 | 'default/_animate.js', 25 | 'default/handleEvent.js', 26 | 'indicator/indicator.js' 27 | ], 28 | postProcessing: [ 'indicator/build.json', 'wheel/build.json', 'snap/build.json', 'keys/build.json' ] 29 | }, 30 | 31 | probe: { 32 | files: [ 33 | 'indicator/_initIndicators.js', 34 | 'wheel/wheel.js', 35 | 'snap/snap.js', 36 | 'keys/keys.js', 37 | 'probe/_animate.js', 38 | 'default/handleEvent.js', 39 | 'indicator/indicator.js' 40 | ], 41 | postProcessing: [ 'indicator/build.json', 'wheel/build.json', 'snap/build.json', 'keys/build.json', 'probe/build.json' ] 42 | }, 43 | 44 | zoom: { 45 | files: [ 46 | 'indicator/_initIndicators.js', 47 | 'zoom/zoom.js', 48 | 'wheel/wheel.js', 49 | 'snap/snap.js', 50 | 'keys/keys.js', 51 | 'default/_animate.js', 52 | 'zoom/handleEvent.js', 53 | 'indicator/indicator.js' 54 | ], 55 | postProcessing: [ 'zoom/build.json', 'indicator/build.json', 'wheel/build.json', 'snap/build.json', 'keys/build.json' ] 56 | }, 57 | 58 | infinite: { 59 | files: [ 60 | 'wheel/wheel.js', 61 | 'snap/snap.js', 62 | 'keys/keys.js', 63 | 'probe/_animate.js', 64 | 'infinite/infinite.js', 65 | 'default/handleEvent.js', 66 | ], 67 | postProcessing: [ 'wheel/build.json', 'snap/build.json', 'keys/build.json', 'infinite/build.json', 'probe/build.json' ] 68 | } 69 | }; 70 | 71 | var args = process.argv.slice(2); 72 | 73 | if ( !args.length ) { 74 | args = ['iscroll']; 75 | } 76 | 77 | if ( args[0] == 'dist' ) { 78 | args = ['lite', 'iscroll', 'zoom', 'probe', 'infinite']; 79 | } 80 | 81 | // Get the list of files 82 | args.forEach(function (release) { 83 | if ( !(release in releases) ) { 84 | console.log('Unrecognized release: ' + release); 85 | return; 86 | } 87 | 88 | console.log('Building release: ' + release); 89 | build(release); 90 | }); 91 | 92 | function build (release) { 93 | var out = ''; 94 | var value = ''; 95 | 96 | var fileList = ['open.js', 'utils.js', 'core.js']; 97 | 98 | fileList = fileList.concat(releases[release].files); 99 | 100 | fileList.push('close.js'); 101 | 102 | // Concatenate files 103 | out = banner + fileList.map(function (filePath) { 104 | return fs.readFileSync('src/' + filePath, 'utf-8'); 105 | }).join(''); 106 | 107 | // Update version 108 | out = out.replace('/* VERSION */', pkg.version); 109 | 110 | // Post processing 111 | if ( releases[release].postProcessing ) { 112 | releases[release].postProcessing.forEach(function (file) { 113 | var postProcessing = require('./src/' + file); 114 | 115 | // Insert point 116 | for ( var i in postProcessing.insert ) { 117 | value = postProcessing.insert[i].substr(postProcessing.insert[i].length-3) == '.js' ? 118 | fs.readFileSync('src/' + postProcessing.insert[i]) : 119 | postProcessing.insert[i]; 120 | 121 | out = out.replace('// INSERT POINT: ' + i, value + '\n\n// INSERT POINT: ' + i ); 122 | } 123 | 124 | // Replace 125 | for ( i in postProcessing.replace ) { 126 | value = postProcessing.replace[i].substr(postProcessing.replace[i].length-3) == '.js' ? 127 | fs.readFileSync('src/' + postProcessing.replace[i]) : 128 | postProcessing.replace[i]; 129 | 130 | var regex = new RegExp('\\/\\* REPLACE START: ' + i + ' \\*\\/[\\s\\S]*\\/\\* REPLACE END: ' + i + ' \\*\\/'); 131 | out = out.replace(regex, '/* REPLACE START: ' + i + ' */' + value + '/* REPLACE END: ' + i + ' */'); 132 | } 133 | }); 134 | } 135 | 136 | // Write build file 137 | var buildFile = './build/iscroll' + (release != 'iscroll' ? '-' + release : '') + '.js'; 138 | fs.writeFileSync(buildFile, out); 139 | 140 | // JSHint 141 | if ( !hint(out) ) { 142 | var lines = out.split('\n'); 143 | hint.errors.forEach(function (err) { 144 | console.log('\033[31m[' + err.code + ']\033[0m ' + err.line + ':' + err.character + '\t- ' + err.reason); 145 | console.log('\033[33m' + lines[err.line-1].replace(/\t/g, ' ') + '\033[0m\n'); 146 | }); 147 | 148 | process.exit(); 149 | } 150 | 151 | // Write dist file 152 | var distFile = buildFile.replace('/build/', '/dist/').replace('.js', '-min.js'); 153 | out = uglify.minify(out, { fromString: true }); 154 | 155 | // Make sure dist folder exists 156 | if ( !fs.existsSync('dist') ) { 157 | fs.mkdirSync('dist'); 158 | } 159 | 160 | // Write files to target 161 | fs.writeFileSync(distFile, banner + out.code); 162 | } 163 | -------------------------------------------------------------------------------- /demos/2d-scroll/index.html: -------------------------------------------------------------------------------- 1 | <!DOCTYPE html> 2 | <html> 3 | <head> 4 | <meta charset="utf-8"> 5 | <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0"> 6 | 7 | <title>iScroll demo: 2d scroll</title> 8 | 9 | <script type="text/javascript" src="../../build/iscroll.js"></script> 10 | <script type="text/javascript" src="../demoUtils.js"></script> 11 | <script type="text/javascript"> 12 | 13 | var myScroll; 14 | 15 | function loaded () { 16 | myScroll = new IScroll('#wrapper', { scrollX: true, freeScroll: true }); 17 | } 18 | 19 | document.addEventListener('touchmove', function (e) { e.preventDefault(); }, isPassive() ? { 20 | capture: false, 21 | passive: false 22 | } : false); 23 | 24 | </script> 25 | 26 | <style type="text/css"> 27 | * { 28 | -webkit-box-sizing: border-box; 29 | -moz-box-sizing: border-box; 30 | box-sizing: border-box; 31 | } 32 | 33 | html { 34 | -ms-touch-action: none; 35 | } 36 | 37 | body,ul,li { 38 | padding: 0; 39 | margin: 0; 40 | border: 0; 41 | } 42 | 43 | body { 44 | font-size: 12px; 45 | font-family: ubuntu, helvetica, arial; 46 | overflow: hidden; /* this is important to prevent the whole page to bounce */ 47 | } 48 | 49 | #header { 50 | position: absolute; 51 | z-index: 2; 52 | top: 0; 53 | left: 0; 54 | width: 100%; 55 | height: 45px; 56 | line-height: 45px; 57 | background: #CD235C; 58 | padding: 0; 59 | color: #eee; 60 | font-size: 20px; 61 | text-align: center; 62 | font-weight: bold; 63 | } 64 | 65 | #footer { 66 | position: absolute; 67 | z-index: 2; 68 | bottom: 0; 69 | left: 0; 70 | width: 100%; 71 | height: 48px; 72 | background: #444; 73 | padding: 0; 74 | border-top: 1px solid #444; 75 | } 76 | 77 | #wrapper { 78 | position: absolute; 79 | z-index: 1; 80 | top: 45px; 81 | bottom: 48px; 82 | left: 0; 83 | width: 100%; 84 | background: #ccc; 85 | overflow: hidden; 86 | } 87 | 88 | #scroller { 89 | position: absolute; 90 | z-index: 1; 91 | -webkit-tap-highlight-color: rgba(0,0,0,0); 92 | width: 2000px; 93 | -webkit-transform: translateZ(0); 94 | -moz-transform: translateZ(0); 95 | -ms-transform: translateZ(0); 96 | -o-transform: translateZ(0); 97 | transform: translateZ(0); 98 | -webkit-touch-callout: none; 99 | -webkit-user-select: none; 100 | -moz-user-select: none; 101 | -ms-user-select: none; 102 | user-select: none; 103 | -webkit-text-size-adjust: none; 104 | -moz-text-size-adjust: none; 105 | -ms-text-size-adjust: none; 106 | -o-text-size-adjust: none; 107 | text-size-adjust: none; 108 | background: #fff; 109 | } 110 | 111 | p { 112 | font-size: 16px; 113 | padding: 1.2em; 114 | line-height: 200%; 115 | } 116 | 117 | </style> 118 | </head> 119 | <body onload="loaded()"> 120 | <div id="header">iScroll</div> 121 | 122 | <div id="wrapper"> 123 | <div id="scroller"> 124 | <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p> 125 | 126 | <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p> 127 | 128 | <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p> 129 | 130 | <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p> 131 | 132 | <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p> 133 | 134 | <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p> 135 | </div> 136 | </div> 137 | 138 | <div id="footer"></div> 139 | 140 | </body> 141 | </html> -------------------------------------------------------------------------------- /demos/barebone/index.html: -------------------------------------------------------------------------------- 1 | <!DOCTYPE html> 2 | <html> 3 | <head> 4 | <meta charset="utf-8"> 5 | <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0"> 6 | 7 | <title>iScroll demo: barebone</title> 8 | 9 | <script type="text/javascript" src="../../build/iscroll.js"></script> 10 | <script type="text/javascript" src="../demoUtils.js"></script> 11 | <script type="text/javascript"> 12 | 13 | var myScroll; 14 | 15 | function loaded () { 16 | myScroll = new IScroll('#wrapper'); 17 | } 18 | 19 | document.addEventListener('touchmove', function (e) { e.preventDefault(); }, isPassive() ? { 20 | capture: false, 21 | passive: false 22 | } : false); 23 | 24 | </script> 25 | 26 | <style> 27 | body { 28 | /* On modern browsers, prevent the whole page to bounce */ 29 | overflow: hidden; 30 | } 31 | 32 | #wrapper { 33 | position: relative; 34 | width: 300px; 35 | height: 300px; 36 | overflow: hidden; 37 | 38 | /* Prevent native touch events on Windows */ 39 | -ms-touch-action: none; 40 | 41 | /* Prevent the callout on tap-hold and text selection */ 42 | -webkit-touch-callout: none; 43 | -webkit-user-select: none; 44 | -moz-user-select: none; 45 | -ms-user-select: none; 46 | user-select: none; 47 | 48 | /* Prevent text resize on orientation change, useful for web-apps */ 49 | -webkit-text-size-adjust: none; 50 | -moz-text-size-adjust: none; 51 | -ms-text-size-adjust: none; 52 | -o-text-size-adjust: none; 53 | text-size-adjust: none; 54 | } 55 | 56 | #scroller { 57 | position: absolute; 58 | 59 | /* Prevent elements to be highlighted on tap */ 60 | -webkit-tap-highlight-color: rgba(0,0,0,0); 61 | 62 | /* Put the scroller into the HW Compositing layer right from the start */ 63 | -webkit-transform: translateZ(0); 64 | -moz-transform: translateZ(0); 65 | -ms-transform: translateZ(0); 66 | -o-transform: translateZ(0); 67 | transform: translateZ(0); 68 | } 69 | </style> 70 | 71 | </head> 72 | <body onload="loaded()"> 73 | 74 | <div id="wrapper"> 75 | <div id="scroller"> 76 | <p><strong>This demo shows the minimum CSS/HTML/JS configuration you need to run the iScroll. Look at the source code for details.</strong></p> 77 | 78 | <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p> 79 | 80 | <p>Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?</p> 81 | 82 | <p>At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat.</p> 83 | </div> 84 | </div> 85 | 86 | </body> 87 | </html> -------------------------------------------------------------------------------- /demos/bounce-easing/index.html: -------------------------------------------------------------------------------- 1 | <!DOCTYPE html> 2 | <html> 3 | <head> 4 | <meta charset="utf-8"> 5 | <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0"> 6 | 7 | <title>iScroll demo: bounce easing</title> 8 | 9 | <script type="text/javascript" src="../../build/iscroll.js"></script> 10 | <script type="text/javascript" src="../demoUtils.js"></script> 11 | <script type="text/javascript"> 12 | 13 | var myScroll; 14 | 15 | function loaded () { 16 | myScroll = new IScroll('#wrapper', { bounceEasing: 'elastic', bounceTime: 1200 }); 17 | } 18 | 19 | document.addEventListener('touchmove', function (e) { e.preventDefault(); }, isPassive() ? { 20 | capture: false, 21 | passive: false 22 | } : false); 23 | 24 | </script> 25 | 26 | <style type="text/css"> 27 | * { 28 | -webkit-box-sizing: border-box; 29 | -moz-box-sizing: border-box; 30 | box-sizing: border-box; 31 | } 32 | 33 | html { 34 | -ms-touch-action: none; 35 | } 36 | 37 | body,ul,li { 38 | padding: 0; 39 | margin: 0; 40 | border: 0; 41 | } 42 | 43 | body { 44 | font-size: 12px; 45 | font-family: ubuntu, helvetica, arial; 46 | overflow: hidden; /* this is important to prevent the whole page to bounce */ 47 | } 48 | 49 | #header { 50 | position: absolute; 51 | z-index: 2; 52 | top: 0; 53 | left: 0; 54 | width: 100%; 55 | height: 45px; 56 | line-height: 45px; 57 | background: #CD235C; 58 | padding: 0; 59 | color: #eee; 60 | font-size: 20px; 61 | text-align: center; 62 | font-weight: bold; 63 | } 64 | 65 | #footer { 66 | position: absolute; 67 | z-index: 2; 68 | bottom: 0; 69 | left: 0; 70 | width: 100%; 71 | height: 48px; 72 | background: #444; 73 | padding: 0; 74 | border-top: 1px solid #444; 75 | } 76 | 77 | #wrapper { 78 | position: absolute; 79 | z-index: 1; 80 | top: 45px; 81 | bottom: 48px; 82 | left: 0; 83 | width: 100%; 84 | background: #ccc; 85 | overflow: hidden; 86 | } 87 | 88 | #scroller { 89 | position: absolute; 90 | z-index: 1; 91 | -webkit-tap-highlight-color: rgba(0,0,0,0); 92 | width: 100%; 93 | -webkit-transform: translateZ(0); 94 | -moz-transform: translateZ(0); 95 | -ms-transform: translateZ(0); 96 | -o-transform: translateZ(0); 97 | transform: translateZ(0); 98 | -webkit-touch-callout: none; 99 | -webkit-user-select: none; 100 | -moz-user-select: none; 101 | -ms-user-select: none; 102 | user-select: none; 103 | -webkit-text-size-adjust: none; 104 | -moz-text-size-adjust: none; 105 | -ms-text-size-adjust: none; 106 | -o-text-size-adjust: none; 107 | text-size-adjust: none; 108 | } 109 | 110 | #scroller ul { 111 | list-style: none; 112 | padding: 0; 113 | margin: 0; 114 | width: 100%; 115 | text-align: left; 116 | } 117 | 118 | #scroller li { 119 | padding: 0 10px; 120 | height: 40px; 121 | line-height: 40px; 122 | border-bottom: 1px solid #ccc; 123 | border-top: 1px solid #fff; 124 | background-color: #fafafa; 125 | font-size: 14px; 126 | } 127 | 128 | </style> 129 | </head> 130 | <body onload="loaded()"> 131 | <div id="header">iScroll</div> 132 | 133 | <div id="wrapper"> 134 | <div id="scroller"> 135 | <ul> 136 | <li>Pretty row 1</li> 137 | <li>Pretty row 2</li> 138 | <li>Pretty row 3</li> 139 | <li>Pretty row 4</li> 140 | <li>Pretty row 5</li> 141 | <li>Pretty row 6</li> 142 | <li>Pretty row 7</li> 143 | <li>Pretty row 8</li> 144 | <li>Pretty row 9</li> 145 | <li>Pretty row 10</li> 146 | <li>Pretty row 11</li> 147 | <li>Pretty row 12</li> 148 | <li>Pretty row 13</li> 149 | <li>Pretty row 14</li> 150 | <li>Pretty row 15</li> 151 | <li>Pretty row 16</li> 152 | <li>Pretty row 17</li> 153 | <li>Pretty row 18</li> 154 | <li>Pretty row 19</li> 155 | <li>Pretty row 20</li> 156 | <li>Pretty row 21</li> 157 | <li>Pretty row 22</li> 158 | <li>Pretty row 23</li> 159 | <li>Pretty row 24</li> 160 | <li>Pretty row 25</li> 161 | <li>Pretty row 26</li> 162 | <li>Pretty row 27</li> 163 | <li>Pretty row 28</li> 164 | <li>Pretty row 29</li> 165 | <li>Pretty row 30</li> 166 | <li>Pretty row 31</li> 167 | <li>Pretty row 32</li> 168 | <li>Pretty row 33</li> 169 | <li>Pretty row 34</li> 170 | <li>Pretty row 35</li> 171 | <li>Pretty row 36</li> 172 | <li>Pretty row 37</li> 173 | <li>Pretty row 38</li> 174 | <li>Pretty row 39</li> 175 | <li>Pretty row 40</li> 176 | <li>Pretty row 41</li> 177 | <li>Pretty row 42</li> 178 | <li>Pretty row 43</li> 179 | <li>Pretty row 44</li> 180 | <li>Pretty row 45</li> 181 | <li>Pretty row 46</li> 182 | <li>Pretty row 47</li> 183 | <li>Pretty row 48</li> 184 | <li>Pretty row 49</li> 185 | <li>Pretty row 50</li> 186 | </ul> 187 | </div> 188 | </div> 189 | 190 | <div id="footer"></div> 191 | 192 | </body> 193 | </html> -------------------------------------------------------------------------------- /demos/carousel/gaugin.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cubiq/iscroll/60ed6f8029b2e097a87399a2b3c688afd596980f/demos/carousel/gaugin.jpg -------------------------------------------------------------------------------- /demos/carousel/giotto.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cubiq/iscroll/60ed6f8029b2e097a87399a2b3c688afd596980f/demos/carousel/giotto.jpg -------------------------------------------------------------------------------- /demos/carousel/index.html: -------------------------------------------------------------------------------- 1 | <!DOCTYPE html> 2 | <html> 3 | <head> 4 | <meta charset="utf-8"> 5 | <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0"> 6 | 7 | <title>iScroll demo: carousel</title> 8 | 9 | <script type="text/javascript" src="../../build/iscroll.js"></script> 10 | <script type="text/javascript" src="../demoUtils.js"></script> 11 | <script type="text/javascript"> 12 | 13 | var myScroll; 14 | 15 | function loaded () { 16 | myScroll = new IScroll('#wrapper', { 17 | scrollX: true, 18 | scrollY: false, 19 | momentum: false, 20 | snap: true, 21 | snapSpeed: 400, 22 | keyBindings: true, 23 | indicators: { 24 | el: document.getElementById('indicator'), 25 | resize: false 26 | } 27 | }); 28 | } 29 | 30 | document.addEventListener('touchmove', function (e) { e.preventDefault(); }, isPassive() ? { 31 | capture: false, 32 | passive: false 33 | } : false); 34 | </script> 35 | 36 | <style type="text/css"> 37 | * { 38 | -webkit-box-sizing: border-box; 39 | -moz-box-sizing: border-box; 40 | box-sizing: border-box; 41 | } 42 | 43 | html { 44 | -ms-touch-action: none; 45 | } 46 | 47 | body, ul, li { 48 | padding: 0; 49 | margin: 0; 50 | border: 0; 51 | } 52 | 53 | body { 54 | font-size: 12px; 55 | font-family: ubuntu, helvetica, arial; 56 | overflow: hidden; /* this is important to prevent the whole page to bounce */ 57 | } 58 | 59 | #viewport { 60 | position: relative; 61 | width: 320px; 62 | height: 240px; 63 | margin: 0 auto; 64 | background: #444; 65 | overflow: hidden; 66 | } 67 | 68 | #wrapper { 69 | width: 200px; 70 | height: 240px; 71 | margin: 0 auto; 72 | } 73 | 74 | #scroller { 75 | position: absolute; 76 | z-index: 1; 77 | -webkit-tap-highlight-color: rgba(0,0,0,0); 78 | width: 800px; 79 | height: 240px; 80 | -webkit-transform: translateZ(0); 81 | -moz-transform: translateZ(0); 82 | -ms-transform: translateZ(0); 83 | -o-transform: translateZ(0); 84 | transform: translateZ(0); 85 | -webkit-touch-callout: none; 86 | -webkit-user-select: none; 87 | -moz-user-select: none; 88 | -ms-user-select: none; 89 | user-select: none; 90 | -webkit-text-size-adjust: none; 91 | -moz-text-size-adjust: none; 92 | -ms-text-size-adjust: none; 93 | -o-text-size-adjust: none; 94 | text-size-adjust: none; 95 | background-color: #444; 96 | } 97 | 98 | .slide { 99 | width: 200px; 100 | height: 240px; 101 | float: left; 102 | } 103 | 104 | .painting { 105 | width: 140px; 106 | height: 200px; 107 | border-radius: 10px; 108 | margin: 20px auto; 109 | border: 1px solid #000; 110 | box-shadow: 111 | inset 2px 2px 6px rgba(255,255,255,0.6), 112 | inset -2px -2px 6px rgba(0,0,0,0.6), 113 | 0 1px 8px rgba(0,0,0,0.8); 114 | } 115 | 116 | .giotto { 117 | background: url(giotto.jpg); 118 | } 119 | 120 | .leonardo { 121 | background: url(leonardo.jpg); 122 | } 123 | 124 | .gaugin { 125 | background: url(gaugin.jpg); 126 | } 127 | 128 | .warhol { 129 | background: url(warhol.jpg); 130 | } 131 | 132 | #indicator { 133 | position: relative; 134 | width: 110px; 135 | height: 20px; 136 | margin: 10px auto; 137 | background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAUBAMAAABohZD3AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3QUGCDYztyDUJgAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAAGFBMVEUAAADNzc3Nzc3Nzc3Nzc3Nzc3Nzc3///8aWwwLAAAABnRSTlMAX5Ks3/nRD0HIAAAAAWJLR0QHFmGI6wAAAFtJREFUGFdjYGBgEHYNMWRAAJE0IHCEc5nSwEABxleD8JOgXMY0KBCA8FlgfAcIXwzGT4TwzWD8ZAjfDcZPgfDDYPxU7Hx09ejmoduH7h5096L7B8O/6OGBGl4APYg8TQ0XAScAAAAASUVORK5CYII=); 138 | } 139 | 140 | #dotty { 141 | position: absolute; 142 | width: 20px; 143 | height: 20px; 144 | border-radius: 10px; 145 | background: #777; 146 | } 147 | 148 | </style> 149 | </head> 150 | <body onload="loaded()"> 151 | 152 | <div id="viewport"> 153 | <div id="wrapper"> 154 | <div id="scroller"> 155 | <div class="slide"> 156 | <div class="painting giotto"></div> 157 | </div> 158 | <div class="slide"> 159 | <div class="painting leonardo"></div> 160 | </div> 161 | <div class="slide"> 162 | <div class="painting gaugin"></div> 163 | </div> 164 | <div class="slide"> 165 | <div class="painting warhol"></div> 166 | </div> 167 | </div> 168 | </div> 169 | </div> 170 | 171 | <div id="indicator"> 172 | <div id="dotty"></div> 173 | </div> 174 | 175 | </body> 176 | </html> -------------------------------------------------------------------------------- /demos/carousel/leonardo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cubiq/iscroll/60ed6f8029b2e097a87399a2b3c688afd596980f/demos/carousel/leonardo.jpg -------------------------------------------------------------------------------- /demos/carousel/warhol.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cubiq/iscroll/60ed6f8029b2e097a87399a2b3c688afd596980f/demos/carousel/warhol.jpg -------------------------------------------------------------------------------- /demos/click/index.html: -------------------------------------------------------------------------------- 1 | <!DOCTYPE html> 2 | <html> 3 | <head> 4 | <meta charset="utf-8"> 5 | <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0"> 6 | 7 | <title>iScroll demo: click</title> 8 | 9 | <script type="text/javascript" src="../../build/iscroll.js"></script> 10 | <script type="text/javascript" src="../demoUtils.js"></script> 11 | <script type="text/javascript"> 12 | 13 | var myScroll; 14 | 15 | function loaded () { 16 | myScroll = new IScroll('#wrapper', { mouseWheel: true, click: true }); 17 | } 18 | 19 | document.addEventListener('touchmove', function (e) { e.preventDefault(); }, isPassive() ? { 20 | capture: false, 21 | passive: false 22 | } : false); 23 | 24 | </script> 25 | 26 | <style type="text/css"> 27 | * { 28 | -webkit-box-sizing: border-box; 29 | -moz-box-sizing: border-box; 30 | box-sizing: border-box; 31 | } 32 | 33 | html { 34 | -ms-touch-action: none; 35 | } 36 | 37 | body,ul,li { 38 | padding: 0; 39 | margin: 0; 40 | border: 0; 41 | } 42 | 43 | body { 44 | font-size: 12px; 45 | font-family: ubuntu, helvetica, arial; 46 | overflow: hidden; /* this is important to prevent the whole page to bounce */ 47 | } 48 | 49 | #header { 50 | position: absolute; 51 | z-index: 2; 52 | top: 0; 53 | left: 0; 54 | width: 100%; 55 | height: 45px; 56 | line-height: 45px; 57 | background: #CD235C; 58 | padding: 0; 59 | color: #eee; 60 | font-size: 20px; 61 | text-align: center; 62 | font-weight: bold; 63 | } 64 | 65 | #footer { 66 | position: absolute; 67 | z-index: 2; 68 | bottom: 0; 69 | left: 0; 70 | width: 100%; 71 | height: 48px; 72 | background: #444; 73 | padding: 0; 74 | border-top: 1px solid #444; 75 | } 76 | 77 | #wrapper { 78 | position: absolute; 79 | z-index: 1; 80 | top: 45px; 81 | bottom: 48px; 82 | left: 0; 83 | width: 100%; 84 | background: #ccc; 85 | overflow: hidden; 86 | } 87 | 88 | #scroller { 89 | position: absolute; 90 | z-index: 1; 91 | -webkit-tap-highlight-color: rgba(0,0,0,0); 92 | width: 100%; 93 | -webkit-transform: translateZ(0); 94 | -moz-transform: translateZ(0); 95 | -ms-transform: translateZ(0); 96 | -o-transform: translateZ(0); 97 | transform: translateZ(0); 98 | -webkit-touch-callout: none; 99 | -webkit-user-select: none; 100 | -moz-user-select: none; 101 | -ms-user-select: none; 102 | user-select: none; 103 | -webkit-text-size-adjust: none; 104 | -moz-text-size-adjust: none; 105 | -ms-text-size-adjust: none; 106 | -o-text-size-adjust: none; 107 | text-size-adjust: none; 108 | } 109 | 110 | #scroller ul { 111 | list-style: none; 112 | padding: 0; 113 | margin: 0; 114 | width: 100%; 115 | text-align: left; 116 | } 117 | 118 | #scroller li { 119 | padding: 0 10px; 120 | height: 40px; 121 | line-height: 40px; 122 | border-bottom: 1px solid #ccc; 123 | border-top: 1px solid #fff; 124 | background-color: #fafafa; 125 | font-size: 14px; 126 | } 127 | 128 | </style> 129 | </head> 130 | <body onload="loaded()"> 131 | <div id="header">iScroll</div> 132 | 133 | <div id="wrapper"> 134 | <div id="scroller"> 135 | <ul> 136 | <li>Pretty row 1</li> 137 | <li>Pretty row 2</li> 138 | <li>Pretty row 3</li> 139 | <li>Pretty row 4</li> 140 | <li>Pretty row 5</li> 141 | <li id="me"><a href="#" onclick="console.log(this.parentNode.style.backgroundColor);this.parentNode.style.backgroundColor=this.parentNode.style.backgroundColor==''?'#a00':'';return false">Click me!</a></li> 142 | <li>Pretty row 7</li> 143 | <li>Pretty row 8</li> 144 | <li>Pretty row 9</li> 145 | <li>Pretty row 10</li> 146 | <li>Pretty row 11</li> 147 | <li>Pretty row 12</li> 148 | <li>Pretty row 13</li> 149 | <li>Pretty row 14</li> 150 | <li>Pretty row 15</li> 151 | <li>Pretty row 16</li> 152 | <li>Pretty row 17</li> 153 | <li>Pretty row 18</li> 154 | <li>Pretty row 19</li> 155 | <li>Pretty row 20</li> 156 | <li>Pretty row 21</li> 157 | <li>Pretty row 22</li> 158 | <li>Pretty row 23</li> 159 | <li>Pretty row 24</li> 160 | <li>Pretty row 25</li> 161 | <li>Pretty row 26</li> 162 | <li>Pretty row 27</li> 163 | <li>Pretty row 28</li> 164 | <li>Pretty row 29</li> 165 | <li>Pretty row 30</li> 166 | <li>Pretty row 31</li> 167 | <li>Pretty row 32</li> 168 | <li>Pretty row 33</li> 169 | <li>Pretty row 34</li> 170 | <li>Pretty row 35</li> 171 | <li>Pretty row 36</li> 172 | <li>Pretty row 37</li> 173 | <li>Pretty row 38</li> 174 | <li>Pretty row 39</li> 175 | <li>Pretty row 40</li> 176 | <li>Pretty row 41</li> 177 | <li>Pretty row 42</li> 178 | <li>Pretty row 43</li> 179 | <li>Pretty row 44</li> 180 | <li>Pretty row 45</li> 181 | <li>Pretty row 46</li> 182 | <li>Pretty row 47</li> 183 | <li>Pretty row 48</li> 184 | <li>Pretty row 49</li> 185 | <li>Pretty row 50</li> 186 | </ul> 187 | </div> 188 | </div> 189 | 190 | <div id="footer"></div> 191 | 192 | </body> 193 | </html> -------------------------------------------------------------------------------- /demos/demoUtils.js: -------------------------------------------------------------------------------- 1 | // ref https://github.com/WICG/EventListenerOptions/pull/30 2 | function isPassive() { 3 | var supportsPassiveOption = false; 4 | try { 5 | addEventListener("test", null, Object.defineProperty({}, 'passive', { 6 | get: function () { 7 | supportsPassiveOption = true; 8 | } 9 | })); 10 | } catch(e) {} 11 | return supportsPassiveOption; 12 | } 13 | -------------------------------------------------------------------------------- /demos/event-passthrough/index.html: -------------------------------------------------------------------------------- 1 | <!DOCTYPE html> 2 | <html> 3 | <head> 4 | <meta charset="utf-8"> 5 | <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0"> 6 | 7 | <title>iScroll demo: Event Passthrough</title> 8 | 9 | <script type="text/javascript" src="../../build/iscroll.js"></script> 10 | 11 | <script type="text/javascript"> 12 | 13 | var myScroll; 14 | 15 | function loaded () { 16 | myScroll = new IScroll('#wrapper', { eventPassthrough: true, scrollX: true, scrollY: false, preventDefault: false }); 17 | } 18 | 19 | </script> 20 | 21 | <style type="text/css"> 22 | * { 23 | -webkit-box-sizing: border-box; 24 | -moz-box-sizing: border-box; 25 | box-sizing: border-box; 26 | } 27 | 28 | body,ul,li { 29 | padding: 0; 30 | margin: 0; 31 | border: 0; 32 | } 33 | 34 | body { 35 | font-size: 12px; 36 | font-family: ubuntu, helvetica, arial; 37 | } 38 | 39 | #header { 40 | width: 100%; 41 | height: 45px; 42 | line-height: 45px; 43 | background: #CD235C; 44 | padding: 0; 45 | color: #eee; 46 | font-size: 20px; 47 | text-align: center; 48 | font-weight: bold; 49 | } 50 | 51 | #wrapper { 52 | position: relative; 53 | z-index: 1; 54 | height: 160px; 55 | width: 100%; 56 | background: #ccc; 57 | overflow: hidden; 58 | -ms-touch-action: none; 59 | } 60 | 61 | #scroller { 62 | position: absolute; 63 | z-index: 1; 64 | -webkit-tap-highlight-color: rgba(0,0,0,0); 65 | width: 2400px; 66 | height: 160px; 67 | -webkit-transform: translateZ(0); 68 | -moz-transform: translateZ(0); 69 | -ms-transform: translateZ(0); 70 | -o-transform: translateZ(0); 71 | transform: translateZ(0); 72 | -webkit-touch-callout: none; 73 | -webkit-user-select: none; 74 | -moz-user-select: none; 75 | -ms-user-select: none; 76 | user-select: none; 77 | -webkit-text-size-adjust: none; 78 | -moz-text-size-adjust: none; 79 | -ms-text-size-adjust: none; 80 | -o-text-size-adjust: none; 81 | text-size-adjust: none; 82 | } 83 | 84 | #scroller ul { 85 | list-style: none; 86 | width: 100%; 87 | padding: 0; 88 | margin: 0; 89 | } 90 | 91 | #scroller li { 92 | width: 120px; 93 | height: 160px; 94 | float: left; 95 | line-height: 160px; 96 | border-right: 1px solid #ccc; 97 | border-bottom: 1px solid #ccc; 98 | background-color: #fafafa; 99 | font-size: 14px; 100 | overflow: hidden; 101 | text-align: center; 102 | } 103 | 104 | p { 105 | font-size: 16px; 106 | padding: 1.2em; 107 | line-height: 200%; 108 | } 109 | 110 | </style> 111 | </head> 112 | <body onload="loaded()"> 113 | <div id="header">iScroll</div> 114 | 115 | <div id="wrapper"> 116 | <div id="scroller"> 117 | <ul> 118 | <li>Pretty cell 1</li> 119 | <li>Pretty cell 2</li> 120 | <li>Pretty cell 3</li> 121 | <li>Pretty cell 4</li> 122 | <li>Pretty cell 5</li> 123 | <li>Pretty cell 6</li> 124 | <li>Pretty cell 7</li> 125 | <li>Pretty cell 8</li> 126 | <li>Pretty cell 9</li> 127 | <li>Pretty cell 10</li> 128 | <li>Pretty cell 11</li> 129 | <li>Pretty cell 12</li> 130 | <li>Pretty cell 13</li> 131 | <li>Pretty cell 14</li> 132 | <li>Pretty cell 15</li> 133 | <li>Pretty cell 16</li> 134 | <li>Pretty cell 17</li> 135 | <li>Pretty cell 18</li> 136 | <li>Pretty cell 19</li> 137 | <li>Pretty cell 20</li> 138 | </ul> 139 | </div> 140 | </div> 141 | 142 | <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p> 143 | 144 | <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p> 145 | 146 | <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p> 147 | 148 | <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p> 149 | 150 | <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p> 151 | 152 | <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p> 153 | 154 | </body> 155 | </html> -------------------------------------------------------------------------------- /demos/forms/index.html: -------------------------------------------------------------------------------- 1 | <!DOCTYPE html> 2 | <html> 3 | <head> 4 | <meta charset="utf-8"> 5 | <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0"> 6 | 7 | <title>iScroll demo: simple</title> 8 | 9 | <script type="text/javascript" src="../../build/iscroll.js"></script> 10 | <script type="text/javascript" src="../demoUtils.js"></script> 11 | <script type="text/javascript"> 12 | 13 | var myScroll; 14 | 15 | function loaded () { 16 | myScroll = new IScroll('#wrapper', { mouseWheel: true }); 17 | } 18 | 19 | document.addEventListener('touchmove', function (e) { e.preventDefault(); }, isPassive() ? { 20 | capture: false, 21 | passive: false 22 | } : false); 23 | 24 | </script> 25 | 26 | <style type="text/css"> 27 | * { 28 | -webkit-box-sizing: border-box; 29 | -moz-box-sizing: border-box; 30 | box-sizing: border-box; 31 | } 32 | 33 | html { 34 | -ms-touch-action: none; 35 | } 36 | 37 | body,ul,li { 38 | padding: 0; 39 | margin: 0; 40 | border: 0; 41 | } 42 | 43 | body { 44 | font-size: 12px; 45 | font-family: ubuntu, helvetica, arial; 46 | overflow: hidden; /* this is important to prevent the whole page to bounce */ 47 | } 48 | 49 | #header { 50 | position: absolute; 51 | z-index: 2; 52 | top: 0; 53 | left: 0; 54 | width: 100%; 55 | height: 45px; 56 | line-height: 45px; 57 | background: #CD235C; 58 | padding: 0; 59 | color: #eee; 60 | font-size: 20px; 61 | text-align: center; 62 | font-weight: bold; 63 | } 64 | 65 | #footer { 66 | position: absolute; 67 | z-index: 2; 68 | bottom: 0; 69 | left: 0; 70 | width: 100%; 71 | height: 48px; 72 | background: #444; 73 | padding: 0; 74 | border-top: 1px solid #444; 75 | } 76 | 77 | #wrapper { 78 | position: absolute; 79 | z-index: 1; 80 | top: 45px; 81 | bottom: 48px; 82 | left: 0; 83 | width: 100%; 84 | background: #ccc; 85 | overflow: hidden; 86 | } 87 | 88 | #scroller { 89 | position: absolute; 90 | z-index: 1; 91 | -webkit-tap-highlight-color: rgba(0,0,0,0); 92 | width: 100%; 93 | -webkit-transform: translateZ(0); 94 | -moz-transform: translateZ(0); 95 | -ms-transform: translateZ(0); 96 | -o-transform: translateZ(0); 97 | transform: translateZ(0); 98 | -webkit-touch-callout: none; 99 | -webkit-user-select: none; 100 | -moz-user-select: none; 101 | -ms-user-select: none; 102 | user-select: none; 103 | -webkit-text-size-adjust: none; 104 | -moz-text-size-adjust: none; 105 | -ms-text-size-adjust: none; 106 | -o-text-size-adjust: none; 107 | text-size-adjust: none; 108 | } 109 | 110 | #scroller ul { 111 | list-style: none; 112 | padding: 0; 113 | margin: 0; 114 | width: 100%; 115 | text-align: left; 116 | } 117 | 118 | #scroller li { 119 | padding: 0 10px; 120 | height: 40px; 121 | line-height: 40px; 122 | border-bottom: 1px solid #ccc; 123 | border-top: 1px solid #fff; 124 | background-color: #fafafa; 125 | font-size: 14px; 126 | } 127 | 128 | </style> 129 | </head> 130 | <body onload="loaded()"> 131 | <div id="header">iScroll</div> 132 | 133 | <div id="wrapper"> 134 | <div id="scroller"> 135 | <ul> 136 | <li>Pretty row 1</li> 137 | <li>Pretty row 2</li> 138 | <li>Pretty row 3</li> 139 | <li>Pretty row 4</li> 140 | <li><input type="text"></li> 141 | <li>Pretty row 6</li> 142 | <li>Pretty row 7</li> 143 | <li>Pretty row 8</li> 144 | <li><input type="checkbox"></li> 145 | <li>Pretty row 10</li> 146 | <li>Pretty row 11</li> 147 | <li>Pretty row 12</li> 148 | <li><input type="radio"></li> 149 | <li>Pretty row 14</li> 150 | <li>Pretty row 15</li> 151 | <li>Pretty row 16</li> 152 | <li><textarea></textarea></li> 153 | <li>Pretty row 18</li> 154 | <li>Pretty row 19</li> 155 | <li>Pretty row 20</li> 156 | <li><select><option>option</option></select></li> 157 | <li>Pretty row 22</li> 158 | <li>Pretty row 23</li> 159 | <li>Pretty row 24</li> 160 | <li>Pretty row 25</li> 161 | <li>Pretty row 26</li> 162 | <li>Pretty row 27</li> 163 | <li>Pretty row 28</li> 164 | <li>Pretty row 29</li> 165 | <li>Pretty row 30</li> 166 | <li>Pretty row 31</li> 167 | <li>Pretty row 32</li> 168 | <li>Pretty row 33</li> 169 | <li>Pretty row 34</li> 170 | <li>Pretty row 35</li> 171 | <li>Pretty row 36</li> 172 | <li>Pretty row 37</li> 173 | <li>Pretty row 38</li> 174 | <li>Pretty row 39</li> 175 | <li>Pretty row 40</li> 176 | <li>Pretty row 41</li> 177 | <li>Pretty row 42</li> 178 | <li>Pretty row 43</li> 179 | <li>Pretty row 44</li> 180 | <li>Pretty row 45</li> 181 | <li>Pretty row 46</li> 182 | <li>Pretty row 47</li> 183 | <li>Pretty row 48</li> 184 | <li>Pretty row 49</li> 185 | <li>Pretty row 50</li> 186 | </ul> 187 | </div> 188 | </div> 189 | 190 | <div id="footer"></div> 191 | 192 | </body> 193 | </html> -------------------------------------------------------------------------------- /demos/horizontal/index.html: -------------------------------------------------------------------------------- 1 | <!DOCTYPE html> 2 | <html> 3 | <head> 4 | <meta charset="utf-8"> 5 | <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0"> 6 | 7 | <title>iScroll demo: horizontal scrolling</title> 8 | 9 | <script type="text/javascript" src="../../build/iscroll.js"></script> 10 | <script type="text/javascript" src="../demoUtils.js"></script> 11 | <script type="text/javascript"> 12 | 13 | var myScroll; 14 | 15 | function loaded () { 16 | myScroll = new IScroll('#wrapper', { scrollX: true, scrollY: false, mouseWheel: true }); 17 | } 18 | 19 | document.addEventListener('touchmove', function (e) { e.preventDefault(); }, isPassive() ? { 20 | capture: false, 21 | passive: false 22 | } : false); 23 | 24 | </script> 25 | 26 | <style type="text/css"> 27 | * { 28 | -webkit-box-sizing: border-box; 29 | -moz-box-sizing: border-box; 30 | box-sizing: border-box; 31 | } 32 | 33 | html { 34 | -ms-touch-action: none; 35 | } 36 | 37 | body,ul,li { 38 | padding: 0; 39 | margin: 0; 40 | border: 0; 41 | } 42 | 43 | body { 44 | font-size: 12px; 45 | font-family: ubuntu, helvetica, arial; 46 | overflow: hidden; /* this is important to prevent the whole page to bounce */ 47 | } 48 | 49 | #header { 50 | position: absolute; 51 | z-index: 2; 52 | top: 0; 53 | left: 0; 54 | width: 100%; 55 | height: 45px; 56 | line-height: 45px; 57 | background: #CD235C; 58 | padding: 0; 59 | color: #eee; 60 | font-size: 20px; 61 | text-align: center; 62 | font-weight: bold; 63 | } 64 | 65 | #footer { 66 | position: absolute; 67 | z-index: 2; 68 | bottom: 0; 69 | left: 0; 70 | width: 100%; 71 | height: 48px; 72 | background: #444; 73 | padding: 0; 74 | border-top: 1px solid #444; 75 | } 76 | 77 | #wrapper { 78 | position: absolute; 79 | z-index: 1; 80 | top: 45px; 81 | bottom: 48px; 82 | left: 0; 83 | width: 100%; 84 | background: #ccc; 85 | overflow: hidden; 86 | } 87 | 88 | #scroller { 89 | position: absolute; 90 | z-index: 1; 91 | -webkit-tap-highlight-color: rgba(0,0,0,0); 92 | width: 5000px; 93 | height: 100%; 94 | background-color: #a00; 95 | -webkit-transform: translateZ(0); 96 | -moz-transform: translateZ(0); 97 | -ms-transform: translateZ(0); 98 | -o-transform: translateZ(0); 99 | transform: translateZ(0); 100 | -webkit-touch-callout: none; 101 | -webkit-user-select: none; 102 | -moz-user-select: none; 103 | -ms-user-select: none; 104 | user-select: none; 105 | -webkit-text-size-adjust: none; 106 | -moz-text-size-adjust: none; 107 | -ms-text-size-adjust: none; 108 | -o-text-size-adjust: none; 109 | text-size-adjust: none; 110 | } 111 | 112 | #scroller ul { 113 | list-style: none; 114 | padding: 0; 115 | margin: 0; 116 | width: 100%; 117 | height: 100%; 118 | text-align: center; 119 | } 120 | 121 | #scroller li { 122 | display: block; 123 | float: left; 124 | width: 100px; 125 | height: 100%; 126 | border-right: 1px solid #ccc; 127 | background-color: #fafafa; 128 | font-size: 14px; 129 | } 130 | 131 | </style> 132 | </head> 133 | <body onload="loaded()"> 134 | <div id="header">iScroll</div> 135 | 136 | <div id="wrapper"> 137 | <div id="scroller"> 138 | <ul> 139 | <li>Cell 1</li> 140 | <li>Cell 2</li> 141 | <li>Cell 3</li> 142 | <li>Cell 4</li> 143 | <li>Cell 5</li> 144 | <li>Cell 6</li> 145 | <li>Cell 7</li> 146 | <li>Cell 8</li> 147 | <li>Cell 9</li> 148 | <li>Cell 10</li> 149 | <li>Cell 11</li> 150 | <li>Cell 12</li> 151 | <li>Cell 13</li> 152 | <li>Cell 14</li> 153 | <li>Cell 15</li> 154 | <li>Cell 16</li> 155 | <li>Cell 17</li> 156 | <li>Cell 18</li> 157 | <li>Cell 19</li> 158 | <li>Cell 20</li> 159 | <li>Cell 21</li> 160 | <li>Cell 22</li> 161 | <li>Cell 23</li> 162 | <li>Cell 24</li> 163 | <li>Cell 25</li> 164 | <li>Cell 26</li> 165 | <li>Cell 27</li> 166 | <li>Cell 28</li> 167 | <li>Cell 29</li> 168 | <li>Cell 30</li> 169 | <li>Cell 31</li> 170 | <li>Cell 32</li> 171 | <li>Cell 33</li> 172 | <li>Cell 34</li> 173 | <li>Cell 35</li> 174 | <li>Cell 36</li> 175 | <li>Cell 37</li> 176 | <li>Cell 38</li> 177 | <li>Cell 39</li> 178 | <li>Cell 40</li> 179 | <li>Cell 41</li> 180 | <li>Cell 42</li> 181 | <li>Cell 43</li> 182 | <li>Cell 44</li> 183 | <li>Cell 45</li> 184 | <li>Cell 46</li> 185 | <li>Cell 47</li> 186 | <li>Cell 48</li> 187 | <li>Cell 49</li> 188 | <li>Cell 50</li> 189 | </ul> 190 | </div> 191 | </div> 192 | 193 | <div id="footer"></div> 194 | 195 | </body> 196 | </html> -------------------------------------------------------------------------------- /demos/infinite/dataset.php: -------------------------------------------------------------------------------- 1 | <?php 2 | //header('Cache-Control: no-cache, must-revalidate'); 3 | //header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); 4 | header('Content-type: application/json'); 5 | 6 | $start = isset($_GET['start']) ? (int)$_GET['start'] : 0; 7 | $count = isset($_GET['count']) ? min((int)$_GET['count'], 2000) : 100; 8 | 9 | $data = array(); 10 | for ( $i = $start; $i < $start+$count; $i++ ) { 11 | $data[] = $i; 12 | } 13 | 14 | echo json_encode($data); 15 | -------------------------------------------------------------------------------- /demos/infinite/index.html: -------------------------------------------------------------------------------- 1 | <!DOCTYPE html> 2 | <html> 3 | <head> 4 | <meta charset="utf-8"> 5 | <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0"> 6 | 7 | <title>iScroll demo: infinite scrolling</title> 8 | 9 | <script type="text/javascript" src="../../build/iscroll-infinite.js"></script> 10 | <script type="text/javascript" src="../demoUtils.js"></script> 11 | <script type="text/javascript"> 12 | /****************************************************************************** 13 | * 14 | * For the sake of keeping the script dependecy free I'm including a custom 15 | * AJAX function. You should probably use a third party plugin 16 | * 17 | */ 18 | function ajax (url, parms) { 19 | parms = parms || {}; 20 | var req = new XMLHttpRequest(), 21 | post = parms.post || null, 22 | callback = parms.callback || null, 23 | timeout = parms.timeout || null; 24 | 25 | req.onreadystatechange = function () { 26 | if ( req.readyState != 4 ) return; 27 | 28 | // Error 29 | if ( req.status != 200 && req.status != 304 ) { 30 | if ( callback ) callback(false); 31 | return; 32 | } 33 | 34 | if ( callback ) callback(req.responseText); 35 | }; 36 | 37 | if ( post ) { 38 | req.open('POST', url, true); 39 | req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); 40 | } else { 41 | req.open('GET', url, true); 42 | } 43 | 44 | req.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); 45 | 46 | req.send(post); 47 | 48 | if ( timeout ) { 49 | setTimeout(function () { 50 | req.onreadystatechange = function () {}; 51 | req.abort(); 52 | if ( callback ) callback(false); 53 | }, timeout); 54 | } 55 | } 56 | /* 57 | *****************************************************************************/ 58 | 59 | var myScroll; 60 | 61 | function loaded () { 62 | myScroll = new IScroll('#wrapper', { 63 | mouseWheel: true, 64 | infiniteElements: '#scroller .row', 65 | //infiniteLimit: 2000, 66 | dataset: requestData, 67 | dataFiller: updateContent, 68 | cacheSize: 1000 69 | }); 70 | } 71 | 72 | function requestData (start, count) { 73 | ajax('dataset.php?start=' + +start + '&count=' + +count, { 74 | callback: function (data) { 75 | data = JSON.parse(data); 76 | myScroll.updateCache(start, data); 77 | } 78 | }); 79 | } 80 | 81 | function updateContent (el, data) { 82 | el.innerHTML = data; 83 | } 84 | 85 | document.addEventListener('touchmove', function (e) { e.preventDefault(); }, isPassive() ? { 86 | capture: false, 87 | passive: false 88 | } : false); 89 | 90 | </script> 91 | 92 | <style type="text/css"> 93 | * { 94 | -webkit-box-sizing: border-box; 95 | -moz-box-sizing: border-box; 96 | box-sizing: border-box; 97 | } 98 | 99 | html { 100 | -ms-touch-action: none; 101 | } 102 | 103 | body,ul,li { 104 | padding: 0; 105 | margin: 0; 106 | border: 0; 107 | } 108 | 109 | body { 110 | font-size: 12px; 111 | font-family: ubuntu, helvetica, arial; 112 | overflow: hidden; /* this is important to prevent the whole page to bounce */ 113 | } 114 | 115 | #header { 116 | position: absolute; 117 | z-index: 2; 118 | top: 0; 119 | left: 0; 120 | width: 100%; 121 | height: 45px; 122 | line-height: 45px; 123 | background: #CD235C; 124 | padding: 0; 125 | color: #eee; 126 | font-size: 20px; 127 | text-align: center; 128 | font-weight: bold; 129 | } 130 | 131 | #footer { 132 | position: absolute; 133 | z-index: 2; 134 | bottom: 0; 135 | left: 0; 136 | width: 100%; 137 | height: 48px; 138 | background: #444; 139 | padding: 0; 140 | border-top: 1px solid #444; 141 | } 142 | 143 | #wrapper { 144 | position: absolute; 145 | z-index: 1; 146 | top: 45px; 147 | bottom: 48px; 148 | left: 0; 149 | width: 100%; 150 | background: #ccc; 151 | overflow: hidden; 152 | } 153 | 154 | #scroller { 155 | position: absolute; 156 | z-index: 1; 157 | -webkit-tap-highlight-color: rgba(0,0,0,0); 158 | width: 100%; 159 | -webkit-transform: translateZ(0); 160 | -moz-transform: translateZ(0); 161 | -ms-transform: translateZ(0); 162 | -o-transform: translateZ(0); 163 | transform: translateZ(0); 164 | -webkit-touch-callout: none; 165 | -webkit-user-select: none; 166 | -moz-user-select: none; 167 | -ms-user-select: none; 168 | user-select: none; 169 | -webkit-text-size-adjust: none; 170 | -moz-text-size-adjust: none; 171 | -ms-text-size-adjust: none; 172 | -o-text-size-adjust: none; 173 | text-size-adjust: none; 174 | } 175 | 176 | #scroller ul { 177 | list-style: none; 178 | padding: 0; 179 | margin: 0; 180 | width: 100%; 181 | text-align: left; 182 | position: relative; 183 | } 184 | 185 | #scroller li { 186 | position: absolute; 187 | width: 100%; 188 | top: 0; 189 | left: 0; 190 | -webkit-transform: translateZ(0); 191 | -moz-transform: translateZ(0); 192 | -ms-transform: translateZ(0); 193 | -o-transform: translateZ(0); 194 | transform: translateZ(0); 195 | padding: 0 10px; 196 | height: 40px; 197 | line-height: 40px; 198 | border-bottom: 1px solid #ccc; 199 | border-top: 1px solid #fff; 200 | background-color: #fafafa; 201 | font-size: 16px; 202 | } 203 | 204 | </style> 205 | </head> 206 | <body onload="loaded()"> 207 | <div id="header">iScroll</div> 208 | 209 | <div id="wrapper"> 210 | <div id="scroller"> 211 | <ul> 212 | <li class="row">Row 1</li> 213 | <li class="row">Row 2</li> 214 | <li class="row">Row 3</li> 215 | <li class="row">Row 4</li> 216 | <li class="row">Row 5</li> 217 | <li class="row">Row 6</li> 218 | <li class="row">Row 7</li> 219 | <li class="row">Row 8</li> 220 | <li class="row">Row 9</li> 221 | <li class="row">Row 10</li> 222 | <li class="row">Row 11</li> 223 | <li class="row">Row 12</li> 224 | <li class="row">Row 13</li> 225 | <li class="row">Row 14</li> 226 | <li class="row">Row 15</li> 227 | 228 | <li class="row">Row 16</li> 229 | <li class="row">Row 17</li> 230 | <li class="row">Row 18</li> 231 | <li class="row">Row 19</li> 232 | <li class="row">Row 20</li> 233 | <li class="row">Row 21</li> 234 | <li class="row">Row 22</li> 235 | <li class="row">Row 23</li> 236 | <li class="row">Row 24</li> 237 | <li class="row">Row 25</li> 238 | <li class="row">Row 26</li> 239 | <li class="row">Row 27</li> 240 | <li class="row">Row 28</li> 241 | <li class="row">Row 29</li> 242 | <li class="row">Row 30</li> 243 | </ul> 244 | </div> 245 | </div> 246 | 247 | <div id="footer"></div> 248 | 249 | </body> 250 | </html> -------------------------------------------------------------------------------- /demos/key-bindings/index.html: -------------------------------------------------------------------------------- 1 | <!DOCTYPE html> 2 | <html> 3 | <head> 4 | <meta charset="utf-8"> 5 | <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0"> 6 | 7 | <title>iScroll demo: key bindings</title> 8 | 9 | <script type="text/javascript" src="../../build/iscroll.js"></script> 10 | <script type="text/javascript" src="../demoUtils.js"></script> 11 | <script type="text/javascript"> 12 | 13 | var myScroll; 14 | 15 | function loaded () { 16 | myScroll = new IScroll('#wrapper', { keyBindings: true }); 17 | } 18 | 19 | document.addEventListener('touchmove', function (e) { e.preventDefault(); }, isPassive() ? { 20 | capture: false, 21 | passive: false 22 | } : false); 23 | 24 | </script> 25 | 26 | <style type="text/css"> 27 | * { 28 | -webkit-box-sizing: border-box; 29 | -moz-box-sizing: border-box; 30 | box-sizing: border-box; 31 | } 32 | 33 | html { 34 | -ms-touch-action: none; 35 | } 36 | 37 | body,ul,li { 38 | padding: 0; 39 | margin: 0; 40 | border: 0; 41 | } 42 | 43 | body { 44 | font-size: 12px; 45 | font-family: ubuntu, helvetica, arial; 46 | overflow: hidden; /* this is important to prevent the whole page to bounce */ 47 | } 48 | 49 | #header { 50 | position: absolute; 51 | z-index: 2; 52 | top: 0; 53 | left: 0; 54 | width: 100%; 55 | height: 45px; 56 | line-height: 45px; 57 | background: #CD235C; 58 | padding: 0; 59 | color: #eee; 60 | font-size: 20px; 61 | text-align: center; 62 | font-weight: bold; 63 | } 64 | 65 | #footer { 66 | position: absolute; 67 | z-index: 2; 68 | bottom: 0; 69 | left: 0; 70 | width: 100%; 71 | height: 48px; 72 | background: #444; 73 | padding: 0; 74 | border-top: 1px solid #444; 75 | } 76 | 77 | #wrapper { 78 | position: absolute; 79 | z-index: 1; 80 | top: 45px; 81 | bottom: 48px; 82 | left: 0; 83 | width: 100%; 84 | background: #ccc; 85 | overflow: hidden; 86 | } 87 | 88 | #scroller { 89 | position: absolute; 90 | z-index: 1; 91 | -webkit-tap-highlight-color: rgba(0,0,0,0); 92 | width: 100%; 93 | -webkit-transform: translateZ(0); 94 | -moz-transform: translateZ(0); 95 | -ms-transform: translateZ(0); 96 | -o-transform: translateZ(0); 97 | transform: translateZ(0); 98 | -webkit-touch-callout: none; 99 | -webkit-user-select: none; 100 | -moz-user-select: none; 101 | -ms-user-select: none; 102 | user-select: none; 103 | -webkit-text-size-adjust: none; 104 | -moz-text-size-adjust: none; 105 | -ms-text-size-adjust: none; 106 | -o-text-size-adjust: none; 107 | text-size-adjust: none; 108 | } 109 | 110 | #scroller ul { 111 | list-style: none; 112 | padding: 0; 113 | margin: 0; 114 | width: 100%; 115 | text-align: left; 116 | } 117 | 118 | #scroller li { 119 | padding: 0 10px; 120 | height: 40px; 121 | line-height: 40px; 122 | border-bottom: 1px solid #ccc; 123 | border-top: 1px solid #fff; 124 | background-color: #fafafa; 125 | font-size: 14px; 126 | } 127 | 128 | </style> 129 | </head> 130 | <body onload="loaded()"> 131 | <div id="header">iScroll</div> 132 | 133 | <div id="wrapper"> 134 | <div id="scroller"> 135 | <ul> 136 | <li>Pretty row 1</li> 137 | <li>Pretty row 2</li> 138 | <li>Pretty row 3</li> 139 | <li>Pretty row 4</li> 140 | <li>Pretty row 5</li> 141 | <li>Pretty row 6</li> 142 | <li>Pretty row 7</li> 143 | <li>Pretty row 8</li> 144 | <li>Pretty row 9</li> 145 | <li>Pretty row 10</li> 146 | <li>Pretty row 11</li> 147 | <li>Pretty row 12</li> 148 | <li>Pretty row 13</li> 149 | <li>Pretty row 14</li> 150 | <li>Pretty row 15</li> 151 | <li>Pretty row 16</li> 152 | <li>Pretty row 17</li> 153 | <li>Pretty row 18</li> 154 | <li>Pretty row 19</li> 155 | <li>Pretty row 20</li> 156 | <li>Pretty row 21</li> 157 | <li>Pretty row 22</li> 158 | <li>Pretty row 23</li> 159 | <li>Pretty row 24</li> 160 | <li>Pretty row 25</li> 161 | <li>Pretty row 26</li> 162 | <li>Pretty row 27</li> 163 | <li>Pretty row 28</li> 164 | <li>Pretty row 29</li> 165 | <li>Pretty row 30</li> 166 | <li>Pretty row 31</li> 167 | <li>Pretty row 32</li> 168 | <li>Pretty row 33</li> 169 | <li>Pretty row 34</li> 170 | <li>Pretty row 35</li> 171 | <li>Pretty row 36</li> 172 | <li>Pretty row 37</li> 173 | <li>Pretty row 38</li> 174 | <li>Pretty row 39</li> 175 | <li>Pretty row 40</li> 176 | <li>Pretty row 41</li> 177 | <li>Pretty row 42</li> 178 | <li>Pretty row 43</li> 179 | <li>Pretty row 44</li> 180 | <li>Pretty row 45</li> 181 | <li>Pretty row 46</li> 182 | <li>Pretty row 47</li> 183 | <li>Pretty row 48</li> 184 | <li>Pretty row 49</li> 185 | <li>Pretty row 50</li> 186 | </ul> 187 | </div> 188 | </div> 189 | 190 | <div id="footer"></div> 191 | 192 | </body> 193 | </html> -------------------------------------------------------------------------------- /demos/minimap/ermine.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cubiq/iscroll/60ed6f8029b2e097a87399a2b3c688afd596980f/demos/minimap/ermine.jpg -------------------------------------------------------------------------------- /demos/minimap/index.html: -------------------------------------------------------------------------------- 1 | <!DOCTYPE html> 2 | <html> 3 | <head> 4 | <meta charset="utf-8"> 5 | <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0"> 6 | 7 | <title>iScroll demo: minimap</title> 8 | 9 | <script type="text/javascript" src="../../build/iscroll.js"></script> 10 | <!--<script type="text/javascript" src="../demoUtils.js"></script>--> 11 | <script type="text/javascript"> 12 | 13 | var myScroll; 14 | 15 | function loaded () { 16 | myScroll = new IScroll('#wrapper', { 17 | startX: -359, 18 | startY: -85, 19 | scrollY: true, 20 | scrollX: true, 21 | freeScroll: true, 22 | mouseWheel: true, 23 | indicators: { 24 | el: document.getElementById('minimap'), 25 | interactive: true 26 | } 27 | }); 28 | } 29 | 30 | // document.addEventListener('touchmove', function (e) { e.preventDefault(); }, isPassive() ? { 31 | // capture: false, 32 | // passive: false 33 | // } : false); 34 | 35 | </script> 36 | 37 | <style type="text/css"> 38 | * { 39 | -webkit-box-sizing: border-box; 40 | -moz-box-sizing: border-box; 41 | box-sizing: border-box; 42 | } 43 | 44 | html { 45 | -ms-touch-action: none; 46 | } 47 | 48 | body,ul,li { 49 | padding: 0; 50 | margin: 0; 51 | border: 0; 52 | } 53 | 54 | body { 55 | font-size: 12px; 56 | font-family: ubuntu, helvetica, arial; 57 | overflow: hidden; /* this is important to prevent the whole page to bounce */ 58 | } 59 | 60 | #header { 61 | position: absolute; 62 | z-index: 2; 63 | top: 0; 64 | left: 0; 65 | width: 100%; 66 | height: 45px; 67 | line-height: 45px; 68 | background: #CD235C; 69 | padding: 0; 70 | color: #eee; 71 | font-size: 20px; 72 | text-align: center; 73 | font-weight: bold; 74 | } 75 | 76 | #footer { 77 | position: absolute; 78 | z-index: 2; 79 | bottom: 0; 80 | left: 0; 81 | width: 100%; 82 | height: 48px; 83 | background: #444; 84 | padding: 0; 85 | border-top: 1px solid #444; 86 | } 87 | 88 | #wrapper { 89 | position: absolute; 90 | z-index: 1; 91 | width: 235px; 92 | height: 321px; 93 | top: 0; 94 | left: 0; 95 | background: #555; 96 | overflow: hidden; 97 | } 98 | 99 | #scroller { 100 | position: absolute; 101 | z-index: 1; 102 | width: 797px; 103 | height: 1087px; 104 | background: url(ermine.jpg); 105 | -webkit-tap-highlight-color: rgba(0,0,0,0); 106 | -webkit-transform: translateZ(0); 107 | -moz-transform: translateZ(0); 108 | -ms-transform: translateZ(0); 109 | -o-transform: translateZ(0); 110 | transform: translateZ(0); 111 | -webkit-touch-callout: none; 112 | -webkit-user-select: none; 113 | -moz-user-select: none; 114 | -ms-user-select: none; 115 | user-select: none; 116 | -webkit-text-size-adjust: none; 117 | -moz-text-size-adjust: none; 118 | -ms-text-size-adjust: none; 119 | -o-text-size-adjust: none; 120 | text-size-adjust: none; 121 | } 122 | 123 | #minimap { 124 | position: absolute; 125 | z-index: 1; 126 | width: 235px; 127 | height: 321px; 128 | background: url(ermine.jpg); 129 | background-size: 235px 321px; 130 | top: 0px; 131 | left: 245px; 132 | } 133 | 134 | #minimap-indicator { 135 | position: absolute; 136 | z-index: 1; 137 | border: 1px solid #fe0; 138 | box-shadow: 0 0 5px #000; 139 | background: rgba(255,255,255,0.15); 140 | -webkit-transform: translateZ(0); 141 | -moz-transform: translateZ(0); 142 | -ms-transform: translateZ(0); 143 | -o-transform: translateZ(0); 144 | transform: translateZ(0); 145 | } 146 | 147 | #bookmarks { 148 | position: absolute; 149 | left: 520px; 150 | font-size: 1.4em; 151 | } 152 | 153 | #bookmarks li { 154 | margin: 5px 0; 155 | } 156 | 157 | </style> 158 | </head> 159 | <body onload="loaded()"> 160 | 161 | <div id="wrapper"> 162 | <div id="scroller"></div> 163 | </div> 164 | 165 | <div id="minimap"> 166 | <div id="minimap-indicator"></div> 167 | </div> 168 | 169 | <ul id="bookmarks"> 170 | <li><a href="javascript:myScroll.scrollTo(-359, -85, 400, IScroll.utils.ease.back)">Face</a></li> 171 | <li><a href="javascript:myScroll.scrollTo(-288, -342, 400, IScroll.utils.ease.back)">Necklace</a></li> 172 | <li><a href="javascript:myScroll.scrollTo(-264, -658, 400, IScroll.utils.ease.back)">Hand</a></li> 173 | <li><a href="javascript:myScroll.scrollTo(-383, -539, 400, IScroll.utils.ease.back)">Ermine</a></li> 174 | </ul> 175 | 176 | </body> 177 | </html> -------------------------------------------------------------------------------- /demos/no-transition/index.html: -------------------------------------------------------------------------------- 1 | <!DOCTYPE html> 2 | <html> 3 | <head> 4 | <meta charset="utf-8"> 5 | <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0"> 6 | 7 | <title>iScroll demo: No transition</title> 8 | 9 | <script type="text/javascript" src="../../build/iscroll.js"></script> 10 | <script type="text/javascript" src="../demoUtils.js"></script> 11 | <script type="text/javascript"> 12 | 13 | var myScroll; 14 | 15 | function loaded () { 16 | myScroll = new IScroll('#wrapper', { useTransition: false }); 17 | } 18 | 19 | document.addEventListener('touchmove', function (e) { e.preventDefault(); }, isPassive() ? { 20 | capture: false, 21 | passive: false 22 | } : false); 23 | 24 | </script> 25 | 26 | <style type="text/css"> 27 | * { 28 | -webkit-box-sizing: border-box; 29 | -moz-box-sizing: border-box; 30 | box-sizing: border-box; 31 | } 32 | 33 | html { 34 | -ms-touch-action: none; 35 | } 36 | 37 | body,ul,li { 38 | padding: 0; 39 | margin: 0; 40 | border: 0; 41 | } 42 | 43 | body { 44 | font-size: 12px; 45 | font-family: ubuntu, helvetica, arial; 46 | overflow: hidden; /* this is important to prevent the whole page to bounce */ 47 | } 48 | 49 | #header { 50 | position: absolute; 51 | z-index: 2; 52 | top: 0; 53 | left: 0; 54 | width: 100%; 55 | height: 45px; 56 | line-height: 45px; 57 | background: #CD235C; 58 | padding: 0; 59 | color: #eee; 60 | font-size: 20px; 61 | text-align: center; 62 | font-weight: bold; 63 | } 64 | 65 | #footer { 66 | position: absolute; 67 | z-index: 2; 68 | bottom: 0; 69 | left: 0; 70 | width: 100%; 71 | height: 48px; 72 | background: #444; 73 | padding: 0; 74 | border-top: 1px solid #444; 75 | } 76 | 77 | #wrapper { 78 | position: absolute; 79 | z-index: 1; 80 | top: 45px; 81 | bottom: 48px; 82 | left: 0; 83 | width: 100%; 84 | background: #ccc; 85 | overflow: hidden; 86 | -webkit-touch-callout: none; 87 | -webkit-user-select: none; 88 | -moz-user-select: none; 89 | -ms-user-select: none; 90 | user-select: none; 91 | -webkit-text-size-adjust: none; 92 | -moz-text-size-adjust: none; 93 | -ms-text-size-adjust: none; 94 | -o-text-size-adjust: none; 95 | text-size-adjust: none; 96 | } 97 | 98 | #scroller { 99 | position: absolute; 100 | z-index: 1; 101 | -webkit-tap-highlight-color: rgba(0,0,0,0); 102 | width: 100%; 103 | -webkit-transform: translateZ(0); 104 | -moz-transform: translateZ(0); 105 | -ms-transform: translateZ(0); 106 | -o-transform: translateZ(0); 107 | transform: translateZ(0); 108 | } 109 | 110 | #scroller ul { 111 | list-style: none; 112 | padding: 0; 113 | margin: 0; 114 | width: 100%; 115 | text-align: left; 116 | } 117 | 118 | #scroller li { 119 | padding: 0 10px; 120 | height: 40px; 121 | line-height: 40px; 122 | border-bottom: 1px solid #ccc; 123 | border-top: 1px solid #fff; 124 | background-color: #fafafa; 125 | font-size: 14px; 126 | } 127 | 128 | </style> 129 | </head> 130 | <body onload="loaded()"> 131 | <div id="header">iScroll</div> 132 | 133 | <div id="wrapper"> 134 | <div id="scroller"> 135 | <ul> 136 | <li>Pretty row 1</li> 137 | <li>Pretty row 2</li> 138 | <li>Pretty row 3</li> 139 | <li>Pretty row 4</li> 140 | <li>Pretty row 5</li> 141 | <li>Pretty row 6</li> 142 | <li>Pretty row 7</li> 143 | <li>Pretty row 8</li> 144 | <li>Pretty row 9</li> 145 | <li>Pretty row 10</li> 146 | <li>Pretty row 11</li> 147 | <li>Pretty row 12</li> 148 | <li>Pretty row 13</li> 149 | <li>Pretty row 14</li> 150 | <li>Pretty row 15</li> 151 | <li>Pretty row 16</li> 152 | <li>Pretty row 17</li> 153 | <li>Pretty row 18</li> 154 | <li>Pretty row 19</li> 155 | <li>Pretty row 20</li> 156 | <li>Pretty row 21</li> 157 | <li>Pretty row 22</li> 158 | <li>Pretty row 23</li> 159 | <li>Pretty row 24</li> 160 | <li>Pretty row 25</li> 161 | <li>Pretty row 26</li> 162 | <li>Pretty row 27</li> 163 | <li>Pretty row 28</li> 164 | <li>Pretty row 29</li> 165 | <li>Pretty row 30</li> 166 | <li>Pretty row 31</li> 167 | <li>Pretty row 32</li> 168 | <li>Pretty row 33</li> 169 | <li>Pretty row 34</li> 170 | <li>Pretty row 35</li> 171 | <li>Pretty row 36</li> 172 | <li>Pretty row 37</li> 173 | <li>Pretty row 38</li> 174 | <li>Pretty row 39</li> 175 | <li>Pretty row 40</li> 176 | <li>Pretty row 41</li> 177 | <li>Pretty row 42</li> 178 | <li>Pretty row 43</li> 179 | <li>Pretty row 44</li> 180 | <li>Pretty row 45</li> 181 | <li>Pretty row 46</li> 182 | <li>Pretty row 47</li> 183 | <li>Pretty row 48</li> 184 | <li>Pretty row 49</li> 185 | <li>Pretty row 50</li> 186 | </ul> 187 | </div> 188 | </div> 189 | 190 | <div id="footer"></div> 191 | 192 | </body> 193 | </html> -------------------------------------------------------------------------------- /demos/parallax/galaxies1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cubiq/iscroll/60ed6f8029b2e097a87399a2b3c688afd596980f/demos/parallax/galaxies1.png -------------------------------------------------------------------------------- /demos/parallax/galaxies2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cubiq/iscroll/60ed6f8029b2e097a87399a2b3c688afd596980f/demos/parallax/galaxies2.png -------------------------------------------------------------------------------- /demos/parallax/index.html: -------------------------------------------------------------------------------- 1 | <!DOCTYPE html> 2 | <html> 3 | <head> 4 | <meta charset="utf-8"> 5 | <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0"> 6 | 7 | <title>iScroll demo: starfield</title> 8 | 9 | <script type="text/javascript" src="../../build/iscroll.js"></script> 10 | <script type="text/javascript" src="../demoUtils.js"></script> 11 | <script type="text/javascript"> 12 | 13 | var myScroll; 14 | 15 | function loaded () { 16 | myScroll = new IScroll('#wrapper', { 17 | mouseWheel: true, 18 | indicators: [{ 19 | el: document.getElementById('starfield1'), 20 | resize: false, 21 | ignoreBoundaries: true, 22 | speedRatioY: 0.4 23 | }, { 24 | el: document.getElementById('starfield2'), 25 | resize: false, 26 | ignoreBoundaries: true, 27 | speedRatioY: 0.2 28 | }] 29 | }); 30 | } 31 | 32 | document.addEventListener('touchmove', function (e) { e.preventDefault(); }, isPassive() ? { 33 | capture: false, 34 | passive: false 35 | } : false); 36 | 37 | </script> 38 | 39 | <style type="text/css"> 40 | * { 41 | -webkit-box-sizing: border-box; 42 | -moz-box-sizing: border-box; 43 | box-sizing: border-box; 44 | } 45 | 46 | html { 47 | -ms-touch-action: none; 48 | } 49 | 50 | body,ul,li { 51 | padding: 0; 52 | margin: 0; 53 | border: 0; 54 | } 55 | 56 | body { 57 | font-size: 12px; 58 | font-family: ubuntu, helvetica, arial; 59 | overflow: hidden; /* this is important to prevent the whole page to bounce */ 60 | background: #000; 61 | } 62 | 63 | #wrapper { 64 | position: absolute; 65 | z-index: 3; 66 | width: 100%; 67 | top: 0; 68 | bottom: 0; 69 | left: 0; 70 | overflow: hidden; 71 | } 72 | 73 | #scroller { 74 | position: absolute; 75 | z-index: 3; 76 | width: 100%; 77 | height: 4000px; 78 | overflow: hidden; 79 | -webkit-tap-highlight-color: rgba(0,0,0,0); 80 | -webkit-transform: translateZ(0); 81 | -moz-transform: translateZ(0); 82 | -ms-transform: translateZ(0); 83 | -o-transform: translateZ(0); 84 | transform: translateZ(0); 85 | -webkit-touch-callout: none; 86 | -webkit-user-select: none; 87 | -moz-user-select: none; 88 | -ms-user-select: none; 89 | user-select: none; 90 | -webkit-text-size-adjust: none; 91 | -moz-text-size-adjust: none; 92 | -ms-text-size-adjust: none; 93 | -o-text-size-adjust: none; 94 | text-size-adjust: none; 95 | background: url(galaxies1.png); 96 | } 97 | 98 | .starfield { 99 | position: absolute; 100 | width: 100%; 101 | top: 0; 102 | left: 0; 103 | bottom: 0; 104 | overflow: hidden; 105 | } 106 | 107 | .starfield div { 108 | position: absolute; 109 | width: 100%; 110 | overflow: hidden; 111 | -webkit-transform: translateZ(0); 112 | -moz-transform: translateZ(0); 113 | -ms-transform: translateZ(0); 114 | -o-transform: translateZ(0); 115 | transform: translateZ(0); 116 | } 117 | 118 | #starfield1 { 119 | z-index: 2; 120 | } 121 | 122 | #stars1 { 123 | z-index: 2; 124 | height: 3000px; 125 | background: url(galaxies2.png); 126 | } 127 | 128 | #starfield2 { 129 | z-index: 1; 130 | } 131 | 132 | #stars2 { 133 | z-index: 1; 134 | height: 2000px; 135 | background: url(stars.jpg); 136 | } 137 | 138 | </style> 139 | </head> 140 | <body onload="loaded()"> 141 | 142 | <div id="wrapper"> 143 | <div id="scroller"></div> 144 | </div> 145 | 146 | <div class="starfield" id="starfield1"> 147 | <div id="stars1"></div> 148 | </div> 149 | 150 | <div class="starfield" id="starfield2"> 151 | <div id="stars2"></div> 152 | </div> 153 | 154 | </body> 155 | </html> -------------------------------------------------------------------------------- /demos/parallax/stars.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cubiq/iscroll/60ed6f8029b2e097a87399a2b3c688afd596980f/demos/parallax/stars.jpg -------------------------------------------------------------------------------- /demos/probe/index.html: -------------------------------------------------------------------------------- 1 | <!DOCTYPE html> 2 | <html> 3 | <head> 4 | <meta charset="utf-8"> 5 | <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0"> 6 | 7 | <title>iScroll demo: probe</title> 8 | 9 | <script type="text/javascript" src="../../build/iscroll-probe.js"></script> 10 | <script type="text/javascript" src="../demoUtils.js"></script> 11 | <script type="text/javascript"> 12 | 13 | var myScroll; 14 | var position; 15 | 16 | function updatePosition () { 17 | position.innerHTML = this.y>>0; 18 | } 19 | 20 | function loaded () { 21 | position = document.getElementById('position'); 22 | 23 | myScroll = new IScroll('#wrapper', { probeType: 3, mouseWheel: true }); 24 | 25 | myScroll.on('scroll', updatePosition); 26 | myScroll.on('scrollEnd', updatePosition); 27 | } 28 | 29 | document.addEventListener('touchmove', function (e) { e.preventDefault(); }, isPassive() ? { 30 | capture: false, 31 | passive: false 32 | } : false); 33 | 34 | </script> 35 | 36 | <style type="text/css"> 37 | * { 38 | -webkit-box-sizing: border-box; 39 | -moz-box-sizing: border-box; 40 | box-sizing: border-box; 41 | } 42 | 43 | html { 44 | -ms-touch-action: none; 45 | } 46 | 47 | body,ul,li { 48 | padding: 0; 49 | margin: 0; 50 | border: 0; 51 | } 52 | 53 | body { 54 | font-size: 12px; 55 | font-family: ubuntu, helvetica, arial; 56 | overflow: hidden; /* this is important to prevent the whole page to bounce */ 57 | } 58 | 59 | #wrapper { 60 | position: absolute; 61 | z-index: 1; 62 | top: 0; 63 | bottom: 0; 64 | left: 0; 65 | width: 50%; 66 | background: #ccc; 67 | overflow: hidden; 68 | } 69 | 70 | #scroller { 71 | position: absolute; 72 | z-index: 1; 73 | -webkit-tap-highlight-color: rgba(0,0,0,0); 74 | width: 100%; 75 | -webkit-transform: translateZ(0); 76 | -moz-transform: translateZ(0); 77 | -ms-transform: translateZ(0); 78 | -o-transform: translateZ(0); 79 | transform: translateZ(0); 80 | -webkit-touch-callout: none; 81 | -webkit-user-select: none; 82 | -moz-user-select: none; 83 | -ms-user-select: none; 84 | user-select: none; 85 | -webkit-text-size-adjust: none; 86 | -moz-text-size-adjust: none; 87 | -ms-text-size-adjust: none; 88 | -o-text-size-adjust: none; 89 | text-size-adjust: none; 90 | } 91 | 92 | #scroller ul { 93 | list-style: none; 94 | padding: 0; 95 | margin: 0; 96 | width: 100%; 97 | text-align: left; 98 | } 99 | 100 | #scroller li { 101 | padding: 0 10px; 102 | height: 40px; 103 | line-height: 40px; 104 | border-bottom: 1px solid #ccc; 105 | border-top: 1px solid #fff; 106 | background-color: #fafafa; 107 | font-size: 14px; 108 | } 109 | 110 | #monitor { 111 | position: absolute; 112 | left: 51%; 113 | } 114 | 115 | </style> 116 | </head> 117 | <body onload="loaded()"> 118 | 119 | <div id="monitor">Y position: <strong id="position">0</strong></div> 120 | 121 | <div id="wrapper"> 122 | <div id="scroller"> 123 | <ul> 124 | <li>Pretty row 1</li> 125 | <li>Pretty row 2</li> 126 | <li>Pretty row 3</li> 127 | <li>Pretty row 4</li> 128 | <li>Pretty row 5</li> 129 | <li>Pretty row 6</li> 130 | <li>Pretty row 7</li> 131 | <li>Pretty row 8</li> 132 | <li>Pretty row 9</li> 133 | <li>Pretty row 10</li> 134 | <li>Pretty row 11</li> 135 | <li>Pretty row 12</li> 136 | <li>Pretty row 13</li> 137 | <li>Pretty row 14</li> 138 | <li>Pretty row 15</li> 139 | <li>Pretty row 16</li> 140 | <li>Pretty row 17</li> 141 | <li>Pretty row 18</li> 142 | <li>Pretty row 19</li> 143 | <li>Pretty row 20</li> 144 | <li>Pretty row 21</li> 145 | <li>Pretty row 22</li> 146 | <li>Pretty row 23</li> 147 | <li>Pretty row 24</li> 148 | <li>Pretty row 25</li> 149 | <li>Pretty row 26</li> 150 | <li>Pretty row 27</li> 151 | <li>Pretty row 28</li> 152 | <li>Pretty row 29</li> 153 | <li>Pretty row 30</li> 154 | <li>Pretty row 31</li> 155 | <li>Pretty row 32</li> 156 | <li>Pretty row 33</li> 157 | <li>Pretty row 34</li> 158 | <li>Pretty row 35</li> 159 | <li>Pretty row 36</li> 160 | <li>Pretty row 37</li> 161 | <li>Pretty row 38</li> 162 | <li>Pretty row 39</li> 163 | <li>Pretty row 40</li> 164 | <li>Pretty row 41</li> 165 | <li>Pretty row 42</li> 166 | <li>Pretty row 43</li> 167 | <li>Pretty row 44</li> 168 | <li>Pretty row 45</li> 169 | <li>Pretty row 46</li> 170 | <li>Pretty row 47</li> 171 | <li>Pretty row 48</li> 172 | <li>Pretty row 49</li> 173 | <li>Pretty row 50</li> 174 | </ul> 175 | </div> 176 | </div> 177 | 178 | </body> 179 | </html> -------------------------------------------------------------------------------- /demos/scroll-to-element/index.html: -------------------------------------------------------------------------------- 1 | <!DOCTYPE html> 2 | <html> 3 | <head> 4 | <meta charset="utf-8"> 5 | <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0"> 6 | 7 | <title>iScroll demo: scroll to element</title> 8 | 9 | <script type="text/javascript" src="../../build/iscroll.js"></script> 10 | <script type="text/javascript" src="../demoUtils.js"></script> 11 | <script type="text/javascript"> 12 | 13 | var myScroll; 14 | 15 | function loaded () { 16 | myScroll = new IScroll('#wrapper', { mouseWheel: true, click: true }); 17 | } 18 | 19 | document.addEventListener('touchmove', function (e) { e.preventDefault(); }, isPassive() ? { 20 | capture: false, 21 | passive: false 22 | } : false); 23 | 24 | </script> 25 | 26 | <style type="text/css"> 27 | * { 28 | -webkit-box-sizing: border-box; 29 | -moz-box-sizing: border-box; 30 | box-sizing: border-box; 31 | } 32 | 33 | html { 34 | -ms-touch-action: none; 35 | } 36 | 37 | body,ul,li { 38 | padding: 0; 39 | margin: 0; 40 | border: 0; 41 | } 42 | 43 | body { 44 | font-size: 12px; 45 | font-family: ubuntu, helvetica, arial; 46 | overflow: hidden; /* this is important to prevent the whole page to bounce */ 47 | } 48 | 49 | #header { 50 | position: absolute; 51 | z-index: 2; 52 | top: 0; 53 | left: 0; 54 | width: 100%; 55 | height: 45px; 56 | line-height: 45px; 57 | background: #CD235C; 58 | padding: 0; 59 | color: #eee; 60 | font-size: 20px; 61 | text-align: center; 62 | font-weight: bold; 63 | } 64 | 65 | #footer { 66 | position: absolute; 67 | z-index: 2; 68 | bottom: 0; 69 | left: 0; 70 | width: 100%; 71 | height: 48px; 72 | background: #444; 73 | padding: 0; 74 | border-top: 1px solid #444; 75 | } 76 | 77 | #wrapper { 78 | position: absolute; 79 | z-index: 1; 80 | top: 45px; 81 | bottom: 48px; 82 | left: 0; 83 | width: 100%; 84 | background: #ccc; 85 | overflow: hidden; 86 | } 87 | 88 | #scroller { 89 | position: absolute; 90 | z-index: 1; 91 | -webkit-tap-highlight-color: rgba(0,0,0,0); 92 | width: 100%; 93 | -webkit-transform: translateZ(0); 94 | -moz-transform: translateZ(0); 95 | -ms-transform: translateZ(0); 96 | -o-transform: translateZ(0); 97 | transform: translateZ(0); 98 | -webkit-touch-callout: none; 99 | -webkit-user-select: none; 100 | -moz-user-select: none; 101 | -ms-user-select: none; 102 | user-select: none; 103 | -webkit-text-size-adjust: none; 104 | -moz-text-size-adjust: none; 105 | -ms-text-size-adjust: none; 106 | -o-text-size-adjust: none; 107 | text-size-adjust: none; 108 | } 109 | 110 | #scroller ul { 111 | list-style: none; 112 | padding: 0; 113 | margin: 0; 114 | width: 100%; 115 | text-align: left; 116 | } 117 | 118 | #scroller li { 119 | padding: 0 10px; 120 | height: 40px; 121 | line-height: 40px; 122 | border-bottom: 1px solid #ccc; 123 | border-top: 1px solid #fff; 124 | background-color: #fafafa; 125 | font-size: 14px; 126 | } 127 | 128 | </style> 129 | </head> 130 | <body onload="loaded()"> 131 | <div id="header">iScroll</div> 132 | 133 | <div id="wrapper"> 134 | <div id="scroller"> 135 | <ul> 136 | <li><a href="javascript:myScroll.scrollToElement(document.querySelector('#scroller li:nth-child(10)'))">Scroll to element 10</a></li> 137 | <li>Pretty row 2</li> 138 | <li>Pretty row 3</li> 139 | <li>Pretty row 4</li> 140 | <li>Pretty row 5</li> 141 | <li>Pretty row 6</li> 142 | <li>Pretty row 7</li> 143 | <li>Pretty row 8</li> 144 | <li>Pretty row 9</li> 145 | <li><a href="javascript:myScroll.scrollToElement(document.querySelector('#scroller li:nth-child(25)'), null, null, true)">Center element 25 to screen</a></li> 146 | <li>Pretty row 11</li> 147 | <li>Pretty row 12</li> 148 | <li>Pretty row 13</li> 149 | <li>Pretty row 14</li> 150 | <li>Pretty row 15</li> 151 | <li>Pretty row 16</li> 152 | <li>Pretty row 17</li> 153 | <li>Pretty row 18</li> 154 | <li>Pretty row 19</li> 155 | <li>Pretty row 20</li> 156 | <li>Pretty row 21</li> 157 | <li>Pretty row 22</li> 158 | <li>Pretty row 23</li> 159 | <li>Pretty row 24</li> 160 | <li><a href="javascript:myScroll.scrollToElement(document.querySelector('#scroller li:nth-child(50)'), 1200, null, null, IScroll.utils.ease.elastic)">Scroll to the last element with elastic easing</a></li> 161 | <li>Pretty row 26</li> 162 | <li>Pretty row 27</li> 163 | <li>Pretty row 28</li> 164 | <li>Pretty row 29</li> 165 | <li>Pretty row 30</li> 166 | <li>Pretty row 31</li> 167 | <li>Pretty row 32</li> 168 | <li>Pretty row 33</li> 169 | <li>Pretty row 34</li> 170 | <li>Pretty row 35</li> 171 | <li>Pretty row 36</li> 172 | <li>Pretty row 37</li> 173 | <li>Pretty row 38</li> 174 | <li>Pretty row 39</li> 175 | <li>Pretty row 40</li> 176 | <li>Pretty row 41</li> 177 | <li>Pretty row 42</li> 178 | <li>Pretty row 43</li> 179 | <li>Pretty row 44</li> 180 | <li>Pretty row 45</li> 181 | <li>Pretty row 46</li> 182 | <li>Pretty row 47</li> 183 | <li>Pretty row 48</li> 184 | <li>Pretty row 49</li> 185 | <li>Pretty row 50</li> 186 | </ul> 187 | </div> 188 | </div> 189 | 190 | <div id="footer"></div> 191 | 192 | </body> 193 | </html> -------------------------------------------------------------------------------- /demos/scrollbars/index.html: -------------------------------------------------------------------------------- 1 | <!DOCTYPE html> 2 | <html> 3 | <head> 4 | <meta charset="utf-8"> 5 | <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0"> 6 | 7 | <title>iScroll demo: scrollbars</title> 8 | 9 | <script type="text/javascript" src="../../build/iscroll.js"></script> 10 | <script type="text/javascript" src="../demoUtils.js"></script> 11 | <script type="text/javascript"> 12 | 13 | var myScroll; 14 | 15 | function loaded () { 16 | myScroll = new IScroll('#wrapper', { 17 | scrollbars: true, 18 | mouseWheel: true, 19 | interactiveScrollbars: true, 20 | shrinkScrollbars: 'scale', 21 | fadeScrollbars: true 22 | }); 23 | } 24 | 25 | document.addEventListener('touchmove', function (e) { e.preventDefault(); }, isPassive() ? { 26 | capture: false, 27 | passive: false 28 | } : false); 29 | 30 | </script> 31 | 32 | <style type="text/css"> 33 | * { 34 | -webkit-box-sizing: border-box; 35 | -moz-box-sizing: border-box; 36 | box-sizing: border-box; 37 | } 38 | 39 | html { 40 | -ms-touch-action: none; 41 | } 42 | 43 | body,ul,li { 44 | padding: 0; 45 | margin: 0; 46 | border: 0; 47 | } 48 | 49 | body { 50 | font-size: 12px; 51 | font-family: ubuntu, helvetica, arial; 52 | overflow: hidden; /* this is important to prevent the whole page to bounce */ 53 | } 54 | 55 | #header { 56 | position: absolute; 57 | z-index: 2; 58 | top: 0; 59 | left: 0; 60 | width: 100%; 61 | height: 45px; 62 | line-height: 45px; 63 | background: #CD235C; 64 | padding: 0; 65 | color: #eee; 66 | font-size: 20px; 67 | text-align: center; 68 | font-weight: bold; 69 | } 70 | 71 | #footer { 72 | position: absolute; 73 | z-index: 2; 74 | bottom: 0; 75 | left: 0; 76 | width: 100%; 77 | height: 48px; 78 | background: #444; 79 | padding: 0; 80 | border-top: 1px solid #444; 81 | } 82 | 83 | #wrapper { 84 | position: absolute; 85 | z-index: 1; 86 | top: 45px; 87 | bottom: 48px; 88 | left: 0; 89 | width: 100%; 90 | background: #ccc; 91 | overflow: hidden; 92 | } 93 | 94 | #scroller { 95 | position: absolute; 96 | z-index: 1; 97 | -webkit-tap-highlight-color: rgba(0,0,0,0); 98 | width: 100%; 99 | -webkit-transform: translateZ(0); 100 | -moz-transform: translateZ(0); 101 | -ms-transform: translateZ(0); 102 | -o-transform: translateZ(0); 103 | transform: translateZ(0); 104 | -webkit-touch-callout: none; 105 | -webkit-user-select: none; 106 | -moz-user-select: none; 107 | -ms-user-select: none; 108 | user-select: none; 109 | -webkit-text-size-adjust: none; 110 | -moz-text-size-adjust: none; 111 | -ms-text-size-adjust: none; 112 | -o-text-size-adjust: none; 113 | text-size-adjust: none; 114 | } 115 | 116 | #scroller ul { 117 | list-style: none; 118 | padding: 0; 119 | margin: 0; 120 | width: 100%; 121 | text-align: left; 122 | } 123 | 124 | #scroller li { 125 | padding: 0 10px; 126 | height: 40px; 127 | line-height: 40px; 128 | border-bottom: 1px solid #ccc; 129 | border-top: 1px solid #fff; 130 | background-color: #fafafa; 131 | font-size: 14px; 132 | } 133 | 134 | </style> 135 | </head> 136 | <body onload="loaded()"> 137 | <div id="header">iScroll</div> 138 | 139 | <div id="wrapper"> 140 | <div id="scroller"> 141 | <ul> 142 | <li>Pretty row 1</li> 143 | <li>Pretty row 2</li> 144 | <li>Pretty row 3</li> 145 | <li>Pretty row 4</li> 146 | <li>Pretty row 5</li> 147 | <li>Pretty row 6</li> 148 | <li>Pretty row 7</li> 149 | <li>Pretty row 8</li> 150 | <li>Pretty row 9</li> 151 | <li>Pretty row 10</li> 152 | <li>Pretty row 11</li> 153 | <li>Pretty row 12</li> 154 | <li>Pretty row 13</li> 155 | <li>Pretty row 14</li> 156 | <li>Pretty row 15</li> 157 | <li>Pretty row 16</li> 158 | <li>Pretty row 17</li> 159 | <li>Pretty row 18</li> 160 | <li>Pretty row 19</li> 161 | <li>Pretty row 20</li> 162 | <li>Pretty row 21</li> 163 | <li>Pretty row 22</li> 164 | <li>Pretty row 23</li> 165 | <li>Pretty row 24</li> 166 | <li>Pretty row 25</li> 167 | <li>Pretty row 26</li> 168 | <li>Pretty row 27</li> 169 | <li>Pretty row 28</li> 170 | <li>Pretty row 29</li> 171 | <li>Pretty row 30</li> 172 | <li>Pretty row 31</li> 173 | <li>Pretty row 32</li> 174 | <li>Pretty row 33</li> 175 | <li>Pretty row 34</li> 176 | <li>Pretty row 35</li> 177 | <li>Pretty row 36</li> 178 | <li>Pretty row 37</li> 179 | <li>Pretty row 38</li> 180 | <li>Pretty row 39</li> 181 | <li>Pretty row 40</li> 182 | <li>Pretty row 41</li> 183 | <li>Pretty row 42</li> 184 | <li>Pretty row 43</li> 185 | <li>Pretty row 44</li> 186 | <li>Pretty row 45</li> 187 | <li>Pretty row 46</li> 188 | <li>Pretty row 47</li> 189 | <li>Pretty row 48</li> 190 | <li>Pretty row 49</li> 191 | <li>Pretty row 50</li> 192 | </ul> 193 | </div> 194 | </div> 195 | 196 | <div id="footer"></div> 197 | 198 | </body> 199 | </html> 200 | -------------------------------------------------------------------------------- /demos/simple/index.html: -------------------------------------------------------------------------------- 1 | <!DOCTYPE html> 2 | <html> 3 | <head> 4 | <meta charset="utf-8"> 5 | <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0"> 6 | 7 | <title>iScroll demo: simple</title> 8 | 9 | <script type="text/javascript" src="../../build/iscroll.js"></script> 10 | <script type="text/javascript" src="../demoUtils.js"></script> 11 | <script type="text/javascript"> 12 | 13 | var myScroll; 14 | 15 | function loaded () { 16 | myScroll = new IScroll('#wrapper', { mouseWheel: true }); 17 | } 18 | 19 | document.addEventListener('touchmove', function (e) { e.preventDefault(); }, isPassive() ? { 20 | capture: false, 21 | passive: false 22 | } : false); 23 | 24 | </script> 25 | 26 | <style type="text/css"> 27 | * { 28 | -webkit-box-sizing: border-box; 29 | -moz-box-sizing: border-box; 30 | box-sizing: border-box; 31 | } 32 | 33 | html { 34 | -ms-touch-action: none; 35 | } 36 | 37 | body,ul,li { 38 | padding: 0; 39 | margin: 0; 40 | border: 0; 41 | } 42 | 43 | body { 44 | font-size: 12px; 45 | font-family: ubuntu, helvetica, arial; 46 | overflow: hidden; /* this is important to prevent the whole page to bounce */ 47 | } 48 | 49 | #header { 50 | position: absolute; 51 | z-index: 2; 52 | top: 0; 53 | left: 0; 54 | width: 100%; 55 | height: 45px; 56 | line-height: 45px; 57 | background: #CD235C; 58 | padding: 0; 59 | color: #eee; 60 | font-size: 20px; 61 | text-align: center; 62 | font-weight: bold; 63 | } 64 | 65 | #footer { 66 | position: absolute; 67 | z-index: 2; 68 | bottom: 0; 69 | left: 0; 70 | width: 100%; 71 | height: 48px; 72 | background: #444; 73 | padding: 0; 74 | border-top: 1px solid #444; 75 | } 76 | 77 | #wrapper { 78 | position: absolute; 79 | z-index: 1; 80 | top: 45px; 81 | bottom: 48px; 82 | left: 0; 83 | width: 100%; 84 | background: #ccc; 85 | overflow: hidden; 86 | } 87 | 88 | #scroller { 89 | position: absolute; 90 | z-index: 1; 91 | -webkit-tap-highlight-color: rgba(0,0,0,0); 92 | width: 100%; 93 | -webkit-transform: translateZ(0); 94 | -moz-transform: translateZ(0); 95 | -ms-transform: translateZ(0); 96 | -o-transform: translateZ(0); 97 | transform: translateZ(0); 98 | -webkit-touch-callout: none; 99 | -webkit-user-select: none; 100 | -moz-user-select: none; 101 | -ms-user-select: none; 102 | user-select: none; 103 | -webkit-text-size-adjust: none; 104 | -moz-text-size-adjust: none; 105 | -ms-text-size-adjust: none; 106 | -o-text-size-adjust: none; 107 | text-size-adjust: none; 108 | } 109 | 110 | #scroller ul { 111 | list-style: none; 112 | padding: 0; 113 | margin: 0; 114 | width: 100%; 115 | text-align: left; 116 | } 117 | 118 | #scroller li { 119 | padding: 0 10px; 120 | height: 40px; 121 | line-height: 40px; 122 | border-bottom: 1px solid #ccc; 123 | border-top: 1px solid #fff; 124 | background-color: #fafafa; 125 | font-size: 14px; 126 | } 127 | 128 | </style> 129 | </head> 130 | <body onload="loaded()"> 131 | <div id="header">iScroll</div> 132 | 133 | <div id="wrapper"> 134 | <div id="scroller"> 135 | <ul> 136 | <li>Pretty row 1</li> 137 | <li>Pretty row 2</li> 138 | <li>Pretty row 3</li> 139 | <li>Pretty row 4</li> 140 | <li>Pretty row 5</li> 141 | <li>Pretty row 6</li> 142 | <li>Pretty row 7</li> 143 | <li>Pretty row 8</li> 144 | <li>Pretty row 9</li> 145 | <li>Pretty row 10</li> 146 | <li>Pretty row 11</li> 147 | <li>Pretty row 12</li> 148 | <li>Pretty row 13</li> 149 | <li>Pretty row 14</li> 150 | <li>Pretty row 15</li> 151 | <li>Pretty row 16</li> 152 | <li>Pretty row 17</li> 153 | <li>Pretty row 18</li> 154 | <li>Pretty row 19</li> 155 | <li>Pretty row 20</li> 156 | <li>Pretty row 21</li> 157 | <li>Pretty row 22</li> 158 | <li>Pretty row 23</li> 159 | <li>Pretty row 24</li> 160 | <li>Pretty row 25</li> 161 | <li>Pretty row 26</li> 162 | <li>Pretty row 27</li> 163 | <li>Pretty row 28</li> 164 | <li>Pretty row 29</li> 165 | <li>Pretty row 30</li> 166 | <li>Pretty row 31</li> 167 | <li>Pretty row 32</li> 168 | <li>Pretty row 33</li> 169 | <li>Pretty row 34</li> 170 | <li>Pretty row 35</li> 171 | <li>Pretty row 36</li> 172 | <li>Pretty row 37</li> 173 | <li>Pretty row 38</li> 174 | <li>Pretty row 39</li> 175 | <li>Pretty row 40</li> 176 | <li>Pretty row 41</li> 177 | <li>Pretty row 42</li> 178 | <li>Pretty row 43</li> 179 | <li>Pretty row 44</li> 180 | <li>Pretty row 45</li> 181 | <li>Pretty row 46</li> 182 | <li>Pretty row 47</li> 183 | <li>Pretty row 48</li> 184 | <li>Pretty row 49</li> 185 | <li>Pretty row 50</li> 186 | </ul> 187 | </div> 188 | </div> 189 | 190 | <div id="footer"></div> 191 | 192 | </body> 193 | </html> -------------------------------------------------------------------------------- /demos/snap/index.html: -------------------------------------------------------------------------------- 1 | <!DOCTYPE html> 2 | <html> 3 | <head> 4 | <meta charset="utf-8"> 5 | <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0"> 6 | 7 | <title>iScroll demo: snap</title> 8 | 9 | <script type="text/javascript" src="../../build/iscroll.js"></script> 10 | <script type="text/javascript" src="../demoUtils.js"></script> 11 | <script type="text/javascript"> 12 | 13 | var myScroll; 14 | 15 | function loaded () { 16 | myScroll = new IScroll('#wrapper', { 17 | scrollX: true, 18 | scrollY: true, 19 | momentum: false, 20 | snap: true 21 | }); 22 | } 23 | 24 | document.addEventListener('touchmove', function (e) { e.preventDefault(); }, isPassive() ? { 25 | capture: false, 26 | passive: false 27 | } : false); 28 | </script> 29 | 30 | <style type="text/css"> 31 | * { 32 | -webkit-box-sizing: border-box; 33 | -moz-box-sizing: border-box; 34 | box-sizing: border-box; 35 | } 36 | 37 | html { 38 | -ms-touch-action: none; 39 | } 40 | 41 | body,ul,li { 42 | padding: 0; 43 | margin: 0; 44 | border: 0; 45 | } 46 | 47 | body { 48 | font-size: 12px; 49 | font-family: ubuntu, helvetica, arial; 50 | overflow: hidden; /* this is important to prevent the whole page to bounce */ 51 | } 52 | 53 | #header { 54 | position: absolute; 55 | z-index: 2; 56 | top: 0; 57 | left: 0; 58 | width: 100%; 59 | height: 45px; 60 | line-height: 45px; 61 | background: #CD235C; 62 | padding: 0; 63 | color: #eee; 64 | font-size: 20px; 65 | text-align: center; 66 | font-weight: bold; 67 | } 68 | 69 | #footer { 70 | position: absolute; 71 | z-index: 2; 72 | bottom: 0; 73 | left: 0; 74 | width: 100%; 75 | height: 48px; 76 | background: #444; 77 | padding: 0; 78 | border-top: 1px solid #444; 79 | } 80 | 81 | #wrapper { 82 | position: absolute; 83 | z-index: 1; 84 | top: 45px; 85 | bottom: 48px; 86 | left: 0; 87 | width: 100%; 88 | background: #ccc; 89 | overflow: hidden; 90 | } 91 | 92 | #scroller { 93 | position: absolute; 94 | z-index: 1; 95 | -webkit-tap-highlight-color: rgba(0,0,0,0); 96 | width: 2000px; 97 | height: 2000px; 98 | background-color: #a00; 99 | -webkit-transform: translateZ(0); 100 | -moz-transform: translateZ(0); 101 | -ms-transform: translateZ(0); 102 | -o-transform: translateZ(0); 103 | transform: translateZ(0); 104 | -webkit-touch-callout: none; 105 | -webkit-user-select: none; 106 | -moz-user-select: none; 107 | -ms-user-select: none; 108 | user-select: none; 109 | -webkit-text-size-adjust: none; 110 | -moz-text-size-adjust: none; 111 | -ms-text-size-adjust: none; 112 | -o-text-size-adjust: none; 113 | text-size-adjust: none; 114 | } 115 | 116 | #scroller ul { 117 | list-style: none; 118 | padding: 0; 119 | margin: 0; 120 | width: 100%; 121 | text-align: center; 122 | } 123 | 124 | #scroller li { 125 | display: block; 126 | float: left; 127 | width: 200px; 128 | height: 200px; 129 | border-right: 1px solid #ccc; 130 | border-bottom: 1px solid #ccc; 131 | background-color: #fafafa; 132 | font-size: 14px; 133 | } 134 | 135 | </style> 136 | </head> 137 | <body onload="loaded()"> 138 | <div id="header">iScroll</div> 139 | 140 | <div id="wrapper"> 141 | <div id="scroller"> 142 | <ul> 143 | <li>Cell</li> 144 | <li>Cell</li> 145 | <li>Cell</li> 146 | <li>Cell</li> 147 | <li>Cell</li> 148 | <li>Cell</li> 149 | <li>Cell</li> 150 | <li>Cell</li> 151 | <li>Cell</li> 152 | <li>Cell</li> 153 | 154 | <li>Cell</li> 155 | <li>Cell</li> 156 | <li>Cell</li> 157 | <li>Cell</li> 158 | <li>Cell</li> 159 | <li>Cell</li> 160 | <li>Cell</li> 161 | <li>Cell</li> 162 | <li>Cell</li> 163 | <li>Cell</li> 164 | 165 | <li>Cell</li> 166 | <li>Cell</li> 167 | <li>Cell</li> 168 | <li>Cell</li> 169 | <li>Cell</li> 170 | <li>Cell</li> 171 | <li>Cell</li> 172 | <li>Cell</li> 173 | <li>Cell</li> 174 | <li>Cell</li> 175 | 176 | <li>Cell</li> 177 | <li>Cell</li> 178 | <li>Cell</li> 179 | <li>Cell</li> 180 | <li>Cell</li> 181 | <li>Cell</li> 182 | <li>Cell</li> 183 | <li>Cell</li> 184 | <li>Cell</li> 185 | <li>Cell</li> 186 | 187 | <li>Cell</li> 188 | <li>Cell</li> 189 | <li>Cell</li> 190 | <li>Cell</li> 191 | <li>Cell</li> 192 | <li>Cell</li> 193 | <li>Cell</li> 194 | <li>Cell</li> 195 | <li>Cell</li> 196 | <li>Cell</li> 197 | 198 | <li>Cell</li> 199 | <li>Cell</li> 200 | <li>Cell</li> 201 | <li>Cell</li> 202 | <li>Cell</li> 203 | <li>Cell</li> 204 | <li>Cell</li> 205 | <li>Cell</li> 206 | <li>Cell</li> 207 | <li>Cell</li> 208 | 209 | <li>Cell</li> 210 | <li>Cell</li> 211 | <li>Cell</li> 212 | <li>Cell</li> 213 | <li>Cell</li> 214 | <li>Cell</li> 215 | <li>Cell</li> 216 | <li>Cell</li> 217 | <li>Cell</li> 218 | <li>Cell</li> 219 | 220 | <li>Cell</li> 221 | <li>Cell</li> 222 | <li>Cell</li> 223 | <li>Cell</li> 224 | <li>Cell</li> 225 | <li>Cell</li> 226 | <li>Cell</li> 227 | <li>Cell</li> 228 | <li>Cell</li> 229 | <li>Cell</li> 230 | 231 | <li>Cell</li> 232 | <li>Cell</li> 233 | <li>Cell</li> 234 | <li>Cell</li> 235 | <li>Cell</li> 236 | <li>Cell</li> 237 | <li>Cell</li> 238 | <li>Cell</li> 239 | <li>Cell</li> 240 | <li>Cell</li> 241 | 242 | <li>Cell</li> 243 | <li>Cell</li> 244 | <li>Cell</li> 245 | <li>Cell</li> 246 | <li>Cell</li> 247 | <li>Cell</li> 248 | <li>Cell</li> 249 | <li>Cell</li> 250 | <li>Cell</li> 251 | <li>Cell</li> 252 | </ul> 253 | </div> 254 | </div> 255 | 256 | <div id="footer"></div> 257 | 258 | </body> 259 | </html> -------------------------------------------------------------------------------- /demos/styled-scrollbars/index.html: -------------------------------------------------------------------------------- 1 | <!DOCTYPE html> 2 | <html> 3 | <head> 4 | <meta charset="utf-8"> 5 | <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0"> 6 | 7 | <title>iScroll demo: styled scrollbars</title> 8 | 9 | <script type="text/javascript" src="../../build/iscroll.js"></script> 10 | <script type="text/javascript" src="../demoUtils.js"></script> 11 | <script type="text/javascript"> 12 | 13 | var myScroll; 14 | 15 | function loaded () { 16 | myScroll = new IScroll('#wrapper', { scrollX: true, scrollbars: 'custom' }); 17 | } 18 | 19 | document.addEventListener('touchmove', function (e) { e.preventDefault(); }, isPassive() ? { 20 | capture: false, 21 | passive: false 22 | } : false); 23 | 24 | </script> 25 | 26 | <style type="text/css"> 27 | 28 | /* Styled scrollbars */ 29 | 30 | .iScrollHorizontalScrollbar { 31 | position: absolute; 32 | z-index: 9999; 33 | height: 16px; 34 | left: 2px; 35 | right: 2px; 36 | bottom: 2px; 37 | overflow: hidden; 38 | } 39 | 40 | .iScrollHorizontalScrollbar.iScrollBothScrollbars { 41 | right: 18px; 42 | } 43 | 44 | .iScrollVerticalScrollbar { 45 | position: absolute; 46 | z-index: 9999; 47 | width: 16px; 48 | bottom: 2px; 49 | top: 2px; 50 | right: 2px; 51 | overflow: hidden; 52 | } 53 | 54 | .iScrollVerticalScrollbar.iScrollBothScrollbars { 55 | bottom: 18px; 56 | } 57 | 58 | .iScrollIndicator { 59 | position: absolute; 60 | background: #cc3f6e; 61 | border-width: 1px; 62 | border-style: solid; 63 | border-color: #EB97B4 #7C2845 #7C2845 #EB97B4; 64 | border-radius: 8px; 65 | } 66 | 67 | .iScrollHorizontalScrollbar .iScrollIndicator { 68 | height: 100%; 69 | background: -moz-linear-gradient(left, #cc3f6e 0%, #93004e 100%); 70 | background: -webkit-linear-gradient(left, #cc3f6e 0%,#93004e 100%); 71 | background: -o-linear-gradient(left, #cc3f6e 0%,#93004e 100%); 72 | background: -ms-linear-gradient(left, #cc3f6e 0%,#93004e 100%); 73 | background: linear-gradient(to right, #cc3f6e 0%,#93004e 100%); 74 | } 75 | 76 | .iScrollVerticalScrollbar .iScrollIndicator { 77 | width: 100%; 78 | background: -moz-linear-gradient(top, #cc3f6e 0%, #93004e 100%); 79 | background: -webkit-linear-gradient(top, #cc3f6e 0%,#93004e 100%); 80 | background: -o-linear-gradient(top, #cc3f6e 0%,#93004e 100%); 81 | background: -ms-linear-gradient(top, #cc3f6e 0%,#93004e 100%); 82 | background: linear-gradient(to bottom, #cc3f6e 0%,#93004e 100%); 83 | } 84 | 85 | 86 | /* end */ 87 | 88 | * { 89 | -webkit-box-sizing: border-box; 90 | -moz-box-sizing: border-box; 91 | box-sizing: border-box; 92 | } 93 | 94 | html { 95 | -ms-touch-action: none; 96 | } 97 | 98 | body,ul,li { 99 | padding: 0; 100 | margin: 0; 101 | border: 0; 102 | } 103 | 104 | body { 105 | font-size: 12px; 106 | font-family: ubuntu, helvetica, arial; 107 | overflow: hidden; /* this is important to prevent the whole page to bounce */ 108 | } 109 | 110 | #header { 111 | position: absolute; 112 | z-index: 2; 113 | top: 0; 114 | left: 0; 115 | width: 100%; 116 | height: 45px; 117 | line-height: 45px; 118 | background: #CD235C; 119 | padding: 0; 120 | color: #eee; 121 | font-size: 20px; 122 | text-align: center; 123 | font-weight: bold; 124 | } 125 | 126 | #footer { 127 | position: absolute; 128 | z-index: 2; 129 | bottom: 0; 130 | left: 0; 131 | width: 100%; 132 | height: 48px; 133 | background: #444; 134 | padding: 0; 135 | border-top: 1px solid #444; 136 | } 137 | 138 | #wrapper { 139 | position: absolute; 140 | z-index: 1; 141 | top: 45px; 142 | bottom: 48px; 143 | left: 0; 144 | width: 100%; 145 | background: #ccc; 146 | overflow: hidden; 147 | } 148 | 149 | #scroller { 150 | position: absolute; 151 | z-index: 1; 152 | -webkit-tap-highlight-color: rgba(0,0,0,0); 153 | width: 2000px; 154 | -webkit-transform: translateZ(0); 155 | -moz-transform: translateZ(0); 156 | -ms-transform: translateZ(0); 157 | -o-transform: translateZ(0); 158 | transform: translateZ(0); 159 | -webkit-touch-callout: none; 160 | -webkit-user-select: none; 161 | -moz-user-select: none; 162 | -ms-user-select: none; 163 | user-select: none; 164 | -webkit-text-size-adjust: none; 165 | -moz-text-size-adjust: none; 166 | -ms-text-size-adjust: none; 167 | -o-text-size-adjust: none; 168 | text-size-adjust: none; 169 | } 170 | 171 | #scroller ul { 172 | list-style: none; 173 | padding: 0; 174 | margin: 0; 175 | width: 100%; 176 | text-align: left; 177 | } 178 | 179 | #scroller li { 180 | padding: 0 10px; 181 | height: 40px; 182 | line-height: 40px; 183 | border-bottom: 1px solid #ccc; 184 | border-top: 1px solid #fff; 185 | background-color: #fafafa; 186 | font-size: 14px; 187 | } 188 | 189 | </style> 190 | </head> 191 | <body onload="loaded()"> 192 | <div id="header">iScroll</div> 193 | 194 | <div id="wrapper"> 195 | <div id="scroller"> 196 | <ul> 197 | <li>Pretty row 1</li> 198 | <li>Pretty row 2</li> 199 | <li>Pretty row 3</li> 200 | <li>Pretty row 4</li> 201 | <li>Pretty row 5</li> 202 | <li>Pretty row 6</li> 203 | <li>Pretty row 7</li> 204 | <li>Pretty row 8</li> 205 | <li>Pretty row 9</li> 206 | <li>Pretty row 10</li> 207 | <li>Pretty row 11</li> 208 | <li>Pretty row 12</li> 209 | <li>Pretty row 13</li> 210 | <li>Pretty row 14</li> 211 | <li>Pretty row 15</li> 212 | <li>Pretty row 16</li> 213 | <li>Pretty row 17</li> 214 | <li>Pretty row 18</li> 215 | <li>Pretty row 19</li> 216 | <li>Pretty row 20</li> 217 | <li>Pretty row 21</li> 218 | <li>Pretty row 22</li> 219 | <li>Pretty row 23</li> 220 | <li>Pretty row 24</li> 221 | <li>Pretty row 25</li> 222 | <li>Pretty row 26</li> 223 | <li>Pretty row 27</li> 224 | <li>Pretty row 28</li> 225 | <li>Pretty row 29</li> 226 | <li>Pretty row 30</li> 227 | <li>Pretty row 31</li> 228 | <li>Pretty row 32</li> 229 | <li>Pretty row 33</li> 230 | <li>Pretty row 34</li> 231 | <li>Pretty row 35</li> 232 | <li>Pretty row 36</li> 233 | <li>Pretty row 37</li> 234 | <li>Pretty row 38</li> 235 | <li>Pretty row 39</li> 236 | <li>Pretty row 40</li> 237 | <li>Pretty row 41</li> 238 | <li>Pretty row 42</li> 239 | <li>Pretty row 43</li> 240 | <li>Pretty row 44</li> 241 | <li>Pretty row 45</li> 242 | <li>Pretty row 46</li> 243 | <li>Pretty row 47</li> 244 | <li>Pretty row 48</li> 245 | <li>Pretty row 49</li> 246 | <li>Pretty row 50</li> 247 | </ul> 248 | </div> 249 | </div> 250 | 251 | <div id="footer"></div> 252 | 253 | </body> 254 | </html> -------------------------------------------------------------------------------- /demos/tap/index.html: -------------------------------------------------------------------------------- 1 | <!DOCTYPE html> 2 | <html> 3 | <head> 4 | <meta charset="utf-8"> 5 | <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0"> 6 | 7 | <title>iScroll demo: simple</title> 8 | 9 | <script type="text/javascript" src="../../build/iscroll.js"></script> 10 | <script type="text/javascript" src="../demoUtils.js"></script> 11 | <script type="text/javascript"> 12 | 13 | var myScroll; 14 | 15 | function loaded () { 16 | myScroll = new IScroll('#wrapper', { mouseWheel: true, tap: true }); 17 | 18 | document.getElementById('me').addEventListener('tap', function () { 19 | this.style.background = !this.style.background ? '#a00' : ''; 20 | }, false); 21 | } 22 | 23 | document.addEventListener('touchmove', function (e) { e.preventDefault(); }, isPassive() ? { 24 | capture: false, 25 | passive: false 26 | } : false); 27 | 28 | </script> 29 | 30 | <style type="text/css"> 31 | * { 32 | -webkit-box-sizing: border-box; 33 | -moz-box-sizing: border-box; 34 | box-sizing: border-box; 35 | } 36 | 37 | html { 38 | -ms-touch-action: none; 39 | } 40 | 41 | body,ul,li { 42 | padding: 0; 43 | margin: 0; 44 | border: 0; 45 | } 46 | 47 | body { 48 | font-size: 12px; 49 | font-family: ubuntu, helvetica, arial; 50 | overflow: hidden; /* this is important to prevent the whole page to bounce */ 51 | } 52 | 53 | #header { 54 | position: absolute; 55 | z-index: 2; 56 | top: 0; 57 | left: 0; 58 | width: 100%; 59 | height: 45px; 60 | line-height: 45px; 61 | background: #CD235C; 62 | padding: 0; 63 | color: #eee; 64 | font-size: 20px; 65 | text-align: center; 66 | font-weight: bold; 67 | } 68 | 69 | #footer { 70 | position: absolute; 71 | z-index: 2; 72 | bottom: 0; 73 | left: 0; 74 | width: 100%; 75 | height: 48px; 76 | background: #444; 77 | padding: 0; 78 | border-top: 1px solid #444; 79 | } 80 | 81 | #wrapper { 82 | position: absolute; 83 | z-index: 1; 84 | top: 45px; 85 | bottom: 48px; 86 | left: 0; 87 | width: 100%; 88 | background: #ccc; 89 | overflow: hidden; 90 | } 91 | 92 | #scroller { 93 | position: absolute; 94 | z-index: 1; 95 | -webkit-tap-highlight-color: rgba(0,0,0,0); 96 | width: 100%; 97 | -webkit-transform: translateZ(0); 98 | -moz-transform: translateZ(0); 99 | -ms-transform: translateZ(0); 100 | -o-transform: translateZ(0); 101 | transform: translateZ(0); 102 | -webkit-touch-callout: none; 103 | -webkit-user-select: none; 104 | -moz-user-select: none; 105 | -ms-user-select: none; 106 | user-select: none; 107 | -webkit-text-size-adjust: none; 108 | -moz-text-size-adjust: none; 109 | -ms-text-size-adjust: none; 110 | -o-text-size-adjust: none; 111 | text-size-adjust: none; 112 | } 113 | 114 | #scroller ul { 115 | list-style: none; 116 | padding: 0; 117 | margin: 0; 118 | width: 100%; 119 | text-align: left; 120 | } 121 | 122 | #scroller li { 123 | padding: 0 10px; 124 | height: 40px; 125 | line-height: 40px; 126 | border-bottom: 1px solid #ccc; 127 | border-top: 1px solid #fff; 128 | background-color: #fafafa; 129 | font-size: 14px; 130 | } 131 | 132 | </style> 133 | </head> 134 | <body onload="loaded()"> 135 | <div id="header">iScroll</div> 136 | 137 | <div id="wrapper"> 138 | <div id="scroller"> 139 | <ul> 140 | <li>Pretty row 1</li> 141 | <li>Pretty row 2</li> 142 | <li>Pretty row 3</li> 143 | <li>Pretty row 4</li> 144 | <li>Pretty row 5</li> 145 | <li id="me"><strong>Tap me! Tap me! Tap me! Tap me!</strong></li> 146 | <li>Pretty row 7</li> 147 | <li>Pretty row 8</li> 148 | <li>Pretty row 9</li> 149 | <li>Pretty row 10</li> 150 | <li>Pretty row 11</li> 151 | <li>Pretty row 12</li> 152 | <li>Pretty row 13</li> 153 | <li>Pretty row 14</li> 154 | <li>Pretty row 15</li> 155 | <li>Pretty row 16</li> 156 | <li>Pretty row 17</li> 157 | <li>Pretty row 18</li> 158 | <li>Pretty row 19</li> 159 | <li>Pretty row 20</li> 160 | <li>Pretty row 21</li> 161 | <li>Pretty row 22</li> 162 | <li>Pretty row 23</li> 163 | <li>Pretty row 24</li> 164 | <li>Pretty row 25</li> 165 | <li>Pretty row 26</li> 166 | <li>Pretty row 27</li> 167 | <li>Pretty row 28</li> 168 | <li>Pretty row 29</li> 169 | <li>Pretty row 30</li> 170 | <li>Pretty row 31</li> 171 | <li>Pretty row 32</li> 172 | <li>Pretty row 33</li> 173 | <li>Pretty row 34</li> 174 | <li>Pretty row 35</li> 175 | <li>Pretty row 36</li> 176 | <li>Pretty row 37</li> 177 | <li>Pretty row 38</li> 178 | <li>Pretty row 39</li> 179 | <li>Pretty row 40</li> 180 | <li>Pretty row 41</li> 181 | <li>Pretty row 42</li> 182 | <li>Pretty row 43</li> 183 | <li>Pretty row 44</li> 184 | <li>Pretty row 45</li> 185 | <li>Pretty row 46</li> 186 | <li>Pretty row 47</li> 187 | <li>Pretty row 48</li> 188 | <li>Pretty row 49</li> 189 | <li>Pretty row 50</li> 190 | </ul> 191 | </div> 192 | </div> 193 | 194 | <div id="footer"></div> 195 | 196 | </body> 197 | </html> -------------------------------------------------------------------------------- /demos/zoom/index.html: -------------------------------------------------------------------------------- 1 | <!DOCTYPE html> 2 | <html> 3 | <head> 4 | <meta charset="utf-8"> 5 | <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0"> 6 | 7 | <title>iScroll demo: zoom</title> 8 | 9 | <script type="text/javascript" src="../../build/iscroll-zoom.js"></script> 10 | <script type="text/javascript" src="../demoUtils.js"></script> 11 | <script type="text/javascript"> 12 | 13 | var myScroll; 14 | 15 | function loaded () { 16 | myScroll = new IScroll('#wrapper', { 17 | zoom: true, 18 | scrollX: true, 19 | scrollY: true, 20 | mouseWheel: true, 21 | wheelAction: 'zoom' 22 | }); 23 | } 24 | 25 | document.addEventListener('touchmove', function (e) { e.preventDefault(); }, isPassive() ? { 26 | capture: false, 27 | passive: false 28 | } : false); 29 | 30 | </script> 31 | 32 | <style type="text/css"> 33 | * { 34 | -webkit-box-sizing: border-box; 35 | -moz-box-sizing: border-box; 36 | box-sizing: border-box; 37 | } 38 | 39 | html { 40 | -ms-touch-action: none; 41 | } 42 | 43 | body,ul,li { 44 | padding: 0; 45 | margin: 0; 46 | border: 0; 47 | } 48 | 49 | body { 50 | font-size: 12px; 51 | font-family: ubuntu, helvetica, arial; 52 | overflow: hidden; /* this is important to prevent the whole page to bounce */ 53 | } 54 | 55 | #wrapper { 56 | position: absolute; 57 | z-index: 1; 58 | top: 50px; 59 | bottom: 50px; 60 | left: 50px; 61 | right: 50px; 62 | background: #ccc; 63 | overflow: hidden; 64 | } 65 | 66 | #scroller { 67 | position: absolute; 68 | z-index: 1; 69 | -webkit-tap-highlight-color: rgba(0,0,0,0); 70 | width: 100%; 71 | -webkit-transform: translateZ(0); 72 | -moz-transform: translateZ(0); 73 | -ms-transform: translateZ(0); 74 | -o-transform: translateZ(0); 75 | transform: translateZ(0); 76 | -webkit-touch-callout: none; 77 | -webkit-user-select: none; 78 | -moz-user-select: none; 79 | -ms-user-select: none; 80 | user-select: none; 81 | -webkit-text-size-adjust: none; 82 | -moz-text-size-adjust: none; 83 | -ms-text-size-adjust: none; 84 | -o-text-size-adjust: none; 85 | text-size-adjust: none; 86 | } 87 | 88 | #scroller ul { 89 | list-style: none; 90 | padding: 0; 91 | margin: 0; 92 | width: 100%; 93 | text-align: left; 94 | } 95 | 96 | #scroller li { 97 | padding: 0 10px; 98 | height: 40px; 99 | line-height: 40px; 100 | border-bottom: 1px solid #ccc; 101 | border-top: 1px solid #fff; 102 | background-color: #fafafa; 103 | font-size: 14px; 104 | } 105 | 106 | </style> 107 | </head> 108 | <body onload="loaded()"> 109 | 110 | <div id="wrapper"> 111 | <div id="scroller"> 112 | <ul> 113 | <li>Pretty row 1</li> 114 | <li>Pretty row 2</li> 115 | <li>Pretty row 3</li> 116 | <li>Pretty row 4</li> 117 | <li>Pretty row 5</li> 118 | <li>Pretty row 6</li> 119 | <li>Pretty row 7</li> 120 | <li>Pretty row 8</li> 121 | <li>Pretty row 9</li> 122 | <li>Pretty row 10</li> 123 | <li>Pretty row 11</li> 124 | <li>Pretty row 12</li> 125 | <li>Pretty row 13</li> 126 | <li>Pretty row 14</li> 127 | <li>Pretty row 15</li> 128 | <li>Pretty row 16</li> 129 | <li>Pretty row 17</li> 130 | <li>Pretty row 18</li> 131 | <li>Pretty row 19</li> 132 | <li>Pretty row 20</li> 133 | <li>Pretty row 21</li> 134 | <li>Pretty row 22</li> 135 | <li>Pretty row 23</li> 136 | <li>Pretty row 24</li> 137 | <li>Pretty row 25</li> 138 | <li>Pretty row 26</li> 139 | <li>Pretty row 27</li> 140 | <li>Pretty row 28</li> 141 | <li>Pretty row 29</li> 142 | <li>Pretty row 30</li> 143 | <li>Pretty row 31</li> 144 | <li>Pretty row 32</li> 145 | <li>Pretty row 33</li> 146 | <li>Pretty row 34</li> 147 | <li>Pretty row 35</li> 148 | <li>Pretty row 36</li> 149 | <li>Pretty row 37</li> 150 | <li>Pretty row 38</li> 151 | <li>Pretty row 39</li> 152 | <li>Pretty row 40</li> 153 | <li>Pretty row 41</li> 154 | <li>Pretty row 42</li> 155 | <li>Pretty row 43</li> 156 | <li>Pretty row 44</li> 157 | <li>Pretty row 45</li> 158 | <li>Pretty row 46</li> 159 | <li>Pretty row 47</li> 160 | <li>Pretty row 48</li> 161 | <li>Pretty row 49</li> 162 | <li>Pretty row 50</li> 163 | </ul> 164 | </div> 165 | </div> 166 | 167 | </body> 168 | </html> -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "iscroll", 3 | "description": "Smooth scrolling for the web", 4 | "version": "5.2.0-snapshot", 5 | "homepage": "http://iscrolljs.com", 6 | "author": "Matteo Spinelli <matteo@cubiq.org> (http://cubiq.org)", 7 | "keywords": [ 8 | "scrolling", 9 | "carousel", 10 | "zoom", 11 | "iphone", 12 | "android", 13 | "mobile", 14 | "desktop" 15 | ], 16 | "main": "build/iscroll.js", 17 | "devDependencies": { 18 | "jshint": "~2.9.1", 19 | "uglify-js": "~2.6.2" 20 | }, 21 | "repository": { 22 | "type": "git", 23 | "url": "https://github.com/cubiq/iscroll.git" 24 | }, 25 | "bugs": { 26 | "url": "https://github.com/cubiq/iscroll/issues" 27 | }, 28 | "license": "MIT" 29 | } 30 | -------------------------------------------------------------------------------- /src/close.js: -------------------------------------------------------------------------------- 1 | 2 | IScroll.utils = utils; 3 | 4 | if ( typeof module != 'undefined' && module.exports ) { 5 | module.exports = IScroll; 6 | } else if ( typeof define == 'function' && define.amd ) { 7 | define( function () { return IScroll; } ); 8 | } else { 9 | window.IScroll = IScroll; 10 | } 11 | 12 | })(window, document, Math); 13 | -------------------------------------------------------------------------------- /src/core.js: -------------------------------------------------------------------------------- 1 | 2 | function IScroll (el, options) { 3 | this.wrapper = typeof el == 'string' ? document.querySelector(el) : el; 4 | this.scroller = this.wrapper.children[0]; 5 | this.scrollerStyle = this.scroller.style; // cache style for better performance 6 | 7 | this.options = { 8 | 9 | // INSERT POINT: OPTIONS 10 | disablePointer : !utils.hasPointer, 11 | disableTouch : utils.hasPointer || !utils.hasTouch, 12 | disableMouse : utils.hasPointer || utils.hasTouch, 13 | startX: 0, 14 | startY: 0, 15 | scrollY: true, 16 | directionLockThreshold: 5, 17 | momentum: true, 18 | 19 | bounce: true, 20 | bounceTime: 600, 21 | bounceEasing: '', 22 | 23 | preventDefault: true, 24 | preventDefaultException: { tagName: /^(INPUT|TEXTAREA|BUTTON|SELECT)$/ }, 25 | 26 | HWCompositing: true, 27 | useTransition: true, 28 | useTransform: true, 29 | bindToWrapper: typeof window.onmousedown === "undefined" 30 | }; 31 | 32 | for ( var i in options ) { 33 | this.options[i] = options[i]; 34 | } 35 | 36 | // Normalize options 37 | this.translateZ = this.options.HWCompositing && utils.hasPerspective ? ' translateZ(0)' : ''; 38 | 39 | this.options.useTransition = utils.hasTransition && this.options.useTransition; 40 | this.options.useTransform = utils.hasTransform && this.options.useTransform; 41 | 42 | this.options.eventPassthrough = this.options.eventPassthrough === true ? 'vertical' : this.options.eventPassthrough; 43 | this.options.preventDefault = !this.options.eventPassthrough && this.options.preventDefault; 44 | 45 | // If you want eventPassthrough I have to lock one of the axes 46 | this.options.scrollY = this.options.eventPassthrough == 'vertical' ? false : this.options.scrollY; 47 | this.options.scrollX = this.options.eventPassthrough == 'horizontal' ? false : this.options.scrollX; 48 | 49 | // With eventPassthrough we also need lockDirection mechanism 50 | this.options.freeScroll = this.options.freeScroll && !this.options.eventPassthrough; 51 | this.options.directionLockThreshold = this.options.eventPassthrough ? 0 : this.options.directionLockThreshold; 52 | 53 | this.options.bounceEasing = typeof this.options.bounceEasing == 'string' ? utils.ease[this.options.bounceEasing] || utils.ease.circular : this.options.bounceEasing; 54 | 55 | this.options.resizePolling = this.options.resizePolling === undefined ? 60 : this.options.resizePolling; 56 | 57 | if ( this.options.tap === true ) { 58 | this.options.tap = 'tap'; 59 | } 60 | 61 | // https://github.com/cubiq/iscroll/issues/1029 62 | if (!this.options.useTransition && !this.options.useTransform) { 63 | if(!(/relative|absolute/i).test(this.scrollerStyle.position)) { 64 | this.scrollerStyle.position = "relative"; 65 | } 66 | } 67 | 68 | // INSERT POINT: NORMALIZATION 69 | 70 | // Some defaults 71 | this.x = 0; 72 | this.y = 0; 73 | this.directionX = 0; 74 | this.directionY = 0; 75 | this._events = {}; 76 | 77 | // INSERT POINT: DEFAULTS 78 | 79 | this._init(); 80 | this.refresh(); 81 | 82 | this.scrollTo(this.options.startX, this.options.startY); 83 | this.enable(); 84 | } 85 | 86 | IScroll.prototype = { 87 | version: '/* VERSION */', 88 | 89 | _init: function () { 90 | this._initEvents(); 91 | 92 | // INSERT POINT: _init 93 | 94 | }, 95 | 96 | destroy: function () { 97 | this._initEvents(true); 98 | clearTimeout(this.resizeTimeout); 99 | this.resizeTimeout = null; 100 | this._execEvent('destroy'); 101 | }, 102 | 103 | _transitionEnd: function (e) { 104 | if ( e.target != this.scroller || !this.isInTransition ) { 105 | return; 106 | } 107 | 108 | this._transitionTime(); 109 | if ( !this.resetPosition(this.options.bounceTime) ) { 110 | this.isInTransition = false; 111 | this._execEvent('scrollEnd'); 112 | } 113 | }, 114 | 115 | _start: function (e) { 116 | // React to left mouse button only 117 | if ( utils.eventType[e.type] != 1 ) { 118 | // for button property 119 | // http://unixpapa.com/js/mouse.html 120 | var button; 121 | if (!e.which) { 122 | /* IE case */ 123 | button = (e.button < 2) ? 0 : 124 | ((e.button == 4) ? 1 : 2); 125 | } else { 126 | /* All others */ 127 | button = e.button; 128 | } 129 | if ( button !== 0 ) { 130 | return; 131 | } 132 | } 133 | 134 | if ( !this.enabled || (this.initiated && utils.eventType[e.type] !== this.initiated) ) { 135 | return; 136 | } 137 | 138 | if ( this.options.preventDefault && !utils.isBadAndroid && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) { 139 | e.preventDefault(); 140 | } 141 | 142 | var point = e.touches ? e.touches[0] : e, 143 | pos; 144 | 145 | this.initiated = utils.eventType[e.type]; 146 | this.moved = false; 147 | this.distX = 0; 148 | this.distY = 0; 149 | this.directionX = 0; 150 | this.directionY = 0; 151 | this.directionLocked = 0; 152 | 153 | this.startTime = utils.getTime(); 154 | 155 | if ( this.options.useTransition && this.isInTransition ) { 156 | this._transitionTime(); 157 | this.isInTransition = false; 158 | pos = this.getComputedPosition(); 159 | this._translate(Math.round(pos.x), Math.round(pos.y)); 160 | this._execEvent('scrollEnd'); 161 | } else if ( !this.options.useTransition && this.isAnimating ) { 162 | this.isAnimating = false; 163 | this._execEvent('scrollEnd'); 164 | } 165 | 166 | this.startX = this.x; 167 | this.startY = this.y; 168 | this.absStartX = this.x; 169 | this.absStartY = this.y; 170 | this.pointX = point.pageX; 171 | this.pointY = point.pageY; 172 | 173 | this._execEvent('beforeScrollStart'); 174 | }, 175 | 176 | _move: function (e) { 177 | if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) { 178 | return; 179 | } 180 | 181 | if ( this.options.preventDefault ) { // increases performance on Android? TODO: check! 182 | e.preventDefault(); 183 | } 184 | 185 | var point = e.touches ? e.touches[0] : e, 186 | deltaX = point.pageX - this.pointX, 187 | deltaY = point.pageY - this.pointY, 188 | timestamp = utils.getTime(), 189 | newX, newY, 190 | absDistX, absDistY; 191 | 192 | this.pointX = point.pageX; 193 | this.pointY = point.pageY; 194 | 195 | this.distX += deltaX; 196 | this.distY += deltaY; 197 | absDistX = Math.abs(this.distX); 198 | absDistY = Math.abs(this.distY); 199 | 200 | // We need to move at least 10 pixels for the scrolling to initiate 201 | if ( timestamp - this.endTime > 300 && (absDistX < 10 && absDistY < 10) ) { 202 | return; 203 | } 204 | 205 | // If you are scrolling in one direction lock the other 206 | if ( !this.directionLocked && !this.options.freeScroll ) { 207 | if ( absDistX > absDistY + this.options.directionLockThreshold ) { 208 | this.directionLocked = 'h'; // lock horizontally 209 | } else if ( absDistY >= absDistX + this.options.directionLockThreshold ) { 210 | this.directionLocked = 'v'; // lock vertically 211 | } else { 212 | this.directionLocked = 'n'; // no lock 213 | } 214 | } 215 | 216 | if ( this.directionLocked == 'h' ) { 217 | if ( this.options.eventPassthrough == 'vertical' ) { 218 | e.preventDefault(); 219 | } else if ( this.options.eventPassthrough == 'horizontal' ) { 220 | this.initiated = false; 221 | return; 222 | } 223 | 224 | deltaY = 0; 225 | } else if ( this.directionLocked == 'v' ) { 226 | if ( this.options.eventPassthrough == 'horizontal' ) { 227 | e.preventDefault(); 228 | } else if ( this.options.eventPassthrough == 'vertical' ) { 229 | this.initiated = false; 230 | return; 231 | } 232 | 233 | deltaX = 0; 234 | } 235 | 236 | deltaX = this.hasHorizontalScroll ? deltaX : 0; 237 | deltaY = this.hasVerticalScroll ? deltaY : 0; 238 | 239 | newX = this.x + deltaX; 240 | newY = this.y + deltaY; 241 | 242 | // Slow down if outside of the boundaries 243 | if ( newX > 0 || newX < this.maxScrollX ) { 244 | newX = this.options.bounce ? this.x + deltaX / 3 : newX > 0 ? 0 : this.maxScrollX; 245 | } 246 | if ( newY > 0 || newY < this.maxScrollY ) { 247 | newY = this.options.bounce ? this.y + deltaY / 3 : newY > 0 ? 0 : this.maxScrollY; 248 | } 249 | 250 | this.directionX = deltaX > 0 ? -1 : deltaX < 0 ? 1 : 0; 251 | this.directionY = deltaY > 0 ? -1 : deltaY < 0 ? 1 : 0; 252 | 253 | if ( !this.moved ) { 254 | this._execEvent('scrollStart'); 255 | } 256 | 257 | this.moved = true; 258 | 259 | this._translate(newX, newY); 260 | 261 | /* REPLACE START: _move */ 262 | 263 | if ( timestamp - this.startTime > 300 ) { 264 | this.startTime = timestamp; 265 | this.startX = this.x; 266 | this.startY = this.y; 267 | } 268 | 269 | /* REPLACE END: _move */ 270 | 271 | }, 272 | 273 | _end: function (e) { 274 | if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) { 275 | return; 276 | } 277 | 278 | if ( this.options.preventDefault && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) { 279 | e.preventDefault(); 280 | } 281 | 282 | var point = e.changedTouches ? e.changedTouches[0] : e, 283 | momentumX, 284 | momentumY, 285 | duration = utils.getTime() - this.startTime, 286 | newX = Math.round(this.x), 287 | newY = Math.round(this.y), 288 | distanceX = Math.abs(newX - this.startX), 289 | distanceY = Math.abs(newY - this.startY), 290 | time = 0, 291 | easing = ''; 292 | 293 | this.isInTransition = 0; 294 | this.initiated = 0; 295 | this.endTime = utils.getTime(); 296 | 297 | // reset if we are outside of the boundaries 298 | if ( this.resetPosition(this.options.bounceTime) ) { 299 | return; 300 | } 301 | 302 | this.scrollTo(newX, newY); // ensures that the last position is rounded 303 | 304 | // we scrolled less than 10 pixels 305 | if ( !this.moved ) { 306 | if ( this.options.tap ) { 307 | utils.tap(e, this.options.tap); 308 | } 309 | 310 | if ( this.options.click ) { 311 | utils.click(e); 312 | } 313 | 314 | this._execEvent('scrollCancel'); 315 | return; 316 | } 317 | 318 | if ( this._events.flick && duration < 200 && distanceX < 100 && distanceY < 100 ) { 319 | this._execEvent('flick'); 320 | return; 321 | } 322 | 323 | // start momentum animation if needed 324 | if ( this.options.momentum && duration < 300 ) { 325 | momentumX = this.hasHorizontalScroll ? utils.momentum(this.x, this.startX, duration, this.maxScrollX, this.options.bounce ? this.wrapperWidth : 0, this.options.deceleration) : { destination: newX, duration: 0 }; 326 | momentumY = this.hasVerticalScroll ? utils.momentum(this.y, this.startY, duration, this.maxScrollY, this.options.bounce ? this.wrapperHeight : 0, this.options.deceleration) : { destination: newY, duration: 0 }; 327 | newX = momentumX.destination; 328 | newY = momentumY.destination; 329 | time = Math.max(momentumX.duration, momentumY.duration); 330 | this.isInTransition = 1; 331 | } 332 | 333 | // INSERT POINT: _end 334 | 335 | if ( newX != this.x || newY != this.y ) { 336 | // change easing function when scroller goes out of the boundaries 337 | if ( newX > 0 || newX < this.maxScrollX || newY > 0 || newY < this.maxScrollY ) { 338 | easing = utils.ease.quadratic; 339 | } 340 | 341 | this.scrollTo(newX, newY, time, easing); 342 | return; 343 | } 344 | 345 | this._execEvent('scrollEnd'); 346 | }, 347 | 348 | _resize: function () { 349 | var that = this; 350 | 351 | clearTimeout(this.resizeTimeout); 352 | 353 | this.resizeTimeout = setTimeout(function () { 354 | that.refresh(); 355 | }, this.options.resizePolling); 356 | }, 357 | 358 | resetPosition: function (time) { 359 | var x = this.x, 360 | y = this.y; 361 | 362 | time = time || 0; 363 | 364 | if ( !this.hasHorizontalScroll || this.x > 0 ) { 365 | x = 0; 366 | } else if ( this.x < this.maxScrollX ) { 367 | x = this.maxScrollX; 368 | } 369 | 370 | if ( !this.hasVerticalScroll || this.y > 0 ) { 371 | y = 0; 372 | } else if ( this.y < this.maxScrollY ) { 373 | y = this.maxScrollY; 374 | } 375 | 376 | if ( x == this.x && y == this.y ) { 377 | return false; 378 | } 379 | 380 | this.scrollTo(x, y, time, this.options.bounceEasing); 381 | 382 | return true; 383 | }, 384 | 385 | disable: function () { 386 | this.enabled = false; 387 | }, 388 | 389 | enable: function () { 390 | this.enabled = true; 391 | }, 392 | 393 | refresh: function () { 394 | utils.getRect(this.wrapper); // Force reflow 395 | 396 | this.wrapperWidth = this.wrapper.clientWidth; 397 | this.wrapperHeight = this.wrapper.clientHeight; 398 | 399 | var rect = utils.getRect(this.scroller); 400 | /* REPLACE START: refresh */ 401 | 402 | this.scrollerWidth = rect.width; 403 | this.scrollerHeight = rect.height; 404 | 405 | this.maxScrollX = this.wrapperWidth - this.scrollerWidth; 406 | this.maxScrollY = this.wrapperHeight - this.scrollerHeight; 407 | 408 | /* REPLACE END: refresh */ 409 | 410 | this.hasHorizontalScroll = this.options.scrollX && this.maxScrollX < 0; 411 | this.hasVerticalScroll = this.options.scrollY && this.maxScrollY < 0; 412 | 413 | if ( !this.hasHorizontalScroll ) { 414 | this.maxScrollX = 0; 415 | this.scrollerWidth = this.wrapperWidth; 416 | } 417 | 418 | if ( !this.hasVerticalScroll ) { 419 | this.maxScrollY = 0; 420 | this.scrollerHeight = this.wrapperHeight; 421 | } 422 | 423 | this.endTime = 0; 424 | this.directionX = 0; 425 | this.directionY = 0; 426 | 427 | if(utils.hasPointer && !this.options.disablePointer) { 428 | // The wrapper should have `touchAction` property for using pointerEvent. 429 | this.wrapper.style[utils.style.touchAction] = utils.getTouchAction(this.options.eventPassthrough, true); 430 | 431 | // case. not support 'pinch-zoom' 432 | // https://github.com/cubiq/iscroll/issues/1118#issuecomment-270057583 433 | if (!this.wrapper.style[utils.style.touchAction]) { 434 | this.wrapper.style[utils.style.touchAction] = utils.getTouchAction(this.options.eventPassthrough, false); 435 | } 436 | } 437 | this.wrapperOffset = utils.offset(this.wrapper); 438 | 439 | this._execEvent('refresh'); 440 | 441 | this.resetPosition(); 442 | 443 | // INSERT POINT: _refresh 444 | 445 | }, 446 | 447 | on: function (type, fn) { 448 | if ( !this._events[type] ) { 449 | this._events[type] = []; 450 | } 451 | 452 | this._events[type].push(fn); 453 | }, 454 | 455 | off: function (type, fn) { 456 | if ( !this._events[type] ) { 457 | return; 458 | } 459 | 460 | var index = this._events[type].indexOf(fn); 461 | 462 | if ( index > -1 ) { 463 | this._events[type].splice(index, 1); 464 | } 465 | }, 466 | 467 | _execEvent: function (type) { 468 | if ( !this._events[type] ) { 469 | return; 470 | } 471 | 472 | var i = 0, 473 | l = this._events[type].length; 474 | 475 | if ( !l ) { 476 | return; 477 | } 478 | 479 | for ( ; i < l; i++ ) { 480 | this._events[type][i].apply(this, [].slice.call(arguments, 1)); 481 | } 482 | }, 483 | 484 | scrollBy: function (x, y, time, easing) { 485 | x = this.x + x; 486 | y = this.y + y; 487 | time = time || 0; 488 | 489 | this.scrollTo(x, y, time, easing); 490 | }, 491 | 492 | scrollTo: function (x, y, time, easing) { 493 | easing = easing || utils.ease.circular; 494 | 495 | this.isInTransition = this.options.useTransition && time > 0; 496 | var transitionType = this.options.useTransition && easing.style; 497 | if ( !time || transitionType ) { 498 | if(transitionType) { 499 | this._transitionTimingFunction(easing.style); 500 | this._transitionTime(time); 501 | } 502 | this._translate(x, y); 503 | } else { 504 | this._animate(x, y, time, easing.fn); 505 | } 506 | }, 507 | 508 | scrollToElement: function (el, time, offsetX, offsetY, easing) { 509 | el = el.nodeType ? el : this.scroller.querySelector(el); 510 | 511 | if ( !el ) { 512 | return; 513 | } 514 | 515 | var pos = utils.offset(el); 516 | 517 | pos.left -= this.wrapperOffset.left; 518 | pos.top -= this.wrapperOffset.top; 519 | 520 | // if offsetX/Y are true we center the element to the screen 521 | var elRect = utils.getRect(el); 522 | var wrapperRect = utils.getRect(this.wrapper); 523 | if ( offsetX === true ) { 524 | offsetX = Math.round(elRect.width / 2 - wrapperRect.width / 2); 525 | } 526 | if ( offsetY === true ) { 527 | offsetY = Math.round(elRect.height / 2 - wrapperRect.height / 2); 528 | } 529 | 530 | pos.left -= offsetX || 0; 531 | pos.top -= offsetY || 0; 532 | 533 | pos.left = pos.left > 0 ? 0 : pos.left < this.maxScrollX ? this.maxScrollX : pos.left; 534 | pos.top = pos.top > 0 ? 0 : pos.top < this.maxScrollY ? this.maxScrollY : pos.top; 535 | 536 | time = time === undefined || time === null || time === 'auto' ? Math.max(Math.abs(this.x-pos.left), Math.abs(this.y-pos.top)) : time; 537 | 538 | this.scrollTo(pos.left, pos.top, time, easing); 539 | }, 540 | 541 | _transitionTime: function (time) { 542 | if (!this.options.useTransition) { 543 | return; 544 | } 545 | time = time || 0; 546 | var durationProp = utils.style.transitionDuration; 547 | if(!durationProp) { 548 | return; 549 | } 550 | 551 | this.scrollerStyle[durationProp] = time + 'ms'; 552 | 553 | if ( !time && utils.isBadAndroid ) { 554 | this.scrollerStyle[durationProp] = '0.0001ms'; 555 | // remove 0.0001ms 556 | var self = this; 557 | rAF(function() { 558 | if(self.scrollerStyle[durationProp] === '0.0001ms') { 559 | self.scrollerStyle[durationProp] = '0s'; 560 | } 561 | }); 562 | } 563 | 564 | // INSERT POINT: _transitionTime 565 | 566 | }, 567 | 568 | _transitionTimingFunction: function (easing) { 569 | this.scrollerStyle[utils.style.transitionTimingFunction] = easing; 570 | 571 | // INSERT POINT: _transitionTimingFunction 572 | 573 | }, 574 | 575 | _translate: function (x, y) { 576 | if ( this.options.useTransform ) { 577 | 578 | /* REPLACE START: _translate */ 579 | 580 | this.scrollerStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.translateZ; 581 | 582 | /* REPLACE END: _translate */ 583 | 584 | } else { 585 | x = Math.round(x); 586 | y = Math.round(y); 587 | this.scrollerStyle.left = x + 'px'; 588 | this.scrollerStyle.top = y + 'px'; 589 | } 590 | 591 | this.x = x; 592 | this.y = y; 593 | 594 | // INSERT POINT: _translate 595 | 596 | }, 597 | 598 | _initEvents: function (remove) { 599 | var eventType = remove ? utils.removeEvent : utils.addEvent, 600 | target = this.options.bindToWrapper ? this.wrapper : window; 601 | 602 | eventType(window, 'orientationchange', this); 603 | eventType(window, 'resize', this); 604 | 605 | if ( this.options.click ) { 606 | eventType(this.wrapper, 'click', this, true); 607 | } 608 | 609 | if ( !this.options.disableMouse ) { 610 | eventType(this.wrapper, 'mousedown', this); 611 | eventType(target, 'mousemove', this); 612 | eventType(target, 'mousecancel', this); 613 | eventType(target, 'mouseup', this); 614 | } 615 | 616 | if ( utils.hasPointer && !this.options.disablePointer ) { 617 | eventType(this.wrapper, utils.prefixPointerEvent('pointerdown'), this); 618 | eventType(target, utils.prefixPointerEvent('pointermove'), this); 619 | eventType(target, utils.prefixPointerEvent('pointercancel'), this); 620 | eventType(target, utils.prefixPointerEvent('pointerup'), this); 621 | } 622 | 623 | if ( utils.hasTouch && !this.options.disableTouch ) { 624 | eventType(this.wrapper, 'touchstart', this); 625 | eventType(target, 'touchmove', this); 626 | eventType(target, 'touchcancel', this); 627 | eventType(target, 'touchend', this); 628 | } 629 | 630 | eventType(this.scroller, 'transitionend', this); 631 | eventType(this.scroller, 'webkitTransitionEnd', this); 632 | eventType(this.scroller, 'oTransitionEnd', this); 633 | eventType(this.scroller, 'MSTransitionEnd', this); 634 | }, 635 | 636 | getComputedPosition: function () { 637 | var matrix = window.getComputedStyle(this.scroller, null), 638 | x, y; 639 | 640 | if ( this.options.useTransform ) { 641 | matrix = matrix[utils.style.transform].split(')')[0].split(', '); 642 | x = +(matrix[12] || matrix[4]); 643 | y = +(matrix[13] || matrix[5]); 644 | } else { 645 | x = +matrix.left.replace(/[^-\d.]/g, ''); 646 | y = +matrix.top.replace(/[^-\d.]/g, ''); 647 | } 648 | 649 | return { x: x, y: y }; 650 | }, -------------------------------------------------------------------------------- /src/default/_animate.js: -------------------------------------------------------------------------------- 1 | 2 | _animate: function (destX, destY, duration, easingFn) { 3 | var that = this, 4 | startX = this.x, 5 | startY = this.y, 6 | startTime = utils.getTime(), 7 | destTime = startTime + duration; 8 | 9 | function step () { 10 | var now = utils.getTime(), 11 | newX, newY, 12 | easing; 13 | 14 | if ( now >= destTime ) { 15 | that.isAnimating = false; 16 | that._translate(destX, destY); 17 | 18 | if ( !that.resetPosition(that.options.bounceTime) ) { 19 | that._execEvent('scrollEnd'); 20 | } 21 | 22 | return; 23 | } 24 | 25 | now = ( now - startTime ) / duration; 26 | easing = easingFn(now); 27 | newX = ( destX - startX ) * easing + startX; 28 | newY = ( destY - startY ) * easing + startY; 29 | that._translate(newX, newY); 30 | 31 | if ( that.isAnimating ) { 32 | rAF(step); 33 | } 34 | } 35 | 36 | this.isAnimating = true; 37 | step(); 38 | }, -------------------------------------------------------------------------------- /src/default/handleEvent.js: -------------------------------------------------------------------------------- 1 | 2 | handleEvent: function (e) { 3 | switch ( e.type ) { 4 | case 'touchstart': 5 | case 'pointerdown': 6 | case 'MSPointerDown': 7 | case 'mousedown': 8 | this._start(e); 9 | break; 10 | case 'touchmove': 11 | case 'pointermove': 12 | case 'MSPointerMove': 13 | case 'mousemove': 14 | this._move(e); 15 | break; 16 | case 'touchend': 17 | case 'pointerup': 18 | case 'MSPointerUp': 19 | case 'mouseup': 20 | case 'touchcancel': 21 | case 'pointercancel': 22 | case 'MSPointerCancel': 23 | case 'mousecancel': 24 | this._end(e); 25 | break; 26 | case 'orientationchange': 27 | case 'resize': 28 | this._resize(); 29 | break; 30 | case 'transitionend': 31 | case 'webkitTransitionEnd': 32 | case 'oTransitionEnd': 33 | case 'MSTransitionEnd': 34 | this._transitionEnd(e); 35 | break; 36 | case 'wheel': 37 | case 'DOMMouseScroll': 38 | case 'mousewheel': 39 | this._wheel(e); 40 | break; 41 | case 'keydown': 42 | this._key(e); 43 | break; 44 | case 'click': 45 | if ( this.enabled && !e._constructed ) { 46 | e.preventDefault(); 47 | e.stopPropagation(); 48 | } 49 | break; 50 | } 51 | } 52 | }; -------------------------------------------------------------------------------- /src/indicator/_initIndicators.js: -------------------------------------------------------------------------------- 1 | 2 | _initIndicators: function () { 3 | var interactive = this.options.interactiveScrollbars, 4 | customStyle = typeof this.options.scrollbars != 'string', 5 | indicators = [], 6 | indicator; 7 | 8 | var that = this; 9 | 10 | this.indicators = []; 11 | 12 | if ( this.options.scrollbars ) { 13 | // Vertical scrollbar 14 | if ( this.options.scrollY ) { 15 | indicator = { 16 | el: createDefaultScrollbar('v', interactive, this.options.scrollbars), 17 | interactive: interactive, 18 | defaultScrollbars: true, 19 | customStyle: customStyle, 20 | resize: this.options.resizeScrollbars, 21 | shrink: this.options.shrinkScrollbars, 22 | fade: this.options.fadeScrollbars, 23 | listenX: false 24 | }; 25 | 26 | this.wrapper.appendChild(indicator.el); 27 | indicators.push(indicator); 28 | } 29 | 30 | // Horizontal scrollbar 31 | if ( this.options.scrollX ) { 32 | indicator = { 33 | el: createDefaultScrollbar('h', interactive, this.options.scrollbars), 34 | interactive: interactive, 35 | defaultScrollbars: true, 36 | customStyle: customStyle, 37 | resize: this.options.resizeScrollbars, 38 | shrink: this.options.shrinkScrollbars, 39 | fade: this.options.fadeScrollbars, 40 | listenY: false 41 | }; 42 | 43 | this.wrapper.appendChild(indicator.el); 44 | indicators.push(indicator); 45 | } 46 | } 47 | 48 | if ( this.options.indicators ) { 49 | // TODO: check concat compatibility 50 | indicators = indicators.concat(this.options.indicators); 51 | } 52 | 53 | for ( var i = indicators.length; i--; ) { 54 | this.indicators.push( new Indicator(this, indicators[i]) ); 55 | } 56 | 57 | // TODO: check if we can use array.map (wide compatibility and performance issues) 58 | function _indicatorsMap (fn) { 59 | if (that.indicators) { 60 | for ( var i = that.indicators.length; i--; ) { 61 | fn.call(that.indicators[i]); 62 | } 63 | } 64 | } 65 | 66 | if ( this.options.fadeScrollbars ) { 67 | this.on('scrollEnd', function () { 68 | _indicatorsMap(function () { 69 | this.fade(); 70 | }); 71 | }); 72 | 73 | this.on('scrollCancel', function () { 74 | _indicatorsMap(function () { 75 | this.fade(); 76 | }); 77 | }); 78 | 79 | this.on('scrollStart', function () { 80 | _indicatorsMap(function () { 81 | this.fade(1); 82 | }); 83 | }); 84 | 85 | this.on('beforeScrollStart', function () { 86 | _indicatorsMap(function () { 87 | this.fade(1, true); 88 | }); 89 | }); 90 | } 91 | 92 | 93 | this.on('refresh', function () { 94 | _indicatorsMap(function () { 95 | this.refresh(); 96 | }); 97 | }); 98 | 99 | this.on('destroy', function () { 100 | _indicatorsMap(function () { 101 | this.destroy(); 102 | }); 103 | 104 | delete this.indicators; 105 | }); 106 | }, 107 | -------------------------------------------------------------------------------- /src/indicator/_transitionTime.js: -------------------------------------------------------------------------------- 1 | 2 | if ( this.indicators ) { 3 | for ( var i = this.indicators.length; i--; ) { 4 | this.indicators[i].transitionTime(time); 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/indicator/_transitionTimingFunction.js: -------------------------------------------------------------------------------- 1 | 2 | if ( this.indicators ) { 3 | for ( var i = this.indicators.length; i--; ) { 4 | this.indicators[i].transitionTimingFunction(easing); 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/indicator/_translate.js: -------------------------------------------------------------------------------- 1 | 2 | if ( this.indicators ) { 3 | for ( var i = this.indicators.length; i--; ) { 4 | this.indicators[i].updatePosition(); 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/indicator/build.json: -------------------------------------------------------------------------------- 1 | { 2 | "insert": { 3 | "OPTIONS": "\t\tresizeScrollbars: true,", 4 | "NORMALIZATION": "\tif ( this.options.shrinkScrollbars == 'scale' ) {\n\t\tthis.options.useTransition = false;\n\t}", 5 | "_init": "\t\tif ( this.options.scrollbars || this.options.indicators ) {\n\t\t\tthis._initIndicators();\n\t\t}", 6 | "_transitionTime": "indicator/_transitionTime.js", 7 | "_transitionTimingFunction": "indicator/_transitionTimingFunction.js", 8 | "_translate": "indicator/_translate.js" 9 | } 10 | } -------------------------------------------------------------------------------- /src/indicator/indicator.js: -------------------------------------------------------------------------------- 1 | 2 | function createDefaultScrollbar (direction, interactive, type) { 3 | var scrollbar = document.createElement('div'), 4 | indicator = document.createElement('div'); 5 | 6 | if ( type === true ) { 7 | scrollbar.style.cssText = 'position:absolute;z-index:9999'; 8 | indicator.style.cssText = '-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;position:absolute;background:rgba(0,0,0,0.5);border:1px solid rgba(255,255,255,0.9);border-radius:3px'; 9 | } 10 | 11 | indicator.className = 'iScrollIndicator'; 12 | 13 | if ( direction == 'h' ) { 14 | if ( type === true ) { 15 | scrollbar.style.cssText += ';height:7px;left:2px;right:2px;bottom:0'; 16 | indicator.style.height = '100%'; 17 | } 18 | scrollbar.className = 'iScrollHorizontalScrollbar'; 19 | } else { 20 | if ( type === true ) { 21 | scrollbar.style.cssText += ';width:7px;bottom:2px;top:2px;right:1px'; 22 | indicator.style.width = '100%'; 23 | } 24 | scrollbar.className = 'iScrollVerticalScrollbar'; 25 | } 26 | 27 | scrollbar.style.cssText += ';overflow:hidden'; 28 | 29 | if ( !interactive ) { 30 | scrollbar.style.pointerEvents = 'none'; 31 | } 32 | 33 | scrollbar.appendChild(indicator); 34 | 35 | return scrollbar; 36 | } 37 | 38 | function Indicator (scroller, options) { 39 | this.wrapper = typeof options.el == 'string' ? document.querySelector(options.el) : options.el; 40 | this.wrapperStyle = this.wrapper.style; 41 | this.indicator = this.wrapper.children[0]; 42 | this.indicatorStyle = this.indicator.style; 43 | this.scroller = scroller; 44 | 45 | this.options = { 46 | listenX: true, 47 | listenY: true, 48 | interactive: false, 49 | resize: true, 50 | defaultScrollbars: false, 51 | shrink: false, 52 | fade: false, 53 | speedRatioX: 0, 54 | speedRatioY: 0 55 | }; 56 | 57 | for ( var i in options ) { 58 | this.options[i] = options[i]; 59 | } 60 | 61 | this.sizeRatioX = 1; 62 | this.sizeRatioY = 1; 63 | this.maxPosX = 0; 64 | this.maxPosY = 0; 65 | 66 | if ( this.options.interactive ) { 67 | if ( !this.options.disableTouch ) { 68 | utils.addEvent(this.indicator, 'touchstart', this); 69 | utils.addEvent(window, 'touchend', this); 70 | } 71 | if ( !this.options.disablePointer ) { 72 | utils.addEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this); 73 | utils.addEvent(window, utils.prefixPointerEvent('pointerup'), this); 74 | } 75 | if ( !this.options.disableMouse ) { 76 | utils.addEvent(this.indicator, 'mousedown', this); 77 | utils.addEvent(window, 'mouseup', this); 78 | } 79 | } 80 | 81 | if ( this.options.fade ) { 82 | this.wrapperStyle[utils.style.transform] = this.scroller.translateZ; 83 | var durationProp = utils.style.transitionDuration; 84 | if(!durationProp) { 85 | return; 86 | } 87 | this.wrapperStyle[durationProp] = utils.isBadAndroid ? '0.0001ms' : '0ms'; 88 | // remove 0.0001ms 89 | var self = this; 90 | if(utils.isBadAndroid) { 91 | rAF(function() { 92 | if(self.wrapperStyle[durationProp] === '0.0001ms') { 93 | self.wrapperStyle[durationProp] = '0s'; 94 | } 95 | }); 96 | } 97 | this.wrapperStyle.opacity = '0'; 98 | } 99 | } 100 | 101 | Indicator.prototype = { 102 | handleEvent: function (e) { 103 | switch ( e.type ) { 104 | case 'touchstart': 105 | case 'pointerdown': 106 | case 'MSPointerDown': 107 | case 'mousedown': 108 | this._start(e); 109 | break; 110 | case 'touchmove': 111 | case 'pointermove': 112 | case 'MSPointerMove': 113 | case 'mousemove': 114 | this._move(e); 115 | break; 116 | case 'touchend': 117 | case 'pointerup': 118 | case 'MSPointerUp': 119 | case 'mouseup': 120 | case 'touchcancel': 121 | case 'pointercancel': 122 | case 'MSPointerCancel': 123 | case 'mousecancel': 124 | this._end(e); 125 | break; 126 | } 127 | }, 128 | 129 | destroy: function () { 130 | if ( this.options.fadeScrollbars ) { 131 | clearTimeout(this.fadeTimeout); 132 | this.fadeTimeout = null; 133 | } 134 | if ( this.options.interactive ) { 135 | utils.removeEvent(this.indicator, 'touchstart', this); 136 | utils.removeEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this); 137 | utils.removeEvent(this.indicator, 'mousedown', this); 138 | 139 | utils.removeEvent(window, 'touchmove', this); 140 | utils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this); 141 | utils.removeEvent(window, 'mousemove', this); 142 | 143 | utils.removeEvent(window, 'touchend', this); 144 | utils.removeEvent(window, utils.prefixPointerEvent('pointerup'), this); 145 | utils.removeEvent(window, 'mouseup', this); 146 | } 147 | 148 | if ( this.options.defaultScrollbars && this.wrapper.parentNode ) { 149 | this.wrapper.parentNode.removeChild(this.wrapper); 150 | } 151 | }, 152 | 153 | _start: function (e) { 154 | var point = e.touches ? e.touches[0] : e; 155 | 156 | e.preventDefault(); 157 | e.stopPropagation(); 158 | 159 | this.transitionTime(); 160 | 161 | this.initiated = true; 162 | this.moved = false; 163 | this.lastPointX = point.pageX; 164 | this.lastPointY = point.pageY; 165 | 166 | this.startTime = utils.getTime(); 167 | 168 | if ( !this.options.disableTouch ) { 169 | utils.addEvent(window, 'touchmove', this); 170 | } 171 | if ( !this.options.disablePointer ) { 172 | utils.addEvent(window, utils.prefixPointerEvent('pointermove'), this); 173 | } 174 | if ( !this.options.disableMouse ) { 175 | utils.addEvent(window, 'mousemove', this); 176 | } 177 | 178 | this.scroller._execEvent('beforeScrollStart'); 179 | }, 180 | 181 | _move: function (e) { 182 | var point = e.touches ? e.touches[0] : e, 183 | deltaX, deltaY, 184 | newX, newY, 185 | timestamp = utils.getTime(); 186 | 187 | if ( !this.moved ) { 188 | this.scroller._execEvent('scrollStart'); 189 | } 190 | 191 | this.moved = true; 192 | 193 | deltaX = point.pageX - this.lastPointX; 194 | this.lastPointX = point.pageX; 195 | 196 | deltaY = point.pageY - this.lastPointY; 197 | this.lastPointY = point.pageY; 198 | 199 | newX = this.x + deltaX; 200 | newY = this.y + deltaY; 201 | 202 | this._pos(newX, newY); 203 | 204 | // INSERT POINT: indicator._move 205 | 206 | e.preventDefault(); 207 | e.stopPropagation(); 208 | }, 209 | 210 | _end: function (e) { 211 | if ( !this.initiated ) { 212 | return; 213 | } 214 | 215 | this.initiated = false; 216 | 217 | e.preventDefault(); 218 | e.stopPropagation(); 219 | 220 | utils.removeEvent(window, 'touchmove', this); 221 | utils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this); 222 | utils.removeEvent(window, 'mousemove', this); 223 | 224 | if ( this.scroller.options.snap ) { 225 | var snap = this.scroller._nearestSnap(this.scroller.x, this.scroller.y); 226 | 227 | var time = this.options.snapSpeed || Math.max( 228 | Math.max( 229 | Math.min(Math.abs(this.scroller.x - snap.x), 1000), 230 | Math.min(Math.abs(this.scroller.y - snap.y), 1000) 231 | ), 300); 232 | 233 | if ( this.scroller.x != snap.x || this.scroller.y != snap.y ) { 234 | this.scroller.directionX = 0; 235 | this.scroller.directionY = 0; 236 | this.scroller.currentPage = snap; 237 | this.scroller.scrollTo(snap.x, snap.y, time, this.scroller.options.bounceEasing); 238 | } 239 | } 240 | 241 | if ( this.moved ) { 242 | this.scroller._execEvent('scrollEnd'); 243 | } 244 | }, 245 | 246 | transitionTime: function (time) { 247 | time = time || 0; 248 | var durationProp = utils.style.transitionDuration; 249 | if(!durationProp) { 250 | return; 251 | } 252 | 253 | this.indicatorStyle[durationProp] = time + 'ms'; 254 | 255 | if ( !time && utils.isBadAndroid ) { 256 | this.indicatorStyle[durationProp] = '0.0001ms'; 257 | // remove 0.0001ms 258 | var self = this; 259 | rAF(function() { 260 | if(self.indicatorStyle[durationProp] === '0.0001ms') { 261 | self.indicatorStyle[durationProp] = '0s'; 262 | } 263 | }); 264 | } 265 | }, 266 | 267 | transitionTimingFunction: function (easing) { 268 | this.indicatorStyle[utils.style.transitionTimingFunction] = easing; 269 | }, 270 | 271 | refresh: function () { 272 | this.transitionTime(); 273 | 274 | if ( this.options.listenX && !this.options.listenY ) { 275 | this.indicatorStyle.display = this.scroller.hasHorizontalScroll ? 'block' : 'none'; 276 | } else if ( this.options.listenY && !this.options.listenX ) { 277 | this.indicatorStyle.display = this.scroller.hasVerticalScroll ? 'block' : 'none'; 278 | } else { 279 | this.indicatorStyle.display = this.scroller.hasHorizontalScroll || this.scroller.hasVerticalScroll ? 'block' : 'none'; 280 | } 281 | 282 | if ( this.scroller.hasHorizontalScroll && this.scroller.hasVerticalScroll ) { 283 | utils.addClass(this.wrapper, 'iScrollBothScrollbars'); 284 | utils.removeClass(this.wrapper, 'iScrollLoneScrollbar'); 285 | 286 | if ( this.options.defaultScrollbars && this.options.customStyle ) { 287 | if ( this.options.listenX ) { 288 | this.wrapper.style.right = '8px'; 289 | } else { 290 | this.wrapper.style.bottom = '8px'; 291 | } 292 | } 293 | } else { 294 | utils.removeClass(this.wrapper, 'iScrollBothScrollbars'); 295 | utils.addClass(this.wrapper, 'iScrollLoneScrollbar'); 296 | 297 | if ( this.options.defaultScrollbars && this.options.customStyle ) { 298 | if ( this.options.listenX ) { 299 | this.wrapper.style.right = '2px'; 300 | } else { 301 | this.wrapper.style.bottom = '2px'; 302 | } 303 | } 304 | } 305 | 306 | utils.getRect(this.wrapper); // force refresh 307 | 308 | if ( this.options.listenX ) { 309 | this.wrapperWidth = this.wrapper.clientWidth; 310 | if ( this.options.resize ) { 311 | this.indicatorWidth = Math.max(Math.round(this.wrapperWidth * this.wrapperWidth / (this.scroller.scrollerWidth || this.wrapperWidth || 1)), 8); 312 | this.indicatorStyle.width = this.indicatorWidth + 'px'; 313 | } else { 314 | this.indicatorWidth = this.indicator.clientWidth; 315 | } 316 | 317 | this.maxPosX = this.wrapperWidth - this.indicatorWidth; 318 | 319 | if ( this.options.shrink == 'clip' ) { 320 | this.minBoundaryX = -this.indicatorWidth + 8; 321 | this.maxBoundaryX = this.wrapperWidth - 8; 322 | } else { 323 | this.minBoundaryX = 0; 324 | this.maxBoundaryX = this.maxPosX; 325 | } 326 | 327 | this.sizeRatioX = this.options.speedRatioX || (this.scroller.maxScrollX && (this.maxPosX / this.scroller.maxScrollX)); 328 | } 329 | 330 | if ( this.options.listenY ) { 331 | this.wrapperHeight = this.wrapper.clientHeight; 332 | if ( this.options.resize ) { 333 | this.indicatorHeight = Math.max(Math.round(this.wrapperHeight * this.wrapperHeight / (this.scroller.scrollerHeight || this.wrapperHeight || 1)), 8); 334 | this.indicatorStyle.height = this.indicatorHeight + 'px'; 335 | } else { 336 | this.indicatorHeight = this.indicator.clientHeight; 337 | } 338 | 339 | this.maxPosY = this.wrapperHeight - this.indicatorHeight; 340 | 341 | if ( this.options.shrink == 'clip' ) { 342 | this.minBoundaryY = -this.indicatorHeight + 8; 343 | this.maxBoundaryY = this.wrapperHeight - 8; 344 | } else { 345 | this.minBoundaryY = 0; 346 | this.maxBoundaryY = this.maxPosY; 347 | } 348 | 349 | this.maxPosY = this.wrapperHeight - this.indicatorHeight; 350 | this.sizeRatioY = this.options.speedRatioY || (this.scroller.maxScrollY && (this.maxPosY / this.scroller.maxScrollY)); 351 | } 352 | 353 | this.updatePosition(); 354 | }, 355 | 356 | updatePosition: function () { 357 | var x = this.options.listenX && Math.round(this.sizeRatioX * this.scroller.x) || 0, 358 | y = this.options.listenY && Math.round(this.sizeRatioY * this.scroller.y) || 0; 359 | 360 | if ( !this.options.ignoreBoundaries ) { 361 | if ( x < this.minBoundaryX ) { 362 | if ( this.options.shrink == 'scale' ) { 363 | this.width = Math.max(this.indicatorWidth + x, 8); 364 | this.indicatorStyle.width = this.width + 'px'; 365 | } 366 | x = this.minBoundaryX; 367 | } else if ( x > this.maxBoundaryX ) { 368 | if ( this.options.shrink == 'scale' ) { 369 | this.width = Math.max(this.indicatorWidth - (x - this.maxPosX), 8); 370 | this.indicatorStyle.width = this.width + 'px'; 371 | x = this.maxPosX + this.indicatorWidth - this.width; 372 | } else { 373 | x = this.maxBoundaryX; 374 | } 375 | } else if ( this.options.shrink == 'scale' && this.width != this.indicatorWidth ) { 376 | this.width = this.indicatorWidth; 377 | this.indicatorStyle.width = this.width + 'px'; 378 | } 379 | 380 | if ( y < this.minBoundaryY ) { 381 | if ( this.options.shrink == 'scale' ) { 382 | this.height = Math.max(this.indicatorHeight + y * 3, 8); 383 | this.indicatorStyle.height = this.height + 'px'; 384 | } 385 | y = this.minBoundaryY; 386 | } else if ( y > this.maxBoundaryY ) { 387 | if ( this.options.shrink == 'scale' ) { 388 | this.height = Math.max(this.indicatorHeight - (y - this.maxPosY) * 3, 8); 389 | this.indicatorStyle.height = this.height + 'px'; 390 | y = this.maxPosY + this.indicatorHeight - this.height; 391 | } else { 392 | y = this.maxBoundaryY; 393 | } 394 | } else if ( this.options.shrink == 'scale' && this.height != this.indicatorHeight ) { 395 | this.height = this.indicatorHeight; 396 | this.indicatorStyle.height = this.height + 'px'; 397 | } 398 | } 399 | 400 | this.x = x; 401 | this.y = y; 402 | 403 | if ( this.scroller.options.useTransform ) { 404 | this.indicatorStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.scroller.translateZ; 405 | } else { 406 | this.indicatorStyle.left = x + 'px'; 407 | this.indicatorStyle.top = y + 'px'; 408 | } 409 | }, 410 | 411 | _pos: function (x, y) { 412 | if ( x < 0 ) { 413 | x = 0; 414 | } else if ( x > this.maxPosX ) { 415 | x = this.maxPosX; 416 | } 417 | 418 | if ( y < 0 ) { 419 | y = 0; 420 | } else if ( y > this.maxPosY ) { 421 | y = this.maxPosY; 422 | } 423 | 424 | x = this.options.listenX ? Math.round(x / this.sizeRatioX) : this.scroller.x; 425 | y = this.options.listenY ? Math.round(y / this.sizeRatioY) : this.scroller.y; 426 | 427 | this.scroller.scrollTo(x, y); 428 | }, 429 | 430 | fade: function (val, hold) { 431 | if ( hold && !this.visible ) { 432 | return; 433 | } 434 | 435 | clearTimeout(this.fadeTimeout); 436 | this.fadeTimeout = null; 437 | 438 | var time = val ? 250 : 500, 439 | delay = val ? 0 : 300; 440 | 441 | val = val ? '1' : '0'; 442 | 443 | this.wrapperStyle[utils.style.transitionDuration] = time + 'ms'; 444 | 445 | this.fadeTimeout = setTimeout((function (val) { 446 | this.wrapperStyle.opacity = val; 447 | this.visible = +val; 448 | }).bind(this, val), delay); 449 | } 450 | }; 451 | -------------------------------------------------------------------------------- /src/infinite/build.json: -------------------------------------------------------------------------------- 1 | { 2 | "insert": { 3 | "OPTIONS": "\t\tinfiniteUseTransform: true,\n\t\tdeceleration: 0.004,", 4 | "NORMALIZATION": "\tif ( this.options.infiniteElements ) {\n\t\tthis.options.probeType = 3;\n\t}\n\tthis.options.infiniteUseTransform = this.options.infiniteUseTransform && this.options.useTransform;", 5 | "_init": "\t\tif ( this.options.infiniteElements ) {\n\t\t\tthis._initInfinite();\n\t\t}" 6 | }, 7 | "replace": { 8 | "refresh": "infinite/refresh.js" 9 | } 10 | } -------------------------------------------------------------------------------- /src/infinite/infinite.js: -------------------------------------------------------------------------------- 1 | 2 | _initInfinite: function () { 3 | var el = this.options.infiniteElements; 4 | 5 | this.infiniteElements = typeof el == 'string' ? document.querySelectorAll(el) : el; 6 | this.infiniteLength = this.infiniteElements.length; 7 | this.infiniteMaster = this.infiniteElements[0]; 8 | this.infiniteElementHeight = utils.getRect(this.infiniteMaster).height; 9 | this.infiniteHeight = this.infiniteLength * this.infiniteElementHeight; 10 | 11 | this.options.cacheSize = this.options.cacheSize || 1000; 12 | this.infiniteCacheBuffer = Math.round(this.options.cacheSize / 4); 13 | 14 | //this.infiniteCache = {}; 15 | this.options.dataset.call(this, 0, this.options.cacheSize); 16 | 17 | this.on('refresh', function () { 18 | var elementsPerPage = Math.ceil(this.wrapperHeight / this.infiniteElementHeight); 19 | this.infiniteUpperBufferSize = Math.floor((this.infiniteLength - elementsPerPage) / 2); 20 | this.reorderInfinite(); 21 | }); 22 | 23 | this.on('scroll', this.reorderInfinite); 24 | }, 25 | 26 | // TO-DO: clean up the mess 27 | reorderInfinite: function () { 28 | var center = -this.y + this.wrapperHeight / 2; 29 | 30 | var minorPhase = Math.max(Math.floor(-this.y / this.infiniteElementHeight) - this.infiniteUpperBufferSize, 0), 31 | majorPhase = Math.floor(minorPhase / this.infiniteLength), 32 | phase = minorPhase - majorPhase * this.infiniteLength; 33 | 34 | var top = 0; 35 | var i = 0; 36 | var update = []; 37 | 38 | //var cachePhase = Math.floor((minorPhase + this.infiniteLength / 2) / this.infiniteCacheBuffer); 39 | var cachePhase = Math.floor(minorPhase / this.infiniteCacheBuffer); 40 | 41 | while ( i < this.infiniteLength ) { 42 | top = i * this.infiniteElementHeight + majorPhase * this.infiniteHeight; 43 | 44 | if ( phase > i ) { 45 | top += this.infiniteElementHeight * this.infiniteLength; 46 | } 47 | 48 | if ( this.infiniteElements[i]._top !== top ) { 49 | this.infiniteElements[i]._phase = top / this.infiniteElementHeight; 50 | 51 | if ( this.infiniteElements[i]._phase < this.options.infiniteLimit ) { 52 | this.infiniteElements[i]._top = top; 53 | if ( this.options.infiniteUseTransform ) { 54 | this.infiniteElements[i].style[utils.style.transform] = 'translate(0, ' + top + 'px)' + this.translateZ; 55 | } else { 56 | this.infiniteElements[i].style.top = top + 'px'; 57 | } 58 | update.push(this.infiniteElements[i]); 59 | } 60 | } 61 | 62 | i++; 63 | } 64 | 65 | if ( this.cachePhase != cachePhase && (cachePhase === 0 || minorPhase - this.infiniteCacheBuffer > 0) ) { 66 | this.options.dataset.call(this, Math.max(cachePhase * this.infiniteCacheBuffer - this.infiniteCacheBuffer, 0), this.options.cacheSize); 67 | } 68 | 69 | this.cachePhase = cachePhase; 70 | 71 | this.updateContent(update); 72 | }, 73 | 74 | updateContent: function (els) { 75 | if ( this.infiniteCache === undefined ) { 76 | return; 77 | } 78 | 79 | for ( var i = 0, l = els.length; i < l; i++ ) { 80 | this.options.dataFiller.call(this, els[i], this.infiniteCache[els[i]._phase]); 81 | } 82 | }, 83 | 84 | updateCache: function (start, data) { 85 | var firstRun = this.infiniteCache === undefined; 86 | 87 | this.infiniteCache = {}; 88 | 89 | for ( var i = 0, l = data.length; i < l; i++ ) { 90 | this.infiniteCache[start++] = data[i]; 91 | } 92 | 93 | if ( firstRun ) { 94 | this.updateContent(this.infiniteElements); 95 | } 96 | 97 | }, 98 | 99 | -------------------------------------------------------------------------------- /src/infinite/refresh.js: -------------------------------------------------------------------------------- 1 | 2 | this.scrollerWidth = rect.width; 3 | this.scrollerHeight = rect.height; 4 | 5 | this.maxScrollX = this.wrapperWidth - this.scrollerWidth; 6 | 7 | var limit; 8 | if ( this.options.infiniteElements ) { 9 | this.options.infiniteLimit = this.options.infiniteLimit || Math.floor(2147483645 / this.infiniteElementHeight); 10 | limit = -this.options.infiniteLimit * this.infiniteElementHeight + this.wrapperHeight; 11 | } 12 | this.maxScrollY = limit !== undefined ? limit : this.wrapperHeight - this.scrollerHeight; 13 | -------------------------------------------------------------------------------- /src/keys/build.json: -------------------------------------------------------------------------------- 1 | { 2 | "insert": { 3 | "_init": "\t\tif ( this.options.keyBindings ) {\n\t\t\tthis._initKeys();\n\t\t}" 4 | } 5 | } -------------------------------------------------------------------------------- /src/keys/keys.js: -------------------------------------------------------------------------------- 1 | 2 | _initKeys: function (e) { 3 | // default key bindings 4 | var keys = { 5 | pageUp: 33, 6 | pageDown: 34, 7 | end: 35, 8 | home: 36, 9 | left: 37, 10 | up: 38, 11 | right: 39, 12 | down: 40 13 | }; 14 | var i; 15 | 16 | // if you give me characters I give you keycode 17 | if ( typeof this.options.keyBindings == 'object' ) { 18 | for ( i in this.options.keyBindings ) { 19 | if ( typeof this.options.keyBindings[i] == 'string' ) { 20 | this.options.keyBindings[i] = this.options.keyBindings[i].toUpperCase().charCodeAt(0); 21 | } 22 | } 23 | } else { 24 | this.options.keyBindings = {}; 25 | } 26 | 27 | for ( i in keys ) { 28 | this.options.keyBindings[i] = this.options.keyBindings[i] || keys[i]; 29 | } 30 | 31 | utils.addEvent(window, 'keydown', this); 32 | 33 | this.on('destroy', function () { 34 | utils.removeEvent(window, 'keydown', this); 35 | }); 36 | }, 37 | 38 | _key: function (e) { 39 | if ( !this.enabled ) { 40 | return; 41 | } 42 | 43 | var snap = this.options.snap, // we are using this alot, better to cache it 44 | newX = snap ? this.currentPage.pageX : this.x, 45 | newY = snap ? this.currentPage.pageY : this.y, 46 | now = utils.getTime(), 47 | prevTime = this.keyTime || 0, 48 | acceleration = 0.250, 49 | pos; 50 | 51 | if ( this.options.useTransition && this.isInTransition ) { 52 | pos = this.getComputedPosition(); 53 | 54 | this._translate(Math.round(pos.x), Math.round(pos.y)); 55 | this.isInTransition = false; 56 | } 57 | 58 | this.keyAcceleration = now - prevTime < 200 ? Math.min(this.keyAcceleration + acceleration, 50) : 0; 59 | 60 | switch ( e.keyCode ) { 61 | case this.options.keyBindings.pageUp: 62 | if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) { 63 | newX += snap ? 1 : this.wrapperWidth; 64 | } else { 65 | newY += snap ? 1 : this.wrapperHeight; 66 | } 67 | break; 68 | case this.options.keyBindings.pageDown: 69 | if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) { 70 | newX -= snap ? 1 : this.wrapperWidth; 71 | } else { 72 | newY -= snap ? 1 : this.wrapperHeight; 73 | } 74 | break; 75 | case this.options.keyBindings.end: 76 | newX = snap ? this.pages.length-1 : this.maxScrollX; 77 | newY = snap ? this.pages[0].length-1 : this.maxScrollY; 78 | break; 79 | case this.options.keyBindings.home: 80 | newX = 0; 81 | newY = 0; 82 | break; 83 | case this.options.keyBindings.left: 84 | newX += snap ? -1 : 5 + this.keyAcceleration>>0; 85 | break; 86 | case this.options.keyBindings.up: 87 | newY += snap ? 1 : 5 + this.keyAcceleration>>0; 88 | break; 89 | case this.options.keyBindings.right: 90 | newX -= snap ? -1 : 5 + this.keyAcceleration>>0; 91 | break; 92 | case this.options.keyBindings.down: 93 | newY -= snap ? 1 : 5 + this.keyAcceleration>>0; 94 | break; 95 | default: 96 | return; 97 | } 98 | 99 | if ( snap ) { 100 | this.goToPage(newX, newY); 101 | return; 102 | } 103 | 104 | if ( newX > 0 ) { 105 | newX = 0; 106 | this.keyAcceleration = 0; 107 | } else if ( newX < this.maxScrollX ) { 108 | newX = this.maxScrollX; 109 | this.keyAcceleration = 0; 110 | } 111 | 112 | if ( newY > 0 ) { 113 | newY = 0; 114 | this.keyAcceleration = 0; 115 | } else if ( newY < this.maxScrollY ) { 116 | newY = this.maxScrollY; 117 | this.keyAcceleration = 0; 118 | } 119 | 120 | this.scrollTo(newX, newY, 0); 121 | 122 | this.keyTime = now; 123 | }, 124 | -------------------------------------------------------------------------------- /src/open.js: -------------------------------------------------------------------------------- 1 | (function (window, document, Math) { 2 | -------------------------------------------------------------------------------- /src/probe/_animate.js: -------------------------------------------------------------------------------- 1 | 2 | _animate: function (destX, destY, duration, easingFn) { 3 | var that = this, 4 | startX = this.x, 5 | startY = this.y, 6 | startTime = utils.getTime(), 7 | destTime = startTime + duration; 8 | 9 | function step () { 10 | var now = utils.getTime(), 11 | newX, newY, 12 | easing; 13 | 14 | if ( now >= destTime ) { 15 | that.isAnimating = false; 16 | that._translate(destX, destY); 17 | 18 | if ( !that.resetPosition(that.options.bounceTime) ) { 19 | that._execEvent('scrollEnd'); 20 | } 21 | 22 | return; 23 | } 24 | 25 | now = ( now - startTime ) / duration; 26 | easing = easingFn(now); 27 | newX = ( destX - startX ) * easing + startX; 28 | newY = ( destY - startY ) * easing + startY; 29 | that._translate(newX, newY); 30 | 31 | if ( that.isAnimating ) { 32 | rAF(step); 33 | } 34 | 35 | if ( that.options.probeType == 3 ) { 36 | that._execEvent('scroll'); 37 | } 38 | } 39 | 40 | this.isAnimating = true; 41 | step(); 42 | }, 43 | -------------------------------------------------------------------------------- /src/probe/_move.js: -------------------------------------------------------------------------------- 1 | 2 | if ( timestamp - this.startTime > 300 ) { 3 | this.startTime = timestamp; 4 | this.startX = this.x; 5 | this.startY = this.y; 6 | 7 | if ( this.options.probeType == 1 ) { 8 | this._execEvent('scroll'); 9 | } 10 | } 11 | 12 | if ( this.options.probeType > 1 ) { 13 | this._execEvent('scroll'); 14 | } 15 | -------------------------------------------------------------------------------- /src/probe/build.json: -------------------------------------------------------------------------------- 1 | { 2 | "insert": { 3 | "NORMALIZATION": "\tif ( this.options.probeType == 3 ) {\n\t\tthis.options.useTransition = false;\t}", 4 | "_wheel": "\t\tif ( this.options.probeType > 1 ) {\n\t\t\tthis._execEvent('scroll');\n\t\t}", 5 | "indicator._move": "probe/indicator._move.js" 6 | }, 7 | "replace": { 8 | "_move": "probe/_move.js" 9 | } 10 | } -------------------------------------------------------------------------------- /src/probe/indicator._move.js: -------------------------------------------------------------------------------- 1 | 2 | if ( this.scroller.options.probeType == 1 && timestamp - this.startTime > 300 ) { 3 | this.startTime = timestamp; 4 | this.scroller._execEvent('scroll'); 5 | } else if ( this.scroller.options.probeType > 1 ) { 6 | this.scroller._execEvent('scroll'); 7 | } 8 | -------------------------------------------------------------------------------- /src/probe/probe.js: -------------------------------------------------------------------------------- 1 | 2 | iScroll.prototype._initProbe = function () { 3 | if ( this.options.probeType == 3 ) { 4 | this.options.useTransition = false; 5 | } 6 | }; 7 | -------------------------------------------------------------------------------- /src/snap/_end.js: -------------------------------------------------------------------------------- 1 | 2 | if ( this.options.snap ) { 3 | var snap = this._nearestSnap(newX, newY); 4 | this.currentPage = snap; 5 | time = this.options.snapSpeed || Math.max( 6 | Math.max( 7 | Math.min(Math.abs(newX - snap.x), 1000), 8 | Math.min(Math.abs(newY - snap.y), 1000) 9 | ), 300); 10 | newX = snap.x; 11 | newY = snap.y; 12 | 13 | this.directionX = 0; 14 | this.directionY = 0; 15 | easing = this.options.bounceEasing; 16 | } -------------------------------------------------------------------------------- /src/snap/build.json: -------------------------------------------------------------------------------- 1 | { 2 | "insert": { 3 | "OPTIONS": "\t\tsnapThreshold: 0.334,", 4 | "_end": "snap/_end.js", 5 | "refresh": "snap/refresh.js", 6 | "_init": "\t\tif ( this.options.snap ) {\n\t\t\tthis._initSnap();\n\t\t}" 7 | } 8 | } -------------------------------------------------------------------------------- /src/snap/refresh.js: -------------------------------------------------------------------------------- 1 | 2 | if ( this.options.snap ) { 3 | var snap = this._nearestSnap(this.x, this.y); 4 | if ( this.x == snap.x && this.y == snap.y ) { 5 | return; 6 | } 7 | 8 | this.currentPage = snap; 9 | this.scrollTo(snap.x, snap.y); 10 | } 11 | -------------------------------------------------------------------------------- /src/snap/snap.js: -------------------------------------------------------------------------------- 1 | 2 | _initSnap: function () { 3 | this.currentPage = {}; 4 | 5 | if ( typeof this.options.snap == 'string' ) { 6 | this.options.snap = this.scroller.querySelectorAll(this.options.snap); 7 | } 8 | 9 | this.on('refresh', function () { 10 | var i = 0, l, 11 | m = 0, n, 12 | cx, cy, 13 | x = 0, y, 14 | stepX = this.options.snapStepX || this.wrapperWidth, 15 | stepY = this.options.snapStepY || this.wrapperHeight, 16 | el, 17 | rect; 18 | 19 | this.pages = []; 20 | 21 | if ( !this.wrapperWidth || !this.wrapperHeight || !this.scrollerWidth || !this.scrollerHeight ) { 22 | return; 23 | } 24 | 25 | if ( this.options.snap === true ) { 26 | cx = Math.round( stepX / 2 ); 27 | cy = Math.round( stepY / 2 ); 28 | 29 | while ( x > -this.scrollerWidth ) { 30 | this.pages[i] = []; 31 | l = 0; 32 | y = 0; 33 | 34 | while ( y > -this.scrollerHeight ) { 35 | this.pages[i][l] = { 36 | x: Math.max(x, this.maxScrollX), 37 | y: Math.max(y, this.maxScrollY), 38 | width: stepX, 39 | height: stepY, 40 | cx: x - cx, 41 | cy: y - cy 42 | }; 43 | 44 | y -= stepY; 45 | l++; 46 | } 47 | 48 | x -= stepX; 49 | i++; 50 | } 51 | } else { 52 | el = this.options.snap; 53 | l = el.length; 54 | n = -1; 55 | 56 | for ( ; i < l; i++ ) { 57 | rect = utils.getRect(el[i]); 58 | if ( i === 0 || rect.left <= utils.getRect(el[i-1]).left ) { 59 | m = 0; 60 | n++; 61 | } 62 | 63 | if ( !this.pages[m] ) { 64 | this.pages[m] = []; 65 | } 66 | 67 | x = Math.max(-rect.left, this.maxScrollX); 68 | y = Math.max(-rect.top, this.maxScrollY); 69 | cx = x - Math.round(rect.width / 2); 70 | cy = y - Math.round(rect.height / 2); 71 | 72 | this.pages[m][n] = { 73 | x: x, 74 | y: y, 75 | width: rect.width, 76 | height: rect.height, 77 | cx: cx, 78 | cy: cy 79 | }; 80 | 81 | if ( x > this.maxScrollX ) { 82 | m++; 83 | } 84 | } 85 | } 86 | 87 | this.goToPage(this.currentPage.pageX || 0, this.currentPage.pageY || 0, 0); 88 | 89 | // Update snap threshold if needed 90 | if ( this.options.snapThreshold % 1 === 0 ) { 91 | this.snapThresholdX = this.options.snapThreshold; 92 | this.snapThresholdY = this.options.snapThreshold; 93 | } else { 94 | this.snapThresholdX = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].width * this.options.snapThreshold); 95 | this.snapThresholdY = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].height * this.options.snapThreshold); 96 | } 97 | }); 98 | 99 | this.on('flick', function () { 100 | var time = this.options.snapSpeed || Math.max( 101 | Math.max( 102 | Math.min(Math.abs(this.x - this.startX), 1000), 103 | Math.min(Math.abs(this.y - this.startY), 1000) 104 | ), 300); 105 | 106 | this.goToPage( 107 | this.currentPage.pageX + this.directionX, 108 | this.currentPage.pageY + this.directionY, 109 | time 110 | ); 111 | }); 112 | }, 113 | 114 | _nearestSnap: function (x, y) { 115 | if ( !this.pages.length ) { 116 | return { x: 0, y: 0, pageX: 0, pageY: 0 }; 117 | } 118 | 119 | var i = 0, 120 | l = this.pages.length, 121 | m = 0; 122 | 123 | // Check if we exceeded the snap threshold 124 | if ( Math.abs(x - this.absStartX) < this.snapThresholdX && 125 | Math.abs(y - this.absStartY) < this.snapThresholdY ) { 126 | return this.currentPage; 127 | } 128 | 129 | if ( x > 0 ) { 130 | x = 0; 131 | } else if ( x < this.maxScrollX ) { 132 | x = this.maxScrollX; 133 | } 134 | 135 | if ( y > 0 ) { 136 | y = 0; 137 | } else if ( y < this.maxScrollY ) { 138 | y = this.maxScrollY; 139 | } 140 | 141 | for ( ; i < l; i++ ) { 142 | if ( x >= this.pages[i][0].cx ) { 143 | x = this.pages[i][0].x; 144 | break; 145 | } 146 | } 147 | 148 | l = this.pages[i].length; 149 | 150 | for ( ; m < l; m++ ) { 151 | if ( y >= this.pages[0][m].cy ) { 152 | y = this.pages[0][m].y; 153 | break; 154 | } 155 | } 156 | 157 | if ( i == this.currentPage.pageX ) { 158 | i += this.directionX; 159 | 160 | if ( i < 0 ) { 161 | i = 0; 162 | } else if ( i >= this.pages.length ) { 163 | i = this.pages.length - 1; 164 | } 165 | 166 | x = this.pages[i][0].x; 167 | } 168 | 169 | if ( m == this.currentPage.pageY ) { 170 | m += this.directionY; 171 | 172 | if ( m < 0 ) { 173 | m = 0; 174 | } else if ( m >= this.pages[0].length ) { 175 | m = this.pages[0].length - 1; 176 | } 177 | 178 | y = this.pages[0][m].y; 179 | } 180 | 181 | return { 182 | x: x, 183 | y: y, 184 | pageX: i, 185 | pageY: m 186 | }; 187 | }, 188 | 189 | goToPage: function (x, y, time, easing) { 190 | easing = easing || this.options.bounceEasing; 191 | 192 | if ( x >= this.pages.length ) { 193 | x = this.pages.length - 1; 194 | } else if ( x < 0 ) { 195 | x = 0; 196 | } 197 | 198 | if ( y >= this.pages[x].length ) { 199 | y = this.pages[x].length - 1; 200 | } else if ( y < 0 ) { 201 | y = 0; 202 | } 203 | 204 | var posX = this.pages[x][y].x, 205 | posY = this.pages[x][y].y; 206 | 207 | time = time === undefined ? this.options.snapSpeed || Math.max( 208 | Math.max( 209 | Math.min(Math.abs(posX - this.x), 1000), 210 | Math.min(Math.abs(posY - this.y), 1000) 211 | ), 300) : time; 212 | 213 | this.currentPage = { 214 | x: posX, 215 | y: posY, 216 | pageX: x, 217 | pageY: y 218 | }; 219 | 220 | this.scrollTo(posX, posY, time, easing); 221 | }, 222 | 223 | next: function (time, easing) { 224 | var x = this.currentPage.pageX, 225 | y = this.currentPage.pageY; 226 | 227 | x++; 228 | 229 | if ( x >= this.pages.length && this.hasVerticalScroll ) { 230 | x = 0; 231 | y++; 232 | } 233 | 234 | this.goToPage(x, y, time, easing); 235 | }, 236 | 237 | prev: function (time, easing) { 238 | var x = this.currentPage.pageX, 239 | y = this.currentPage.pageY; 240 | 241 | x--; 242 | 243 | if ( x < 0 && this.hasVerticalScroll ) { 244 | x = 0; 245 | y--; 246 | } 247 | 248 | this.goToPage(x, y, time, easing); 249 | }, 250 | -------------------------------------------------------------------------------- /src/utils.js: -------------------------------------------------------------------------------- 1 | var rAF = window.requestAnimationFrame || 2 | window.webkitRequestAnimationFrame || 3 | window.mozRequestAnimationFrame || 4 | window.oRequestAnimationFrame || 5 | window.msRequestAnimationFrame || 6 | function (callback) { window.setTimeout(callback, 1000 / 60); }; 7 | 8 | var utils = (function () { 9 | var me = {}; 10 | 11 | var _elementStyle = document.createElement('div').style; 12 | var _vendor = (function () { 13 | var vendors = ['t', 'webkitT', 'MozT', 'msT', 'OT'], 14 | transform, 15 | i = 0, 16 | l = vendors.length; 17 | 18 | for ( ; i < l; i++ ) { 19 | transform = vendors[i] + 'ransform'; 20 | if ( transform in _elementStyle ) return vendors[i].substr(0, vendors[i].length-1); 21 | } 22 | 23 | return false; 24 | })(); 25 | 26 | function _prefixStyle (style) { 27 | if ( _vendor === false ) return false; 28 | if ( _vendor === '' ) return style; 29 | return _vendor + style.charAt(0).toUpperCase() + style.substr(1); 30 | } 31 | 32 | me.getTime = Date.now || function getTime () { return new Date().getTime(); }; 33 | 34 | me.extend = function (target, obj) { 35 | for ( var i in obj ) { 36 | target[i] = obj[i]; 37 | } 38 | }; 39 | 40 | me.addEvent = function (el, type, fn, capture) { 41 | el.addEventListener(type, fn, !!capture); 42 | }; 43 | 44 | me.removeEvent = function (el, type, fn, capture) { 45 | el.removeEventListener(type, fn, !!capture); 46 | }; 47 | 48 | me.prefixPointerEvent = function (pointerEvent) { 49 | return window.MSPointerEvent ? 50 | 'MSPointer' + pointerEvent.charAt(7).toUpperCase() + pointerEvent.substr(8): 51 | pointerEvent; 52 | }; 53 | 54 | me.momentum = function (current, start, time, lowerMargin, wrapperSize, deceleration) { 55 | var distance = current - start, 56 | speed = Math.abs(distance) / time, 57 | destination, 58 | duration; 59 | 60 | deceleration = deceleration === undefined ? 0.0006 : deceleration; 61 | 62 | destination = current + ( speed * speed ) / ( 2 * deceleration ) * ( distance < 0 ? -1 : 1 ); 63 | duration = speed / deceleration; 64 | 65 | if ( destination < lowerMargin ) { 66 | destination = wrapperSize ? lowerMargin - ( wrapperSize / 2.5 * ( speed / 8 ) ) : lowerMargin; 67 | distance = Math.abs(destination - current); 68 | duration = distance / speed; 69 | } else if ( destination > 0 ) { 70 | destination = wrapperSize ? wrapperSize / 2.5 * ( speed / 8 ) : 0; 71 | distance = Math.abs(current) + destination; 72 | duration = distance / speed; 73 | } 74 | 75 | return { 76 | destination: Math.round(destination), 77 | duration: duration 78 | }; 79 | }; 80 | 81 | var _transform = _prefixStyle('transform'); 82 | 83 | me.extend(me, { 84 | hasTransform: _transform !== false, 85 | hasPerspective: _prefixStyle('perspective') in _elementStyle, 86 | hasTouch: 'ontouchstart' in window, 87 | hasPointer: !!(window.PointerEvent || window.MSPointerEvent), // IE10 is prefixed 88 | hasTransition: _prefixStyle('transition') in _elementStyle 89 | }); 90 | 91 | /* 92 | This should find all Android browsers lower than build 535.19 (both stock browser and webview) 93 | - galaxy S2 is ok 94 | - 2.3.6 : `AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1` 95 | - 4.0.4 : `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30` 96 | - galaxy S3 is badAndroid (stock brower, webview) 97 | `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30` 98 | - galaxy S4 is badAndroid (stock brower, webview) 99 | `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30` 100 | - galaxy S5 is OK 101 | `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)` 102 | - galaxy S6 is OK 103 | `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)` 104 | */ 105 | me.isBadAndroid = (function() { 106 | var appVersion = window.navigator.appVersion; 107 | // Android browser is not a chrome browser. 108 | if (/Android/.test(appVersion) && !(/Chrome\/\d/.test(appVersion))) { 109 | var safariVersion = appVersion.match(/Safari\/(\d+.\d)/); 110 | if(safariVersion && typeof safariVersion === "object" && safariVersion.length >= 2) { 111 | return parseFloat(safariVersion[1]) < 535.19; 112 | } else { 113 | return true; 114 | } 115 | } else { 116 | return false; 117 | } 118 | })(); 119 | 120 | me.extend(me.style = {}, { 121 | transform: _transform, 122 | transitionTimingFunction: _prefixStyle('transitionTimingFunction'), 123 | transitionDuration: _prefixStyle('transitionDuration'), 124 | transitionDelay: _prefixStyle('transitionDelay'), 125 | transformOrigin: _prefixStyle('transformOrigin'), 126 | touchAction: _prefixStyle('touchAction') 127 | }); 128 | 129 | me.hasClass = function (e, c) { 130 | var re = new RegExp("(^|\\s)" + c + "(\\s|$)"); 131 | return re.test(e.className); 132 | }; 133 | 134 | me.addClass = function (e, c) { 135 | if ( me.hasClass(e, c) ) { 136 | return; 137 | } 138 | 139 | var newclass = e.className.split(' '); 140 | newclass.push(c); 141 | e.className = newclass.join(' '); 142 | }; 143 | 144 | me.removeClass = function (e, c) { 145 | if ( !me.hasClass(e, c) ) { 146 | return; 147 | } 148 | 149 | var re = new RegExp("(^|\\s)" + c + "(\\s|$)", 'g'); 150 | e.className = e.className.replace(re, ' '); 151 | }; 152 | 153 | me.offset = function (el) { 154 | var left = -el.offsetLeft, 155 | top = -el.offsetTop; 156 | 157 | // jshint -W084 158 | while (el = el.offsetParent) { 159 | left -= el.offsetLeft; 160 | top -= el.offsetTop; 161 | } 162 | // jshint +W084 163 | 164 | return { 165 | left: left, 166 | top: top 167 | }; 168 | }; 169 | 170 | me.preventDefaultException = function (el, exceptions) { 171 | for ( var i in exceptions ) { 172 | if ( exceptions[i].test(el[i]) ) { 173 | return true; 174 | } 175 | } 176 | 177 | return false; 178 | }; 179 | 180 | me.extend(me.eventType = {}, { 181 | touchstart: 1, 182 | touchmove: 1, 183 | touchend: 1, 184 | 185 | mousedown: 2, 186 | mousemove: 2, 187 | mouseup: 2, 188 | 189 | pointerdown: 3, 190 | pointermove: 3, 191 | pointerup: 3, 192 | 193 | MSPointerDown: 3, 194 | MSPointerMove: 3, 195 | MSPointerUp: 3 196 | }); 197 | 198 | me.extend(me.ease = {}, { 199 | quadratic: { 200 | style: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)', 201 | fn: function (k) { 202 | return k * ( 2 - k ); 203 | } 204 | }, 205 | circular: { 206 | style: 'cubic-bezier(0.1, 0.57, 0.1, 1)', // Not properly "circular" but this looks better, it should be (0.075, 0.82, 0.165, 1) 207 | fn: function (k) { 208 | return Math.sqrt( 1 - ( --k * k ) ); 209 | } 210 | }, 211 | back: { 212 | style: 'cubic-bezier(0.175, 0.885, 0.32, 1.275)', 213 | fn: function (k) { 214 | var b = 4; 215 | return ( k = k - 1 ) * k * ( ( b + 1 ) * k + b ) + 1; 216 | } 217 | }, 218 | bounce: { 219 | style: '', 220 | fn: function (k) { 221 | if ( ( k /= 1 ) < ( 1 / 2.75 ) ) { 222 | return 7.5625 * k * k; 223 | } else if ( k < ( 2 / 2.75 ) ) { 224 | return 7.5625 * ( k -= ( 1.5 / 2.75 ) ) * k + 0.75; 225 | } else if ( k < ( 2.5 / 2.75 ) ) { 226 | return 7.5625 * ( k -= ( 2.25 / 2.75 ) ) * k + 0.9375; 227 | } else { 228 | return 7.5625 * ( k -= ( 2.625 / 2.75 ) ) * k + 0.984375; 229 | } 230 | } 231 | }, 232 | elastic: { 233 | style: '', 234 | fn: function (k) { 235 | var f = 0.22, 236 | e = 0.4; 237 | 238 | if ( k === 0 ) { return 0; } 239 | if ( k == 1 ) { return 1; } 240 | 241 | return ( e * Math.pow( 2, - 10 * k ) * Math.sin( ( k - f / 4 ) * ( 2 * Math.PI ) / f ) + 1 ); 242 | } 243 | } 244 | }); 245 | 246 | me.tap = function (e, eventName) { 247 | var ev = document.createEvent('Event'); 248 | ev.initEvent(eventName, true, true); 249 | ev.pageX = e.pageX; 250 | ev.pageY = e.pageY; 251 | e.target.dispatchEvent(ev); 252 | }; 253 | 254 | me.click = function (e) { 255 | var target = e.target, 256 | ev; 257 | 258 | if ( !(/(SELECT|INPUT|TEXTAREA)/i).test(target.tagName) ) { 259 | // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/initMouseEvent 260 | // initMouseEvent is deprecated. 261 | ev = document.createEvent(window.MouseEvent ? 'MouseEvents' : 'Event'); 262 | ev.initEvent('click', true, true); 263 | ev.view = e.view || window; 264 | ev.detail = 1; 265 | ev.screenX = target.screenX || 0; 266 | ev.screenY = target.screenY || 0; 267 | ev.clientX = target.clientX || 0; 268 | ev.clientY = target.clientY || 0; 269 | ev.ctrlKey = !!e.ctrlKey; 270 | ev.altKey = !!e.altKey; 271 | ev.shiftKey = !!e.shiftKey; 272 | ev.metaKey = !!e.metaKey; 273 | ev.button = 0; 274 | ev.relatedTarget = null; 275 | ev._constructed = true; 276 | target.dispatchEvent(ev); 277 | } 278 | }; 279 | 280 | me.getTouchAction = function(eventPassthrough, addPinch) { 281 | var touchAction = 'none'; 282 | if ( eventPassthrough === 'vertical' ) { 283 | touchAction = 'pan-y'; 284 | } else if (eventPassthrough === 'horizontal' ) { 285 | touchAction = 'pan-x'; 286 | } 287 | if (addPinch && touchAction != 'none') { 288 | // add pinch-zoom support if the browser supports it, but if not (eg. Chrome <55) do nothing 289 | touchAction += ' pinch-zoom'; 290 | } 291 | return touchAction; 292 | }; 293 | 294 | me.getRect = function(el) { 295 | if (el instanceof SVGElement) { 296 | var rect = el.getBoundingClientRect(); 297 | return { 298 | top : rect.top, 299 | left : rect.left, 300 | width : rect.width, 301 | height : rect.height 302 | }; 303 | } else { 304 | return { 305 | top : el.offsetTop, 306 | left : el.offsetLeft, 307 | width : el.offsetWidth, 308 | height : el.offsetHeight 309 | }; 310 | } 311 | }; 312 | 313 | return me; 314 | })(); -------------------------------------------------------------------------------- /src/wheel/build.json: -------------------------------------------------------------------------------- 1 | { 2 | "insert": { 3 | "OPTIONS": "\t\tmouseWheelSpeed: 20,", 4 | "NORMALIZATION": "\tthis.options.invertWheelDirection = this.options.invertWheelDirection ? -1 : 1;", 5 | "_init": "\t\tif ( this.options.mouseWheel ) {\n\t\t\tthis._initWheel();\n\t\t}" 6 | } 7 | } -------------------------------------------------------------------------------- /src/wheel/wheel.js: -------------------------------------------------------------------------------- 1 | 2 | _initWheel: function () { 3 | utils.addEvent(this.wrapper, 'wheel', this); 4 | utils.addEvent(this.wrapper, 'mousewheel', this); 5 | utils.addEvent(this.wrapper, 'DOMMouseScroll', this); 6 | 7 | this.on('destroy', function () { 8 | clearTimeout(this.wheelTimeout); 9 | this.wheelTimeout = null; 10 | utils.removeEvent(this.wrapper, 'wheel', this); 11 | utils.removeEvent(this.wrapper, 'mousewheel', this); 12 | utils.removeEvent(this.wrapper, 'DOMMouseScroll', this); 13 | }); 14 | }, 15 | 16 | _wheel: function (e) { 17 | if ( !this.enabled ) { 18 | return; 19 | } 20 | 21 | e.preventDefault(); 22 | 23 | var wheelDeltaX, wheelDeltaY, 24 | newX, newY, 25 | that = this; 26 | 27 | if ( this.wheelTimeout === undefined ) { 28 | that._execEvent('scrollStart'); 29 | } 30 | 31 | // Execute the scrollEnd event after 400ms the wheel stopped scrolling 32 | clearTimeout(this.wheelTimeout); 33 | this.wheelTimeout = setTimeout(function () { 34 | if(!that.options.snap) { 35 | that._execEvent('scrollEnd'); 36 | } 37 | that.wheelTimeout = undefined; 38 | }, 400); 39 | 40 | if ( 'deltaX' in e ) { 41 | if (e.deltaMode === 1) { 42 | wheelDeltaX = -e.deltaX * this.options.mouseWheelSpeed; 43 | wheelDeltaY = -e.deltaY * this.options.mouseWheelSpeed; 44 | } else { 45 | wheelDeltaX = -e.deltaX; 46 | wheelDeltaY = -e.deltaY; 47 | } 48 | } else if ( 'wheelDeltaX' in e ) { 49 | wheelDeltaX = e.wheelDeltaX / 120 * this.options.mouseWheelSpeed; 50 | wheelDeltaY = e.wheelDeltaY / 120 * this.options.mouseWheelSpeed; 51 | } else if ( 'wheelDelta' in e ) { 52 | wheelDeltaX = wheelDeltaY = e.wheelDelta / 120 * this.options.mouseWheelSpeed; 53 | } else if ( 'detail' in e ) { 54 | wheelDeltaX = wheelDeltaY = -e.detail / 3 * this.options.mouseWheelSpeed; 55 | } else { 56 | return; 57 | } 58 | 59 | wheelDeltaX *= this.options.invertWheelDirection; 60 | wheelDeltaY *= this.options.invertWheelDirection; 61 | 62 | if ( !this.hasVerticalScroll ) { 63 | wheelDeltaX = wheelDeltaY; 64 | wheelDeltaY = 0; 65 | } 66 | 67 | if ( this.options.snap ) { 68 | newX = this.currentPage.pageX; 69 | newY = this.currentPage.pageY; 70 | 71 | if ( wheelDeltaX > 0 ) { 72 | newX--; 73 | } else if ( wheelDeltaX < 0 ) { 74 | newX++; 75 | } 76 | 77 | if ( wheelDeltaY > 0 ) { 78 | newY--; 79 | } else if ( wheelDeltaY < 0 ) { 80 | newY++; 81 | } 82 | 83 | this.goToPage(newX, newY); 84 | 85 | return; 86 | } 87 | 88 | newX = this.x + Math.round(this.hasHorizontalScroll ? wheelDeltaX : 0); 89 | newY = this.y + Math.round(this.hasVerticalScroll ? wheelDeltaY : 0); 90 | 91 | this.directionX = wheelDeltaX > 0 ? -1 : wheelDeltaX < 0 ? 1 : 0; 92 | this.directionY = wheelDeltaY > 0 ? -1 : wheelDeltaY < 0 ? 1 : 0; 93 | 94 | if ( newX > 0 ) { 95 | newX = 0; 96 | } else if ( newX < this.maxScrollX ) { 97 | newX = this.maxScrollX; 98 | } 99 | 100 | if ( newY > 0 ) { 101 | newY = 0; 102 | } else if ( newY < this.maxScrollY ) { 103 | newY = this.maxScrollY; 104 | } 105 | 106 | this.scrollTo(newX, newY, 0); 107 | 108 | // INSERT POINT: _wheel 109 | }, 110 | -------------------------------------------------------------------------------- /src/zoom/build.json: -------------------------------------------------------------------------------- 1 | { 2 | "insert": { 3 | "OPTIONS": "\t\tzoomMin: 1,\n\t\tzoomMax: 4, startZoom: 1,", 4 | "DEFAULTS": "\tthis.scale = Math.min(Math.max(this.options.startZoom, this.options.zoomMin), this.options.zoomMax);", 5 | "_init": "\t\tif ( this.options.zoom ) {\n\t\t\tthis._initZoom();\n\t\t}" 6 | }, 7 | "replace": { 8 | "refresh": "zoom/refresh.js", 9 | "_translate": "\t\t\tthis.scrollerStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px) scale(' + this.scale + ') ' + this.translateZ;" 10 | } 11 | } -------------------------------------------------------------------------------- /src/zoom/handleEvent.js: -------------------------------------------------------------------------------- 1 | 2 | handleEvent: function (e) { 3 | switch ( e.type ) { 4 | case 'touchstart': 5 | case 'pointerdown': 6 | case 'MSPointerDown': 7 | case 'mousedown': 8 | this._start(e); 9 | 10 | if ( this.options.zoom && e.touches && e.touches.length > 1 ) { 11 | this._zoomStart(e); 12 | } 13 | break; 14 | case 'touchmove': 15 | case 'pointermove': 16 | case 'MSPointerMove': 17 | case 'mousemove': 18 | if ( this.options.zoom && e.touches && e.touches[1] ) { 19 | this._zoom(e); 20 | return; 21 | } 22 | this._move(e); 23 | break; 24 | case 'touchend': 25 | case 'pointerup': 26 | case 'MSPointerUp': 27 | case 'mouseup': 28 | case 'touchcancel': 29 | case 'pointercancel': 30 | case 'MSPointerCancel': 31 | case 'mousecancel': 32 | if ( this.scaled ) { 33 | this._zoomEnd(e); 34 | return; 35 | } 36 | this._end(e); 37 | break; 38 | case 'orientationchange': 39 | case 'resize': 40 | this._resize(); 41 | break; 42 | case 'transitionend': 43 | case 'webkitTransitionEnd': 44 | case 'oTransitionEnd': 45 | case 'MSTransitionEnd': 46 | this._transitionEnd(e); 47 | break; 48 | case 'wheel': 49 | case 'DOMMouseScroll': 50 | case 'mousewheel': 51 | if ( this.options.wheelAction == 'zoom' ) { 52 | this._wheelZoom(e); 53 | return; 54 | } 55 | this._wheel(e); 56 | break; 57 | case 'keydown': 58 | this._key(e); 59 | break; 60 | } 61 | } 62 | 63 | }; -------------------------------------------------------------------------------- /src/zoom/refresh.js: -------------------------------------------------------------------------------- 1 | 2 | this.scrollerWidth = Math.round(rect.width * this.scale); 3 | this.scrollerHeight = Math.round(rect.height * this.scale); 4 | 5 | this.maxScrollX = this.wrapperWidth - this.scrollerWidth; 6 | this.maxScrollY = this.wrapperHeight - this.scrollerHeight; 7 | -------------------------------------------------------------------------------- /src/zoom/zoom.js: -------------------------------------------------------------------------------- 1 | 2 | _initZoom: function () { 3 | this.scrollerStyle[utils.style.transformOrigin] = '0 0'; 4 | }, 5 | 6 | _zoomStart: function (e) { 7 | var c1 = Math.abs( e.touches[0].pageX - e.touches[1].pageX ), 8 | c2 = Math.abs( e.touches[0].pageY - e.touches[1].pageY ); 9 | 10 | this.touchesDistanceStart = Math.sqrt(c1 * c1 + c2 * c2); 11 | this.startScale = this.scale; 12 | 13 | this.originX = Math.abs(e.touches[0].pageX + e.touches[1].pageX) / 2 + this.wrapperOffset.left - this.x; 14 | this.originY = Math.abs(e.touches[0].pageY + e.touches[1].pageY) / 2 + this.wrapperOffset.top - this.y; 15 | 16 | this._execEvent('zoomStart'); 17 | }, 18 | 19 | _zoom: function (e) { 20 | if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) { 21 | return; 22 | } 23 | 24 | if ( this.options.preventDefault ) { 25 | e.preventDefault(); 26 | } 27 | 28 | var c1 = Math.abs( e.touches[0].pageX - e.touches[1].pageX ), 29 | c2 = Math.abs( e.touches[0].pageY - e.touches[1].pageY ), 30 | distance = Math.sqrt( c1 * c1 + c2 * c2 ), 31 | scale = 1 / this.touchesDistanceStart * distance * this.startScale, 32 | lastScale, 33 | x, y; 34 | 35 | this.scaled = true; 36 | 37 | if ( scale < this.options.zoomMin ) { 38 | scale = 0.5 * this.options.zoomMin * Math.pow(2.0, scale / this.options.zoomMin); 39 | } else if ( scale > this.options.zoomMax ) { 40 | scale = 2.0 * this.options.zoomMax * Math.pow(0.5, this.options.zoomMax / scale); 41 | } 42 | 43 | lastScale = scale / this.startScale; 44 | x = this.originX - this.originX * lastScale + this.startX; 45 | y = this.originY - this.originY * lastScale + this.startY; 46 | 47 | this.scale = scale; 48 | 49 | this.scrollTo(x, y, 0); 50 | }, 51 | 52 | _zoomEnd: function (e) { 53 | if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) { 54 | return; 55 | } 56 | 57 | if ( this.options.preventDefault ) { 58 | e.preventDefault(); 59 | } 60 | 61 | var newX, newY, 62 | lastScale; 63 | 64 | this.isInTransition = 0; 65 | this.initiated = 0; 66 | 67 | if ( this.scale > this.options.zoomMax ) { 68 | this.scale = this.options.zoomMax; 69 | } else if ( this.scale < this.options.zoomMin ) { 70 | this.scale = this.options.zoomMin; 71 | } 72 | 73 | // Update boundaries 74 | this.refresh(); 75 | 76 | lastScale = this.scale / this.startScale; 77 | 78 | newX = this.originX - this.originX * lastScale + this.startX; 79 | newY = this.originY - this.originY * lastScale + this.startY; 80 | 81 | if ( newX > 0 ) { 82 | newX = 0; 83 | } else if ( newX < this.maxScrollX ) { 84 | newX = this.maxScrollX; 85 | } 86 | 87 | if ( newY > 0 ) { 88 | newY = 0; 89 | } else if ( newY < this.maxScrollY ) { 90 | newY = this.maxScrollY; 91 | } 92 | 93 | if ( this.x != newX || this.y != newY ) { 94 | this.scrollTo(newX, newY, this.options.bounceTime); 95 | } 96 | 97 | this.scaled = false; 98 | 99 | this._execEvent('zoomEnd'); 100 | }, 101 | 102 | zoom: function (scale, x, y, time) { 103 | if ( scale < this.options.zoomMin ) { 104 | scale = this.options.zoomMin; 105 | } else if ( scale > this.options.zoomMax ) { 106 | scale = this.options.zoomMax; 107 | } 108 | 109 | if ( scale == this.scale ) { 110 | return; 111 | } 112 | 113 | var relScale = scale / this.scale; 114 | 115 | x = x === undefined ? this.wrapperWidth / 2 : x; 116 | y = y === undefined ? this.wrapperHeight / 2 : y; 117 | time = time === undefined ? 300 : time; 118 | 119 | x = x + this.wrapperOffset.left - this.x; 120 | y = y + this.wrapperOffset.top - this.y; 121 | 122 | x = x - x * relScale + this.x; 123 | y = y - y * relScale + this.y; 124 | 125 | this.scale = scale; 126 | 127 | this.refresh(); // update boundaries 128 | 129 | if ( x > 0 ) { 130 | x = 0; 131 | } else if ( x < this.maxScrollX ) { 132 | x = this.maxScrollX; 133 | } 134 | 135 | if ( y > 0 ) { 136 | y = 0; 137 | } else if ( y < this.maxScrollY ) { 138 | y = this.maxScrollY; 139 | } 140 | 141 | this.scrollTo(x, y, time); 142 | }, 143 | 144 | _wheelZoom: function (e) { 145 | var wheelDeltaY, 146 | deltaScale, 147 | that = this; 148 | 149 | // Execute the zoomEnd event after 400ms the wheel stopped scrolling 150 | clearTimeout(this.wheelTimeout); 151 | this.wheelTimeout = setTimeout(function () { 152 | that._execEvent('zoomEnd'); 153 | }, 400); 154 | 155 | if ( 'deltaX' in e ) { 156 | wheelDeltaY = -e.deltaY / Math.abs(e.deltaY); 157 | } else if ('wheelDeltaX' in e) { 158 | wheelDeltaY = e.wheelDeltaY / Math.abs(e.wheelDeltaY); 159 | } else if('wheelDelta' in e) { 160 | wheelDeltaY = e.wheelDelta / Math.abs(e.wheelDelta); 161 | } else if ('detail' in e) { 162 | wheelDeltaY = -e.detail / Math.abs(e.wheelDelta); 163 | } else { 164 | return; 165 | } 166 | 167 | deltaScale = this.scale + wheelDeltaY / 5; 168 | 169 | this.zoom(deltaScale, e.pageX, e.pageY, 0); 170 | }, 171 | --------------------------------------------------------------------------------