text: const socket = io();
  
  // Elementes
  const $messageForm = document.querySelector('#message-form');
  const $messageFormInput = $messageForm.querySelector('input');
  const $messageFormButton = $messageForm.querySelector('button');
  const $sendLocationButton = document.querySelector('#send-location');
  const $messages = document.querySelector('#messages');
  
  // Templates
  const messageTemplate = document.querySelector('#message-template').innerHTML;
  const locationMessageTemplate = document.querySelector(
    '#location-message-template'
  ).innerHTML;
  const sidebarTemplate = document.querySelector('#sidebar-template').innerHTML;
  
  // Options
  const { username, room } = Qs.parse(location.search, {
    ignoreQueryPrefix: true
  });
  
  const autoscroll = () => {
    const $newMessage = $messages.lastElementChild;
  
    const newMessageStyles = getComputedStyle($newMessage);
    const newMessageMargin = parseInt(newMessageStyles.marginBottom);
    const newMessageHeight = $newMessage.offsetHeight + newMessageMargin;
  
    const visibleHeight = $messages.offsetHeight;
  
    const containerHeight = $messages.scrollHeight;
  
    const scrollOffset = $messages.scrollTop + visibleHeight;
  
    if (containerHeight - newMessageHeight <= scrollOffset) {
      $messages.scrollTop = $messages.scrollHeight;
    }
  };
  
  socket.on('sendMessage', message => {
    const html = Mustache.render(messageTemplate, {
      username: message.username,
      message: message.text,
      createdAt: moment(message.createdAt).format('hh:mm A')
    });
    $messages.insertAdjacentHTML('beforeend', html);
    autoscroll();
  });
  
  socket.on('roomData', ({ room, users }) => {
    const html = Mustache.render(sidebarTemplate, {
      room,
      users
    });
    document.querySelector('#sidebar').innerHTML = html;
  });
  
  socket.on('sendLocationMessage', locationMessage => {
    const html = Mustache.render(locationMessageTemplate, {
      username: locationMessage.username,
      locationURL: locationMessage.url,
      createdAt: moment(locationMessage.createdAt).format('hh:mm A')
    });
    $messages.insertAdjacentHTML('beforeend', html);
    autoscroll();
  });
  
  document.querySelector('#message-form').addEventListener('submit', e => {
    $messageFormButton.setAttribute('disabled', 'disabled');
  
    e.preventDefault();
    const inputMessage = e.target.elements.message.value;
    socket.emit('newMessage', inputMessage, error => {
      $messageFormButton.removeAttribute('disabled');
  
      if (error) {
        return alert(error);
      }
  
      $messageFormInput.value = '';
      $messageFormInput.focus();
      console.log('Message delivered!');
    });
  });
  
  $sendLocationButton.addEventListener('click', () => {
    $sendLocationButton.setAttribute('disabled', 'disabled');
    if (!navigator.geolocation) {
      return alert('Geolocation is not supported by your browser!');
    }
  
    navigator.geolocation.getCurrentPosition(position => {
      socket.emit(
        'sendLocation',
        {
          latitude: position.coords.latitude,
          longitude: position.coords.longitude
        },
        () => {
          console.log('Location shared!');
          $sendLocationButton.removeAttribute('disabled');
        }
      );
    });
  });
  
  socket.emit('join', { username, room }, error => {
    if (error) {
      alert(error);
      location.href = '/';
    }
  });
  