text: // Make connection
  const socket = io()
  
  // Query DOM
  const message = document.getElementById('message')
  const username = document.getElementById('username')
  const btnLocation = document.getElementById('sendLocation')
  const output = document.getElementById('output')
  const feedback = document.getElementById('feedback')
  const file = document.getElementById('myfile')
  const clearBtn = document.getElementById('clear')
  const ipsBtn = document.getElementById('ips')
  const input = document.querySelector('input[type="file')
  const plane = document.getElementById('plane')
  const siteurl = 'https://YOURWEBSITEURL:8080'
  // const siteurl = 'https://localhost:8080'
  // const siteurl = 'https://192.168.1.100:8080'
  
  // Grab the current username so we can apply css rules ex: bubble color
  const currentusername = username.value
  // console.log('The current username is:', currentusername)
  
  // Start Modal
  // Get the modal
  const modal = document.getElementById('myModal')
  // Get the image and insert it inside the modal
  const img = document.getElementById('myImg')
  const modalImg = document.getElementById('img01')
  const captionText = document.getElementById('caption')
  
  function imgClick(elem){
      modal.style.display = 'block'
      let img = document.getElementsByTagName("img")
  
      for (i = 0; i < img.length; i++) {
          img[i].classList.remove('active')
      }
      elem.classList.add('active')
  
      let x = document.getElementsByClassName("active")
      let y = x.item(0).src
      modalImg.src = y
      // Notes...
      // First assign active class name to clicked element
      // Then select active class and extract the HTMLCollection src item
      // First my assign x to the className
      // Then by assign y to the parsed src item from the HTMLCollection
      // Important pass elem to imgClick function then use (this) inside the inline html onclick action ex: "onclick="imgClick(this)"
  }
  
  function hrefClick(elem){
      modal.style.display = 'block'
      let a = document.getElementsByTagName("a")
  
      for (i = 0; i < a.length; i++) {
          a[i].classList.remove('active')
      }
      elem.classList.add('active');
  
      let x = document.getElementsByClassName("active")
      let y =     x.item(0).attributes[0].nodeValue
      modalImg.src = y
  }
  
  // Get the <span> element that closes the modal
  const span = document.getElementsByClassName('close')[0]
  // Close modal by clicking to x on modal
  function spanClick() {
      modal.style.display = 'none'
  }
  // Close modal by hitting the esacape key
  window.addEventListener('keydown', function (event) {
    if (event.key === 'Escape') {
      modal.style.display = 'none'
    }
  })
  // End Modal
  
  // Sound Notfication
  let myRing = new Audio('/sounds/ring.ogg');
  myRing.load();
  
  // Time setup
  function hhmm () {
      let now = new Date();
      return  now.getDate() + '/' + (now.getMonth() + 1) + '/' + now.getFullYear() + ' - ' + (now.getHours() < 10 ? '0' : '') + now.getHours() + ':' + (now.getMinutes() < 10 ? '0' : '') + now.getMinutes() + ':' + (now.getSeconds() < 10 ? '0' : '') + now.getSeconds();
  }
  
  // Emit events
  
  // Scroll to bottom
  window.onload=function () {
      let objDiv = document.getElementById("output");
      objDiv.scrollTop = objDiv.scrollHeight;
  }
  
  function updateScroll(){
      let element = document.getElementById("output");
      element.scrollTop = element.scrollHeight;
  }
  
  // Show hide buttons to only admin
  clearBtn.style.display = 'none'
  ipsBtn.style.display = 'none'
  btnLocation.style.display = 'none'
  
  if (username.value == 'YOUR-ADMIN-USER-NAME-HERE') {
      clearBtn.style.display = 'block'
      ipsBtn.style.display = 'block'
      btnLocation.style.display = 'block'
  }
  
  // Detect editable content on message input and permute send and file icons
  plane.style.display = 'none'
  upload_btn.style.display = 'block'
  
  message.addEventListener('input', function() {
      if (message.textContent === '' ) {
          plane.style.display = 'none'
          upload_btn.style.display = 'block'        
      } else {
          plane.style.display = 'block'
          upload_btn.style.display = 'none'
      }
      // console.log('Message:)', message)
      // console.log('TextContent:)', message.textContent)
      // console.log('Inner HTML:)', message.innerHTML)
  })
  
  function getFocus() {
      document.getElementById("message").focus();
    }
  
  function hideKeyboard() {
  	document.activeElement.blur()
  }
  
  function sendNewMessageAlert() {
      setTimeout(function() { document.title = "New message" }, 1000)
      message.addEventListener('click', () => { document.title = "Chat" })
  }
  
  function autoClick(){
      let b = document.getElementById('message')
      setTimeout(function(){
          b.click()
      }, 1000)
      // console.log('clicked')
  }
  
  // Testing
  
  // Get browser
  // if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
  //     console.log('mobile')
  //     } else {
  //         console.log('not mobile')
  //     }
  // End Get browser
  
  // Change page title on new message
  
  
  // End of Change page title on new message
  
  // End Testing
  
  // Emit Geolocation to server
  function showPosition() {
      if(navigator.geolocation) {
          navigator.geolocation.getCurrentPosition(function(position) {
              let positionInfo = "<a href=https://www.google.com/maps/place/" + position.coords.latitude + "," + position.coords.longitude + " " + "target=" + "_blank" + ">My location</a>"
  
              socket.emit('chat-geolocation', {
                  username: username.value,
                  message: positionInfo,
                  createdAt: hhmm()
              })
              message.textContent = ''
              getFocus()
          })
      } else {
          alert("Sorry, your browser does not support HTML5 geolocation.")
      }
  }
  
  // Function to detect browser window size
  function getWindowSize() {
      let dimensions = document, root = dimensions.documentElement, body = dimensions.body;
      let width = window.innerWidth || root.clientWidth || body.clientWidth, 
      height = window.innerHeight || root.clientHeight || body.clientHeight ;
      return [width,height]
     }
  // console.log('x & y axis:', getWindowSize())
  // console.log('x axis:', getWindowSize()[0])
  // console.log('y axis:', getWindowSize()[1])
  
  // Emit chat message to server if enter key is pressed and device is a phone device
  // Detect keypress on message input element
  message.onkeyup = function (e) {
      // console.log('keyup');
      if (!e) {
          e = window.event;
      }
      let keyCode = e.which || e.keyCode,
          message = e.target || e.srcElement;
  
      if (keyCode === 13 && !e.shiftKey) {
          // console.log('Just enter');
          if (e.preventDefault) {
              e.preventDefault();
          } else {
              e.returnValue = false;
          }
          if(getWindowSize()[0] > 415){
              if (username.text == '' || message.textContent == '') {
                  alert('no empty username or message field allowed')
              } else if (message.textContent.startsWith('www') 
              || message.textContent.startsWith('http://') 
              || message.textContent.startsWith('https://')) {
                  socket.emit('chat', {
                      username: username.value,
                      message: '<a href="' + message.textContent + '"target="_blank">Check this link</a>',
                      createdAt: hhmm()
                  })
                      // console.log('user:', username.value)
                      // console.log('message:', message.textContent)
                      message.textContent = ''
                      plane.style.display = 'none'
                      upload_btn.style.display = 'block'
                      getFocus()
                  }
              else {
                  socket.emit('chat', {
                      username: username.value,
                      message: message.textContent,
                      createdAt: hhmm()
                  })
                  message.textContent = ''
                  plane.style.display = 'none'
                  upload_btn.style.display = 'block'
                  getFocus()
              }
          }       
      }
  }
  
  // Emit chat message to server
  plane.addEventListener('click', () => {
      if (username.text == '' || message.textContent == '') {
          alert('no empty username or message field allowed')
      } else if (message.textContent.startsWith('www') 
      || message.textContent.startsWith('http://') 
      || message.textContent.startsWith('https://')) {
          socket.emit('chat', {
              username: username.value,
              message: '<a href="' + message.textContent + '"target="_blank">Check this link</a>',
              createdAt: hhmm()
          })
              // console.log('user:', username.value)
              // console.log('message:', message.textContent)
              message.textContent = ''
              plane.style.display = 'none'
              upload_btn.style.display = 'block'
              getFocus()
              hideKeyboard()
          }
      else {
          socket.emit('chat', {
              username: username.value,
              message: message.textContent,
              createdAt: hhmm()
          })
          message.textContent = ''
          plane.style.display = 'none'
          upload_btn.style.display = 'block'
          getFocus()
          hideKeyboard()
      }
  }, true)
  
  // Set the timeout function for the user is typing feature
    let timeout;
    function timeoutFunction() {
        typing = false;
    }
  
  // Emit user is typing event
  message.addEventListener('keypress', (event) => {
      // socket.emit('typing', username.value)
      if (event.code !== 'Enter') {
          typing = true; // we know the user is typing because they have pressed a key but not 'Enter'
          socket.emit("typing", username.value, true);
          clearTimeout(timeout);
          timeout = setTimeout(timeoutFunction, 1500);
      } else {
          clearTimeout(timeout); // no need to fire the timeoutFunction twice (as we do it on the next line)
          timeoutFunction();     // probably needs a better name but this will immediately send the necessary `socket.emit('typing', false)` when the enter key is pressed
      }
  })
  
  function loadMessages(data) {
      feedback.innerHTML = ''
      if(data.username === currentusername && data.message == undefined) {
          output.innerHTML += '<li class="mymsg-image-thisuser"><strong>' + data.username + ': </strong>' + '<a img="' + siteurl + '/uploads/'+ data.name + '" onclick="hrefClick(this)"> click to view photo or file</a></li>' + '<span class="mymsg-thisuser time"><strong>sent at: </strong>' + data.createdAt + '<a href="/' + data._id + '/message_delete?_method=DELETE"' + `onclick="return confirm('Are you sure you want to delete this message?')"` + '><i class="fas fa-times-circle fa-2x"></i></a>' + '</span>'
      } else if (data.message == undefined) {
          output.innerHTML += '<li class="mymsg-image"><strong>' + data.username + ': </strong>' + '<a img="' + siteurl + '/uploads/'+ data.name + '" onclick="hrefClick(this)"> click to view photo or file</a></li>' + '<span class="mymsg time"><strong>sent at: </strong>' + data.createdAt + '<a href="/' + data._id + '/message_delete?_method=DELETE"' + `onclick="return confirm('Are you sure you want to delete this message?')"` + '><i class="fas fa-times-circle fa-2x"></i></a>' + '</span>'
      } else if (data.username == currentusername) {
          output.innerHTML += '<li class="mymsg-thisuser"><strong>' + data.username + ': </strong>' + data.message + '</li>' + '<span class="mymsg-thisuser time"><strong>sent at: </strong>' + data.createdAt + '<a href="/' + data._id + '/message_delete?_method=DELETE"' + `onclick="return confirm('Are you sure you want to delete this message?')"` + '><i class="fas fa-times-circle fa-2x"></i></a>' + '</span>'
      } else {
          output.innerHTML += '<li class="mymsg"><strong>' + data.username + ': </strong>' + data.message + '</li>' + '<span class="mymsg time"><strong>sent at: </strong>' + data.createdAt + '<a href="/' + data._id + '/message_delete?_method=DELETE"' + `onclick="return confirm('Are you sure you want to delete this message?')"` + '><i class="fas fa-times-circle fa-2x"></i></a>' + '</span>'
      }
      file.value = ''
      updateScroll()
  }
  
  function showMessages(data) {
      feedback.innerHTML = ''
      if(data.username === currentusername && data.message == undefined) {
          output.innerHTML += '<li class="mymsg-image-thisuser"><strong>' + data.username + ': </strong>' + '<a img="' + siteurl + '/uploads/'+ data.name + '" onclick="hrefClick(this)"> click to view photo or file</a></li>' + '<span class="mymsg-thisuser time"><strong>sent at: </strong>' + data.createdAt + '<a href="/' + data._id + '/message_delete?_method=DELETE"' + `onclick="return confirm('Are you sure you want to delete this message?')"` + '><i class="fas fa-times-circle fa-2x"></i></a>' + '</span>'
      } else if (data.message == undefined) {
          output.innerHTML += '<li class="mymsg-image"><strong>' + data.username + ': </strong>' + '<a img="' + siteurl + '/uploads/'+ data.name + '" onclick="hrefClick(this)"> click to view photo or file</a></li>' + '<span class="mymsg time"><strong>sent at: </strong>' + data.createdAt + '<a href="/' + data._id + '/message_delete?_method=DELETE"' + `onclick="return confirm('Are you sure you want to delete this message?')"` + '><i class="fas fa-times-circle fa-2x"></i></a>' + '</span>'
      } else if (data.username == currentusername) {
          output.innerHTML += '<li class="mymsg-thisuser"><strong>' + data.username + ': </strong>' + data.message + '</li>' + '<span class="mymsg-thisuser time"><strong>sent at: </strong>' + data.createdAt + '<a href="/' + data._id + '/message_delete?_method=DELETE"' + `onclick="return confirm('Are you sure you want to delete this message?')"` + '><i class="fas fa-times-circle fa-2x"></i></a>' + '</span>'
      } else {
          output.innerHTML += '<li class="mymsg"><strong>' + data.username + ': </strong>' + data.message + '</li>' + '<span class="mymsg time"><strong>sent at: </strong>' + data.createdAt + '<a href="/' + data._id + '/message_delete?_method=DELETE"' + `onclick="return confirm('Are you sure you want to delete this message?')"` + '><i class="fas fa-times-circle fa-2x"></i></a>' + '</span>'
      }
      file.value = ''
      updateScroll()
      myRing.play()
      sendNewMessageAlert()
      if (data.username === currentusername){
          autoClick()
      }
  }
  
  function showMessagesWithFiles(data) {
      feedback.innerHTML = ''
      if (data.username == currentusername) {
          output.innerHTML += '<li class="mymsg-image-thisuser"><strong>' + data.username + ': </strong>' + '<a img="' + siteurl + '/uploads/'+ data.name + '" onclick="hrefClick(this)"> click to view photo or file</a></li>' + '<span class="mymsg-thisuser time"><strong>sent at: </strong>' + data.createdAt + '<a href="/' + data._id + '/message_delete?_method=DELETE"' + `onclick="return confirm('Are you sure you want to delete this message?')"` + '><i class="fas fa-times-circle fa-2x"></i></a>' + '</span>'
      } else {
          output.innerHTML += '<li class="mymsg-image"><strong>' + data.username + ': </strong>' + '<a img="' + siteurl + '/uploads/'+ data.name + '" onclick="hrefClick(this)"> click to view photo or file</a></li>' + '<span class="mymsg time"><strong>sent at: </strong>' + data.createdAt + '<a href="/' + data._id + '/message_delete?_method=DELETE"' + `onclick="return confirm('Are you sure you want to delete this message?')"` + '><i class="fas fa-times-circle fa-2x"></i></a>' + '</span>'
      }
      updateScroll()
      myRing.play()
      sendNewMessageAlert()
      if (data.username === currentusername){
          autoClick()
      }
  }
  
  // Listen for events
  // Load all db messages to browser
  socket.on('load old msgs', (data) => {
      for(let i = 0; i < data.length; i++) {
      loadMessages(data[i])
      }
  })
  
  // Show Geolocation data on browser
  socket.on('chat-geolocation', (data) => {
      showMessages(data)
  })
  
  // Show message
  socket.on('chat', (data) => {
      showMessages(data)
  })
  
  // Upload document (images, videos, files, etc...)
  document.addEventListener('DOMContentLoaded', () => {
      // Initialize instances:
      let siofu = new SocketIOFileUpload(socket)
  
      // Configure the three ways that SocketIOFileUpload can read files:
      document.getElementById('upload_btn').addEventListener('click', siofu.prompt, false)
      // siofu.listenOnInput(document.getElementById('upload_input'))
      // siofu.listenOnDrop(document.getElementById('file_drop'))
  
      // Do something on upload progress:
      siofu.addEventListener('progress', (event) => {
          let percent = event.bytesLoaded / event.file.size * 100
          console.log('File is', percent.toFixed(2), 'percent loaded')
      });
  
      // Do something when a file is uploaded:
      siofu.addEventListener('complete', (event) => {
          socket.emit('chat-username', {
              username: username.value
          })
          console.log(event.success)
          getFocus()
      })
  }, false)
  
  // Display image on browser
  socket.on('chat-image', (data) => {
      showMessagesWithFiles(data)
  })
  
  // Broadcast typing event
  socket.on('typing', (data) => {
      feedback.innerHTML = '<p class="feedback-msg"><em>' + data + ' is typing a message <span>.</span><span>.</span><span>.</span> </em></p>'
  })
  
  // Handle Chat Clear
  clearBtn.addEventListener('click', function(){
      socket.emit('clear')
      window.location.reload()
  })    
  