Slider FileReader JS Multiple Image Upload (Incrementing Index)
I am trying to make a JavaScript multiple image uploader that uploads image previews to a slider, but I am having some issues. So far it looks like I was able to get the images to upload into the slider, but the problem seems to happen with my i
variable - when I try to increment it, it stays the same, not allowing my next
and previous
slider arrows from working. If anyone knows how to get this slider working properly, I would appreciate the help.
JS Code:
$('#_uploadImages').click(function() {
$('#_imagesInput').click()
})
$('#_imagesInput').on('change', function() {
handleFileSelect();
});
function handleFileSelect() {
//Check File API support
if (window.File && window.FileList && window.FileReader) {
var files = event.target.files; //FileList object
var output = document.getElementById("frames");
for (var i = 0; i < files.length; i++) {
var file = files[i];
//Only pics
if (!file.type.match('image')) continue;
var picReader = new FileReader();
picReader.addEventListener("load", function (event) {
var picFile = event.target;
console.log(event);
current_i = i;
prev_i = current_i - 1;
next_i = current_i + 1;
//var div = document.createElement("div");
//div.innerHTML = div.innerHTML + "<img class='thumbnail' src='" + picFile.result + "'" + "title='" + picFile.name + "'/>";
//output.insertBefore(div, null);
////output.innerHTML = output.innerHTML + "<img class='thumbnail' style='max-width:500px' src='" + picFile.result + "'" + "title=''/>"; // TODO: Enter Title
output.innerHTML = output.innerHTML + '<li id="slide-' + current_i + '" class="slide">' + "<img src='" + picFile.result + "'" + "title=''/>" + '<nav>' + '<a class="prev" href="#slide-' + prev_i + '">←</a>' + '<a class="next" href="#slide-' + next_i + '">→</a>' + '</nav>' + '<li>'; // TODO: Enter Title
});
//Read the image
picReader.readAsDataURL(file);
}
//output.innerHTML = output.innerHTML + '<li class="quicknav">' + '<ul>' + '<li><a href="#slide-1"></a></li>' + '<li><a href="#slide-2"></a></li>' + '<li><a href="#slide-3"></a></li>' + '</ul>' + '</li>'
} else {
console.log("Your browser does not support File API");
}
}
JSFiddle: http://jsfiddle.net/Hybridx24/yfr57u6w/
The problem with the code is that by the time the load event executes - the for loop has already incremented. So if two images are added - the value of i
when the load event is executing is already 2.
One way to solve this is to add the value of i
to an array and retrieve it in the event listener one by one:
var arrFilesCount = [];
for (var i = 0; i < files.length; i++) {
arrFilesCount.push(i); //push to array
var file = files[i];
//Only pics
if (!file.type.match('image')) continue;
var picReader = new FileReader();
picReader.addEventListener("load", function (event) {
var picFile = event.target;
current_i = arrFilesCount.shift(); // get from array instead of using i
prev_i = current_i - 1;
next_i = current_i + 1;
...
...
Corresponding jsFiddle here
Now, this array can also be used for determining the first/last element and thereby using this to go from last to first element. Because we cannot be sure when the event listener will execute (say if there are 100 images the first event listener may execute when the count of loop has reached 5 or 10), so I've used two loops instead of one. The first loop just to populate the array.
var arrFilesCount = [];
for (var i = 0; i < files.length; i++) {
arrFilesCount.push(i);
}
Lets use this to find the first and last elements
current_i = arrFilesCount.shift();
if(current_i === 0){
prev_i = files.length - 1; //This is for the first element. The previous slide will be the last image. (i=length-1)
}
else{
prev_i = current_i - 1;
}
if(arrFilesCount.length === 0){
next_i = 0; //This is for the last element. The next slide will be the first image (i=0)
}
else{
next_i = current_i + 1;
}
See this jsFiddle.
Finally, there can be scenarios where the user first adds a couple of images then clicks on upload button again and adds a couple of more images. In this case we need to correct the existing href. The elements which we need to correct are the next
of last and prev
of first. This can be done using:
var start = $(output).find('li').length;
var end = start+ files.length;
if(start !== 0){
$(output).find('li > nav > a.prev').first().attr('href','#slide-' + (end-1));
$(output).find('li > nav > a.next').last().attr('href','#slide-'+start);
}
So the final jsFiddle will be something like this.
Substituted .append()
for .innerHTML
; created variable idx
to increment .slide li
elements id
s ; added delegated click
event to nav a
elements ; added .bind()
with this
set to picReader
, i
passed as parameter to picReader
onload
event ; added file.name
to title
attribute of img
element ; added "dot" navigation with thumbanail of images beneath #frames
; title
to arrow navigation
var idx = -1, re = /(.*)(?=.)/;
$('#_uploadImages').click(function() {
$('#_imagesInput').click();
});
$('#_imagesInput').on('change', function(event) {
handleFileSelect(event);
});
$(document).on("click", ".slider .slide nav a, .nav a", function(e) {
e.preventDefault();
$(".slide").hide()
.filter(":has(img[title^="+e.target.title.match(re)[0]+"])").show();
});
function handleFileSelect(event) {
//Check File API support
if (window.File && window.FileList && window.FileReader) {
var files = event.target.files; //FileList object
var output = document.getElementById("frames");
for (var i = 0; i < files.length; i++) {
var file = files[i];
var picReader = new FileReader();
picReader.onload = function(index, event) {
++idx;
var picFile = event.target;
var slides = $(".slider li[id^=slide]");
// TODO: Enter Title
$(output)
.append('<li id="slide-'
+ idx
+ '" class="slide">'
+ "<img src='"
+ picFile.result
// set `title`
+ "'title="
//`index` : `i`
+ files[index].name
+ "/>"
+ '<nav>'
+ '<a class="prev">←</a>'
+ '<a class="next">→</a>'
+ '</nav>'
+ '</li>');
// add title to `nav a` elements
if (file.name === files[files.length - 1].name) {
$(".nav").empty();
$("nav a").each(function(i, el) {
if ($(el).closest("[id^=slide]").prev("[id^=slide]").length
&& $(el).is("nav a:nth-of-type(1)")) {
$(el).attr("title",
$(el).closest("[id^=slide]")
.prev("[id^=slide]").find("img").attr("title")
)
}
if ($(el).closest("[id^=slide]").next("[id^=slide]").length
&& $(el).is("nav a:nth-of-type(2)")) {
$(el).attr("title",
$(el).closest("[id^=slide]")
.next("[id^=slide]").find("img").attr("title")
)
}
if ($(el).is(".slider [id^=slide]:first a:first")) {
$(el).attr("title",
$("[id^=slide]:last").find("img").attr("title")
)
}
if ($(el).is(".slider [id^=slide]:last a:last")) {
$(el).attr("title",
$("[id^=slide]:first").find("img").attr("title")
)
};
});
$(".slider img").each(function(i, el) {
$(".nav").append(
$("nav a[title^="
+$(el).attr("title").match(re)[0]
+"]:first")
.clone().html(el.outerHTML)
)
})
}
}.bind(picReader, i);
//Read the image
picReader.readAsDataURL(file);
};
} else {
console.log("Your browser does not support File API");
}
}
* {
margin: 0;
padding: 0;
/*transition*/
-webkit-transition: all 1s ease;
-moz-transition: all 1s ease;
-o-transition: all 1s ease;
transition: all 1s ease;
}
body {
padding: 30px;
}
/* Slider */
.slider {
height: 250px;
left: 50%;
margin: -125px -225px;
position: absolute;
top: 48%;
width: 450px;
/*box-shadow*/
-webkit-box-shadow: 0 0 5px #000;
-moz-box-shadow: 0 0 5px #000;
box-shadow: 0 0 5px #000;
}
.slider .frames {
height: 250px;
position: relative;
list-style-type: none;
}
.slider .frames .slide {
height: 250px;
list-style: none;
position: absolute;
width: 450px;
}
.slider .slide:target {
z-index: 100
}
.slider .frames .slide img {
height: 250px;
width: 450px;
}
.slider .frames .slide nav a {
background: hsla(0, 0%, 0%, .75);
color: #fff;
font-size: 16px;
line-height: 50px;
margin-top: -25px;
opacity: 0;
position: absolute;
text-align: center;
text-decoration: none;
top: 50%;
width: 50px;
visibility: hidden;
z-index: 10;
}
.slider:hover .frames .slide nav a {
opacity: 1;
visibility: visible;
}
.slider .slide nav a:hover {
cursor: pointer;
}
.slider .frames .slide nav .prev {
/*border-radius*/
-webkit-border-radius: 0 25px 25px 0;
-moz-border-radius: 0 25px 25px 0;
border-radius: 0 25px 25px 0;
left: 0;
}
.slider .frames .slide nav .next {
/*border-radius*/
-webkit-border-radius: 25px 0 0 25px;
-moz-border-radius: 25px 0 0 25px;
border-radius: 25px 0 0 25px;
right: 0;
}
.slider .frames .slide nav a:hover {
background: #000
}
.slider .quicknav {
bottom: 0;
font-size: 0;
opacity: 0;
position: absolute;
text-align: center;
width: 100%;
z-index: 100;
}
.slider:hover .quicknav {
opacity: .9
}
.slider .quicknav li {
display: inline-block
}
.slider .quicknav a {
background: hsla(0, 0%, 100%, .9);
border: 1px solid hsla(0, 0%, 0%, .9);
/*border-radius*/
-webkit-border-radius: 100%;
-moz-border-radius: 100%;
border-radius: 100%;
display: block;
height: 10px;
margin: 10px 5px;
text-decoration: none;
width: 10px;
}
.slider .quicknav a:hover {
background: hsla(0, 0%, 50%, .9)
}
.nav {
width:100%;
text-align:center;
}
.nav a {
display:inline-block;
background:transparent;
border-radius:50%;
border:4px solid transparent;
width:24px;
height:24px;
margin:4px;
}
.nav a img {
width:22px;
height:22px;
border-radius:50%;
}
.slider #one:target ~ .quicknav a[href="#one"],
.slider #two:target ~ .quicknav a[href="#two"],
.slider #three:target ~ .quicknav a[href="#three"],
.slider #four:target ~ .quicknav a[href="#four"],
.slider #five:target ~ .quicknav a[href="#five"] {
background: hsla(0, 0%, 0%, .9);
border-color: hsla(0, 0%, 100%, .9);
background: rgb(244, 246, 245);
/*linear-gradient*/
background: -webkit-gradient(linear, left top, left bottom, color-stop(rgba(244, 246, 245, 1), 0.01), color-stop(rgba(203, 219, 219, 1), 1), color-stop(rgba(216, 216, 216, 1), 1));
background: -webkit-linear-gradient(top, rgba(244, 246, 245, 1) 1%, rgba(203, 219, 219, 1) 100%, rgba(216, 216, 216, 1) 100%);
background: -moz-linear-gradient(top, rgba(244, 246, 245, 1) 1%, rgba(203, 219, 219, 1) 100%, rgba(216, 216, 216, 1) 100%);
background: -o-linear-gradient(top, rgba(244, 246, 245, 1) 1%, rgba(203, 219, 219, 1) 100%, rgba(216, 216, 216, 1) 100%);
background: linear-gradient(top, rgba(244, 246, 245, 1) 1%, rgba(203, 219, 219, 1) 100%, rgba(216, 216, 216, 1) 100%);
background: -webkit-gradient(linear, left top, left bottom, color-stop(1%, rgba(244, 246, 245, 1)), color-stop(100%, rgba(203, 219, 219, 1)), color-stop(100%, rgba(216, 216, 216, 1)));
background: -webkit-linear-gradient(top, rgba(244, 246, 245, 1) 1%, rgba(203, 219, 219, 1) 100%, rgba(216, 216, 216, 1) 100%);
background: -moz-linear-gradient(top, rgba(244, 246, 245, 1) 1%, rgba(203, 219, 219, 1) 100%, rgba(216, 216, 216, 1) 100%);
background: -o-linear-gradient(top, rgba(244, 246, 245, 1) 1%, rgba(203, 219, 219, 1) 100%, rgba(216, 216, 216, 1) 100%);
background: linear-gradient(top, rgba(244, 246, 245, 1) 1%, rgba(203, 219, 219, 1) 100%, rgba(216, 216, 216, 1) 100%);
filter: progid: DXImageTransform.Microsoft.gradient(startColorstr='#f4f6f5', endColorstr='#d8d8d8', GradientType=0);
/*box-shadow*/
-webkit-box-shadow: inset 0 0 3px #000, 0 0 2px rgba(0, 0, 0, .5), 0 2px 3px #666;
-moz-box-shadow: inset 0 0 3px #000, 0 0 2px rgba(0, 0, 0, .5), 0 2px 3px #666;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
<button id="_uploadImages" class="btn btn-primary">Upload Images</button>
<form id="_imagesForm" action="" method="post">
<input id="_imagesInput" accept="image/*" type="file" style="display:none" multiple>
</form>
<div id="_displayImages">
<div class="slider">
<ul id="frames" class="frames">
</ul>
<div class="nav"></div>
</div>
</div>
链接地址: http://www.djcxy.com/p/88566.html