Componente de botão flutuante do WhatsApp
Atualizado em: 28/05/2023
Código javascript que cria um botão flutuante com chamada para o WhatsApp, em um número previamente informado.
const whatsAppFloatComponent = (bottom, right, phoneNumber, title, opacity = 0.8) => {
const hide = (element, annimationTime) => {
element.style.display = 'none';
element.style.transition = `all ${annimationTime}ms`;
}
const show = (element, annimationTime) => {
element.style.display = 'block';
element.style.transition = `all ${annimationTime}ms`;
}
const handleCloseForm = () => {
hide(document.getElementById(`chat-popup${uniqueId}`), 500);
document.getElementById(`interactive-message${uniqueId}`).innerHTML = '';
document.getElementById(`button${uniqueId}`).disabled = false;
}
const handleTipingEffect = (element, text) => {
let i = 0;
const speed = 50;
const typeWriter = () => {
if (i < text.length) {
element.innerHTML += text.charAt(i);
i++;
setTimeout(typeWriter, speed);
}
}
typeWriter();
}
const handleOpenForm = () => {
show(document.getElementById(`chat-popup${uniqueId}`), 500);
handleTipingEffect(document.getElementById(`interactive-message${uniqueId}`), 'Olá, em que podemos ajudar?');
document.getElementById(`button${uniqueId}`).disabled = true;
}
const handleKeyDown = (event) => {}
const handleAutoResize = () => {
console.log('handleAutoResize');
}
const handleSendMessage = () => {
const message = document.getElementById(`text-area${uniqueId}`).value;
window.open(`https://api.whatsapp.com/send?phone=${phoneNumber}&text=${message}`, '_blank');
document.getElementById(`text-area${uniqueId}`).value = '';
handleCloseForm();
}
const uniqueId = Math.random().toString(36).substring(2) + Date.now().toString(36);
const image = document.createElement('img'); //whatsapp_logo
image.src = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+DQo8IS0tIFVwbG9hZGVkIHRvOiBTVkcgUmVwbywgd3d3LnN2Z3JlcG8uY29tLCBHZW5lcmF0b3I6IFNWRyBSZXBvIE1peGVyIFRvb2xzIC0tPg0KPHN2ZyB3aWR0aD0iODAwcHgiIGhlaWdodD0iODAwcHgiIHZpZXdCb3g9IjAgMCA0OCA0OCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj4NCiAgICANCiAgICA8dGl0bGU+V2hhdHNhcHAtY29sb3I8L3RpdGxlPg0KICAgIDxkZXNjPkNyZWF0ZWQgd2l0aCBTa2V0Y2guPC9kZXNjPg0KICAgIDxkZWZzPg0KDQo8L2RlZnM+DQogICAgPGcgaWQ9Ikljb25zIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMSIgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj4NCiAgICAgICAgPGcgaWQ9IkNvbG9yLSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTcwMC4wMDAwMDAsIC0zNjAuMDAwMDAwKSIgZmlsbD0iIzY3QzE1RSI+DQogICAgICAgICAgICA8cGF0aCBkPSJNNzIzLjk5MzAzMywzNjAgQzcxMC43NjIyNTIsMzYwIDcwMCwzNzAuNzY1Mjg3IDcwMCwzODMuOTk5ODAxIEM3MDAsMzg5LjI0ODQ1MSA3MDEuNjkyNjYxLDM5NC4xMTYwMjUgNzA0LjU3MDAyNiwzOTguMDY2OTQ3IEw3MDEuNTc5NjA1LDQwNi45ODM3OTggTDcxMC44MDQ0NDksNDA0LjAzNTUzOSBDNzE0LjU5ODYwNSw0MDYuNTQ2OTc1IDcxOS4xMjY0MzQsNDA4IDcyNC4wMDY5NjcsNDA4IEM3MzcuMjM3NzQ4LDQwOCA3NDgsMzk3LjIzNDMxNSA3NDgsMzg0LjAwMDE5OSBDNzQ4LDM3MC43NjU2ODUgNzM3LjIzNzc0OCwzNjAuMDAwMzk4IDcyNC4wMDY5NjcsMzYwLjAwMDM5OCBMNzIzLjk5MzAzMywzNjAuMDAwMzk4IEw3MjMuOTkzMDMzLDM2MCBaIE03MTcuMjkyODUsMzcyLjE5MDgzNiBDNzE2LjgyNzQ4OCwzNzEuMDc2MjggNzE2LjQ3NDc4NCwzNzEuMDM0MDcxIDcxNS43Njk3NzQsMzcxLjAwNTQwMSBDNzE1LjUyOTcyOCwzNzAuOTkxNDY0IDcxNS4yNjIyMTQsMzcwLjk3NzUyNyA3MTQuOTY1NjQsMzcwLjk3NzUyNyBDNzE0LjA0ODQ1LDM3MC45Nzc1MjcgNzEzLjA4OTQ2MiwzNzEuMjQ1NTE0IDcxMi41MTEwNDMsMzcxLjgzODAzMyBDNzExLjgwNjAzMywzNzIuNTU3NTc3IDcxMC4wNTY4NDMsMzc0LjIzNjM4IDcxMC4wNTY4NDMsMzc3LjY3OTIwMiBDNzEwLjA1Njg0MywzODEuMTIyMDIzIDcxMi41Njc1NzEsMzg0LjQ1MTc1NiA3MTIuOTA1OTQ0LDM4NC45MTc2NDggQzcxMy4yNTg2NDgsMzg1LjM4Mjc0MyA3MTcuODAwODA4LDM5Mi41NTAzMSA3MjQuODUzMjk3LDM5NS40NzE0OTIgQzczMC4zNjgzNzksMzk3Ljc1NzE0OSA3MzIuMDA0OTEsMzk3LjU0NTMwNyA3MzMuMjYwMDc0LDM5Ny4yNzczMiBDNzM1LjA5MzY1OCwzOTYuODgyMzA4IDczNy4zOTMwMDIsMzk1LjUyNzIzOSA3MzcuOTcxNDIxLDM5My44OTEwNDMgQzczOC41NDk4NCwzOTIuMjU0MDUgNzM4LjU0OTg0LDM5MC44NTcxNzEgNzM4LjM4MDI1NSwzOTAuNTYwOTEyIEM3MzguMjExMDY4LDM5MC4yNjQ2NTIgNzM3Ljc0NTMwOCwzOTAuMDk1ODE2IDczNy4wNDAyOTgsMzg5Ljc0MjYxNSBDNzM2LjMzNTI4OCwzODkuMzg5ODExIDczMi45MDczNywzODcuNjk2NjczIDczMi4yNTg0OSwzODcuNDcwODk0IEM3MzEuNjIzNTQzLDM4Ny4yMzExNzkgNzMxLjAxNzI1OSwzODcuMzE1OTk1IDczMC41Mzc5NjMsMzg3Ljk5MzMzIEM3MjkuODYwODE5LDM4OC45Mzg2NTMgNzI5LjE5ODAwNiwzODkuODk4MzEgNzI4LjY2MTc4NSwzOTAuNDc2NDk0IEM3MjguMjM4NjE5LDM5MC45MjgwNTEgNzI3LjU0NzE0NCwzOTAuOTg0NTk1IDcyNi45NjkxMjMsMzkwLjc0NDQ4MSBDNzI2LjE5MzI1NCwzOTAuNDIwMzQ4IDcyNC4wMjEyOTgsMzg5LjY1Nzc5OCA3MjEuMzQwOTg1LDM4Ny4yNzMzODggQzcxOS4yNjczNTYsMzg1LjQyNTM1IDcxNy44NTY5MzgsMzgzLjEyNTc1NiA3MTcuNDQ4MTA0LDM4Mi40MzQ0ODQgQzcxNy4wMzg4NzEsMzgxLjcyOTI3NSA3MTcuNDA1OTA3LDM4MS4zMTk1MjkgNzE3LjcyOTk0OCwzODAuOTM4ODUyIEM3MTguMDgyNjUzLDM4MC41MDEyMzIgNzE4LjQyMTAyNiwzODAuMTkxMDM2IDcxOC43NzM3MywzNzkuNzgxNjg4IEM3MTkuMTI2NDM0LDM3OS4zNzI3MzggNzE5LjMyMzg4NCwzNzkuMTYwODk3IDcxOS41NDk1OTksMzc4LjY4MTA2OCBDNzE5Ljc4OTY0NSwzNzguMjE1NTc1IDcxOS42MjAwNiwzNzcuNzM1NzQ2IDcxOS40NTA4NzQsMzc3LjM4Mjk0MiBDNzE5LjI4MTY4NywzNzcuMDMwMTM5IDcxNy44NzEyNjksMzczLjU4NzMxNyA3MTcuMjkyODUsMzcyLjE5MDgzNiBaIiBpZD0iV2hhdHNhcHAiPg0KDQo8L3BhdGg+DQogICAgICAgIDwvZz4NCiAgICA8L2c+DQo8L3N2Zz4=';
image.alt = 'whatsapp icon';
image.style.width = '45px';
const div = document.createElement('div'); //whatsAppWidget
div.id = `root${uniqueId}`;
div.style.fontFamily = "'Segoe UI', Tahoma, Geneva, Verdana, sans-serif";
const button = document.createElement('button'); // open-button
button.id = `button${uniqueId}`;
button.style.position = 'fixed';
button.style.bottom = `${bottom}px`;
button.style.right = `${right}px`;
button.style.backgroundColor = 'transparent';
button.style.color = 'white';
button.style.border = 'none';
button.style.opacity = opacity;
button.style.cursor = 'pointer';
button.style.zIndex = '9999';
button.addEventListener('click', handleOpenForm);
const chat = document.createElement('div'); // myForm (.chat-popup)
chat.id = `chat-popup${uniqueId}`;
chat.style.display = 'none';
chat.style.position = 'fixed';
chat.style.bottom = '60px';
chat.style.right = `${right}px`;
chat.style.borderRadius = '10px';
chat.style.zIndex = '9999';
const form = document.createElement('form');
form.id = `form${uniqueId}`;
form.method = 'post';
form.style.maxWidth = '300px';
form.style.backgroundColor = '#E5DDD5';
form.style.borderRadius = '10px';
form.style.border = '1px solid #25d366';
const titleH6 = document.createElement('h6');
titleH6.id = `title${uniqueId}`;
titleH6.style.backgroundColor = '#25d366';
titleH6.style.color = 'white';
titleH6.style.fontSize = '0.8rem';
titleH6.style.padding = '7px';
titleH6.style.borderRadius = '10px 10px 0 0';
titleH6.style.height = '30px';
titleH6.style.display = 'flex';
titleH6.style.justifyContent = 'space-between';
titleH6.style.alignItems = 'center';
titleH6.style.margin = '0';
const text = document.createElement('span');
text.id = `text${uniqueId}`;
text.style.float = 'left';
text.innerText = title;
const close = document.createElement('span');
close.id = `close${uniqueId}`;
close.style.float = 'right';
close.style.cursor = 'pointer';
close.innerText = 'X';
close.addEventListener('click', handleCloseForm);
const fields = document.createElement('div'); // campos-chat
div.id = `fields${uniqueId}`;
div.style.padding = '0 10px 10px 10px';
const chatContainer = document.createElement('div'); //balao-chat
chatContainer.id = `chat-container${uniqueId}`;
chatContainer.style.backgroundColor = '#fff';
chatContainer.style.padding = '8px';
chatContainer.style.fontSize = '16px';
chatContainer.style.borderRadius = '0 0 10px 10px';
chatContainer.style.marginBottom = '40px';
chatContainer.style.marginTop = '10px';
chatContainer.style.color = '#444';
const interactiveText = document.createElement('span'); // msg-p-wp
interactiveText.id = `interactive-text${uniqueId}`;
interactiveText.style.display = 'none';
interactiveText.innerText = '...';
const interactiveMessage = document.createElement('span'); // msg-wp
interactiveMessage.id = `interactive-message${uniqueId}`;
const labelMsg = document.createElement('label'); // msg
const b = document.createElement('b');
labelMsg.appendChild(b);
const containerTextArea = document.createElement('div'); // container-textarea
containerTextArea.id = `container-textarea${uniqueId}`;
containerTextArea.style.height = '60px';
containerTextArea.style.display = 'flex';
containerTextArea.style.alignItems = 'center';
containerTextArea.style.marginBottom = '10px';
containerTextArea.addEventListener('click', handleAutoResize);
const textArea = document.createElement('textarea'); // msg-whatts
textArea.id = `text-area${uniqueId}`;
textArea.name = 'msg';
textArea.placeholder = 'Digite sua mensagem...';
textArea.style.width = '100%';
textArea.style.padding = '15px';
textArea.style.margin = '5px 0 22px 0';
textArea.style.border = 'none';
textArea.style.background = '#f1f1f1';
textArea.style.resize = 'none';
textArea.style.height = '100%';
textArea.style.borderRadius = '10px 0 10px 10px';
textArea.setAttribute('required', '');
textArea.addEventListener('keydown', handleKeyDown);
const buttonSubmit = document.createElement('img'); // .btn-send
buttonSubmit.id = `button-submit${uniqueId}`;
buttonSubmit.src = "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pgo8IS0tIEdlbmVyYXRvcjogQWRvYmUgSWxsdXN0cmF0b3IgMTYuMC4wLCBTVkcgRXhwb3J0IFBsdWctSW4gLiBTVkcgVmVyc2lvbjogNi4wMCBCdWlsZCAwKSAgLS0+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+CjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iQ2FwYV8xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCIKCSB3aWR0aD0iNTM1LjVweCIgaGVpZ2h0PSI1MzUuNXB4IiB2aWV3Qm94PSIwIDAgNTM1LjUgNTM1LjUiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDUzNS41IDUzNS41OyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSIKCT4KPGc+Cgk8ZyBpZD0ic2VuZCI+CgkJPHBvbHlnb24gcG9pbnRzPSIwLDQ5Ny4yNSA1MzUuNSwyNjcuNzUgMCwzOC4yNSAwLDIxNi43NSAzODIuNSwyNjcuNzUgMCwzMTguNzUgCQkiLz4KCTwvZz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8L3N2Zz4K";
buttonSubmit.style.width = '25px';
buttonSubmit.style.backgroundColor = 'transparent';
buttonSubmit.style.color = 'transparent';
buttonSubmit.style.padding = '0';
buttonSubmit.style.border = 'none';
buttonSubmit.style.cursor = 'pointer';
buttonSubmit.style.marginLeft = '5px';
buttonSubmit.style.marginTop = '-15px';
buttonSubmit.addEventListener('click', handleSendMessage);
containerTextArea.appendChild(textArea);
containerTextArea.appendChild(buttonSubmit);
chatContainer.appendChild(interactiveText);
chatContainer.appendChild(interactiveMessage);
fields.appendChild(chatContainer);
fields.appendChild(labelMsg);
fields.appendChild(containerTextArea);
titleH6.appendChild(text);
titleH6.appendChild(close);
form.appendChild(titleH6);
form.appendChild(fields);
chat.appendChild(form);
button.appendChild(image);
div.appendChild(button);
div.appendChild(chat);
document.body.appendChild(div);
}
Como usar:
<!DOCTYPE html>
<html lang="pt-br">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Teste</title>
</head>
<body>
Olá, tudo bem?
<script src="whatsAppFloatComponent.js"></script>
<script>
whatsAppFloatComponent(10, 10, '5567999000000', 'Bem vindo')
</script>
</body>
</html>