JSFiddle - React, Tailwind, and code Playground

by Kanatantsin

HTML

<div class="text-editor" id="editor">
  <div class="text-editor__title">
    Имя файла: <span class="text-editor__filename">(документ)</span>
  </div>
  <textarea class="text-editor__content"></textarea>
  <div class="text-editor__hint">
    <div class="text-editor__hint-content">
      Перенесите и отпустите .txt файл для загрузки содержимого в редактор
    </div>
  </div>
</div>

CSS

body, html {
  height: 100%;
}
body {
  margin: 0;
  font-family: Verdana;
}
.text-editor {
  display: flex;
  flex-direction: column;
  height: 100%;
  padding: 20px;
  box-sizing: border-box;
  position: relative;
}
.text-editor__title {
  margin-bottom: 10px;
}
.text-editor__hint {
  display: none;
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
  background: rgba( 255, 255, 255, 0.9 );
  justify-content: center;
  align-items: stretch;
  font-size: 30px;
  padding: 20px;
  box-sizing: border-box;
}
.text-editor__hint-content {
  flex-grow: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 4px dashed gray;
  color: gray;
}
.text-editor__hint_visible {
  display: flex;
}
.text-editor__content {
  flex-grow: 1;
  border: 1px solid #CCC;
}

JavaScript

const throttle = ( handler, ms ) => {
	let timeout;
  return () => {
  	clearTimeout( timeout );
    timeout = setTimeout( handler, ms );
  }
};
class TextEditor {
	constructor( container, storageKey = '_text-editor__content' ) {
  	this.container = container;
    this.contentContainer = container.querySelector( '.text-editor__content' );
    this.hintContainer = container.querySelector( '.text-editor__hint' );
    this.filenameContainer = container.querySelector( '.text-editor__filename' );
    this.storageKey = storageKey;
    this.registerEvents();
    this.load( this.getStorageData());
  }
  registerEvents() {
  	const save = throttle( this.save.bind( this ), 1000 );
  	this.contentContainer.addEventListener( 'input', save );
    this.container.addEventListener('dragover', (event) => this.showHint.call(this, event));
    this.container.addEventListener('drop', (event) => this.loadFile.call(this, event));
  }
  
  loadFile(e) { 
    e.preventDefault();
    this.hideHint();
    this.readFile(e.dataTransfer.files[0]);
  }
  
  readFile(file) { 
    console.log(file);
    
    if (file.type == 'text/plain') {
      const reader = new FileReader();

      this.contentContainer.value = '';
      this.setFilename(file.name);

      reader.addEventListener('load', event => {
        this.contentContainer.value = event.currentTarget.result;
      });

      reader.readAsText(file);        
    } else {
      this.contentContainer.value = 'Сюда можно перетаскивать только файлы в формате .txt';
    }
  }
  
  setFilename(filename) { 
  	this.filenameContainer.textContent = filename;
  }
  
  showHint(e) { 
    e.preventDefault();
    console.log(e);
    console.log(document.elementFromPoint(event.clientX, event.clientY));
    this.hintContainer.classList.add('text-editor__hint_visible');
  }
  
  hideHint() { 
    this.hintContainer.classList.remove('text-editor__hint_visible');    
  }
  
  load(value) {
  	this.contentContainer.value = value || '';
  }
 ...