Drag’n’Drop without CSS classes using ObservableTypes

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…


This content originally appeared on DEV Community and was authored by Dario Mannu

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:


This content originally appeared on DEV Community and was authored by Dario Mannu


Print Share Comment Cite Upload Translate Updates
APA

Dario Mannu | Sciencx (2024-11-07T00:02:29+00:00) Drag’n’Drop without CSS classes using ObservableTypes. Retrieved from https://www.scien.cx/2024/11/07/dragndrop-without-css-classes-using-observabletypes/

MLA
" » Drag’n’Drop without CSS classes using ObservableTypes." Dario Mannu | Sciencx - Thursday November 7, 2024, https://www.scien.cx/2024/11/07/dragndrop-without-css-classes-using-observabletypes/
HARVARD
Dario Mannu | Sciencx Thursday November 7, 2024 » Drag’n’Drop without CSS classes using ObservableTypes., viewed ,<https://www.scien.cx/2024/11/07/dragndrop-without-css-classes-using-observabletypes/>
VANCOUVER
Dario Mannu | Sciencx - » Drag’n’Drop without CSS classes using ObservableTypes. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2024/11/07/dragndrop-without-css-classes-using-observabletypes/
CHICAGO
" » Drag’n’Drop without CSS classes using ObservableTypes." Dario Mannu | Sciencx - Accessed . https://www.scien.cx/2024/11/07/dragndrop-without-css-classes-using-observabletypes/
IEEE
" » Drag’n’Drop without CSS classes using ObservableTypes." Dario Mannu | Sciencx [Online]. Available: https://www.scien.cx/2024/11/07/dragndrop-without-css-classes-using-observabletypes/. [Accessed: ]
rf:citation
» Drag’n’Drop without CSS classes using ObservableTypes | Dario Mannu | Sciencx | https://www.scien.cx/2024/11/07/dragndrop-without-css-classes-using-observabletypes/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.