{"id":6970,"date":"2015-11-05T09:18:51","date_gmt":"2015-11-05T08:18:51","guid":{"rendered":"https:\/\/anexia.com\/stagingblog\/?p=6970"},"modified":"2022-04-22T09:30:45","modified_gmt":"2022-04-22T07:30:45","slug":"setting-up-your-own-online-chat-module-with-codeigniter","status":"publish","type":"post","link":"https:\/\/anexia.com\/blog\/en\/setting-up-your-own-online-chat-module-with-codeigniter\/","title":{"rendered":"Setting up your own online chat module with CodeIgniter"},"content":{"rendered":"<p>Everyone is familiar with it, or has at least seen it before \u2013 we&#8217;re talking about the online chat feature available on many websites like Facebook or Google+.<\/p>\n<p><!--more--><\/p>\n<p>But what the underlying technology actually looks like and how these chat services basically work is what I would like to explain in the following.<\/p>\n<p>You can then complete a tutorial on how to build your own chat feature using the CodeIgniter framework for your next <a href=\"https:\/\/anexia.com\/en\/software-development\/web-development\/\">web development<\/a>.<\/p>\n<p><a href=\"https:\/\/anexia.com\/blog\/wp-content\/uploads\/2015\/10\/ci_chat.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-1116\" src=\"https:\/\/anexia.com\/blog\/wp-content\/uploads\/2015\/10\/ci_chat-1024x302.png\" alt=\"CodeIgniter Chat\" width=\"474\" height=\"140\" srcset=\"https:\/\/anexia.com\/blog\/wp-content\/uploads\/2015\/10\/ci_chat-1024x302.png 1024w, https:\/\/anexia.com\/blog\/wp-content\/uploads\/2015\/10\/ci_chat-325x96.png 325w, https:\/\/anexia.com\/blog\/wp-content\/uploads\/2015\/10\/ci_chat-300x89.png 300w, https:\/\/anexia.com\/blog\/wp-content\/uploads\/2015\/10\/ci_chat.png 1175w\" sizes=\"(max-width: 474px) 100vw, 474px\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<h2>THE UNDERLYING PRINCIPLE<\/h2>\n<p>There are essentially three different types of online chat:<\/p>\n<ul>\n<li>Internet Relay Chat (IRC)<\/li>\n<li>Web chat<\/li>\n<li>Instant Messaging<\/li>\n<\/ul>\n<p>IRC uses a traditional client-server architecture, which requires special chat servers that are interconnected. A dedicated piece of client software that is either installed directly on the PCs of the various chat participants or runs in their browser is used to exchange messages.<\/p>\n<p>Simple webchat modules, such as those used on live support systems, do not require any additional software. Communication is usually limited to the specific website.<\/p>\n<p>Instant messaging is completely different, however. Communications are not typically exchanged by way of a public chatroom, but rather exclusively between the respective chat participants who identify themselves using a specific piece of software.<\/p>\n<p>IRC and instant messaging usually offer other features such as chat logs or files transfers as well.<\/p>\n<h2>YOUR OWN CHAT MODULE WITH CODEIGNITER<\/h2>\n<p><a href=\"https:\/\/anexia.com\/blog\/wp-content\/uploads\/2015\/01\/codeigniter_logo.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-medium wp-image-504\" src=\"https:\/\/anexia.com\/blog\/wp-content\/uploads\/2015\/01\/codeigniter_logo-300x70.png\" alt=\"CodeIgniter Logo\" width=\"300\" height=\"70\" srcset=\"https:\/\/anexia.com\/blog\/wp-content\/uploads\/2015\/01\/codeigniter_logo-300x70.png 300w, https:\/\/anexia.com\/blog\/wp-content\/uploads\/2015\/01\/codeigniter_logo-600x140.png 600w, https:\/\/anexia.com\/blog\/wp-content\/uploads\/2015\/01\/codeigniter_logo-1024x239.png 1024w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<h3>BUILD THE FOUNDATION<\/h3>\n<p>To get started, we recommend that you first download the latest version of the CodeIgniter framework from the website (<a href=\"http:\/\/www.codeigniter.com\/\">http:\/\/www.codeigniter.com<\/a>). This is currently version 3.0.2.<\/p>\n<p>Next, copy all of the files to a subdirectory called &#8222;ci-chat&#8220; on the web server (e.g. XAMPP, LAMP, etc.) and open its root directory in your browser, e.g. http:\/\/localhost\/ci-chat\/.<\/p>\n<p>Once all of the requirements for the framework are met, you should then see the CodeIgniter welcome page.<\/p>\n<p>In the autoloader configuration, navigate to <strong>\/application\/config\/autoload.php<\/strong> and then add the URL Helper and the database library, as we will need these components later.<\/p>\n<pre class=\"lang:php decode:true\">$autoload['libraries'] = array('database');\r\n$autoload['helper'] = array('url');<\/pre>\n<p>In the route configuration under <strong>\/application\/config\/routes.php,<\/strong> now change the default controller from \u201c<em>welcome<\/em>\u201d to \u201c<em>chat<\/em>\u201d since later we want our chat application to be loaded by default.<\/p>\n<h3>THE APPLICATION ITSELF<\/h3>\n<pre class=\"lang:php decode:true \">$route['default_controller'] = 'chat';<\/pre>\n<p>&nbsp;<\/p>\n<h3>The actual application<\/h3>\n<p>In the current state, the route configuration would simply return a 404 error because we have not yet defined a chat controller.<\/p>\n<p>So we first need to create a new controller under <strong>\/application\/controllers<\/strong> with a new name<strong>Chat.php<\/strong> and should also note the following here:<\/p>\n<pre class=\"lang:php decode:true\">&lt;?php\r\ndefined('BASEPATH') OR exit('No direct script access allowed');\r\n\r\nclass Chat extends CI_Controller {\r\n\r\n\r\n\tpublic function index()\r\n\t{\r\n\t\t$this-&gt;load-&gt;view('chat');\r\n\t}\r\n}\r\n<\/pre>\n<p>This controller looks \u2012 and is \u2012 primitive. Its only purpose is to load the appropriate view. A separate API controller is used for the actual functionality.<\/p>\n<p>It would, of course, be possible to include the entire logic in the previously created controller as well. The separation into multiple controllers makes sense, especially in the case of larger projects, because it greatly increases readability and therefore maintainability.<\/p>\n<p>To save the individual messages so that they can then be delivered to the other chat participants, we need a database and a suitable model.<\/p>\n<pre class=\"lang:vim decode:true \">CREATE TABLE IF NOT EXISTS `messages` (\r\n`id` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,\r\n`message` text NOT NULL,\r\n`nickname` varchar(50) NOT NULL,\r\n`guid` varchar(100) NOT NULL,\r\n`timestamp` int(11) NOT NULL\r\n);\r\n<\/pre>\n<p>Under <strong>\/application\/models<\/strong>, we will now create a new model called <strong>Chat_model.php <\/strong>and add the following items:<\/p>\n<pre class=\"lang:php decode:true \">&lt;?php\r\ndefined('BASEPATH') OR exit('No direct script access allowed');\r\n\r\nclass Chat_model extends CI_Model {  \r\n  \r\n\tfunction add_message($message, $nickname, $guid)\r\n\t{\r\n\t\t$data = array(\r\n\t\t\t'message'\t=&gt; (string) $message,\r\n\t\t\t'nickname'\t=&gt; (string) $nickname,\r\n\t\t\t'guid'\t\t=&gt; (string)\t$guid,\r\n\t\t\t'timestamp'\t=&gt; time(),\r\n\t\t);\r\n\t\t  \r\n\t\t$this-&gt;db-&gt;insert('messages', $data);\r\n\t}\r\n\r\n\tfunction get_messages($timestamp)\r\n\t{\r\n\t\t$this-&gt;db-&gt;where('timestamp &gt;', $timestamp);\r\n\t\t$this-&gt;db-&gt;order_by('timestamp', 'DESC');\r\n\t\t$this-&gt;db-&gt;limit(10); \r\n\t\t$query = $this-&gt;db-&gt;get('messages');\r\n\t\t\r\n\t\treturn array_reverse($query-&gt;result_array());\r\n\t}\r\n\r\n}\r\n<\/pre>\n<p>The method <strong>add_message()<\/strong> allows us to add new messages. The parameter of the method is the actual message and nickname of the chat participant who sent the message. To avoid conflicts when multiple chat participants use the same nickname, we also save a GUID. This is a unique identifier, which will then be used only by the application itself.<\/p>\n<p>The method <strong>get_messages()<\/strong> lets us retrieve all messages written from a specific point in time. The method requires the respective UNIX timestamp for this.<\/p>\n<p>&nbsp;<\/p>\n<p>To make both of these methods available externally as well, we create a new controller <strong>Api.php<\/strong> under <strong>\/application\/controllers<\/strong> and add:<\/p>\n<pre class=\"lang:php decode:true \">&lt;?php\r\ndefined('BASEPATH') OR exit('No direct script access allowed');\r\n\r\nclass Api extends CI_Controller {\r\n\r\n\t\r\n\tpublic function __construct()\r\n\t{\r\n\t\tparent::__construct();\r\n\t\t\r\n\t\t$this-&gt;load-&gt;model('Chat_model');\r\n\t}\r\n\t\r\n\t\r\n\tpublic function send_message()\r\n\t{\r\n\t\t$message = $this-&gt;input-&gt;get('message', null);\r\n\t\t$nickname = $this-&gt;input-&gt;get('nickname', '');\r\n\t\t$guid = $this-&gt;input-&gt;get('guid', '');\r\n\t\t\r\n\t\t$this-&gt;Chat_model-&gt;add_message($message, $nickname, $guid);\r\n\t\t\r\n\t\t$this-&gt;_setOutput($message);\r\n\t}\r\n\t\r\n\t\r\n\tpublic function get_messages()\r\n\t{\r\n\t\t$timestamp = $this-&gt;input-&gt;get('timestamp', null);\r\n\t\t\r\n\t\t$messages = $this-&gt;Chat_model-&gt;get_messages($timestamp);\r\n\t\t\r\n\t\t$this-&gt;_setOutput($messages);\r\n\t}\r\n\t\r\n\t\r\n\tprivate function _setOutput($data)\r\n\t{\r\n\t\theader('Cache-Control: no-cache, must-revalidate');\r\n\t\theader('Expires: Mon, 26 Jul 1997 05:00:00 GMT');\r\n\t\theader('Content-type: application\/json');\r\n\t\t\r\n\t\techo json_encode($data);\r\n\t}\r\n}<\/pre>\n<p>The previously created chat model is now loaded into the framework. In addition, <strong>_setOutput()<\/strong> is used to set up a central output handler, to which we simply pass the required data and then process this accordingly (in this case, JSON).<\/p>\n<h3>The graphical user interface<\/h3>\n<p>Under <strong>\/application\/views<\/strong>, we create a new view <strong>chat.php<\/strong> (which we already linked in the chat controller).<\/p>\n<p>Here, we build the basic HTML framework for our chat based on jQuery und Bootstrap.<\/p>\n<pre class=\"lang:vim decode:true\">&lt;?php\r\ndefined('BASEPATH') OR exit('No direct script access allowed');\r\n?&gt;&lt;!DOCTYPE html&gt;\r\n&lt;html lang=\"en\"&gt;\r\n&lt;head&gt;\r\n\t&lt;meta charset=\"utf-8\"&gt;\r\n\t&lt;title&gt;Chat-Example | CodeIgniter&lt;\/title&gt;\r\n\t\r\n\t&lt;script type=\"text\/javascript\" src=\"https:\/\/code.jquery.com\/jquery-2.1.4.min.js\"&gt;&lt;\/script&gt;\r\n\r\n\t\t\r\n\t&lt;link rel=\"stylesheet\" href=\"https:\/\/maxcdn.bootstrapcdn.com\/bootstrap\/3.3.5\/css\/bootstrap.min.css\" \/&gt;\r\n\t&lt;script type=\"text\/javascript\" src=\"https:\/\/maxcdn.bootstrapcdn.com\/bootstrap\/3.3.5\/js\/bootstrap.min.js\"&gt;&lt;\/script&gt;\r\n\t\r\n\t&lt;!-- http:\/\/bootsnipp.com\/snippets\/4jXW --&gt;\r\n\t&lt;link rel=\"stylesheet\" href=\"&lt;?php echo base_url(); ?&gt;assets\/css\/chat.css\" \/&gt;\r\n\t\r\n\t\r\n\t&lt;script type=\"text\/javascript\"&gt;\t  \r\n\t\t$( document ).ready ( function () {\r\n\t\t\t\r\n\t\t\t$('#nickname').keyup(function() {\r\n\t\t\t\tvar nickname = $(this).val();\r\n\t\t\t\t\r\n\t\t\t\tif(nickname == ''){\r\n\t\t\t\t\t$('#msg_block').hide();\r\n\t\t\t\t}else{\r\n\t\t\t\t\t$('#msg_block').show();\r\n\t\t\t\t}\r\n\t\t\t});\r\n\t\t\t\r\n\t\t\t\/\/ initial nickname check\r\n\t\t\t$('#nickname').trigger('keyup');\r\n\t\t});\r\n\t\t\r\n\t\t\r\n\t&lt;\/script&gt;\r\n\r\n&lt;\/head&gt;\r\n&lt;body&gt;\r\n\r\n\r\n\r\n&lt;div class=\"container\"&gt;\r\n    &lt;div class=\"row\"&gt;\r\n\t\t&lt;div class=\"panel panel-primary\"&gt;\r\n\t\t\t&lt;div class=\"panel-heading\"&gt;\r\n\t\t\t\t&lt;span class=\"glyphicon glyphicon-comment\"&gt;&lt;\/span&gt; Chat\r\n\t\t\t&lt;\/div&gt;\r\n\t\t\t&lt;div class=\"panel-body\"&gt;\r\n\t\t\t\t&lt;ul class=\"chat\" id=\"received\"&gt;\r\n\t\t\t\t\t\r\n\t\t\t\t&lt;\/ul&gt;\r\n\t\t\t&lt;\/div&gt;\r\n\t\t\t&lt;div class=\"panel-footer\"&gt;\r\n\t\t\t\t&lt;div class=\"clearfix\"&gt;\r\n\t\t\t\t\t&lt;div class=\"col-md-3\"&gt;\r\n\t\t\t\t\t\t&lt;div class=\"input-group\"&gt;\r\n\t\t\t\t\t\t\t&lt;span class=\"input-group-addon\"&gt;\r\n\t\t\t\t\t\t\t\tNickname:\r\n\t\t\t\t\t\t\t&lt;\/span&gt;\r\n\t\t\t\t\t\t\t&lt;input id=\"nickname\" type=\"text\" class=\"form-control input-sm\" placeholder=\"Nickname...\" \/&gt;\r\n\t\t\t\t\t\t&lt;\/div&gt;\r\n\t\t\t\t\t&lt;\/div&gt;\r\n\t\t\t\t\t&lt;div class=\"col-md-9\" id=\"msg_block\"&gt;\r\n\t\t\t\t\t\t&lt;div class=\"input-group\"&gt;\r\n\t\t\t\t\t\t\t&lt;input id=\"message\" type=\"text\" class=\"form-control input-sm\" placeholder=\"Type your message here...\" \/&gt;\r\n\t\t\t\t\t\t\t&lt;span class=\"input-group-btn\"&gt;\r\n\t\t\t\t\t\t\t\t&lt;button class=\"btn btn-warning btn-sm\" id=\"submit\"&gt;Send&lt;\/button&gt;\r\n\t\t\t\t\t\t\t&lt;\/span&gt;\r\n\t\t\t\t\t\t&lt;\/div&gt;\r\n\t\t\t\t\t&lt;\/div&gt;\r\n\t\t\t\t&lt;\/div&gt;\r\n\t\t\t&lt;\/div&gt;\r\n\t\t&lt;\/div&gt;\r\n    &lt;\/div&gt;\r\n&lt;\/div&gt;\r\n\r\n\r\n\r\n&lt;\/body&gt;\r\n&lt;\/html&gt;<\/pre>\n<p><span id=\"result_box\" class=\"\" lang=\"en\"><span class=\"hps\">In<\/span>  the <span class=\"hps\">Javascript<\/span><span class=\"atn\"> section <\/span><span class=\"hps\">there is a<\/span> <span class=\"hps\">check<\/span>, <span class=\"hps\">so that the<\/span> <span class=\"hps\">input field <\/span><span class=\"hps\">for<\/span> <span class=\"hps\">chat messages<\/span> <span class=\"hps\">is<\/span> <span class=\"hps\">only<\/span> <span class=\"hps\">visible if<\/span> <span class=\"hps\">the user has entered<\/span> <span class=\"hps\">a nickname<\/span><span class=\"\">.<\/span><\/span><\/p>\n<p>For making this looking beautiful, we now create a <strong>chat.css<\/strong> with following content:<\/p>\n<pre class=\"lang:css decode:true\">.chat\r\n{\r\n    list-style: none;\r\n    margin: 0;\r\n    padding: 0;\r\n}\r\n\r\n.chat li\r\n{\r\n    margin-bottom: 10px;\r\n    padding-bottom: 5px;\r\n    border-bottom: 1px dotted #B3A9A9;\r\n}\r\n\r\n.chat li.left .chat-body\r\n{\r\n    margin-left: 60px;\r\n}\r\n\r\n.chat li.right .chat-body\r\n{\r\n    margin-right: 60px;\r\n}\r\n\r\n\r\n.chat li .chat-body p\r\n{\r\n    margin: 0;\r\n    color: #777777;\r\n}\r\n\r\n.panel .slidedown .glyphicon, .chat .glyphicon\r\n{\r\n    margin-right: 5px;\r\n}\r\n\r\n.panel-body\r\n{\r\n    overflow-y: scroll;\r\n    height: 250px;\r\n}\r\n\r\n::-webkit-scrollbar-track\r\n{\r\n    -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3);\r\n    background-color: #F5F5F5;\r\n}\r\n\r\n::-webkit-scrollbar\r\n{\r\n    width: 12px;\r\n    background-color: #F5F5F5;\r\n}\r\n\r\n::-webkit-scrollbar-thumb\r\n{\r\n    -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,.3);\r\n    background-color: #555;\r\n}<\/pre>\n<p>&nbsp;<\/p>\n<p><span id=\"result_box\" class=\"\" lang=\"en\"><span class=\"hps\">In the next step<\/span> <span class=\"hps\">we define<\/span> <span class=\"hps\">here<\/span> <span class=\"hps\">additional<\/span> <span class=\"hps\">auxiliary functions<\/span> <span class=\"hps\">and<\/span> <span class=\"hps\">also<\/span> <span class=\"hps\">save<\/span> <span class=\"hps\">the GUID of the<\/span> <span class=\"hps\">chat<\/span> <span class=\"hps\">participant<\/span> <span class=\"hps\">in <\/span><span class=\"hps\">a cookie<\/span>. <span class=\"hps\">For simplicity,<\/span> <span class=\"hps\">this identifier<\/span> <span class=\"hps\">is generated<\/span> <span class=\"hps\">locally<\/span> <span class=\"hps\">in the browser<\/span>. <span class=\"hps\">In<\/span> <span class=\"hps\">a production environment<\/span>, this <span class=\"hps\">could<\/span> <span class=\"hps\">for example<\/span> <span class=\"hps\">be<\/span> <span class=\"hps\">stored in a<\/span> <span class=\"hps\">user table<\/span> <span class=\"hps\">directly<\/span> <span class=\"hps\">in the database<\/span><span class=\"\">.<\/span><\/span><\/p>\n<pre class=\"lang:js decode:true \">var request_timestamp = 0;\r\n\r\nvar setCookie = function(key, value) {\r\n\tvar expires = new Date();\r\n\texpires.setTime(expires.getTime() + (5 * 60 * 1000));\r\n\tdocument.cookie = key + '=' + value + ';expires=' + expires.toUTCString();\r\n}\r\n\r\nvar getCookie = function(key) {\r\n\tvar keyValue = document.cookie.match('(^|;) ?' + key + '=([^;]*)(;|$)');\r\n\treturn keyValue ? keyValue[2] : null;\r\n}\r\n\r\nvar guid = function() {\r\n\tfunction s4() {\r\n\t\treturn Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);\r\n\t}\r\n\treturn s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4();\r\n}\r\n\r\nif(getCookie('user_guid') == null || typeof(getCookie('user_guid')) == 'undefined'){\r\n\tvar user_guid = guid();\r\n\tsetCookie('user_guid', user_guid);\r\n}\r\n\r\n\r\n\/\/ https:\/\/gist.github.com\/kmaida\/6045266\r\nvar parseTimestamp = function(timestamp) {\r\n\tvar d = new Date( timestamp * 1000 ), \/\/ milliseconds\r\n\t\tyyyy = d.getFullYear(),\r\n\t\tmm = ('0' + (d.getMonth() + 1)).slice(-2),\t\/\/ Months are zero based. Add leading 0.\r\n\t\tdd = ('0' + d.getDate()).slice(-2),\t\t\t\/\/ Add leading 0.\r\n\t\thh = d.getHours(),\r\n\t\th = hh,\r\n\t\tmin = ('0' + d.getMinutes()).slice(-2),\t\t\/\/ Add leading 0.\r\n\t\tampm = 'AM',\r\n\t\ttimeString;\r\n\t\t\t\r\n\tif (hh &gt; 12) {\r\n\t\th = hh - 12;\r\n\t\tampm = 'PM';\r\n\t} else if (hh === 12) {\r\n\t\th = 12;\r\n\t\tampm = 'PM';\r\n\t} else if (hh == 0) {\r\n\t\th = 12;\r\n\t}\r\n\r\n\ttimeString = yyyy + '-' + mm + '-' + dd + ', ' + h + ':' + min + ' ' + ampm;\r\n\t\t\r\n\treturn timeString;\r\n}<\/pre>\n<p>&nbsp;<\/p>\n<p>Now we define the actual functions in the form of closures for adding and displaying messages.<\/p>\n<pre class=\"lang:vim decode:true \">var sendChat = function (message, callback) {\r\n\t$.getJSON('&lt;?php echo base_url(); ?&gt;api\/send_message?message=' + message + '&amp;nickname=' + $('#nickname').val() + '&amp;guid=' + getCookie('user_guid'), function (data){\r\n\t\tcallback();\r\n\t});\r\n}\r\n\r\nvar append_chat_data = function (chat_data) {\r\n\tchat_data.forEach(function (data) {\r\n\t\tvar is_me = data.guid == getCookie('user_guid');\r\n\t\t\r\n\t\tif(is_me){\r\n\t\t\tvar html = '&lt;li class=\"right clearfix\"&gt;';\r\n\t\t\thtml += '\t&lt;span class=\"chat-img pull-right\"&gt;';\r\n\t\t\thtml += '\t\t&lt;img src=\"http:\/\/placehold.it\/50\/FA6F57\/fff&amp;text=' + data.nickname.slice(0,2) + '\" alt=\"User Avatar\" class=\"img-circle\" \/&gt;';\r\n\t\t\thtml += '\t&lt;\/span&gt;';\r\n\t\t\thtml += '\t&lt;div class=\"chat-body clearfix\"&gt;';\r\n\t\t\thtml += '\t\t&lt;div class=\"header\"&gt;';\r\n\t\t\thtml += '\t\t\t&lt;small class=\"text-muted\"&gt;&lt;span class=\"glyphicon glyphicon-time\"&gt;&lt;\/span&gt;' + parseTimestamp(data.timestamp) + '&lt;\/small&gt;';\r\n\t\t\thtml += '\t\t\t&lt;strong class=\"pull-right primary-font\"&gt;' + data.nickname + '&lt;\/strong&gt;';\r\n\t\t\thtml += '\t\t&lt;\/div&gt;';\r\n\t\t\thtml += '\t\t&lt;p&gt;' + data.message + '&lt;\/p&gt;';\r\n\t\t\thtml += '\t&lt;\/div&gt;';\r\n\t\t\thtml += '&lt;\/li&gt;';\r\n\t\t}else{\r\n\t\t  \r\n\t\t\tvar html = '&lt;li class=\"left clearfix\"&gt;';\r\n\t\t\thtml += '\t&lt;span class=\"chat-img pull-left\"&gt;';\r\n\t\t\thtml += '\t\t&lt;img src=\"http:\/\/placehold.it\/50\/55C1E7\/fff&amp;text=' + data.nickname.slice(0,2) + '\" alt=\"User Avatar\" class=\"img-circle\" \/&gt;';\r\n\t\t\thtml += '\t&lt;\/span&gt;';\r\n\t\t\thtml += '\t&lt;div class=\"chat-body clearfix\"&gt;';\r\n\t\t\thtml += '\t\t&lt;div class=\"header\"&gt;';\r\n\t\t\thtml += '\t\t\t&lt;strong class=\"primary-font\"&gt;' + data.nickname + '&lt;\/strong&gt;';\r\n\t\t\thtml += '\t\t\t&lt;small class=\"pull-right text-muted\"&gt;&lt;span class=\"glyphicon glyphicon-time\"&gt;&lt;\/span&gt;' + parseTimestamp(data.timestamp) + '&lt;\/small&gt;';\r\n\t\t\t\r\n\t\t\thtml += '\t\t&lt;\/div&gt;';\r\n\t\t\thtml += '\t\t&lt;p&gt;' + data.message + '&lt;\/p&gt;';\r\n\t\t\thtml += '\t&lt;\/div&gt;';\r\n\t\t\thtml += '&lt;\/li&gt;';\r\n\t\t}\r\n\t\t$(\"#received\").html( $(\"#received\").html() + html);\r\n\t});\r\n  \r\n\t$('#received').animate({ scrollTop: $('#received').height()}, 1000);\r\n}\r\n\r\nvar update_chats = function () {\r\n\tif(typeof(request_timestamp) == 'undefined' || request_timestamp == 0){\r\n\t\tvar offset = 60*15; \/\/ 15min\r\n\t\trequest_timestamp = parseInt( Date.now() \/ 1000 - offset );\r\n\t}\r\n\t$.getJSON('&lt;?php echo base_url(); ?&gt;api\/get_messages?timestamp=' + request_timestamp, function (data){\r\n\t\tappend_chat_data(data);\t\r\n\r\n\t\tvar newIndex = data.length-1;\r\n\t\tif(typeof(data[newIndex]) != 'undefined'){\r\n\t\t\trequest_timestamp = data[newIndex].timestamp;\r\n\t\t}\r\n\t});      \r\n}<\/pre>\n<p>For the sake of simplicity, the HTML markup is assembled directly in <strong>append_chat_data()<\/strong>. The data itself is ideally passed to separate rendering functions, or a proper JavaScript template engine is used.<\/p>\n<p>However, this would go well beyond the scope of this example, which is why we are using this basic solution<\/p>\n<p>&nbsp;<\/p>\n<p>Now we define the behavior of actual GUI.<\/p>\n<pre class=\"lang:js decode:true \">$('#submit').click(function (e) {\r\n\te.preventDefault();\r\n\t\r\n\tvar $field = $('#message');\r\n\tvar data = $field.val();\r\n\r\n\t$field.addClass('disabled').attr('disabled', 'disabled');\r\n\tsendChat(data, function (){\r\n\t\t$field.val('').removeClass('disabled').removeAttr('disabled');\r\n\t});\r\n});\r\n\r\n$('#message').keyup(function (e) {\r\n\tif (e.which == 13) {\r\n\t\t$('#submit').trigger('click');\r\n\t}\r\n});\r\n\r\nsetInterval(function (){\r\n\tupdate_chats();\r\n}, 1500);<\/pre>\n<p>This code makes it possible to send messages directly by clicking on the Enter button and disables the field until the message has been processed by the server. In the callback from <strong>sendChat()<\/strong>, this field is enabled again.<\/p>\n<p>To ensure all messages are received nearly in real-time, the function <strong>update_chats()<\/strong> is called in 1.5 second intervals. The function uses the respective timestamp to check whether there are new messages and adds them to the chat window if any are available.<\/p>\n<p>&nbsp;<\/p>\n<h2>Conclusion<\/h2>\n<p>The type of chat integration presented in this example generates numerous server requests and therefore a relatively high server load for the database.<\/p>\n<p>For larger websites, it would be advisable to opt for an appropriate infrastructure, i.e. select a suitable chat protocol (e.g. XMPP) and then select an appropriate integration option.<\/p>\n<p>This example is intended for learning purposes, but can still be implemented for smaller-scale websites that see less traffic.<\/p>\n<p>&nbsp;<\/p>\n<p><strong>Note:<\/strong> This example requires basic knowledge of the CodeIgniter framework  (see <a href=\"https:\/\/anexia.com\/blog\/en\/quickstart-to-the-codeigniter-framework\/\">Quickstart to the CodeIgniter framework<\/a>) and uses uses certain open source code snippets from  <a href=\"http:\/\/bootswatch.com\/\" target=\"_blank\" rel=\"noopener\">Bootswatch.com<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Everyone is familiar with it, or has at least seen it before \u2013 we&#8217;re talking about the online chat feature available on many websites like Facebook.<\/p>\n","protected":false},"author":15,"featured_media":515,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1135],"tags":[1985,1657,1819,1987,1989,1991,1329,1614,1570],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v22.2 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Setting up your own online chat module with CodeIgniter - ANEXIA Blog<\/title>\n<meta name=\"description\" content=\"Everyone is familiar with it, or has at least seen it before \u2013 we&#039;re talking about the online chat feature available on many websites like Facebook.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/anexia.com\/blog\/en\/setting-up-your-own-online-chat-module-with-codeigniter\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Setting up your own online chat module with CodeIgniter - ANEXIA Blog\" \/>\n<meta property=\"og:description\" content=\"Everyone is familiar with it, or has at least seen it before \u2013 we&#039;re talking about the online chat feature available on many websites like Facebook.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/anexia.com\/blog\/en\/setting-up-your-own-online-chat-module-with-codeigniter\/\" \/>\n<meta property=\"og:site_name\" content=\"ANEXIA Blog\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/anexiagmbh\/\" \/>\n<meta property=\"article:published_time\" content=\"2015-11-05T08:18:51+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2022-04-22T07:30:45+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/anexia.com\/blog\/wp-content\/uploads\/2015\/01\/Manuel-Wutte_anexia-blau_web.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1600\" \/>\n\t<meta property=\"og:image:height\" content=\"1067\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Manuel Wutte\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@_ANEXIA\" \/>\n<meta name=\"twitter:site\" content=\"@_ANEXIA\" \/>\n<meta name=\"twitter:label1\" content=\"Verfasst von\" \/>\n\t<meta name=\"twitter:data1\" content=\"Manuel Wutte\" \/>\n\t<meta name=\"twitter:label2\" content=\"Gesch\u00e4tzte Lesezeit\" \/>\n\t<meta name=\"twitter:data2\" content=\"12\u00a0Minuten\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/anexia.com\/blog\/en\/setting-up-your-own-online-chat-module-with-codeigniter\/\",\"url\":\"https:\/\/anexia.com\/blog\/en\/setting-up-your-own-online-chat-module-with-codeigniter\/\",\"name\":\"Setting up your own online chat module with CodeIgniter - ANEXIA Blog\",\"isPartOf\":{\"@id\":\"https:\/\/anexia.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/anexia.com\/blog\/en\/setting-up-your-own-online-chat-module-with-codeigniter\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/anexia.com\/blog\/en\/setting-up-your-own-online-chat-module-with-codeigniter\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/anexia.com\/blog\/wp-content\/uploads\/2015\/01\/Manuel-Wutte_anexia-blau_web.jpg\",\"datePublished\":\"2015-11-05T08:18:51+00:00\",\"dateModified\":\"2022-04-22T07:30:45+00:00\",\"author\":{\"@id\":\"https:\/\/anexia.com\/blog\/#\/schema\/person\/926f6b9e5aeed88b145cf86d87fd09de\"},\"description\":\"Everyone is familiar with it, or has at least seen it before \u2013 we're talking about the online chat feature available on many websites like Facebook.\",\"breadcrumb\":{\"@id\":\"https:\/\/anexia.com\/blog\/en\/setting-up-your-own-online-chat-module-with-codeigniter\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/anexia.com\/blog\/en\/setting-up-your-own-online-chat-module-with-codeigniter\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\/\/anexia.com\/blog\/en\/setting-up-your-own-online-chat-module-with-codeigniter\/#primaryimage\",\"url\":\"https:\/\/anexia.com\/blog\/wp-content\/uploads\/2015\/01\/Manuel-Wutte_anexia-blau_web.jpg\",\"contentUrl\":\"https:\/\/anexia.com\/blog\/wp-content\/uploads\/2015\/01\/Manuel-Wutte_anexia-blau_web.jpg\",\"width\":1600,\"height\":1067},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/anexia.com\/blog\/en\/setting-up-your-own-online-chat-module-with-codeigniter\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/anexia.com\/blog\/de\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Setting up your own online chat module with CodeIgniter\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/anexia.com\/blog\/#website\",\"url\":\"https:\/\/anexia.com\/blog\/\",\"name\":\"ANEXIA Blog\",\"description\":\"[:de] ANEXIA Blog - Technischen Themen, Anexia News und Insights [:]\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/anexia.com\/blog\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"de\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/anexia.com\/blog\/#\/schema\/person\/926f6b9e5aeed88b145cf86d87fd09de\",\"name\":\"Manuel Wutte\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\/\/anexia.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/9528a61f48f4294cd5f7cd8a4141bd55?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/9528a61f48f4294cd5f7cd8a4141bd55?s=96&d=mm&r=g\",\"caption\":\"Manuel Wutte\"},\"url\":\"https:\/\/anexia.com\/blog\/author\/mwu\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Setting up your own online chat module with CodeIgniter - ANEXIA Blog","description":"Everyone is familiar with it, or has at least seen it before \u2013 we're talking about the online chat feature available on many websites like Facebook.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/anexia.com\/blog\/en\/setting-up-your-own-online-chat-module-with-codeigniter\/","og_locale":"de_DE","og_type":"article","og_title":"Setting up your own online chat module with CodeIgniter - ANEXIA Blog","og_description":"Everyone is familiar with it, or has at least seen it before \u2013 we're talking about the online chat feature available on many websites like Facebook.","og_url":"https:\/\/anexia.com\/blog\/en\/setting-up-your-own-online-chat-module-with-codeigniter\/","og_site_name":"ANEXIA Blog","article_publisher":"https:\/\/www.facebook.com\/anexiagmbh\/","article_published_time":"2015-11-05T08:18:51+00:00","article_modified_time":"2022-04-22T07:30:45+00:00","og_image":[{"width":1600,"height":1067,"url":"https:\/\/anexia.com\/blog\/wp-content\/uploads\/2015\/01\/Manuel-Wutte_anexia-blau_web.jpg","type":"image\/jpeg"}],"author":"Manuel Wutte","twitter_card":"summary_large_image","twitter_creator":"@_ANEXIA","twitter_site":"@_ANEXIA","twitter_misc":{"Verfasst von":"Manuel Wutte","Gesch\u00e4tzte Lesezeit":"12\u00a0Minuten"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/anexia.com\/blog\/en\/setting-up-your-own-online-chat-module-with-codeigniter\/","url":"https:\/\/anexia.com\/blog\/en\/setting-up-your-own-online-chat-module-with-codeigniter\/","name":"Setting up your own online chat module with CodeIgniter - ANEXIA Blog","isPartOf":{"@id":"https:\/\/anexia.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/anexia.com\/blog\/en\/setting-up-your-own-online-chat-module-with-codeigniter\/#primaryimage"},"image":{"@id":"https:\/\/anexia.com\/blog\/en\/setting-up-your-own-online-chat-module-with-codeigniter\/#primaryimage"},"thumbnailUrl":"https:\/\/anexia.com\/blog\/wp-content\/uploads\/2015\/01\/Manuel-Wutte_anexia-blau_web.jpg","datePublished":"2015-11-05T08:18:51+00:00","dateModified":"2022-04-22T07:30:45+00:00","author":{"@id":"https:\/\/anexia.com\/blog\/#\/schema\/person\/926f6b9e5aeed88b145cf86d87fd09de"},"description":"Everyone is familiar with it, or has at least seen it before \u2013 we're talking about the online chat feature available on many websites like Facebook.","breadcrumb":{"@id":"https:\/\/anexia.com\/blog\/en\/setting-up-your-own-online-chat-module-with-codeigniter\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/anexia.com\/blog\/en\/setting-up-your-own-online-chat-module-with-codeigniter\/"]}]},{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/anexia.com\/blog\/en\/setting-up-your-own-online-chat-module-with-codeigniter\/#primaryimage","url":"https:\/\/anexia.com\/blog\/wp-content\/uploads\/2015\/01\/Manuel-Wutte_anexia-blau_web.jpg","contentUrl":"https:\/\/anexia.com\/blog\/wp-content\/uploads\/2015\/01\/Manuel-Wutte_anexia-blau_web.jpg","width":1600,"height":1067},{"@type":"BreadcrumbList","@id":"https:\/\/anexia.com\/blog\/en\/setting-up-your-own-online-chat-module-with-codeigniter\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/anexia.com\/blog\/de\/"},{"@type":"ListItem","position":2,"name":"Setting up your own online chat module with CodeIgniter"}]},{"@type":"WebSite","@id":"https:\/\/anexia.com\/blog\/#website","url":"https:\/\/anexia.com\/blog\/","name":"ANEXIA Blog","description":"[:de] ANEXIA Blog - Technischen Themen, Anexia News und Insights [:]","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/anexia.com\/blog\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"de"},{"@type":"Person","@id":"https:\/\/anexia.com\/blog\/#\/schema\/person\/926f6b9e5aeed88b145cf86d87fd09de","name":"Manuel Wutte","image":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/anexia.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/9528a61f48f4294cd5f7cd8a4141bd55?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/9528a61f48f4294cd5f7cd8a4141bd55?s=96&d=mm&r=g","caption":"Manuel Wutte"},"url":"https:\/\/anexia.com\/blog\/author\/mwu\/"}]}},"lang":"en","translations":{"en":6970,"de":1111},"amp_enabled":true,"pll_sync_post":[],"_links":{"self":[{"href":"https:\/\/anexia.com\/blog\/wp-json\/wp\/v2\/posts\/6970"}],"collection":[{"href":"https:\/\/anexia.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/anexia.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/anexia.com\/blog\/wp-json\/wp\/v2\/users\/15"}],"replies":[{"embeddable":true,"href":"https:\/\/anexia.com\/blog\/wp-json\/wp\/v2\/comments?post=6970"}],"version-history":[{"count":1,"href":"https:\/\/anexia.com\/blog\/wp-json\/wp\/v2\/posts\/6970\/revisions"}],"predecessor-version":[{"id":6973,"href":"https:\/\/anexia.com\/blog\/wp-json\/wp\/v2\/posts\/6970\/revisions\/6973"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/anexia.com\/blog\/wp-json\/wp\/v2\/media\/515"}],"wp:attachment":[{"href":"https:\/\/anexia.com\/blog\/wp-json\/wp\/v2\/media?parent=6970"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/anexia.com\/blog\/wp-json\/wp\/v2\/categories?post=6970"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/anexia.com\/blog\/wp-json\/wp\/v2\/tags?post=6970"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}