PageSourceSearch

https://littlebirdelectronics.com.au/assets/controllers/sortable_controller-51127e97.js

js littlebirdelectronics.com.au collected 2026-09-25 14:11:52 UTC 2,082 bytes, 57 lines download raw bytes

1import { Controller } from "@hotwired/stimulus"
2import { Turbo } from "@hotwired/turbo-rails"
3import Sortable from "sortablejs"
4
5// data-controller="sortable"
6// data-sortable-url-value="/path/to/reorder"  (optional; PATCH with ids[])
7// data-sortable-handle-value=".drag-handle"   (CSS selector for drag handle)
8// data-sortable-item-selector-value="[data-block-id]" (optional; how to find items)
9// data-sortable-id-attribute-value="data-block-id"    (attr to read for PATCH ids)
10// data-sortable-turbo-stream-value="true"     (optional; render the response as
11//   a Turbo Stream — for endpoints that have to hand back a fresh list, e.g.
12//   because saving the new order changed the ids the next PATCH would send)
13export default class extends Controller {
14  static values = {
15    url: String,
16    handle: { type: String, default: "" },
17    itemSelector: { type: String, default: "[data-block-id],[data-row-id]" },
18    idAttribute: { type: String, default: "data-block-id" },
19    turboStream: { type: Boolean, default: false }
20  }
21
22  connect() {
23    this.sortable = Sortable.create(this.element, {
24      handle: this.handleValue || undefined,
25      animation: 150,
26      ghostClass: "opacity-40",
27      onEnd: this.onEnd.bind(this)
28    })
29  }
30
31  disconnect() {
32    if (this.sortable) this.sortable.destroy()
33  }
34
35  async onEnd() {
36    if (!this.urlValue) return
37    const ids = Array.from(this.element.querySelectorAll(this.itemSelectorValue))
38      .map(el => el.getAttribute(this.idAttributeValue))
39      .filter(Boolean)
40    const body = new FormData()
41    ids.forEach(id => body.append("ids[]", id))
42    const accept = this.turboStreamValue ? "text/vnd.turbo-stream.html" : "application/json"
43    const response = await fetch(this.urlValue, {
44      method: "PATCH",
45      headers: { "X-CSRF-Token": this.csrf(), Accept: accept },
46      body
47    })
48    if (this.turboStreamValue && response.ok) {
49      Turbo.renderStreamMessage(await response.text())
50    }
51  }
52
53  csrf() {
54    const m = document.querySelector('meta[name="csrf-token"]')
55    return m ? m.content : ""
56  }
57}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.