-
Notifications
You must be signed in to change notification settings - Fork 39
Vanilla JavaScript messenger or how to add private messages to your app
Today almost every app requires private message system and it takes weeks to make it.
Bunny Messenger is a vanilla JavaScript (ES6) private messanger framework for browser. It allows to easily build custom messengers and style them in any way.
All what you need is a back-end app or script with JSON API to get latest messages and create new ones. Probably you already have one or using any package. With Bunny Messenger focus only on your busines and app.
There should be a way to get user authentication state from Server on client-side. For example, server can just render in response a JS variable or may be you have some component, AJAX calls for that.
Server should have 3 API methods:
- To load latest N (per page) messages between currently authenticated user and user X, for example
GET /api/messenger/read/{senderId}/{page=1} - To check and load new messages since last message, for example
GET /api/messenger/check/{senderId}/{lastMessageId} - To create new messages, for example
POST /api/messenger/create/{receiverId}/ and text as input param
Server should check for authentication itself.
First method should return data about the user (senderId) in user key and array of messages in messages key ordered by date created DESC and limited to any number per page you want, 20, for example.
{
user: {
id: 1,
name: 'Bob',
profileUrl: 'https://app.com/users/1',
photoUrl: 'https://app.com/img/users/1.jpg'
},
messages: [
{
id: 20,
message: 'Hello, world!',
dateCreated: '2016-09-02T14:21:48+00:00', // (valid W3C/ISO string which can be passed to JS new Date('date string')
senderId: 1,
receiverId: 4
},
// rest message object...
]
}Second method should return only array of messages in same format as in previous read() method but ordered by date created ASC this time!
Last POST method should return single message object and not an array:
Now any model or state with AJAX calls required on client-side.
Each model method should return a Promise.
Create any JS object with next interface:
- read(userId, page = 1)
- should return data with at least 2 keys:
userandmessagesin same format as described in Section 1.1 -
MessengerConfig.messagesPerPageshould be same as server-side per page limit, defaults to 20. - should be ordered by date created DESC
- should return data with at least 2 keys:
- create(userId, text)
- creates new message to userId with message = text and receives a single message object
- check(userId)
- checks for new messages since last message each
MessengerConfig.checkForNewMessagesIntervalseconds (defaults to 30) - should return data same as read() but ordered by date created ASC not DESC
- checks for new messages since last message each
Add attribute data-messenger="{userId} to all elements which should trigger messenger on click.
Usually they are "Send PM" buttons, profile pictures, etc.
Attribute value should be a non-empty and contain an ID for second user. If auth user and second user are the same, then attribute should not be added.
If there is DOM content loaded later and it is required to attach new events on new containers then Messenger.initToggles(container) can be used.
Create a single container for private messages with hidden attribute and ID = MessengerConfig.id ("pm" by default),
Container should have child elements:
- header with
- any element which will contain the name of the 2nd user (receiver) with ID =
MessengerConfig.idName("pm_name") - close button with ID =
MessengerConfig.idClose
- any element which will contain the name of the 2nd user (receiver) with ID =
- element with overflow Y only for messenger body (container for messages itself) with ID =
MessengerConfig.idBody - footer with form containing one textarea with ID =
MessengerConfig.idInput
Example:
<div id="pm" class="app-pm" hidden>
<header class="app-pm-header">
<span id="pm_name"></span>
<button id="pm_close" class="pull-right app-btn-reset app-s-close-bold"></button>
</header>
<div id="pm_body" class="app-pm-body">
</div>
<footer class="app-pm-footer">
<form>
<textarea id="pm_input" placeholder="Type a message..." class="app-pm-input" type="text" name="pm"></textarea>
</form>
</footer>
</div>Each message will have next markup:
<message data-id="{message.id}">
<div>
<a href="{user.profileUrl}">
<img src="{user.photoUrl}">
</a>
</div>
<p>{message.message}</p>
</message>Answers (messages sent by auth user):
- will have
<message type="answer">attribute - and will not have first child
<div>, but only<p>
Time will be added between messages within <time></time>
Finally on DOM ready initialize a Messenger with Messenger.init(Model, authCheck)
authCheck:
- represents a current auth user state,
- it should be a boolean or a result from any function or AJAX call,
- it should be TRUE if user is authenticated and only then messenger will be initialized
import { Messenger } from 'bunnyjs/src/Messenger';
import { PrivateMessage } from '../Models/PrivateMessage';
document.addEventListener('DOMContentLoaded', () => {
Messenger.init(PrivateMessage, Server.auth.check);
});