웹 채팅 라이브러리(Chating library) 자바스크립트(javascript) 소스 오픈
일단 시작하기에 앞서 자바스크립트 풀소스 오픈하겠습니다.
작동 방식은 크게 아래와 같습니다.
1. 자바스크립트 오브젝트(Object) 방식의 개발.(채팅방별로 독립적으로 구동가능하게 하기위해서~)
2. 변수 polling_time 에 의한 초단위 폴링 방식의 데이터베이스 접근
사실 채팅에서 가장 구식적인 방법이 바로 폴링(Polling) 방식입니다.
하지만 굳이 폴링방식으로 개발을 한 이유는,
일단 소켓서버가 필요가 없습니다.
어찌보면 채팅의 개발방식은 소켓서버 구축으로 인한 데이터 교환방식이 정석입니다.
하지만 소켓방식으로 구현하기 위해서는, 소켓서버를 구축해야 하며, 저같이 호스팅을 사용하거나, 소규모 채팅만 있으면 되는 분들에게는 딱히 권해드리고 싶진 않습니다.
뭐 굳이 예로 들자면, "쥐" 잡는데 "엑스칼리버"을 사용한다고나 할까...
즉 소규모 단위의 채팅만 있어도 되는 정도의 규모의 환경이라면, 폴링방식의 채팅이 오히려 자원소모에 더 유용할 수도 있다는 의미입니다.
뭐 둘중에 개발난이도로 따져보면, 솔직히 소켓방식이 간단하고 큰 어려움은 없습니다.
제가 외부에 저만의 단독서버라도 가지고 있다면, 그 공간에 웹소켓이라도 장착해 두겠지만, 제가 그정도의 여유자금이 있는 개발자가 아니라서...
뭐 일단 취지는 소규모단위의 1:1 웹채팅이 컨셉인 프로그램입니다.
소스 하나하나에 대한 설명은 추후 들어가겠습니다.
오늘은 여기까지~
역시 포스팅도 부지런한 사람이 가능합니다...
갑자기 이전에 개발한 리뷰들을 작성하려니 은근 긔차니즘이 폭발하네요 ㅠㅠ
그렇지만 포기하지 않고 계속 진행해 나가보도록 하겠습니다.
- var open_window = new Array();
- var talk = function(){
- return {
- "other_id" : null,
- "create_id" : null,
- "date_before" : null,
- "room_no" : null,
- "other_name" : null,
- "last_idx" : 0,
- //"path" : "/alba/process/chat_proc.php",
- "path" : "action.php?c=chating&f=proc",
- "pos" : "top:10%;right:10%",
- "device" : "pc",
- "is_company" : false,
- "company_name" : "",
- "polling_hander" : null,
- "polling_time" : 1000,
- "msg_type" : "text",
- "z_index" : 1000000000,
- "adminMode" : false,
- "onmousewheel" : function(){
- $("html, body").on('mousewheel DOMMouseScroll', function(e) {
- var E = e.originalEvent;
- //console.log(E);
- });
- },
- "start_load_re" : function(){
- //x눌러서 껐다가 다시 켜기
- var _self = this;
- _self.polling_hander = true;
- _self.last_idx = 0;
- _self.start_load();
- },
- "start_load" : function(state){
- var _self = this;
- //console.log('test');
- //_self.onmousewheel();
- if(_self.polling_hander == false){
- //x누름
- return;
- }
- if(state != "ing"){
- //초기스타트
- _self.polling_hander = true;
- }
- var json_data = {};
- json_data['type'] = "start";
- json_data['other_id'] = _self.other_id;
- json_data['last_idx'] = _self.last_idx;
- json_data['create_id'] = _self.create_id;
- //console.log(json_data);
- $.post(_self.path, json_data, function(res){
- //console.log(res);
- try
- {
- //console.log(res);
- if(res.result == true)
- {
- if(state == "ing"){
- _self.proc(res.list);
- return;
- }
- _self.room_no = res.room_no;
- var html = $("#talk_html_box").html();
- html = html.replace(/%방번호%/gi, _self.room_no);
- html = html.replace(/%포지션%/gi, _self.pos);
- html = html.replace(/%상대방닉네임%/gi, _self.other_name);
- //html = html.replace(/%컴파니네임%/gi, _self.company_name);
- $("#talk_box").append(html);
- if(_self.company_name == "" || _self.company_name == undefined){
- $("#talk_company_" + _self.room_no).remove();
- }
- if(_self.adminMode == true){
- $("#talk_room_title_" + _self.room_no).hide();
- }
- $("#talk_room_" + _self.room_no).slideToggle(function(){
- $("#chatbox_" + _self.room_no).focus();
- });
- //$("#talk_room_" + _self.room_no).draggable({appendTo:'body'});
- //console.log(_self.room_no);
- $("#talk_room_" + _self.room_no).draggable({
- cancel : "#talk_contentbox_" + _self.room_no
- });
- _self.proc(res.list);
- $("#talk_close_" + _self.room_no).click(function(){
- $("#talk_room_" + _self.room_no).slideToggle(function(){
- $(this).remove();
- //console.log(open_window);
- //open_window.remove("ROOM" + _self.room_no);
- open_window["ROOM" + _self.room_no] = "ROOM" + _self.room_no;
- });
- _self.polling_hander = false;
- });
- $("#talk_room_" + _self.room_no).click(function(){
- _self.z_index = _self.z_index + 1;
- $(this).css("z-index", _self.z_index);
- });
- $("#talk_image_" + _self.room_no).change(function(){
- //console.log("이미지 올리자");
- $("#talk_form_" + _self.room_no).ajaxForm({
- dataType : "json",
- success : function(res){
- if(res.msg){
- alert(res.msg);
- }
- else{
- $("#chatbox_" + _self.room_no).val(res.filename);
- _self.msg_type = "image";
- $("#talk_submit_" + _self.room_no).trigger("click");
- $("#upload_ing_" + _self.room_no).remove();
- }
- },
- beforeSubmit : function (data,form,option) {
- //console.log("이미지 업로드 중");
- var html = "<div id='upload_ing_" + _self.room_no + "' style='text-align:center;line-height:30px;'>이미지 업로드 중...</div>";
- $("#talk_content_" + _self.room_no).append(html);
- },
- error : function(res){
- }
- });
- $("#talk_form_" + _self.room_no).submit();
- });
- $("#talk_submit_" + _self.room_no).click(function(){
- if($("#chatbox_" + _self.room_no).val().trim() == ""){
- $("#chatbox_" + _self.room_no).focus();
- return;
- }
- var json_data = {};
- json_data['type'] = "insert";
- json_data['message'] = $("#chatbox_" + _self.room_no).val();
- json_data['other_id'] = _self.other_id;
- json_data['last_idx'] = _self.last_idx;
- json_data['create_id'] = _self.create_id;
- json_data['msg_type'] = _self.msg_type;
- $.post(_self.path, json_data, function(res){
- try{
- if(res.result == true){
- _self.msg_type = "text";
- }
- else{
- alert(res.msg);
- }
- }
- catch(e){
- alert("에러가 발생했습니다.\n관리자에게 문의바랍니다.\n" + e);
- }
- }, "json");
- $("#chatbox_" + _self.room_no).val("");
- });
- $("#chatbox_" + _self.room_no).keyup(function(e){
- if(e.keyCode == 13 && !e.shiftKey){
- $("#talk_submit_" + _self.room_no).trigger("click");
- }
- });
- $("#chatbox_" + _self.room_no).focus(function(){
- $("#read_" + _self.room_no).hide();
- });
- /*
- $(".photo_" + _self.room_no).load(function(){
- _self.scroll_bottom();
- });
- */
- if(_self.device == "m"){
- var height = (parseInt($(window).height()) - 150) + "px";
- $("#talk_content_" + _self.room_no).css("height", height);
- console.log(height);
- }
- }
- else
- {
- alert(res.msg);
- }
- }
- catch(e){
- alert("메세지 로딩에 문제가 발생했습니다.\n관리자에게 문의해주세요.\n" + e);
- }
- }, "json");
- },
- "proc" : function(list){
- var _self = this;
- //console.log("proc -> " + _self.room_no);
- var cnt = 0;
- for(var key in list)
- {
- var row = list[key];
- //console.log(row);
- if(!row.IDX){
- continue;
- }
- var idx = row.IDX;
- var create_id = row.CREATE_ID;
- var is_read = row.IS_READ;
- var message = row.MESSAGE;
- var reg_datetime = row.REG_DATETIME;
- var msgHTML = "";
- if(row.REG_DATE != _self.date_before && _self.date_before != null){ //날짜 구분선
- msgHTML += "<table width='100%' style='margin:5px 0px;'>";
- msgHTML += "<tr>";
- msgHTML += " <td width='25%'><div style='border-top:1px solid gray;margin-left:10px;'></div></td>";
- msgHTML += " <td width='50%' align='center'>" + row.REG_DATE + "</td>";
- msgHTML += " <td width='25%'><div style='border-top:1px solid gray;margin-right:10px;'></div></td>";
- msgHTML += "</tr>";
- msgHTML += "</table>";
- }
- if(row.is_me == true){
- msgHTML += $("#talk_me_" + _self.room_no).html();
- if(row.TYPE == "image"){
- msgHTML = msgHTML.replace("bubble_right", "");
- }
- msgHTML = msgHTML.replace(/%고유번호%/gi, idx);
- }
- else{
- msgHTML += $("#talk_other_" + _self.room_no).html();
- if(row.TYPE == "image"){
- msgHTML = msgHTML.replace("bubble_left", "");
- }
- msgHTML = msgHTML.replace(/%닉네임%/gi, row.USR_NICK);
- if(row.USR_PHOTO){
- msgHTML = msgHTML.replace(/%상대방사진%/gi, row.USR_PHOTO);
- }
- else{
- msgHTML = msgHTML.replace(/%상대방사진%/gi, "/alba/no_user.png");
- }
- }
- msgHTML = msgHTML.replace(/%작성시간%/gi, reg_datetime);
- if(row.TYPE == "image"){
- var imgTag = "";
- if(_self.adminMode == true){
- // 이거 사용안함.
- imgTag += "<a href='action.php?c=chating&f=image_view&idx=" + idx + "' style='max-height:100px;max-width:200px;' target='_blank'>";
- imgTag += " <img src='action.php?c=chating&f=image_view&idx=" + idx + "' style='max-height:100px;max-width:200px;' =\"$('#talk_content_"+_self.room_no+"').scrollTop($('#talk_content_"+_self.room_no+"')[0].scrollHeight);\" />";
- imgTag += "</a>";
- }
- else{
- //device
- if(_self.device == "m"){
- imgTag += "<a href='action.php?c=chating&f=image_view&idx=" + idx + "' target='_blank'>";
- imgTag += " <img src='action.php?c=chating&f=image_view&idx=" + idx + "' style='max-height:100px;max-width:200px;' =\"$('#talk_content_"+_self.room_no+"').scrollTop($('#talk_content_"+_self.room_no+"')[0].scrollHeight);\" />";
- imgTag += "</a>";
- }
- else{
- imgTag += "<a href='#photo_msg_" + _self.room_no + "_" + idx + "' xrel='modal:open' =\"show_chating_photo('action.php?c=chating&f=image_view&idx=" + idx + "');\">";
- imgTag += " <img src='action.php?c=chating&f=image_view&idx=" + idx + "' style='max-height:100px;max-width:200px;' =\"$('#talk_content_"+_self.room_no+"').scrollTop($('#talk_content_"+_self.room_no+"')[0].scrollHeight);\" />";
- imgTag += "</a>";
- imgTag += "<img src='action.php?c=chating&f=image_view&idx=" + idx + "' xclass='w3-circle' style='display:none;' id='photo_msg_" + _self.room_no + "_" + idx + "' />";
- }
- }
- msgHTML = msgHTML.replace(/%메세지%/gi, imgTag);
- }
- else{
- msgHTML = msgHTML.replace(/%메세지%/gi, message);
- }
- var is_read = "";
- //console.log(list.OTHER_LAST_IDX + ">=" + idx);
- if(list.OTHER_LAST_IDX >= idx){
- is_read = "";
- }
- else{
- is_read = "1";
- }
- msgHTML = msgHTML.replace(/%읽음%/, is_read);
- $("#talk_content_" + _self.room_no).append(msgHTML);
- _self.last_idx = idx;
- _self.date_before = row.REG_DATE;
- _self.last_idx = idx;
- cnt++;
- }
- //읽음처리
- var other_last_idx = parseInt(list.OTHER_LAST_IDX);
- $(".talk_me").each(function(){
- var primary_number = parseInt($(this).attr("primary_number"));
- if(primary_number <= other_last_idx){
- $(this).find(".is_read").replaceWith("");
- $(this).removeClass("talk_me");
- }
- });
- if(cnt > 0){ // 새 메세지가 존재할 경우 스크롤 맨 하단으로
- _self.scroll_bottom();
- }
- if(_self.polling_hander == true){
- _self.polling();
- }
- },
- "scroll_bottom" : function(){
- var _self = this;
- $("#talk_content_" + _self.room_no).scrollTop($("#talk_content_" + _self.room_no)[0].scrollHeight);
- },
- "polling" : function(){
- var _self = this;
- setTimeout(function(){
- _self.start_load("ing");
- }, _self.polling_time);
- }
- }
- };
- var talk_list = function(){
- var room_data = {};
- var pos_x = 0;
- var pos_y = 0;
- var time_interval = 3000;
- var click_row = null;
- var me_id = null;
- //var path = "/alba/process/chat_proc.php";
- var path = "action.php?c=chating&f=proc";
- this.getTimeInterval = function(){
- return time_interval;
- }
- this.setMeId = function(meId){
- me_id = meId;
- }
- this.setUrl = function(url){
- path = url;
- }
- this.load = function(){
- var json_data = {};
- json_data['type'] = "start_list";
- //console.log(path);
- $.post(path, json_data, function(res){
- try{
- //console.log(res);
- if(res.result == true)
- {
- $("#talk_list").html("");
- //console.log(res.list);
- for(var key in res.list)
- {
- var row = res.list[key];
- if(!row.CREATE_ID){
- break;
- }
- room_data[row.ROOM_NO] = row;
- var listHTML = $("#talk_list_row").html();
- if(row.USR_PHOTO){
- listHTML = listHTML.replace(/%사진%/gi, row.USR_PHOTO);
- }
- else{
- listHTML = listHTML.replace(/%사진%/gi, "/alba/no_user.png");
- }
- listHTML = listHTML.replace(/%닉네임%/gi, row.USR_NICK);
- listHTML = listHTML.replace(/%마지막메세지시간%/gi, row.USR_MESSAGE_TIME);
- listHTML = listHTML.replace(/%방번호%/gi, row.ROOM_NO);
- //listHTML = listHTML.replace(/%컴파니네임%/gi, row.COMPANY_NAME);
- if(row.TYPE == "image"){
- listHTML = listHTML.replace(/%메세지%/gi, "사진");
- }
- else{
- listHTML = listHTML.replace(/%메세지%/gi, row.USR_MESSAGE);
- }
- read_cnt = parseInt(row.NO_READ);
- //console.log(read_cnt);
- //alert(read_cnt);
- listHTML = listHTML.replace(/%안읽은카운트%/gi, read_cnt);
- //console.log(listHTML);
- $("#talk_list").append(listHTML);
- if(read_cnt == 0){
- $("#read_" + row.ROOM_NO).remove();
- }
- if(row.COMPANY_NAME == "" || row.COMPANY_NAME == undefined){
- $("#chat_list_company_" + row.ROOM_NO).remove();
- }
- $("#talk_item_" + row.ROOM_NO).click(function(){
- var ROOM_NO = $(this).attr("room");
- click_row = ROOM_NO;
- $(".talk_item").css("background-color", "#FFFFFF");
- $(this).css("background-color", "#FFF173");
- });
- if(click_row == row.ROOM_NO){
- $("#talk_item_" + click_row).trigger("click");
- }
- }
- $('.talk_item').on('mousedown', function(e) {
- e.preventDefault();
- });
- $(".talk_item").dblclick(function(){
- var ROOM_NO = $(this).attr("room");
- if($.inArray("ROOM" + ROOM_NO, open_window) != -1){
- //console.log("ROOM_NO : " + ROOM_NO + " 이미 열려있음.");
- return;
- }
- //console.log("ROOM_NO : " + ROOM_NO + " 오픈");
- var data = room_data[ROOM_NO];
- //console.log(data);
- //open_window.push("ROOM" + ROOM_NO);
- open_window["ROOM" + ROOM_NO] = "ROOM" + ROOM_NO;
- talk_ = new talk();
- talk_.other_name = data.USR_NICK;
- talk_.other_id = data.OTHER_ID;
- talk_.create_id = data.CREATE_ID;
- talk_.me_id = me_id;
- talk_.last_idx = 0;
- talk_.path = path;
- talk_.is_company = true;
- talk_.company_name = data.COMPANY_NAME;
- pos_x = pos_x + 5;
- pos_y = pos_y + 5;
- talk_.pos = "top:" + pos_x + "%;left:" + pos_y + "%";
- talk_.start_load();
- $("#read_" + ROOM_NO).hide();
- room_data[ROOM_NO].is_open = true;
- });
- }
- else{
- alert(res.msg);
- }
- }
- catch(e){
- alert("채팅방 리스트 불러오기에 실패했습니다.\n관리자에게 문의바랍니다.\n" + e);
- }
- }, "json");
- }
- }
- function show_chating_photo(src)
- {
- //alert(src);
- $("#chating_photo_box").attr("src", src);
- $("#model_chating_photo").modal('show');
- }