Categories: CSSScriptWeb Design

Mobile-First Drag and Drop Alternative for List Reordering – picknplace.js

picknplace.js is a JavaScript library that replaces traditional drag-and-drop with a two-step pick-and-place interaction pattern.

Standard HTML5 drag and drop APIs are notoriously difficult to control on mobile devices. You might often accidentally scroll the page when you intend to move an item.

Picknplace.js addresses this by changing the interaction model. The user first “picks” an item (locks it), scrolls or moves to the desired location, and then “places” it. This ensures intentionality and prevents accidental UI shifts.

Features:

  • Two-Step Interaction Model: Separates selection from placement.
  • Visual Feedback: Creates a ghost element during picking mode. Users see exactly where their item will be placed.
  • Scroll-Aware Positioning: Automatically adjusts ghost element position during scrolling.
  • Customizable Selectors: Configurable class names and DOM selectors.
  • Keyboard Support: Includes Enter and Escape key handlers for accessibility.
  • State Management Pattern: Uses a reducer-based approach for predictable state transitions.

See It In Action:

Use Cases:

  • Mobile Task Management Apps: Reorder priority lists on smartphones.
  • E-Commerce Product Ordering: Arrange items in wishlists or shopping cart priorities.
  • Dashboard Widget Arrangement: Customize dashboard layouts on tablets.
  • Content Management Systems: Reorder articles, images, or menu items in admin panels.

How It Works:

  • Click on Pick Button: Enters picking mode. Creates a ghost element and cloned list overlay.
  • Click on Place Button: Confirms the new position. Reorders the DOM to match the visual layout.
  • Click on Cancel Button: Exits picking mode. Discards all position changes and removes visual overlays.
  • Enter Key Press: Confirms placement when in picking mode. Functions identically to clicking the Place button.
  • Escape Key Press: Cancels the operation when in picking mode. Functions identically to clicking the Cancel button.
  • Scroll Event: Updates ghost element position during picking mode. Maintains proper visual alignment with list items.

How to use it:

1. Download the picknplace.js library and import the createPickPlace function into your project:

import { createPickPlace } from "./picknplace.js";

2. Initialize the library and attach it to your list elements:

// Create a new instance with default settings
const pnp = createPickPlace();

// Initialize the pick-and-place functionality
pnp.init();

3. Create the list structure. You need a container (list), items (list elements), and trigger buttons inside the items.

<ul class="pnp-list">
  <li class="pnp-item">
    <div class="item-content">
      <div class="avatar">👨‍💻</div>
      <div class="info">
        <span class="name">Alex Chen</span>
        <span class="role">Frontend Lead</span>
      </div>
    </div>
    <div class="pnp-buttons">
      <button class="pnp-pick btn-pick">Move</button>
    </div>
  </li>
  <li class="pnp-item">
    <div class="item-content">
      <div class="avatar">👩‍🎨</div>
      <div class="info">
        <span class="name">Sarah Jones</span>
        <span class="role">Product Designer</span>
      </div>
    </div>
    <div class="pnp-buttons">
      <button class="pnp-pick btn-pick">Move</button>
    </div>
  </li>
  <li class="pnp-item">
    <div class="item-content">
      <div class="avatar">🚀</div>
      <div class="info">
        <span class="name">Mike Ross</span>
        <span class="role">DevOps Engineer</span>
      </div>
    </div>
    <div class="pnp-buttons">
      <button class="pnp-pick btn-pick">Move</button>
    </div>
  </li>
  <li class="pnp-item">
    <div class="item-content">
      <div class="avatar">💼</div>
      <div class="info">
        <span class="name">Jessica Wu</span>
        <span class="role">Product Owner</span>
      </div>
    </div>
    <div class="pnp-buttons">
      <button class="pnp-pick btn-pick">Move</button>
    </div>
  </li>
  <li class="pnp-item">
    <div class="item-content">
      <div class="avatar">🛡️</div>
      <div class="info">
        <span class="name">David Miller</span>
        <span class="role">Security Specialist</span>
      </div>
    </div>
    <div class="pnp-buttons">
      <button class="pnp-pick btn-pick">Move</button>
    </div>
  </li>
  <li class="pnp-item">
    <div class="item-content">
      <div class="avatar">📊</div>
      <div class="info">
        <span class="name">Emily Davis</span>
        <span class="role">Data Scientist</span>
      </div>
    </div>
    <div class="pnp-buttons">
      <button class="pnp-pick btn-pick">Move</button>
    </div>
  </li>
</ul>

4. Create global controls to confirm or cancel the action.

<div class="pnp-controls">
  <button class="pnp-cancel ctrl-btn ctrl-cancel">Cancel (Esc)</button>
  <button class="pnp-place ctrl-btn ctrl-place">Confirm (Enter)</button>
</div>

5. picknplace.js accepts an options object during initialization. All selectors and class names can be customized:

  • root: The root element for event listeners. Default: document.
  • listSelector: Selector for the container element. Default: .pnp-list.
  • itemSelector: Selector for individual list items. Default: .pnp-item.
  • controlsSelector: Selector for the global control container. Default: .pnp-controls.
  • buttonsSelector: Selector for the button container within an item. Default: .pnp-buttons.
  • pickSelector: Selector for the button that starts the pick action. Default: .pnp-pick.
  • placeSelector: Selector for the button that confirms the new position. Default: .pnp-place.
  • cancelSelector: Selector for the button that cancels the action. Default: .pnp-cancel.
  • pickedClass: Class added to the item currently selected. Default: pnp-picked.
  • realClass: Class applied to the original DOM elements. Default: pnp-real.
  • ghostClass: Class applied to the floating duplicate element. Default: pnp-ghost.
  • cloneClass: Class applied to the placeholder clones during sorting. Default: pnp-clone.
createPickPlace({
  // options here
})

Alternatives:

  • Sortable: A lightweight and simple JavaScript library that makes a list of items sortable by using the native HTML5 drag and drop API.
  • dragula: A simple, dependency-free, touch-enabled JavaScript library that provides drag and drop functionality on DOM elements.
  • 10 Best Drag And Drop JavaScript Libraries

FAQs

Q: Can I use this library with dynamically added list items?
A: Yes. The library attaches event listeners to the root element using event delegation. New items added to the list automatically gain pick-and-place functionality.

Q: Does the library work with nested lists?
A: No. The current implementation assumes a flat list structure. Each createPickPlace instance targets a single list level. For nested hierarchies, you would need to create separate instances for each nesting level and handle the interaction boundaries manually.

Q: How do I persist the new order after placement?
A: The library reorders DOM elements but does not handle persistence. After a successful place event, read the new order from the DOM and send it to your backend. You can query all items with document.querySelectorAll('.pnp-item.pnp-real') and extract their data attributes or IDs in sequence.

Q: Can I customize the animation timing for item transitions?
A: Yes. The cloned items use CSS transforms for positioning. Add transition properties to the .pnp-clone class in your stylesheet. For example: .pnp-clone { transition: transform 0.3s ease-out; } will smooth the repositioning animations.

Q: Why does the ghost element sometimes appear offset during fast scrolling?
A: The library adjusts ghost position using CSS custom properties and requestAnimationFrame. On very fast scroll events, there may be a brief visual lag. This happens because the browser processes scroll events faster than animation frames. The offset corrects itself within one frame cycle.

The post Mobile-First Drag and Drop Alternative for List Reordering – picknplace.js appeared first on CSS Script.

rssfeeds-admin

Share
Published by
rssfeeds-admin

Recent Posts

Officers, officials cheer construction of new Concord Police HQ

Inside the concrete shell of the former Concord Insurance Building, Concord Police officers strolled with…

1 minute ago

Belmont Elementary improvises to preserve artist residencies threatened by cuts to State Council on the Arts

A grin pressed Luna Nazariah’s almond eyes into guileless crescents, widening even more as she…

1 minute ago

Boys and Girls Club to close pre-school at former Eastman School following voter approval of sale

The Boys and Girls Clubs of Central and Northern New Hampshire will close its pre-school…

1 minute ago

‘I think we can get a better deal’: Executive Council halts $700M replacement of NH men’s prison

Executive Councilor Karen Liot Hill recounted the stories she’d heard while touring New Hampshire’s men’s…

1 minute ago

NH Senate kills attempt to repeal refugee resettlement program

The New Hampshire Senate killed legislation that would’ve ended the state’s participation in the federal…

2 minutes ago

Lampposts installed near Warner Town Hall to address safety concerns

The first phase of a lighting project around Warner Town Hall was completed Thursday to…

2 minutes ago

This website uses cookies.