BeRu / frontend.html
BeRU Deployer
Deploy BeRU Streamlit RAG System - Add app, models logic, configs, and optimizations for HF Spaces
dec533d
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>BeRU Chat - Multimodal</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
<style>
/* *** EXISTING STYLES (keeping all your original styles) *** */
body {
font-family: 'Roboto', sans-serif;
margin: 0;
padding: 0;
transition: background-color 0.5s ease, color 0.5s ease;
}
.light-mode {
background-color: #caf2fa;
color: #333;
}
.dark-mode {
background-color: #1e1e1e;
color: #f5f5f5;
}
.dark-mode .chat-container {
background-color: #1e1e1e;
color: #f5f5f5;
}
.sidebar {
width: 300px;
height: 100vh;
background-color: #0d131a;
position: fixed;
top: 0;
left: 0;
z-index: 1;
overflow-x: hidden;
transition: width 0.3s, background-color 0.5s ease;
}
.light-mode .sidebar {
background-color: #01414e;
}
.sidebar.collapsed {
width: 50px;
}
.tooltip {
position: absolute;
top: 0;
right: -20px;
}
.tooltip .tooltiptext {
visibility: hidden;
width: 120px;
background-color: rgb(0, 0, 0);
color: #fff;
text-align: center;
border-radius: 6px;
padding: 5px 0;
position: absolute;
z-index: 1;
bottom: 125%;
left: 50%;
margin-left: -60px;
opacity: 0;
transition: opacity 0.3s;
}
#sidebar-toggle {
background-color: transparent;
margin: -22%;
align-items: center;
margin-top: 600%;
}
.tooltip .tooltiptext::after {
content: "";
position: absolute;
top: 100%;
left: 50%;
border-width: 5px;
border-style: solid;
border-color: black transparent transparent transparent;
}
.tooltip:hover .tooltiptext {
visibility: visible;
opacity: 1;
}
.sidebar-content {
padding-top: 20px;
transition: opacity 0.3s;
}
.sidebar.collapsed .sidebar-content {
opacity: 0;
pointer-events: none;
}
.conversation-list {
padding: 0 20px;
}
.conversation {
margin-bottom: 10px;
}
.conversation-text {
font-weight: bold;
color: #fff;
transition: color 0.5s ease;
}
.light-mode .conversation-text {
color: #ccc;
}
.conversation-content {
color: #ddd;
transition: color 0.5s ease;
}
.light-mode .conversation-content {
color: #888;
}
#new-conversation-btn {
background-color: #3a3b3b;
color: #fff;
border: none;
padding: 10px 20px;
border-radius: 5px;
cursor: pointer;
transition: background-color 0.3s, color 0.5s ease;
}
#new-conversation-btn:hover {
background-color: #242020;
}
.light-mode #new-conversation-btn {
background-color: #c9c9c9;
color: #171717;
}
.light-mode #new-conversation-btn:hover {
background-color: #e0e0e0;
color: #171717;
}
.chat-container {
width: calc(100% - 300px);
margin-left: 300px;
height: 100vh;
overflow: hidden;
transition: all 0.3s ease-in-out, background-color 0.5s ease;
}
.sidebar.collapsed ~ .chat-container {
width: calc(100% - 50px);
margin-left: 50px;
}
.chat-content {
display: flex;
flex-direction: column;
height: 100%;
padding-bottom: 80px;
}
.logo-container {
display: flex;
align-items: center;
}
.logo {
width: 30px;
height: 30px;
margin-right: 10px;
}
.chat-header {
margin-left: 2%;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 10px;
height: 60px;
background-color: #171717;
transition: background-color 0.5s ease, color 0.5s ease;
}
.light-mode h1 {
color: black;
}
.dark-mode h1 {
color: #f5f5f5;
}
.light-mode .chat-header {
background-color: #caf2fa;
color: #333;
}
.dark-mode .chat-header {
background-color: #1e1e1e;
color: #f5f5f5;
}
h1 {
color: #cfcfcf;
font-family: 'Trebuchet MS', sans-serif;
transition: color 0.5s ease;
}
/* Toggle Switch Styles */
.toggle-switch {
position: relative;
width: 50px;
height: 25px;
margin-right: 20px;
--light: #d8dbe0;
--dark: #28292c;
}
.switch-label {
position: absolute;
width: 100%;
height: 100%;
background-color: var(--dark);
border-radius: 12px;
cursor: pointer;
border: 1.5px solid var(--dark);
transition: background-color 0.3s;
}
.checkbox {
position: absolute;
display: none;
}
.slider {
position: absolute;
width: 100%;
height: 100%;
border-radius: 12px;
transition: 0.3s;
}
.checkbox:checked ~ .slider {
background-color: var(--light);
}
.slider::before {
content: "";
position: absolute;
top: 5.5px;
left: 5.5px;
width: 14px;
height: 14px;
border-radius: 50%;
box-shadow: inset 7px -2px 0px 0px var(--light);
background-color: var(--dark);
transition: 0.3s;
}
.checkbox:checked ~ .slider::before {
transform: translateX(26px);
background-color: var(--dark);
box-shadow: none;
}
.chat-box {
display: flex;
flex-direction: column;
flex: 1;
overflow-y: auto;
padding: 15px;
overflow-x: hidden;
}
.chat-box::-webkit-scrollbar {
width: 3px;
}
.chat-box::-webkit-scrollbar-track {
background: transparent;
}
.chat-box::-webkit-scrollbar-track-piece {
background: #b0b0b000;
border-radius: 999px;
}
.chat-box::-webkit-scrollbar-thumb {
background-color: #ffd700;
border-radius: 999px;
border: 2px solid transparent;
background-clip: padding-box;
}
.chat-box {
scrollbar-width: thin;
scrollbar-color: #ffd700 #b0b0b0;
}
.chat-box p {
margin: 10px 0;
font-size: 16px;
}
.messageBox {
position: fixed;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
display: flex;
align-items: center;
background-color: #2d2d2d;
padding: 0 12px;
border-radius: 10px;
border: 1px solid rgb(63, 63, 63);
width: 60%;
max-width: 800px;
height: 50px;
transition: all 0.3s ease-in-out, background-color 0.5s ease, border-color 0.5s ease;
}
.light-mode .messageBox {
background-color: white;
border: 1px solid #1d495f;
}
.messageBox:focus-within {
border: 1px solid rgb(110, 110, 110);
}
#messageInput {
flex: 1;
height: 100%;
background-color: transparent;
outline: none;
border: none;
padding: 0 12px;
color: white;
width: auto;
font-family: 'Roboto', sans-serif;
font-size: 14px;
transition: color 0.5s ease;
}
.light-mode #messageInput {
color: #171717;
}
#sendButton {
width: 50px;
height: 100%;
background-color: transparent;
outline: none;
border: none;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
padding: 0;
}
#sendButton svg {
height: 60%;
width: auto;
transition: all 0.3s;
}
#sendButton svg path {
transition: all 0.3s;
}
#sendButton:hover svg path,
#sendButton:active svg path {
fill: #3c3c3c;
stroke: white;
}
.light-mode #sendButton:hover svg path,
.light-mode #sendButton:active svg path {
fill: #fbf7e7;
stroke: #ffcd07 !important;
}
.message-row {
width: 100%;
margin: 8px 0;
display: flex;
}
.message-user {
justify-content: flex-end;
}
.message-bot {
justify-content: flex-start;
}
.message-bubble {
max-width: 70%;
padding: 10px 14px;
border-radius: 16px;
font-size: 14px;
transition: background-color 0.5s ease, color 0.5s ease;
}
.message-user .message-bubble {
background-color: #1b798e;
color: white;
border-bottom-right-radius: 4px;
border: 1px solid #FFD700;
}
.message-bot .message-bubble {
background-color: #2d2d2d;
color: white;
border-bottom-left-radius: 4px;
border: 1px solid #FFD700;
}
.light-mode .message-bot .message-bubble {
background-color: #fefdf6;
color: #111;
}
/* ✅ NEW: Image Gallery Styles */
.image-gallery {
display: flex;
gap: 10px;
flex-wrap: wrap;
margin-top: 12px;
padding-top: 12px;
border-top: 1px solid rgba(255, 215, 0, 0.3);
}
.image-container {
position: relative;
border-radius: 8px;
overflow: hidden;
cursor: pointer;
transition: transform 0.2s ease;
border: 2px solid #FFD700;
}
.image-container:hover {
transform: scale(1.05);
}
.image-container img {
width: 150px;
height: 150px;
object-fit: cover;
display: block;
}
.image-caption {
position: absolute;
bottom: 0;
left: 0;
right: 0;
background: rgba(0, 0, 0, 0.7);
color: #FFD700;
padding: 4px 8px;
font-size: 10px;
text-align: center;
}
/* ✅ NEW: Image Modal/Lightbox */
.image-modal {
display: none;
position: fixed;
z-index: 9999;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.9);
align-items: center;
justify-content: center;
}
.image-modal.active {
display: flex;
}
.modal-content {
max-width: 90%;
max-height: 90%;
border-radius: 8px;
box-shadow: 0 4px 20px rgba(255, 215, 0, 0.5);
}
.modal-close {
position: absolute;
top: 20px;
right: 35px;
color: #FFD700;
font-size: 40px;
font-weight: bold;
cursor: pointer;
transition: color 0.3s;
}
.modal-close:hover {
color: #fff;
}
.fileUploadWrapper {
position: relative;
display: flex;
align-items: center;
margin-right: 8px;
}
.fileUploadWrapper label {
display: flex;
align-items: center;
cursor: pointer;
padding: 0;
margin: 0;
}
.fileUploadWrapper svg {
width: 20px;
height: 20px;
fill: #6c6c6c;
transition: all 0.3s ease;
}
.fileUploadWrapper label:hover svg {
fill: #10a37f;
}
.fileUploadWrapper .tooltip {
display: none;
position: absolute;
bottom: 125%;
left: 50%;
transform: translateX(-50%);
background-color: #000;
color: #fff;
padding: 5px 10px;
border-radius: 6px;
font-size: 12px;
white-space: nowrap;
z-index: 1;
}
.fileUploadWrapper label:hover .tooltip {
display: block;
}
.fileUploadWrapper input {
display: none;
}
.fileUploadWrapper,
#sendButton {
width: 40px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
margin: 0 8px;
}
.fileUploadWrapper svg,
#sendButton svg {
width: 20px;
height: 20px;
fill: #6c6c6c;
transition: all 0.3s ease;
}
.fileUploadWrapper label:hover svg path,
.fileUploadWrapper label:hover svg circle,
#sendButton:hover svg path {
stroke: white;
transition: stroke 0.3s ease;
}
.light-mode .fileUploadWrapper label:hover svg path,
.light-mode .fileUploadWrapper label:hover svg circle,
.light-mode #sendButton:hover svg path {
stroke: #ffcd07;
transition: stroke 0.3s ease;
}
#sendButton svg,
.fileUploadWrapper svg {
transition: all 0.3s ease;
}
/* Mode Dropdown Styles */
.mode-dropdown-wrapper {
position: relative;
display: flex;
align-items: center;
margin: 0 8px;
}
.mode-dropdown-button {
display: inline-flex;
justify-content: center;
align-items: center;
padding: 6px 12px;
background-color: transparent;
border: none;
color: #e5e5e5;
font-size: 14px;
font-family: 'Roboto', sans-serif;
font-weight: 500;
cursor: pointer;
border-radius: 6px;
white-space: nowrap;
transition: background-color 0.3s, color 0.5s ease;
}
.light-mode .mode-dropdown-button {
background-color: #f9f9f9;
color: #171717;
}
.mode-dropdown-button:hover {
background-color: rgba(110, 110, 110, 0.12);
}
.light-mode .mode-dropdown-button:hover {
background-color: #f0f0f0;
}
.dropdown-arrow {
width: 16px;
height: 16px;
margin-left: 6px;
transition: transform 0.2s ease, color 0.5s ease;
}
.mode-dropdown-button[aria-expanded="true"] .dropdown-arrow {
transform: rotate(180deg);
}
.mode-dropdown-menu {
position: absolute;
bottom: 100%;
right: 0;
margin-bottom: 8px;
min-width: 180px;
background-color: #2d2d2d;
border: 1px solid rgb(63, 63, 63);
border-radius: 8px;
box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.4);
z-index: 1000;
opacity: 0;
transform: translateY(-8px);
transition: opacity 0.2s ease, transform 0.2s ease, background-color 0.5s ease, border-color 0.5s ease;
pointer-events: none;
}
.mode-dropdown-menu:not(.hidden) {
opacity: 1;
transform: translateY(0);
pointer-events: auto;
}
.light-mode .mode-dropdown-menu {
background-color: #ffffff;
border-color: #1d495f;
box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.15);
}
.dropdown-items {
padding: 4px 0;
}
.dropdown-item {
display: flex;
align-items: center;
padding: 10px 16px;
color: #ddd;
text-decoration: none;
font-size: 14px;
font-family: 'Roboto', sans-serif;
cursor: pointer;
transition: background-color 0.15s ease, color 0.5s ease;
}
.dropdown-item:first-child {
border-top-left-radius: 8px;
border-top-right-radius: 8px;
}
.dropdown-item:last-child {
border-bottom-left-radius: 8px;
border-bottom-right-radius: 8px;
}
.dropdown-item:hover {
background-color: rgba(110, 110, 110, 0.25);
color: #fff;
}
.light-mode .dropdown-item {
color: #1f2937;
}
.light-mode .dropdown-item:hover {
background-color: #f3f4f6;
color: #1e40af;
}
.dropdown-item .font-semibold {
font-weight: 600;
}
.hidden {
display: none;
}
</style>
</head>
<body>
<div class="sidebar collapsed">
<div class="tooltip">
<span class="tooltiptext">Open Sidebar</span>
<button id="sidebar-toggle">
<i class="fas fa-chevron-right"></i>
</button>
</div>
<div class="sidebar-content">
<div class="conversation-list">
<div class="conversation">
<p class="conversation-text">Last Conversation:</p>
<p class="conversation-content">No conversation yet</p>
</div>
</div>
<button id="new-conversation-btn">Start New Conversation</button>
</div>
</div>
<div class="chat-container light-mode">
<div class="chat-content">
<div class="chat-header">
<div class="logo-container">
<h1>BeRU&nbsp;</h1>
</div>
<div class="toggle-switch">
<label class="switch-label">
<input type="checkbox" id="toggle-checkbox" class="checkbox">
<span class="slider"></span>
</label>
</div>
</div>
<div id="chat-box" class="chat-box"></div>
<div class="messageBox">
<div class="fileUploadWrapper">
<label for="file">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 337 337">
<circle stroke-width="20" stroke="#6c6c6c" fill="none" r="158.5" cy="168.5" cx="168.5"></circle>
<path stroke-linecap="round" stroke-width="25" stroke="#6c6c6c" d="M167.759 79V259"></path>
<path stroke-linecap="round" stroke-width="25" stroke="#6c6c6c" d="M79 167.138H259"></path>
</svg>
<span class="tooltip">Add an image</span>
</label>
<input type="file" id="file" name="file" />
</div>
<input required="" placeholder="Message..." type="text" id="messageInput" />
<div class="mode-dropdown-wrapper">
<button id="modeDropdownButton" type="button" class="mode-dropdown-button" aria-expanded="false" aria-haspopup="true">
Detailed
<svg class="dropdown-arrow" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
<path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd" />
</svg>
</button>
<div id="modeDropdownMenu" class="mode-dropdown-menu hidden" role="menu" aria-orientation="vertical" aria-labelledby="modeDropdownButton" tabindex="-1">
<div class="dropdown-items">
<a href="#" class="dropdown-item" role="menuitem" tabindex="-1">
<span class="font-semibold">Short and Concise</span>
</a>
<a href="#" class="dropdown-item" role="menuitem" tabindex="-1">
<span class="font-semibold">Detailed</span>
</a>
<a href="#" class="dropdown-item" role="menuitem" tabindex="-1">
<span class="font-semibold">Step-by-Step</span>
</a>
</div>
</div>
</div>
<button id="sendButton">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 664 663">
<path fill="none" d="M646.293 331.888L17.7538 17.6187L155.245 331.888M646.293 331.888L17.753 646.157L155.245 331.888M646.293 331.888L318.735 330.228L155.245 331.888"></path>
<path stroke-linejoin="round" stroke-linecap="round" stroke-width="33.67" stroke="#6c6c6c" d="M646.293 331.888L17.7538 17.6187L155.245 331.888M646.293 331.888L17.753 646.157L155.245 331.888M646.293 331.888L318.735 330.228L155.245 331.888"></path>
</svg>
</button>
</div>
</div>
</div>
<!-- ✅ NEW: Image Modal -->
<div id="imageModal" class="image-modal">
<span class="modal-close" id="modalClose">&times;</span>
<img class="modal-content" id="modalImage">
</div>
<script>
const chatBox = document.getElementById('chat-box');
const userInput = document.getElementById('messageInput');
const sendButton = document.getElementById('sendButton');
const sidebarToggle = document.getElementById('sidebar-toggle');
const modeToggle = document.getElementById('toggle-checkbox');
const sidebar = document.querySelector('.sidebar');
const chatContainer = document.querySelector('.chat-container');
const messageBox = document.querySelector('.messageBox');
const imageModal = document.getElementById('imageModal');
const modalImage = document.getElementById('modalImage');
const modalClose = document.getElementById('modalClose');
let currentMode = 'Detailed';
let sessionId = 'session-' + Date.now();
// ✅ NEW: Image Modal Functions
function openImageModal(imageSrc) {
imageModal.classList.add('active');
modalImage.src = imageSrc;
}
function closeImageModal() {
imageModal.classList.remove('active');
modalImage.src = '';
}
modalClose.addEventListener('click', closeImageModal);
imageModal.addEventListener('click', (e) => {
if (e.target === imageModal) {
closeImageModal();
}
});
// Utility Functions
function getCurrentTime() {
const now = new Date();
return now.toLocaleTimeString();
}
// ✅ MODIFIED: Chat Functions with Image Support
function appendMessage(sender, message, images = []) {
const wrapper = document.createElement('div');
wrapper.classList.add('message-row');
wrapper.classList.add(sender === 'user' ? 'message-user' : 'message-bot');
const bubble = document.createElement('div');
bubble.classList.add('message-bubble');
// Add text message
bubble.innerHTML = message.replace(/\n/g, '<br>');
// ✅ NEW: Add images if present
if (images && images.length > 0) {
const gallery = document.createElement('div');
gallery.classList.add('image-gallery');
images.forEach((img, index) => {
const imgContainer = document.createElement('div');
imgContainer.classList.add('image-container');
const imgElement = document.createElement('img');
imgElement.src = img.data;
imgElement.alt = `Image from ${img.source}`;
imgElement.loading = 'lazy';
// Click to open modal
imgElement.addEventListener('click', () => {
openImageModal(img.data);
});
const caption = document.createElement('div');
caption.classList.add('image-caption');
caption.textContent = `📄 ${img.source} | Page ${img.page}`;
imgContainer.appendChild(imgElement);
imgContainer.appendChild(caption);
gallery.appendChild(imgContainer);
});
bubble.appendChild(gallery);
}
wrapper.appendChild(bubble);
chatBox.appendChild(wrapper);
chatBox.scrollTop = chatBox.scrollHeight;
}
async function sendMessage() {
const message = userInput.value.trim();
if (message === '') return;
// Append user message
appendMessage('user', message);
userInput.value = '';
// Show loading message
appendMessage('ChatGPT', '⏳ Thinking...');
try {
const response = await fetch('/api/chat', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
message: message,
mode: currentMode,
session_id: sessionId,
include_images: true // ✅ NEW: Request images
})
});
const data = await response.json();
// Remove loading message
chatBox.removeChild(chatBox.lastChild);
if (data.error) {
appendMessage('ChatGPT', '❌ Error: ' + data.error);
} else {
// ✅ NEW: Pass images to appendMessage
const images = data.images || [];
appendMessage('ChatGPT', data.response, images);
// Log image info
if (images.length > 0) {
console.log(`📷 Received ${images.length} images`);
}
}
} catch (error) {
// Remove loading message
chatBox.removeChild(chatBox.lastChild);
appendMessage('ChatGPT', '❌ Connection error. Please check if the server is running.');
console.error('Error:', error);
}
}
// Event Listeners
document.addEventListener('DOMContentLoaded', function() {
const newConversationBtn = document.getElementById('new-conversation-btn');
const conversationContent = document.querySelector('.conversation-content');
// Sidebar Toggle
sidebarToggle.addEventListener('click', function() {
sidebar.classList.toggle('collapsed');
adjustMessageBoxPosition();
});
function adjustMessageBoxPosition() {
const sidebarWidth = sidebar.classList.contains('collapsed') ? 50 : 300;
const chatAreaWidth = window.innerWidth - sidebarWidth;
messageBox.style.left = sidebarWidth + (chatAreaWidth / 2) + 'px';
messageBox.style.transform = 'translateX(-50%)';
}
adjustMessageBoxPosition();
window.addEventListener('resize', adjustMessageBoxPosition);
// New Conversation
newConversationBtn.addEventListener('click', async function() {
conversationContent.textContent = 'New Conversation Started!';
chatBox.innerHTML = '';
sessionId = 'session-' + Date.now();
try {
await fetch('/api/new-conversation', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({session_id: sessionId})
});
} catch (error) {
console.error('Error starting new conversation:', error);
}
adjustMessageBoxPosition();
});
// Theme Toggle
modeToggle.addEventListener('change', function() {
document.body.classList.toggle('dark-mode');
document.body.classList.toggle('light-mode');
chatContainer.classList.toggle('light-mode');
chatContainer.classList.toggle('dark-mode');
adjustMessageBoxPosition();
});
// Set initial mode
document.body.classList.add('light-mode');
// Send button
sendButton.addEventListener('click', sendMessage);
userInput.addEventListener('keydown', (event) => {
if (event.key === 'Enter') sendMessage();
});
// Mode Dropdown
const modeDropdownButton = document.getElementById('modeDropdownButton');
const modeDropdownMenu = document.getElementById('modeDropdownMenu');
if (modeDropdownButton && modeDropdownMenu) {
function toggleMenu() {
const isHidden = modeDropdownMenu.classList.contains('hidden');
if (isHidden) {
modeDropdownMenu.classList.remove('hidden');
modeDropdownButton.setAttribute('aria-expanded', 'true');
} else {
modeDropdownMenu.classList.add('hidden');
modeDropdownButton.setAttribute('aria-expanded', 'false');
}
}
modeDropdownButton.addEventListener('click', (event) => {
event.stopPropagation();
toggleMenu();
});
document.addEventListener('click', (event) => {
if (!modeDropdownButton.contains(event.target) && !modeDropdownMenu.contains(event.target)) {
if (!modeDropdownMenu.classList.contains('hidden')) {
toggleMenu();
}
}
});
modeDropdownMenu.querySelectorAll('.dropdown-item').forEach(item => {
item.addEventListener('click', (event) => {
event.preventDefault();
const selectedMode = event.currentTarget.querySelector('.font-semibold').textContent.trim();
console.log('Mode selected:', selectedMode);
currentMode = selectedMode;
const buttonTextNode = Array.from(modeDropdownButton.childNodes).find(node =>
node.nodeType === Node.TEXT_NODE && node.textContent.trim() !== ''
);
if (buttonTextNode) {
buttonTextNode.textContent = selectedMode;
} else {
const textNode = document.createTextNode(selectedMode);
modeDropdownButton.insertBefore(textNode, modeDropdownButton.querySelector('.dropdown-arrow'));
}
toggleMenu();
});
});
}
});
</script>
</body>
</html>