Create a JavaScript library. Implement Scroll Lock
Tags: javascript, typescript, webdev, tutorial
Published: 2020-06-24 17:03:24

The basic functionality is implemented, the dev build is working, it's time to expand the general functionality. In this part, I'll add new methods for opening and closing modal windows and work on the scroll behavior.

{% youtube iwfhkOM-IEg %}

## Add new methods

Earlier, we implemented the `init` method that initialized all modal windows according to the markup.

```js
/**
 * Open modal window by selector
 *
 * @param {string} selector - Modal window selector
 * @param {ConfigType} config - Modal window configuration
 */
const open = (selector: string, config?: ConfigType) => {
    const options = config || {};
    modal = new Modal({...options, selector});
    modal.open();
};
```

The `open` method has one required parameter, the modal window selector that needs to be opened, and the second parameter is the `config`. This method creates a new instance of the modal window with the passed selector.

```js
/**
 * Close modal
 *
 * @param {string} selector - Modal window selector
 */
const close = (selector?: string) => {
    if (!modal) return;
    selector ? modal.closeBySelector(selector) : modal.close();
};
```

The `close` method has one optional parameter - a selector. If there are no previously opened modal windows, this function will end its work. If the selector is not passed, the last opened modal window will be closed; if the selector is explicitly passed, the new method `closeBySelector` will be called. In the Modal class, we implement the `closeBySelector` method.

```js
/**
 * Close modal window by selector
 *
 * @param {string} selector - Modal window selector to close
 */
closeBySelector(selector: string) {
    const element = document.querySelector<HTMLElement>(selector);
    if (!element) return;
    this.$modal = element;
    this.close();
}
```

We are looking for an element by the selector. For the found element, call the `close` method. If the item is not found, the function will stop its work.

## Scroll behavior

Modal windows are more convenient to use when the scroll of the main part of the site is blocked. However, this behavior cannot be strictly defined, since some of the modal windows can be informational and in this case, they should not block the scroll.

Let's expand the modal class configuration. It'll be an object of the following type

```js
export type ConfigType = {
    ...
    scrollBehavior?: {
        isDisabled?: boolean;
        container?: string;
        defaultValue?: string;
    };
} 
```

Define the default value for `scrollBehavior`

```js
this.scrollBehavior = {
    isDisabled: true,
    container: 'body',
    defaultValue: '',
    ...scrollBehavior,
};
```

By default, we'll block the scroll for the `body` tag. The scroll behavior method will look like this.

```js
/**
 * Change scroll behavior
 *
 * @param {string} value - Scroll state value
 */
changeScrollBehavior(value: 'disable' | 'enable') {
    if (!this.scrollBehavior.isDisabled) return;
    const element = document.querySelector<HTMLElement>(this.scrollBehavior.container);
    if (!element) return;
    if (value === SCROLL_STATE.ENABLE)
        element.style.overflow = this.scrollBehavior.defaultValue;
    else if (value === SCROLL_STATE.DISABLE) element.style.overflow = 'hidden';
}
```

The method takes one parameter to determine the state of the scroll (there may be one of two options: `disable` or `enable`).  If `isDisabled` is `false` or `container` is not there, the function should not do anything. Further, depending on the state, we change the `overflow` value of the element.

I recommend putting any text data into constants to avoid possible typos when using.

```js
export const SCROLL_STATE = {
    DISABLE: 'disable',
    ENABLE: 'enable',
} as const;
```

The function is ready, add a call to the `open` and `close` methods.

```js
open() {
    this.$modal?.classList.add(this.openClass);
    this.changeScrollBehavior(SCROLL_STATE.DISABLE);
    this.addEventListeners();
}

close() {
    this.$modal?.classList.remove(this.openClass);
    this.changeScrollBehavior(SCROLL_STATE.ENABLE);
    this.removeEventListeners();
}
```

To check, you can set the height of the `body` and then open the modal window. When the `body` tag has `style="overflow: hidden;"` the content under the modal window should stop scrolling. And after closing the modal window, everything should return to its original state

___

Thanks for reading! Some improvements to the library are ready, but more improvements are coming. Join me if you are interested. See you soon 👋