お絵かきちゃんチャット
好きを仕事に生きていく
初めてでもできるイラスト起業の秘密
6問の質問に答えてプレゼントを受け取ってください
`; formDiv.appendChild(formContent); chatMessages.appendChild(formDiv); // フォームのバリデーション機能を追加 setupFormValidation(); // スクロールを最下部に chatMessages.scrollTop = chatMessages.scrollHeight; } // フォームバリデーション機能 function setupFormValidation() { const form = document.getElementById('UserItemForm'); const emailInput = document.getElementById('Usermail'); if (form) { form.addEventListener('submit', function(e) { let isValid = true; // メールアドレスのバリデーション if (!emailInput.value || !validateEmail(emailInput.value)) { emailInput.style.border = '1px solid red'; isValid = false; } else { emailInput.style.border = '1px solid #ccc'; } if (!isValid) { e.preventDefault(); } }); } } // メールアドレスバリデーション関数 function validateEmail(email) { const re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; return re.test(String(email).toLowerCase()); } const chatMessages = document.getElementById('chatMessages'); let typingIndicator; // タイピングインジケータをすべて削除する関数 function removeAllTypingIndicators() { const oldTypingIndicators = document.querySelectorAll('.typing'); oldTypingIndicators.forEach(indicator => { indicator.remove(); }); } // タイピングインジケータを表示する関数 function showTypingIndicator() { const newTypingIndicator = window.typingIndicator.cloneNode(true); chatMessages.appendChild(newTypingIndicator); newTypingIndicator.style.display = 'block'; chatMessages.scrollTop = chatMessages.scrollHeight; return newTypingIndicator; } // チャットを表示する関数 function displayChat(scene) { // シーン開始時に古いタイピングインジケータをクリーンアップ removeAllTypingIndicators(); const messages = chatData[scene].messages; let currentIndex = 0; function displayNextMessage() { if (currentIndex >= messages.length) return; const message = messages[currentIndex]; // タイピングインジケータを正しい位置に配置して表示 const currentTyping = showTypingIndicator(); chatMessages.scrollTop = chatMessages.scrollHeight; // 指定された時間後にメッセージを表示 let typingTime = currentIndex === 0 ? 1000 : (currentIndex === 1 ? 1000 : 3000); setTimeout(() => { // タイピングインジケータを非表示 removeAllTypingIndicators(); // メッセージ要素を作成 const messageDiv = document.createElement('div'); messageDiv.classList.add('message', message.type); const contentDiv = document.createElement('div'); contentDiv.classList.add('message-content'); contentDiv.innerHTML = message.content; messageDiv.appendChild(contentDiv); chatMessages.appendChild(messageDiv); chatMessages.scrollTop = chatMessages.scrollHeight; // 選択肢ボタンがあれば表示 if (message.options) { // ボタン要素を作成 const buttonsDiv = document.createElement('div'); buttonsDiv.classList.add('option-buttons'); message.options.forEach((option) => { const button = document.createElement('button'); button.classList.add('option-button'); button.textContent = option.text; button.onclick = () => { // ボタンを無効化して選択されたもの以外を非表示にする message.options.forEach((opt, idx) => { const btns = document.querySelectorAll('.option-button'); btns.forEach((btn, btnIdx) => { if (btnIdx === idx && btn.textContent === option.text) { // 選択されたボタンは無効化するだけ btn.disabled = true; btn.style.backgroundColor = '#e6f7ef'; } else { // 選択されなかったボタンは非表示 btn.style.display = 'none'; } }); }); // ユーザーの選択を表示 const userMessageDiv = document.createElement('div'); userMessageDiv.classList.add('message', 'user'); const userContentDiv = document.createElement('div'); userContentDiv.classList.add('message-content'); userContentDiv.textContent = option.text; userMessageDiv.appendChild(userContentDiv); chatMessages.appendChild(userMessageDiv); chatMessages.scrollTop = chatMessages.scrollHeight; // タイピングインジケータを表示してから次のシーンに進む // 既存のタイピングを削除して新しいものを追加 removeAllTypingIndicators(); const userResponseTyping = showTypingIndicator(); chatMessages.scrollTop = chatMessages.scrollHeight; // 少し待ってから次のシーンに進む setTimeout(() => { displayChat(option.next); }, 2000); // タイピングを2秒間表示 }; buttonsDiv.appendChild(button); }); // ボタンをメッセージの後に追加 messageDiv.appendChild(buttonsDiv); // アニメーション効果のため少し遅らせて表示 setTimeout(() => { buttonsDiv.classList.add('visible'); chatMessages.scrollTop = chatMessages.scrollHeight; }, 100); } // 最終メッセージの場合、バナーとフォームを表示 if (message.final) { setTimeout(() => { showBannerAndForm(); }, 1000); } // 次のメッセージへ currentIndex++; if (currentIndex < messages.length) { setTimeout(displayNextMessage, message.delay); } }, typingTime); // 「・・・」表示時間は状況に応じて変化 } // 最初のメッセージを表示 displayNextMessage(); } // ページ読み込み後にチャットを開始 window.onload = function() { // タイピングインジケータを作成 const typingDiv = document.createElement('div'); typingDiv.id = 'typing'; typingDiv.className = 'typing'; const typingAnimation = document.createElement('div'); typingAnimation.className = 'typing-animation'; for (let i = 0; i < 3; i++) { const span = document.createElement('span'); typingAnimation.appendChild(span); } typingDiv.appendChild(typingAnimation); // グローバル変数に代入 window.typingIndicator = typingDiv; // タイピングインジケータを初期化 typingIndicator = typingDiv.cloneNode(true); // チャット開始 displayChat('start'); };