Home >Web Front-end >JS Tutorial >Drag&#n&#Drop without CSS classes using ObservableTypes

Drag&#n&#Drop without CSS classes using ObservableTypes

Mary-Kate Olsen
Mary-Kate OlsenOriginal
2024-11-09 07:07:02359browse

Drag

Many UI libraries and CSS frameworks used to enable special functionality by resorting to CSS classes. This was especially trendy at the time of jQuery plugins.

Despite being a very popular choice, it's definitely a programming anti-pattern.

Today we have several alternative ways. One approach from the functional-reactive land makes it possible to just "merge" functionality into an existing element. No CSS classes, no id attribute abuse.

Suppose we want to enable drag'n'drop in an HTML list by means of a separate reusable module we can add or remove at will.

  <ul ...${Sortable({onOrderChange: todoList.move})}>
    <li>item 1</li>
    <li>item 2</li>
    <li>item 3</li>
    <li>item 4</li>
    <li>item 5</li>
  </ul>

Sortable is going to be implemented in what's known as a Mixin. What it does, is export attributes, styles, classes, event handlers in a so called "DOM Object": whatever it contains, will be merged in the target element.

// sortable.ts
import { Subject, map, withLatestFrom } from 'rxjs';

export const Sortable = ({ onOrderChange }) => {
  const dragStart = new Subject<HTMLLIElement>();
  const drop = new Subject<HTMLLIElement>();

  drop.pipe(
    withLatestFrom(dragStart),
    map(([dropEvt, dragEvt]) => {
      const list = [...dragEvt.target.closest('ol,ul').children];
      return [ list.indexOf(dragEvt.target), list.indexOf(dropEvt.target.closest('li')) ]
    }),
  ).subscribe(([src, dst])=>onOrderChange(src, dst));

  // Export a DOM Object for a framework or UI library
  // to take care of and merge into the target element
  return {
    ondragstart: dragStart,
    ondragover: e=>e.preventDefault(),
    ondrop: drop,
  };
};

So, the final application code will look something like this:

import { rml } from 'rimmel';

const List = () => {

  return rml`
      <ul ...${Sortable({onOrderChange: todoList.move})}>
        <li>item 1</li>
        <li>item 2</li>
        <li>item 3</li>
        <li>item 4</li>
        <li>item 5</li>
      </ul>
  `;
}

Play with a fully working example here:

The above is the detailed content of Drag&#n&#Drop without CSS classes using ObservableTypes. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn