bfa61c8a0a3a067b4e9b6dc6ac3bb45c7c08458f
[moodle.git] / contentbank / amd / src / sort.js
1 // This file is part of Moodle - http://moodle.org/
2 //
3 // Moodle is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, either version 3 of the License, or
6 // (at your option) any later version.
7 //
8 // Moodle is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 // GNU General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
16 /**
17  * Content bank UI actions.
18  *
19  * @module     core_contentbank/sort
20  * @package    core_contentbank
21  * @copyright  2020 Bas Brands <bas@moodle.com>
22  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23  */
25 import selectors from 'core_contentbank/selectors';
26 import {get_string as getString} from 'core/str';
27 import Prefetch from 'core/prefetch';
29 /**
30  * Set up the contentbank views.
31  *
32  * @method init
33  */
34 export const init = () => {
35     const contentBank = document.querySelector(selectors.regions.contentbank);
36     Prefetch.prefetchStrings('contentbank', ['sortbyx', 'sortbyxreverse', 'contentname',
37         'lastmodified', 'size', 'type']);
38     registerListenerEvents(contentBank);
39 };
41 /**
42  * Register contentbank related event listeners.
43  *
44  * @method registerListenerEvents
45  * @param {HTMLElement} contentBank The DOM node of the content bank
46  */
47 const registerListenerEvents = (contentBank) => {
49     // The search.
50     const fileArea = document.querySelector(selectors.regions.filearea);
51     const shownItems = fileArea.querySelectorAll(selectors.elements.listitem);
53     // The view buttons.
54     const viewGrid = contentBank.querySelector(selectors.actions.viewgrid);
55     const viewList = contentBank.querySelector(selectors.actions.viewlist);
57     viewGrid.addEventListener('click', () => {
58         contentBank.classList.remove('view-list');
59         contentBank.classList.add('view-grid');
60         viewGrid.classList.add('active');
61         viewList.classList.remove('active');
62     });
64     viewList.addEventListener('click', () => {
65         contentBank.classList.remove('view-grid');
66         contentBank.classList.add('view-list');
67         viewList.classList.add('active');
68         viewGrid.classList.remove('active');
69     });
71     // Sort by file name alphabetical
72     const sortByName = contentBank.querySelector(selectors.actions.sortname);
73     sortByName.addEventListener('click', () => {
74         const ascending = updateSortButtons(contentBank, sortByName);
75         updateSortOrder(fileArea, shownItems, 'data-file', ascending);
76     });
78     // Sort by date.
79     const sortByDate = contentBank.querySelector(selectors.actions.sortdate);
80     sortByDate.addEventListener('click', () => {
81         const ascending = updateSortButtons(contentBank, sortByDate);
82         updateSortOrder(fileArea, shownItems, 'data-timemodified', ascending);
83     });
85     // Sort by size.
86     const sortBySize = contentBank.querySelector(selectors.actions.sortsize);
87     sortBySize.addEventListener('click', () => {
88         const ascending = updateSortButtons(contentBank, sortBySize);
89         updateSortOrder(fileArea, shownItems, 'data-bytes', ascending);
90     });
92     // Sort by type
93     const sortByType = contentBank.querySelector(selectors.actions.sorttype);
94     sortByType.addEventListener('click', () => {
95         const ascending = updateSortButtons(contentBank, sortByType);
96         updateSortOrder(fileArea, shownItems, 'data-type', ascending);
97     });
98 };
100 /**
101  * Update the sort button view.
102  *
103  * @method updateSortButtons
104  * @param {HTMLElement} contentBank The DOM node of the contentbank button
105  * @param {HTMLElement} sortButton The DOM node of the sort button
106  * @return {Bool} sort ascending
107  */
108 const updateSortButtons = (contentBank, sortButton) => {
109     const sortButtons = contentBank.querySelectorAll(selectors.elements.sortbutton);
111     sortButtons.forEach((button) => {
112         if (button !== sortButton) {
113             button.classList.remove('dir-asc');
114             button.classList.remove('dir-desc');
115             button.classList.add('dir-none');
117             updateButtonTitle(button, false);
118         }
119     });
121     let ascending = true;
123     if (sortButton.classList.contains('dir-none')) {
124         sortButton.classList.remove('dir-none');
125         sortButton.classList.add('dir-asc');
126     } else if (sortButton.classList.contains('dir-asc')) {
127         sortButton.classList.remove('dir-asc');
128         sortButton.classList.add('dir-desc');
129         ascending = false;
130     } else if (sortButton.classList.contains('dir-desc')) {
131         sortButton.classList.remove('dir-desc');
132         sortButton.classList.add('dir-asc');
133     }
135     updateButtonTitle(sortButton, ascending);
137     return ascending;
138 };
140 /**
141  * Update the button title.
142  *
143  * @method updateButtonTitle
144  * @param {HTMLElement} button Button to update
145  * @param {Bool} ascending Sort direction
146  * @return {Promise} string promise
147  */
148 const updateButtonTitle = (button, ascending) => {
150     const sortString = (ascending ? 'sortbyxreverse' : 'sortbyx');
152     return getString(button.dataset.string, 'contentbank')
153     .then(columnName => {
154         return getString(sortString, 'core', columnName);
155     })
156     .then(sortByString => {
157         button.setAttribute('title', sortByString);
158         return sortByString;
159     })
160     .catch();
161 };
163 /**
164  * Update the sort order of the itemlist and update the DOM
165  *
166  * @method updateSortOrder
167  * @param {HTMLElement} fileArea the Dom container for the itemlist
168  * @param {Array} itemList Nodelist of Dom elements
169  * @param {String} attribute, the attribut to sort on
170  * @param {Bool} ascending, Sort Ascending
171  */
172 const updateSortOrder = (fileArea, itemList, attribute, ascending) => {
173     const sortList = [].slice.call(itemList).sort(function(a, b) {
175         let aa = a.getAttribute(attribute);
176         let bb = b.getAttribute(attribute);
177         if (!isNaN(aa)) {
178            aa = parseInt(aa);
179            bb = parseInt(bb);
180         }
182         if (ascending) {
183             return aa > bb ? 1 : -1;
184         } else {
185             return aa < bb ? 1 : -1;
186         }
187     });
188     sortList.forEach(listItem => fileArea.appendChild(listItem));
189 };