Skip to content

Commit

Permalink
Add more configuration options (#374)
Browse files Browse the repository at this point in the history
* Add more configuration options

* Add cleanup functionality
  • Loading branch information
scriptex committed Jan 12, 2022
1 parent eb854ec commit 352c680
Show file tree
Hide file tree
Showing 11 changed files with 517 additions and 1,967 deletions.
99 changes: 86 additions & 13 deletions README.md
Expand Up @@ -9,17 +9,15 @@

# ScrollSpy

A vanilla ES2017 module for scroll spy functionality.
> Automatically update your navigation components based on scroll position to indicate which link is currently active in the viewport.
## Install

```sh
npm i @three11/scrollspy
```

or
# or

```sh
yarn add @three11/scrollspy
```

Expand All @@ -28,15 +26,15 @@ or
Just download this repository and link the files located in dist folder:

```html
<script src="path-to-scrollspy/dist/scrollspy.min.js"></script>
<script src="path-to-scrollspy/dist/index.js"></script>
```

or

Include it from Unpkg CDN

```html
<script src="//unpkg.com/@three11/scrollspy/dist/scrollspy.min.js"></script>
<script src="//unpkg.com/@three11/scrollspy"></script>
```

## Usage
Expand All @@ -50,24 +48,99 @@ import ScrollSpy from '@three11/scrollspy';
Then initialize a new instance of the module:

```javascript
const scrollSpy = new ScrollSpy();
const scrollSpy = new ScrollSpy(scrollSpySettings, scrollSpyEasings);
```

## Settings

The default settings are:

| Name | Type | Description | Default |
| ------------------------ | ---------- | -------------------------------------------------------------------- | ------------------------ |
| `headerClass` | `string` | The class name of your Header element | `.c-header` |
| `headerOffset` | `boolean` | Flag which indicates if the Header height should be calculated | `true` |
| `animationSpeed` | `number` | Speed of the scroll animation (in milliseconds) | `2000` |
| `animationEasing` | `string` | Name of the easing function. For more details see below | `easeInOutQuint` |
| `sectionSelector` | `string` | CSS selector for your Section elements | `.js-scroll-spy-section` |
| `linkCurrentClass` | `string` | Class name to be applied to the currently active link | `current` |
| `linksContainerSelector` | `string` | CSS selector for your scroll spy navigation | `.js-scroll-spy-nav` |
| `onAfterScroll` | `function` | A function to run after the scroll after click on a link is complete | `() => {}` |

## Easings

The `ScrollSpy` instance accepts a second optional argument which specifies a list of easing functions.

The current list contains several predefined easing functions:

```javascript
{
linear: t => t,
easeInQuad: t => t * t,
easeOutQuad: t => t * (2 - t),
easeInCubic: t => t * t * t,
easeOutCubic: t => --t * t * t + 1,
easeInQuart: t => t * t * t * t,
easeOutQuart: t => 1 - --t * t * t * t,
easeInQuint: t => t * t * t * t * t,
easeOutQuint: t => 1 + --t * t * t * t * t,
easeInOutQuad: t => (t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t),
easeInOutCubic: t => (t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1),
easeInOutQuart: t => (t < 0.5 ? 8 * t * t * t * t : 1 - 8 * --t * t * t * t),
easeInOutQuint: t => (t < 0.5 ? 16 * t * t * t * t * t : 1 + 16 * --t * t * t * t * t),
}
```

If you wish to add your own easing function, you can do so by adding it to the second argument of the `ScrollSpy` constructor.

Just remember that your custom easing function should accept a single `time` argument which is a `number` and should return a `number`.

In order to use your custom easing function, you need to specify its name in the `animationEasing` setting.

## API

There are two public methods of the `ScrollSpy` instance.

The `unbind` method unbinds (removes) all of the event listeners and the `bind` method binds (adds) all of the event listeners.

These methods are useful in various cases - for example if you load the content of your pages with AJAX and you want to remove all possible memory leaks after you remove the ScrollSpy markup/HTML.

Here is how you can use them:

```javascript
const scrollSpy = new ScrollSpy(scrollSpySettings, scrollSpyEasings);

// Later in your code
scrollSpy.unbind();

// Then, if you wish to re-enable the ScrollSpy functionality
scrollSpy.bind();
```

## Example

```javascript
linkCurrentClass : 'current', // The class that will be applied to the current element
linksContainerSelector: '.js-scroll-spy-nav', // The container of the scroll spy navigation
sectionSelector : '.js-scroll-spy-section', // The selector for the sections that will be monitored
headerOffset : true, // Should calculate the header height
headerClass : '.c-header', // The class of the header element
new ScrollSpy(
{
linkCurrentClass: 'current',
linksContainerSelector: '.nav',
sectionSelector: '.section',
headerOffset: true,
headerClass: '.header',
animationSpeed: 3000,
animationEasing: 'customEasingFunction',
onAfterScroll: () => {
console.log('scroll ended');
}
},
{
customEasingFunction: t => t ** t
}
);
```

## Demo

A minimal demo is available [here](https://github.com/three11/scrollspy/blob/master/demo/index.html)
A minimal demo is available [here](https://three11-scrollspy.netlify.app)

## License

Expand Down
43 changes: 43 additions & 0 deletions dist/index.d.ts
@@ -0,0 +1,43 @@
export declare type EasingFunction = (t: number) => number;
export declare type EasingFunctions = Record<string, EasingFunction>;
export declare type UnknownFunction = (...args: unknown[]) => unknown;
export declare type ScrollToOptions = {
readonly position: number;
readonly duration: number;
readonly callback: UnknownFunction;
readonly easingFunction: EasingFunction;
};
export declare type ScrollSpyOptions = {
readonly headerClass: string;
readonly headerOffset: boolean;
readonly animationSpeed: number;
readonly animationEasing: string;
readonly sectionSelector: string;
readonly linkCurrentClass: string;
readonly linksContainerSelector: string;
readonly onAfterScroll: UnknownFunction;
};
export default class ScrollSpy {
private options;
private easings;
private links;
private sections;
private currentIdx;
private headerClass;
private headerOffset;
private linksContainer;
private sectionSelector;
private linkCurrentClass;
private linksContainerSelector;
private data;
constructor(settings?: Partial<ScrollSpyOptions>, easings?: EasingFunctions);
init(): void;
private setProperties;
private setSectionData;
private refreshPositions;
private getSectionOffset;
private setCurrentIndex;
private setCurrentState;
bind(): void;
unbind(): void;
}
19 changes: 16 additions & 3 deletions demo/index.html → dist/index.html
Expand Up @@ -110,16 +110,29 @@ <h4>Section 4</h4>
<p>&copy; 2018 Three 11 | License MIT</p>
</footer>

<script src="../dist/scrollspy.min.js"></script>
<script src="./index.js"></script>

<script>
new ScrollSpy({
const instance = new ScrollSpy({
linkCurrentClass: 'current',
linksContainerSelector: '.nav',
sectionSelector: '.section',
headerOffset: true,
headerClass: '.header'
headerClass: '.header',
animationSpeed: 300,
animationEasing: 'easeInCubic',
onAfterScroll: () => {
console.log('scroll ended');
}
});

// Remove all event listeners after 20 seconds.
// This is just for demo purposes
// This stops the ScrollSpy functionality.

// setTimeout(() => {
// instance.unbind();
// }, 20000);
</script>
</body>
</html>
15 changes: 15 additions & 0 deletions dist/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion dist/scrollspy.min.js

This file was deleted.

33 changes: 15 additions & 18 deletions package.json
@@ -1,23 +1,22 @@
{
"name": "@three11/scrollspy",
"version": "1.0.0",
"description": "Vanilla ES2017 module for scroll spy",
"main": "dist/scrollspy.min.js",
"version": "2.0.0",
"description": "Automatically update your navigation components based on scroll position to indicate which link is currently active in the viewport",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"typings": "dist/index.d.ts",
"scripts": {
"build": "rollup -c"
},
"dependencies": {
"@three11/animate-top-offset": "^1.0.0"
"build": "rollup -c",
"start": "rollup -c -w"
},
"repository": {
"type": "git",
"url": "git+https://github.com/three11/scrollspy.git"
},
"keywords": [
"Spy",
"Scroll",
"JS",
"ES2017"
"ScrollSpy",
"Navigation",
"Animated scroll"
],
"authors": [
{
Expand All @@ -41,14 +40,12 @@
"url": "https://github.com/three11/scrollspy/issues"
},
"homepage": "https://github.com/three11/scrollspy#readme",
"dependencies": {},
"devDependencies": {
"@babel/cli": "7.16.8",
"@babel/core": "7.16.7",
"@babel/preset-env": "7.16.8",
"@rollup/plugin-typescript": "8.3.0",
"rollup": "2.63.0",
"rollup-plugin-babel": "4.4.0",
"rollup-plugin-commonjs": "10.1.0",
"rollup-plugin-node-resolve": "5.2.0",
"rollup-plugin-terser": "7.0.2"
"rollup-plugin-terser": "7.0.2",
"tslib": "2.3.1",
"typescript": "4.5.4"
}
}

0 comments on commit 352c680

Please sign in to comment.