add_module.js
1 year ago
checkbox_group.js
1 year ago
module.js
1 year ago
module_editor.js
1 year ago
module_list.js
1 year ago
module_picker.js
1 year ago
reorder_modules.js
1 year ago
module_list.js
131 lines
| 1 | import {Controller} from "@hotwired/stimulus" |
| 2 | import Sortable from 'sortablejs' |
| 3 | import {StickySidebar} from "../../modules/sticky-sidebar" |
| 4 | |
| 5 | export default class extends Controller { |
| 6 | static targets = ['list'] |
| 7 | |
| 8 | connect() { |
| 9 | const modulesSortable = new Sortable(this.listTarget, { |
| 10 | animation: 400, |
| 11 | ghostClass: 'iawp-sortable-ghost', |
| 12 | handle: '.draggable-module', // ANDREW: you could use .module and just toggle "disabled" on/off instead. I don't have access to modulesSortable in my JS file |
| 13 | delay: 2000, |
| 14 | delayOnTouchOnly: true, |
| 15 | onUpdate: (event) => { |
| 16 | this.unwrapSideBySideModules() |
| 17 | this.saveModuleOrder(modulesSortable, event) |
| 18 | }, |
| 19 | onStart: (event) => { |
| 20 | document.getElementById('module-list').classList.add('dragging-active') |
| 21 | |
| 22 | if(this.isFullWidthModule(event.item)) { |
| 23 | this.wrapSideBySideModules() |
| 24 | } |
| 25 | }, |
| 26 | onEnd: (event) => { |
| 27 | document.getElementById('module-list').classList.remove('dragging-active') |
| 28 | this.unwrapSideBySideModules() |
| 29 | } |
| 30 | }) |
| 31 | } |
| 32 | |
| 33 | wrapSideBySideModules() { |
| 34 | if (window.innerWidth < 900 |
| 35 | || (window.innerWidth >= 1000 && window.innerWidth < 1200 && !document.getElementById('iawp-layout').classList.contains('collapsed')) |
| 36 | ) { |
| 37 | return; |
| 38 | } |
| 39 | const modules = Array.from(this.listTarget.querySelectorAll('.iawp-module:not(.module-picker)')) |
| 40 | const pairsToWrap = [] |
| 41 | let columnsRemaining = 2 |
| 42 | |
| 43 | modules.forEach((current, index) => { |
| 44 | const next = current.nextElementSibling |
| 45 | const isLast = !next || next.matches('.iawp-module.module-picker') |
| 46 | |
| 47 | if (this.isFullWidthModule(current)) { |
| 48 | columnsRemaining = 2 // Next module will always be on the next row |
| 49 | return |
| 50 | } |
| 51 | |
| 52 | columnsRemaining--; |
| 53 | |
| 54 | if(columnsRemaining === 1 && !isLast && !this.isFullWidthModule(next)) { |
| 55 | pairsToWrap.push(current) |
| 56 | } |
| 57 | |
| 58 | if(columnsRemaining === 0) { |
| 59 | columnsRemaining = 2 |
| 60 | } |
| 61 | }) |
| 62 | |
| 63 | pairsToWrap.forEach(module => { |
| 64 | const nextSibling = module.nextElementSibling |
| 65 | |
| 66 | const wrapper = document.createElement('div') |
| 67 | wrapper.classList.add('iawp-module-reorder-wrapper') |
| 68 | |
| 69 | module.parentNode.insertBefore(wrapper, module) |
| 70 | wrapper.appendChild(module) |
| 71 | wrapper.appendChild(nextSibling) |
| 72 | }) |
| 73 | } |
| 74 | |
| 75 | unwrapSideBySideModules() { |
| 76 | const wrappers = this.listTarget.querySelectorAll('.iawp-module-reorder-wrapper') |
| 77 | |
| 78 | wrappers.forEach(wrapper => { |
| 79 | const parent = wrapper.parentNode |
| 80 | const fragment = document.createDocumentFragment() |
| 81 | |
| 82 | // Move children into a fragment to avoid reflow during insert |
| 83 | while (wrapper.firstChild) { |
| 84 | fragment.appendChild(wrapper.firstChild) |
| 85 | } |
| 86 | |
| 87 | parent.replaceChild(fragment, wrapper) |
| 88 | }) |
| 89 | } |
| 90 | |
| 91 | isFullWidthModule(element) { |
| 92 | return element.classList.contains('full-width') |
| 93 | } |
| 94 | |
| 95 | saveModuleOrder(sortable, event) { |
| 96 | const elements = Array.from(event.target.querySelectorAll('.iawp-module')) |
| 97 | const ids = elements.map((element) => { |
| 98 | return this.application.getControllerForElementAndIdentifier(element, 'module') |
| 99 | }).filter((controller) => { |
| 100 | return controller !== null |
| 101 | }).map((controller) => { |
| 102 | return controller.moduleIdValue |
| 103 | }) |
| 104 | |
| 105 | const data = { |
| 106 | ...iawpActions.reorder_modules, |
| 107 | module_ids: ids, |
| 108 | } |
| 109 | |
| 110 | jQuery.post(ajaxurl, data, (response) => { |
| 111 | // Do nothing |
| 112 | }).fail((error) => { |
| 113 | sortable.sort( |
| 114 | this.moveArrayItem(sortable.toArray(), event.newIndex, event.oldIndex) |
| 115 | ) |
| 116 | }) |
| 117 | } |
| 118 | |
| 119 | moveArrayItem(array, fromIndex, toIndex) { |
| 120 | const newArray = [...array] |
| 121 | |
| 122 | if (fromIndex === toIndex) { |
| 123 | return newArray |
| 124 | } |
| 125 | |
| 126 | const itemToMove = newArray.splice(fromIndex, 1)[0] |
| 127 | newArray.splice(toIndex, 0, itemToMove) |
| 128 | |
| 129 | return newArray |
| 130 | } |
| 131 | } |