Skip to content

Commit 86bcf83

Browse files
committed
V-1 bug to correct
1 parent ecac390 commit 86bcf83

File tree

3 files changed

+175
-167
lines changed

3 files changed

+175
-167
lines changed

public/js/dashboard/TagHandler.js

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
/**
2+
* @param {Object} options
3+
* @param {Element} options.textarea
4+
* @param {Array} options.dataset
5+
* @param {Element} options.elementWrapper
6+
* @param {"channel"|"user"} options.type
7+
*/
8+
class TagHandler {
9+
/**
10+
* @param {Object} options
11+
* @param {Element} options.textarea
12+
* @param {Array} options.dataset
13+
* @param {Element} options.elementWrapper
14+
* @param {"channel"|"user"} options.type
15+
*/
16+
constructor(options) {
17+
this.type = options.type;
18+
this.wrapper = options.elementWrapper;
19+
this.data = options.dataset;
20+
this.textarea = options.textarea;
21+
22+
this.textarea.addEventListener("input", () => this.onInputTextarea(this.textarea.value));
23+
this.textarea.addEventListener("keydown", event => this.onKeyPressedTextarea(event));
24+
this.wrapper.querySelectorAll("div").forEach(
25+
el => el.addEventListener("click", () => this.onElClick(el)));
26+
}
27+
28+
/**
29+
* Method triggered when the user input something in the textarea
30+
* if a @ or a # is written the tag window will be shown
31+
* @param {string} data content of the textarea
32+
*/
33+
onInputTextarea(data) {
34+
const lastChar = data.charAt(this.textarea.value.length-1);
35+
if ((this.type == "user" && lastChar == "@") || (this.type == "channel" && lastChar == "#")) {
36+
this.wrapper.classList.remove("scale-out");
37+
this.wrapper.classList.add("scale-in");
38+
this.clear();
39+
} else if ((lastChar == " " || lastChar == "") && this.wrapper.classList.contains("scale-in")) {
40+
this.wrapper.classList.remove("scale-in");
41+
this.wrapper.classList.add("scale-out");
42+
this.clear();
43+
if (this.wrapper.querySelector(".selected"))
44+
this.wrapper.querySelector(".selected").classList.remove("selected");
45+
} else if (this.wrapper.classList.contains("scale-in")) {
46+
this.filter(data);
47+
if (this.wrapper.querySelector(".selected"))
48+
this.wrapper.querySelector(".selected").classList.remove("selected");
49+
}
50+
}
51+
52+
onKeyPressedTextarea(event) {
53+
if (!this.wrapper.classList.contains("scale-in")) return; //Si la fenêtre est pas affiché on fait rien
54+
//Sinon on fait un déplacement gauche/droite/haut/bas des flêches pour sélectionner les tags
55+
if (event.keyCode == 40 || event.keyCode == 39) {
56+
event.preventDefault();
57+
this.moveTagRight(this.wrapper);
58+
} else if (event.keyCode == 38 || event.keyCode == 37) {
59+
event.preventDefault();
60+
this.moveTagLeft(this.wrapper);
61+
} else if (event.keyCode == 13) {
62+
event.preventDefault();
63+
this.wrapper.querySelector(".selected").click();
64+
}
65+
}
66+
67+
/**
68+
* If a tag element is clicked
69+
* @param {Element} element element clicked
70+
*/
71+
onElClick(element) {
72+
const text = element.innerText;
73+
this.textarea.value = this.textarea.value.substring(0, this.textarea.value.lastIndexOf(this.type == "user" ? "@" : "#")) + text;
74+
M.textareaAutoResize(this.textarea);
75+
this.wrapper.classList.remove("scale-in");
76+
this.wrapper.classList.add("scale-out");
77+
this.wrapper.querySelector(".selected").classList.remove("selected");
78+
}
79+
/**
80+
*
81+
* Method to filter the tag list
82+
* @param {string} textContent
83+
*/
84+
filter(textContent) {
85+
const query = textContent.substring(textContent.lastIndexOf(this.type == "user" ? "@" : "#")+1, textContent.length);
86+
console.log(this.data, query);
87+
const elsToHide = this.data.filter(el => {
88+
const name = el.name || el.username || el.nickname;
89+
return !name.toLowerCase().includes(query.toLowerCase());
90+
});
91+
const elsToShow = this.data.filter(el => {
92+
const name = el.name || el.username || el.nickname;
93+
return name.toLowerCase().includes(query.toLowerCase());
94+
});
95+
elsToHide.forEach(el => this.wrapper.querySelector('div[data-id="'+el.id+'"]').classList.add("hidden"));
96+
elsToShow.forEach(el => this.wrapper.querySelector('div[data-id="'+el.id+'"]').classList.remove("hidden"));
97+
}
98+
99+
clear() {
100+
this.wrapper.querySelectorAll(".hidden").forEach(el => el.classList.remove("hidden"));
101+
}
102+
103+
moveTagRight() {
104+
const selected = this.wrapper.querySelector(".selected");
105+
if (selected) {
106+
//If there is a element after
107+
if (selected.nextElementSibling) {
108+
//We iterate the tag list and we find the next element shown to add the selected class
109+
for (let i = Array.prototype.indexOf.call(this.wrapper.children, selected)+1; i < this.wrapper.children.length; i++) {
110+
const el = this.wrapper.children[i];
111+
if (!el.classList.contains("hidden")) {
112+
el.classList.add("selected");
113+
selected.classList.remove("selected");
114+
break;
115+
}
116+
}
117+
} else { //If there is no element after we select the first one
118+
for (let el of this.wrapper.children) {
119+
if (!el.classList.contains("hidden")) {
120+
selected.classList.remove("selected");
121+
el.classList.add("selected");
122+
break;
123+
}
124+
}
125+
}
126+
} else {
127+
//if there is nothing selected we select the first one
128+
for (let el of this.wrapper.children) {
129+
if (!el.classList.contains("hidden")) {
130+
el.classList.add("selected");
131+
break;
132+
}
133+
}
134+
}
135+
}
136+
moveTagLeft() {
137+
const selected = this.wrapper.querySelector(".selected");
138+
if (selected) {
139+
if (selected.previousElementSibling) {
140+
for (let i = Array.prototype.indexOf.call(this.wrapper.children, selected)-1; i >= 0; i--) {
141+
const el = this.wrapper.children[i];
142+
if (!el.classList.contains("hidden")) {
143+
el.classList.add("selected");
144+
selected.classList.remove("selected");
145+
break;
146+
}
147+
}
148+
}
149+
} else {
150+
for (let i = this.wrapper.children.length-1; i >= 0; i--) {
151+
const el = this.wrapper.children[i];
152+
if (!el.classList.contains("hidden")) {
153+
el.classList.add("selected");
154+
break;
155+
}
156+
}
157+
}
158+
}
159+
}
160+
export default TagHandler;
Lines changed: 14 additions & 166 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import TagHandler from "./TagHandler.js";
12
class VueDashboard {
23
constructor() {
34
this.months = [
@@ -66,6 +67,18 @@ class VueDashboard {
6667
yearRange: 1,
6768
defaultDate: new Date(),
6869
});
70+
document.querySelectorAll(".channels_wrapper").forEach(el => new TagHandler({
71+
elementWrapper: el,
72+
dataset: document.channels,
73+
textarea: el.parentElement.querySelector("textarea"),
74+
type: "channel"
75+
}));
76+
document.querySelectorAll(".users_wrapper").forEach(el => new TagHandler({
77+
elementWrapper: el,
78+
dataset: document.users,
79+
textarea: el.parentElement.querySelector("textarea"),
80+
type: "user"
81+
}));
6982
M.FormSelect.init(document.querySelectorAll("select"));
7083
this.addEventListener();
7184
}
@@ -75,13 +88,7 @@ class VueDashboard {
7588
document.querySelector(".schedule-add-btn").addEventListener("click", () => this.addCronModal.open());
7689
document.querySelector(".timer-add-btn").addEventListener("click", () => this.addTimerModal.open());
7790
document.querySelector(".guild-timezone").addEventListener("click", () => this.timezoneModal.open());
78-
document.querySelectorAll("textarea").forEach(el => {
79-
el.addEventListener("input", () => this.onInputTextarea(el));
80-
el.addEventListener("keydown", (event) => this.onKeyPressedTextarea(event, el));
81-
});
8291
document.querySelector(".autocomplete").addEventListener("change", (e) => this.onInputAutoComplete(e));
83-
document.querySelectorAll(".user_el").forEach(el => el.addEventListener("click", () => this.onUserClick(el)));
84-
document.querySelectorAll(".channel_el").forEach(el => el.addEventListener("click", () => this.onChannelClick(el)));
8592
document.querySelector("#setTimezone .modal-confirm").addEventListener("click", () => this.onConfirmSetTimer());
8693
document.querySelector("#options_modal .delete").addEventListener("click", () => this.onRemoveEl());
8794
document.querySelector("#options_modal .edit").addEventListener("click", () => this.onOpenEdit());
@@ -97,37 +104,6 @@ class VueDashboard {
97104
});
98105
this.removeCron_modalConfirm.addEventListener("click", () => this.onConfirmRemoveCron());
99106
}
100-
101-
onInputTextarea(element) {
102-
const data = element.value;
103-
const channels_wrapper = element.parentNode.querySelector(".channels_wrapper");
104-
const users_wrapper = element.parentNode.querySelector(".users_wrapper");
105-
if (data.charAt(data.length-1) == "@") {
106-
users_wrapper.classList.remove("scale-out");
107-
users_wrapper.classList.add("scale-in");
108-
this.sortUsers(element, true);
109-
} else if (data.charAt(data.length-1) == "#") {
110-
channels_wrapper.classList.remove("scale-out");
111-
channels_wrapper.classList.add("scale-in");
112-
this.sortUsers(element, true);
113-
} else if ((data.charAt(data.length-1) == " " || data == "") && channels_wrapper.classList.contains("scale-in")) {
114-
channels_wrapper.classList.remove("scale-in");
115-
channels_wrapper.classList.add("scale-out");
116-
this.sortUsers(element, true);
117-
} else if ((data.charAt(data.length-1) == " " || data == "") && users_wrapper.classList.contains("scale-in")) {
118-
users_wrapper.classList.remove("scale-in");
119-
users_wrapper.classList.add("scale-out");
120-
this.sortUsers(element, true);
121-
if (users_wrapper.querySelector(".selected"))
122-
users_wrapper.querySelector(".selected").classList.remove("selected");
123-
} else if (channels_wrapper.classList.contains("scale-in")) {
124-
this.sortChannels(element);
125-
} else if (users_wrapper.classList.contains("scale-in")) {
126-
this.sortUsers(element);
127-
if (channels_wrapper.querySelector(".selected"))
128-
channels_wrapper.querySelector(".selected").classList.remove("selected");
129-
}
130-
}
131107
onInputAutoComplete(e) {
132108
//Bug patched for selecting :
133109
if (e.target.value in this.timezoneSelector.options.data || " " + e.target.value in this.timezoneSelector.options.data)
@@ -136,134 +112,6 @@ class VueDashboard {
136112
this.addTimezone.classList.add("disabled");
137113
}
138114

139-
onUserClick(element) {
140-
const user = element.innerText;
141-
const textarea = element.parentNode.parentNode.querySelector("textarea");
142-
const users_wrapper = element.parentNode.parentNode.querySelector(".users_wrapper");
143-
textarea.value = textarea.value.substring(0, textarea.value.lastIndexOf("@")) + user;
144-
for (let el of document.users) {
145-
const nickname = el.nickname || el.username;
146-
if ("@"+nickname == user) {
147-
document.users.push(el);
148-
break;
149-
}
150-
}
151-
M.textareaAutoResize(textarea);
152-
users_wrapper.classList.remove("scale-in");
153-
users_wrapper.classList.add("scale-out");
154-
if (users_wrapper.querySelector(".selected"))
155-
users_wrapper.querySelector(".selected").classList.remove("selected");
156-
}
157-
onChannelClick(element) {
158-
const channel = element.innerText;
159-
const textarea = element.parentNode.parentNode.querySelector("textarea");
160-
const channels_wrapper = element.parentNode.parentNode.querySelector(".channels_wrapper");
161-
textarea.value = textarea.value.substring(0, textarea.value.lastIndexOf("#")) + channel;
162-
M.textareaAutoResize(textarea);
163-
channels_wrapper.classList.remove("scale-in");
164-
channels_wrapper.classList.add("scale-out");
165-
if (channels_wrapper.querySelector(".selected"))
166-
channels_wrapper.querySelector(".selected").classList.remove("selected");
167-
}
168-
169-
sortChannels(element, clear) {
170-
const data = element.value;
171-
const wrapper = element.parentNode.querySelector(".channels_wrapper");
172-
const keyword = data.substring(data.lastIndexOf("#")+1, data.length);
173-
if (!clear) {
174-
const elsToHide = document.channels.filter(el => !el.name.toLowerCase().includes(keyword.toLowerCase()));
175-
const elsToShow = document.channels.filter(el => el.name.toLowerCase().includes(keyword.toLowerCase()));
176-
elsToHide.forEach(el => wrapper.querySelector('div[data-id="'+el.id+'"]').classList.add("hidden"));
177-
elsToShow.forEach(el => wrapper.querySelector('div[data-id="'+el.id+'"]').classList.remove("hidden"));
178-
} else {
179-
wrapper.querySelectorAll(".hidden").forEach(el => el.classList.remove("hidden"));
180-
}
181-
}
182-
sortUsers(element, clear) {
183-
const data = element.value;
184-
const wrapper = element.parentNode.querySelector(".users_wrapper");
185-
const keyword = data.substring(data.lastIndexOf("@")+1, data.length);
186-
if (!clear) {
187-
const elsToHide = document.users.filter(el => el.nickname ? !el.nickname.toLowerCase().includes(keyword.toLowerCase()) : !el.username.toLowerCase().includes(keyword.toLowerCase()));
188-
const elsToShow = document.users.filter(el => el.nickname ? el.nickname.toLowerCase().includes(keyword.toLowerCase()) : el.username.toLowerCase().includes(keyword.toLowerCase()));
189-
elsToHide.forEach(el => wrapper.querySelector('div[data-id="'+el.id+'"]').classList.add("hidden"));
190-
elsToShow.forEach(el => wrapper.querySelector('div[data-id="'+el.id+'"]').classList.remove("hidden"));
191-
} else {
192-
wrapper.querySelectorAll(".hidden").forEach(el => el.classList.remove("hidden"));
193-
}
194-
}
195-
196-
onKeyPressedTextarea(event, element) {
197-
const tag_wrapper = element.parentNode.querySelector(".scale-in");
198-
if (!tag_wrapper) return; //Si la fenêtre est pas affiché on fait rien
199-
//Sinon on fait un déplacement gauche/droite/haut/bas des flêches pour sélectionner les tags
200-
if (event.keyCode == 40 || event.keyCode == 39) {
201-
event.preventDefault();
202-
this.moveTagRight(tag_wrapper);
203-
} else if (event.keyCode == 38 || event.keyCode == 37) {
204-
event.preventDefault();
205-
this.moveTagLeft(tag_wrapper);
206-
} else if (event.keyCode == 13) {
207-
event.preventDefault();
208-
tag_wrapper.querySelector(".selected").click();
209-
}
210-
}
211-
212-
moveTagRight(tag_wrapper) {
213-
const selected = tag_wrapper.querySelector(".selected");
214-
if (selected) {
215-
if (selected.nextElementSibling) {
216-
for (let i = Array.prototype.indexOf.call(tag_wrapper.children, selected)+1; i < tag_wrapper.children.length; i++) {
217-
const el = tag_wrapper.children[i];
218-
if (!el.classList.contains("hidden")) {
219-
el.classList.add("selected");
220-
selected.classList.remove("selected");
221-
break;
222-
}
223-
}
224-
} else {
225-
for (let el of tag_wrapper.children) {
226-
if (!el.classList.contains("hidden")) {
227-
selected.classList.remove("selected");
228-
el.classList.add("selected");
229-
break;
230-
}
231-
}
232-
}
233-
} else {
234-
//Si jamais l'utilisateur n'a pas encore appuyé sur une flèche alors le premier élément sera celui sans hidden
235-
for (let el of tag_wrapper.children) {
236-
if (!el.classList.contains("hidden")) {
237-
el.classList.add("selected");
238-
break;
239-
}
240-
}
241-
}
242-
}
243-
moveTagLeft(tag_wrapper) {
244-
const selected = tag_wrapper.querySelector(".selected");
245-
if (selected) {
246-
if (selected.previousElementSibling) {
247-
for (let i = Array.prototype.indexOf.call(tag_wrapper.children, selected)-1; i >= 0; i--) {
248-
const el = tag_wrapper.children[i];
249-
if (!el.classList.contains("hidden")) {
250-
el.classList.add("selected");
251-
selected.classList.remove("selected");
252-
break;
253-
}
254-
}
255-
}
256-
} else {
257-
for (let i = tag_wrapper.children.length-1; i >= 0; i--) {
258-
const el = tag_wrapper.children[i];
259-
if (!el.classList.contains("hidden")) {
260-
el.classList.add("selected");
261-
break;
262-
}
263-
}
264-
}
265-
}
266-
267115
onChangeEachSelect() {
268116
if (this.eachSelect.value == "week") {
269117
this.timePickerWrapper.style.display = "block";
@@ -282,7 +130,7 @@ class VueDashboard {
282130

283131
onConfirmAddCron() {
284132
if (!this.form.checkValidity()) {
285-
M.toast({html: "You message has to be more thicc!"});
133+
M.toast({html: "You're message has to be more thicc!"});
286134
return;
287135
}
288136
const eachVal = this.eachSelect.value;

views/dashboard.ejs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<head>
55
<% include partials/head.ejs %>
66
<link rel="stylesheet" href="/stylesheets/dashboard.css">
7-
<script src="/js/viewDashboard.js"></script>
7+
<script src="/js/dashboard/VueDashboard.js" type="module"></script>
88
<script>
99
document.channels = <%- JSON.stringify(channel_list) %>;
1010
document.users = <%- JSON.stringify(people_list) %>;

0 commit comments

Comments
 (0)