UNPKG

livechat-widget

Version:

LiveChat Widget for Next.js applications

233 lines (197 loc) 6.44 kB
/** * LiveChat Widget Loader * * This script allows for easy integration of the LiveChat Widget into any website. * Usage: * 1. Include this script in your website * 2. Initialize with: LiveChatWidget.init({ roomCode: 'YOUR_ROOM_CODE', appId: 'YOUR_APP_ID' }) */ (function(window) { 'use strict'; // Configuration defaults const DEFAULT_CONFIG = { roomName: 'Chat Room', theme: 'light', position: 'bottom-right', width: '350px', height: '500px', buttonText: 'Chat with us', buttonIcon: '💬', zIndex: 9999 }; // Main LiveChatWidget object const LiveChatWidget = { config: {}, widgetFrame: null, widgetButton: null, isOpen: false, /** * Initialize the LiveChat Widget * @param {Object} userConfig - User configuration */ init: function(userConfig) { // Validate required parameters if (!userConfig.roomCode || !userConfig.appId) { console.error('LiveChatWidget: roomCode and appId are required parameters'); return; } // Merge default config with user config this.config = { ...DEFAULT_CONFIG, ...userConfig }; // Create widget elements this._createWidgetButton(); this._createWidgetFrame(); // Add event listeners this._setupEventListeners(); // Log initialization console.log('LiveChatWidget: Initialized successfully'); }, /** * Create the chat button element */ _createWidgetButton: function() { const button = document.createElement('div'); button.id = 'livechat-widget-button'; button.innerHTML = ` <span class="icon">${this.config.buttonIcon}</span> <span class="text">${this.config.buttonText}</span> `; // Apply styles Object.assign(button.style, { position: 'fixed', zIndex: this.config.zIndex, cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center', padding: '12px 20px', borderRadius: '30px', backgroundColor: '#4a90e2', color: 'white', boxShadow: '0 2px 12px rgba(0, 0, 0, 0.15)', transition: 'all 0.3s ease', fontFamily: 'Arial, sans-serif', fontSize: '14px', fontWeight: 'bold' }); // Position the button based on config this._positionElement(button); // Add to DOM document.body.appendChild(button); this.widgetButton = button; }, /** * Create the chat frame element */ _createWidgetFrame: function() { const frame = document.createElement('iframe'); frame.id = 'livechat-widget-frame'; // Build the widget URL with parameters const widgetUrl = new URL('/widget', window.location.origin); widgetUrl.searchParams.append('roomCode', this.config.roomCode); widgetUrl.searchParams.append('appId', this.config.appId); widgetUrl.searchParams.append('roomName', this.config.roomName); widgetUrl.searchParams.append('theme', this.config.theme); frame.src = widgetUrl.toString(); // Apply styles Object.assign(frame.style, { position: 'fixed', zIndex: this.config.zIndex, width: this.config.width, height: this.config.height, border: 'none', borderRadius: '10px', boxShadow: '0 5px 40px rgba(0, 0, 0, 0.16)', display: 'none', transition: 'all 0.3s ease' }); // Position the frame based on config this._positionElement(frame); // Add to DOM document.body.appendChild(frame); this.widgetFrame = frame; }, /** * Position an element based on the config position * @param {HTMLElement} element - Element to position */ _positionElement: function(element) { const positions = this.config.position.split('-'); const vertical = positions[0]; // 'top' or 'bottom' const horizontal = positions[1]; // 'left' or 'right' // Set vertical position if (vertical === 'top') { element.style.top = '20px'; } else { element.style.bottom = '20px'; } // Set horizontal position if (horizontal === 'left') { element.style.left = '20px'; } else { element.style.right = '20px'; } }, /** * Set up event listeners */ _setupEventListeners: function() { // Toggle widget visibility when button is clicked this.widgetButton.addEventListener('click', () => { this.toggle(); }); // Handle messages from the widget iframe window.addEventListener('message', (event) => { // Only process messages from our widget if (event.source !== this.widgetFrame.contentWindow) return; const { type } = event.data; switch (type) { case 'widget:close': this.close(); break; case 'widget:ready': console.log('LiveChatWidget: Widget is ready'); break; // Add more message handlers as needed } }); }, /** * Toggle the widget visibility */ toggle: function() { if (this.isOpen) { this.close(); } else { this.open(); } }, /** * Open the widget */ open: function() { if (this.isOpen) return; this.widgetFrame.style.display = 'block'; // Trigger a small delay before adding the visible class for animation setTimeout(() => { this.widgetFrame.style.opacity = '1'; this.widgetButton.style.opacity = '0.7'; }, 10); this.isOpen = true; }, /** * Close the widget */ close: function() { if (!this.isOpen) return; this.widgetFrame.style.opacity = '0'; this.widgetButton.style.opacity = '1'; // Hide the frame after transition completes setTimeout(() => { this.widgetFrame.style.display = 'none'; }, 300); this.isOpen = false; } }; // Expose to window window.LiveChatWidget = LiveChatWidget; })(window);