help@rskworld.in +91 93305 39277
RSK World
  • Home
  • Development
    • Web Development
    • Mobile Apps
    • Software
    • Games
    • Project
  • Technologies
    • Data Science
    • AI Development
    • Cloud Development
    • Blockchain
    • Cyber Security
    • Dev Tools
    • Testing Tools
  • Blog
  • About
  • Contact

Theme Settings

Color Scheme
Display Options
Font Size
100%
Back to Project
RSK World
weather-chatbot
/
static
RSK World
weather-chatbot
Weather Chatbot - Python + Flask + OpenWeatherMap + OpenAI + Weather Forecast + Weather Alerts + Natural Language Processing
static
  • uploads
  • robots.txt327 B
  • script.js13.4 KB
  • style.css3.3 KB
script.js
static/script.js
Raw Download
Find: Go to:
/**
 * Weather Chatbot JavaScript
 * ===========================
 *
 * Author: RSK World (https://rskworld.in)
 * Founded by: Molla Samser
 * Designer & Tester: Rima Khatun
 * Contact: +91 93305 39277, hello@rskworld.in, support@rskworld.in
 * Location: Nutanhat, Mongolkote, Purba Burdwan, West Bengal, India, 713147
 * Year: 2026
 *
 * Description: JavaScript functionality for the Weather Chatbot web interface
 */

// Global variables
let isTyping = false;
let chatHistory = [];

// Initialize on page load
document.addEventListener('DOMContentLoaded', function() {
    initializeChat();
    loadChatHistory();
    
    // Auto-focus on message input
    const messageInput = document.getElementById('messageInput');
    if (messageInput) {
        messageInput.focus();
    }
    
    // Add event listeners
    setupEventListeners();
});

/**
 * Initialize chat interface
 */
function initializeChat() {
    // Add welcome message if chat is empty
    const chatMessages = document.getElementById('chatMessages');
    if (chatMessages && chatMessages.children.length === 0) {
        addWelcomeMessage();
    }
}

/**
 * Add welcome message
 */
function addWelcomeMessage() {
    const welcomeMessage = `
        <div class="message bot-message">
            <div>👋 Hello! I'm your Weather Assistant. I can help you with:</div>
            <ul class="mb-0 mt-2">
                <li>Current weather conditions</li>
                <li>Weather forecasts</li>
                <li>Weather alerts and warnings</li>
            </ul>
            <div class="mt-2">Try asking: "What's the weather in London?"</div>
        </div>
    `;
    addMessage(welcomeMessage, 'bot', false);
}

/**
 * Setup event listeners
 */
function setupEventListeners() {
    const messageInput = document.getElementById('messageInput');
    const sendButton = document.getElementById('sendButton');
    
    if (messageInput) {
        messageInput.addEventListener('keypress', handleKeyPress);
        messageInput.addEventListener('input', handleInputChange);
    }
    
    if (sendButton) {
        sendButton.addEventListener('click', sendMessage);
    }
    
    // Window resize handler
    window.addEventListener('resize', function() {
        scrollToBottom();
    });
}

/**
 * Handle Enter key press
 */
function handleKeyPress(event) {
    if (event.key === 'Enter' && !event.shiftKey) {
        event.preventDefault();
        sendMessage();
    }
}

/**
 * Handle input change
 */
function handleInputChange(event) {
    const messageInput = event.target;
    const sendButton = document.getElementById('sendButton');
    
    if (sendButton) {
        sendButton.disabled = !messageInput.value.trim() || isTyping;
    }
}

/**
 * Send quick message from quick action buttons
 */
function sendQuickMessage(message) {
    const messageInput = document.getElementById('messageInput');
    if (messageInput) {
        messageInput.value = message;
        sendMessage();
    }
}

/**
 * Send message to server
 */
async function sendMessage() {
    const messageInput = document.getElementById('messageInput');
    const message = messageInput ? messageInput.value.trim() : '';
    
    if (!message || isTyping) return;
    
    // Add user message to chat
    addMessage(escapeHtml(message), 'user');
    messageInput.value = '';
    
    // Update send button state
    updateSendButton(false);
    
    // Show typing indicator
    showTypingIndicator();
    
    // Save to chat history
    chatHistory.push({ type: 'user', message: message });
    
    try {
        const response = await fetch('/chat', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded',
            },
            body: `message=${encodeURIComponent(message)}`
        });
        
        const data = await response.json();
        hideTypingIndicator();
        
        if (data.error) {
            addMessage(`❌ Error: ${escapeHtml(data.error)}`, 'bot');
        } else {
            addWeatherResponse(data);
            chatHistory.push({ type: 'bot', data: data });
        }
        
    } catch (error) {
        hideTypingIndicator();
        addMessage('❌ Sorry, I encountered an error. Please try again.', 'bot');
        console.error('Error:', error);
    }
    
    // Update send button state
    updateSendButton(true);
}

/**
 * Add message to chat
 */
function addMessage(message, sender, scroll = true) {
    const chatMessages = document.getElementById('chatMessages');
    if (!chatMessages) return;
    
    const messageDiv = document.createElement('div');
    messageDiv.className = `message ${sender}-message`;
    messageDiv.innerHTML = message;
    
    chatMessages.appendChild(messageDiv);
    
    if (scroll) {
        scrollToBottom();
    }
}

/**
 * Add weather response to chat
 */
function addWeatherResponse(data) {
    let message = '';
    
    if (data.city && data.temperature !== undefined) {
        // Current weather response
        message = formatCurrentWeatherResponse(data);
    } else if (data.forecasts && Array.isArray(data.forecasts)) {
        // Forecast response
        message = formatForecastResponse(data);
    } else if (data.alerts && Array.isArray(data.alerts) && data.alerts.length > 0) {
        // Alerts response
        message = formatAlertsResponse(data);
    } else if (data.has_alerts === false) {
        message = `✅ No weather alerts currently for ${escapeHtml(data.city || 'this location')}`;
    } else {
        message = `❌ Sorry, I couldn't get weather information. Please try again.`;
    }
    
    addMessage(message, 'bot');
}

/**
 * Format current weather response
 */
function formatCurrentWeatherResponse(data) {
    return `
        <div>
            <strong>🌍 ${escapeHtml(data.city)}${data.country ? ', ' + escapeHtml(data.country) : ''}</strong>
            <div class="weather-info">
                <div class="d-flex align-items-center mb-2">
                    <i class="fas fa-thermometer-half fa-2x me-3"></i>
                    <div>
                        <h3 class="mb-0">${Math.round(data.temperature)}°C</h3>
                        <small>Feels like ${Math.round(data.feels_like || data.temperature)}°C</small>
                    </div>
                </div>
                <div class="weather-details">
                    <div class="weather-detail">
                        <i class="fas fa-tint"></i>
                        <small>Humidity</small>
                        <strong>${data.humidity || 'N/A'}%</strong>
                    </div>
                    <div class="weather-detail">
                        <i class="fas fa-wind"></i>
                        <small>Wind</small>
                        <strong>${data.wind_speed || 'N/A'} m/s</strong>
                    </div>
                    <div class="weather-detail">
                        <i class="fas fa-compress-arrows-alt"></i>
                        <small>Pressure</small>
                        <strong>${data.pressure || 'N/A'} hPa</strong>
                    </div>
                    <div class="weather-detail">
                        <i class="fas fa-eye"></i>
                        <small>Visibility</small>
                        <strong>${data.visibility || 'N/A'} km</strong>
                    </div>
                </div>
                <div class="mt-2">
                    <i class="fas fa-cloud me-2"></i>
                    ${escapeHtml((data.description || 'Unknown conditions').charAt(0).toUpperCase() + (data.description || '').slice(1))}
                </div>
                ${data.timestamp ? `<div class="mt-2"><small><i class="fas fa-clock me-1"></i>${escapeHtml(data.timestamp)}</small></div>` : ''}
            </div>
        </div>
    `;
}

/**
 * Format forecast response
 */
function formatForecastResponse(data) {
    const forecasts = data.forecasts.slice(0, 8);
    const forecastItems = forecasts.map(forecast => {
        const date = new Date(forecast.datetime);
        return `
            <div class="weather-detail mb-2">
                <i class="fas fa-clock me-2"></i>
                <strong>${date.toLocaleString()}</strong>
                <div class="mt-1">
                    🌡️ ${Math.round(forecast.temperature)}°C | 
                    💧 ${forecast.humidity || 'N/A'}% | 
                    💨 ${forecast.wind_speed || 'N/A'} m/s
                </div>
                <div>${escapeHtml(forecast.description || 'No description')}</div>
            </div>
        `;
    }).join('');
    
    return `
        <div>
            <strong>🌍 ${escapeHtml(data.city)}${data.country ? ', ' + escapeHtml(data.country) : ''} - 5 Day Forecast</strong>
            <div class="weather-info">
                ${forecastItems}
            </div>
        </div>
    `;
}

/**
 * Format alerts response
 */
function formatAlertsResponse(data) {
    const alerts = data.alerts.map(alert => {
        return `
            <div class="weather-detail mb-2">
                <div class="d-flex align-items-center mb-1">
                    <i class="fas fa-exclamation-triangle me-2"></i>
                    <strong>${escapeHtml(alert.event || 'Weather Alert')}</strong>
                </div>
                ${alert.start ? `<div><small>From: ${escapeHtml(alert.start)}</small></div>` : ''}
                ${alert.end ? `<div><small>To: ${escapeHtml(alert.end)}</small></div>` : ''}
                ${alert.description ? `<div class="mt-1">${escapeHtml(alert.description)}</div>` : ''}
                ${alert.severity ? `<div class="mt-1"><small>Severity: ${escapeHtml(alert.severity)}</small></div>` : ''}
            </div>
        `;
    }).join('');
    
    return `
        <div>
            <strong>⚠️ Weather Alerts for ${escapeHtml(data.city || 'this location')}</strong>
            <div class="weather-info">
                ${alerts}
            </div>
        </div>
    `;
}

/**
 * Show typing indicator
 */
function showTypingIndicator() {
    isTyping = true;
    const typingIndicator = document.getElementById('typingIndicator');
    const sendButton = document.getElementById('sendButton');
    const loadingSpinner = document.getElementById('loadingSpinner');
    const paperPlane = document.querySelector('#sendButton .fa-paper-plane');
    
    if (typingIndicator) {
        typingIndicator.style.display = 'flex';
    }
    
    if (sendButton) {
        sendButton.disabled = true;
    }
    
    if (loadingSpinner) {
        loadingSpinner.style.display = 'block';
    }
    
    if (paperPlane) {
        paperPlane.style.display = 'none';
    }
}

/**
 * Hide typing indicator
 */
function hideTypingIndicator() {
    isTyping = false;
    const typingIndicator = document.getElementById('typingIndicator');
    const sendButton = document.getElementById('sendButton');
    const loadingSpinner = document.getElementById('loadingSpinner');
    const paperPlane = document.querySelector('#sendButton .fa-paper-plane');
    
    if (typingIndicator) {
        typingIndicator.style.display = 'none';
    }
    
    if (sendButton) {
        sendButton.disabled = false;
    }
    
    if (loadingSpinner) {
        loadingSpinner.style.display = 'none';
    }
    
    if (paperPlane) {
        paperPlane.style.display = 'block';
    }
}

/**
 * Update send button state
 */
function updateSendButton(enabled) {
    const sendButton = document.getElementById('sendButton');
    if (sendButton) {
        sendButton.disabled = !enabled;
    }
}

/**
 * Scroll to bottom of chat
 */
function scrollToBottom() {
    const chatMessages = document.getElementById('chatMessages');
    if (chatMessages) {
        chatMessages.scrollTop = chatMessages.scrollHeight;
    }
}

/**
 * Escape HTML to prevent XSS
 */
function escapeHtml(text) {
    if (!text) return '';
    const map = {
        '&': '&amp;',
        '<': '&lt;',
        '>': '&gt;',
        '"': '&quot;',
        "'": '&#039;'
    };
    return String(text).replace(/[&<>"']/g, m => map[m]);
}

/**
 * Load chat history from localStorage
 */
function loadChatHistory() {
    try {
        const saved = localStorage.getItem('weatherChatbotHistory');
        if (saved) {
            chatHistory = JSON.parse(saved);
            // Optionally restore chat history to UI
        }
    } catch (error) {
        console.error('Error loading chat history:', error);
    }
}

/**
 * Save chat history to localStorage
 */
function saveChatHistory() {
    try {
        localStorage.setItem('weatherChatbotHistory', JSON.stringify(chatHistory));
    } catch (error) {
        console.error('Error saving chat history:', error);
    }
}

/**
 * Clear chat history
 */
function clearChatHistory() {
    chatHistory = [];
    localStorage.removeItem('weatherChatbotHistory');
    const chatMessages = document.getElementById('chatMessages');
    if (chatMessages) {
        chatMessages.innerHTML = '';
        addWelcomeMessage();
    }
}

// Export functions for use in HTML
window.sendQuickMessage = sendQuickMessage;
window.sendMessage = sendMessage;
window.handleKeyPress = handleKeyPress;
window.clearChatHistory = clearChatHistory;
451 lines•13.4 KB
javascript

About RSK World

Founded by Molla Samser, with Designer & Tester Rima Khatun, RSK World is your one-stop destination for free programming resources, source code, and development tools.

Founder: Molla Samser
Designer & Tester: Rima Khatun

Development

  • Game Development
  • Web Development
  • Mobile Development
  • AI Development
  • Development Tools

Legal

  • Terms & Conditions
  • Privacy Policy
  • Disclaimer

Contact Info

Nutanhat, Mongolkote
Purba Burdwan, West Bengal
India, 713147

+91 93305 39277

hello@rskworld.in
support@rskworld.in

© 2026 RSK World. All rights reserved.

Content used for educational purposes only. View Disclaimer