Skip to content

Commit 8e667f7

Browse files
committed
Rewrite the translator filter module to plain ES6
1 parent 1990289 commit 8e667f7

File tree

10 files changed

+227
-28
lines changed

10 files changed

+227
-28
lines changed

amd/build/filter.min.js

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

amd/build/filter.min.js.map

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

amd/src/filter.js

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
// This file is part of Moodle - https://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 <https://www.gnu.org/licenses/>.
15+
16+
/**
17+
* JS module for the AMOS translator filter.
18+
*
19+
* @module local_amos/filter
20+
* @package local_amos
21+
* @copyright 2020 David Mudrák <[email protected]>
22+
* @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23+
*/
24+
25+
import {debounce} from 'core/utils';
26+
27+
const SELECTORS = {
28+
ROOT: {
29+
ID: 'amosfilter',
30+
REGION: 'amosfilter'
31+
},
32+
FCMP: {
33+
ID: 'amosfilter_fcmp',
34+
REGION: 'amosfilter_fcmp'
35+
},
36+
FCMPITEM: {
37+
REGION: 'amosfilter_fcmp_item'
38+
},
39+
FCMPCOUNTER: {
40+
ID: 'amosfilter_fcmp_counter'
41+
},
42+
FCMPSEARCH: {
43+
ID: 'amosfilter_fcmp_search'
44+
}
45+
};
46+
47+
/**
48+
* Initialise the module and register events handlers.
49+
*
50+
* @function init
51+
*/
52+
export const init = () => {
53+
registerEventListeners();
54+
updateCounterOfSelectedComponents();
55+
};
56+
57+
/**
58+
* @function registerEventListeners
59+
* @param {Element} root
60+
*/
61+
const registerEventListeners = () => {
62+
let root = document.getElementById(SELECTORS.ROOT.ID);
63+
let fcmp = document.getElementById(SELECTORS.FCMP.ID);
64+
let componentSearch = document.getElementById(SELECTORS.FCMPSEARCH.ID);
65+
66+
// Click event delegation.
67+
root.addEventListener('click', e => {
68+
if (!e.target.hasAttribute('data-action')) {
69+
return;
70+
}
71+
72+
let action = e.target.getAttribute('data-action');
73+
let region = e.target.closest('[data-region]').getAttribute('data-region');
74+
75+
if (region == SELECTORS.FCMP.REGION) {
76+
handleComponentSelectorAction(e, fcmp, action);
77+
}
78+
});
79+
80+
// Input change event delegation.
81+
root.addEventListener('change', e => {
82+
if (e.target.getAttribute('id').startsWith('amosfilter_fcmp_')) {
83+
updateCounterOfSelectedComponents();
84+
}
85+
});
86+
87+
// Prevent form submission on pressing Enter in the component search input.
88+
componentSearch.addEventListener('keypress', e => {
89+
if (e.keyCode == 13) {
90+
e.preventDefault();
91+
e.stopPropagation();
92+
}
93+
});
94+
95+
// Handle component search.
96+
componentSearch.addEventListener('input', debounce(e => {
97+
handleComponentSearch(e, componentSearch, fcmp);
98+
}, 200));
99+
};
100+
101+
/**
102+
* @function handleComponentSelectorAction
103+
* @param {Event} e
104+
* @param {Element} fcmp
105+
* @param {string} action
106+
*/
107+
const handleComponentSelectorAction = (e, fcmp, action) => {
108+
109+
let selectorComponentItem = `:scope [data-region="${SELECTORS.FCMPITEM.REGION}"]:not(.hidden) input[name="fcmp[]"]`;
110+
111+
if (action == 'selectstandard') {
112+
e.preventDefault();
113+
let selectorByType = type => `${selectorComponentItem}[data-component-type="${type}"]`;
114+
fcmp.querySelectorAll(`${selectorByType('core')}, ${selectorByType('standard')}`).forEach(item => {
115+
item.checked = true;
116+
});
117+
}
118+
119+
if (action == 'selectapp') {
120+
e.preventDefault();
121+
fcmp.querySelectorAll(`${selectorComponentItem}[data-component-app]`).forEach(item => {
122+
item.checked = true;
123+
});
124+
}
125+
126+
if (action == 'selectall') {
127+
e.preventDefault();
128+
fcmp.querySelectorAll(`${selectorComponentItem}`).forEach(item => {
129+
item.checked = true;
130+
});
131+
}
132+
133+
if (action == 'selectnone') {
134+
e.preventDefault();
135+
fcmp.querySelectorAll(`${selectorComponentItem}`).forEach(item => {
136+
item.checked = false;
137+
});
138+
}
139+
140+
updateCounterOfSelectedComponents();
141+
};
142+
143+
/**
144+
* @function handleComponentSearch
145+
* @param {Event} e
146+
* @param {Element} inputField
147+
* @param {Element} fcmp
148+
*/
149+
const handleComponentSearch = (e, inputField, fcmp) => {
150+
let needle = inputField.value.toString().replace(/^ +| +$/, '');
151+
152+
fcmp.querySelectorAll(':scope label[for^="amosfilter_fcmp_f_"]').forEach(item => {
153+
let row = item.closest('[data-region="amosfilter_fcmp_item"]');
154+
if (needle == '' || item.innerText.toString().indexOf(needle) !== -1) {
155+
row.classList.remove('hidden');
156+
} else {
157+
row.classList.add('hidden');
158+
}
159+
});
160+
};
161+
162+
/**
163+
* @function updateCounterOfSelectedComponents
164+
*/
165+
const updateCounterOfSelectedComponents = () => {
166+
let fcmp = document.getElementById(SELECTORS.FCMP.ID);
167+
let counter = document.getElementById(SELECTORS.FCMPCOUNTER.ID);
168+
let count = fcmp.querySelectorAll(':scope input[name="fcmp[]"]:checked').length;
169+
170+
if (count == 0) {
171+
counter.classList.add('badge-danger');
172+
} else {
173+
counter.classList.remove('badge-danger');
174+
}
175+
176+
counter.textContent = count;
177+
};

classes/output/filter.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -549,7 +549,7 @@ protected function export_for_template_fcmp(\renderer_base $outpup, object $filt
549549
'standard' => [],
550550
'contrib' => [],
551551
],
552-
'someselected' => false,
552+
'numselected' => 0,
553553
];
554554

555555
$options = [
@@ -593,13 +593,14 @@ protected function export_for_template_fcmp(\renderer_base $outpup, object $filt
593593
'name' => $componentname,
594594
'label' => $componentlabel,
595595
'selected' => false,
596-
'type' => get_string('type' . $type . 'badge', 'local_amos'),
596+
'type' => $type,
597+
'typename' => get_string('type' . $type . 'badge', 'local_amos'),
597598
'since' => $sinceversion[$componentname],
598599
'app' => isset($mobileapp[$componentname]),
599600
];
600601

601602
if (in_array($componentname, $filterdata->component)) {
602-
$fcmp['someselected'] = true;
603+
$fcmp['numselected']++;
603604
$option['selected'] = true;
604605
}
605606

lang/en/local_amos.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@
5050
$string['committablenone'] = 'no languages allowed - please contact AMOS manager';
5151
$string['componentsall'] = 'All';
5252
$string['componentsapp'] = 'Moodle App';
53-
$string['componentsenlarge'] = 'Enlarge';
5453
$string['componentsnone'] = 'None';
5554
$string['componentsstandard'] = 'Standard';
5655
$string['confirmaction'] = 'This can not be undone. Are you sure?';

scss/filter.scss

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@
77
margin-bottom: 0.25rem;
88
}
99

10+
// Make component and language selectors resizable vertically.
11+
#amosfilter_fcmp,
12+
#amosfilter_flng {
13+
resize: vertical;
14+
}
15+
1016
// Once a component is selected, highlight it in bold.
1117
#amosfilter_fcmp input[type=checkbox]:checked + label {
1218
font-weight: bold;

0 commit comments

Comments
 (0)