JSFiddle - React, Tailwind, and code Playground

by Ivan Pshenitsyn

HTML

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<div class="photo-box">
  <form id="imageForm" class="image-form" action="/image/upload" method="post" enctype="multipart/form-data">
    <input type="file" name="upload_image">
    <input type="submit" style="display:none">
    <div class="mask">
      <div class="mask-inner">
      
      </div>
    </div>
  </form>
  <input type="hidden" name="image" value="" />
</div>

CSS

.image-form{
    position: relative;
    overflow: hidden;
    width: 100px;
    height: 100px;    
}
.image-form input[type=file]{
  opacity: 0;
  cursor: pointer;
  width: 100%;
  height: 100%;
  position: absolute;
  left: 0;
  top: 0;
  z-index: 2;
  padding: 0;
}
.image-form .uploaded_image{
  position: absolute;
  left: 0;
  top: 0;
  background-color: white;
  z-index: 1;
}
.image-form:hover .mask{
  background-color: #F5FFF8;
  
}
.image-form:hover .mask .mask-inner{
  border: 3px dotted #5eb666;  
}
.image-form.error .mask{
  background-color: #FFF5F6;  
}
.image-form.error .mask .mask-inner{
  border: 3px dotted #FF7177;
}
.image-form .mask {
  background-color: #F5F8FF;
  position: absolute;
  left: 0;
  top: 0;
  z-index: 1;
  width: 100%;
  height: 100%;
  box-shadow: 0 0 7px #ccc inset;  
}
.image-form .mask .mask-inner {
  width: 84%;
  height: 88%;
  position: absolute;
  top: 6%;
  margin-left: -3px;
  border-radius: 10px;
  left: 8%;
  border: 3px dotted #71B5FF;
  margin-top: -3px;
}
.image-form.dragenter{
  background-color: #f9fff9;
  border-color: #008700;
}
.image-form.dragenter .mask{
    background-color: #F5FFF8;
}
.image-form.dragenter .mask .mask-inner{
  border-color: #5eb666;
  color: #5eb666;
}

JavaScript

$.fn.myLoadImage = function(options){
    if(!options) options = {};
    var default_options = {
        width: false, //ширина превьюшки по-умолчанию, которая будет добавлена в форму. может быть переопределена в ответе сервера
        height: false, //высота превьюшки по-умолчанию, которая будет добавлена в форму. может быть переопределена в ответе сервера
        afterLoad: function(form, data){}, //функция, вызываемая после загрузки 
        setImage: function(data){
          var file = data.thumbnail || data.filepath;
          
          //в форму добавляем (или изменяем, если он уже добавлен) элемент img.uploaded_image с превьюшкой
          if(form.find('img.uploaded_image').length){
              form.find('img.uploaded_image').attr({
                  src:file,
                  width:data.width||'',
                  height:data.height||''
              });
          } else {
              var image = $('<img class="uploaded_image" src="'+file+'" alt="upload image" width="'+(data.width||params.width||'')+'" height="'+(data.height||params.height||'')+'">');
              form.append(image);
          }
          
          //после формы в HTML идет скрытый инпут, куда добавляем имя загруженного файла
          form.parent().find('input[type=hidden]').val(data.filename);
          
          //вызываем функцию afterLoad, которую можно определить в параметрах
          if(params.afterLoad) params.afterLoad(form, data);
        }
    };
    var params = $.extend(true, {}, default_options, options),
        form = $(this);

    form.on('change','input[type=file]',function(){
    
        var iframe = $("<iframe id='upload_image_iframe' name='upload_image_iframe' style='display: none;'></iframe>"),
            input = $(this);
            
        iframe.appendTo($("body")).on('load',function () {
            var response = $(this).contents().find("body").text();
            
            try {
                var data = JSON.parse(response);
               ...