JSFiddle - React, Tailwind, and code Playground

Div Selector and Sorter

by skibulk

HTML

<script src="https://cdn.jsdelivr.net/npm/[email protected]/jquery.mousewheel.min.js"></script>
<div id="scroll">
  <div id="set1" class="set">
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
  </div>
  <div id="set2" class="set">
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
  </div>
</div>

CSS

* {
  box-sizing: border-box;
  margin: 0;
  border: 0;
}

body {
  font-family: arial, sans-serif;
}

.set {
  white-space: nowrap;
  font-size: 0;
  counter-reset: boxCount;
  user-select: none;
}

.box {
  position: relative;
  display: inline-block;
  width: 200px;
  height: 200px;
  margin: 4px;
  border-top: 8px solid white;
  background: #f5f5f5;
}

#set1 .box::before {
  position: absolute;
  z-index: 1;
  top: 170px;
  right: 0;
  left: 0;
  counter-increment: boxCount;
  content: counter(boxCount);
  text-align: center;
  font-size: 50px;
}

.selected {
  border-top: 8px solid lightblue;
}

.anchor::after {
  position: absolute;
  top: 0;
  left: 0;
  border: 15px solid transparent;
  border-top-color: lightblue;
  border-left-color: lightblue;
  content: "";
}

/*
#scroll {
  overflow-x: scroll;
}
*/

JavaScript

/*
1) Swipe a tile up to select it or down to deselect it.
2) Click a tile to set a range selection endpoint. Click it again to cancel.
3) While an endpoint is set, swipe any tile up/down to select/deselect that tile and all tiles up to and including the endpoint. Then the endpoint is unset.

To-Do:
Horizontal drag-scroll
Move selection before/after

Single Click = Toggle Selection
Double Click = Range Endpoint
Drag and Drop
*/

(function($) {
  "use strict";

  function setupSet(set) {

    var mouseStart;
    var mouseEnd;
    var anchor;

    $(set).on("mousedown", ".box", function(event) {
      mouseStart = event;
    }).on("mouseup", ".box", function(event) {
      mouseEnd = event;
    });

    $(window).mouseup(function(event) {
      if (!mouseStart) {
        return;
      }

      if (event.pageY < mouseStart.pageY - 10) {
        // swipe up
        console.log("Swipe Up");
        getRange(mouseStart.target).addClass("selected");
        if (anchor) {
        	anchor.classList.remove("anchor");
          anchor = null;
        }
      } else if (event.pageY > mouseStart.pageY + 10) {
        // swipe down
        console.log("Swipe Down");
        getRange(mouseStart.target).removeClass("selected");
        if (anchor) {
	        anchor.classList.remove("anchor");
          anchor = null;
        }
      } else if (mouseEnd && mouseStart.target == mouseEnd.target) {
        // click
        console.log("Click");
        if (anchor) {
          anchor.classList.remove("anchor");
        }
        if (mouseStart.target != anchor) {
          mouseStart.target.classList.add("anchor");
          anchor = mouseStart.target;
        } else {
          anchor = null;
        }
      }

      mouseStart = mouseEnd = null;
    });

    function getRange(toBox) {
      if (anchor && toBox != anchor) {
        var fromIndex = $(toBox).index();
        var toIndex = $(anchor).index();
        console.log(fromIndex, toIndex);

       ...