$1')
// Handle bold
.replace(/\*\*([^*]+)\*\*/g, '
$1')
// Handle line breaks (but not inside HTML tags)
.replace(/\n(?![^<]*>)/g, '
');
}
// Regular markdown formatting for text-only messages
try {
return message
// Handle links
.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '
$1')
// Handle bold
.replace(/\*\*([^*]+)\*\*/g, '
$1')
// Handle headings
.replace(/^### (.*$)/gm, '')
.replace(/^## (.*$)/gm, '')
// Handle emphasis
.replace(/\*([^*]+)\*/g, '
$1')
// Handle lists
.replace(/^\s*-\s+(.+)$/gm, '
$1')
// Wrap lists
.replace(/(
.+<\/li>\s*)+/g, '')
// Handle line breaks
.replace(/\n/g, '
');
} catch (e) {
console.error('Error formatting message:', e);
return message; // Return original message if formatting fails
}
}
function addMessage(type, content) {
const messageEl = document.createElement('div');
messageEl.className = `tta-message tta-message-${type === 'user' ? 'user' : 'bot'}`;
messageEl.id = 'msg-' + Date.now();
// Set content based on type (HTML for bot, text for user)
if (type === 'bot') {
messageEl.innerHTML = content;
} else {
messageEl.textContent = content;
}
messages.appendChild(messageEl);
scrollToBottom();
return messageEl.id;
}
function addTypingIndicator() {
const typingId = 'typing-' + Date.now();
const typingEl = document.createElement('div');
typingEl.id = typingId;
typingEl.className = 'tta-message tta-message-bot';
typingEl.innerHTML = '
';
messages.appendChild(typingEl);
scrollToBottom();
return typingId;
}
function removeElement(id) {
const el = document.getElementById(id);
if (el) el.remove();
}
function scrollToBottom() {
messages.scrollTop = messages.scrollHeight;
}
function toggleChat() {
if (state.isOpen) {
hideChat();
} else {
showChat();
}
}
function showChat() {
chatWidget.style.display = 'flex';
chatWidget.setAttribute('aria-hidden', 'false');
state.isOpen = true;
chatButton.style.animation = 'none';
// **Show/Hide Login Banner based on login status**
if (config.requireLoginBanner) {
loginBanner.style.display = state.isUserLoggedIn ? 'none' : 'block';
} else {
loginBanner.style.display = 'none'; // Hide banner if disabled in config
}
// Add initial message if first time opening
if (messages.children.length === 0) {
addMessage('bot', config.welcomeMessage);
}
// Focus input
setTimeout(() => messageInput.focus(), 300);
}
function hideChat() {
chatWidget.style.display = 'none';
chatWidget.setAttribute('aria-hidden', 'true');
state.isOpen = false;
}
function toggleMinimize() {
state.isMinimized = !state.isMinimized;
chatWidget.classList.toggle('minimized', state.isMinimized);
}
function generateSessionId() {
return 'tta-' + Math.random().toString(36).substring(2, 15);
}
// Auto-resize input field based on content
messageInput.addEventListener('input', function() {
this.style.height = 'auto';
const maxHeight = 100;
const newHeight = Math.min(this.scrollHeight, maxHeight);
if (newHeight > 50) {
this.style.height = newHeight + 'px';
} else {
this.style.height = '';
}
});
// Save chat state in localStorage when window is closed
window.addEventListener('beforeunload', function() {
if (state.messageHistory.length > 0) {
try {
localStorage.setItem('tta-chat-history', JSON.stringify(state.messageHistory));
localStorage.setItem('tta-session-id', state.sessionId);
} catch (e) {
console.log('Could not save chat history', e);
}
}
});
// Restore chat state when page loads
function restoreChatState() {
try {
const savedHistory = localStorage.getItem('tta-chat-history');
const savedSessionId = localStorage.getItem('tta-session-id');
if (savedHistory && savedSessionId) {
state.messageHistory = JSON.parse(savedHistory);
state.sessionId = savedSessionId;
// Rebuild the conversation UI
state.messageHistory.forEach(msg => {
if (msg.role === 'user') {
addMessage('user', msg.content);
} else if (msg.role === 'assistant') {
addMessage('bot', formatBotMessage(msg.content));
}
});
}
} catch (e) {
console.log('Could not restore chat history', e);
}
}
// Inactivity detection
setInterval(() => {
if (state.isOpen && (Date.now() - state.lastActivity > 300000) && !state.isTyping) { // 5 minutes
addMessage('bot', "Are you still there? I'm here if you have any more questions about your test prep.");
state.lastActivity = Date.now();
}
}, 60000); // Check every minute
// Auto-resize when window is resized
window.addEventListener('resize', function() {
if (state.isOpen) {
scrollToBottom();
}
});
// Initialize any needed features based on page
function initializePageSpecificFeatures() {
// Check if we're on a skill drill test page
if (window.location.pathname.includes('/skill-drill-test-details/')) {
// Extract the test ID from the URL
const testIdMatch = window.location.pathname.match(/\/skill-drill-test-details\/(\d+)/);
if (testIdMatch && testIdMatch[1]) {
// Add test-specific suggestions
config.suggestedQuestions.unshift(
{ text: "How should I prepare for this test?", category: "test" },
{ text: "What skills does this test focus on?", category: "test" }
);
// Update the suggestions
populateSuggestions('all');
}
}
// Check if we're on a test page
if (window.location.pathname.includes('/test/') ||
window.location.pathname.includes('/tests/')) {
// Add test-specific suggestions
config.suggestedQuestions.push(
{ text: "How do I interpret this passage?", category: "test" },
{ text: "What's a good strategy for this question type?", category: "test" }
);
// Update the suggestions
populateSuggestions('all');
}
}
// Restore chat history when available
restoreChatState();
// Initialize with page-specific features
initializePageSpecificFeatures();
})();
-->