InputManJS コメントコンポーネント(GcComment)を導入する
最初に、コメントコンポーネント(GcComment)の導入方法を紹介します。
まずはクライアント側、HTMLのコードを見ていきましょう。
index.htmlの<head>と<body>部分は以下のようになっています。
<head>
<link href="https://cdn.mescius.com/inputmanjs/hosted/comment/css/gc.inputman.comment.css" rel="stylesheet">
<script src="https://cdn.mescius.com/inputmanjs/hosted/comment/scripts/gc.inputman.comment.ja.js"></script>
<script src="assets/socket.io.js"></script>
<script src="client/loader.js"></script>
</head>
<body>
<div style="padding: 20px; background-color: #f5f5f5; border-bottom: 1px solid #ddd;">
<label for="userSelect">ユーザー選択:</label>
<select id="userSelect">
<option value="0">架空 太郎</option>
<option value="1">電信 次郎</option>
</select>
</div>
<div id="gcComment"></div>
</body>
前述のように、今回はCDN版のInputManJSを利用しています。head内でCSSとJavaScriptを読み込むことで、GcCommentのスタイルと機能が利用可能になります。
server.js側で/assetsをnode_modules/socket.io/client-distにマッピングしているため、ブラウザからは<script src="assets/socket.io.js">と書くだけでローカルのSocket.IOクライアントを取得できます。
client/loader.jsは、DOMContentLoaded後にclient/comment-chat.jsを差し込むローダーで、index.htmlのどこに置いても安全に初期化できるようにしています。
body内ではセレクトボックスでユーザーを切り替えられるようにしています。その下の<div id="gcComment"></div>がコメントコンポーネントの挿入先です。
GcCommentを初期化する
次に、このGcCommentの初期化コードを見ていきましょう。client/comment-chat.jsの内容から、重要な部分を抜粋します。
const socket = io();
const { GcComment, GcCommentMode, GcCommentEditorPosition, GcCommentCommand } = GC.InputMan;
この部分でSocket.IOクライアントを初期化し、InputManJSのGcComment関連のクラスや定数を取得しています。これによって、コメントコンポーネントの操作が可能になります。
次にsocketの接続完了イベントでinitializeComment()を呼び出します。
socket.on("connect", () => {
initializeComment();
});
WebSocketの接続が確立したタイミングでコメントコンポーネントを初期化します。これにより、socket.idが利用可能な状態でGcCommentをセットアップできます。
このsocket.idはサーバー側で「送信者以外」にイベントをブロードキャストするために重要な役割を果たします。詳しくは後述します。
それでは、initializeComment()関数の中身を見てみましょう。
function initializeComment() {
const userInfo = usersMap[currentUserId];
if (gcComment) {
gcCommentContainer.innerHTML = "";
}
gcComment = new GcComment(gcCommentContainer, {
commentMode: GcCommentMode.ChatMode,
dataSource: {
enabled: true,
remote: {
comments: {
read: { url: commentURL },
create: { url: commentURL, requestData: { socketId: socket.id } },
update: { url: commentURL, requestData: { socketId: socket.id } },
delete: { url: commentURL, requestData: { socketId: socket.id } },
},
users: {
read: { url: userURL },
},
reactions: {
read: { url: reactionURL },
create: { url: reactionURL, requestData: { socketId: socket.id } },
delete: { url: reactionURL, requestData: { socketId: socket.id } },
},
},
},
addCommentEditorPosition: GcCommentEditorPosition.Top,
userInfo,
});
}
このコードでは適宜クリーンアップを行った後、GcCommentコンポーネントを生成しています。また、設定オブジェクトとして、以下のようなプロパティを指定しています。
-
commentMode:表示モードを指定します。 -
dataSource:コメントやユーザー、リアクションを取得・更新するAPIエンドポイントを定義します。 -
addCommentEditorPosition:コメント入力欄の表示位置を指定します。 -
userInfo:現在操作しているユーザー情報を指定します。
着目すべきはdataSource.remoteの部分です。ここで各種APIエンドポイントを指定することで、GcCommentが内部的にHTTPリクエストを送信できるようになります。Read, Create, Update, DeleteのCRUD操作に対応したURLを設定することができ、さらにrequestDataでsocket.idを渡すことで、サーバー側で送信者を識別できるようにしています。
今回はコメント、ユーザー、リアクションの3つのデータソースを設定しています。 これにより、GcCommentは自動的にAPIと連携し、コメントの取得・投稿・編集・削除やリアクションの管理を行います。
(※各プロパティの詳細は、InputManJSのコメントコンポーネントに関する公式ドキュメントもご参照ください)
例えばユーザーがコメントを書いて送信ボタンを押すと、次のようなPOSTリクエスト(payload)が送信されます(ChromeのDevToolsのNetworkタブで確認可能です)。
POST /comments
{
"content": "こんにちは!",
"userId": "1",
"parentId": "0123456789012",
"socketId": "abc123def456"
}
parentIdとは、返信先コメントのIDです。もし、特定のコメントに返信した場合はそのIDが入ります。このあたりもGcCommentが自動的に処理してくれます。あとはこのリクエストをサーバー側で受け取り、SQLiteに保存した後、Socket.IOで他のクライアントに通知する流れになります。
InputManJSを使うことで、可読性の高いコードを書きつつ、コメントUIを簡単に構築できました。

