-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathchat.js
More file actions
116 lines (102 loc) · 3.7 KB
/
Copy pathchat.js
File metadata and controls
116 lines (102 loc) · 3.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
class Chat {
constructor(el, collectionName) {
this.el = el;
const db = firebase.firestore();
this.collection = db.collection(collectionName || 'messages');
this.messagesDiv = el.querySelector('.messages');
this.listenCollection();
this.listenForm();
}
listenCollection() {
this.collection.orderBy('createdAt').onSnapshot({
includeMetadataChanges: true,
}, snapshot => {
snapshot.docChanges().filter(change => {
return (change.type === 'added' && change.doc.data().createdAt)
|| change.type === 'modified';
}).forEach(change => {
const el = this.createMessageEl(change.doc.data());
this.messagesDiv.insertBefore(el, this.messagesDiv.firstChild);
});
}, error => {
alert(`Error listening collection: ${error}`);
});
}
createMessageEl(data) {
const containerDiv = document.createElement('div');
const userDiv = document.createElement('div');
const timeDiv = document.createElement('div');
const pre = document.createElement('pre');
containerDiv.classList.add('message');
userDiv.classList.add('user');
timeDiv.classList.add('time');
userDiv.textContent = data.user || '(匿名)';
timeDiv.textContent = this.formatDate(data.createdAt.seconds);
pre.textContent = data.message;
pre.innerHTML = this.urlToAnchor(pre.innerHTML);
containerDiv.appendChild(userDiv);
containerDiv.appendChild(timeDiv);
containerDiv.appendChild(pre);
return containerDiv;
}
formatDate(seconds) {
const d = new Date(seconds * 1000);
return d.getFullYear() + '/' + (d.getMonth() + 1) + '/' + d.getDate()
+ '(' + this.jpDay(d.getDay()) + ')'
+ ' ' + d.getHours()
+ ':' + d.getMinutes().toString().padStart(2, '0')
+ ':' + d.getSeconds().toString().padStart(2, '0');
}
jpDay(day) {
switch (day) {
case 0:
return '日';
case 1:
return '月';
case 2:
return '火';
case 3:
return '水';
case 4:
return '木';
case 5:
return '金';
case 6:
return '土';
default:
throw new RangeError('The argument must be between 0 and 6.');
}
}
urlToAnchor(text) {
return text.replace(/https?:\/\/\S+/ig, '<a href="$&" target="_blank">$&</a>');
}
listenForm() {
const form = this.el.querySelector('form.input-form');
const userNameArea = form.querySelector('input.user');
const messageArea = form.querySelector('textarea.message');
form.addEventListener('submit', event => {
event.preventDefault();
const [user, message] = [userNameArea.value, messageArea.value];
if (message.length === 0) {
return;
}
this.post(user, message).then(docRef => {
messageArea.value = '';
}).catch(error => {
alert(`Error adding a message: ${error}`);
});
});
messageArea.addEventListener('keydown', event => {
if (event.key === 'Enter' && (event.ctrlKey || event.metaKey)) {
form.dispatchEvent(new Event('submit'));
}
});
}
post(user, message) {
return this.collection.add({
user,
message,
createdAt: firebase.firestore.FieldValue.serverTimestamp(),
});
}
}