FileReader - Thumbnail Preview


#1

Using the following code for a thumbnail preview in two separate file fields but It must be long-winded the way I've done it. I di NOt want to use a multiple file field btw. If anyone can point me in the right direction for amore streamlined version as I'm sure this is a very-long-winded approach:

<html>
<head>
<title>Preview Image Uploadt</title>
<meta charset="utf-8">
</head>


<style>
#uploadPreview {
	width:100px;
} 
#uploadPreview-container {
	display:none;
    position: relative;
    width: 100px;
}
#uploadReset {
    position: absolute;
    top: 0;
    right: 0;
}
#uploadPreview2 {
	width:100px;
} 
#uploadPreview-container2 {
	display:none;
    position: relative;
    width: 100px;
}
#uploadReset2 {
    position: absolute;
    top: 0;
    right: 0;
}
</style>
<script>
    function PreviewImage() {
        var oFReader = new FileReader();
        oFReader.readAsDataURL(document.getElementById("uploadImage").files[0]);

        oFReader.onload = function (oFREvent) {
            document.getElementById("uploadPreview").src = oFREvent.target.result;
			document.getElementById('uploadPreview-container').style.display='block';
        };
    };
	function ResetImage() {
			document.getElementById('uploadPreview-container').style.display='none';
			document.getElementById('uploadImage').value = '';
	};

    function PreviewImage2() {
        var oFReader = new FileReader();
        oFReader.readAsDataURL(document.getElementById("uploadImage2").files[0]);

        oFReader.onload = function (oFREvent) {
            document.getElementById("uploadPreview2").src = oFREvent.target.result;
			document.getElementById('uploadPreview-container2').style.display='block';
        };
    };
	function ResetImage2() {
			document.getElementById('uploadPreview-container2').style.display='none';
			document.getElementById('uploadImage2').value = '';
	};

</script>
</html>
<body>

    <div id="uploadPreview-container">
    <img id="uploadPreview"/>
    <div id="uploadReset"><a href="javascript:void(0)" onclick="ResetImage()" title="Reset Image Upload"><img src="includes/image-upload-preview/reset-image-preview.png" width="20" height="20" alt="Reset Image Upload"/></a></div>
    </div>
    <div><input id="uploadImage" type="file" name="myPhoto" data-max-size="248" onChange="PreviewImage();" /></div>
	
	   <div id="uploadPreview-container2">
    <img id="uploadPreview2"/>
    <div id="uploadReset2"><a href="javascript:void(0)" onclick="ResetImage2()" title="Reset Image Upload"><img src="includes/image-upload-preview/reset-image-preview.png" width="20" height="20" alt="Reset Image Upload"/></a></div>
    </div>
    <div><input id="uploadImage2" type="file" name="myPhoto" data-max-size="248" onChange="PreviewImage2();" /></div>

</body>
</html>

#2

As far as it being long-winded, you're absolutely correct.The programming axiom of 'if you copy and paste the same code multiple times, you've done it wrong' should be ringing in your ears. :wink:

so heres how I would shorten that up, and potentially make it extendable: The concept of Function Parameters.

<script>
    function PreviewImage(field) {
        var oFReader = new FileReader();
        oFReader.readAsDataURL(document.getElementById("uploadImage"+field).files[0]);

        oFReader.onload = function (oFREvent) {
            document.getElementById("uploadPreview"+field).src = oFREvent.target.result;
			document.getElementById('uploadPreview-container'+field).style.display='block';
        };
    };
	function ResetImage(field) {
			document.getElementById('uploadPreview-container'+field).style.display='none';
			document.getElementById('uploadImage'+field).value = '';
	};

and then the form is instead:

    <div id="uploadPreview-container1">
    <img id="uploadPreview1"/>
    <div id="uploadReset1"><a href="javascript:void(0)" onclick="ResetImage(1)" title="Reset Image Upload"><img src="includes/image-upload-preview/reset-image-preview.png" width="20" height="20" alt="Reset Image Upload"/></a></div>
    </div>
    <div><input id="uploadImage1" type="file" name="myPhoto" data-max-size="248" onChange="PreviewImage(1);" /></div>

copy/paste, replace "1" for "2" everywhere, etc.


#3

thank you .... that works a treat ...


#4

Just ut of interest how would I call the ResetImage() function nside another function if that makes sense, there is some javascript already in use tahat checks file size and type, bot seem to work but I can't the thumbnail to hide if file size and type validation fails:

<style>
#uploadPreview1, #uploadPreview2, #uploadPreview3  {
	width:100px;
} 
#uploadPreview-container1, #uploadPreview-container2, #uploadPreview-container3 {
	display:none;
    position: relative;
    width: 100px;
}
#uploadReset1, #uploadReset2, #uploadReset3 {
    position: absolute;
    top: 0;
    right: 0;
}
</style>
<script>
    function PreviewImage(field) {
        var oFReader = new FileReader();
        oFReader.readAsDataURL(document.getElementById("uploadImage"+field).files[0]);

        oFReader.onload = function (oFREvent) {
            document.getElementById("uploadPreview"+field).src = oFREvent.target.result;
			document.getElementById('uploadPreview-container'+field).style.display='block';
        };
    };
	function ResetImage(field) {
			document.getElementById('uploadPreview-container'+field).style.display='none';
			document.getElementById('uploadImage'+field).value = '';
	};
	
	window.onload=function(){
		document.getElementById('uploadImage1').addEventListener('change', checkImage, false);
		uploadImage2.addEventListener('change', checkImage, false);
		uploadImage3.addEventListener('change', checkImage, false);
	function checkImage(e) {
		var file_list = e.target.files;
    	for (var i = 0, file; file = file_list[i]; i++) {
        var sFileName = file.name;
        var sFileExtension = sFileName.split('.')[sFileName.split('.').length - 1].toLowerCase();
        var iFileSize = file.size;
        var iConvert = (file.size / 1048576).toFixed(2);

        if (!(sFileExtension === "jpg" || sFileExtension === "jpeg" || sFileExtension === "png") || iFileSize > 10485760) {
            txt = "Your File type : " + sFileExtension + "\n\n";
            txt += "Your File Size: " + iConvert + " MB \n\n";
            txt += "Please make sure your file is in image format with extension jpg, jpeg, png or gif format and less than 10 MB.\n\n";
			uppertxt = txt.toUpperCase();
			alert(uppertxt);
			ResetImage();

        }
    }
}
}


	</script>
</head>

<body>

    <div id="uploadPreview-container1">
    <img id="uploadPreview1"/>
    <div id="uploadReset1"><a href="javascript:void(0)" onclick="ResetImage(1)" title="Reset Image Upload"><img src="includes/image-upload-preview/reset-image-preview.png" width="20" height="20" alt="Reset Image Upload"/></a></div>
    </div>
    <div><input id="uploadImage1" type="file" name="myPhoto" data-max-size="248" onChange="PreviewImage(1);" /></div>
copy/paste, replace "1" for "2" everywhere, etc.
    <div id="uploadPreview-container2">
    <img id="uploadPreview2"/>
    <div id="uploadReset2"><a href="javascript:void(0)" onclick="ResetImage(2)" title="Reset Image Upload"><img src="includes/image-upload-preview/reset-image-preview.png" width="20" height="20" alt="Reset Image Upload"/></a></div>
    </div>
    <div><input id="uploadImage2" type="file" name="myPhoto" data-max-size="248" onChange="PreviewImage(2);" /></div>
	
	    <div id="uploadPreview-container3">
    <img id="uploadPreview3"/>
    <div id="uploadReset3"><a href="javascript:void(0)" onclick="ResetImage(3)" title="Reset Image Upload"><img src="includes/image-upload-preview/reset-image-preview.png" width="20" height="20" alt="Reset Image Upload"/></a></div>
    </div>
    <div><input id="uploadImage3" type="file" name="myPhoto" data-max-size="248" onChange="PreviewImage(3);" /></div>

</body>
</html>

#5

TL;DR: ResetImage(e.target.id.replace("uploadImage",""))

Why?
Because this is inside an event handler, which spits the object "e" (the event object, named e by the function declaration. Remember Function Parameters we used before?)

How do you come to the definition you did?
Step 1: Break the javascript execution. This process is slightly different for each browser, but the general pattern is the same: Open the Developer Tools (F12 in most browsers), check the Sources section, and give a breakpoint by clicking the line number you want to stop on - in my case, line 36. (See top half of picture.)
Step 2: Investigate the objects you have available. We know that there is an object "e" available, because line 35 tells us so (also your browser might show you what's currently in e, that's the orange-highlighted bit in the picture on line 35). So into the console we go (It's the bit down at the bottom of the image.). The console is accessing the local variable scope of the point at which we broke, so I can just type "e" into the console, and it gives me back the object.
Step 3: Look for context clues. I know I have "e" to play with, but the code that's already there must be doing something to the image already, because otherwise the function would be empty. Line 36 in particular strikes my eye. "var file_list = e.target.files;". Now I know that e has something in it called "target", and it has something inside IT called "files". Well, you wrote something yourself that accesses a "files" (line 19)... so if that's the case, maybe .target is the node we're interested in...
Step 4: Contextualized investigation. Now I've got a hunch that e.target is what i'm interested in. So i pop e.target into the console. Ah! It's my input node! Excellent. I've got the information I need in there to identify which node we're talking about - I stuck a number on the end of the ID attribute. Well, if the target has a .files, does it have a .id? Put that into the console and... yup! e.target.id = "uploadImage1" ... but my ResetImage function is expecting just to have the number... hrm...
Step 5: Massage the data. I only want the "1" on the end of uploadImage1. I could tell Javascript to find only the last character in the string, but what if I have 10 inputs? That wont work anymore. Instead, we'll just get rid of the "uploadImage" text. There's a couple of ways to do that, but I chose to make Javascript turn the "uploadImage" into the empty string "", leaving me with just... "1". One last test in the console to make sure it works.... and that I can pass to my ResetImage function. e.target.id.replace("uploadImage","")


#6

Thanks I tried:

        if (!(sFileExtension === "jpg" || sFileExtension === "jpeg" || sFileExtension === "png") || iFileSize > 10485760) {
            txt = "Your File type : " + sFileExtension + "\n\n";
            txt += "Your File Size: " + iConvert + " MB \n\n";
            txt += "Please make sure your file is in image format with extension jpg, jpeg, png or gif format and less than 10 MB.\n\n";
			uppertxt = txt.toUpperCase();
			alert(uppertxt);
			ResetImage(e.target.id.replace("uploadImage",""))

When file size or type validation fails, this only clear the file input field but it doesn't set #uploadPreview-container back to display:none which is what I'm having a problem with


#7

Show me your full code then, because it works for me...


#8

Here it is, probably I made a novice error!!

<html>
<head>
<title>Untitled Document</title>
<meta charset="utf-8">
<style>
#uploadPreview1, #uploadPreview2, #uploadPreview3  {
	width:100px;
} 
#uploadPreview-container1, #uploadPreview-container2, #uploadPreview-container3 {
	display:none;
    position: relative;
    width: 100px;
}
#uploadReset1, #uploadReset2, #uploadReset3 {
    position: absolute;
    top: 0;
    right: 0;
}
</style>
<script>
    function PreviewImage(field) {
        var oFReader = new FileReader();
        oFReader.readAsDataURL(document.getElementById("uploadImage"+field).files[0]);

        oFReader.onload = function (oFREvent) {
            document.getElementById("uploadPreview"+field).src = oFREvent.target.result;
			document.getElementById('uploadPreview-container'+field).style.display='block';
        };
    };
	function ResetImage(field) {
			document.getElementById('uploadPreview-container'+field).style.display='none';
			document.getElementById('uploadImage'+field).value = '';
	};
	
	window.onload=function(){
		document.getElementById('uploadImage1').addEventListener('change', checkImage, false);
		uploadImage2.addEventListener('change', checkImage, false);
		uploadImage3.addEventListener('change', checkImage, false);
	function checkImage(e) {
		var file_list = e.target.files;
    	for (var i = 0, file; file = file_list[i]; i++) {
        var sFileName = file.name;
        var sFileExtension = sFileName.split('.')[sFileName.split('.').length - 1].toLowerCase();
        var iFileSize = file.size;
        var iConvert = (file.size / 1048576).toFixed(2);

        if (!(sFileExtension === "jpg" || sFileExtension === "jpeg" || sFileExtension === "png") || iFileSize > 10485760) {
            txt = "Your File type : " + sFileExtension + "\n\n";
            txt += "Your File Size: " + iConvert + " MB \n\n";
            txt += "Please make sure your file is in image format with extension jpg, jpeg, png or gif format and less than 10 MB.\n\n";
			uppertxt = txt.toUpperCase();
			alert(uppertxt);
			ResetImage(e.target.id.replace("uploadImage",""))

        }
    }
}
}


	</script>
</head>

<body>

    <div id="uploadPreview-container1">
    <img id="uploadPreview1"/>
    <div id="uploadReset1"><a href="javascript:void(0)" onclick="ResetImage(1)" title="Reset Image Upload"><img src="includes/image-upload-preview/reset-image-preview.png" width="20" height="20" alt="Reset Image Upload"/></a></div>
    </div>
    <div><input id="uploadImage1" type="file" name="myPhoto" data-max-size="248" onChange="PreviewImage(1);" /></div>

    <div id="uploadPreview-container2">
    <img id="uploadPreview2"/>
    <div id="uploadReset2"><a href="javascript:void(0)" onclick="ResetImage(2)" title="Reset Image Upload"><img src="includes/image-upload-preview/reset-image-preview.png" width="20" height="20" alt="Reset Image Upload"/></a></div>
    </div>
    <div><input id="uploadImage2" type="file" name="myPhoto" data-max-size="248" onChange="PreviewImage(2);" /></div>
	
	<div id="uploadPreview-container3">
    <img id="uploadPreview3"/>
    <div id="uploadReset3"><a href="javascript:void(0)" onclick="ResetImage(3)" title="Reset Image Upload"><img src="includes/image-upload-preview/reset-image-preview.png" width="20" height="20" alt="Reset Image Upload"/></a></div>
    </div>
    <div><input id="uploadImage3" type="file" name="myPhoto" data-max-size="248" onChange="PreviewImage(3);" /></div>

</body>
</html>

#9

so two things, one 'cleanup', one errorchecking.

Cleanup: I'd recommend cleaning up your CSS to general class definitions rather than ID selectors. that way you dont have to keep changing your CSS every time you add a field.

Errorchecking: I believe the problem you're seeing is because you're latching 2 events onto change:

    <div><input id="uploadImage1" type="file" name="myPhoto" data-max-size="248" onChange="PreviewImage(1);" /></div>

	document.getElementById('uploadImage1').addEventListener('change', checkImage, false);

Instead of invoking PreviewImage from the element, add it as the last line of checkImage, and add a "return;" line to the end of the "if something went bad, throw error and hide everything:

        if (!(sFileExtension === "jpg" || sFileExtension === "jpeg" || sFileExtension === "png") || iFileSize > 10485760) {
            txt = "Your File type : " + sFileExtension + "\n\n";
            txt += "Your File Size: " + iConvert + " MB \n\n";
            txt += "Please make sure your file is in image format with extension jpg, jpeg, png or gif format and less than 10 MB.\n\n";
			uppertxt = txt.toUpperCase();
			alert(uppertxt);
			ResetImage(e.target.id.replace("uploadImage",""));
            return; //This prevents PreviewImage from being called if something went wrong.
        }
        PreviewImage(e.target.id.replace("uploadImage",""));

(Alternatively, dont return, and instead put the PreviewImage call inside an else {} clause.)


#10

Thanks .... Do you have a full working code example, I just can't get this to quite work correctly


#11

OK I got full working code, don't know hot change to ids to classes but this works ... thanks for help:

<html>
<head>
<title>Untitled Document</title>
<meta charset="utf-8">
<style>
#uploadPreview1, #uploadPreview2, #uploadPreview3  {
	width:100px;
} 
#uploadPreview-container1, #uploadPreview-container2, #uploadPreview-container3 {
	display:none;
    position: relative;
    width: 100px;
}
#uploadReset1, #uploadReset2, #uploadReset3 {
    position: absolute;
    top: 0;
    right: 0;
}
</style>
<script>
function PreviewImage(field) {
        var oFReader = new FileReader();
        oFReader.readAsDataURL(document.getElementById("uploadImage" + field).files[0]);

        oFReader.onload = function(oFREvent) {
            document.getElementById("uploadPreview" + field).src = oFREvent.target.result;
            document.getElementById('uploadPreview-container' + field).style.display = 'block';
        };
    };

    function ResetImage(field) {
        document.getElementById('uploadPreview-container' + field).style.display = 'none';
        document.getElementById('uploadImage' + field).value = '';
    };

    window.onload = function() {
        document.getElementById('uploadImage1').addEventListener('change', checkImage, false);
        uploadImage2.addEventListener('change', checkImage, false);
        uploadImage3.addEventListener('change', checkImage, false);

        function checkImage(e) {
            var file_list = e.target.files;
            for (var i = 0, file; file = file_list[i]; i++) {
                var sFileName = file.name;
                var sFileExtension = sFileName.split('.')[sFileName.split('.').length - 1].toLowerCase();
                var iFileSize = file.size;
                var iConvert = (file.size / 1048576).toFixed(2);

                if (!(sFileExtension === "jpg" || sFileExtension === "jpeg" || sFileExtension === "png") || iFileSize > 10485760) {
                    txt = "Your File type : " + sFileExtension + "\n\n";
                    txt += "Your File Size: " + iConvert + " MB \n\n";
                    txt += "Please make sure your file is in image format with extension jpg, jpeg, png or gif format and less than 10 MB.\n\n";
                    uppertxt = txt.toUpperCase();
                    alert(uppertxt);
                    ResetImage(e.target.id.replace("uploadImage", ""));


                } else {
                    PreviewImage(e.target.id.replace("uploadImage", ""))
                }
            }
        }
    }


	</script>
</head>

<body>

    <div id="uploadPreview-container1">
    <img id="uploadPreview1"/>
    <div id="uploadReset1"><a href="javascript:void(0)" onclick="ResetImage(1)" title="Reset Image Upload"><img src="includes/image-upload-preview/reset-image-preview.png" width="20" height="20" alt="Reset Image Upload"/></a></div>
    </div>
    <div><input id="uploadImage1" type="file" name="myPhoto" data-max-size="248" /></div>

    <div id="uploadPreview-container2">
    <img id="uploadPreview2"/>
    <div id="uploadReset2"><a href="javascript:void(0)" onclick="ResetImage(2)" title="Reset Image Upload"><img src="includes/image-upload-preview/reset-image-preview.png" width="20" height="20" alt="Reset Image Upload"/></a></div>
    </div>
    <div><input id="uploadImage2" type="file" name="myPhoto" data-max-size="248" /></div>
	
	<div id="uploadPreview-container3">
    <img id="uploadPreview3"/>
    <div id="uploadReset3"><a href="javascript:void(0)" onclick="ResetImage(3)" title="Reset Image Upload"><img src="includes/image-upload-preview/reset-image-preview.png" width="20" height="20" alt="Reset Image Upload"/></a></div>
    </div>
    <div><input id="uploadImage3" type="file" name="myPhoto" data-max-size="248" /></div>

</body>
</html>

#12

CSS Syntax - W3Schools
Basically give the elements a class="aclassname", and then define CSS for .aclassname instead of #elementId,#elementid...

Glad it works though!


closed #13

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.