DEV Community

Cover image for Fake C++ Compiler with Node.js - Frontend - Part 3
Gurigraphics
Gurigraphics

Posted on

1

Fake C++ Compiler with Node.js - Frontend - Part 3

Finally the front end...

index.html

<!DOCTYPE html>
<html lang='en'>
  <head>
    <meta name='viewport' content='width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no'>
    <meta charset='utf-8'>
    <title>Fake Compiler C++</title>

    <link rel='stylesheet' href='./style.css'>
  </head>
  <body >
    <div id='root'>

      <div id="loader" class="center">        
        <div class="loader"></div>        
      </div>

      <div class="forms center">

        <h1>
          Fake Compiler C++
        </h1>

        <div class="area area_download hide">

          <div class="folder_icon  transparent">
            <svg class="transparent" stroke="currentColor" fill="currentColor" stroke-width="0" version="1.1" viewBox="0 0 16 16" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M9 4l-2-2h-7v13h16v-11h-7zM8 13.5l-3.5-3.5h2.5v-4h2v4h2.5l-3.5 3.5z"></path></svg></div>
           <label class="form-label transparent" for="customFile"><span class="transparent">Download</span></label>

        </div>


         <div class="area txt_area">

          <div class="folder_icon folder_icon_txt transparent">
              <svg class="transparent" stroke="currentColor" stroke-width="0" version="1.1" viewBox="0 0 16 16" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M9 4l-2-2h-7v13h16v-11h-7zM8 7.5l3.5 3.5h-2.5v4h-2v-4h-2.5l3.5-3.5z"></path></svg>
          </div>   

           <div class="folder_icon confirm_icon_txt transparent hide">           
           <svg class="transparent" stroke="currentColor" stroke-width="0" viewBox="0 0 16 16" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zm-3.97-3.03a.75.75 0 0 0-1.08.022L7.477 9.417 5.384 7.323a.75.75 0 0 0-1.06 1.06L6.97 11.03a.75.75 0 0 0 1.079-.02l3.992-4.99a.75.75 0 0 0-.01-1.05z"></path></svg>
           </div>


          <label class="form-label transparent txt_browse" for="customFile">Drag & Drop or <span class="transparent">Browse</span></label>
          <label class="form-label transparent txt_remove hide" for="customFile">Click to <span class="transparent">Remove</span></label> 

          <form class="form transparent" id="txt" method="post" enctype="multipart/form-data" action="/uploads">
            <input type="hidden" name="msgtype" value="2"/>
            <input onchange="txt_change();" type="file" name="uploadFile" accept=".txt" class="form-control hide input_file_txt"/>  
            <label class="form-label suports transparent" for="customFile">Suports: <span class="span transparent">TXT</span></label>
            <button type="submit" value="Upload" class="btn btn-dark hide">Browse File</button>
          </form>

        </div>

        <div class="area exe_area">

          <div class="folder_icon folder_icon_exe transparent">
              <svg class="transparent" stroke="currentColor" stroke-width="0" version="1.1" viewBox="0 0 16 16" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M9 4l-2-2h-7v13h16v-11h-7zM8 7.5l3.5 3.5h-2.5v4h-2v-4h-2.5l3.5-3.5z"></path></svg>
          </div> 

          <div class="folder_icon confirm_icon_exe transparent hide">           
           <svg class="transparent" stroke="currentColor" stroke-width="0" viewBox="0 0 16 16" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zm-3.97-3.03a.75.75 0 0 0-1.08.022L7.477 9.417 5.384 7.323a.75.75 0 0 0-1.06 1.06L6.97 11.03a.75.75 0 0 0 1.079-.02l3.992-4.99a.75.75 0 0 0-.01-1.05z"></path></svg>
           </div>

          <label class="form-label transparent exe_browse" for="customFile">Drag & Drop or <span class="transparent">Browse</span></label>
          <label class="form-label transparent exe_remove hide" for="customFile">Click to <span class="transparent">Remove</span></label> 

          <form class="form transparent" id="exe" method="post" enctype="multipart/form-data" action="/uploads">
            <input type="hidden" name="msgtype" value="2"/>
            <input onchange="exe_change();" type="file" name="uploadFile" accept=".exe" class="form-control hide input_file_exe"/>  
            <label class="form-label suports transparent" for="customFile">Suports: <span class="span transparent">EXE</span></label>
            <button type="submit" value="Upload" class="btn btn-dark hide btn_exe">Browse File</button>
          </form>

        </div>

        <div class="btn_compile noSelect hide">Send</div>

      </div>

    </div>
   <script src='./main.js'></script>
  </body>
</html>

Enter fullscreen mode Exit fullscreen mode

style.css

*{
  padding: 0px;
  margin: 0px;
  outline: none;
  box-sizing: border-box;
  font-family: Arial;
  background: #191818;
  color: black;
}

h1{
  color: #b9b9bd;
  margin-top: 50px;
  margin-bottom: 50px;
}

#loader{
  min-width: 100%;
  min-height: 90vh;
  position: absolute;
  background: #191818;
}

.loader{
  border: 16px solid #f3f3f3;
  border-radius: 50%;
  border-top: 16px solid #3498db;
  width: 120px;
  height: 120px;
  -webkit-animation: spin 2s linear infinite; /* Safari */
  animation: spin 2s linear infinite;
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

.center-buttons{
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
  text-align: center;
}

.center{
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  text-align: center;
}  

.transparent{
  background-color: rgba(255,255,255,0);
  pointer-events: none;
}

.noSelect{
  -webkit-touch-callout: none; /* iOS Safari */
  -webkit-user-select: none; /* Safari */
  -khtml-user-select: none; /* Konqueror HTML */
  -moz-user-select: none; /* Old versions of Firefox */
  -ms-user-select: none; /* Internet Explorer/Edge */
  user-select: none; /* Non-prefixed version, currently
  supported by Chrome, Edge, Opera and Firefox */
}

.hide{
  display: none;
}

.btn{
  margin-left: 6px;
}

.forms{
  margin-top: 50px;
}

.form{
  display: grid;
  grid-template-columns: 1fr;
  grid-template-rows: 1fr;
} 

.area{
  border: 2px dashed #000000; 
  font-size: 24px;
  background: #2d2d2d;
  width: 320px;
  height: 197px;
  padding-top: 36px;
}

.txt_area{

}

.exe_area{
  margin-top: 50px;  
}

.area_hover{
  border: 2px dashed #272629;
  background: #3F51B5;
  cursor: grabbing;
}

.area_active{
  border: 2px dashed #272629;
  background: #4CAF50;
  cursor: grabbing;
}

.area_download{
  padding-top: 46px;
  border: 2px solid #000000;
  cursor: pointer;
  border-radius: 4px
}

.area_download:hover{
  background: #4CAF50; 
}

.area_download:active{
  background: #3F51B5;
}

.folder_icon{
  font-size: 50px;
}

span{
  font-weight: bold;
  font-size: 24px;
}

.suports{
  font-size: 18px;
}
.span{
  font-size: 16px;
}


.btn_compile{
  background: #FFC107;

  width: 160px;
  height: 52px;
  line-height: 52px;

  margin-top: 50px;
  align-items: center;
  font-weight: bold;
  font-size: 20px;
  border-radius: 4px;
  border: 1px solid #000000;
  cursor: pointer;
}

.btn_compile:hover{
  background: #3F51B5;
}

.btn_compile:active{
  background: #4CAF50;
}

Enter fullscreen mode Exit fullscreen mode

main.js

const log = val => console.log( val )
const get = val => document.querySelector( val )

var txt_area = get('.txt_area')
var exe_area = get('.exe_area')

var txt_active = false
var exe_active = false

// audio
var AUDIO = {}
var audio = new Audio('ok.ogg')

AUDIO.play = () => {
  audio.play()  
}


// loader
var LOADER = {}

LOADER.hide = () => {

  get("#loader").classList.add("hide")  
}

LOADER.show = () => {

  get("#loader").classList.remove("hide")  
}


// active and remove
var txt_active_fn = () => {

  txt_area.classList.remove("area_hover")
  txt_area.classList.add("area_active")

  // Confirm
  get(".folder_icon_txt").classList.add("hide")
  get(".confirm_icon_txt").classList.remove("hide")

  get(".txt_browse").classList.add("hide")
  get(".txt_remove").classList.remove("hide")
  txt_active = true
  update_compile_button()

  AUDIO.play()  

  post_txt() 
}

var exe_active_fn = () => {

  exe_area.classList.remove("area_hover")
  exe_area.classList.add("area_active")

    // Confirm
  get(".folder_icon_exe").classList.add("hide")
  get(".confirm_icon_exe").classList.remove("hide")

  get(".exe_browse").classList.add("hide")
  get(".exe_remove").classList.remove("hide")
  exe_active = true
  update_compile_button()

  AUDIO.play()  
}

var txt_remove = () => {

  get('.input_file_txt').value = ""
  txt_area.classList.remove("area_active")

  get(".folder_icon_txt").classList.remove("hide")
  get(".confirm_icon_txt").classList.add("hide")

  get(".txt_browse").classList.remove("hide")
  get(".txt_remove").classList.add("hide")

  txt_active = false
  update_compile_button()
}

var exe_remove = () => {

  get('.input_file_exe').value = ""
  exe_area.classList.remove("area_active")

  get(".folder_icon_exe").classList.remove("hide")
  get(".confirm_icon_exe").classList.add("hide")

  get(".exe_browse").classList.remove("hide")
  get(".exe_remove").classList.add("hide")

  exe_active = false
  update_compile_button()
}


// txt_area

txt_area.onclick = function(){ 
  if( !txt_area.classList.contains("area_active") ){
    get('.input_file_txt').click()
  }else{
    txt_remove()
  }
}

txt_area.ondragenter = function(){ 
  console.log("start")  
  if( !txt_area.classList.contains("area_active") ){
    txt_area.classList.add("area_hover")
  } 
}

txt_area.ondragleave = function(){ 
  console.log("end")
  if( !txt_area.classList.contains("area_active") ){
    txt_area.classList.remove("area_hover")
  }
}

txt_area.ondragover = function (e) { 
  e.preventDefault() 
}

txt_area.ondrop = function(e){ 

  e.preventDefault();
  console.log("drop")

  txt_area.classList.remove("area_hover")
  txt_area.classList.add("area_active")

  get('.input_file_txt').files = e.dataTransfer.files
  const dT = new DataTransfer()
  dT.items.add(e.dataTransfer.files[0])
  get('.input_file_txt').files = dT.files


  // Correct type
  var type = get(".input_file_txt").files[0].type
  var correct_type = "text/plain" 

  if(type != correct_type){
    txt_remove()
    alert("Correct type is TXT")
    return 0
  }


  // Max size
  var size = get('.input_file_txt').files[0].size
  var max_size = 3525120 

  if(size > max_size){
    txt_remove()
    alert("Max size is 3525120 kb")
    return 0
  } 

  txt_active_fn()
}




// exe_area

exe_area.onclick = function(){ 
  if( !exe_area.classList.contains("area_active") ){
    get('.input_file_exe').click()
  }else{
    exe_remove()
  }
}

exe_area.ondragenter = function(){ 
  console.log("start")  
  if( !exe_area.classList.contains("area_active") ){
    exe_area.classList.add("area_hover")
  } 
}

exe_area.ondragleave = function(){ 
  console.log("end")
  if( !exe_area.classList.contains("area_active") ){
    exe_area.classList.remove("area_hover")
  }
}

exe_area.ondragover = function (e) { 
  e.preventDefault() 
}


exe_area.ondrop = function(e){ 

  e.preventDefault();
  console.log("drop")

  exe_area.classList.remove("area_hover")
  exe_area.classList.add("area_active")

  get('.input_file_exe').files = e.dataTransfer.files
  const dT = new DataTransfer()
  dT.items.add(e.dataTransfer.files[0])
  get('.input_file_exe').files = dT.files 

  // Correct type
  var type = get(".input_file_exe").files[0].type
  var correct_type = "application/x-msdownload" 

  if(type != correct_type){
    get('.input_file_exe').files.clear()
    exe_area.classList.remove("area_active")
    alert("Correct type is EXE")
    return 0
  }


  // Max size
  var size = get('.input_file_exe').files[0].size
  var max_size = 3525120 

  if(size > max_size){
    get('.input_file_exe').files.clear()
    exe_area.classList.remove("area_active")
    alert("Max size is 3525120 kb")
    return 0
  }

  exe_active_fn()
}


// compile
var btn_compile = get(".btn_compile")

var update_compile_button = () => {

  if(txt_active && exe_active){
    btn_compile.classList.remove("hide")
  }else{
    btn_compile.classList.add("hide")
  }    
}

btn_compile.onclick = () => {

  LOADER.show()
  post_exe() 
}


// post
const txt = get("#txt");
const exe = get("#exe");

var post_txt = async() => {

  const formData = new FormData(txt);

  try {
    const response = await fetch('/uploads', {
      method: 'POST',
      body: formData
    });

    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.error(error);
  }
}

var txt_change = () => {

  log("txt_change")

  if( get(".input_file_txt").files[0].type == "text/plain" ){

    txt_active_fn()

  }else{
    txt_remove()
  }
} 

var link = ""

var post_exe = async() => {

  const formData = new FormData(exe);

  try {
    const response = await fetch('/uploads', {
      method: 'POST',
      body: formData
    });

    const data = await response.json();
    link = data.download_link

    console.log(data);    

    txt_remove()
    exe_remove()

    LOADER.hide()

    get(".txt_area").classList.add("hide")
    get(".exe_area").classList.add("hide")

    get(".area_download").classList.remove("hide")          

  } catch (error) {
    console.error(error);
  }
}

var exe_change = () => {

  log("exe_change")

  if( get(".input_file_exe").files[0].type == "application/x-msdownload" ){

    exe_active_fn()

  }else{
    exe_remove()
  }
}


function saveFile(blob, filename) {
  if (window.navigator.msSaveOrOpenBlob) {
    window.navigator.msSaveOrOpenBlob(blob, filename);
  } else {
    const a = document.createElement('a');
    document.body.appendChild(a);
    const url = window.URL.createObjectURL(blob);
    a.href = url;
    a.download = filename;
    a.click();
    setTimeout(() => {
      window.URL.revokeObjectURL(url);
      document.body.removeChild(a);
    }, 0)
  }
}

get(".area_download").onclick = async() => {

  log("download")

  try {

    var result = await fetch(link).then(async res => ({
      filename: res.headers.get('content-disposition').split('filename=')[1].split(';')[0].slice(1, -1),
      blob: await res.blob()
    }))

    saveFile(result.blob, result.filename)

    location.reload()

  } catch (error) {
    console.error(error);
  }
}

Enter fullscreen mode Exit fullscreen mode

Demo

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

Top comments (0)

Image of Docusign

🛠️ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more