var domainName = document.currentScript.getAttribute("domainname") let currentScriptElement = document.currentScript let liveChatFlowload = false // Main Live Chat const mainLiveChatDiv = document.createElement('div') mainLiveChatDiv.className = "mainLiveChatDiv" // For the Shadow Root const bodyElement = mainLiveChatDiv.attachShadow({ mode: 'open' }); let appearance = mainLiveChatDiv.getAttribute('appearance'); // Will Add the Styles file. var link = document.createElement("link"); link.rel = "stylesheet"; link.type = "text/css"; link.href = `${domainName}/build/assets/plugins/livechat/livechat.css?v_3`; // will add the Bootstrap Styles var BootstrapStyles = document.createElement("link"); BootstrapStyles.rel = "stylesheet"; BootstrapStyles.type = "text/css"; BootstrapStyles.href = `${domainName}/build/assets/plugins/bootstrap/css/bootstrap.css`; bodyElement.appendChild(BootstrapStyles); //will add the web-socket.js file . var script = document.createElement("script"); script.setAttribute('domainName', domainName) script.src = `${domainName}/build/assets/plugins/livechat/web-socket.js`; script.setAttribute("wsport", currentScriptElement.getAttribute("wsport")) script.defer = true; link.onload = function () { script.onload = function () { if (!localStorage.getItem('presentChatIp')) { const ipgetInfo = async () => { try { const response = await fetch('https://ipinfo.io/json'); if (!response.ok) { throw new Error('Network response was not ok'); } const data = await response.json(); localStorage.setItem('presentChatIp', data.ip); } catch (error) { console.error('Failed to fetch IP address:', error); } }; ipgetInfo(); } let audioBlob; function startRecording() { const voiceRecorderButton = bodyElement.querySelector('.voiceRecorderButton'); if(voiceRecorderButton){ // Detach any existing onclick handlers to avoid duplicating handlers voiceRecorderButton.onclick = null; voiceRecorderButton.onclick = (e) => { navigator.mediaDevices.getUserMedia({ audio: true }) .then(function (stream) { voiceRecorderButton.classList.toggle('btn-active') let audioChunks = []; let mediaRecorder = new MediaRecorder(stream, { mimeType: 'audio/webm; codecs=opus' }); mediaRecorder.start(); mediaRecorder.ondataavailable = function (event) { audioChunks.push(event.data); }; // Setup stop handling once inside the recording session voiceRecorderButton.onclick = () => { if (mediaRecorder && mediaRecorder.state !== "inactive") { mediaRecorder.stop(); // stop recording } }; mediaRecorder.onstop = function () { voiceRecorderButton.classList.toggle('btn-active') audioBlob = new Blob(audioChunks, { type: 'audio/webm; codecs=opus' }); // Specify codec in Blob const audioUrl = URL.createObjectURL(audioBlob); let audioElement = document.createElement('div'); audioElement.classList.add('audio-container'); audioElement.innerHTML = ` <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-trash text-danger cursor-pointer" viewBox="0 0 16 16"> <path d="M5.5 5.5A.5.5 0 0 1 6 6v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5m2.5 0a.5.5 0 0 1 .5.5v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5m3 .5a.5.5 0 0 0-1 0v6a.5.5 0 0 0 1 0z"/> <path d="M14.5 3a1 1 0 0 1-1 1H13v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V4h-.5a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1H6a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1h3.5a1 1 0 0 1 1 1zM4.118 4 4 4.059V13a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V4.059L11.882 4zM2.5 3h11V2h-11z"/> </svg> <audio id="audio-player" controls="" src="${audioUrl}" style="width: 240px;"></audio> `; const existingAudioPlayer = bodyElement.querySelector('#audio-player'); if (existingAudioPlayer) { existingAudioPlayer.parentNode.replaceChild(audioElement, existingAudioPlayer); bodyElement.querySelector('.text-danger.cursor-pointer').remove(); } else { bodyElement.querySelector('.popup-messages-footer').insertBefore(audioElement, bodyElement.querySelector('.popup-messages-footer .chat-footer-icons')); } // Ensure all tracks are stopped stream.getTracks().forEach(track => track.stop()); bodyElement.querySelector('.cursor-pointer.text-danger').onclick = () => { audioElement.remove(); } // Re-attach the handler for a new recording startRecording(); }; // Optionally update a UI element to indicate that recording has started // document.getElementById('recording-status').innerText = "Recording..."; }) .catch(function (error) { alert("Error accessing microphone. Please connect a microphone"); console.error("Error accessing microphone", error); // Optionally update a UI element to indicate that the microphone is unavailable // document.getElementById('recording-status').innerText = "Microphone access denied or unavailable."; }); }; } } // // with visualiser // let audioBlob; // const audioContext = new (window.AudioContext || window.webkitAudioContext)(); // Audio context for visualizer // let audioSource; // let drawVisual; // function startRecording() { // const voiceRecorderButton = bodyElement.querySelector('.voiceRecorderButton'); // const visualizerCanvas = bodyElement.querySelector('.visualizer'); // const micIcon = bodyElement.querySelector('.mic-icon'); // // Detach any existing onclick handlers to avoid duplicating handlers // voiceRecorderButton.onclick = null; // voiceRecorderButton.onclick = async () => { // try { // const stream = await navigator.mediaDevices.getUserMedia({ audio: true }); // audioContext.resume(); // Make sure the AudioContext is not suspended // const audioSource = audioContext.createMediaStreamSource(stream); // const analyser = audioContext.createAnalyser(); // audioSource.connect(analyser); // visualizerCanvas.style.display = 'block'; // micIcon.style.display = 'none'; // analyser.fftSize = 2048; // const bufferLength = analyser.frequencyBinCount; // const dataArray = new Uint8Array(bufferLength); // function draw() { // drawVisual = requestAnimationFrame(draw); // analyser.getByteTimeDomainData(dataArray); // let canvasCtx = visualizerCanvas.getContext('2d'); // canvasCtx.fillStyle = 'rgb(200, 200, 200)'; // canvasCtx.fillRect(0, 0, visualizerCanvas.width, visualizerCanvas.height); // canvasCtx.lineWidth = 2; // canvasCtx.strokeStyle = 'rgb(0, 0, 0)'; // canvasCtx.beginPath(); // let sliceWidth = visualizerCanvas.width * 1.0 / bufferLength; // let x = 0; // for(let i = 0; i < bufferLength; i++) { // let v = dataArray[i] / 128.0; // let y = v * visualizerCanvas.height / 2; // if(i === 0) { // canvasCtx.moveTo(x, y); // } else { // canvasCtx.lineTo(x, y); // } // x += sliceWidth; // } // canvasCtx.lineTo(visualizerCanvas.width, visualizerCanvas.height/2); // canvasCtx.stroke(); // } // draw(); // let audioChunks = []; // const mediaRecorder = new MediaRecorder(stream, { mimeType: 'audio/webm; codecs=opus' }); // mediaRecorder.ondataavailable = e => audioChunks.push(e.data); // mediaRecorder.start(); // mediaRecorder.ondataavailable = function (event) { // audioChunks.push(event.data); // }; // // Setup stop handling once inside the recording session // voiceRecorderButton.onclick = () => { // if (mediaRecorder && mediaRecorder.state !== "inactive") { // mediaRecorder.stop(); // stop recording // cancelAnimationFrame(drawVisual); // Stop drawing when recording stops // visualizerCanvas.style.display = 'none'; // micIcon.style.display = 'block'; // } // }; // mediaRecorder.onstop = function () { // audioBlob = new Blob(audioChunks, { type: 'audio/webm; codecs=opus' }); // Specify codec in Blob // const audioUrl = URL.createObjectURL(audioBlob); // let audioElement = document.createElement('div'); // audioElement.innerHTML = ` // <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-trash text-danger cursor-pointer" viewBox="0 0 16 16"> // <path d="M5.5 5.5A.5.5 0 0 1 6 6v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5m2.5 0a.5.5 0 0 1 .5.5v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5m3 .5a.5.5 0 0 0-1 0v6a.5.5 0 0 0 1 0z"/> // <path d="M14.5 3a1 1 0 0 1-1 1H13v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V4h-.5a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1H6a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1h3.5a1 1 0 0 1 1 1zM4.118 4 4 4.059V13a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V4.059L11.882 4zM2.5 3h11V2h-11z"/> // </svg> // <audio id="audio-player" controls="" src="${audioUrl}" style="width: 240px;"></audio> // `; // const existingAudioPlayer = bodyElement.querySelector('#audio-player'); // if (existingAudioPlayer) { // existingAudioPlayer.parentNode.replaceChild(audioElement, existingAudioPlayer); // bodyElement.querySelector('.text-danger.cursor-pointer').remove(); // } else { // bodyElement.querySelector('.popup-messages-footer').insertBefore(audioElement, bodyElement.querySelector('.popup-messages-footer .chat-footer-icons')); // } // // Ensure all tracks are stopped // stream.getTracks().forEach(track => track.stop()); // bodyElement.querySelector('.cursor-pointer.text-danger').onclick = () => { // audioElement.remove(); // } // // Re-attach the handler for a new recording // startRecording(); // }; // // Optionally update a UI element to indicate that recording has started // // document.getElementById('recording-status').innerText = "Recording..."; // } // catch (error) { // alert("Error accessing microphone. Please connect a microphone"); // console.error("Error accessing microphone", error); // // Optionally update a UI element to indicate that the microphone is unavailable // // document.getElementById('recording-status').innerText = "Microphone access denied or unavailable."; // }; // }; // } // tooltip initialization function initializeTooltips() { var tooltipElements = bodyElement.querySelectorAll('[data-bs-toggle="tooltip"]'); tooltipElements.forEach(function (element) { if (element) { new bootstrap.Tooltip(element); } }); } // Which will use to get the API data const getDataAPI = async (endPoint) => { const responce = await fetch(`${domainName}/livechat/${endPoint}`) let data = await responce.json() return data } // Which use to Post the data to API const postDataAPI = async (postdata, endPoint) => { const url = `${domainName}/livechat/${endPoint}`; let data = await fetch(url, { method: "POST", headers: { 'Content-Type': 'application/json', 'X-Csrf-Token': 'N7J5vyQ9AcmVQW9dA2n4AJV1OcWzJ4pW2umV0QoI', 'X-Requested-With': 'XMLHttpRequest', 'Accept': 'application/json, text/javascript, */*; q=0.01', }, body: JSON.stringify(postdata), }).then(response => response.text()) return data } // To getting the Country Name function getCountryName(countryCode) { const countryMapping = { "BD": "Bangladesh", "BE": "Belgium", "BF": "Burkina Faso", "BG": "Bulgaria", "BA": "Bosnia and Herzegovina", "BB": "Barbados", "WF": "Wallis and Futuna", "BL": "Saint Barthelemy", "BM": "Bermuda", "BN": "Brunei", "BO": "Bolivia", "BH": "Bahrain", "BI": "Burundi", "BJ": "Benin", "BT": "Bhutan", "JM": "Jamaica", "BV": "Bouvet Island", "BW": "Botswana", "WS": "Samoa", "BQ": "Bonaire, Saint Eustatius and Saba ", "BR": "Brazil", "BS": "Bahamas", "JE": "Jersey", "BY": "Belarus", "BZ": "Belize", "RU": "Russia", "RW": "Rwanda", "RS": "Serbia", "TL": "East Timor", "RE": "Reunion", "TM": "Turkmenistan", "TJ": "Tajikistan", "RO": "Romania", "TK": "Tokelau", "GW": "Guinea-Bissau", "GU": "Guam", "GT": "Guatemala", "GS": "South Georgia and the South Sandwich Islands", "GR": "Greece", "GQ": "Equatorial Guinea", "GP": "Guadeloupe", "JP": "Japan", "GY": "Guyana", "GG": "Guernsey", "GF": "French Guiana", "GE": "Georgia", "GD": "Grenada", "GB": "United Kingdom", "GA": "Gabon", "SV": "El Salvador", "GN": "Guinea", "GM": "Gambia", "GL": "Greenland", "GI": "Gibraltar", "GH": "Ghana", "OM": "Oman", "TN": "Tunisia", "JO": "Jordan", "HR": "Croatia", "HT": "Haiti", "HU": "Hungary", "HK": "Hong Kong", "HN": "Honduras", "HM": "Heard Island and McDonald Islands", "VE": "Venezuela", "PR": "Puerto Rico", "PS": "Palestinian Territory", "PW": "Palau", "PT": "Portugal", "SJ": "Svalbard and Jan Mayen", "PY": "Paraguay", "IQ": "Iraq", "PA": "Panama", "PF": "French Polynesia", "PG": "Papua New Guinea", "PE": "Peru", "PK": "Pakistan", "PH": "Philippines", "PN": "Pitcairn", "PL": "Poland", "PM": "Saint Pierre and Miquelon", "ZM": "Zambia", "EH": "Western Sahara", "EE": "Estonia", "EG": "Egypt", "ZA": "South Africa", "EC": "Ecuador", "IT": "Italy", "VN": "Vietnam", "SB": "Solomon Islands", "ET": "Ethiopia", "SO": "Somalia", "ZW": "Zimbabwe", "SA": "Saudi Arabia", "ES": "Spain", "ER": "Eritrea", "ME": "Montenegro", "MD": "Moldova", "MG": "Madagascar", "MF": "Saint Martin", "MA": "Morocco", "MC": "Monaco", "UZ": "Uzbekistan", "MM": "Myanmar", "ML": "Mali", "MO": "Macao", "MN": "Mongolia", "MH": "Marshall Islands", "MK": "Macedonia", "MU": "Mauritius", "MT": "Malta", "MW": "Malawi", "MV": "Maldives", "MQ": "Martinique", "MP": "Northern Mariana Islands", "MS": "Montserrat", "MR": "Mauritania", "IM": "Isle of Man", "UG": "Uganda", "TZ": "Tanzania", "MY": "Malaysia", "MX": "Mexico", "IL": "Israel", "FR": "France", "IO": "British Indian Ocean Territory", "SH": "Saint Helena", "FI": "Finland", "FJ": "Fiji", "FK": "Falkland Islands", "FM": "Micronesia", "FO": "Faroe Islands", "NI": "Nicaragua", "NL": "Netherlands", "NO": "Norway", "NA": "Namibia", "VU": "Vanuatu", "NC": "New Caledonia", "NE": "Niger", "NF": "Norfolk Island", "NG": "Nigeria", "NZ": "New Zealand", "NP": "Nepal", "NR": "Nauru", "NU": "Niue", "CK": "Cook Islands", "XK": "Kosovo", "CI": "Ivory Coast", "CH": "Switzerland", "CO": "Colombia", "CN": "China", "CM": "Cameroon", "CL": "Chile", "CC": "Cocos Islands", "CA": "Canada", "CG": "Republic of the Congo", "CF": "Central African Republic", "CD": "Democratic Republic of the Congo", "CZ": "Czech Republic", "CY": "Cyprus", "CX": "Christmas Island", "CR": "Costa Rica", "CW": "Curacao", "CV": "Cape Verde", "CU": "Cuba", "SZ": "Swaziland", "SY": "Syria", "SX": "Sint Maarten", "KG": "Kyrgyzstan", "KE": "Kenya", "SS": "South Sudan", "SR": "Suriname", "KI": "Kiribati", "KH": "Cambodia", "KN": "Saint Kitts and Nevis", "KM": "Comoros", "ST": "Sao Tome and Principe", "SK": "Slovakia", "KR": "South Korea", "SI": "Slovenia", "KP": "North Korea", "KW": "Kuwait", "SN": "Senegal", "SM": "San Marino", "SL": "Sierra Leone", "SC": "Seychelles", "KZ": "Kazakhstan", "KY": "Cayman Islands", "SG": "Singapore", "SE": "Sweden", "SD": "Sudan", "DO": "Dominican Republic", "DM": "Dominica", "DJ": "Djibouti", "DK": "Denmark", "VG": "British Virgin Islands", "DE": "Germany", "YE": "Yemen", "DZ": "Algeria", "US": "United States", "UY": "Uruguay", "YT": "Mayotte", "UM": "United States Minor Outlying Islands", "LB": "Lebanon", "LC": "Saint Lucia", "LA": "Laos", "TV": "Tuvalu", "TW": "Taiwan", "TT": "Trinidad and Tobago", "TR": "Turkey", "LK": "Sri Lanka", "LI": "Liechtenstein", "LV": "Latvia", "TO": "Tonga", "LT": "Lithuania", "LU": "Luxembourg", "LR": "Liberia", "LS": "Lesotho", "TH": "Thailand", "TF": "French Southern Territories", "TG": "Togo", "TD": "Chad", "TC": "Turks and Caicos Islands", "LY": "Libya", "VA": "Vatican", "VC": "Saint Vincent and the Grenadines", "AE": "United Arab Emirates", "AD": "Andorra", "AG": "Antigua and Barbuda", "AF": "Afghanistan", "AI": "Anguilla", "VI": "U.S. Virgin Islands", "IS": "Iceland", "IR": "Iran", "AM": "Armenia", "AL": "Albania", "AO": "Angola", "AQ": "Antarctica", "AS": "American Samoa", "AR": "Argentina", "AU": "Australia", "AT": "Austria", "AW": "Aruba", "IN": "India", "AX": "Aland Islands", "AZ": "Azerbaijan", "IE": "Ireland", "ID": "Indonesia", "UA": "Ukraine", "QA": "Qatar", "MZ": "Mozambique" }; return countryMapping[countryCode?.toUpperCase()] || 'Unknown Country'; } // popupicon draggable code start var nowDraggainginprogress = 'notinprocess'; function dragElement(elmnt) { let ulMove = bodyElement.querySelector('.chat-popup-list') var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0; if (bodyElement.getElementById(elmnt.id + "header")) { bodyElement.getElementById(elmnt.id + "header").onmousedown = dragMouseDown; } else { elmnt.onmousedown = dragMouseDown; } function dragMouseDown(e) { e = e || window.event; e.preventDefault(); pos3 = e.clientX; pos4 = e.clientY; nowDraggainginprogress = 'notinprocess'; document.onmouseup = closeDragElement; document.onmousemove = elementDrag; } function elementDrag(e) { nowDraggainginprogress = 'inprogress'; e = e || window.event; e.preventDefault(); pos1 = pos3 - e.clientX; pos2 = pos4 - e.clientY; pos3 = e.clientX; pos4 = e.clientY; elmnt.style.top = (elmnt.offsetTop - pos2) + "px"; elmnt.style.left = (elmnt.offsetLeft - pos1) + "px"; // Move the ulMove element if it exists if (ulMove && ulMove.classList.contains('chat-popup-list-lg')) { ulMove.classList.remove('firstClass'); ulMove.style.top = (elmnt.offsetTop - pos2) - 205 + "px"; ulMove.style.left = (elmnt.offsetLeft - pos1) + 2 +"px"; } else if(ulMove && !ulMove.classList.contains('chat-popup-list-lg')) { ulMove.classList.remove('firstClass'); ulMove.style.top = (elmnt.offsetTop - pos2) - 178 + "px"; ulMove.style.left = (elmnt.offsetLeft - pos1) -1 + "px"; } } function closeDragElement() { document.onmouseup = null; document.onmousemove = null; } } // popupicon draggable code end let popupButton; let chatMessagePopup = document.createElement("div") chatMessagePopup.className = "chat-message-popup card mb-4 animated chat-message-pop-default" chatMessagePopup.setAttribute('appearance', appearance) chatMessagePopup.innerHTML = ` <div class="popup-head"> <div class="row"> <div class="col-8 before-chatstart"> <h4 class="mb-3 livechatpopuptitle"></h4> <span class="d-block fs-13 livechatpopupsubtitle"> </span> </div> <div class="col-4"> <div class="dropdown"> <div class="dropdown-menu dropdown-menu-left dropdown-menu-arrow" style=""> <a class="dropdown-item dropdownCloseBtn" href="javascript:void(0);"> <i class="fe fe-thumbs-up text-primary me-1"></i> Close </a> </div> </div> <div class="d-flex align-items-center gap-4 justify-content-end supportusersdata"> <div class="d-flex align-items-center gap-2"> <a class="popup-minimize-normal" href="javascript:void(0);"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-chevron-down text-white" viewBox="0 0 16 16"> <path fill-rule="evenodd" d="M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708"/> </svg> </a> <a class="feedBackBtn d-none" href="javascript:void(0);"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-x text-white" viewBox="0 0 16 16"> <path d="M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708"/> </svg> </a> <a class="popup-minimize" href="javascript:void(0);"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-x text-white" viewBox="0 0 16 16"> <path d="M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708"/> </svg> </a> <a class="popup-minimize-fullscreen" href="javascript:void(0);"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-x text-white" viewBox="0 0 16 16"> <path d="M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708"/> </svg> </a> </div> </div> </div> </div> </div> <div class="p-2 px-4 fs-12 online-status-indicator"> </div> <div class="popup-chat-main-body"> </div> ` bodyElement.appendChild(chatMessagePopup) // To remove the chat Message Popup chatMessagePopup.querySelector('.popup-minimize-normal').onclick = () => { chatMessagePopup.classList.remove("active") popupButton.classList.remove("d-none") } chatMessagePopup.querySelector('.dropdownCloseBtn').onclick = () => { chatMessagePopup.classList.remove("active") popupButton.classList.remove("d-none") } let popupList; const addButtonScript = (data) => { if (!bodyElement.querySelector('.chat-popup-active')) { // create all icons if (!currentScriptElement.getAttribute('testitout') && ((data.whatsappEnabled == 'on' && data.whatsappNumber != null) || (data.instagramEnabled == 'on' && data.instagramUsername != null))) { // Adding the chat Popup Button popupButton = document.createElement("a"); // popupButton.id = "chat-popup" popupButton.id = "chat-popup" popupButton.setAttribute('appearance', appearance) popupButton.className = "chat-popup-active1 chat-popup-active d-none" let whatsappIcon = (data.whatsappEnabled == 'on' && data.whatsappNumber != null) ? ` <li class="mb-2"> <a href="https://wa.me/${data.whatsappNumber}" target="_blank" class="chat-icon whatsapp" data-bs-toggle="tooltip" data-bs-placement="left" title="Whatsapp Chat"> <svg xmlns="http://www.w3.org/2000/svg" width="25" height="25" fill="currentColor" class="bi bi-whatsapp text-fixed-white" viewBox="0 0 16 16"> <path d="M13.601 2.326A7.85 7.85 0 0 0 7.994 0C3.627 0 .068 3.558.064 7.926c0 1.399.366 2.76 1.057 3.965L0 16l4.204-1.102a7.9 7.9 0 0 0 3.79.965h.004c4.368 0 7.926-3.558 7.93-7.93A7.9 7.9 0 0 0 13.6 2.326zM7.994 14.521a6.6 6.6 0 0 1-3.356-.92l-.24-.144-2.494.654.666-2.433-.156-.251a6.56 6.56 0 0 1-1.007-3.505c0-3.626 2.957-6.584 6.591-6.584a6.56 6.56 0 0 1 4.66 1.931 6.56 6.56 0 0 1 1.928 4.66c-.004 3.639-2.961 6.592-6.592 6.592m3.615-4.934c-.197-.099-1.17-.578-1.353-.646-.182-.065-.315-.099-.445.099-.133.197-.513.646-.627.775-.114.133-.232.148-.43.05-.197-.1-.836-.308-1.592-.985-.59-.525-.985-1.175-1.103-1.372-.114-.198-.011-.304.088-.403.087-.088.197-.232.296-.346.1-.114.133-.198.198-.33.065-.134.034-.248-.015-.347-.05-.099-.445-1.076-.612-1.47-.16-.389-.323-.335-.445-.34-.114-.007-.247-.007-.38-.007a.73.73 0 0 0-.529.247c-.182.198-.691.677-.691 1.654s.71 1.916.81 2.049c.098.133 1.394 2.132 3.383 2.992.47.205.84.326 1.129.418.475.152.904.129 1.246.08.38-.058 1.171-.48 1.338-.943.164-.464.164-.86.114-.943-.049-.084-.182-.133-.38-.232"/> </svg> </a> </li> ` : ''; let instagramIcon = (data.instagramEnabled == 'on' && data.instagramUsername != null) ? ` <li class="mb-2"> <a href="https://ig.me/m/${data.instagramUsername}" target="_blank" class="chat-icon messanger" data-bs-toggle="tooltip" data-bs-placement="left" title="Instagram Chat"> <svg xmlns="http://www.w3.org/2000/svg" width="25" height="25" fill="currentColor" class="bi bi-instagram text-fixed-white" viewBox="0 0 16 16"> <path d="M8 0C5.829 0 5.556.01 4.703.048 3.85.088 3.269.222 2.76.42a3.9 3.9 0 0 0-1.417.923A3.9 3.9 0 0 0 .42 2.76C.222 3.268.087 3.85.048 4.7.01 5.555 0 5.827 0 8.001c0 2.172.01 2.444.048 3.297.04.852.174 1.433.372 1.942.205.526.478.972.923 1.417.444.445.89.719 1.416.923.51.198 1.09.333 1.942.372C5.555 15.99 5.827 16 8 16s2.444-.01 3.298-.048c.851-.04 1.434-.174 1.943-.372a3.9 3.9 0 0 0 1.416-.923c.445-.445.718-.891.923-1.417.197-.509.332-1.09.372-1.942C15.99 10.445 16 10.173 16 8s-.01-2.445-.048-3.299c-.04-.851-.175-1.433-.372-1.941a3.9 3.9 0 0 0-.923-1.417A3.9 3.9 0 0 0 13.24.42c-.51-.198-1.092-.333-1.943-.372C10.443.01 10.172 0 7.998 0zm-.717 1.442h.718c2.136 0 2.389.007 3.232.046.78.035 1.204.166 1.486.275.373.145.64.319.92.599s.453.546.598.92c.11.281.24.705.275 1.485.039.843.047 1.096.047 3.231s-.008 2.389-.047 3.232c-.035.78-.166 1.203-.275 1.485a2.5 2.5 0 0 1-.599.919c-.28.28-.546.453-.92.598-.28.11-.704.24-1.485.276-.843.038-1.096.047-3.232.047s-2.39-.009-3.233-.047c-.78-.036-1.203-.166-1.485-.276a2.5 2.5 0 0 1-.92-.598 2.5 2.5 0 0 1-.6-.92c-.109-.281-.24-.705-.275-1.485-.038-.843-.046-1.096-.046-3.233s.008-2.388.046-3.231c.036-.78.166-1.204.276-1.486.145-.373.319-.64.599-.92s.546-.453.92-.598c.282-.11.705-.24 1.485-.276.738-.034 1.024-.044 2.515-.045zm4.988 1.328a.96.96 0 1 0 0 1.92.96.96 0 0 0 0-1.92m-4.27 1.122a4.109 4.109 0 1 0 0 8.217 4.109 4.109 0 0 0 0-8.217m0 1.441a2.667 2.667 0 1 1 0 5.334 2.667 2.667 0 0 1 0-5.334"/> </svg> </a> </li> ` : ''; let chatPopupButton = ` <li class="mb-2"> <a href="javascript:void(0);" id="chat-popup" class="chat-icon livechat chat-popup-active" data-bs-toggle="tooltip" data-bs-placement="left" title="Direct LiveChat"> <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-chat-left text-fixed-white" viewBox="0 0 16 16" style="display: block;"> <path d="M14 1a1 1 0 0 1 1 1v8a1 1 0 0 1-1 1H4.414A2 2 0 0 0 3 11.586l-2 2V2a1 1 0 0 1 1-1zM2 0a2 2 0 0 0-2 2v12.793a.5.5 0 0 0 .854.353l2.853-2.853A1 1 0 0 1 4.414 12H14a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2z"></path> </svg> <span class="position-absolute top-0 start-100 d-none translate-middle badge rounded-pill bg-danger unreadIndexNumberPopup"></span> </a> </li> `; popupList = document.createElement("ul"); popupList.className = "chat-popup-list firstClass mb-0 ps-0"; popupList.setAttribute('style', 'display: none') setTimeout(() => { popupList.setAttribute('appearance', appearance) }, 30); popupList.innerHTML = ` ${whatsappIcon} ${instagramIcon} ${chatPopupButton} `; popupButton.innerHTML = ` <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-chat-left feather feather-message-square text-fixed-white chat-icon1" viewBox="0 0 16 16"> <path d="M14 1a1 1 0 0 1 1 1v8a1 1 0 0 1-1 1H4.414A2 2 0 0 0 3 11.586l-2 2V2a1 1 0 0 1 1-1zM2 0a2 2 0 0 0-2 2v12.793a.5.5 0 0 0 .854.353l2.853-2.853A1 1 0 0 1 4.414 12H14a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2z"/> </svg> <svg xmlns="http://www.w3.org/2000/svg" width="25" height="25" fill="currentColor" class="bi bi-x text-fixed-white close-icon" viewBox="0 0 16 16"> <path d="M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708"/> </svg> <span class="position-absolute top-0 start-100 d-none translate-middle badge rounded-pill bg-danger unreadIndexNumberPopup"></span> <span class="chat-icon-text d-none"></span> ` bodyElement.appendChild(popupButton); popupButton.insertAdjacentElement('afterend', popupList); const chatPopupIcon = bodyElement.querySelector(".chat-popup-active1"); const chatList = bodyElement.querySelector(".chat-popup-list"); function toggleIcons() { // popupList.classList.toggle('d-none') if (chatList.classList.contains("show")) { if (chatPopupIcon.querySelector(".chat-icon1")) { chatPopupIcon.querySelector(".chat-icon1").style.display = "none"; } if (chatPopupIcon.querySelector(".unreadIndexNumberPopup")) { chatPopupIcon.querySelector(".unreadIndexNumberPopup").classList.add('d-none'); } if (chatPopupIcon.querySelector(".close-icon")) { chatPopupIcon.querySelector(".close-icon").style.display = "inline"; } popupList.style.display = ""; } else { if (chatPopupIcon.querySelector(".chat-icon1")) { chatPopupIcon.querySelector(".chat-icon1").style.display = "inline"; } if (chatPopupIcon.querySelector(".unreadIndexNumberPopup")) { chatPopupIcon.querySelector(".unreadIndexNumberPopup").classList.remove('d-none'); } if (chatPopupIcon.querySelector(".close-icon")) { chatPopupIcon.querySelector(".close-icon").style.display = "none"; } setTimeout(() => { popupList.style.display = "none"; }, 350); } } chatPopupIcon.onclick = () => { if (nowDraggainginprogress != 'inprogress') { chatList.classList.toggle("show"); toggleIcons() } }; chatList.querySelectorAll('li a').forEach(function (item) { item.onclick = () => { chatList.classList.remove("show"); // bodyElement.querySelector('.chat-popup-active').classList.toggle('d-none'); toggleIcons(); }; }); const chatPopupLink = popupList.querySelector('.chat-popup-active'); if (chatPopupLink) { chatPopupLink.onclick = () => { chatList.classList.remove("show"); if (nowDraggainginprogress === 'inprogress') { return; } chatList.style.display = 'none' toggleIcons(); if (!localStorage.getItem("LiveChatVisitor") && !localStorage?.LiveChatCust) { function fetchBrowserDetails() { const userAgent = navigator.userAgent; let browserName = "Unknown"; if (userAgent.match(/Firefox\/\d+/)) { browserName = "Firefox"; } else if (userAgent.match(/Edg\/\d+/)) { browserName = "Microsoft Edge"; } else if (userAgent.match(/Chrome\/\d+/)) { browserName = "Chrome"; } else if (userAgent.match(/Safari\/\d+/) && !userAgent.match(/Chrome\/\d+/)) { browserName = "Safari"; } else if (userAgent.match(/MSIE \d+/) || userAgent.match(/Trident.*rv:\d+/)) { browserName = "Internet Explorer"; } return browserName; } fetch('https://ipinfo.io/json') .then(response => response.json()).then(data => { let custipdata let retrundata custipdata = { "ipaddress": data.ip, "city": data.city, "state": data.region, "countrycode": data.country, "country": getCountryName(data.country), "loginurl": domainName, "browserinfo": fetchBrowserDetails(), } retrundata = postDataAPI(custipdata, 'livevisitors'); retrundata.then((resData) => { let updatedData = JSON.parse(resData) localStorage.setItem("LiveChatVisitor", updatedData?.visitordata?.visitor_unique_id) }) }) .catch(error => { console.error('Error fetching IP details:', error); }); } chatMessagePopup.classList.add("active") if (localStorage.LiveChatCust) { // For the Message Seen Indication postDataAPI(JSON.parse(localStorage.LiveChatCust), 'user-seen-messages-indication') // For the customer's online Indaction postDataAPI({ custID: JSON.parse(localStorage.LiveChatCust).id }, 'customer-online').then((ele) => { }) } // To Remove the Unread Index Number popupButton.querySelector('.unreadIndexNumberPopup').innerText = "" popupList.querySelector('.unreadIndexNumberPopup').innerText = "" popupButton.querySelector('.unreadIndexNumberPopup').classList.add("d-none") popupList.querySelector('.unreadIndexNumberPopup').classList.add("d-none") if (liveChatFlowload) { bodyElement.querySelector('.direct-chat-messages').appendChild(basedOnTimeMessageConversationFlow()) } // To scroll Down Chat bodyElement.querySelector(".popup-messages").scrollBy(0, bodyElement.querySelector(".popup-messages").scrollHeight) popupButton.classList.add('d-none'); } } } // Create only the livechat icon else { // Adding the chat Popup Button popupButton = document.createElement("a"); popupButton.id = "chat-popup" popupButton.setAttribute('appearance', appearance) popupButton.className = "chat-popup-active d-none" popupButton.onclick = () => { if (nowDraggainginprogress == 'inprogress') { return; } if (!localStorage.getItem("LiveChatVisitor") && !localStorage?.LiveChatCust) { function fetchBrowserDetails() { const userAgent = navigator.userAgent; let browserName = "Unknown"; if (userAgent.match(/Firefox\/\d+/)) { browserName = "Firefox"; } else if (userAgent.match(/Edg\/\d+/)) { browserName = "Microsoft Edge"; } else if (userAgent.match(/Chrome\/\d+/)) { browserName = "Chrome"; } else if (userAgent.match(/Safari\/\d+/) && !userAgent.match(/Chrome\/\d+/)) { browserName = "Safari"; } else if (userAgent.match(/MSIE \d+/) || userAgent.match(/Trident.*rv:\d+/)) { browserName = "Internet Explorer"; } return browserName; } fetch('https://ipinfo.io/json') .then(response => response.json()).then(data => { let custipdata let retrundata custipdata = { "ipaddress": data.ip, "city": data.city, "state": data.region, "countrycode": data.country, "country": getCountryName(data.country), "loginurl": domainName, "browserinfo": fetchBrowserDetails(), } retrundata = postDataAPI(custipdata, 'livevisitors'); retrundata.then((resData) => { let updatedData = JSON.parse(resData) localStorage.setItem("LiveChatVisitor", updatedData?.visitordata?.visitor_unique_id) }) }) .catch(error => { console.error('Error fetching IP details:', error); }); } chatMessagePopup.classList.add("active") if (localStorage.LiveChatCust) { // For the Message Seen Indication postDataAPI(JSON.parse(localStorage.LiveChatCust), 'user-seen-messages-indication') // For the customer's online Indaction postDataAPI({ custID: JSON.parse(localStorage.LiveChatCust).id }, 'customer-online').then((ele) => { }) } // To Remove the Unread Index Number popupButton.querySelector('.unreadIndexNumberPopup').innerText = "" popupButton.querySelector('.unreadIndexNumberPopup').classList.add("d-none") popupList.querySelector('.unreadIndexNumberPopup').innerText = "" popupList.querySelector('.unreadIndexNumberPopup').classList.add("d-none") if (liveChatFlowload) { bodyElement.querySelector('.direct-chat-messages').appendChild(basedOnTimeMessageConversationFlow()) } // To scroll Down Chat bodyElement.querySelector(".popup-messages").scrollBy(0, bodyElement.querySelector(".popup-messages").scrollHeight) popupButton.classList.add('d-none'); } popupButton.innerHTML = ` <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-chat-left feather feather-message-square" viewBox="0 0 16 16"> <path d="M14 1a1 1 0 0 1 1 1v8a1 1 0 0 1-1 1H4.414A2 2 0 0 0 3 11.586l-2 2V2a1 1 0 0 1 1-1zM2 0a2 2 0 0 0-2 2v12.793a.5.5 0 0 0 .854.353l2.853-2.853A1 1 0 0 1 4.414 12H14a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2z"/> </svg> <span class="position-absolute top-0 start-100 d-none translate-middle badge rounded-pill bg-danger unreadIndexNumberPopup"></span> <span class="chat-icon-text d-none"></span> ` bodyElement.appendChild(popupButton); } if (data.inspectDisable == 'on') { bodyElement.addEventListener('contextmenu', function(event) { event.preventDefault(); }); bodyElement.onkeydown = function(e) { if (e.code == 'F12') { return false; } if ((e.ctrlKey || e.metaKey) && e.shiftKey && (e.key === 'I' || e.key === 'C')) { e.preventDefault(); return false; } } } if (data.selectDisabled == 'on') { bodyElement.addEventListener('selectstart', function(event) { const editableElements = ['INPUT', 'TEXTAREA', 'DIV']; const isEditable = editableElements.some(tag => event.target.tagName === tag && event.target.isContentEditable); if (!isEditable) { event.preventDefault(); } }); } } } let pauseAudios = () => { const audios = bodyElement.querySelectorAll('audio'); // Attach event listeners to each audio element audios.forEach(audio => { audio.addEventListener('play', () => { // Pause all other audio elements audios.forEach(otherAudio => { if (otherAudio !== audio) { otherAudio.pause(); otherAudio.currentTime = 0; // Reset to the start if required } }); }); }); } // Which use to add the chat Body Content const chatBody = (htmlData, noNeedFullRefresh = true) => { if (noNeedFullRefresh) { chatMessagePopup.querySelector(".popup-chat-main-body").innerHTML = htmlData } setTimeout(() => { pauseAudios() }, 500); } // if(chatMessagePopup.classList.contains('active')){ // popupButton.classList.add("d-none"); // }else{ // popupButton.classList.remove("d-none"); // } // For the feedBackForm Form const feedBackForm = (data, livechatdata, question) => { data = data.split(",") let feedBackFormData = document.createElement("div") feedBackFormData.className = 'rating-chat-main-body' feedBackFormData.innerHTML = ` <div class="p-3"> <div class="text-start"> <button type="button" class="btn btn-primary btn-sm py-0 mb-2 downloadChart">Download Chat</button> <button type="button" class="btn btn-secondary btn-sm py-0 mb-2 emailChat">Email Chat</button> <h5 class="font-weight-bold fs-20">Thank you for Contacting Us</h5> <h6>Please rate our supportive team in the following areas </h6> <form class="mt-4"> <div class="mt-0"> <label>What is your best reason for your score <span class="text-red">*</span></label> <div class="star-ratings start-ratings-main mb-2 mt-1 clearfix"> <svg class="ratingIcon " xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" viewBox="0 0 24 24" id="star"><path d="M22,10.1c0.1-0.5-0.3-1.1-0.8-1.1l-5.7-0.8L12.9,3c-0.1-0.2-0.2-0.3-0.4-0.4C12,2.3,11.4,2.5,11.1,3L8.6,8.2L2.9,9 C2.6,9,2.4,9.1,2.3,9.3c-0.4,0.4-0.4,1,0,1.4l4.1,4l-1,5.7c0,0.2,0,0.4,0.1,0.6c0.3,0.5,0.9,0.7,1.4,0.4l5.1-2.7l5.1,2.7 c0.1,0.1,0.3,0.1,0.5,0.1l0,0c0.1,0,0.1,0,0.2,0c0.5-0.1,0.9-0.6,0.8-1.2l-1-5.7l4.1-4C21.9,10.5,22,10.3,22,10.1z"></path></svg> <svg class="ratingIcon " xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" viewBox="0 0 24 24" id="star"><path d="M22,10.1c0.1-0.5-0.3-1.1-0.8-1.1l-5.7-0.8L12.9,3c-0.1-0.2-0.2-0.3-0.4-0.4C12,2.3,11.4,2.5,11.1,3L8.6,8.2L2.9,9 C2.6,9,2.4,9.1,2.3,9.3c-0.4,0.4-0.4,1,0,1.4l4.1,4l-1,5.7c0,0.2,0,0.4,0.1,0.6c0.3,0.5,0.9,0.7,1.4,0.4l5.1-2.7l5.1,2.7 c0.1,0.1,0.3,0.1,0.5,0.1l0,0c0.1,0,0.1,0,0.2,0c0.5-0.1,0.9-0.6,0.8-1.2l-1-5.7l4.1-4C21.9,10.5,22,10.3,22,10.1z"></path></svg> <svg class="ratingIcon " xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" viewBox="0 0 24 24" id="star"><path d="M22,10.1c0.1-0.5-0.3-1.1-0.8-1.1l-5.7-0.8L12.9,3c-0.1-0.2-0.2-0.3-0.4-0.4C12,2.3,11.4,2.5,11.1,3L8.6,8.2L2.9,9 C2.6,9,2.4,9.1,2.3,9.3c-0.4,0.4-0.4,1,0,1.4l4.1,4l-1,5.7c0,0.2,0,0.4,0.1,0.6c0.3,0.5,0.9,0.7,1.4,0.4l5.1-2.7l5.1,2.7 c0.1,0.1,0.3,0.1,0.5,0.1l0,0c0.1,0,0.1,0,0.2,0c0.5-0.1,0.9-0.6,0.8-1.2l-1-5.7l4.1-4C21.9,10.5,22,10.3,22,10.1z"></path></svg> <svg class="ratingIcon" xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" viewBox="0 0 24 24" id="star"><path d="M22,10.1c0.1-0.5-0.3-1.1-0.8-1.1l-5.7-0.8L12.9,3c-0.1-0.2-0.2-0.3-0.4-0.4C12,2.3,11.4,2.5,11.1,3L8.6,8.2L2.9,9 C2.6,9,2.4,9.1,2.3,9.3c-0.4,0.4-0.4,1,0,1.4l4.1,4l-1,5.7c0,0.2,0,0.4,0.1,0.6c0.3,0.5,0.9,0.7,1.4,0.4l5.1-2.7l5.1,2.7 c0.1,0.1,0.3,0.1,0.5,0.1l0,0c0.1,0,0.1,0,0.2,0c0.5-0.1,0.9-0.6,0.8-1.2l-1-5.7l4.1-4C21.9,10.5,22,10.3,22,10.1z"></path></svg> <svg class="ratingIcon" xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" viewBox="0 0 24 24" id="star"><path d="M22,10.1c0.1-0.5-0.3-1.1-0.8-1.1l-5.7-0.8L12.9,3c-0.1-0.2-0.2-0.3-0.4-0.4C12,2.3,11.4,2.5,11.1,3L8.6,8.2L2.9,9 C2.6,9,2.4,9.1,2.3,9.3c-0.4,0.4-0.4,1,0,1.4l4.1,4l-1,5.7c0,0.2,0,0.4,0.1,0.6c0.3,0.5,0.9,0.7,1.4,0.4l5.1-2.7l5.1,2.7 c0.1,0.1,0.3,0.1,0.5,0.1l0,0c0.1,0,0.1,0,0.2,0c0.5-0.1,0.9-0.6,0.8-1.2l-1-5.7l4.1-4C21.9,10.5,22,10.3,22,10.1z"></path></svg> </div> </div> <div class="mt-0"> <label>${question} <span class="text-red">*</span></label> <div class="star-ratings start-ratings-main my-2 clearfix"> <div class="stars stars-example-fontawesome star-sm"> <div class="form-check ps-0"> ${data.map((option, index) => { return ( `<input type="radio" class="rating-fontawesome" name="rating" value='${option}' id="flexRadioDefault${index}" onchange="handleChange(event)"> <label for="flexRadioDefault${index}"> ${option} </label><br/>` ) }).join('')} </div> </div> </div> </div> <div class="mt-3"> <label>Could you please provide additional feedback for us? <span class="text-red">*</span></label> <textarea class="form-control mt-2 feedBackData" rows="5" cols="50" placeholder="Type Here..."></textarea> </div> <button disabled type="button" class="btn btn-success px-5 mt-4 btn-chat-close submitFeedBackBtn" href="javascript:void(0);">Submit your Review</button> </form> </div> </div> ` // Rating click Function feedBackFormData.querySelectorAll(".ratingIcon").forEach((star, index) => { star.addEventListener('click', function () { feedBackFormData.querySelectorAll(".ratingIcon").forEach(s => s.classList.remove('checked')); for (let i = 0; i <= index; i++) { feedBackFormData.querySelectorAll(".ratingIcon")[i].classList.add('checked'); } if (!feedBackFormData.querySelector(".rating-fontawesome:checked")?.value || !bodyElement.querySelector(".feedBackData").value) { feedBackFormData.querySelector(".submitFeedBackBtn").disabled = true; } else { feedBackFormData.querySelector(".submitFeedBackBtn").disabled = false; } }); }) // feed back Form submit feedBackFormData.querySelector(".submitFeedBackBtn").onclick = () => { feedBackFormData.querySelector(".submitFeedBackBtn").innerHTML = 'submiting ... '; feedBackFormData.querySelector(".submitFeedBackBtn").disabled = true; let feedBackData = { starRating: feedBackFormData.querySelectorAll(".ratingIcon.checked").length, problemRectified: feedBackFormData.querySelector(".rating-fontawesome:checked").value, feedBackData: feedBackFormData.querySelector(".feedBackData").value } let data = { message: JSON.stringify(feedBackData), username: liveChatCust.username, id: liveChatCust.id, customerId: liveChatCust.id, messageType: "feedBack" } postDataAPI(data, 'broadcast-message').then((res) => { chatBody(messageConversation()) startRecording(); emojiLoader(); feedBackFormData.querySelectorAll(".ratingIcon").forEach(e => e.classList.remove("checked")); if (feedBackFormData.querySelector(".rating-fontawesome:checked")) { feedBackFormData.querySelector(".rating-fontawesome:checked").checked = false; } feedBackFormData.querySelector(".feedBackData").value = ""; chatMessagePopup.classList.remove("rating-section-body") bodyElement.querySelector(".feedBackBtn").classList.add('d-none') // To Scroll Down the Conversation bodyElement.querySelector(".popup-messages").scrollBy(0, bodyElement.querySelector(".popup-messages").scrollHeight) }) } // To append the feedBackFormData if (!chatMessagePopup.querySelector(".rating-chat-main-body")) { chatMessagePopup.appendChild(feedBackFormData) bodyElement.querySelector(".feedBackData").oninput = (res => { if (feedBackFormData.querySelector(".rating-fontawesome:checked")?.value && bodyElement.querySelectorAll(".ratingIcon.checked").length && bodyElement.querySelector(".feedBackData").value) { bodyElement.querySelector(".submitFeedBackBtn").disabled = false } else { bodyElement.querySelector(".submitFeedBackBtn").disabled = true } }) } window.handleChange = (event) => { if (bodyElement.querySelectorAll(".ratingIcon.checked").length && bodyElement.querySelector(".feedBackData").value) { feedBackFormData.querySelector(".submitFeedBackBtn").disabled = false; } else { feedBackFormData.querySelector(".submitFeedBackBtn").disabled = true; } }; function downloadTextFile(filename, textContent) { const blob = new Blob([textContent], { type: 'text/plain' }); const url = URL.createObjectURL(blob); const link = document.createElement('a'); link.href = url; link.download = filename; link.click(); URL.revokeObjectURL(url); } // For the Text file DownLoad const filename = 'liveChatConversation.txt'; const modifiedData = livechatdata.map(item => `${item.created_at} - ${item.livechat_username} - ${item.message}`); const textContent = JSON.stringify(modifiedData, null, 4); feedBackFormData.querySelector(".downloadChart").onclick = () => { downloadTextFile(filename, textContent); } // Send email the text file feedBackFormData.querySelector(".emailChat").onclick = () => { let userInfo = JSON.parse(localStorage.LiveChatCust) const formData = new FormData(); formData.append('file', new Blob([textContent], { type: 'text/plain' }), filename); formData.append('email', userInfo?.email); fetch(`${domainName}/livechat/livechat-download-file`, { method: 'POST', body: formData, headers: { 'X-Csrf-Token': 'N7J5vyQ9AcmVQW9dA2n4AJV1OcWzJ4pW2umV0QoI', 'X-Requested-With': 'XMLHttpRequest', 'Accept': 'application/json, text/javascript, */*; q=0.01', }, }).then((res) => res.json()).then(data => { alert(data.message) }) } } let FlowChatConversation = [] // Welcome Form const welcomeForm = (onFlowmessage, offlineSendMessage) => { // To Get The IP let ipAddress = [] let geolocationPermission = false fetch('https://ipinfo.io/json') .then(response => response.json()) .then(data => { ipAddress = data }) .catch((error) => { console.error('Error fetching IP address:', error) ipAddress.ip = 'null' ipAddress.city = 'null' ipAddress.region = 'null' ipAddress.timezone = 'null' }); // To get the User Browser Name function getBrowserName() { if (typeof navigator.userAgentData !== 'undefined') { // Use navigator.userAgentData if available (Chrome, Edge, Opera) return navigator.userAgentData.brands[navigator.userAgentData.brands.length - 1].brand; } else { // Fallback to parsing the User-Agent string const userAgent = navigator.userAgent; let browserName; if (userAgent.match(/Firefox\//i)) { browserName = "Firefox"; } else if (userAgent.match(/Chrome\//i)) { browserName = "Chrome"; } else if (userAgent.match(/Edge\//i)) { browserName = "Edge"; } else if (userAgent.match(/Safari\//i)) { browserName = "Safari"; } else if (userAgent.match(/Opera\//i)) { browserName = "Opera"; } else if (userAgent.match(/MSIE\//i)) { browserName = "Internet Explorer"; } else { browserName = "Unknown"; } return browserName; } } // To get the geolocation data if (navigator.geolocation) { navigator.geolocation.getCurrentPosition(getLoc, errorlog) } function getLoc(data) { geolocationPermission = true const latitude = data.coords.latitude; const longitude = data.coords.longitude; // Construct the Nominatim API URL const apiUrl = `https://nominatim.openstreetmap.org/reverse?lat=${latitude}&lon=${longitude}&format=json`; // Make a request to the API fetch(apiUrl) .then(response => response.json()) .then(data => { if (data) { const address = data; geolocationPermission = address } else { console.error('Unable to retrieve address.'); } }) .catch(error => { console.error('Error fetching data from Nominatim API:', error); }); } function errorlog(data) { geolocationPermission = false } // To send the form data to DB myFunction = () => { // To disabled the submit Button bodyElement.querySelector("#chatUserdata [type='button']").disabled = true let Userdata = bodyElement.querySelector("#chatUserdata"); const formData = new FormData(Userdata); var name = formData.get('name'); var email = formData.get('email'); var mobile = formData.get('mobilenumber'); // Clear existing errors Userdata.querySelectorAll('.errorFormMessage').forEach(elem => elem.classList.remove('errorFormMessage')); Userdata.querySelectorAll('.text-danger').forEach(elem => elem.remove()); let errors = []; // Check for name if (!name) { Userdata.querySelector("#username").classList.add("errorFormMessage"); errors.push({ element: "#username", message: "Please enter your full name" }); } // Check for email if (!email) { Userdata.querySelector("#email").classList.add("errorFormMessage"); errors.push({ element: "#email", message: "Please enter your email" }); } else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) { Userdata.querySelector("#email").classList.add("errorFormMessage"); errors.push({ element: "#email", message: "Please enter a valid email address." }); } // Check for mobile if (!mobile) { Userdata.querySelector("#mobile").classList.add("errorFormMessage"); errors.push({ element: "#mobile", message: "Please enter your mobile number" }); } errors.forEach(error => { let errorSpan = document.createElement("span"); errorSpan.className = "text-danger ms-2"; errorSpan.innerText = error.message; Userdata.querySelector(error.element).closest("div").appendChild(errorSpan); }); if (errors.length > 0) { bodyElement.querySelector("#chatUserdata [type='button']").disabled = false; } else { let postData if (geolocationPermission) { postData = { "name": formData.get("name"), "email": formData.get("email"), "mobilenumber": formData.get("mobilenumber"), "browserAndOSInfo": getBrowserName(), "flowChatMessages": JSON.stringify(FlowChatConversation), "loginurl": location.href, "fullAddress": geolocationPermission.display_name, "loginIp": ipAddress.ip, "city": geolocationPermission.address.city, "state": geolocationPermission.address.state, "timezone": ipAddress.timezone, "country": geolocationPermission.address.country, "visitoruniqueid": localStorage.getItem("LiveChatVisitor") ? localStorage.getItem("LiveChatVisitor") : null, "message": onFlowmessage, } } else { postData = { "name": formData.get("name"), "email": formData.get("email"), "mobilenumber": formData.get("mobilenumber"), "browserAndOSInfo": getBrowserName(), "flowChatMessages": JSON.stringify(FlowChatConversation), "loginurl": location.href, "fullAddress": `${ipAddress.city}, ${ipAddress.region}, ${getCountryName(ipAddress.country)}`, "loginIp": ipAddress.ip, "city": ipAddress.city, "state": ipAddress.region, "timezone": ipAddress.timezone, "country": getCountryName(ipAddress.country), "visitoruniqueid": localStorage.getItem("LiveChatVisitor") ? localStorage.getItem("LiveChatVisitor") : null, "message": onFlowmessage, } } let processData = postDataAPI(postData, 'customerdata') processData.then(data => { let responceData = JSON.parse(data) if(responceData?.message == 'domainblock'){ let errorSpan = document.createElement("span"); errorSpan.className = "text-danger ms-2"; errorSpan.innerText = responceData.error; Userdata.querySelector("#email").closest("div").appendChild(errorSpan); } if (responceData.success) { if (localStorage.getItem("LiveChatVisitor")) { localStorage.removeItem("LiveChatVisitor"); } localStorage.setItem("LiveChatCust", JSON.stringify(responceData.custdata)) // TO Add the customer Online postDataAPI({ custID: JSON.parse(localStorage.LiveChatCust).id }, 'customer-online').then((ele) => { }) // To send the First Message if (onFlowmessage) { let firstMessageData = { message: onFlowmessage, username: responceData.custdata.username, id: responceData.custdata.id, customerId: responceData.custdata.id } // To Add the first Message postDataAPI(firstMessageData, 'broadcast-message').then(subdata => { // To Send the Offline Message if (offlineSendMessage) { let liveChatCust = localStorage.LiveChatCust ? JSON.parse(localStorage.LiveChatCust) : [] let welcomeMessagedata = { message: offlineSendMessage.errorMessage, username: liveChatCust.username, id: liveChatCust.id, customerId: liveChatCust.id, messageType: "welcomeMessage" } postDataAPI(welcomeMessagedata, 'broadcast-message').then((ele) => { chatBody(messageConversation()) startRecording(); emojiLoader(); }) } else { chatBody(messageConversation()) startRecording(); emojiLoader(); } }) } } }) processData.catch(error => { console.log("error", error); }) } } // To submit the form when the user presses the Enter key setTimeout(() => { bodyElement.getElementById("chatUserdata").addEventListener("keydown", function (event) { if (event.key === "Enter") { event.preventDefault(); // Prevent the default form submission bodyElement.querySelector("#chatUserdata .wecomeFormSubmitBtn").click() } }); let submitDetailsButton = bodyElement.querySelector('.wecomeFormSubmitBtn'); const validationEvent = () => { const usernameInput = bodyElement.querySelector('#username'); const mobileInput = bodyElement.querySelector('#mobile'); const emailInput = bodyElement.querySelector('#email'); const isUsernameValid = usernameInput.value.length > 4; const isMobileValid = mobileInput.value.length > 6; const isEmailValid = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(emailInput.value); // Check all conditions if (isUsernameValid && isMobileValid && isEmailValid) { submitDetailsButton.disabled = false; } else { submitDetailsButton.disabled = true; } }; bodyElement.querySelector('#username').addEventListener('input', (ele) => { if (ele.target.value.length <= 4) { ele.target.classList.add('is-invalid'); ele.target.classList.remove('is-valid'); errorBtn = true; validationEvent(); } else { ele.target.classList.add('is-valid'); ele.target.classList.remove('is-invalid'); validationEvent(); } }) bodyElement.querySelector('#mobile').addEventListener('input', (ele) => { if (ele.target.value.length <= 6) { ele.target.classList.add('is-invalid'); ele.target.classList.remove('is-valid'); validationEvent(); } else { ele.target.classList.add('is-valid'); ele.target.classList.remove('is-invalid'); validationEvent(); } }) bodyElement.querySelector('#email').addEventListener('input', (event) => { const email = event.target.value; const isValidEmail = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email); if (!isValidEmail) { event.target.classList.add('is-invalid'); event.target.classList.remove('is-valid'); validationEvent(); } else { event.target.classList.remove('is-invalid'); event.target.classList.add('is-valid'); validationEvent(); } }); }, 1000); return (` <div class="chat-message-popup card mb-4 popup-fields"> <div class="card mb-4 popup-entry-fields"> <div class="popup-chat-main-body d-flex align-items-center justify-content-center my-auto"> <a class="popup-minimize-normal-fields text-white" href="javascript:void(0);"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-x" viewBox="0 0 16 16"> <path d="M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708"/> </svg> </a> <div class="p-4"> <div class="popup-fields-bg-top"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1440 320"><path fill="rgb(var(--primary))" fill-opacity="1" d="M0,96L48,112C96,128,192,160,288,154.7C384,149,480,107,576,101.3C672,96,768,128,864,122.7C960,117,1056,75,1152,48C1248,21,1344,11,1392,5.3L1440,0L1440,0L1392,0C1344,0,1248,0,1152,0C1056,0,960,0,864,0C768,0,672,0,576,0C480,0,384,0,288,0C192,0,96,0,48,0L0,0Z"></path></svg> </div> <h5>Enter Basic Information</h5> <div class="mb-3">Kindly provide your name and email address before we begin</div> <form id="chatUserdata"> <div class="mb-4"> <div class="mb-2"> <label for="username" class="form-label mb-1">Name <span class="text-red">*</span> :</label> <input type="text" name="name" class="form-control form-control-lg" id="username" placeholder="Enter Full Name"> </div> <div class="mb-2"> <label for="email" class="form-label mb-1">Email Id <span class="text-red">*</span> :</label> <input type="email" name="email" class="form-control form-control-lg" id="email" placeholder="Enter email"> </div> <div class="mb-2"> <label for="mobile" class="form-label mb-1">Phone No <span class="text-red">*</span> :</label> <input type="number" name="mobilenumber" class="form-control form-control-lg" id="mobile" placeholder="Enter Mobile Number"> </div> </div> <div class="d-grid"> <button type="button" onclick="myFunction()" class="btn btn-primary py-2 wecomeFormSubmitBtn">Get started</button> </div> </form> <div class="popup-fields-bg-bottom"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1440 320"><path fill="rgb(var(--primary))" fill-opacity="1" d="M0,288L48,272C96,256,192,224,288,197.3C384,171,480,149,576,165.3C672,181,768,235,864,250.7C960,267,1056,245,1152,250.7C1248,256,1344,288,1392,304L1440,320L1440,320L1392,320C1344,320,1248,320,1152,320C1056,320,960,320,864,320C768,320,672,320,576,320C480,320,384,320,288,320C192,320,96,320,48,320L0,320Z"></path></svg> </div> </div> </div> </div> </div> `) } // To add the all Message conversation let liveChatCust = localStorage.LiveChatCust ? JSON.parse(localStorage.LiveChatCust) : [] const messageConversation = () => { // to Update the liveChatCust liveChatCust = localStorage.LiveChatCust ? JSON.parse(localStorage.LiveChatCust) : [] let OfflineMessagePermission = false sendMessage = () => { if (liveChatCust && liveChatCust.userType == 'livevisitor') { // To open The welcome Form chatBody(welcomeForm(bodyElement.querySelector("#status_message").textContent, OfflineMessagePermission)) } else { afterMessageSend = false // To send the Typing Indication After message send setTimeout(() => { afterMessageSend = true }, 500); const now = new Date(); const hours = now.getHours(); const minutes = now.getMinutes(); const period = hours >= 12 ? "PM" : "AM"; function sanitizeHTML(input) { const map = { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''', '/': '/', // For forward slash '`': '`', // Backtick '=': '=' // Equals }; return input.replace(/[&<>"'/`=]/g, function (char) { return map[char]; }); } const formattedTime = `${((hours + 11) % 12) + 1}:${minutes}${period}`; if (bodyElement.querySelector("#status_message").textContent.trim()) { let data = { message: sanitizeHTML(bodyElement.querySelector("#status_message").textContent), username: liveChatCust.username, id: liveChatCust.id, customerId: liveChatCust.id } postDataAPI(data, 'broadcast-message').then((ele) => { // For the Offline Message Send var allDirectChatMsgs = bodyElement.querySelectorAll('.direct-chat-msg'); var filteredDirectChatMsgs = Array.from(allDirectChatMsgs).filter(function (element) { return !element.classList.contains('right'); }); var lastDirectChatMsg = filteredDirectChatMsgs[filteredDirectChatMsgs.length - 1]; if (OfflineMessagePermission && lastDirectChatMsg.innerText.replace(/\b\d{1,2}:\d{2}[APMapm]{2}\b/, '').trim() != OfflineMessagePermission.errorMessage.trim()) { bodyElement.querySelector('.direct-chat-messages').appendChild(OfflineMessageIndication(OfflineMessagePermission.errorMessage)) // For the Message Seen Indication if (chatMessagePopup.classList.contains('active')) { postDataAPI(JSON.parse(localStorage.LiveChatCust), 'user-seen-messages-indication') } bodyElement.querySelector(".popup-messages").scrollBy(0, bodyElement.querySelector(".popup-messages").scrollHeight) } }) bodyElement.querySelector("#status_message").textContent = "" } if (bodyElement.querySelector("#audio-player")) { var formData = new FormData(); formData.append('chatFileUpload', audioBlob, 'recording.webm'); const now = new Date(); const hours = now.getHours(); const minutes = now.getMinutes(); const period = hours >= 12 ? "PM" : "AM"; const formattedTime = `${((hours + 11) % 12) + 1}:${minutes}${period}`; fetch(`${domainName}/livechat/live-chat-image-upload`, { method: 'POST', body: formData, headers: { 'X-Csrf-Token': 'N7J5vyQ9AcmVQW9dA2n4AJV1OcWzJ4pW2umV0QoI', 'X-Requested-With': 'XMLHttpRequest', 'Accept': 'application/json, text/javascript, */*; q=0.01', }, }) .then(response => { return response.json() }) .then(resdata => { let data = { message: `${resdata.imageurl}`, username: liveChatCust.username, id: liveChatCust.id, customerId: liveChatCust.id, messageType: "audio" } postDataAPI(data, 'broadcast-message') bodyElement.querySelector("#audio-player").parentElement.remove() }) .catch(error => { console.error('Error:', error); }); } // To remove the emoji dropdown in the chatpopup bodyElement.getElementById("emojiGrid").classList.remove('d-block'); } } function formatTime(inputTime) { const date = new Date(inputTime); const hours = date.getHours(); const minutes = date.getMinutes(); const ampm = hours >= 12 ? 'PM' : 'AM'; const formattedHours = hours % 12 === 0 ? 12 : hours % 12; const formattedMinutes = minutes < 10 ? '0' + minutes : minutes; const formattedTime = `${formattedHours}:${formattedMinutes}${ampm}`; return formattedTime; } // For the Chat data function formatDateString(inputDateStr) { const inputDate = new Date(inputDateStr); const monthNames = [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ]; const year = inputDate.getFullYear(); const month = monthNames[inputDate.getMonth()]; const day = inputDate.getDate(); const formattedDate = `${day},${month} ${year}`; return formattedDate; } let customerMessage = (data) => { let custLi = document.createElement("div"); custLi.className = "direct-chat-msg right" custLi.innerHTML = ` <div class="direct-chat-text"> ${data.message_type == "image" ? ` <img class="imageMessageLiveChat" imagesrc="${data.message}" src="${data.message.toLowerCase().endsWith(".jpg") || data.message.toLowerCase().endsWith(".png") ? data.message : `${domainName}/build/assets/images/svgs/file.svg`}" class="d-block" alt="img" style="${data.message.toLowerCase().endsWith(".jpg") || data.message.toLowerCase().endsWith(".png") ? '' : 'height: 5rem;'}"> ` : data.message_type == "feedBack" ? `Your feedback has been submitted` : data.message_type == "audio" ? `<audio controls="" src="${data.message}" style="width: 240px;"></audio>` :`${data.message}`} <small class="time-text">${formatTime(data.created_at)}</small> </div> ` return custLi } let AgentMessage = (data) => { let agentLi = document.createElement("div"); agentLi.className = "direct-chat-msg" agentLi.innerHTML = ` <div class="direct-chat-text" ${data.message_type == "image" ? 'style="text-align: center;"' : ''}> ${data.message_type == "image" ? ` <img class="imageMessageLiveChat" imagesrc="${data.message}" src="${data.message.toLowerCase().endsWith(".jpg") || data.message.toLowerCase().endsWith(".png") ? data.message : `${domainName}/build/assets/images/svgs/file.svg`}" class="d-block" alt="img" style="${data.message.toLowerCase().endsWith(".jpg") || data.message.toLowerCase().endsWith(".png") ? '' : 'height: 5rem;'}"> ` : data.message_type == "audio" ? `<audio controls="" style="width: 240px;" src="${data.message}"></audio>` :`${data.message}`} <small class="time-text">${formatTime(data.created_at)}</small></div> ` return agentLi } let conversationDiv = document.createElement("div"); conversationDiv.className = "direct-chat-messages" conversationDiv.style.overflow = "hidden" getDataAPI(`singlecustdata/${JSON.parse(localStorage.LiveChatCust)?.id}`).then((data) => { if (data.nocustomerdatafound) { chatBody(messageConversationFlow()) startRecording(); localStorage.removeItem("LiveChatCust") return false } addButtonScript(data.livechatcust); if (data.livechatcust.maintenance == 'on') { return; } // To modify the size of the Live Chat icon. if (data.livechatcust.livechatIconSize == "large") { popupButton.classList.add("chat-popup-lg") if (bodyElement.querySelector('.chat-popup-list')) { bodyElement.querySelector('.chat-popup-list').classList.add('chat-popup-list-lg') } } else { popupButton.classList.remove("chat-popup-lg") if (bodyElement.querySelector('.chat-popup-list')) { bodyElement.querySelector('.chat-popup-list').classList.remove('chat-popup-list-lg') } } if (document.documentElement.getAttribute('dir') == 'rtl') { chatMessagePopup.setAttribute('dir', 'ltr'); popupButton.setAttribute('dir', 'ltr'); } // To Change the live Chat Position if (data.livechatcust.livechatPosition == "left") { mainLiveChatDiv.setAttribute('appearance', 'left'); appearance = "left"; chatMessagePopup.setAttribute('appearance', appearance) popupButton.setAttribute('appearance', appearance) chatMessagePopup.classList.add("chat-message-popup-right") popupButton.classList.add("chat-popup-right") } else { mainLiveChatDiv.setAttribute('appearance', 'right'); appearance = "right"; chatMessagePopup.setAttribute('appearance', appearance) popupButton.setAttribute('appearance', appearance) chatMessagePopup.classList.remove("chat-message-popup-right") popupButton.classList.remove("chat-popup-right") } if (bodyElement.querySelector('.chat-popup-list')) { bodyElement.querySelector('.chat-popup-list').setAttribute('appearance', appearance) } if (data.livechatcust.banstatus == 'banned' && data.livechatcust.login_ip == localStorage.getItem('presentChatIp')) { // popupButton.classList.add("d-none") return // } else { // popupButton.classList.remove("d-none") // popupButton.style.setProperty('--primary', data.livechatcust.livechatthemecolor); // popupButton.style.backgroundImage = `url(${data.livechatcust.chaticonimage})`; // } }else{ popupButton.classList.remove("d-none") } popupButton.style.setProperty('--primary', data.livechatcust.livechatthemecolor); if (data.livechatcust.chaticonimage) { popupButton.style.backgroundImage = `url(${data.livechatcust.chaticonimage})`; if (bodyElement.querySelector('.feather.feather-message-square')) { bodyElement.querySelector('.feather.feather-message-square').remove(); } if (bodyElement.querySelector('.close-icon')) { bodyElement.querySelector('.close-icon').remove(); } } if (data.livechatcust.chatheaderimage) { bodyElement.querySelector('.popup-head').style.backgroundImage = `url(${data.livechatcust.chatheaderimage})`; } if (data.livechatcust.chaticondraggableswitch == 'on') { popupButton.style.setProperty('cursor', 'grabbing') dragElement(popupButton); } bodyElement.querySelector(".chat-icon-text").classList.remove('d-none'); bodyElement.querySelector(".chat-icon-text").innerText = data.livechatcust.beforechatshowdata; if (bodyElement.querySelector(".livechatpopuptitle")) { bodyElement.querySelector(".livechatpopuptitle").innerText = data?.livechatcust?.livechatpopuptitle; } if (bodyElement.querySelector(".livechatpopupsubtitle")) { bodyElement.querySelector(".livechatpopupsubtitle").innerText = data?.livechatcust?.livechatpopupsubtitle; } chatMessagePopup.style.setProperty('--primary', data.livechatcust.livechatthemecolor); // To add the FeedBack Click Event if (data.livechatcust.engage_conversation && JSON.parse(data.livechatcust.engage_conversation).length) { chatMessagePopup.querySelector(".feedBackBtn").classList.remove("d-none") chatMessagePopup.querySelector(".feedBackBtn").onclick = () => { chatMessagePopup.classList.add("rating-section-body") feedBackForm(data.livechatcust.livechatFeedbackDropdown, data.livechatdata, data.livechatcust.LivechatCustFeedbackQuestion) } } // For the Chat Flow Created Date let currentDate = null; // For the Chat Flow Messages if (data.livechatcust.chat_flow_messages) { const messageDate = formatDateString(data.livechatcust.created_at); conversationDiv.innerHTML += ` <div class="chat-box-single-line"> <abbr class="timestamp">${messageDate}</abbr> </div> `; currentDate = messageDate; JSON.parse(data.livechatcust.chat_flow_messages).map((flowMes) => { let updatedFlowMes = flowMes updatedFlowMes.created_at = data.livechatcust.created_at if (flowMes.authMessage == "agent") { conversationDiv.appendChild(AgentMessage(updatedFlowMes)) } else { conversationDiv.appendChild(customerMessage(updatedFlowMes)) } }) } let unreadIndexNumber = 0 // For the Messages append data.livechatdata.map((chatdata) => { const messageDate = formatDateString(chatdata.created_at); if (messageDate !== currentDate) { conversationDiv.innerHTML += ` <div class="chat-box-single-line"> <abbr class="timestamp">${messageDate}</abbr> </div> `; // For the date of the Chat currentDate = messageDate; } { if (!chatdata.livechat_cust_id && chatdata.status != "comment") { conversationDiv.appendChild(AgentMessage(chatdata)) } else { if (chatdata.status != "comment") { conversationDiv.appendChild(customerMessage(chatdata)) } } } // To get the get the unread index number if (chatdata.livechat_user_id && chatdata.status != "comment" && chatdata.status != "seen") { unreadIndexNumber = unreadIndexNumber + 1 } }) // To add the Unread Index Number if (unreadIndexNumber) { popupButton.querySelector('.unreadIndexNumberPopup').innerText = unreadIndexNumber popupButton.querySelector('.unreadIndexNumberPopup').classList.remove('d-none') popupList.querySelector('.unreadIndexNumberPopup').innerText = unreadIndexNumber popupList.querySelector('.unreadIndexNumberPopup').classList.remove('d-none') } // To show the LiveChat include Users informaction if (data.livechatcust.engage_conversation) { let livechatInfo = document.createElement('div') livechatInfo.innerHTML = ` <div class="d-flex align-items-center gap-4"></div> <div class="d-flex align-items-center gap-3 main-avatar"><div class="avatar-list avatar-list-stacked"></div></div> ` let onlineUserNames = []; JSON.parse(data.livechatcust.engage_conversation).map((user, index) => { let userSpan = document.createElement('span') userSpan.className = `avatar avatar-sm brround` userSpan.setAttribute('data-bs-toggle', 'tooltip'); userSpan.setAttribute('data-bs-custom-class', 'livechat-tooltip'); userSpan.setAttribute('data-bs-placement', 'top'); userSpan.setAttribute('data-bs-title', `${user.name}`); userSpan.style.backgroundImage = `url('${user.profileimage}')` if (index + 1 <= 2) { livechatInfo.querySelector(".avatar-list-stacked").appendChild(userSpan) } onlineUserNames.push(user.name) }) if (JSON.parse(data.livechatcust.engage_conversation).length > 2) { let userSpan = document.createElement('span') userSpan.className = `avatar brround` userSpan.setAttribute('data-bs-toggle', 'tooltip'); userSpan.setAttribute('data-bs-custom-class', 'livechat-tooltip'); userSpan.setAttribute('data-bs-placement', 'top'); userSpan.setAttribute('data-bs-title', `${data.livechatcust.LivechatCustWelcomeMsg}`); userSpan.innerHTML = `+${JSON.parse(data.livechatcust.engage_conversation).length - 2}` livechatInfo.querySelector(".avatar-list-stacked").appendChild(userSpan) } let span = document.createElement('span'); span.classList.add('className'); span.textContent = data.livechatcust?.LivechatCustWelcomeMsg; livechatInfo.querySelector(".main-avatar").appendChild(span) if (bodyElement.querySelector(".before-chatstart")) { if (bodyElement.querySelector(".onlineorofflinediv")) { bodyElement.querySelector(".onlineorofflinediv").remove() } bodyElement.querySelector(".before-chatstart").innerHTML = livechatInfo.innerHTML } } // For No One joined At the time to show the online users info if (!JSON.parse(data.livechatcust.engage_conversation).length && data.livechatcust.onlineUsers && JSON.parse(data.livechatcust.onlineUsers).length) { let livechatInfo = document.createElement('div') livechatInfo.innerHTML = ` <div class="d-flex align-items-center gap-4"></div> <div class="d-flex align-items-center gap-3 main-avatar"><div class="avatar-list avatar-list-stacked"></div></div> ` let onlineUserNames = [] JSON.parse(data.livechatcust.onlineUsers).map((user, index) => { let userSpan = document.createElement('span') userSpan.className = `avatar brround` userSpan.className = `avatar brround` userSpan.setAttribute('data-bs-toggle', 'tooltip'); userSpan.setAttribute('data-bs-custom-class', 'livechat-tooltip'); userSpan.setAttribute('data-bs-placement', 'top'); userSpan.setAttribute('data-bs-title', `${user.name}`); userSpan.style.backgroundImage = `url('${user.profileurl}')` if (index + 1 <= 2) { let onlineSpan = document.createElement('span') onlineSpan.className = "avatar-status bg-green" userSpan.appendChild(onlineSpan) livechatInfo.querySelector(".avatar-list-stacked").appendChild(userSpan) } onlineUserNames.push(user.name) }) if (JSON.parse(data.livechatcust.onlineUsers).length > 2) { let userSpan = document.createElement('span') userSpan.className = `avatar brround` userSpan.setAttribute('data-bs-toggle', 'tooltip'); userSpan.setAttribute('data-bs-custom-class', 'livechat-tooltip'); userSpan.setAttribute('data-bs-placement', 'top'); userSpan.setAttribute('data-bs-title', `${data.livechatcust.LivechatCustWelcomeMsg}`); userSpan.innerHTML = `+${JSON.parse(data.livechatcust.onlineUsers).length - 2}` livechatInfo.querySelector(".avatar-list-stacked").appendChild(userSpan) } let span = document.createElement('span'); span.classList.add('className'); span.classList.add('fs-5'); span.classList.add('ms-2'); span.textContent = data.livechatcust?.LivechatCustWelcomeMsg; livechatInfo.querySelector(".main-avatar").appendChild(span) if (bodyElement.querySelector(".before-chatstart")) { if (bodyElement.querySelector(".onlineorofflinediv")) { bodyElement.querySelector(".onlineorofflinediv").remove() } bodyElement.querySelector(".before-chatstart").innerHTML = livechatInfo.innerHTML } } else if (JSON.parse(data.livechatcust.engage_conversation).length && data.livechatcust.onlineUsers && JSON.parse(data.livechatcust.onlineUsers).length) { // where there was an engage agent let livechatInfo = document.createElement('div') livechatInfo.innerHTML = ` <div class="d-flex align-items-center gap-4"></div> <div class="d-flex align-items-center gap-3 main-avatar"><div class="avatar-list avatar-list-stacked"></div></div> ` let onlineUserNames = [] JSON.parse(data.livechatcust.engage_conversation).map((user, index) => { let userSpan = document.createElement('span') userSpan.className = `avatar brround` userSpan.className = `avatar brround` userSpan.setAttribute('data-bs-toggle', 'tooltip'); userSpan.setAttribute('data-bs-custom-class', 'livechat-tooltip'); userSpan.setAttribute('data-bs-placement', 'top'); userSpan.setAttribute('data-bs-title', `${user.name}`); userSpan.style.backgroundImage = `url('${user.profileurl}')` if (index + 1 <= 2) { let onlineSpan = document.createElement('span') onlineSpan.className = "avatar-status bg-green" userSpan.appendChild(onlineSpan) livechatInfo.querySelector(".avatar-list-stacked").appendChild(userSpan) } onlineUserNames.push(user.name) }) if (JSON.parse(data.livechatcust.engage_conversation).length > 2) { let userSpan = document.createElement('span') userSpan.className = `avatar brround` userSpan.setAttribute('data-bs-toggle', 'tooltip'); userSpan.setAttribute('data-bs-custom-class', 'livechat-tooltip'); userSpan.setAttribute('data-bs-placement', 'top'); userSpan.setAttribute('data-bs-title', `${data.livechatcust.LivechatCustWelcomeMsg}`); userSpan.innerHTML = `+${JSON.parse(data.livechatcust.engage_conversation).length - 2}` livechatInfo.querySelector(".avatar-list-stacked").appendChild(userSpan) } let span = document.createElement('span'); span.classList.add('className'); span.classList.add('fs-5'); span.classList.add('ms-2'); span.textContent = data.livechatcust?.LivechatCustWelcomeMsg; livechatInfo.querySelector(".main-avatar").appendChild(span) if (bodyElement.querySelector(".before-chatstart")) { if (bodyElement.querySelector(".onlineorofflinediv")) { bodyElement.querySelector(".onlineorofflinediv").remove() } bodyElement.querySelector(".before-chatstart").innerHTML = livechatInfo.innerHTML } } else { let livechatInfo = document.createElement('div') livechatInfo.innerHTML = ` <div class="d-flex align-items-center gap-4"></div> <div class="d-flex align-items-center gap-3 main-avatar"><div class="avatar-list avatar-list-stacked"></div></div> ` let span = document.createElement('span'); span.classList.add('className'); span.classList.add('fs-5'); span.classList.add('ms-2'); span.textContent = data.livechatcust?.LivechatCustWelcomeMsg; livechatInfo.querySelector(".main-avatar").appendChild(span) if (bodyElement.querySelector(".before-chatstart")) { if (bodyElement.querySelector(".onlineorofflinediv")) { bodyElement.querySelector(".onlineorofflinediv").remove() } bodyElement.querySelector(".before-chatstart").innerHTML = livechatInfo.innerHTML } } initializeTooltips(); // if the messages already present. At the time the messages will not add let ConversationBodyElement = bodyElement.querySelector(".popup-messages") if (!ConversationBodyElement.children.length) { ConversationBodyElement.appendChild(conversationDiv); // To scroll Down the Chat bodyElement.querySelector(".popup-messages").scrollBy(0, bodyElement.querySelector(".popup-messages").scrollHeight) // To add the Image Viewer bodyElement.querySelectorAll(".imageMessageLiveChat").forEach((element) => { element.parentElement.onclick = () => { window.open(element.getAttribute('imagesrc')) } }) // To check the last Message time cross the 24 Hours if (data.livechatdata[0]) { let welcomeMessages = data.livechatdata.filter(item => item.message_type === "welcomeMessage"); let createdAtTimeArray = welcomeMessages.length > 0 ? welcomeMessages[welcomeMessages.length - 1].created_at : data.livechatdata[0].created_at if (createdAtTimeArray) { let lastWelcomeMessageCreatedAt = createdAtTimeArray const creationTimeString = lastWelcomeMessageCreatedAt; const creationTime = new Date(creationTimeString); const currentTime = new Date(); const timeDifference = currentTime - creationTime; const hoursDifference = timeDifference / (1000 * 60 * 60); if (data.livechatcust.liveChatFlowload == "every-24-hours" && hoursDifference >= 24) { liveChatFlowload = true } } } } // If it is Offline let statusIndicator = bodyElement.querySelector('.online-status-indicator'); if (data.livechatcust.isonlineoroffline == "offline" && data.livechatcust.OfflineStatusMessage) { statusIndicator.classList.remove('online') statusIndicator.classList.add('offline') OfflineMessagePermission = { errorMessage: data.livechatcust.OfflineMessage } // To Add the Offline Message Status if (statusIndicator) { statusIndicator.innerHTML = ` <span class="w-2 h-2 brround bg-secondary d-inline-block me-2"></span>${data.livechatcust.OfflineStatusMessage} `; } } // If it is Online if (data.livechatcust.isonlineoroffline == "online" && data.livechatcust.OnlineStatusMessage) { statusIndicator.classList.add('online') statusIndicator.classList.remove('offline') // To Add the Online Message Status if (statusIndicator) { statusIndicator.innerHTML = ` <span class="w-2 h-2 brround pulse d-inline-block me-2"></span>${data.livechatcust.OnlineStatusMessage} `; } } // Chat File Upload if (!data.livechatcust.file_upload_permission) { bodyElement.querySelector(".liveChatFileUpload").style.display = "none" } else { bodyElement.querySelector(".liveChatFileUpload").style.display = "" } // voice Chat enable/disable if (data.livechatcust.customerVoiceChat == 'off') { bodyElement.querySelector(".voiceRecorderButton").style.display = "none" } else { bodyElement.querySelector(".voiceRecorderButton").style.display = "" } // For the LiveChat Image Upload bodyElement.querySelector("#chat-file-upload").onchange = () => { var fileInput = bodyElement.querySelector("#chat-file-upload"); var file = fileInput.files[0]; fileInput.value = '' var ThereIsError = false if (file) { const chatMsgElements = bodyElement.querySelectorAll('.direct-chat-msg.right'); const lastTwoElements = Array.from(chatMsgElements).slice(-data.livechatcust.livechatMaxFileUpload); if (!data.livechatcust.file_upload_permission) { ThereIsError = { errorMessage: "You are Not Having File Upload Permission " }; } else if (file.size > parseInt(data.livechatcust.livechatFileUploadMax) * 1024 * 1024) { ThereIsError = { errorMessage: `File size exceeds ${data.livechatcust.livechatFileUploadMax} MB. Please choose a smaller file.` }; } else if (data.livechatcust.livechatFileUploadTypes && !data.livechatcust.livechatFileUploadTypes.split(',').some(ext => file.name.toLowerCase().endsWith(ext.toLowerCase().trim()))) { ThereIsError = { errorMessage: `Invalid file extension. Please choose a file with ${data.livechatcust.livechatFileUploadTypes} extension(s).` }; } else if (lastTwoElements.every(element => element.querySelector('img'))) { ThereIsError = { errorMessage: `The maximum file upload limit has been exceeded.` }; } else { ThereIsError = false } // For add the Upload indication let uploadingIndication = document.createElement("div") uploadingIndication.className = "direct-chat-msg right" uploadingIndication.id = "uploadingIndication" uploadingIndication.innerHTML = ` <div class="direct-chat-text"> uploading... </div> ` if (!ThereIsError) { // bodyElement.querySelector(".direct-chat-messages").appendChild(uploadingIndication) // bodyElement.querySelector(".popup-messages").scrollBy(0, bodyElement.querySelector(".popup-messages").scrollHeight) } if (!ThereIsError) { var formData = new FormData(); formData.append('chatFileUpload', file); const now = new Date(); const hours = now.getHours(); const minutes = now.getMinutes(); const period = hours >= 12 ? "PM" : "AM"; const formattedTime = `${((hours + 11) % 12) + 1}:${minutes}${period}`; fetch(`${domainName}/livechat/live-chat-image-upload`, { method: 'POST', body: formData, headers: { 'X-Csrf-Token': 'N7J5vyQ9AcmVQW9dA2n4AJV1OcWzJ4pW2umV0QoI', 'X-Requested-With': 'XMLHttpRequest', 'Accept': 'application/json, text/javascript, */*; q=0.01', }, }) .then(response => { return response.json() }) .then(resdata => { // console.log(resdata); // return let data = { message: `${resdata.imageurl}`, username: liveChatCust.username, id: liveChatCust.id, customerId: liveChatCust.id, messageType: "image" } postDataAPI(data, 'broadcast-message') // let directChatMessages = bodyElement.querySelector(".direct-chat-messages") // let custMessage = document.createElement("div"); // custMessage.className = "direct-chat-msg right" // custMessage.innerHTML = ` // <div class="direct-chat-text"> // <img class="imageMessageLiveChat" imagesrc="${data.message}" // src="${data.message.toLowerCase().endsWith(".jpg") || data.message.toLowerCase().endsWith(".png") ? data.message : `${domainName}/build/assets/images/svgs/file.svg`}" // style="${data.message.toLowerCase().endsWith(".jpg") || data.message.toLowerCase().endsWith(".png") ? '' : 'height: 5rem;'}" // /> // <small class="time-text">${formattedTime}</small> // </div> // ` // directChatMessages.querySelector("#uploadingIndication")?.remove() // directChatMessages.appendChild(custMessage) // // To add the Image Viwer // bodyElement.querySelectorAll(".imageMessageLiveChat").forEach((element) => { // element.parentElement.onclick = () => { // window.open(element.getAttribute('imagesrc')) // } // }) // bodyElement.querySelector(".popup-messages").scrollBy(0, bodyElement.querySelector(".popup-messages").scrollHeight) }) .catch(error => { console.error('Error:', error); }); } else { alert(ThereIsError.errorMessage) } } } // Offline no need to display chat if (!parseInt(data.livechatcust.offlineDisplayLiveChat) && data.livechatcust.isonlineoroffline == "offline") { chatMessagePopup.remove() popupButton.remove() } // To remove the LiveChat if (data.livechatcust.liveChatHidden == "true") { chatMessagePopup.remove() popupButton.remove() } // To remove the live chat online indaction const beforeUnloadHandler = (event) => { postDataAPI({ custID: data.livechatcust.id }, 'remove-customer-online').then((ele) => { }) setTimeout(() => { if (bodyElement.querySelector(".chat-message-popup").classList.contains("active")) { postDataAPI({ custID: JSON.parse(localStorage.LiveChatCust).id }, 'customer-online').then((ele) => { }) } }, 3000); event.returnValue = "Write something clever here.." } // Adding beforeunload event To Livechat BTN bodyElement.querySelector("#chat-popup").addEventListener("click", () => { window.addEventListener('beforeunload', beforeUnloadHandler) }) // TO Remove the beforeunload event To Livechat Close BTN bodyElement.querySelector(".popup-minimize-normal").addEventListener("click", () => { window.removeEventListener('beforeunload', beforeUnloadHandler) postDataAPI({ custID: data.livechatcust.id }, 'remove-customer-online').then((ele) => { }) }) // To remove the online in the initial state if (!bodyElement.querySelector(".chat-message-popup").classList.contains('active')) { postDataAPI({ custID: data.livechatcust.id }, 'remove-customer-online').then((ele) => { }) } }) // Typing var debounceTimeout; var afterMessageSend = true customerTyping = (ele) => { clearTimeout(debounceTimeout); debounceTimeout = setTimeout(function () { if (afterMessageSend) { textAreaChanged(ele); } }, 500); } function textAreaChanged(textarea) { let data = { message: null, username: liveChatCust.username, id: null, customerId: liveChatCust.id, typingMessage: textarea.textContent } postDataAPI(data, 'broadcast-message-typing') } // Enter Message Send Function handleKeyDown = (event) => { if (event.key === 'Enter' && !event.shiftKey) { event.preventDefault(); sendMessage() } } return (` <div class="popup-messages"> </div> <div class="popup-messages-footer border-top p-0"> <div class="editable-container"> <div contenteditable="true" onkeyup="customerTyping(this)" onkeydown="handleKeyDown(event)" id="status_message" name="message" class="form-control textarea-chatoptions shadow-none"></div> </div> <div class="chat-footer-icons d-flex align-items-center justify-content-between border-top border-block-start-dashed"> <div class="btn-list"> <a class="btn btn-lg border-0 rounded-circle me-0 liveChatFileUpload" style="display: none;" onkeydown="handleKeyDown(event)" href="javascript:void(0);" onclick="{bodyElement.querySelector('#chat-file-upload').click()}"> <svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#5f6368"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M16.5 6v11.5c0 2.21-1.79 4-4 4s-4-1.79-4-4V5c0-1.38 1.12-2.5 2.5-2.5s2.5 1.12 2.5 2.5v10.5c0 .55-.45 1-1 1s-1-.45-1-1V6H10v9.5c0 1.38 1.12 2.5 2.5 2.5s2.5-1.12 2.5-2.5V5c0-2.21-1.79-4-4-4S7 2.79 7 5v12.5c0 3.04 2.46 5.5 5.5 5.5s5.5-2.46 5.5-5.5V6h-1.5z"/></svg> </a> <input type="file" id="chat-file-upload" class="d-none" name="chat-file-upload" autocomplete="off"> <a class="btn btn-lg border-0 rounded-circle allEmojisBtn" href="javascript:void(0);"> <svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#5f6368"><path d="M0 0h24v24H0V0z" fill="none"/><circle cx="15.5" cy="9.5" r="1.5"/><circle cx="8.5" cy="9.5" r="1.5"/><path d="M12 16c-1.48 0-2.75-.81-3.45-2H6.88c.8 2.05 2.79 3.5 5.12 3.5s4.32-1.45 5.12-3.5h-1.67c-.69 1.19-1.97 2-3.45 2zm-.01-14C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z"/></svg> </a> <ul class="dropdown-menu" id="emojiGrid" style="height: 215px; overflow-y: scroll;"></ul> <a class="btn btn-lg border-0 rounded-circle voiceRecorderButton" href="javascript:void(0);"> <div class="mic-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" fill="currentColor" class="bi bi-mic" viewBox="0 0 16 16"> <path d="M3.5 6.5A.5.5 0 0 1 4 7v1a4 4 0 0 0 8 0V7a.5.5 0 0 1 1 0v1a5 5 0 0 1-4.5 4.975V15h3a.5.5 0 0 1 0 1h-7a.5.5 0 0 1 0-1h3v-2.025A5 5 0 0 1 3 8V7a.5.5 0 0 1 .5-.5"/> <path d="M10 8a2 2 0 1 1-4 0V3a2 2 0 1 1 4 0zM8 0a3 3 0 0 0-3 3v5a3 3 0 0 0 6 0V3a3 3 0 0 0-3-3"/> </svg> </div> <canvas class="visualizer" width="24" height="24" style="display: none;"></canvas> </a> </div> <div> <a class="btn btn-lg btn-icon btn-primary border rounded-circle send-icon shadow-none" href="javascript:void(0);" onclick="sendMessage()"> <svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#5f6368"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M4.01 6.03l7.51 3.22-7.52-1 .01-2.22m7.5 8.72L4 17.97v-2.22l7.51-1M2.01 3L2 10l15 2-15 2 .01 7L23 12 2.01 3z"/></svg> </a> </div> </div> </div> `) } // Message flow conversation const messageConversationFlow = () => { let flowChatData let OfflineMessagePermission = false // Getting the chat Flow data getDataAPI(`flow/${currentScriptElement.getAttribute('testitout') ? currentScriptElement.getAttribute('testitout') : null}/${localStorage.getItem('presentChatIp') ? localStorage.getItem('presentChatIp') : null}`).then((data) => { if (data.success) { addButtonScript(data.success); if (data.success.maintenance == 'on') { return; } // To modify the size of the Live Chat icon. if (data.success.livechatIconSize == "large") { popupButton.classList.add("chat-popup-lg") if (bodyElement.querySelector('.chat-popup-list')) { bodyElement.querySelector('.chat-popup-list').classList.add('chat-popup-list-lg') } } else { popupButton.classList.remove("chat-popup-lg") if (bodyElement.querySelector('.chat-popup-list')) { bodyElement.querySelector('.chat-popup-list').classList.remove('chat-popup-list-lg') } } if (document.documentElement.getAttribute('dir') == 'rtl') { chatMessagePopup.setAttribute('dir', 'ltr'); popupButton.setAttribute('dir', 'ltr'); } // To Change the live Chat Position if (data.success.livechatPosition == "left") { mainLiveChatDiv.setAttribute('appearance', 'left'); appearance = "left"; chatMessagePopup.setAttribute('appearance', appearance) popupButton.setAttribute('appearance', appearance) chatMessagePopup.classList.add("chat-message-popup-right") popupButton.classList.add("chat-popup-right") } else { mainLiveChatDiv.setAttribute('appearance', 'right'); appearance = "right"; chatMessagePopup.setAttribute('appearance', appearance) popupButton.setAttribute('appearance', appearance) chatMessagePopup.classList.remove("chat-message-popup-right") popupButton.classList.remove("chat-popup-right") } if (bodyElement.querySelector('.chat-popup-list')) { bodyElement.querySelector('.chat-popup-list').setAttribute('appearance', appearance) } if (data.success.ipbannedstatus != 'banned' && data.success.maintenance == 'off') { popupButton.classList.remove("d-none") popupButton.style.setProperty('--primary', data.success.livechatthemecolor); if (data.success.chaticonimage) { popupButton.style.backgroundImage = `url(${data.success.chaticonimage})`; if (bodyElement.querySelector('.feather.feather-message-square')) { bodyElement.querySelector('.feather.feather-message-square').remove(); } if (bodyElement.querySelector('.close-icon')) { bodyElement.querySelector('.close-icon').remove(); } } } if (data.success.chatheaderimage) { bodyElement.querySelector('.popup-head').style.backgroundImage = `url(${data.success.chatheaderimage})`; } bodyElement.querySelector(".chat-icon-text").classList.remove('d-none'); bodyElement.querySelector(".chat-icon-text").innerText = data.success.beforechatshowdata; bodyElement.querySelector(".livechatpopuptitle").innerText = data.success.livechatpopuptitle; bodyElement.querySelector(".livechatpopupsubtitle").innerText = data.success.livechatpopupsubtitle; chatMessagePopup.style.setProperty('--primary', data.success.livechatthemecolor); flowChatData = data.success.liveChatFlow ? JSON.parse(data.success.liveChatFlow).nodes : null // To shoe the first Welcome Message if (data.success.liveChatFlow && JSON.parse(data.success.liveChatFlow).nodes['1'].name == "Welcome Message" && !bodyElement.querySelector(".popup-messages")?.children.length) { AgentMessage(JSON.parse(data.success.liveChatFlow).nodes['1']) } // To show the LiveChat Info informaction if (JSON.parse(data.success.onlineUsers).length) { bodyElement.querySelector('.onlineorofflinediv')?.remove(); let livechatInfo = document.createElement('div') livechatInfo.className = "onlineorofflinediv mt-4 me-3" livechatInfo.innerHTML = ` <div class="avatar-list avatar-list-stacked d-flex flex-nowrap justify-content-end"></div> <div class="ms-4 infoNamesText"></div> ` let onlineUserNames = [] JSON.parse(data.success.onlineUsers).map((user, index) => { let userSpan = document.createElement('span') userSpan.className = `avatar brround` userSpan.setAttribute('data-bs-toggle', 'tooltip'); userSpan.setAttribute('data-bs-custom-class', 'livechat-tooltip'); userSpan.setAttribute('data-bs-placement', 'top'); userSpan.setAttribute('data-bs-title', `${user.name}`); userSpan.style.backgroundImage = `url('${user.profileurl}')`; if (index + 1 <= 2) { let onlineSpan = document.createElement('span') onlineSpan.className = "avatar-status bg-green" userSpan.appendChild(onlineSpan) livechatInfo.querySelector(".avatar-list-stacked").appendChild(userSpan) } onlineUserNames.push(user.name) }) if (JSON.parse(data.success.onlineUsers).length > 2) { let userSpan = document.createElement('span') userSpan.className = `avatar brround`; userSpan.setAttribute('data-bs-toggle', 'tooltip'); userSpan.setAttribute('data-bs-custom-class', 'livechat-tooltip'); userSpan.setAttribute('data-bs-placement', 'top'); userSpan.setAttribute('data-bs-title', `${data.success.LivechatCustWelcomeMsg}`); userSpan.innerHTML = `+${JSON.parse(data.success.onlineUsers).length - 2}` livechatInfo.querySelector(".avatar-list-stacked").appendChild(userSpan) } let span = document.createElement('span'); span.classList.add('className'); span.textContent = data.livechatcust?.LivechatCustWelcomeMsg; livechatInfo.querySelector(".avatar-list-stacked").appendChild(span) if (bodyElement.querySelector(".supportusersdata")) { bodyElement.querySelector(".supportusersdata").insertAdjacentElement('afterend', livechatInfo); } } else { bodyElement.querySelector('.onlineorofflinediv')?.remove(); let livechatInfo = document.createElement('div') livechatInfo.className = "onlineorofflinediv mt-4 me-3" livechatInfo.innerHTML = ` <div class="avatar-list avatar-list-stacked d-flex flex-nowrap justify-content-end"></div> <div class="ms-4 infoNamesText"></div> ` // For the online user names livechatInfo.querySelector('.infoNamesText').innerHTML = ` <h6 class="mb-0 font-weight-bold text-truncate"></h6> ` bodyElement.querySelector(".offline-msg")?.remove() if (bodyElement.querySelector(".supportusersdata")) { bodyElement.querySelector(".supportusersdata").insertAdjacentElement('afterend', livechatInfo); } } initializeTooltips(); // If it is Online let statusIndicator = bodyElement.querySelector('.online-status-indicator'); if (data.success.isonlineoroffline == "online" && data.success.OnlineStatusMessage) { statusIndicator.classList.add('online') statusIndicator.classList.remove('offline') // To Add the Online Message Status if (statusIndicator) { statusIndicator.innerHTML = ` <span class="w-2 h-2 brround pulse d-inline-block me-2"></span>${data.success.OnlineStatusMessage} `; } } // If it is Offline if (data.success.isonlineoroffline == "offline" && data.success.OfflineStatusMessage) { statusIndicator.classList.remove('online') statusIndicator.classList.add('offline') OfflineMessagePermission = { errorMessage: data.success.OfflineMessage } // To Add the Offline Message Status if (statusIndicator) { statusIndicator.innerHTML = ` <span class="w-2 h-2 brround bg-secondary d-inline-block me-2"></span>${data.success.OfflineStatusMessage} `; } } if (data.success.chaticondraggableswitch == 'on') { popupButton.style.setProperty('cursor', 'grabbing') dragElement(popupButton); } // For Offline remove liveChat if (data.success.isonlineoroffline == "offline" && !parseInt(data.success.offlineDisplayLiveChat)) { chatMessagePopup.remove() popupButton.remove() } // To remove the liveCht if (data.success.liveChatHidden == "true") { chatMessagePopup.remove() popupButton.remove() } // voice Chat enable/disable // if (data.success.customerVoiceChat == 'off') { // bodyElement.querySelector(".voiceRecorderButton").style.display = "none" // } else { // bodyElement.querySelector(".voiceRecorderButton").style.display = "" // } } }) // Agent Message div let AgentMessage = (data) => { // For the message div let agentLi = document.createElement("div"); agentLi.className = "direct-chat-msg" agentLi.innerHTML = ` <div class="direct-chat-text">${data.data.text}</div> ` // For the Option buttons let liveChatOptionBtn = document.createElement("div") liveChatOptionBtn.className = "d-flex flex-wrap liveChatOptionBtn" let typeIndicator = document.createElement('div') typeIndicator.className = 'typing-indicator'; typeIndicator.innerHTML = ` <div class="dot"></div> <div class="dot"></div> <div class="dot"></div> ` // connections node Loop data.outputs.act.connections.map((connectedNode) => { let optionNode = document.createElement("div") optionNode.onclick = () => { // To remove the Options bodyElement.querySelector(".liveChatOptionBtn").remove() // Append the selected option as a customer message bodyElement.querySelector(".popup-messages").appendChild(customerMessage(flowChatData[connectedNode.node])) bodyElement.querySelector('.popup-messages').appendChild(typeIndicator) setTimeout(() => { // to loop the messages and options if (flowChatData[connectedNode.node].inputs.text.connections[0]) { AgentMessage(flowChatData[flowChatData[connectedNode.node].inputs.text.connections[0].node]) } bodyElement.querySelector('.popup-messages .typing-indicator')?.remove(); }, 1000); } optionNode.innerHTML = ` <button style="background-image: none; border-color: #0d6efd;" class="btn btn-outline-primary m-1 shadow-none"> ${flowChatData[connectedNode.node].data.optionName} </button> ` liveChatOptionBtn.appendChild(optionNode) bodyElement.querySelector('.popup-messages .typing-indicator')?.remove(); }) // For the Message bodyElement.querySelector(".popup-messages")?.appendChild(agentLi); // For the Options bodyElement.querySelector(".popup-messages")?.appendChild(liveChatOptionBtn); } // Customer div let customerMessage = (data) => { let custLi = document.createElement("div"); custLi.className = "direct-chat-msg right" custLi.innerHTML = ` <div class="direct-chat-text">${data.data.optionName}</div> ` return custLi } function sanitizeHTML(input) { const map = { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''', '/': '/', // For forward slash '`': '`', // Backtick '=': '=' // Equals }; return input.replace(/[&<>"'/`=]/g, function (char) { return map[char]; }); } sendMessage = () => { if (bodyElement.querySelector("#status_message").textContent.length) { // For the Making Chat Flow Message Array bodyElement.querySelectorAll(".popup-messages .direct-chat-msg").forEach((element) => { if (element.classList.contains('right')) { FlowChatConversation.push({ authMessage: 'cust', message: element.querySelector(".direct-chat-text").innerText }) } else { FlowChatConversation.push({ authMessage: 'agent', message: element.querySelector(".direct-chat-text").innerText }) } }) // To open The welcome Form chatBody(welcomeForm(sanitizeHTML(bodyElement.querySelector("#status_message").textContent), OfflineMessagePermission)) bodyElement.querySelector('.popup-minimize-normal-fields')?.addEventListener('click', function () { const targetElement = bodyElement.querySelector('.popup-fields'); if (targetElement) { targetElement.classList.add('d-none'); chatBody(messageConversationFlow()); startRecording(); } }); } } // Enter Message Send Function handleKeyDown = (ele) => { if (ele.key === 'Enter' && !ele.shiftKey) { ele.preventDefault(); sendMessage() } } return (` <div class="popup-messages"> </div> <div class="popup-messages-footer border-top p-0"> <div class="editable-container"> <div contenteditable="true" id="status_message" onkeydown="handleKeyDown(event)" name="message" class="form-control textarea-chatoptions shadow-none"></div> </div> <div class="chat-footer-icons d-flex align-items-center justify-content-between border-top border-block-start-dashed"> <div class="btn-list"> <a class="btn btn-lg border-0 rounded-circle me-0 liveChatFileUpload" style="display: none;" onkeydown="handleKeyDown(event)" href="javascript:void(0);" onclick="{bodyElement.querySelector('#chat-file-upload').click()}"> <svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#5f6368"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M16.5 6v11.5c0 2.21-1.79 4-4 4s-4-1.79-4-4V5c0-1.38 1.12-2.5 2.5-2.5s2.5 1.12 2.5 2.5v10.5c0 .55-.45 1-1 1s-1-.45-1-1V6H10v9.5c0 1.38 1.12 2.5 2.5 2.5s2.5-1.12 2.5-2.5V5c0-2.21-1.79-4-4-4S7 2.79 7 5v12.5c0 3.04 2.46 5.5 5.5 5.5s5.5-2.46 5.5-5.5V6h-1.5z"/></svg> </a> <input type="file" id="chat-file-upload" class="d-none" name="chat-file-upload" autocomplete="off"> <a class="btn btn-lg border-0 rounded-circle allEmojisBtn" href="javascript:void(0);"> <svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#5f6368"><path d="M0 0h24v24H0V0z" fill="none"/><circle cx="15.5" cy="9.5" r="1.5"/><circle cx="8.5" cy="9.5" r="1.5"/><path d="M12 16c-1.48 0-2.75-.81-3.45-2H6.88c.8 2.05 2.79 3.5 5.12 3.5s4.32-1.45 5.12-3.5h-1.67c-.69 1.19-1.97 2-3.45 2zm-.01-14C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z"/></svg> </a> <ul class="dropdown-menu" id="emojiGrid" style="height: 200px; overflow-y: scroll;"></ul> </div> <div> <a class="btn btn-lg btn-icon btn-primary border rounded-circle send-icon shadow-none" href="javascript:void(0);" onclick="sendMessage()"> <svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#5f6368"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M4.01 6.03l7.51 3.22-7.52-1 .01-2.22m7.5 8.72L4 17.97v-2.22l7.51-1M2.01 3L2 10l15 2-15 2 .01 7L23 12 2.01 3z"/></svg></a> </div> </div> </div> `) } // To add the Flow Message After the 24 Hours const basedOnTimeMessageConversationFlow = () => { let flowChatElement = document.createElement("div") flowChatElement.className = "basedOnTimeMessageConversationFlowDiv" let flowChatData // Getting the chat Flow data getDataAPI(`flow/null`).then((data) => { if (data.success) { flowChatData = JSON.parse(data.success.liveChatFlow).nodes // To shoe the first Welcome Message if (JSON.parse(data.success.liveChatFlow).nodes['1'].name == "Welcome Message") { AgentMessage(JSON.parse(data.success.liveChatFlow).nodes['1']) } } }) // Agent Message div let AgentMessage = (data) => { // For the message div let agentLi = document.createElement("div"); agentLi.className = "direct-chat-msg" agentLi.innerHTML = ` <div class="direct-chat-text">${data.data.text}</div> ` // To send the Welcome Message as a message let welcomeMessagedata = { message: data.data.text, username: liveChatCust.username, id: liveChatCust.id, customerId: liveChatCust.id, messageType: "welcomeMessage" } postDataAPI(welcomeMessagedata, 'broadcast-message') // For the Option buttons let liveChatOptionBtn = document.createElement("div") liveChatOptionBtn.className = "d-flex flex-wrap liveChatOptionBtn" let typeIndicator = document.createElement('div') typeIndicator.className = 'typing-indicator'; typeIndicator.innerHTML = ` <div class="dot"></div> <div class="dot"></div> <div class="dot"></div> ` // connections node Loop data.outputs.act.connections.map((connectedNode) => { let optionNode = document.createElement("div") optionNode.onclick = () => { // To remove the Options bodyElement.querySelector(".liveChatOptionBtn").remove() // Append the selected option as a customer message bodyElement.querySelector(".basedOnTimeMessageConversationFlowDiv").appendChild(customerMessage(flowChatData[connectedNode.node])) bodyElement.querySelector('.basedOnTimeMessageConversationFlowDiv').appendChild(typeIndicator) // To send the Welcome Message as a message let welcomeMessagedata = { message: flowChatData[connectedNode.node].data.optionName, username: liveChatCust.username, id: liveChatCust.id, customerId: liveChatCust.id, } setTimeout(() => { postDataAPI(welcomeMessagedata, 'broadcast-message').then((ele) => { // to loop the messages and options if (flowChatData[connectedNode.node].inputs.text.connections[0]) { AgentMessage(flowChatData[flowChatData[connectedNode.node].inputs.text.connections[0].node]) } bodyElement.querySelector('.basedOnTimeMessageConversationFlowDiv .typing-indicator')?.remove(); }) }, 1000); } optionNode.innerHTML = ` <button style="background-image: none; border-color: #0d6efd;" class="btn btn-outline-primary m-1 shadow-none"> ${flowChatData[connectedNode.node].data.optionName} </button> ` liveChatOptionBtn.appendChild(optionNode) bodyElement.querySelector('.basedOnTimeMessageConversationFlowDiv .typing-indicator')?.remove(); }) // For the Message flowChatElement.appendChild(agentLi); // For the Options flowChatElement.appendChild(liveChatOptionBtn); } // Customer div let customerMessage = (data) => { let custLi = document.createElement("div"); custLi.className = "direct-chat-msg right" custLi.innerHTML = ` <div class="direct-chat-text">${data.data.optionName}</div> ` return custLi } return flowChatElement } // For the Offline Message Indication const OfflineMessageIndication = (message) => { let offlineChatElement = document.createElement("div") offlineChatElement.className = "direct-chat-msg" // For the Corrent Time function getCurrentTime() { const currentDate = new Date(); let hours = currentDate.getHours(); let minutes = currentDate.getMinutes(); const ampm = hours >= 12 ? 'PM' : 'AM'; // Convert hours to 12-hour format hours = hours % 12 || 12; // Add leading zero to minutes if necessary minutes = minutes < 10 ? '0' + minutes : minutes; const currentTime = hours + ':' + minutes + ampm; return currentTime; } // To post The Message let welcomeMessagedata = { message: message, username: liveChatCust.username, id: liveChatCust.id, customerId: liveChatCust.id, messageType: "welcomeMessage" } postDataAPI(welcomeMessagedata, 'broadcast-message') offlineChatElement.innerHTML = ` <div class="direct-chat-text"> ${message} <small class="time-text">${getCurrentTime()}</small> </div> ` return offlineChatElement } // Adding the WellCome form if (!localStorage.LiveChatCust) { chatBody(messageConversationFlow()) // startRecording(); } else { chatBody(messageConversation()) emojiLoader(); startRecording(); } // Adding the Emojis- let storedRange; function storeRange() { let message = bodyElement.querySelector('#status_message'); const selection = bodyElement.getSelection(); if (selection?.rangeCount) { let selected = selection.getRangeAt(0).commonAncestorContainer; if (message.contains(selected)) { // Storing the range storedRange = selection.getRangeAt(0); } else { let newRng = document.createRange(); newRng.setStart(message, message.childNodes.length); newRng.setEnd(message, message.childNodes.length); selection.removeAllRanges(); selection.addRange(newRng); storedRange = selection.getRangeAt(0); } } else { let newRng = document.createRange(); newRng.setStart(message, message.childNodes.length); newRng.setEnd(message, message.childNodes.length); selection.removeAllRanges(); selection.addRange(newRng); storedRange = selection.getRangeAt(0); } } function insertEmoji(emoji) { if (!storedRange) return; const textNode = document.createTextNode(emoji); storedRange.insertNode(textNode); // Move the caret after the inserted emoji let selection = bodyElement.getSelection(); let newRng = document.createRange(); newRng.setStartAfter(textNode); newRng.setEndAfter(textNode); selection.removeAllRanges(); selection.addRange(newRng); // Update the stored range to the new position storedRange = newRng; bodyElement.getElementById("emojiGrid").classList.toggle('d-block'); } function EmojiGridShow() { storeRange(); bodyElement.getElementById("emojiGrid").classList.toggle('d-block'); } function emojiLoader() { const messageElement = bodyElement.querySelector('#status_message'); messageElement?.addEventListener('mouseup', storeRange); messageElement?.addEventListener('keyup', storeRange); let allEmojisBtn = bodyElement.querySelector('.allEmojisBtn'); allEmojisBtn?.removeEventListener('click', EmojiGridShow) allEmojisBtn?.addEventListener('click', EmojiGridShow) const emojiGrid = bodyElement.getElementById("emojiGrid"); // Emojis data const emojisData = [ '๐', '๐', '๐', '๐', '๐', '๐ ', '๐', '๐คฃ', '๐', '๐', '๐', '๐', '๐', '๐', '๐', '๐ฅฐ', '๐', '๐', '๐', '๐', '๐', '๐', '๐', '๐คช', '๐', '๐ค', '๐ค', '๐คญ', '๐คซ', '๐ค', '๐ค', '๐คจ', '๐', '๐', '๐ถ', '๐', '๐', '๐', '๐ฌ', '๐ฎ', '๐ฏ', '๐ฆ', '๐ง', '๐จ', '๐ฐ', '๐ฑ', '๐ณ', '๐ต', '๐ก', '๐ ', '๐ค', '๐', '๐', '๐', '๐ท', '๐', '๐ค', '๐ค ', '๐ธ', '๐บ', '๐ป', '๐ผ', '๐ฝ', '๐', '๐ฟ', '๐พ', '๐', '๐', '๐', '๐ค', '๐', '๐', '๐', 'โ', '๐ค', '๐ค', '๐ค', 'โ๏ธ', '๐ค', '๐', '๐', '๐', '๐', '๐', 'โ', '๐ค', '๐', '๐', '๐', '๐ค', '๐ช', '๐', 'โ๏ธ', '๐', '๐ฆถ', '๐ฆต', '๐', '๐', 'โค๏ธ', '๐', '๐', '๐', '๐', '๐งก', '๐', 'โค๏ธ', '๐', '๐', '๐', '๐', '๐', '๐', '๐', '๐', '๐ค', '๐ข', '๐ฃ', '๐ฅ', '๐ซ', '๐ฆ', '๐จ', '๐ณ๏ธ', '๐ง', '๐ฉ', '๐', '๐', '๐', '๐ช', '๐', '๐', '๐', '๐', '๐', '๐ค', '๐ค', '๐ค', '๐ค', '๐', '๐', '๐', '๐', 'โ', '๐ค', '๐ค', '๐', '๐', '๐', 'โค๏ธ', '๐', '๐', '๐', '๐', '๐', '๐', '๐', '๐', '๐ค', '๐ข', '๐ฃ', '๐ฅ', '๐ซ', '๐ฆ', '๐จ', '๐ณ๏ธ', '๐ง', '๐ฉ', '๐', '๐', '๐', '๐ช', '๐', '๐', '๐', '๐', '๐', '๐ค', '๐ค', '๐ค', '๐ค', '๐', '๐', '๐', '๐', 'โ', '๐ค', '๐ค', '๐', '๐', '๐', 'โค๏ธ', '๐', '๐', '๐', '๐', '๐', '๐', '๐', '๐', '๐ค', '๐ข', '๐ฃ', '๐ฅ', '๐ซ', '๐ฆ', '๐จ', '๐ณ๏ธ', '๐ง', '๐ฉ', '๐', '๐', '๐', '๐ช', '๐', '๐', '๐', '๐', '๐', '๐ค', '๐ค', '๐ค', '๐ค', '๐', '๐', '๐', '๐', 'โ', '๐ค', '๐ค', '๐', '๐', '๐', 'โค๏ธ', '๐', '๐', '๐', '๐', '๐', '๐', '๐', '๐', '๐ค', '๐ข', '๐ฃ', '๐ฅ', '๐ซ', '๐ฆ', '๐จ', '๐ณ๏ธ', '๐ง', '๐ฉ', '๐', '๐', '๐', '๐ช', '๐', '๐', '๐', '๐', '๐', '๐ค', '๐ค', '๐ค', '๐ค', '๐', '๐', '๐', '๐', 'โ', '๐ค', '๐ค', '๐', '๐', '๐', 'โค๏ธ', '๐', '๐', '๐', '๐', '๐', '๐', '๐', '๐', '๐ค', '๐ข', '๐ฃ', '๐ฅ', '๐ซ', '๐ฆ', '๐จ', '๐ณ๏ธ', '๐ง', '๐ฉ', '๐', '๐', '๐', '๐ช', '๐', '๐', '๐', '๐', '๐', '๐ค', '๐ค', '๐ค', '๐ค', '๐', '๐', '๐', '๐', 'โ', '๐ค', '๐ค', '๐', '๐', '๐', 'โค๏ธ', '๐', '๐', '๐', '๐', '๐', '๐', '๐', '๐', '๐ค', '๐ข', '๐ฃ', '๐ฅ', '๐ซ', '๐ฆ', '๐จ', '๐ณ๏ธ', '๐ง', '๐ฉ', '๐', '๐', '๐', '๐ช', '๐', '๐', '๐', '๐', '๐', '๐ค', '๐ค', '๐ค', '๐ค', '๐', '๐', '๐', '๐', 'โ', '๐ค', '๐ค', '๐', '๐', '๐', 'โค๏ธ', '๐', '๐', '๐', '๐', '๐', '๐', '๐', '๐', '๐ค', '๐ข', '๐ฃ', '๐ฅ', '๐ซ', '๐ฆ', '๐จ', '๐ณ๏ธ', '๐ง', '๐ฉ', '๐', '๐', '๐', '๐ช', '๐', '๐', '๐', '๐', '๐', '๐ค', '๐ค', '๐ค', '๐ค', '๐', '๐', '๐', '๐', 'โ', '๐ค', '๐ค', '๐', '๐', '๐', 'โค๏ธ', '๐', '๐', '๐', '๐', '๐', '๐', '๐', '๐', '๐ค', '๐ข', '๐ฃ', '๐ฅ', '๐ซ', '๐ฆ', '๐จ', '๐ณ๏ธ', '๐ง', '๐ฉ', '๐', '๐', '๐', '๐ช', '๐', '๐', '๐', '๐', '๐', '๐ค', '๐ค', '๐ค', '๐ค', '๐', '๐', '๐', '๐', 'โ', '๐ค', '๐ค', '๐', '๐', '๐', 'โค๏ธ', '๐', '๐', '๐', '๐', '๐', '๐', '๐', '๐', '๐ค', '๐ข', '๐ฃ', '๐ฅ', '๐ซ', '๐ฆ', '๐จ', '๐ณ๏ธ', '๐ง', '๐ฉ', '๐', '๐', '๐', '๐ช', '๐', '๐', '๐', '๐', '๐', '๐ค', '๐ค', '๐ค', '๐ค', '๐', '๐', '๐', '๐', 'โ', '๐ค', '๐ค', '๐', '๐', '๐', 'โค๏ธ', '๐', '๐', '๐', '๐', '๐', '๐', '๐', '๐', '๐ค', '๐ข', '๐ฃ', '๐ฅ', '๐ซ', '๐ฆ', '๐จ', '๐ณ๏ธ', '๐ง', '๐ฉ', '๐', '๐', '๐', '๐ช', '๐', '๐', '๐', '๐', '๐', '๐ค', '๐ค', '๐ค', '๐ค', '๐', '๐', '๐', '๐', 'โ', '๐ค', '๐ค', '๐', '๐', '๐', 'โค๏ธ', '๐', '๐', '๐', '๐', '๐', '๐', '๐', '๐', '๐ค', '๐ข', '๐ฃ', '๐ฅ', '๐ซ', '๐ฆ', '๐จ', '๐ณ๏ธ', '๐ง', '๐ฉ', '๐', '๐', '๐', '๐ช', '๐', '๐', '๐', '๐', '๐', '๐ค', '๐ค', '๐ค', '๐ค', '๐', '๐', '๐', '๐', 'โ', '๐ค', '๐ค', '๐', '๐', '๐', 'โค๏ธ', '๐', '๐', '๐', '๐', '๐', '๐', '๐', '๐', '๐ค', '๐ข', '๐ฃ', '๐ฅ', '๐ซ', '๐ฆ', '๐จ', '๐ณ๏ธ', '๐ง', '๐ฉ', '๐', '๐', '๐', '๐ช', '๐', '๐', '๐', '๐', '๐', '๐ค', '๐ค', '๐ค', '๐ค', '๐', '๐', '๐', '๐', 'โ', '๐ค', '๐ค', '๐', '๐', '๐', 'โค๏ธ', '๐', '๐', '๐', '๐', '๐', '๐', '๐', '๐', '๐ค', '๐ข', '๐ฃ', '๐ฅ', '๐ซ', '๐ฆ', '๐จ', '๐ณ๏ธ', '๐ง', '๐ฉ', '๐' ]; let emojis = [...new Set(emojisData)] // Number of emojis per row const emojisPerRow = 8; // Generate emoji grid for (let i = 0; i < emojis.length; i++) { if (i % emojisPerRow === 0) { // Start a new row const newRow = document.createElement("li"); newRow.className = "d-flex"; emojiGrid?.appendChild(newRow); } // Create emoji element const col = document.createElement("span"); col.style.padding = "0.5rem" col.classList.add("dropdown-item",); col.style.cursor = 'pointer' col.onclick = () => { insertEmoji(emojis[i]) } col.innerHTML = `${emojis[i]}`; // Append emoji to the current row const currentRow = emojiGrid?.lastElementChild; // bodyElement.querySelector("#agentSendMessage").disabled = false // bodyElement.querySelector("#agentSendMessage").classList.remove('disabled') currentRow?.appendChild(col); } } emojiLoader(); let debouncing let debouncing2 let debouncing3 const vibrateTwoTimes = () => { if ('vibrate' in navigator) { try { window.navigator.vibrate([300, 100, 300]); } catch (error) { console.error('Vibration API error:', error); } } } const playingaudio = (socket) => { let newMessageSoundCurrentAudio = ''; // Stop the current audio if it exists if (newMessageSoundCurrentAudio) { newMessageSoundCurrentAudio.pause(); newMessageSoundCurrentAudio.currentTime = 0; } // Create a new audio element let audioElement = document.createElement('audio'); audioElement.id = "audioPlayer"; audioElement.innerHTML = `<source src="${socket.agentInfo.newMessageSound}" allow="autoplay">`; // Play the new audio if (audioElement.paused) { audioElement.play(); vibrateTwoTimes(); } // Set the new audio as the current audio newMessageSoundCurrentAudio = audioElement; newMessageSoundCurrentAudio.__proto__.cusumerId = socket.custdata.id let intervalId; if (socket.agentInfo.notificationType == "Loop") { const clickEventHandler = () => { newMessageSoundCurrentAudio.pause(); clearInterval(intervalId); chatMessagePopup.removeEventListener('click', clickEventHandler); intervalId = null }; if (chatMessagePopup) { chatMessagePopup.addEventListener('click', clickEventHandler); } function checkAndPlaySound() { if (audioElement.paused) { audioElement.play(); vibrateTwoTimes(); } } if (!intervalId) { intervalId = setInterval(checkAndPlaySound, 1000); } } } // Public Socket Echo.channel('liveChat').listen('ChatMessageEvent', (socket) => { if(socket && socket?.comments?.includes('banned this customer at') && socket?.custdata?.banstatus == 'banned' && socket?.custdata?.login_ip == localStorage.getItem('presentChatIp')){ chatMessagePopup?.remove(); popupButton?.remove(); } if (socket.visitoruiqueid != null && socket.visitoruiqueid == localStorage.getItem("LiveChatVisitor")) { if (!socket.message && socket.customerId == 'visitoronlinestatuscheck') { let statusdata statusdata = { "id": localStorage.getItem("LiveChatVisitor"), } postDataAPI(statusdata, 'livevisitorsstatus'); } else { const now = new Date(); const hours = now.getHours(); const minutes = now.getMinutes(); const period = hours >= 12 ? "PM" : "AM"; const formattedTime = `${((hours + 11) % 12) + 1}:${minutes}${period}`; // To remove the Typing induction if (bodyElement.querySelector("#typingIndication")) { bodyElement.querySelector("#typingIndication").remove() } function formatTime() { const date = new Date(); const hours = date.getHours(); const minutes = date.getMinutes(); const ampm = hours >= 12 ? 'PM' : 'AM'; const formattedHours = hours % 12 === 0 ? 12 : hours % 12; const formattedMinutes = minutes < 10 ? '0' + minutes : minutes; const formattedTime = `${formattedHours}:${formattedMinutes}${ampm}`; return formattedTime; } let conversationDiv = document.createElement("div"); conversationDiv.className = "direct-chat-messages" conversationDiv.style.overflow = "hidden" let ToVisitorLi = document.createElement("div"); ToVisitorLi.className = "direct-chat-msg"; conversationDiv.appendChild(ToVisitorLi); bodyElement.querySelector(".popup-messages").appendChild(conversationDiv); // To Scroll Down the Conversation bodyElement.querySelector(".popup-messages").scrollBy(0, bodyElement.querySelector(".popup-messages").scrollHeight) localStorage.setItem("LiveChatCust", JSON.stringify(socket.custdata)) // For the Message Seen Indication if (chatMessagePopup.classList.contains('active')) { postDataAPI({ cust_unique_id: socket.visitoruiqueid }, 'user-seen-messages-indication') } if (!chatMessagePopup.classList.contains('active') && popupButton.querySelector('.unreadIndexNumberPopup').classList.contains("d-none")) { popupButton.querySelector('.unreadIndexNumberPopup').innerText = "1" popupButton.querySelector('.unreadIndexNumberPopup').classList.remove("d-none") popupList.querySelector('.unreadIndexNumberPopup').innerText = "1" popupList.querySelector('.unreadIndexNumberPopup').classList.remove("d-none") } else { if (!chatMessagePopup.classList.contains('active') && !popupButton.querySelector('.unreadIndexNumberPopup').classList.contains("d-none")) { popupButton.querySelector('.unreadIndexNumberPopup').innerText = parseInt(popupButton.querySelector('.unreadIndexNumberPopup').innerText) + 1 popupList.querySelector('.unreadIndexNumberPopup').innerText = parseInt(popupButton.querySelector('.unreadIndexNumberPopup').innerText) + 1 } } } } // For the Online Users Update if (!socket.message && socket.onlineUserUpdated == 'true' && !localStorage.LiveChatCust) { clearTimeout(debouncing) debouncing = setTimeout(() => { chatBody(messageConversationFlow(), false) startRecording(); }, 1000); } // For the Engage Users Update if (!socket.message && (socket.onlineUserUpdated == 'true' || socket.engageUser) && localStorage.LiveChatCust) { clearTimeout(debouncing3) debouncing3 = setTimeout(() => { chatBody(messageConversation(), false) emojiLoader(); startRecording(); }, 3000); } // For the Message update if (localStorage.LiveChatCust) { let liveChatCust = JSON.parse(localStorage.LiveChatCust) if(socket.messageType == 'fileuploadermision' && liveChatCust.id == socket.custdata.id){ if(!socket.custdata.file_upload_permission){ bodyElement.querySelector(".liveChatFileUpload").style.display = "none" }else{ bodyElement.querySelector(".liveChatFileUpload").style.display = "" } } if (typeof (socket.customerId) == 'string' && socket.customerId == liveChatCust.id && socket.message) { const now = new Date(); const hours = now.getHours(); const minutes = now.getMinutes(); const period = hours >= 12 ? "PM" : "AM"; const formattedTime = `${((hours + 11) % 12) + 1}:${minutes}${period}`; // To remove the Typing induction if (bodyElement.querySelector("#typingIndication")) { bodyElement.querySelector("#typingIndication").remove() } let directChatMessages = bodyElement.querySelector(".direct-chat-messages") let custMessage = document.createElement("div"); custMessage.className = "direct-chat-msg" custMessage.innerHTML = `<div class="direct-chat-text"> ${socket.messageType == "image" ? `<img imagesrc="${socket.message}" src="${socket.message.toLowerCase().endsWith(".jpg") || socket.message.toLowerCase().endsWith(".png") ? socket.message : `${domainName}/build/assets/images/svgs/file.svg`}"/>` : (socket.messageType == "audio" ? `<audio controls src="${socket.message}" style="width: 240px;"></audio>` : `${socket.message}`)} <small class="time-text">${formattedTime}</small></div>` // To Open Image In the new Tab if (custMessage.querySelector("img")) { custMessage.querySelector("img").onclick = () => { window.open(custMessage.querySelector("img").getAttribute('imagesrc')); } } directChatMessages.appendChild(custMessage) playingaudio(socket); // To Scroll Down the Conversation bodyElement.querySelector(".popup-messages").scrollBy(0, bodyElement.querySelector(".popup-messages").scrollHeight) // For the Message Seen Indication if (chatMessagePopup.classList.contains('active')) { postDataAPI(JSON.parse(localStorage.LiveChatCust), 'user-seen-messages-indication') } if (!chatMessagePopup.classList.contains('active') && popupButton.querySelector('.unreadIndexNumberPopup').classList.contains("d-none")) { popupButton.querySelector('.unreadIndexNumberPopup').innerText = "1" popupButton.querySelector('.unreadIndexNumberPopup').classList.remove("d-none") } else { if (!chatMessagePopup.classList.contains('active') && !popupButton.querySelector('.unreadIndexNumberPopup').classList.contains("d-none")) { // audioElement.play(); popupButton.querySelector('.unreadIndexNumberPopup').innerText = parseInt(popupButton.querySelector('.unreadIndexNumberPopup').innerText) + 1 } } } if (!socket.agentInfo && socket.userName != 'chatBot' && socket.customerId == liveChatCust.id && socket.message) { const now = new Date(); const hours = now.getHours(); const minutes = now.getMinutes(); const period = hours >= 12 ? "PM" : "AM"; const formattedTime = `${((hours + 11) % 12) + 1}:${minutes}${period}`; let directChatMessages = bodyElement.querySelector(".direct-chat-messages") let custMessage = document.createElement("div"); custMessage.className = "direct-chat-msg right" custMessage.innerHTML = `<div class="direct-chat-text"> ${socket.messageType == "image" ? `<img class="imageMessageLiveChat" imagesrc="${socket.message}" src="${socket.message.toLowerCase().endsWith(".jpg") || socket.message.toLowerCase().endsWith(".png") ? socket.message : `${domainName}/build/assets/images/svgs/file.svg`}"/>` : (socket.messageType == "audio" ? `<audio controls="" src="${socket.message}" style="width: 240px;"></audio>` : `${socket.message}`)} <small class="time-text">${formattedTime}</small></div>` // To Open Image In the new Tab if (custMessage.querySelector("img")) { custMessage.querySelector("img").onclick = () => { window.open(custMessage.querySelector("img").getAttribute('imagesrc')); } } directChatMessages?.appendChild(custMessage) // To Scroll Down the Conversation bodyElement.querySelector(".popup-messages")?.scrollBy(0, bodyElement.querySelector(".popup-messages").scrollHeight) } } // For the Typing induction if (!socket.message && socket.agentInfo && socket.customerId == liveChatCust?.id && socket.typingMessage) { // To remove the Typing induction if (bodyElement.querySelector("#typingIndication")) { bodyElement.querySelector("#typingIndication").remove() } let directChatMessages = bodyElement.querySelector(".direct-chat-messages") let custMessage = document.createElement("div"); custMessage.id = "typingIndication" custMessage.className = "direct-chat-msg" custMessage.innerHTML = `<div class="direct-chat-text">Typing....</div>` directChatMessages.appendChild(custMessage) // To Scroll Down the Conversation bodyElement.querySelector(".popup-messages").scrollBy(0, bodyElement.querySelector(".popup-messages").scrollHeight) clearTimeout(debouncing2); debouncing2 = setTimeout(function () { if (bodyElement.querySelector("#typingIndication")) { bodyElement.querySelector("#typingIndication").remove() } }, 5000); } pauseAudios(); }) }; bodyElement.appendChild(script); } bodyElement.appendChild(link); // To add the Main Live Chat Div document.body.appendChild(mainLiveChatDiv);