1// Hamdard University Chatbot - WordPress Integration 2// Ultra Premium UI/UX Version 3(function() { 4 'use strict'; 5 6 const CHATBOT_CONFIG = { 7 title: 'Hamdard University', 8 subtitle: 'Admissions & AI Assistant', 9 primaryColor: '#059669', // Emerald-600 10 secondaryColor: '#047857', // Emerald-700 11 }; 12 13 const QUICK_REPLIES = [ 14 "Admission Process", 15 "Fee Structure", 16 "Courses Offered", 17 "Scholarships", 18 "Contact Information" 19 ]; 20 21 class WordPressChatbot { 22 constructor() { 23 this.messages = []; 24 this.isOpen = false; 25 this.isTyping = false; 26 this.init(); 27 } 28 29 init() { 30 this.createChatbotHTML(); 31 this.attachEventListeners(); 32 this.addWelcomeMessage(); 33 } 34 35 createChatbotHTML() { 36 const chatbotHTML = ` 37 <div id="hamdard-chatbot" class="hamdard-chatbot-container"> 38 <div id="hamdard-chat-button" class="hamdard-chat-button"> 39 <svg width="28" height="28" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> 40 <path d="M8 12H16M8 8H16M8 16H12M21 12C21 16.9706 16.9706 21 12 21C10.2 21 8.5 20.5 7 19.6L3 21L4.4 17C3.5 15.5 3 13.8 3 12C3 7.02944 7.02944 3 12 3C16.9706 3 21 7.02944 21 12Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> 41 </svg> 42 </div> 43 44 <div id="hamdard-chat-window" class="hamdard-chat-window"> 45 <div class="hamdard-chat-header"> 46 <div class="hamdard-chat-header-info"> 47 <div class="hamdard-chat-avatar"> 48 <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M12 2L13.09 8.26L20 9L13.09 9.74L12 16L10.91 9.74L4 9L10.91 8.26L12 2Z" fill="currentColor"/></svg> 49 </div> 50 <div class="hamdard-header-text"> 51 <h3 style="margin: 0; font-size: 16px; font-weight: 700; letter-spacing: 0.3px; color: white;">${CHATBOT_CONFIG.title}</h3> 52 <div class="hamdard-status"> 53 <div class="hamdard-status-dot"></div> 54 <span>${CHATBOT_CONFIG.subtitle}</span> 55 </div> 56 </div> 57 </div> 58 <button id="hamdard-chat-close" class="hamdard-chat-close"> 59 <svg width="22" height="22" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M18 6L6 18M6 6L18 18" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg> 60 </button> 61 </div> 62 <div class="hamdard-quick-contact"> 63 <span style="display: flex; align-items: center; gap: 4px;"><svg width="14" height="14" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z"></path></svg> 021-111-102-030</span> 64 <span class="hamdard-divider">|</span> 65 <span style="display: flex; align-items: center; gap: 4px;"><svg width="14" height="14" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"></path></svg> [email protected]</span> 66 </div> 67 <div id="hamdard-chat-messages" class="hamdard-chat-messages"></div> 68 <div id="hamdard-quick-replies" class="hamdard-quick-replies"></div> 69 <div class="hamdard-chat-input"> 70 <input type="text" id="hamdard-message-input" placeholder="Type your message... / Ø§Ù¾ÙØ§ Ù¾ÛØºØ§Ù ÙÚ©Ú¾ÛÚº" autocomplete="off" /> 71 <button id="hamdard-send-button"> 72 <svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M22 2L11 13M22 2L15 22L11 13M22 2L2 9L11 13" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg> 73 </button> 74 </div> 75 </div> 76 </div> 77 `; 78 document.body.insertAdjacentHTML('beforeend', chatbotHTML); 79 this.loadStyles(); 80 } 81 82 loadStyles() { 83 const styles = ` 84 @import url('https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700&display=swap'); 85 86 <style id="hamdard-chatbot-premium-styles"> 87 /* Base Reset */ 88 .hamdard-chatbot-container * { box-sizing: border-box; } 89 .hamdard-chatbot-container { 90 position: fixed; bottom: 24px; right: 24px; 91 z-index: 999999 !important; 92 font-family: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; 93 } 94 95 /* Floating Button */ 96 .hamdard-chat-button { 97 width: 64px; height: 64px; 98 background: linear-gradient(135deg, ${CHATBOT_CONFIG.primaryColor}, ${CHATBOT_CONFIG.secondaryColor}); 99 border-radius: 50%; display: flex; align-items: center; justify-content: center; 100 color: white; cursor: pointer; 101 box-shadow: 0 8px 24px rgba(5, 150, 105, 0.4); 102 transition: transform 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275), box-shadow 0.3s; 103 animation: hamdardPulse 2.5s infinite; 104 position: relative; z-index: 1000000 !important; 105 } 106 .hamdard-chat-button:hover { 107 transform: scale(1.1) translateY(-4px); 108 box-shadow: 0 12px 28px rgba(5, 150, 105, 0.5); 109 } 110 @keyframes hamdardPulse { 111 0% { box-shadow: 0 0 0 0 rgba(5, 150, 105, 0.4); } 112 70% { box-shadow: 0 0 0 15px rgba(5, 150, 105, 0); } 113 100% { box-shadow: 0 0 0 0 rgba(5, 150, 105, 0); } 114 } 115 116 /* Chat Window - Premium Glassmorphism */ 117 .hamdard-chat-window { 118 width: 400px; height: 680px; max-height: calc(100vh - 120px); 119 background: rgba(255, 255, 255, 0.98); 120 backdrop-filter: blur(20px); 121 border-radius: 20px; 122 box-shadow: 0 20px 50px rgba(0, 0, 0, 0.15), 0 0 0 1px rgba(0,0,0,0.05); 123 display: none; flex-direction: column; overflow: hidden; 124 position: absolute; bottom: 84px; right: 0; 125 transform-origin: bottom right; 126 } 127 .hamdard-chat-window.open { 128 display: flex; 129 animation: scaleIn 0.4s cubic-bezier(0.16, 1, 0.3, 1) forwards; 130 } 131 @keyframes scaleIn { 132 from { opacity: 0; transform: scale(0.9) translateY(20px); } 133 to { opacity: 1; transform: scale(1) translateY(0); } 134 } 135 136 /* Header */ 137 .hamdard-chat-header { 138 background: linear-gradient(135deg, ${CHATBOT_CONFIG.primaryColor} 0%, ${CHATBOT_CONFIG.secondaryColor} 100%), url("data:image/svg+xml,%3Csvg width='60' height='60' viewB
138ox='0 0 60 60' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg fill='%23ffffff' fill-opacity='0.08'%3E%3Cpath d='M36 34v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zm0-30V0h-2v4h-4v2h4v4h2V6h4V4h-4zM6 34v-4H4v4H0v2h4v4h2v-4h4v-2H6zM6 4V0H4v4H0v2h4v4h2V6h4V4H6z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E"); 139 color: white; padding: 20px; 140 display: flex; align-items: center; justify-content: space-between; 141 border-top-left-radius: 20px; border-top-right-radius: 20px; 142 border-bottom: 1px solid rgba(0,0,0,0.05); 143 } 144 .hamdard-chat-header-info { display: flex; align-items: center; gap: 14px; } 145 .hamdard-chat-avatar { 146 width: 44px; height: 44px; 147 background: rgba(255, 255, 255, 0.2); 148 border-radius: 50%; display: flex; align-items: center; justify-content: center; 149 box-shadow: 0 4px 10px rgba(0,0,0,0.1); 150 backdrop-filter: blur(4px); 151 border: 2px solid rgba(255,255,255,0.4); 152 } 153 .hamdard-status { display: flex; align-items: center; gap: 6px; margin-top: 4px; } 154 .hamdard-status-dot { width: 8px; height: 8px; background: #34d399; border-radius: 50%; box-shadow: 0 0 8px rgba(52, 211, 153, 0.8); animation: blink 2s infinite; } 155 @keyframes blink { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } } 156 .hamdard-status span { font-size: 13px; opacity: 0.95; font-weight: 500; color: white;} 157 158 .hamdard-chat-close { 159 background: rgba(255, 255, 255, 0.1); border: none; color: white; 160 cursor: pointer; padding: 8px; border-radius: 50%; 161 transition: all 0.2s; display: flex; align-items: center; justify-content: center; 162 } 163 .hamdard-chat-close:hover { background: rgba(255, 255, 255, 0.3); transform: rotate(90deg); } 164 165 /* Contact Bar */ 166 .hamdard-quick-contact { 167 background: #f0fdf4; padding: 10px 20px; 168 display: flex; justify-content: center; gap: 12px; align-items: center; 169 font-size: 12px; color: ${CHATBOT_CONFIG.secondaryColor}; 170 border-bottom: 1px solid rgba(5, 150, 105, 0.1); font-weight: 600; 171 } 172 .hamdard-divider { opacity: 0.3; } 173 174 /* Messages Area */ 175 .hamdard-chat-messages { 176 flex: 1; overflow-y: auto; padding: 20px; 177 background: #f8fafc; display: flex; flex-direction: column; 178 scroll-behavior: smooth; 179 } 180 181 /* Custom Scrollbar */ 182 .hamdard-chat-messages::-webkit-scrollbar { width: 6px; } 183 .hamdard-chat-messages::-webkit-scrollbar-track { background: transparent; } 184 .hamdard-chat-messages::-webkit-scrollbar-thumb { background: #cbd5e1; border-radius: 10px; } 185 .hamdard-chat-messages::-webkit-scrollbar-thumb:hover { background: #94a3b8; } 186 187 /* Message Bubbles */ 188 .hamdard-message { margin-bottom: 20px; display: flex; align-items: flex-end; gap: 10px; opacity: 0; animation: msgFadeIn 0.3s ease-out forwards; } 189 @keyframes msgFadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } 190 .hamdard-message.user { flex-direction: row-reverse; } 191 192 .hamdard-message-avatar { 193 width: 32px; height: 32px; border-radius: 50%; 194 display: flex; align-items: center; justify-content: center; flex-shrink: 0; 195 } 196 .hamdard-message.bot .hamdard-message-avatar { 197 background: white; color: ${CHATBOT_CONFIG.primaryColor}; 198 box-shadow: 0 4px 10px rgba(0,0,0,0.08); 199 border: 1px solid rgba(0,0,0,0.04); 200 } 201 .hamdard-message.user .hamdard-message-avatar { display: none; } 202 203 .hamdard-message-content { 204 max-width: 85%; padding: 14px 18px; font-size: 14.5px; 205 line-height: 1.6; word-wrap: break-word; letter-spacing: 0.1px; 206 } 207 208 /* Advanced Message Tails and Shadows */ 209 .hamdard-message.bot .hamdard-message-content { 210 background: white; color: #334155; 211 border-radius: 20px 20px 20px 4px; border: 1px solid rgba(0,0,0,0.04); 212 box-shadow: 0 4px 15px rgba(0,0,0,0.04); 213 } 214 .hamdard-message.user .hamdard-message-content { 215 background: linear-gradient(135deg, ${CHATBOT_CONFIG.primaryColor}, ${CHATBOT_CONFIG.secondaryColor}); 216 color: white; border-radius: 20px 20px 4px 20px; 217 box-shadow: 0 4px 15px rgba(5, 150, 105, 0.25); 218 } 219 220 .hamdard-message-time { font-size: 11px; opacity: 0.6; margin-top: 8px; text-align: right; font-weight: 500;} 221 .hamdard-message.user .hamdard-message-time { color: rgba(255,255,255,0.9); } 222 223 /* Quick Replies */ 224 .hamdard-quick-replies { 225 padding: 12px 20px; background: white; 226 border-top: 1px solid rgba(0,0,0,0.05); display: flex; flex-wrap: wrap; gap: 8px; 227 } 228 .hamdard-quick-reply { 229 background: white; color: ${CHATBOT_CONFIG.primaryColor}; border: 1px solid #a7f3d0; 230 padding: 8px 14px; border-radius: 20px; font-size: 13px; font-weight: 600; 231 cursor: pointer; transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1); 232 box-shadow: 0 2px 4px rgba(5, 150, 105, 0.05); 233 font-family: inherit; 234 } 235 .hamdard-quick-reply:hover { 236 background: #ecfdf5; transform: translateY(-2px); 237 box-shadow: 0 4px 10px rgba(5, 150, 105, 0.15); 238 } 239 240 /* Input Area */ 241 .hamdard-chat-input { 242 padding: 16px 20px; background: white; 243 border-top: 1px solid rgba(0,0,0,0.05); display: flex; gap: 10px; align-items: center; 244 } 245 .hamdard-chat-input input { 246 flex: 1; border: 1px solid #e2e8f0; border-radius: 24px; 247 padding: 14px 20px; font-size: 15px; outline: none; 248 transition: all 0.3s ease; background: #f8fafc; color: #1e293b; 249 font-family: inherit; 250 } 251 .hamdard-chat-input input:focus { 252 background: white; border-color: ${CHATBOT_CONFIG.primaryColor}; 253 box-shadow: 0 0 0 3px rgba(5, 150, 105, 0.15); 254 } 255 .hamdard-chat-input input::placeholder { color: #94a3b8; } 256 257 .hamdard-chat-input button { 258 background: ${CHATBOT_CONFIG.primaryColor}; color: white; 259 border: none; border-radius: 50%; width: 48px; height: 48px; 260 display: flex; align-items: center; justify-content: center; 261 cursor: pointer; transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275); 262 box-shadow: 0 4px 12px rgba(5, 150, 105, 0.25); 263 } 264 .hamdard-chat-input button:hover:not(:disabled) { 265 background: ${CHATBOT_CONFIG.secondaryColor}; transform: scale(1.1); 266 box-shadow: 0 6px 16px rgba(5, 150, 105, 0.35); 267 } 268 .hamdard-chat-input button:disabled { 269 background: #cbd5e1;
269 cursor: not-allowed; box-shadow: none; transform: none; 270 } 271 272 /* Typing Indicator */ 273 .hamdard-typing { display: flex; gap: 6px; padding: 6px 4px; } 274 .hamdard-typing-dot { 275 width: 8px; height: 8px; background: #94a3b8; border-radius: 50%; 276 animation: bounce 1.4s infinite ease-in-out both; 277 } 278 .hamdard-typing-dot:nth-child(1) { animation-delay: -0.32s; } 279 .hamdard-typing-dot:nth-child(2) { animation-delay: -0.16s; } 280 @keyframes bounce { 0%, 80%, 100% { transform: scale(0); } 40% { transform: scale(1); } } 281 282 /* Form Inputs Focus */ 283 .hamdard-lead-input:focus { border-color: ${CHATBOT_CONFIG.primaryColor} !important; box-shadow: 0 0 0 3px rgba(5, 150, 105, 0.15) !important; } 284 .hamdard-lead-submit:hover:not(:disabled) { background: ${CHATBOT_CONFIG.secondaryColor} !important; transform: translateY(-1px); } 285 .hamdard-lead-submit:active:not(:disabled) { transform: translateY(1px); } 286 287 /* Markdown Content Styles */ 288 .hamdard-markdown-content { font-size: 14.5px; line-height: 1.6; color: inherit; } 289 .hamdard-markdown-content h4, .hamdard-markdown-content h3, .hamdard-markdown-content h2 { background: #f0fdf4; color: #047857; padding: 10px 14px; border-radius: 8px; border-left: 4px solid #059669; font-size: 15px; margin: 16px 0 8px 0; font-weight: 700; } 290 .hamdard-markdown-content p { margin: 0 0 10px 0; } 291 .hamdard-markdown-content strong { color: #0f172a; font-weight: 700; } 292 .hamdard-markdown-content a { color: #059669; text-decoration: underline; font-weight: 600; } 293 .hamdard-markdown-content ul, .hamdard-markdown-content ol { margin: 0 0 12px 0; padding-left: 24px; } 294 .hamdard-markdown-content li { margin-bottom: 6px; } 295 .hamdard-markdown-content li::marker { color: #059669; font-weight: 700; } 296 .hamdard-markdown-content table { width: 100%; border-collapse: collapse; margin-bottom: 10px; font-size: 13px; } 297 .hamdard-markdown-content th, .hamdard-markdown-content td { padding: 8px; border: 1px solid rgba(0,0,0,0.1); text-align: left; } 298 .hamdard-markdown-content th { background: rgba(5,150,105,0.05); color: #059669; font-weight: 600; } 299 300 /* Mobile Responsiveness */ 301 @media (max-width: 480px) { 302 .hamdard-chat-window { 303 position: fixed; bottom: 0; right: 0; width: 100vw; height: 100vh; max-height: 100vh; 304 border-radius: 0; z-index: 9999999; animation: slideUp 0.3s forwards; 305 } 306 .hamdard-chat-header { border-radius: 0; } 307 @keyframes slideUp { from { transform: translateY(100%); } to { transform: translateY(0); } } 308 } 309 </style> 310 `; 311 document.head.insertAdjacentHTML('beforeend', styles); 312 } 313 314 attachEventListeners() { 315 document.addEventListener('click', (e) => { 316 const chatBtn = e.target.closest('#hamdard-chat-button'); 317 if (chatBtn) this.toggleChat(); 318 319 const closeBtn = e.target.closest('#hamdard-chat-close'); 320 if (closeBtn) this.closeChat(); 321 322 const sendBtn = e.target.closest('#hamdard-send-button'); 323 if (sendBtn && !this.isTyping) this.sendMessage(); 324 325 const quickReplyBtn = e.target.closest('.hamdard-quick-reply'); 326 if (quickReplyBtn && !this.isTyping) this.sendMessage(quickReplyBtn.getAttribute('data-val')); 327 328 // Handle Form Submissions within Chat 329 const leadSubmitBtn = e.target.closest('.hamdard-lead-submit'); 330 if (leadSubmitBtn && !this.isTyping) { 331 const msgId = leadSubmitBtn.getAttribute('data-msgid'); 332 const nameInput = document.getElementById(`lead-name-${msgId}`); 333 const phoneInput = document.getElementById(`lead-phone-${msgId}`); 334 const programInput = document.getElementById(`lead-program-${msgId}`); 335
336 if (nameInput && phoneInput) { 337 const name = nameInput.value.trim(); 338 const phone = phoneInput.value.trim(); 339 const program = programInput ? programInput.value.trim() : ''; 340 341 if (!name || !phone) { 342 if (!name) { nameInput.style.borderColor = '#ef4444'; nameInput.style.backgroundColor = '#fef2f2'; } 343 if (!phone) { phoneInput.style.borderColor = '#ef4444'; phoneInput.style.backgroundColor = '#fef2f2'; } 344 setTimeout(() => { 345 if (nameInput) { nameInput.style.borderColor = '#cbd5e1'; nameInput.style.backgroundColor = 'white'; } 346 if (phoneInput) { phoneInput.style.borderColor = '#cbd5e1'; phoneInput.style.backgroundColor = 'white'; } 347 }, 2000); 348 return; 349 } 350 351 let text = `My name is ${name}, my WhatsApp number is ${phone}.`; 352 if (program) text += ` I am interested in ${program}.`; 353 354 nameInput.disabled = true; 355 phoneInput.disabled = true; 356 if(programInput) programInput.disabled = true; 357 leadSubmitBtn.innerHTML = 'Submitted âï¸'; 358 leadSubmitBtn.style.background = '#10b981'; 359 leadSubmitBtn.style.boxShadow = 'none'; 360 leadSubmitBtn.disabled = true; 361 362 this.sendMessage(text); 363 } 364 } 365 }); 366 367 document.addEventListener('keypress', (e) => { 368 const inputElement = e.target.closest('#hamdard-message-input'); 369 if (e.key === 'Enter' && inputElement && !this.isTyping) { 370 e.preventDefault(); 371 this.sendMessage(); 372 } 373 }); 374 375 this.renderQuickReplies(); 376 } 377 378 toggleChat() { 379 const chatWindow = document.getElementById('hamdard-chat-window'); 380 if (this.isOpen) { 381 this.closeChat(); 382 } else { 383 chatWindow.classList.add('open'); 384 this.isOpen = true; 385 this.scrollToBottom(); 386 } 387 } 388 389 closeChat() { 390 const chatWindow = document.getElementById('hamdard-chat-window'); 391 chatWindow.classList.remove('open'); 392 this.isOpen = false; 393 } 394 395 addWelcomeMessage() { 396 this.addMessage( 397 "Ø§ÙØ³Ùا٠عÙÛÚ©Ù ! Welcome to Hamdard University!\n\nI'm your Premium AI Assistant here to help you with:\n- Admission Process / داخÙÛ Ú©Ø§ طرÛÙÛ\n- Fee Structure / ÙÛØ³ Ú©Û ØªÙØµÛÙØ§Øª\n- Courses & Programs / Ú©ÙØ±Ø³Ø²\n- Scholarships / ÙØ¸Ø§Ø¦Ù\n- Contact Information / Ø±Ø§Ø¨Ø·Û Ú©Û Ù Ø¹ÙÙ٠ات\n\nHow can I assist you today? آپ Ú©Ù Ú©ÛØ§ جاÙÙØ§ ÛÛØ", 398 true 399 ); 400 } 401 402 async sendMessage(messageText) { 403 const input = document.getElementById('hamdard-message-input'); 404 const text = messageText || input.value.trim(); 405 406 if (!text || this.isTyping) return; 407 408 this.addMessage(text, false); 409 input.value = ''; 410 this.showTyping(); 411 412 try { 413 if (typeof window.hamdard_ajax === 'undefined') throw new Error("WP AJAX config not found"); 414 415 const formData = new FormData(); 416 formData.append('action', 'hamdard_chatbot_message'); 417 formData.append('nonce', window.hamdard_ajax.nonce); 418 formData.append('message', text); 419 420 const response = await fetch(window.hamdard_ajax.ajax_url, { method: 'POST', body: formData }); 421 const result = await response.json(); 422 423 this.hideTyping(); 424 425 if (result.success && result.data) { 426 this.addMessage(result.data.content || "I have received your query.", true); 427 if (result.data.suggestions) this.renderQuickRepliesArray(result.data.suggestions); 428 } else { 429 this.addMessage("Sorry, the chat system encountered an issue connecting to our servers.", true); 430 } 431 } catch (error) { 432 console.error("Chatbot Plugin Fetch Error:", error); 433 this.hideTyping(); 434 this.addMessage("Sorry, I could not reach our core automation servers right now. Please try again later.", true); 435 } 436 } 437 438 addMessage(content, isBot) { 439 const messagesContainer = document.getElementById('hamdard-chat-messages'); 440 if (!messagesContainer) return; 441 442 const messageId = Date.now(); 443 const messageHTML = ` 444 <div class="hamdard-message ${isBot ? 'bot' : 'user'}" id="message-${messageId}"> 445 <div class="hamdard-message-avatar"> 446 ${isBot ? '<svg width="16" height="16" viewB
446ox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M12 2L13.09 8.26L20 9L13.09 9.74L12 16L10.91 9.74L4 9L10.91 8.26L12 2Z" fill="currentColor"/></svg>' : ''} 447 </div> 448 <div class="hamdard-message-content"> 449 ${isBot ? this.formatMessage(content, messageId) : content} 450 <div class="hamdard-message-time">${new Date().toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'})}</div> 451 </div> 452 </div> 453 `; 454 messagesContainer.insertAdjacentHTML('beforeend', messageHTML); 455 456 // SMART SCROLLING ALGORITHM 457 this.scrollToMessage(messageId, isBot); 458 } 459 460 scrollToMessage(messageId, isBot) { 461 const messagesContainer = document.getElementById('hamdard-chat-messages'); 462 const newMessage = document.getElementById(`message-${messageId}`); 463 if (!messagesContainer || !newMessage) return; 464 465 // Give the browser a tiny rendering tick to compute the actual DOM height of the new message 466 setTimeout(() => { 467 if (isBot) { 468 // Check if the message is tall (more than 40% of the screen) 469 const isTallMessage = newMessage.clientHeight > messagesContainer.clientHeight * 0.4; 470 if (isTallMessage) { 471 // Scroll to the top of the NEW message, with a slight 15px top-margin padding 472 messagesContainer.scrollTo({ 473 top: newMessage.offsetTop - 15, 474 behavior: 'smooth' 475 }); 476 return; 477 } 478 } 479 // Fallback: scroll to bottom 480 messagesContainer.scrollTo({ 481 top: messagesContainer.scrollHeight, 482 behavior: 'smooth' 483 }); 484 }, 10); 485 } 486 487 scrollToBottom() { 488 const messagesContainer = document.getElementById('hamdard-chat-messages'); 489 if (messagesContainer) { 490 messagesContainer.scrollTo({ top: messagesContainer.scrollHeight, behavior: 'smooth' }); 491 } 492 } 493 494 formatMessage(content, messageId) { 495 if (!content) return ''; 496 let html = content.replace(/\r\n/g, '\n'); 497 498 // 1. LEAD CAPTURE DETECTION 499 const textLower = html.toLowerCase(); 500 const isLeadRequest = (textLower.includes("whatsapp") && (textLower.includes("naam") || textLower.includes("name"))); 501 502 // Remove JSON blocks 503 html = html.replace(/`{3}json([\s\S]*?)`{3}/g, ''); 504 505 // Robust Markdown to HTML Converter 506 // Headings 507 html = html.replace(/^### (.*$)/gim, '<h4>$1</h4>'); 508 html = html.replace(/^## (.*$)/gim, '<h3>$1</h3>'); 509 html = html.replace(/^# (.*$)/gim, '<h2>$1</h2>'); 510 511 // Bold & Italic 512 html = html.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>'); 513 html = html.replace(/\*(.*?)\*/g, '<em>$1</em>'); 514 515 // Links 516 html = html.replace(/\[(.*?)\]\((.*?)\)/g, '<a href="$2" target="_blank">$1</a>'); 517 html = html.replace(/(https?:\/\/[^\s\)]+)/g, '<a href="$1" target="_blank">$1</a>'); 518 519 // Lists 520 html = html.replace(/^(\d+)\.\s+(.*$)/gim, '<li class="num-list" data-num="$1">$2</li>'); 521 html = html.replace(/^[-â¢*]\s+(.*$)/gim, '<li class="bullet-list">$1</li>'); 522 523 html = html.replace(/(<li class="bullet-list">.*<\/li>\n?)+/g, match => `<ul>\n${match}</ul>\n`); 524 html = html.replace(/(<li class="num-list".*<\/li>\n?)+/g, match => `<ol>\n${match}</ol>\n`); 525 526 // Line Breaks handling 527 html = html.split('\n').map(line => { 528 if(line.trim() === '') return ''; 529 if(line.startsWith('<ul') || line.startsWith('</ul') || line.startsWith('<ol') || line.startsWith('</ol') || line.startsWith('<li') || line.startsWith('<h') || line.startsWith('<table')) return line; 530 return `<p>${line}</p>`; 531 }).filter(line => line !== '').join(''); 532 533 // Wrap in styling container 534 html = `<div class="hamdard-markdown-content">${html}</div>`; 535
536 // 2. APPLY LEAD CAPTURE CARD FORMATTING IF DETECTED 537 if (isLeadRequest) { 538 html = ` 539 <div style="background: linear-gradient(135deg, #ffffff 0%, #f0fdf4 100%); border: 1px solid #10b981; border-radius: 16px; padding: 18px; margin: 12px 0; box-shadow: 0 6px 16px rgba(16,185,129,0.12); position: relative; overflow: hidden;"> 540 <div style="position: absolute; right: -15px; top: -15px; font-size: 80px; opacity: 0.04;">ð</div> 541 <div style="display: flex; align-items: center; gap: 12px; margin-bottom: 14px; position: relative; z-index: 1;"> 542 <div style="background: #059669; color: white; width: 36px; height: 36px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 16px; box-shadow: 0 4px 10px rgba(5,150,105,0.3);">ð</div> 543 <strong style="color: #065f46; font-size: 16px; font-weight: 700; letter-spacing: 0.2px;">Action Required</strong> 544 </div> 545 <div style="color: #334155; font-size: 15px; line-height: 1.6; margin-bottom: 16px; position: relative; z-index: 1;"> 546 ${html} 547 </div> 548 <div class="hamdard-lead-form" style="margin-top: 16px; display: flex; flex-direction: column; gap: 10px; position: relative; z-index: 1;"> 549 <input type="text" class="hamdard-lead-input" id="lead-name-${messageId}" placeholder="Full Name *" style="width: 100%; padding: 12px 14px; border: 1px solid #cbd5e1; border-radius: 8px; font-size: 14px; font-family: inherit; outline: none; transition: border-color 0.2s, box-shadow 0.2s;" required /> 550 <input type="tel" class="hamdard-lead-input" id="lead-phone-${messageId}" placeholder="WhatsApp Number *" style="width: 100%; padding: 12px 14px; border: 1px solid #cbd5e1; border-radius: 8px; font-size: 14px; font-family: inherit; outline: none; transition: border-color 0.2s, box-shadow 0.2s;" required /> 551 <input type="text" class="hamdard-lead-input" id="lead-program-${messageId}" placeholder="Interested Program (Optional)" style="width: 100%; padding: 12px 14px; border: 1px solid #cbd5e1; border-radius: 8px; font-size: 14px; font-family: inherit; outline: none; transition: border-color 0.2s, box-shadow 0.2s;" /> 552 <button class="hamdard-lead-submit" data-msgid="${messageId}" style="width: 100%; padding: 12px; margin-top: 4px; background: #059669; color: white; border: none; border-radius: 8px; font-size: 14.5px; font-weight: 600; cursor: pointer; transition: background 0.2s, transform 0.1s; display: flex; justify-content: center; align-items: center; gap: 8px; font-family: inherit; box-shadow: 0 4px 10px rgba(5,150,105,0.2);"> 553 Submit Details 554 <svg width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M14 5l7 7m0 0l-7 7m7-7H3"></path></svg> 555 </button> 556 </div> 557 </div>`; 558 } 559 560 return html; 561 } 562 563 showTyping() { 564 this.isTyping = true; 565 document.getElementById('hamdard-send-button').disabled = true; 566 document.getElementById('hamdard-message-input').disabled = true; 567 568 const messagesContainer = document.getElementById('hamdard-chat-messages'); 569 const typingHTML = ` 570 <div id="hamdard-typing-indicator" class="hamdard-message bot"> 571 <div class="hamdard-message-avatar"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M12 2L13.09 8.26L20 9L13.09 9.74L12 16L10.91 9.74L4 9L10.91 8.26L12 2Z" fill="currentColor"/></svg></div> 572 <div class="hamdard-message-content" style="padding: 14px 20px;"> 573 <div class="hamdard-typing"><div class="hamdard-typing-dot"></div><div class="hamdard-typing-dot"></div><div class="hamdard-typing-dot"></div></div> 574 </div> 575 </div> 576 `; 577 messagesContainer.insertAdjacentHTML('beforeend', typingHTML); 578 this.scrollToBottom(); 579 } 580 581 hideTyping() { 582 this.isTyping = false;
583 document.getElementById('hamdard-send-button').disabled = false; 584 document.getElementById('hamdard-message-input').disabled = false; 585 document.getElementById('hamdard-message-input').focus(); 586 587 const typingIndicator = document.getElementById('hamdard-typing-indicator'); 588 if (typingIndicator) typingIndicator.remove(); 589 } 590 591 renderQuickReplies() { 592 this.renderQuickRepliesArray(QUICK_REPLIES); 593 } 594 595 renderQuickRepliesArray(repliesArray) { 596 const quickRepliesContainer = document.getElementById('hamdard-quick-replies'); 597 if (!quickRepliesContainer) return; 598 599 if (!repliesArray || repliesArray.length === 0) { 600 quickRepliesContainer.innerHTML = ''; 601 return; 602 } 603 604 const repliesHTML = repliesArray.slice(0, 3).map(reply => 605 `<button class="hamdard-quick-reply" data-val="${reply.split(' / ')[0]}">${reply.split(' / ')[0]}</button>` 606 ).join(''); 607 608 quickRepliesContainer.innerHTML = repliesHTML; 609 } 610 } 611 612 if (document.readyState === 'loading') { 613 document.addEventListener('DOMContentLoaded', () => window.hamdardChatbot = new WordPressChatbot()); 614 } else { 615 window.hamdardChatbot = new WordPressChatbot(); 616 } 617})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.