Facebook Like Chat Application using React JS, PHP and jQuery
Reading Time:
Reading Time:
The database design is pretty much same as that is used in the previous chat application.
The FbChatMock class is same as the one previously used, so there is no change in that.
This is where the chat is loaded. Remeber to pass the user_id in the url for setting the current chat user id.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Facebook Chat application using React JS, PHP and MySQL</title>
<link href="style/core.css" rel="stylesheet" type="text/css" />
</head>
<body>
<?php
@session_start();
$_SESSION['user_id'] = isset($_GET['user_id']) ? (int) $_GET['user_id'] : 0;
// Load the messages initially
require_once __DIR__ . '/../core/FbChatMock.php';
$chat = new FbChatMock();
$messages = $chat->getMessages();
?>
<!-- This is the React main render container -->
<div id="container"></div>
<!-- Load JS at bottom for performance -->
<script type="text/javascript" src="scripts/jquery-1.11.0.min.js"></script>
<script type="text/javascript" src="scripts/react.js"></script>
<script type="text/javascript" src="scripts/JSXTransformer.js"></script>
<script type="text/jsx" src="scripts/react-chat.js"></script>
</body>
</html>
The HTML is pretty much simple, because React will take care of the rest.
There are two ajax components.
<?php
require_once __DIR__ . '/../../core/FbChatMock.php';
$chat = new FbChatMock();
$messages = $chat->getMessages();
$chat_converstaion = array();
if (!empty($messages)) {
foreach ($messages as $message) {
$chat_id = (int) $message['chat_id'];
$msg = htmlentities($message['message'], ENT_NOQUOTES);
$user_name = ucfirst($message['username']);
$sent = date('F j, Y, g:i a', $message['sent_on']);
$chat_converstaion[] = array (
'username' => $user_name,
'message' => $msg,
'time' => $sent,
'id' => $chat_id
);
}
$response = json_encode($chat_converstaion);
} else {
echo '<span style="margin-left: 25px;">No chat messages available!</span>';
}
header('Content-type: application/json');
echo $response;
?>
<?php
session_start();
if (isset($_POST['msg'])) {
require_once __DIR__ . '/../../core/FbChatMock.php';
$userId = (int) $_SESSION['user_id'];
// Escape the message string
$msg = htmlentities($_POST['msg'], ENT_NOQUOTES);
$chat = new FbChatMock();
$result = $chat->addMessage($userId, $msg);
// Send back the updated messages
$messages = $chat->getMessages();
$chat_converstaion = array();
if (!empty($messages)) {
foreach ($messages as $message) {
$chat_id = (int) $message['chat_id'];
$msg = htmlentities($message['message'], ENT_NOQUOTES);
$user_name = ucfirst($message['username']);
$sent = date('F j, Y, g:i a', $message['sent_on']);
$chat_converstaion[] = array (
'username' => $user_name,
'message' => $msg,
'time' => $sent,
'id' => $chat_id
);
}
$response = json_encode($chat_converstaion);
} else {
echo '<span style="margin-left: 25px;">No chat messages available!</span>';
}
header('Content-type: application/json');
echo $response;
}
?>
This the main React js script where all the rendering of the Chat components takes place. React allows us to express the design that we make and convert them to components that is finally rendered as a web component. Below is the component structure of the Chat application.
-ChatContainer
-ChatHeader
-Messages
-Row(Loop)
-ChatFooter
/**
* This is the chat header component,
* Data inside this is static based on the browser url
*/
var ChatHeader = React.createClass({
render: function() {
// To display the username
if (/user_id=1/i.test(window.location.search)) {
name = 'John';
} else {
name = 'Scott';
}
return (
<div className="msg-wgt-header">
<a href="#">{name}</a>
</div>
);
}
});
// This is the chat row component
var Row = React.createClass({
render: function() {
return (
<div className="msg-row-container">
<div className="msg-row">
<div className="avatar"></div>
<span className="user-label">
<a href="#" className="chat-username">{this.props.username}</a> <span className="msg-time">{this.props.time}</span>
</span><br/>
{this.props.message}
</div>
</div>
);
}
});
/**
* Messages component
*/
var Messages = React.createClass({
render: function() {
// This is how you set inline styles in React
var inlineStyles = {
height: '300px',
overflowY: 'scroll'
};
// Loop through the list of chats and create array of Row components
var Rows = this.props.datas.map(function(data) {
return (
<Row key={data.id} username={data.username} time={data.time} message={data.message} />
)
});
return (
<div style={inlineStyles}>
{Rows}
</div>
);
}
});
/**
* This component contains the chat textarea
*/
var ChatFooter = React.createClass({
// Message send event handler
handleUserMessage: function(event) {
// When shift and enter key is pressed
if (event.shiftKey && event.keyCode === 13) {
var msg = this.refs.textArea.getDOMNode().value.trim();
if (msg !== '') {
// call the sendmessages of ChatContainer throught the props
this.props.sendMessage(msg);
}
// Prevent default and clear the textarea
event.preventDefault();
this.refs.textArea.getDOMNode().value = null;
}
},
render: function() {
return (
<div className="msg-wgt-footer">
<textarea id="chatMsg" ref="textArea" onKeyDown={this.handleUserMessage} placeholder="Type your message. Press shift + Enter to send" />
</div>
);
}
});
var ChatContainer = React.createClass({
// Load the initial chats
getInitialState: function() {
return {datas: []};
},
// Get's the list of messages from the server and set's the state,
// so that it re-renders the Messages
getMessages: function() {
$.ajax({
url: 'ajax/get_messages.php',
dataType: 'json',
success: function(data) {
this.setState({datas: data});
}.bind(this)
});
},
// Will add a new message and update the messages list
sendMessage: function(message) {
var that = this;
$.ajax({
url: 'ajax/add_msg.php',
method: 'post',
dataType: 'json',
data: {msg: message},
success: function(data) {
this.setState({datas: data});
}.bind(this)
});
},
componentDidMount: function() {
// get the list of messages
this.getMessages();
// set the poll interval
setInterval(this.getMessages, 5000);
},
render: function() {
return (
<div className="chat-container">
<ChatHeader />
<Messages datas={this.state.datas} />
<ChatFooter sendMessage={this.sendMessage} />
</div>
);
}
});
// React entry point
React.render(
<ChatContainer />,
document.getElementById('container')
);
.chat-container {
bottom: 0px;
width: 250px;
position: fixed;
z-index: 300;
right: 50px;
border-top-right-radius: 3px;
border-top-left-radius: 3px;
font-family: 'tahoma';
font-size: 12px;
border: 1px solid lightgray;
}
/* message box header styles*/
.msg-wgt-header {
background-color: #6D84B4;
border: 1px solid rgba(67, 106, 187, 0.76);
border-top-right-radius: 3px;
border-top-left-radius: 3px;
color: white;
text-align: center;
height: 28px;
}
.msg-wgt-header a {
text-decoration: none;
font-weight: bold;
color: white;
vertical-align: middle;
}
/* message box body styles*/
.msg-row-container {
border-bottom: 1px solid lightgray;
}
.msg-row {
width: 100%;
display: inline-block;
}
.message {
margin-left: 40px;
}
/* Message box footer styles*/
.msg-wgt-footer {
height: 42px;
}
.msg-wgt-footer textarea {
width: 95%;
font-family: 'tahoma';
font-size: 13px;
padding: 5px;
}
.user-label {
font-size: 11px;
}
.chat-username {
color: '#6D84B4';
}
.msg-time {
font-size: 10px;
float: right;
color: gray;
}
.avatar {
width: 30px;
height: 30px;
float: left;
background: url('/chat/public/assets/chat_avatar.png');
border: 1px solid lightgray;
}
If you have any queries leave a comment and subscribe to get more of updates like this.