livechat-widget
Version:
LiveChat Widget for Next.js applications
233 lines (197 loc) • 6.44 kB
JavaScript
/**
* 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);