| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274 |
- const SEND_MESSAGE_ACTION = "send-message" // 채팅 메시지
- const USER_JOINED_ACTION = "user-join" // 회원 접속
- const USER_LEFT_ACTION = "user-left" // 회원 접속 종료
- const JOIN_ROOM_ACTION = "join-room" // 방 입장
- const LEAVE_ROOM_ACTION = "leave-room" // 방 퇴장
- const JOIN_ROOM_PRIVATE_ACTION = "join-room-private" // 방 비밀 입장
- const ROOM_JOINED_ACTION = "room-joined" // 방 입장함
- const DUPLICATION_ACTION = "duplication" // 회원 중복
- const CHAT_HISTORY_ACTION = "set-history"
- const SERVER_URL = "ws://localhost:7070";
- const ChatClient = class {
- constructor(url) {
- this.url = url;
- }
- isConnected = null;
- socket = null;
- user = null;
- rooms = [];
- users = [];
- // 작업영역
- notice = null;
- log = null;
- message = null;
- btnPush = null;
- // 글자크기
- fontSize = 14;
- init() {
- if (!window.WebSocket) {
- this.setWarning("해당 브라우저는 채팅을 지원하지 않습니다. 최신 버전의 브라우저를 설치 후 실행 해주세요.")
- } else {
- this.isConnected = false;
- this.notice = document.getElementById("chatNotice");
- this.log = document.getElementById("chatLog");
- this.message = document.getElementById("message");
- this.btnPush = document.getElementById("btnPushMessage");
- this.connect();
- let $this = this;
- this.socket.onopen = function() {
- console.log("[Connected]");
- $this.isConnected = true;
- $this.btnPush.removeAttribute("disabled");
- $this.message.focus();
- $this.setNotice("서버와 연결 되었습니다.");
- $this.setEvent();
- $this.emit(CHAT_HISTORY_ACTION);
- };
- this.socket.onmessage = function (e) {
- let data = e.data;
- data = data.split(/\r?\n/);
- for (let i = 0; i < data.length; i++) {
- let msg = JSON.parse(data[i]);
- switch (msg.action) {
- case DUPLICATION_ACTION:
- $this.setAlert("중복접속으로 이전접속을 종료합니다.");
- break;
- case SEND_MESSAGE_ACTION:
- $this.setMessage(msg)
- break;
- case USER_JOINED_ACTION:
- $this.handleUserJoined(msg);
- break;
- case USER_LEFT_ACTION:
- $this.handleUserLeft(msg);
- break;
- case ROOM_JOINED_ACTION:
- break;
- case CHAT_HISTORY_ACTION:
- $this.handleSetHistory(msg);
- break;
- default:
- break;
- }
- }
- };
- this.socket.onerror = function() {
- $this.setWarning("연결 요청에 실패하였습니다.");
- };
- this.socket.onclose = function() {
- $this.setFailed("서버 연결이 종료되었습니다.");
- };
- }
- }
- // 서버 소켓 연결
- connect() {
- try {
- let query = "?";
- // 로그인 회원 정보
- if (IS_USER) {
- let userInfo = document.getElementById("userInfo").value.trim();
- if (typeof userInfo !== "undefined") {
- this.user = JSON.parse(atob(userInfo, true));
- query += "bearer=" + this.user.token;
- }
- }else{
- query += "name=" + generateRandomString(6);
- }
- // 웹소켓 연결
- this.socket = new WebSocket(this.url + query);
- } catch (err) {
- this.setFailed(err);
- }
- }
- // 클라이언트 기능 처리 담당
- setEvent() {
- // 메시지 전송
- document.getElementById("btnPushMessage").addEventListener("click", function (e) {
- this.emit(SEND_MESSAGE_ACTION, {
- message: this.message.value
- });
- }.bind(this));
- this.message.addEventListener("keyup", function (e) {
- if (e.key === "Enter" || e.keyCode === 13) {
- this.emit(SEND_MESSAGE_ACTION, {
- message: e.target.value
- });
- e.preventDefault();
- }
- }.bind(this));
- // 새창으로
- document.getElementById("btnPopupChat").addEventListener("click", function() {
- window.open(window.location.href, "master", "popup=1,toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=no,resizable=no,copyhistory=no");
- });
- // 청소하기
- document.getElementById("btnTxtClear").addEventListener("click", function() {
- this.clear();
- }.bind(this));
- // 글자크게
- document.getElementById("btnTxtPlus").addEventListener("click", function(e) {
- e.stopPropagation();
- this.textResize(1);
- }.bind(this));
- // 글자작게
- document.getElementById("btnTxtMinus").addEventListener("click", function(e) {
- e.stopPropagation();
- this.textResize(-1);
- }.bind(this));
- // 새로고침
- document.getElementById("btnTxtRefresh").addEventListener("click", function() {
- this.refresh();
- }.bind(this));
- }
- // 서버에 송신 담당
- emit(name, data) {
- if (this.socket.readyState === 1) {
- this.socket.send(JSON.stringify(Object.assign({action: name}, data)));
- }else{
- this.setFailed("통신이 불가합니다. 새로고침 후 다시 시도하세요.");
- }
- }
- // 송/수신 메시지 표시
- setDisplay(s) {
- $(this.log).append(s.trim());
- this.log.scrollTop = this.log.scrollHeight;
- this.message.value = "";
- }
- // 일반 메시지
- setMessage(s) {
- this.setDisplay(`<em style="font-size: ${this.fontSize}px;">${s.sender.User.Name}: ${s.message}</em>`);
- }
- // 공지사항
- setNotice(s) {
- this.setDisplay('<p class="notice">' + s + '</p>');
- }
- // 경고
- setAlert(s) {
- this.setDisplay('<p class="alert">' + s + '</p>');
- }
- // 알림
- setWarning(s) {
- this.setDisplay('<p class="warning">' + s + '</p>');
- }
- // 실패
- setFailed(s) {
- this.setDisplay('<p class="failed">' + s + '</p>');
- }
- // 글자 크게/작게
- textResize(num) {
- let n = Number(num);
- let fontSize = (Number(this.fontSize) + n);
- if (!(fontSize > 10 && fontSize < 23)) {
- return;
- }
- document.getElementById("chatLog").querySelectorAll("em").forEach(function (row) {
- row.style.fontSize = (fontSize + "px");
- });
- this.fontSize = fontSize;
- }
- // 청소하기
- clear() {
- this.message.focus();
- this.log.innerText = "";
- this.setAlert("채팅방이 청소되었습니다.");
- }
- // 새로고침
- refresh() {
- window.location.reload();
- }
- // 이미 존재하는 회원인지 확인
- userExists(user) {
- for (let i = 0; i < this.users.length; i++) {
- if (this.users[i].id == user.id) {
- return true;
- }
- }
- return false;
- }
- // 회원 입장
- handleUserJoined(msg) {
- document.getElementById("chatUserRows").innerText = msg.message;
- if (!this.userExists(msg.sender)) {
- this.users.push(msg.sender);
- }
- }
- // 회원 퇴장
- handleUserLeft(msg) {
- document.getElementById("chatUserRows").innerText = msg.message;
- for (let i = 0; i < this.users.length; i++) {
- if (this.users[i].id == msg.sender.id) {
- this.users.splice(i, 1);
- return;
- }
- }
- }
- handleSetHistory(msg) {
- let histories = JSON.parse(msg.message.replace("\x00", ""));
- if (histories.length > 0) {
- for (let row of histories) {
- this.setMessage(row);
- }
- }
- }
- }
- let client;
- window.addEventListener("DOMContentLoaded", function() {
- client = new ChatClient(SERVER_URL);
- client.init();
- });
|