JS implementation of form multiple file upload style beautification support to delete related items after selecting files _javascript tips

Source: Internet
Author: User
Tags prev

Development will often involve file upload requirements, according to different business needs, there are different file upload situation.

Have simple single file upload, there are multiple file upload, because the browser native file upload style and function of the support is not too high, many times we will beautify the style, to improve the function.

This article based on an example, the upload style of multiple files to do some simple landscaping (in fact, not how to beautify.) , while supporting the selection of files after the custom delete related files, and finally upload

The article is longer, the first simple look at the diagram:

First, file upload base

1. Single File Upload

The simplest file upload, is a single file upload, form tag to add enctype= "multipart/form-data", form form has a input[type= "file" item

<form name= "Form1" method= "Post" action= "/abc.php" enctype= "Multipart/form-data" >
<input type= "text" Name= "User" id= "user" placeholder= "Please enter nickname" >
<input type= "file" Name= "Userimage" id= "Userimage" >
<input type= "Submit" Name= "sub" value= "submitted" >
</form>

2. Multi-File Upload

1 similar to single file upload, simple multiple file upload is actually more than a few input[type= "file" item

<form name= "Form1" method= "Post" action= "/abc.php" enctype= "Multipart/form-data" >
<input type= "text" Name= "User" id= "user" placeholder= "Please enter nickname" >
<input type= "file" Name= "UserImage1" id= "UserImage1" >
<input type= "File" Name= "UserImage2" id= "UserImage2" >
<input type= "file" Name= "UserImage3" id= " UserImage3 ">
<input type=" Submit "Name=" sub "value=" Submit ">
</form>

2) HTML5 a new multiple property for the form file entry, you can set the implementation to select multiple files, such as

<form name= "Form1" method= "Post" action= "/abc.php" enctype= "Multipart/form-data" >
<input type= "text" name= "user" id= "user" placeholder= "Please enter nickname" >
<input type= "File" Name= "Userimage" id= "Userimage" multiple>
<input type= "Submit" Name= "sub" value= "submitted" >
</form>

Second, the form file upload beautification

Look at the above several pictures, you can know that the original file selection style is the most basic, mainly reflected in three points:

No border, not in sync with other elements with borders
Select a File button style too basic
Select more than one file to display only the total number, no detailed selection of file name
Based on several problems, it can be beautified on demand

1th style that you can add a border directly

2nd need to add other elements, you can add a button (on-demand landscaping), the original file box to hide, with JS event binding, click the button after the Simulation file box click

<input type= "File" Name= "Userimage" id= "Userimage" style= "Display:none"; >
<input type= "button" id= "value=" Select File "onclick=" document.getElementById (' Userimage '). Click () ">

3rd and 2nd similar, also have to add new elements, select files, through JS get selected file information, and in the new elements show

Think very simple, but the problem is that, if the number of selected files, the new elements of the number of space is a problem, you can display a few files by default, and then "see more Files" to see more information

The other idea is that there are a lot of files that are selected at once, and you have to choose again when you want to cancel a file. This is too cumbersome, so you need to provide immediate removal of a selected file operation

Third, delete after the selected file

To provide an action that can be deleted after the file is selected, it is necessary to provide the relevant portal and scripting operations, and then do some parsing around this

1. Interface processing

After selecting the file, we can delete the selected file by removing the button, because there will be multiple files, so we need an information template

<!--the currently selected file list file information template-->
<script type= "text/template" id= "File-temp-item-tpl" >
<span class= " File-temp-item "style=" {{style}} ">
<span class=" File-temp-name ">{{name}}</span>
<span class= "file-temp-btn" >x</span>
</span>
</script>

Select more than one file, you have to add a drop-down box to assist, display up to 5 file information, and then through the Drop-down button to expand the Drop-down box (button style set itself)

Here 5 files between the location of the calculation is not very in place, mainly this code, you can set

Calculate each coordinate left, width left
= i = = 0 2:2 + i * (100/filetemplen);
width = 100/filetemplen-2;

Each item in the Drop-down list is also a template

<!--view more file information template-->
<script type= "text/template" id= "File-more-item-tpl" >
<li>
<span class= "File-item-more-name" >{{name}}</span>
<span class= "File-item-more-btn" >x</ span>
</li>
</script>

The following is the initial HTML structure

<form name= "form" id= "form" method= "POST" action= "filetest.php" enctype= "Multipart/form-data" >
<!-- <input type= "number" name= "Numbertest" value= "M" >--> <input type=
"file" name= "filetest[" "id=" Filetest "multiple>
<!--list of currently selected files (up to 5)-->
<span class=" file-temp ">
</span>
<!--See more files-->
<ul class= "Item-more" >
</ul>
<input type= "button" class= "btn Btn-success "id=" uploadbtn "value=" Upload ">
<p class=" upload-tip "> File Upload success </p>
</form>

The following are all CSS styles

<link rel= "stylesheet" type= "Text/css" href= "Bootstrap.min.css" > <style type= "text/css" > HTML {F
    ont-family:arial;
      form {margin:50px auto;
    width:400px;
      } input {width:300px;
    padding:4px;
      } #uploadBtn {margin-top: -3px;
      margin-left:5px;
      width:60px;
      height:30px;
      Font-weight:bold;
    font-size:12px;
      } #fileTest {display:inline-block;
      border:1px solid #ccc;
    border-radius:3px;
      }. file-temp {position:relative;
      Display:none;
      width:300px;
    height:31px;
      }. file-temp-item {position:absolute;
      top:4px;
    height:24px;
      }. item-more-btn {display:inline-block;
      Position:absolute;
      top:18px;
      right:0.5%;
      width:10px;
      height:10px;
      Color: #777;
    Cursor:pointer;
    }. item-more-btn:hover {border-top-color: #aaa; }. File-temp-name {display:inline-block;
      Overflow:hidden;
      width:90%;
      height:26px;
      padding:2px 15px 2px 5px;
      border-radius:2px;
      Background-color: #eaeaf3;
      Text-overflow:ellipsis;
    White-space:nowrap;
      }. file-temp-btn {position:absolute;
      Display:inline-block;
      top:4px;
      right:11%;
      width:18px;
      height:18px;
      line-height:18px;
      Text-align:center;
      border:1px solid #ddd;
      Background-color: #ccc;
      border-radius:50%;
      Color: #fff;
      font-size:18px;
    Cursor:pointer;
      }. item-more {position:absolute;
      Overflow-y: auto;
      Display:none;
      padding-left:0;
      width:300px;
      max-height:150px;
    List-style:none;
      }. item-more Li {position:relative;
      padding:5px;
      border:1px solid #ccc;
    Border-top:none;
    }. Item-more Li:hover {background-color: #f5f5f9;
   } . file-item-more-name {display:inline-block;
      width:90%;
      Overflow:hidden;
      Text-overflow:ellipsis;
    White-space:nowrap;
      }. file-item-more-btn {position:absolute;
      Display:inline-block;
      top:8px;
      right:2%;
      width:18px;
      height:18px;
      line-height:18px;
      Text-align:center;
      border:1px solid #ddd;
      Background-color: #ddd;
      border-radius:50%;
      Color: #fff;
      font-size:18px;
    Cursor:pointer;
    }. file-item-more-btn:hover {background-color: #ccc;
      }. upload-tip {display:none;
      margin:50px Auto;
      Text-align:center;
    font-size:12px; } </style>

2. Script Processing

Below, focus on the processing of JS script

To get the information of the selected file, it is natural to think of the value attribute, but the value of the file item can only be obtained to a file path (the first), whether or not multiple

No multiple

<input type= "File" onchange= "Console.log (this.value);" >

Have multiple

<input type= "file" multiple onchange= "Console.log (this.value);" >

Since you cannot get all of the selected file information directly through value, you can only find other ways.

1) filelist

To get the selected file information, you can also use the FileList object, which is added in HTML5, and each form file item has a files attribute that stores some information about the selected file

<input type= "file" multiple onchange= "Console.log (this.files);" >

View file information After two files are selected

The FileList object looks like an array of classes with a length attribute. Therefore, we should be able to modify or delete the relevant items from the definition of our selected files (note that this is actually not modified, and continue to look at)

If I choose two files, I want to delete the second item and use splice to delete it.

<input type= "file" multiple onchange= "Console.log (Array.prototype.splice.call (This.files, 1, 1));" >

Error, so that FileList length property is read-only, that directly modified to writable configurable it

Object.defineproperty (filelist.prototype, ' length ', {
writable:true,
configurable:true
});

After the configuration length can be modified, at first glance thought splice effective, however, the output of a look, FileList object content unchanged, still two

After consulting some information, understand that the browser for security considerations, the content of the FileList object is set to not be changed, can only manually empty, but not modify the content

So, the solution is to add an array that initially duplicates the contents of the FileList object's file, and then the modification is done through this modifiable array

Store update selected file
var curfiles = []; 
...
Select File
var files = this.files;
if (Files && files.length) {
//original FileList object cannot be changed, it is given to Curfiles to provide the next modification
Array.prototype.push.apply (curfiles, files);

If you click the Remove fork, you can update the file information array directly

var name = $ (this). Prev (). text ();
Remove the file
curfiles = curfiles.filter (function (file) {return
file.name!== name;
});

As a result, the problem of updating the file information is resolved, and then the file is uploaded.

Click on file upload if direct call to $form.submit (); Then uploaded file information is still the original FileList object, not up to our custom requirements, so we need to submit with Ajax

So how do you want to provide a file object in the background?

2) FormData

HTML5 introduces the new object of the form formdata, it can generate a Form object, we can get/set the key value pairs of information, and then submitted to the background

Referencing MDN's Formdata use method, we can add various types of data, using AJAX to submit

var omyform = new FormData ();
Omyform.append ("username", "Groucho");
Omyform.append ("AccountNum", 123456); The number 123456 is immediately converted to a string "123456"
//Fileinputelement already contains the files selected by the user
omyform.append ("UserFile", Fileinputelement.files[0]);
var ofilebody = ' <a id= ' a ' ><b id= ' b ' >hey!</b></a> '; Blob object contains file contents
var oblob = new Blob ([Ofilebody], {type: "Text/xml"});
Omyform.append ("Webmasterfile", Oblob);
var oreq = new XMLHttpRequest ();
Oreq.open ("POST", "http://foo.com/submitform.php");
Oreq.send (Omyform);

You can also use JQ's encapsulated Ajax, but be aware that setting the ProcessData and ContentType properties to false prevents JQ from randomly parsing file formats

var fd = new FormData (document.getElementById ("FileInfo")); Use a form as the initial item
fd.append ("CustomField", "This is some extra data");
$.ajax ({
URL: "stash.php",
Type: "POST",
data:fd,
processdata:false,//tell jquery not to handle the sent data
contenttype:false//Tell jquery not to set Content-type request headers
});

Here are a few points to note:

1 the attribute value in Formdata accepts a single file information and cannot be a composite object. May be unclear, and see

var fd = new FormData ($ (' #form ') [0]);
Fd.append (' Myfiletest ', curfiles);
$files = $_request[' myfiletest '];
Var_dump ($files);

With PHP to receive the data passed, the data is directly converted to a string, not file objects

Curfiles is a file object, that PHP end should use $_files to receive information, try to replace $files = $_files[' myfiletest '];

There is a direct problem, the description can not be handled, you need to curfiles content of a piece of the piece, that is, a single file information

var fd = new FormData ($ (' #form ') [0]);
for (var i = 0, j = curfiles.length I < J; ++i) {
fd.append (' myfiletest[] ', curfiles[i]);
$files = $_files[' myfiletest '];
Var_dump ($files);

The file is received successfully, then the file can be manipulated as needed

2 when the backend obtains the file information, is obtains directly through the original $_files, other general information only uses the $_request to obtain

Change to $files = $_request[' myfiletest ']; try, direct is the problem that can't find myfiletest

Try adding a generic file before submitting

var fd = new FormData ($ (' #form ') [0]);
for (var i = 0, j = curfiles.length I < J; ++i) {
fd.append (' myfiletest[] ', curfiles[i]);
Fd.append (' MyTest ', [1, 2, 3]);
$files = $_files[' myfiletest '];
$test = $_request[' myTest '];
Var_dump ($test);
Var_dump ($files);

3 If you need to multiple multiple file upload, you need to add the [] number after the file entry file, indicating that this is a multiple-file array for backend processing parsing

Fd.append (' myfiletest[] ', curfiles[i]);

If there is no later [], then the continuous append will directly overwrite the original, the last backend to get only the last append entry

4 do not directly in JQ Ajax to instantiate a Formdata object, there will be problems

The Formdata object is generated directly in the data property and is ignored by the JQ, so there is no information at the back end.

Mixed table Single Simple example:

In the form processing, many times we will upload files and other basic items to submit, simply add an input project to see if the process of success

<input type= "number" name= "Numbertest" value= ">"

<?php
$files = $_files[' myfiletest '];
$test = $_request[' numbertest '];
echo json_encode (
' len ' => count ($files [' name ']),
' num ' => $test
));
? >

The following are all JS scripts:

<script type= "Text/javascript" >/** * Add the corresponding file entry to the file list element * @param {array} files The current file list array object/function AddItem (Files {var filetempitemtpl = $ (' #file-temp-item-tpl '). html (), FILEMOREITEMTPL = $ (' #file-more-item-tpl '). HTML () htmltemp = [ ], htmlmoretemp = [], the coordinates of each file in the file list and the space left = 2, width = 100,//MAX. 5 Filetemplen = files.length > 5?
5:files.length; for (var i = 0, j = files.length I < J; ++i) {//When I > 4, that is, the 6th file start if (i > 4) {htmlmoretemp.push (filemoreitemtpl
. replace (' {{name}} ', Files[i].name));
Continue //calculate each coordinate left, width left = i = = 0?
2:2 + i * (100/filetemplen);
width = 100/filetemplen-2; Htmltemp.push (filetempitemtpl. Replace (' {{style}} ', ' Left: ' + Left + '%;width: ' + width + '%; '). Replace (' {{name}} '), fil
Es[i].name)); //Render related element contents $ ('. File-temp '). html (' + ' <input type= ' text ' style= ' background-color: #fff; "class=" Form-control "id=" Filetemp "Readonly> ' + htmltemp.join (") + (Files.length > 5?) ' <span class= ' Item-moRe-btn "title=" View More ">=</span>");
$ ('. Item-more '). HTML (Htmlmoretemp.join ('));
//Save the currently selected (updated) file list var curfiles = []; The $ (' #fileTest ') is triggered when the file is initially selected. Change (the function () {var $this = $ (this), $temp = $ ('. File-temp '), files = this.files; if (file
S && files.length) {//original FileList object cannot be changed, so give it to Curfiles to provide the next modification Array.prototype.push.apply (curfiles, files);
AddItem (Curfiles);
$this. Hide ();
$temp. CSS (' Display ', ' inline-block ');
}
}); $ (document)//deselect a file, delete the value in the file list array object, and update the list. On (' click ', '. file-temp-btn,. File-item-more-btn ', function () {$ ('.
Upload-tip '). Hide ();
var name = $ (this). Prev (). text ();
Remove the file Curfiles = curfiles.filter (function (file) {return file.name!== name;}); The file list array object is longer than 5 to display the "More file list" Drop-down if (curfiles.length <= 5) {$ ('. Item-more '). Hide ();}//File list array emptied then reset file select Table Single if (!curfil
Es.length) {$ (' #fileTest '). Val ('). Show (); $ ('. File-temp '). CSS (' Display ', ' none ');} else {addItem (curfiles);} Console.log (Curfiles)})//Show the "More File List" dropdown. On (' click ', '.Item-more-btn ', function () {$ ('. Upload-tip '). Hide (); $ ('. Item-more '). Show (' normal '); 
Upload Operation $ (' #uploadBtn '). Click (function () {$ ('. Upload-tip '). Hide ();//Build FormData object var fd = new FormData ($ (' #form ') [0]); for (var i = 0, j = curfiles.length I < J ++i) {fd.append (' myfiletest[] ', curfiles[i]); $.ajax ({url: ' FILETEST.P HP ', type: ' Post ', DATA:FD, Processdata:false, Contenttype:false, Success:function (rs) {rs = Json.parse (RS); $ ('. Uplo
Ad-tip '). addclass (' text-success '). Removeclass (' Text-error '). Text (rs.len + ' file upload succeeded, number value is ' + Rs.num '). Show ();
}, Error:function (Err) {}});
}); </script>

The above is a small set of JS to introduce the implementation of the form of multiple file upload style beautification support selected files Delete related items, I hope to help you, if you have any questions please give me a message, small series will promptly reply to everyone. Here also thank you very much for the cloud Habitat Community website support!

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.