<form id="form" action="">
<!-- Область с превью файлов -->
<div id="files_prev" class="block_input">
<ol class="_items"></ol>
</div>
<!-- Добавление новых файлов -->
<div class="block_input">
<label for="file_add">Добавить файлы</label>
<input id="file_add" type="file" multiple>
</div>
<!-- Дополнительное поле -->
<div class="block_input">
<label>
Номер телефона
<input type="text" name="phone" plaseholder="+7 999 999 99 99">
</label>
</div>
<!-- Сохранение и отправка -->
<div class="block_input">
<input id="file_save" type="submit" value="Отправить">
</div>
</form>
body
background: black
color: transparent
text-shadow: 0 0 2px green
#form
display: block
padding: 0 10px
border-radius: 5px
input,
label[for="file_add"]
display: inline-block
font-size: 16px
line-height: 18px
background: none
outline: none
border: none
color: transparent
padding: 5px 10px
box-shadow: 0 0 2px 0 green
border-radius: 5px
text-shadow: 0 0 2px green
cursor: pointer
.block_input
margin-bottom: 5px
#files
visibility: hidden
#file_add
visibility: hidden
#files_prev
padding: 0
margin-bottom: 15px
max-width: 100%
overflow: hidden
box-shadow: 0 0 1px 0 green
& > ._items
display: flex
align-items: flex-end
flex-wrap: wrap
padding: 10px
max-width: 100%
& > ._item
position: relative
padding: 5px
margin: 0 0 5px 25px
img
height: 100px
._remove
position: absolute
top: -10px
right: -10px
width: 10px
height: 10px
font-size: 20px
cursor: pointer
label
height: 10px
font-size: 14px
line-height: 10px
display: block
View Compiled
// Необходимые параметры и функции
var form_selector = '#form'
function b64toBlob(dataURI) {
var
byteString = atob( dataURI.split(',')[1] ),
ab = new ArrayBuffer( byteString.length ),
ia = new Uint8Array( ab )
for (var i = 0; i < byteString.length; i++)
ia[i] = byteString.charCodeAt(i)
return new Blob( [ab], { type: 'image/jpeg' } )
}
// Подключаем перетаскивание файлов
$(document)
.find( form_selector )
.find( '#files_prev ._items' )
.sortable()
// При добавлении файлов
$(document)
.find( form_selector )
.find( '#file_add' )
.on( 'change', function( elem ){
var oFiles = elem.target.files // Файлы
// + Перебираем выбранные файлы
$.each(
oFiles,
function( index, elem ){
// + Получаем изображение
var readerImg = new FileReader()
readerImg.onloadend = function () {
// + Формируем html
var
resultHtml = '<li class="_item">'
resultHtml += '<img'
resultHtml += ' src="' + readerImg.result + '"'
resultHtml += ' name="' + elem.name + '"'
resultHtml += '/>'
resultHtml += '<span class="_remove">x</span>'
resultHtml += '<label>'
resultHtml += '<input type="radio" name="main_img"/>'
resultHtml += 'Обложка'
resultHtml += '</label>'
resultHtml += '</li>'
// + Добавляем файлы в область файлов
$(document)
.find( form_selector )
.find( '#files_prev ._items' )
.append( resultHtml )
}
// + Загружаем изображение в превью
readerImg.readAsDataURL( elem )
}
)
return false
})
// Сохраниение и отправка
$(document)
.find( form_selector )
.on( 'submit', function(){
// + Если поля заполненны верно
if ( $( document ).find( form_selector )[0].checkValidity() ){
var formData = new FormData() // Все изображения
// + Перебираем загруженные файл
$.each(
$(document).find( '#files_prev ._items ._item img' ),
function( index, elem ){
// + Добавляем все загруженные картинки
formData.append(
'files[]',
b64toBlob( $(this).attr('src') ),
$(this).attr('name')
)
}
)
// + Перебираем остальные поля
var arrValues = $( document ).find( form_selector ).serializeArray()
$.each(
arrValues,
function( index, value ){
formData.append(
value['name'],
value['value']
)
}
)
// + Вывод результата
for( var pair of formData.entries() ) {
console.log(pair[0]+ ', '+ pair[1])
}
}
return false
})
// Удаление
$(document)
.on(
'click',
form_selector + ' #files_prev ._items ._item ._remove',
function(){
$(this).parents('._item').remove()
}
)
// Обложка
$(document)
.on(
'click',
form_selector + ' #files_prev ._items ._item [name="main_img"]',
function(){
$(this).parents('._item').prependTo( form_selector + ' #files_prev ._items' )
}
)
This Pen doesn't use any external CSS resources.