1import { Controller } from '@hotwired/stimulus' 2import Sortable from 'sortablejs' 3 4export default class extends Controller { 5 static get targets () { 6 return ['templateBlock', 'block', 'blocks', 'templateEmpty', 'button', 'buttons'] 7 } 8 9 connect () { 10 Sortable.create(this.blocksTarget, { 11 onEnd: () => { 12 this.reorderPositions() 13 } 14 }) 15 16 this.toggleEmpty() 17 } 18 19 toggleEmpty () { 20 if (this.blockCount() > 0) { 21 const empty = this.blocksTarget.querySelector('#blocks-empty') 22 if (empty) { 23 empty.remove() 24 } 25 } else { 26 const empty = this.templateEmptyTarget.innerHTML 27 this.blocksTarget.insertAdjacentHTML('beforeend', empty) 28 } 29 } 30 31 add (event) { 32 event.preventDefault() 33 const blockType = event.target.dataset.type 34 let html = this.templateBlockTargets.filter(blockTarget => blockTarget.id === blockType)[0].innerHTML 35 36 html = this.setPosition(html) 37 38 const element = this.blocksTarget.querySelector(`li[data-position='${event.target.dataset.position}']`) 39 40 if (element) { 41 element.insertAdjacentHTML('afterend', html) 42 } else { 43 this.blocksTarget.insertAdjacentHTML('afterbegin', html) 44 } 45 46 this.reorderPositions() 47 this.toggleEmpty() 48 } 49 50 remove (event) { 51 event.preventDefault() 52 53 const block = event.target.closest('.list-group-item') 54 const destroyInput = block.querySelector("input[name*='_destroy']") 55 56 if (destroyInput) { 57 destroyInput.value = 1 58 block.style.display = 'none' 59 } else { 60 block.remove() 61 } 62 63 this.reorderPositions() 64 this.toggleEmpty() 65 } 66 67 setPosition (html) { 68 const position = this.retrieveLastPosition() + 1 69 70 return html.replace(/99999/g, position) 71 } 72 73 retrieveLastPosition () { 74 const blocks = Array.from(this.blockTargets) 75 if (blocks.length < 1) { 76 return 0 77 } 78 79 const lastBlock = blocks.slice(-1)[0] 80 return parseInt(lastBlock.querySelector("[name*='position']").value) 81 } 82 83 reorderPositions () { 84 for (const [index, block] of this.blockTargets.entries()) { 85 this.changePositionInfo(block, index) 86 } 87 } 88 89 changePositionInfo (block, index) { 90 block.setAttribute('data-position', index) 91 block.querySelector("input[name*='position']").value = index 92 } 93 94 blockCount () { 95 return this.blockTargets.length 96 } 97}
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.