├── .bowerrc
├── .editorconfig
├── .eslintignore
├── .eslintrc.json
├── .gitignore
├── .npmrc
├── .nvmrc
├── .travis.yml
├── CHANGELOG.md
├── CONTRIBUTING.md
├── DOCS.md
├── Gruntfile.js
├── LICENSE.md
├── README.md
├── bower.json
├── dist
├── angular-snapscroll.js
└── angular-snapscroll.min.js
├── package.json
├── src
├── directives
│ ├── fitWindowHeight.js
│ └── snapscroll.js
└── snapscroll.js
└── test
├── .eslintrc.json
├── karma.conf.js
└── spec
├── directives
├── fitWindowHeight.js
└── snapscroll.js
└── snapscroll.js
/.bowerrc:
--------------------------------------------------------------------------------
1 | {
2 | "directory": "bower_components"
3 | }
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | end_of_line = lf
5 | insert_final_newline = true
6 | charset = utf-8
7 | indent_style = space
8 | indent_size = 4
9 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | dist/*.min.js
2 | coverage
3 |
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "es6": true,
4 | "browser": true,
5 | "node": true,
6 | "mocha": true,
7 | "amd": true
8 | },
9 | "parserOptions": {
10 | "ecmaVersion": 6,
11 | "sourceType": "module"
12 | },
13 | "extends": ["eslint:recommended"],
14 | "rules": {
15 | "block-scoped-var": [2],
16 | "brace-style": [2, "1tbs", { "allowSingleLine": true }],
17 | "camelcase": [2, { "properties": "never" }],
18 | "comma-dangle": [2, "never"],
19 | "comma-spacing": [2],
20 | "comma-style": [2, "last"],
21 | "curly": [2, "all"],
22 | "dot-notation": [2, { "allowKeywords": true }],
23 | "eol-last": [2],
24 | "eqeqeq": [2],
25 | "indent": [2, 4],
26 | "keyword-spacing": [2],
27 | "new-cap": [2, {"capIsNew": false}],
28 | "no-caller": [2],
29 | "no-cond-assign": [2, "except-parens"],
30 | "no-debugger": [2],
31 | "no-eval": [2],
32 | "no-iterator": [2],
33 | "no-multi-str": [2],
34 | "no-proto": [2],
35 | "no-redeclare": [2],
36 | "no-script-url": [2],
37 | "no-trailing-spaces": [2],
38 | "no-undef": [2],
39 | "no-unreachable": [2],
40 | "no-unused-vars": [2, { "args": "after-used" }],
41 | "semi": [2, "always"],
42 | "space-before-function-paren": [2, {"anonymous": "always", "named": "never"} ],
43 | "space-before-blocks": [2, { "functions": "always" } ],
44 | "space-in-parens": [2, "never"],
45 | "space-infix-ops": [2],
46 | "space-unary-ops": [2],
47 | "no-with": [2],
48 | "wrap-iife": [2, "any"]
49 | },
50 | "globals": {
51 | "angular": true
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .tmp
2 | .coveralls.yml
3 | coverage
4 | node_modules
5 | bower_components
6 |
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | registry = https://registry.npmjs.org/
2 |
--------------------------------------------------------------------------------
/.nvmrc:
--------------------------------------------------------------------------------
1 | 8
2 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## 1.3.0
2 |
3 | ### Features
4 | - Add module exports (https://github.com/joelmukuthu/angular-snapscroll/issues/46)
5 |
6 | ## 1.2.0
7 |
8 | ### Features
9 | - Support passing events to [`before-snap`](DOCS.md#before-snap) and
10 | [`after-snap`](DOCS.md#after-snap) callbacks
11 | - Support disabling wheel and trackpad events with
12 | [`disable-wheel-binding`](DOCS.md#disable-wheel-binding)
13 |
14 | ## 1.1.0
15 |
16 | ### Features
17 | - Support ignoring wheel events from specified elements with
18 | [`ignore-wheel-class`](DOCS.md#ignore-wheel-class)
19 |
20 | ## 1.0.2
21 |
22 | ### Fixes
23 | - On trackpads with high sensitivity (e.g. Macs), swiping once does not lead to
24 | a double snap anymore (thanks https://github.com/reco). There's a 1 second delay
25 | that prevents the next snap, which can be changed (or disabled) with
26 | [`prevent-double-snap-delay`](DOCS.md#prevent-double-snap-delay)
27 |
28 | ## 1.0.1
29 |
30 | ## Fixes
31 | - Do not translate left/right scroll to up/down scroll
32 | (https://github.com/joelmukuthu/angular-snapscroll/issues/37)
33 |
34 | ## 1.0.0
35 |
36 | ### Breaking changes
37 | - Dependency on [angular-scrollie](https://github.com/joelmukuthu/angular-scrollie)
38 | - [`before-snap`](DOCS.md#before-snap) and [`after-snap`](DOCS.md#after-snap) are
39 | now only called if snapIndex changes
40 |
41 | ### Features
42 | - Support overriding the next snapIndex by returning a number from
43 | [`before-snap`](DOCS.md#before-snap)
44 | - Support [disabling/enabling](DOCS.md#snapscroll-directive) snapscroll
45 | programmatically
46 | - Support child elements whose height is greater than the snapscroll element
47 | - Support for arrow keys using [`enable-arrow-keys`](DOCS.md#enable-arrow-keys)
48 |
49 | ### Fixes
50 | - [`snap-index`](DOCS.md#snap-index) is not initialized if the element is not
51 | scrollable
52 | - Ensure snapscroll never tries to set scrollTop to a value that is out of bounds
53 |
54 | ## 0.3.0
55 |
56 | ### Breaking changes
57 | - Dependency on [angular-wheelie](https://github.com/joelmukuthu/angular-wheelie)
58 |
59 | ### Features
60 | - Support children elements (slides) of unequal heights, but have to be smaller
61 | or equal to the snapscroll element
62 |
63 | ### Fixes
64 | - [`snap-height`](DOCS.md#snap-height) is now an opt-in feature
65 | - If `overflow-y` on the snapscroll element is set to `scroll`, then it is not
66 | changed to `auto`
67 | - Change angular dep version to the lowest supported version (`1.2.24`)
68 |
69 | ## 0.2.5
70 |
71 | ### Features
72 | - Support for installation with npm
73 |
74 | ## 0.2.4
75 |
76 | ### Fixes
77 | - Fix wheel event when jQuery is also included on the page
78 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | Feel free to contribute!
2 |
3 | 1. Create an issue where your contribution can be tracked/discussed
4 | 2. Fork the repo and make updates. Create git branches as you see fit
5 | 3. Write tests for your changes and verify that all tests run
6 | 5. Submit a pull request, referencing the issue that your changes will fix
7 |
--------------------------------------------------------------------------------
/DOCS.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | **Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
4 |
5 | - [angular-snapscroll](#angular-snapscroll)
6 | - [snapscroll](#snapscroll)
7 | - [snap-index](#snap-index)
8 | - [snap-height](#snap-height)
9 | - [fit-window-height](#fit-window-height)
10 | - [enable-arrow-keys](#enable-arrow-keys)
11 | - [disable-wheel-binding](#disable-wheel-binding)
12 | - [ignore-wheel-class](#ignore-wheel-class)
13 | - [before-snap](#before-snap)
14 | - [after-snap](#after-snap)
15 | - [snap-animation](#snap-animation)
16 | - [snap-duration](#snap-duration)
17 | - [snap-easing](#snap-easing)
18 | - [prevent-snapping-after-manual-scroll](#prevent-snapping-after-manual-scroll)
19 | - [scroll-delay](#scroll-delay)
20 | - [resize-delay](#resize-delay)
21 | - [prevent-double-snap-delay](#prevent-double-snap-delay)
22 |
23 |
24 |
25 | # angular-snapscroll
26 |
27 | ## snapscroll
28 | Adds scroll-and-snap behaviour to any element that has a vertical scrollbar:
29 | ```html
30 |
31 |
32 |
33 |
34 |
35 | ```
36 | You can disable snapscroll programmatically by passing `false` or a binding that
37 | evaluates to `false`:
38 | ```javascript
39 | angular.controller('MainCtrl', function ($scope, $window) {
40 | $scope.snapscrollEnabled = $window.innerWidth > 320;
41 | });
42 | ```
43 | ```html
44 |
45 |
...
46 |
47 |
48 |
...
49 |
50 | ```
51 |
52 | Other attributes that can be added are:
53 |
54 | ### snap-index
55 | provides a two-way bind to the current index of the visible child element.
56 | indeces are zero-based.
57 | ```html
58 |
59 |
...
60 | ```
61 | ```html
62 |
63 |
64 |
...
65 |
66 | ```
67 |
68 | ### snap-height
69 | allows you to provide the height of the element (and children elements) instead
70 | of doing it in CSS. this is a two-way bind.
71 | ```html
72 |
...
73 | ```
74 | ```html
75 |
76 |
...
77 |
78 | ```
79 |
80 | ### fit-window-height
81 | instead of `snap-height`, you can use this attribute (it's actually a directive)
82 | to make the snapHeight equal the window height. snapHeight will be updated
83 | automatically if the window is resized.
84 | ```html
85 |
...
86 | ```
87 |
88 | ### enable-arrow-keys
89 | enable support for snapping up and down when the up and down keyboard keys are
90 | pressed, respectively.
91 | ```html
92 |
...
93 | ```
94 |
95 | ### disable-wheel-binding
96 | by default, wheel (and trackpad) events will lead to the element being snapped
97 | up or down. you can disable this functionality using this attribute, which means
98 | that wheel events will lead to the element being scrolled normally instead of
99 | being snap-scrolled.
100 | ```html
101 |
...
102 | ```
103 | note that you will still be able to control snapping using the
104 | [`snap-index`](#snap-index) binding and using the keyboard arrow keys if
105 | [`enable-arrow-keys`](#enable-arrow-keys) is set.
106 |
107 | also note that when the element is scrolled normally, snapscroll will try to
108 | reset the `scrollTop` so that the current snap is fully visible. So to ensure
109 | wheel events have completely no side-effects, also set the
110 | [`prevent-snapping-after-manual-scroll`](#prevent-snapping-after-manual-scroll)
111 | attribute.
112 |
113 | ### ignore-wheel-class
114 | snapscroll takes over the wheel events for the element it's bound to and
115 | translates them to snapping up/down. to allow the normal scrolling on a nested
116 | element (i.e. prevent snapping when the wheel event comes from that element),
117 | add a class to the element and provide that class-name as the value for the
118 | `ignore-wheel-class` attribute.
119 | ```html
120 |
121 |
122 |
normal scrolling here
123 |
124 |
125 | ```
126 | note that if you wish to ignore wheel events from an element with children, then
127 | the class-name must also be added to the child elements. that's because in this
128 | case wheel events will bubble from the child elements.
129 |
130 | ### before-snap
131 | is a callback executed before snapping occurs. the callback is passed a
132 | `snapIndex` parameter, which is the index being snapped to, and an `$event`
133 | parameter, which is the event triggering the snapping, if available (e.g.
134 | WheelEvent if it was the mousewheel or KeyboardEvent if it was an arrow key).
135 | returning `false` from this callback will prevent snapping. you can also override
136 | the next `snapIndex` by returning a number.
137 | ```javascript
138 | angular.controller('MainCtrl', function ($scope) {
139 | $scope.beforeSnap = function (snapIndex) {
140 | console.log('snapping to', snapIndex);
141 | if (snapIndex > 4) {
142 | return false; // prevent snapping
143 | }
144 | if (snapIndex === 2) {
145 | return 3; // snap to snapIndex 3 instead
146 | }
147 | };
148 | });
149 | ```
150 | ```html
151 |
152 |
...
153 |
154 | ```
155 |
156 | ### after-snap
157 | is a callback executed after snapping occurs. the callback is passed a
158 | `snapIndex` parameter, which is the index just snapped to, and an `$event`
159 | parameter, which is the event triggering the snapping if available ( e.g.
160 | WheelEvent if it was the mousewheel or KeyboardEvent if it was an arrow key). any return value from
161 | this callback is ignored.
162 | ```javascript
163 | angular.controller('MainCtrl', function ($scope) {
164 | $scope.log = function (snapIndex) {
165 | console.log('just snapped to', snapIndex);
166 | };
167 | });
168 | ```
169 | ```html
170 |
196 | ```
197 |
198 | ### snap-duration
199 | integer value indicating the length of the snap animation in milliseconds. a
200 | value of 0 disables the snap-animation as well. default is 800ms.
201 | ```html
202 |
...
203 | ```
204 | the snap-duration can also be changed for all snapscroll instances by changing
205 | the default value:
206 | ```javascript
207 | angular.module('myapp', ['snapscroll'])
208 | .value('defaultSnapscrollSnapDuration', 1200);
209 | ```
210 |
211 | ### snap-easing
212 | function reference that allows overriding the default easing of the snap
213 | animation. note that this is not a regular angular callback but rather a
214 | function reference. the default easing is easeInOutQuad. any of the javascript
215 | easing functions can be provided.
216 | ```javascript
217 | angular.controller('MainCtrl', function ($scope) {
218 | $scope.linearEasing = function () {
219 | // easing code
220 | };
221 | });
222 | ```
223 | ```html
224 |
225 |
...
226 |
227 | ```
228 | the snap-easing can also be changed for all snapscroll instances by changing the
229 | default value:
230 | ```javascript
231 | angular.module('myapp', ['snapscroll'])
232 | .value('defaultSnapscrollScrollEasing', function () {
233 | // ... easing code
234 | });
235 | ```
236 |
237 | ### prevent-snapping-after-manual-scroll
238 | snapscroll listens to the `scroll` event on the element that it's bound to and
239 | automatically resets the current snap after a manual scroll so that it's always
240 | fully visible. this behaviour can be prevented by adding this attribute.
241 |
242 | ### scroll-delay
243 | the `scroll` listener described above is throttled using a `scroll-delay`. this
244 | delay can be changed by providing a value in milliseconds. it can also be turned
245 | off by providing `false`.
246 | ```html
247 |
...
248 | ```
249 | the scroll-delay can also be changed for all snapscroll instances by changing
250 | the default value:
251 | ```javascript
252 | angular.module('myapp', ['snapscroll'])
253 | .value('defaultSnapscrollScrollDelay', 400);
254 | ```
255 |
256 | ### resize-delay
257 | the `resize` listener used by `fit-window-height` is throttled using a
258 | `resize-delay`. this delay can be changed by providing a value in milliseconds.
259 | it can also be turned off by providing `false`.
260 | ```html
261 |
...
262 | ```
263 | the scroll-delay can also be changed for all snapscroll instances by changing
264 | the default value:
265 | ```javascript
266 | angular.module('myapp', ['snapscroll'])
267 | .value('defaultSnapscrollResizeDelay', 400);
268 | ```
269 |
270 | ### prevent-double-snap-delay
271 | In order to prevent snapping twice in the same direction on trackpads with high
272 | sensitivity, there is a 1 second delay that disables snapping to the same
273 | direction. This can be altered using this attribute or disabled altogether by
274 | passing `false`.
275 | ```html
276 |
...
277 | ```
278 | the scroll-delay can also be changed for all snapscroll instances by changing
279 | the default value:
280 | ```javascript
281 | angular.module('myapp', ['snapscroll'])
282 | .value('defaultSnapscrollPreventDoubleSnapDelay', 400);
283 | ```
284 |
--------------------------------------------------------------------------------
/Gruntfile.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = function (grunt) {
4 |
5 | require('load-grunt-tasks')(grunt);
6 |
7 | grunt.initConfig({
8 | pkg: grunt.file.readJSON('package.json'),
9 |
10 | info: {
11 | banner: {
12 | short: '/* <%= pkg.name %> v<%= pkg.version %>, (c) 2014-<%= grunt.template.today("yyyy") %> Joel Mukuthu, MIT License, built: <%= grunt.template.date("dd-mm-yyyy HH:MM:ss Z") %> */\n',
13 | long: '/**\n * <%= pkg.name %>\n * Version: <%= pkg.version %>\n * (c) 2014-<%= grunt.template.today("yyyy") %> Joel Mukuthu\n * MIT License\n * Built on: <%= grunt.template.date("dd-mm-yyyy HH:MM:ss Z") %>\n **/\n\n'
14 | }
15 | },
16 |
17 | clean: {
18 | dist: 'dist'
19 | },
20 |
21 | concat: {
22 | options: {
23 | separator: '\n',
24 | banner: '<%= info.banner.long %>'
25 | },
26 | dist: {
27 | src: ['src/*.js', 'src/**/*.js'],
28 | dest: 'dist/<%= pkg.name %>.js'
29 | }
30 | },
31 |
32 | uglify: {
33 | options: {
34 | banner: '<%= info.banner.short %>'
35 | },
36 | dist: {
37 | src: ['<%= concat.dist.dest %>'],
38 | dest: 'dist/<%= pkg.name %>.min.js'
39 | }
40 | },
41 |
42 | eslint: {
43 | target: [
44 | 'src/**/*.js',
45 | 'test/spec/**/*.js'
46 | ]
47 | },
48 |
49 | karma: {
50 | options: {
51 | configFile: 'test/karma.conf.js'
52 | },
53 | single: {
54 | singleRun: true
55 | }
56 | },
57 |
58 | watch: {
59 | files: [
60 | 'src/**/*.js',
61 | 'test/spec/**/*.js'
62 | ],
63 | tasks: [
64 | 'newer:eslint',
65 | 'karma:single'
66 | ]
67 | },
68 |
69 | 'release-it': {
70 | options: {
71 | pkgFiles: ['package.json', 'bower.json'],
72 | commitMessage: 'Release %s',
73 | tagName: 'v%s',
74 | tagAnnotation: 'Release %s',
75 | buildCommand: 'grunt build'
76 | }
77 | }
78 | });
79 |
80 | grunt.registerTask('default', [
81 | 'eslint',
82 | 'watch'
83 | ]);
84 |
85 | grunt.registerTask('test', [
86 | 'eslint',
87 | 'karma:single'
88 | ]);
89 |
90 | grunt.registerTask('build', [
91 | 'test',
92 | 'clean:dist',
93 | 'concat',
94 | 'uglify'
95 | ]);
96 | };
97 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License
2 |
3 | Copyright (c) 2014 - 2017, Joel Mukuthu.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # angular-snapscroll
2 |
3 | [](https://greenkeeper.io/)
4 | [](https://travis-ci.org/joelmukuthu/angular-snapscroll) [](https://david-dm.org/joelmukuthu/angular-snapscroll) [](https://github.com/joelmukuthu/angular-snapscroll/blob/master/LICENSE.md) [](https://coveralls.io/r/joelmukuthu/angular-snapscroll) [](https://github.com/joelmukuthu/angular-snapscroll) [](https://www.npmjs.com/package/angular-snapscroll)
5 |
6 | ## UPDATE 2020-04-14: Archived
7 |
8 | This project still works as is but is no longer maintained.
9 |
10 | ---
11 |
12 | angular-snapscroll adds vertical scroll-and-snap functionality to angular.
13 |
14 | - JS-only implementation
15 | - Only requires angular core
16 | - 6.2kB when minified, 2.3kB when gzipped
17 |
18 | ### [Demo](http://joelmukuthu.github.io/angular-snapscroll/)
19 |
20 | ### Installation
21 | Install with bower:
22 | ```sh
23 | bower install angular-snapscroll
24 | ```
25 | Or with npm:
26 | ```sh
27 | npm install angular-snapscroll
28 | ```
29 | Or simply download the [latest release](https://github.com/joelmukuthu/angular-snapscroll/releases/latest).
30 | Note that in this case you also need to download the
31 | [latest angular-wheelie release](https://github.com/joelmukuthu/angular-wheelie/releases/latest)
32 | and the
33 | [latest angular-scrollie release](https://github.com/joelmukuthu/angular-scrollie/releases/latest).
34 |
35 | ### Usage
36 | The pre-built files can be found in the `dist/` directory.
37 | `dist/angular-snapscroll.min.js` is minified and production-ready. Example usage:
38 | ```html
39 |
40 |
41 |
42 | ```
43 | Add `snapscroll` to your app's module dependencies:
44 | ```javascript
45 | angular.module('myapp', ['snapscroll']);
46 | ```
47 | And now you can add a `snapscroll` attribute to any element to make it
48 | snap-scrollable! The element would have a scrollbar to begin with, the idea being
49 | that with the `snapscroll` attribute you're adding scroll-and-snap behaviour to
50 | an element that is otherwise already scrollable:
51 | ```html
52 |
53 |
54 |
55 |
56 |
57 | ```
58 | All you need to set are the heights of the snapscroll element and it's children
59 | (you can also use the [`snap-height`](DOCS.md#snap-height) attribute for that).
60 | To have the element fill the browser viewport height:
61 | ```html
62 |
63 |
64 |
65 |
66 |
67 | ```
68 |
69 | ### Touch support
70 | I recommend using [angular-swipe](https://github.com/marmorkuchen-net/angular-swipe)
71 | to add touch support but you can use any other library or module that recognizes
72 | vertical swipe gestures (e.g. hammer.js). Here's how to do it using angular-swipe:
73 | ```html
74 |