]> BookStack Code Mirror - bookstack/blobdiff - resources/js/components/shelf-sort.js
Opensearch: Fixed XML declaration when php short tags enabled
[bookstack] / resources / js / components / shelf-sort.js
index d10470bd79a4ea7e19774bcb5eedc3c6e533ffad..b56b01980a147cc17f9cda63bdff62b2ccdf47e4 100644 (file)
@@ -1,5 +1,6 @@
-import Sortable from "sortablejs";
-import {Component} from "./component";
+import Sortable from 'sortablejs';
+import {Component} from './component';
+import {buildListActions, sortActionClickListener} from '../services/dual-lists.ts';
 
 export class ShelfSort extends Component {
 
@@ -9,6 +10,9 @@ export class ShelfSort extends Component {
         this.shelfBookList = this.$refs.shelfBookList;
         this.allBookList = this.$refs.allBookList;
         this.bookSearchInput = this.$refs.bookSearch;
+        this.sortButtonContainer = this.$refs.sortButtonContainer;
+
+        this.lastSort = null;
 
         this.initSortable();
         this.setupListeners();
@@ -28,28 +32,30 @@ export class ShelfSort extends Component {
     }
 
     setupListeners() {
-        this.elem.addEventListener('click', event => {
-            const sortItem = event.target.closest('.scroll-box-item');
-            if (sortItem) {
-                event.preventDefault();
-                this.sortItemClick(sortItem);
-            }
-        });
+        const listActions = buildListActions(this.allBookList, this.shelfBookList);
+        const sortActionListener = sortActionClickListener(listActions, this.onChange.bind(this));
+        this.elem.addEventListener('click', sortActionListener);
 
-        this.bookSearchInput.addEventListener('input', event => {
+        this.bookSearchInput.addEventListener('input', () => {
             this.filterBooksByName(this.bookSearchInput.value);
         });
+
+        this.sortButtonContainer.addEventListener('click', event => {
+            const button = event.target.closest('button[data-sort]');
+            if (button) {
+                this.sortShelfBooks(button.dataset.sort);
+            }
+        });
     }
 
     /**
      * @param {String} filterVal
      */
     filterBooksByName(filterVal) {
-
         // Set height on first search, if not already set, to prevent the distraction
         // of the list height jumping around
         if (!this.allBookList.style.height) {
-            this.allBookList.style.height = this.allBookList.getBoundingClientRect().height + 'px';
+            this.allBookList.style.height = `${this.allBookList.getBoundingClientRect().height}px`;
         }
 
         const books = this.allBookList.children;
@@ -61,22 +67,32 @@ export class ShelfSort extends Component {
         }
     }
 
-    /**
-     * Called when a sort item is clicked.
-     * @param {Element} sortItem
-     */
-    sortItemClick(sortItem) {
-        const lists = this.elem.querySelectorAll('.scroll-box');
-        const newList = Array.from(lists).filter(list => sortItem.parentElement !== list);
-        if (newList.length > 0) {
-            newList[0].appendChild(sortItem);
-        }
-        this.onChange();
-    }
-
     onChange() {
         const shelfBookElems = Array.from(this.shelfBookList.querySelectorAll('[data-id]'));
         this.input.value = shelfBookElems.map(elem => elem.getAttribute('data-id')).join(',');
     }
 
-}
\ No newline at end of file
+    sortShelfBooks(sortProperty) {
+        const books = Array.from(this.shelfBookList.children);
+        const reverse = sortProperty === this.lastSort;
+
+        books.sort((bookA, bookB) => {
+            const aProp = bookA.dataset[sortProperty].toLowerCase();
+            const bProp = bookB.dataset[sortProperty].toLowerCase();
+
+            if (reverse) {
+                return bProp.localeCompare(aProp);
+            }
+
+            return aProp.localeCompare(bProp);
+        });
+
+        for (const book of books) {
+            this.shelfBookList.append(book);
+        }
+
+        this.lastSort = (this.lastSort === sortProperty) ? null : sortProperty;
+        this.onChange();
+    }
+
+}