Skip to content

Commit 6d4ac56

Browse files
authored
Make handy-scroll a web component (#26)
* Implement handy-scroll as a web component * Update docs * Update docs * Uninstall optional dependency * Add type declaration. Minor updates * Minor fix in typings * Update dev dependencies. Prevent emptying outDir
1 parent 47be80a commit 6d4ac56

23 files changed

+1370
-3916
lines changed

.babelrc

Lines changed: 0 additions & 5 deletions
This file was deleted.

.husky/pre-commit

Lines changed: 0 additions & 1 deletion
This file was deleted.

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ If you have found a bug, please feel free to report an issue after ensuring that
66

77
## Making changes in code and opening a pull request
88

9-
If you know the way to fix some bug or just to make the widget better, you are welcome to open a pull request. Please provide a clear and detailed description of what do your changes fix or improve, or refer an existing issue containing such an explanation.
9+
If you know the way to fix some bug or just to make the component better, you are welcome to open a pull request. Please provide a clear and detailed description of what do your changes fix or improve, or refer an existing issue containing such an explanation.
1010

1111
Before submitting a new pull request be sure to do the following things.
1212

README.md

Lines changed: 35 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -1,132 +1,75 @@
11
# handy-scroll
22

3-
Handy dependency-free floating scrollbar widget
3+
Handy dependency-free floating scrollbar web component.
44

55
## Synopsis
66

7-
handy-scroll is a dependency-free module which can be used to solve the problem of scrolling some lengthy containers horizontally when those containers don’t fit into the viewport. The widget is just a scrollbar which is attached at the bottom of the container’s visible area. It doesn’t get out of sight when the page is scrolled, thereby making horizontal scrolling of the container much handier.
7+
handy-scroll is a dependency-free web component which can be used to solve the problem of scrolling lengthy containers horizontally when those containers don’t fit into the viewport. The component is just a scrollbar which is attached at the bottom of the container’s visible area. It doesn’t get out of sight when the page is scrolled, thereby making horizontal scrolling of the container much handier.
88

9-
> [!TIP]
10-
> * If you are rather looking for a jQuery plugin with the same functionality, please check out the sibling project [floating-scroll](https://github.com/Amphiluke/floating-scroll) instead.
11-
> * Developing a Vue.js-based app? Consider using the [vue-handy-scroll](https://github.com/Amphiluke/vue-handy-scroll) component.
9+
> [!NOTE]
10+
> Current version of the component targets modern browsers only. If you need to support older browser versions, please stick to the former implementation [[email protected]](https://github.com/Amphiluke/handy-scroll/tree/v1).
1211
13-
## Usage
12+
## Installation and import
1413

15-
The widget requires the CSS file [handy-scroll.css](dist/handy-scroll.css) to be included on the page (you may also import it in your CSS/LESS files). The module script file [handy-scroll.min.js](dist/handy-scroll.min.js) may be added on the web page either via a separate `<script>` element, or it may be loaded by any AMD/CommonJS compatible module loader.
14+
If you use a bundler in your project, install handy-scroll as a dependency:
1615

17-
:bulb: **Tip:** If you don’t care about supporting Internet Explorer, feel free to use the file [handy-scroll.es6.min.js](dist/handy-scroll.es6.min.js), which is de facto the same as handy-scroll.min.js but is written in ES6, and is a bit smaller.
18-
19-
The handy-scroll package is available on npm, so you may add it to your project as usual:
20-
21-
```
16+
```shell
2217
npm install handy-scroll
2318
```
2419

25-
## Details & API
26-
27-
The module exports a single object `handyScroll` which provides the following methods:
28-
29-
* [`mount`](#mounting-the-widget) — initializes and “mounts” the widgets in the specified containers;
30-
* [`mounted`](#checking-widget-existence) — checks if the widget is already mounted in the given container;
31-
* [`update`](#updating-scrollbar) — updates the widget parameters and position;
32-
* [`destroy`](#destroying-the-widget) — destroys the widgets mounted in the specified containers and removes all related event handlers;
33-
* [`destroyDetached`](#destroying-detached-widgets) — destroys handy-scroll widget instances whose containers were removed from the document.
34-
35-
### Mounting the widget
36-
37-
The only thing required to attach the widget to a static container (whose sizes will never change during the session) is a single call of the `handyScroll.mount()` method. The method expects a single argument, the target containers reference, which can be either an element, or a list of elements, or a selector.
20+
Now you may import it wherever it’s needed:
3821

3922
```javascript
40-
// mount widget in the specified container element
41-
handyScroll.mount(document.getElementById("spacious-container"));
42-
43-
// mount widgets in all the container elements in the collection
44-
handyScroll.mount(document.getElementsByClassName("spacious-container"));
45-
handyScroll.mount([myDOMElement1, myDOMElement2, myDOMElement3]);
46-
47-
// mount widgets in all the container elements matching the selector
48-
handyScroll.mount(".examples > .spacious-container");
23+
import "handy-scroll";
4924
```
5025

51-
### Auto-initialisation
52-
53-
There is another way to mount the handy-scroll widget without writing a single line of JavaScript code. Just add the attribute `data-handy-scroll` to the desired containers. As the DOM is ready the module will detect all such elements and will mount widgets automatically.
26+
If you don’t use bundlers, just import the component as a module in your HTML files:
5427

5528
```html
56-
<div class="spacious-container" data-handy-scroll>
57-
<!-- Horizontally wide contents -->
58-
</div>
29+
<script type="module" src="https://unpkg.com/handy-scroll"></script>
5930
```
6031

61-
### Checking widget existence
32+
## Standard usage
6233

63-
You may check if the widget is already mounted in the given container by calling the `handyScroll.mounted()` method.
34+
Drop the custom element `<handy-scroll>` where you need in your markup and link the component to the horizontally-scrollable target using the `owner` attribute:
6435

65-
```javascript
66-
handyScroll.mount("#spacious-container");
67-
console.log(handyScroll.mounted("#spacious-container")); // true
68-
```
69-
70-
### Updating scrollbar
71-
72-
If you mount the widget in a container whose size and/or content may dynamically change, you need a way to update the scrollbar each time the container’s sizes change. This can be done by invoking the method `handyScroll.update()` as in the example below.
73-
74-
```javascript
75-
handyScroll.mount(".spacious-container");
76-
// ... some actions which change the total scroll width of the container ...
77-
handyScroll.update(".spacious-container");
36+
```html
37+
<div id="horizontally-scrollable">
38+
<!-- Horizontally wide contents -->
39+
</div>
40+
<handy-scroll owner="horizontally-scrollable"></handy-scroll>
7841
```
7942

80-
The method expects a single argument, the target containers reference, which can be either an element, or a list of elements, or a selector.
81-
82-
### Destroying the widget
43+
## Custom viewport element
8344

84-
To unmount the widget and remove all related event handlers, use the method `handyScroll.destroy()` as follows:
45+
Standard use case above implies that handy-scroll will stick to the bottom of the browser window viewport. If instead you want to attach a floating scrollbar at the bottom of your custom scrollable “viewport” (e.g. a scrollable modal popup), then you need to link the component to your custom viewport element using the `viewport` attribute:
8546

86-
```javascript
87-
handyScroll.destroy(".spacious-container");
47+
```html
48+
<div id="custom-viewport">
49+
<div id="horizontally-scrollable">
50+
<!-- Horizontally wide contents -->
51+
</div>
52+
<handy-scroll owner="horizontally-scrollable" viewport="custom-viewport"></handy-scroll>
53+
</div>
8854
```
8955

90-
The method expects a single argument, the target containers reference, which can be either an element, or a list of elements, or a selector.
56+
## API
9157

58+
### `HandyScroll.prototype.update()`
9259

93-
### Destroying detached widgets
94-
95-
If your app completely re-renders a large portion of DOM where handy-scroll widgets were mounted, actual container references are lost, and therefore you cannot unmount the widgets and perform related cleanup using the `destroy` method. In this case, you may just call the `handyScroll.destroyDetached()` method, and the module will find all “zombie” instances and will destroy them for you.
60+
handy-scroll automatically tracks viewport changes in order to keep the component’s size, position and visibility in sync with the owner’s metrics. However there can be some cases when you’ll need to trigger the component update programmatically (e.g. after some changes in DOM). To do so, just call the method `update()` on the specific `<handy-scroll>` element:
9661

9762
```javascript
98-
handyScroll.mount(".main-view .spacious-container");
99-
// ... the app re-renders the main view ...
100-
document.querySelector(".main-view").innerHTML = "...";
101-
// destroy handy-scroll widgets whose containers are not in the document anymore
102-
handyScroll.destroyDetached();
63+
document.getElementById("my-handy-scroll").update();
10364
```
10465

105-
### Special cases
106-
107-
If you want to attach the widget to a container living in a positioned box (e.g. a modal popup with `position: fixed`) then you need to apply two special indicating class names in the markup. The module detects these indicating class names (they are prefixed with `handy-scroll-`) and switches to a special functioning mode.
108-
109-
```html
110-
<div class="handy-scroll-viewport"><!-- (1) -->
111-
<div class="handy-scroll-body"><!-- (2) -->
112-
<div class="spacious-container">
113-
<!-- Horizontally wide contents -->
114-
</div>
115-
</div>
116-
</div>
117-
```
118-
119-
The `.handy-scroll-viewport` element (1) is a positioned block (with any type of positioning except `static`) which serves for correct positioning of the widget. Note that this element itself should _not_ be scrollable. The `.handy-scroll-body` element (2) is a vertically scrollable block (with `overflow: auto`) which encloses the target container the widget is mounted in. After applying these special class names, you may initialise the widget as usual:
120-
121-
```javascript
122-
handyScroll.mount(".spacious-container");
123-
```
66+
### `HandyScroll.prototype.owner`
12467

125-
The [handy-scroll.css](dist/handy-scroll.css) file provides some basic styles for elements with classes `.handy-scroll-viewport` and `.handy-scroll-body`. Feel free to adjust their styles in your stylesheets as needed.
68+
Reflects the value of the `owner` attribute, which in turn should reference the `id` attribute of the horizontally-scrollable container (owner).
12669

127-
### “Unobtrusive” mode
70+
### `HandyScroll.prototype.viewport`
12871

129-
You can make the widget more “unobtrusive” so that it will appear only when the mouse pointer hovers over the scrollable container. To do so just apply the class `handy-scroll-hoverable` to the desired scrollable container owning the widget.
72+
Reflects the value of the `viewport` attribute, which (if present) should reference the `id` attribute of the element serving as custom viewport.
13073

13174
## Live demos
13275

dist/handy-scroll.css

Lines changed: 0 additions & 1 deletion
This file was deleted.

dist/handy-scroll.d.mts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
declare class HandyScroll extends HTMLElement {
2+
#private;
3+
static get observedAttributes(): string[];
4+
get owner(): string | null;
5+
set owner(ownerId: string);
6+
get viewport(): string | null;
7+
set viewport(viewportId: string);
8+
constructor();
9+
connectedCallback(): void;
10+
disconnectedCallback(): void;
11+
attributeChangedCallback(name: string): void;
12+
update(): void;
13+
}
14+
export default HandyScroll;

dist/handy-scroll.d.ts

Lines changed: 0 additions & 10 deletions
This file was deleted.

0 commit comments

Comments
 (0)