0
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

JSでWebページのレスポンス待機メッセージを表示/非表示する

Last updated at Posted at 2024-01-10

はじめに

前回、ChatGPTをSpringアプリケーションに組み込みました。しかし、ChatGPTのレスポンスを待機する間、ユーザーは待機中であることを認識しづらいという問題がありました。

そこで、JavaScriptを使って待機メッセージを表示/非表示させてみました。

やりたいこと

主な処理の流れは、次の通りです。

  1. ボタンをクリックすると、待機メッセージ「考え中…」が表示される(画像①)
    ※このとき、過去のレスポンスは消える。
  2. レスポンスを受信すると、待機メッセージは消え、レスポンスが表示される(画像②)

▼ フォームに入力し、ボタンクリックした後(①)
画像①

▼ レスポンスを受信した後(②)
画像②

実装方針

  • HTML上に、待機メッセージ要素レスポンス要素を用意します。
  • 要素が特定のクラスを持つ場合、非表示にします。非表示の処理はCSSで実装します。
  • 要素へのクラスの追加・削除は、イベント発生時に行います。JSで実装します。

これらをまとめると、処理フローは次のようになります。

ボタンクリック レスポンス受信
待機メッセージ要素 表示 非表示
レスポンス要素 非表示 表示

上の表に、適切なイベントとクラス名・ID名を指定します。

clickイベント loadイベント
待機メッセージ要素(id="wait”, class="message”) loadedクラス削除 表示 loadedクラス追加 #wait.loadedは非表示
レスポンス要素(id=”resp”, class="message”) loadedクラス削除 #resp:not(.loaded)は非表示 loadedクラス追加 表示
  • :not(クラス名)を使用することで、特定のクラス名を含まない場合を指定しています。詳細はこちらをご確認ください。

実装する

実装方針に従い、実装したコードを以下に示します。

1.HTML

2つの要素を記述します。(サーバからレスポンスを受信するためにThymeleafを使用していますが、本記事とは直接的な関係が無い為、説明は省略します。)

<!-- 待機メッセージ要素 -->
<p class="message" id="wait">考え中…</p>
<!-- レスポンス -->
<p class="message" id="resp" th:if="${apiMessage != null}" nl2br:text="${apiMessage}"></p>

2.JavaScript

2つのイベントに対する処理を記述します。2要素に対するクラスの追加・削除操作は、forEach文で行います。

// ボタンクリックイベント
var button = document.getElementById("button");
button.addEventListener('click', () => {
	// 2要素を取得する
	var message = document.querySelectorAll(".message");
	message.forEach(element => {
		// それぞれの要素に対してloadedクラスを削除
		element.classList.remove('loaded');
	});
});

// ロードイベント
window.addEventListener('load', () => {
	// 2要素を取得する
	var message = document.querySelectorAll(".message");
	message.forEach(element => {
		// それぞれの要素に対してloadedクラスを追加
		element.classList.add('loaded');
	});
});

3.CSS

要素を非表示にする処理を記述します。
上述の表をもとに、非表示の場合のクラス名・ID名をセレクタに指定します。

#wait.loaded,
#resp:not(.loaded) {
	display: none; /* 非表示 */
}

以上が、JavaScriptを使った待機メッセージ表示処理のコードです。

コード全体

前回紹介したWebアプリケーションに、本記事の内容を追加したコードを示します。

form.html
form.html
    <!DOCTYPE html>
    <html lang="ja" xmlns:th="http://www.thymeleaf.org" xmlns:nl2br="https://github.com/bufferings/thymeleaf-extras-nl2br">
    <head><!-- 省略 --></head>
    <body>
    	<div class="container">
    		<h1 class="m-5">ChatGPT API Demo</h1>
    
    		<form th:action="@{/chat}" method="post" class="form-floating m-5">
    			<textarea class="form-control" id="userMessage" name="userMessage" style="height: 100px"></textarea>
    			<label for="userMessage">Enter your message</label>
    			<button type="submit" class="btn btn-outline-primary mt-3" id="button">Generate Response</button>
    		</form>
    
    		<div class="m-5 p-3 bg-light rounded">
    			<h2 class="m-3">ChatGPT Response</h2>
    			<!-- 待機中 -->
    			<p class="m-3 message" id="wait">考え中…</p>
    			<!-- レスポンス -->
    			<p class="m-3 message" id="resp" th:if="${apiMessage != null}" nl2br:text="${apiMessage}"></p>
    		</div>
    	</div>
    
    	<style>
    		#wait.loaded,
    		#resp:not(.loaded) {
    			display: none; /* 非表示 */
    		}
    	</style>
    
    	<script>
    		var button = document.getElementById("button");
    		button.addEventListener('click', () => {
    			var message = document.querySelectorAll(".message");
    			message.forEach(element => {
    				element.classList.remove('loaded');
    			});
    		});
    
    		window.addEventListener('load', () => {
    			var message = document.querySelectorAll(".message");
    			message.forEach(element => {
    				element.classList.add('loaded');
    			});
    		});
    	</script>
    </body>
    </html>

【追記】戻るボタンを押すとどうなる?

※コメントを頂戴しましたので、追記させていだたきます!

レスポンス後(画像③)に戻るボタンを押した場合、「Generate Response」クリック前の画面に戻ります。(画像④)
待機メッセージは非表示、レスポンスは(前回の内容を)表示となっています。
※ただし、前回のレスポンスが存在しない場合は、表示されません。

▼ 「戻るボタン」クリック前(③)
画像③

▼「戻るボタン」クリック後(④)
画像④

戻るボタンを押すと、loadイベントが発生する為、各要素の表示状態はレスポンス後と同じになるようです。

今回の目的である「JSを使ってレスポンス待機メッセージを表示/非表示する」という点において、戻るボタン押下後は待機中では無い為、待機メッセージは非表示であるべきです。
よって、上記の画面表示に問題はないと考えています。
(とはいえ、戻るボタンについてはすっかり失念しておりましたので、今後は注意を払いたいです。)

おわりに

JavaScriptを使って待機メッセージの表示・非表示を管理することができました。
これにより、「ユーザーは待機中であることを認識しづらい」という問題を解決することができたかと思います。

お読みいただきありがとうございました。この記事が誰かのお役に立てることを祈っております。

今後、Ajaxを使った実装も試してみる予定です。(2024/01/11追記)

参考文献

0
3
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?