I dare to suggest that my drag & drop handler of fields for loading images be introduced to familiarization (and use, if appropriate). I have been using it for several years in various projects. During this time, the code became very complicated and acquired various features. Here I will present an “outdated” version for me, but a simpler version that is free from unnecessary functionality. If desired, it can be finished and up to a beautiful multi-download of files and before filtering the selection of files by mime-type and in general to everything that the soul wishes.
Yes, I know that there is a mass of plug-ins of a similar subject. And I used a few pieces of them. But such a situation comes very quickly that you need non-standard behavior from the download form and you have to search for crutches for hours to attach new functionality. Even customization of styles can be a problem, not to mention outputting already loaded files in a form when loading a page (for example, editing existing material with pictures).
The main advantages of the proposed method:
- showing a preview of the image (or the full image) immediately after selecting the file, before submitting the form. Including, you can add postprocessing of images, delete added files, etc.
- The ability to process and validate the file already at the stage of filling out the form. The file is sent to the server immediately after the selection, which allows you to check its type, size, width and height (for images), etc.
However, the proposed principle of loading, I believe, is not suitable for everyone , because:
after dragging the file into the field (or selecting through the standard window), the file is immediately sent to the server, where it is supposed to be processed and saved. That is, not with the form submission, as usual, but immediately, after selecting the file.
The drop zone is a form
element, which imposes some restrictions. For example, you cannot place this form inside another form. You have to either take out this dropzone form beyond the limits of the main one, or convert the main form to a div and collect data from all fields and send the main form manually (I do, most often, just like that. I like to do everything on my own)).
Now more about the work :
- The drop zone, as already mentioned, is a form element with a single input [type = file]. Styles disguise this input and we see a friendly box in which you can add the words "drag here or click ...".
- File selection is performed by dragging on the field or by clicking on it and using the standard file selection window.
- after selecting a file, it is immediately sent to the server at the address specified in the action attribute of the form.
- The server response expects information about the uploaded file and (optionally) its thumbnail to display in the form. The file name is stored in a hidden field next to the form (if you wish, you can, of course, write it on any input or whatever you like).
- after the server responds, either an error message is issued, or (if the response is successful), a thumbnail image is added to the form and the file name is added to the hidden input next to the form.
What you need to finish in the presented code to run at:
1 . in the action attribute of the form specified address where the file will be sent. From there, the correct response is expected in json format.
This either
{"error":"описание ошибки"}
in case of a problem with the file, either
{ "id": "id или имя файла. будет добавлен в основную форму в поле name=uploaded_image", //обязательно "thumbnail": "адрес превьюшки", //необязательно "filepath": "адрес основного файла", //обязательно, если не указан thumbnail "width": "ширина выводимого превью", //необязательно, можно указать в стилях или определить в параметрах myLoadImage, но пригодится в случае динамического размера изображений "height": "высота выводимого превью", //необязательно, можно указать в стилях или определить в параметрах myLoadImage, но пригодится в случае динамического размера изображений }
2 In the HTML fragment of the presented fragment there is a field input[name=uploaded_image]
. It must be placed inside the main form, so that when sending the main form to the server, the file id or name or what you will identify the file with will leave. When sending the main form to the server, it is assumed that the file has long been processed and saved (this happened at the address specified in the action), and together with the form you get a link to it to bind the finished file to the material.
2.5 . Probably correct styles at will. Especially the thumbnail, I did not check how it looks now. There is no server handler at hand.
If necessary, you can finish loading several files (I have already done this repeatedly with the presented code), filter for selecting files by file type, deleting downloaded files, showing previously downloaded files (in editing forms) with the possibility of deleting them, and much more.
Example
Unfortunately, I cannot organize a full-fledged demonstration . No server support. Therefore, the message " Image not uploaded " - all that you can count on.
Local snippets work out not quite correctly, there is no alert and event'a dragenter, so the best thing to do is look at jsfiddle :
https://jsfiddle.net/ipshenicyn/vyhhxvxu/3/
$.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, thumbWidth = data.width||params.width||'', thumbHeight = data.height||params.height||''. //в форму добавляем (или изменяем, если он уже добавлен) элемент img.uploaded_image с превьюшкой if(form.find('img.uploaded_image').length){ form.find('img.uploaded_image').attr({ src:file, width:thumbWidth, height:thumbHeight }); } else { var image = $('<img class="uploaded_image" src="'+file+'" alt="upload image" width="'+thumbWidth+'" height="'+thumbHeight+'">'); form.append(image); } //после формы в HTML идет скрытый инпут, куда добавляем имя загруженного файла $('input[name="uploaded_image"]').val(data.id); //вызываем функцию 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); if (data.error) { alert(data.error.replace("\\r\\n","\r\n","g")); } else { params.setImage(data); } } catch(e) { alert('Изображение не загружено'); } setTimeout(function(){ iframe.remove(); },1000); input.val(null); return false; }); form.attr('target', 'upload_image_iframe').submit(); }).on('dragenter', function(){ $(this).addClass('dragenter'); }).on('dragleave', function(){ $(this).removeClass('dragenter'); }); }; $('#imageForm').myLoadImage();
.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; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/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="uploaded_image" value="" /> </div>