Solved

need help displaying better images with plupload

Posted on 2014-12-30
9
645 Views
Last Modified: 2015-01-05
Hi

I'm currently writing a shop for a friend and the add item page needs to be able to allow x number of image uploads to go with the item for sale.

I'm using plupload ( http://www.plupload.com ) which seems quite good and I' believe also used in WordPress etc.

I have the following code that does a basic job how I want it but it needs a few polishing bits, perhaps some of you javascript / jQuery gurus could assist please ( as this has taken me a while to get this far grabbing bits from lots of examples :( )

Heres the code so far based on a basic install of plupload
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    
    <script src="//code.jquery.com/jquery-1.11.2.min.js"></script>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.11.2/jquery-ui.min.js" charset="UTF-8"></script> 
    <script type="text/javascript" src="../../js/plupload/plupload.full.min.js"></script>
    <script type="text/javascript" src="../../js/plupload/jquery.ui.plupload/jquery.ui.plupload.min.js" charset="UTF-8"></script> 
    
    <title>Untitled Document</title>
</head>

<body>

<div id="filelist">Your browser doesn't have Flash, Silverlight or HTML5 support.</div>

<br />
 
<div id="container">
    <a id="pickfiles" href="javascript:;">[Select files]</a> 
</div>
 
<br />

<pre id="console"></pre>
 
<input type="text" id="itemImage1" name="itemImage1" size="50" value=""/><br>
      
<script type="text/javascript">

	(function( $, plupload ) {
			
	 
		var uploader = new plupload.Uploader({
			
			runtimes : 'html5,flash,silverlight,html4',		 
			browse_button : 'pickfiles',
			container: document.getElementById('container'), 		 
			url : "upload.php",		 
			filters : {
				max_file_size : '30mb',
				mime_types: [
					{title : "Image files", extensions : "jpg,jpeg,gif,png"}
				]
			},
			preserve_headers: true,	
			max_file_count: 1,
			unique_names:true,
			autostart: true,
			max_file_size : '50mb',		
			chunk_size: '1mb',
			resize : {
				width : 800, 
				height : 800, 
				quality : 90,
				crop: false // crop to exact dimensions
			},
			flash_swf_url : '../../js/plupload/Moxie.swf',
			silverlight_xap_url : '../../js/plupload/Moxie.xap',
		 
	 
			init: {
				PostInit: function() {
					document.getElementById('filelist').innerHTML = ''; 
				},
		 
				FilesAdded: function(up, files) {
					plupload.each(files, function(file) {
						showImagePreview(file);
						document.getElementById('filelist').innerHTML += '<div id="' + file.id + '">' + file.name + ' (' + plupload.formatSize(file.size) + ') <b></b></div>';
						uploader.start();
					});
				},
		 
				UploadProgress: function(up, file) {
					document.getElementById('itemImage1').value = file.target_name;
					document.getElementById(file.id).getElementsByTagName('b')[0].innerHTML = '<span>' + file.percent + "%</span>";
				},
		 
				Error: function(up, err) {
					document.getElementById('console').innerHTML += "\nError #" + err.code + ": " + err.message;
				}
			}
			
		});
	
		uploader.init();
		
		function showImagePreview( file ) {
			
			var item = $( "<span></span>" ).prependTo( "#console" );
			var image = $( new Image() ).appendTo( item );
			var preloader = new mOxie.Image();
			
			preloader.onload = function() {
				preloader.downsize( 200, 200 );
				image.prop( "src", preloader.getAsDataURL() );
			};
			
			preloader.load( file.getSource() );
	
		}
			
	})( jQuery, plupload );
  
</script>

</body>
</html>

Open in new window


At present this is what it does:

# allows for the selection of an image
# uploads it after selection (renaming uniquely)
# creates a thumbnail (base64, but I'm sure there are better ways, the demo seems to do one much nicer but I cant see how?)
# adds the new unique name to a input box (as I will need to have these as an array to send with the item details to know # when the page is viewed what images to then show

This is what I need it to do

# append each newly uploaded image unique name into the itemImage1 text box
# have a delete button with each image so the user can remove an item (this will also delete from the itemImage1 text box
# display a better thumbnail, does jQuery have a better way of doing this?
# limit the images in total to 5, I guess this is some sort of jQuery count on the elements in a container? but well out of my league with JavaScript

Please do not just push me in the direction of examples. I learn quickly but only when I can see how my implementation works so would appreciate ideas based on my code, or a better working entire plupload solution here please.

user selects file
select-1.png
upload complete and thumbnail displayed with unique name (created by plupload in text box)
select-2.png
need to limit to 5 total images allowing deletion of any/all images hiding the {select} option when max is reached but showing again when images are deleted.
select-3.png
0
Comment
Question by:Neil Thompson
  • 6
  • 3
9 Comments
 
LVL 3

Author Comment

by:Neil Thompson
ID: 40523688
ok, I've worked out how to remove the [Select files] when the image count = 5 :)

FilesAdded: function(up, files) {
   plupload.each(files, function(file) {
      showImagePreview(file);
      document.getElementById('filelist').innerHTML += '<div id="' + file.id + '">' + file.name + ' (' + plupload.formatSize(file.size) + ') <b></b></div>';
     
---->      var numberOfUploadedImages = $("#filelist div").length;
---->      if (numberOfUploadedImages==5) { $("#pickfiles").hide(); }


      uploader.start();
    });
				},

Open in new window

0
 
LVL 82

Expert Comment

by:leakim971
ID: 40523819
Please do not just push me in the direction of examples. I learn quickly but only when I can see how my implementation works so would appreciate ideas based on my code, or a better working entire plupload solution here please.

So why not splitting your project in at least four questions?
0
 
LVL 3

Author Comment

by:Neil Thompson
ID: 40523831
sorry, what do you mean please?
I'm trying to ask for assistance to achieve my request using "my" code, not example codes that are different from mine (that's where I'm struggling to see how to then implement them in to mine), hope that makes more sense
0
Space-Age Communications Transitions to DevOps

ViaSat, a global provider of satellite and wireless communications, securely connects businesses, governments, and organizations to the Internet. Learn how ViaSat’s Network Solutions Engineer, drove the transition from a traditional network support to a DevOps-centric model.

 
LVL 82

Expert Comment

by:leakim971
ID: 40523833
This Is What I Need It To Do

1) append each newly uploaded image unique name into the itemImage1 text box
2) have a delete button with each image so the user can remove an item (this will also delete from the itemImage1 text box
3) display a better thumbnail, does jQuery have a better way of doing this?
4) limit the images in total to 5, I guess this is some sort of jQuery count on the elements in a container? but well out of my league with JavaScript
0
 
LVL 3

Author Comment

by:Neil Thompson
ID: 40523834
I've also crudely worked out a way to add the removal button I think, could possibly be made slicker?

----->				// remove image
----->				var wrapper = $("#console"); //Fields wrapper
----->				$(wrapper).on("click",".remove_field", function(e){ //user click on remove text
----->					e.preventDefault();
----->					$(this).parent('span').remove();
----->				})
	
		uploader.init();
		
		function showImagePreview( file ) {
			
			var item = $("<span></span>").prependTo("#console");
----->		var removeLink = $("<a href='#' class='remove_field'>Remove</a><br/>").prependTo(item);
			var image = $(new Image()).appendTo(item);
			var preloader = new mOxie.Image();
			
			preloader.onload = function() {
				preloader.downsize( 200, 200 );
				image.prop( "src", preloader.getAsDataURL() );
			};
			
			preloader.load( file.getSource() );
	
		}

Open in new window

0
 
LVL 82

Expert Comment

by:leakim971
ID: 40523848
it look good for me
0
 
LVL 3

Author Comment

by:Neil Thompson
ID: 40525130
I intend to ask support to close this question as I have altered the code substantially and fixed many of the issues requested. Additionally then layout of the request as noted isn't very clear.

I will tidy up my working code, and post it below to assist others then ask a new question to solve the issues if no-one that has commented has any objections
0
 
LVL 3

Accepted Solution

by:
Neil Thompson earned 0 total points
ID: 40525174
Here is my working code based on my original question, there are bits of it that do not yet fully work as required.

This may help someone down the line that wants to use plupload to

1) select x images (1 at a time, although this can be altered)
2) upload them once selected (again can be altered)
3) resize them on the fly before uploading (can be altered)
4) allow the option to remove an image from the DOM (not the file system)
5) hide the upload button from view when the max limit of files is reached, adding again if images are removed

What this code doesn't yet do nicely:

1) provide a way to remove the associated unique name from the hidden field array of uploaded images
2) utilise the image upload thumb as effectively as possible (this works out the upload path and scales the image rather than doing something on the fly)

adding images with select button, remove link and list of assiciated unique file names
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    
    <script src="//code.jquery.com/jquery-1.11.2.min.js"></script>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.11.2/jquery-ui.min.js" charset="UTF-8"></script> 
    <script type="text/javascript" src="../../js/plupload/plupload.full.min.js"></script>
    <script type="text/javascript" src="../../js/plupload/jquery.ui.plupload/jquery.ui.plupload.min.js" charset="UTF-8"></script> 
    
    <title>Untitled Document</title>
</head>

<body>

<div id="imageGalleryState">Your browser doesn't have Flash, Silverlight or HTML5 support.</div>

<br />
 
<div id="selectFilesContainer">
    <a id="pickfiles" href="javascript:;">[Select files]</a> 
</div>
 
<br />

<div id="imageGalleryContainer"></div>
 
<textarea id="associatedImages" name="associatedImages" cols="60" rows="10"></textarea><br>
      
<script type="text/javascript">	

	(function( $, plupload ) {			
	 
	 	// create a new instance of the uploader
		var uploader = new plupload.Uploader({
						
			runtimes : 'html5,flash,silverlight,html4',						// runtime setup	 
			browse_button : 'pickfiles', 									// select files button
			container: document.getElementById('selectFilesContainer'),		// selected files container
			url : "upload.php",												// URL of uploader
			filters : {
				max_file_size : '30mb',										// max single file size (plupload compresses client size so upload will be small :)
				mime_types: [
					{title : "Image files", extensions : "jpg,jpeg,gif,png"}// upload types to allow
				]
			},
			preserve_headers: true,											// retain EXIF info (good for iphone images etc as it then knows the right way up
			max_file_count: 1,												// only allow 1 file at a time to be uploaded
			multi_selection:false,											// do not allow multiple selections
			unique_names:true,												// rename on the fly
			autostart: true,												// auto upload when selected
			chunk_size: '1mb',												// split into 1mb chunks (only really needed for huge files)
			resize : {
				width : 800,												// resize width
				height : 800,												// resize height
				quality : 90,												// resize quality
				crop: false													// do not crop
			},
			flash_swf_url : '../../js/plupload/Moxie.swf',					// URL for flash uploader
			silverlight_xap_url : '../../js/plupload/Moxie.xap',			// URL for silverlight uploader
		 
		 
	 		// Fires when the current RunTime has been initialized.
			init: {
				
				// Fires after the init event incase you need to perform actions there.
				PostInit: function() {
					document.getElementById('imageGalleryState').innerHTML = ''; 
					document.getElementById('associatedImages').innerHTML = ''; 
				},
		 		
				// Fires after files were filtered and added to the queue.
				FilesAdded: function(up, files) {				
					// loop through files, if there are 5 then hide the add button 
					plupload.each(files, function(file) {	
						uploader.start();
						var numberOfUploadedImages = $("#imageGalleryContainer div").length;
						if (numberOfUploadedImages < 5) { $("#pickfiles").show(); }
						if (numberOfUploadedImages == 5) { $("#pickfiles").hide(); }				
					});
					// update the file container so we know what images are assigned to this item
					// this is sent in the form post on submission
					updateAssociatedImages(files);
				},
				
				// Fires when a file is successfully uploaded.
				FileUploaded: function(up, file, info) {
					// shows the thumb of the uploaded image
					showImagePreview(file);
				},
		 
		 		// Fires while a file is being uploaded. Use this event to update the current file upload progress.
				UploadProgress: function(up, file) {
					//document.getElementById('associatedImages').value = file.target_name;
				},
		 
		 		// Fires when a error occurs.
				Error: function(up, err) {
					document.getElementById('imageGalleryContainer').innerHTML += "\nError #" + err.code + ": " + err.message;
				}
			}
			
		});
	
	
		// Initializes the Uploader instance and adds internal event listeners.
		uploader.init();
		
		
		// provide the ability to remove images
		// This DOES NOT remove the image from the server, only from the DOM (and ideally in my case) the associatedImages hidden field
		var igc = $("#imageGalleryContainer");
		$(igc).on("click",".remove_field", function(e){ 
		
			// remove the selected image
			e.preventDefault();
			$(this).parent('div').remove();
			
			 /* ------ TO-DO ------ */
			// update the associated images container
			var getRemovedTargetName = $(this).parent('div');
			//alert(getRemovedTargetName.get(0).outerHTML);
			
			// if the removal brings the total below 5 also show the add button again		
			var numberOfUploadedImages = $("#imageGalleryContainer div").length;
			if (numberOfUploadedImages <5) { $("#pickfiles").show(); }		
							
		})
		
		
		// creates a thumbnail based on the uploaded image unique name and the upload path
		// in this case based on folders for year / month / day / [unique file nalme]
		function showImagePreview( file ) {	
				
			// create a div to hold the image
			var item = $("<div></div>").prependTo("#imageGalleryContainer");
			
			// add a remove link
			var removeLink = $("<a href='#' id='"+file.target_name+"' class='remove_field'>Remove</a><br/>").prependTo(item);
			
			// work out where the image was uploaded to
			var uploadURLPrefix = "../../uploads/user/plupload/";				
			var d = new Date();
			var mkFolderYear  = d.getFullYear();
			var mkFolderMonth = d.getMonth()+1; // 0-11
			var mkFolderDay   = d.getDate();
			var uploadFullPathForThumb = uploadURLPrefix + mkFolderYear + '/' +  mkFolderMonth + '/' + mkFolderDay + '/' + file.target_name;
			
			// add the image thumb
			var imageThumb = $("<img src='"+uploadFullPathForThumb+"' class='addImageThumb' height='120'/>").appendTo(item);	
			
		}
		
		
		// I want to be able to create a hidden form field I can post with my item that
		// will store in the database all the related images for this item
		// this is the best way I could think to do it but this will be improved
		function updateAssociatedImages (files) {
			
			// get the value of the associated images container
			var ai = document.getElementById('associatedImages').value;
			
			// add the latest uploaded image to the associated images
			plupload.each(files, function(file) {
				ai += ' ' + file.target_name;
				ai = ai.replace(/\s{2,}/g, ' ');
				document.getElementById('associatedImages').value = ai;				
			});
			
		}
		
			
	})( jQuery, plupload );
  		

</script>

</body>
</html>

Open in new window


Once I have those options fixed I'll also post that code below to assist. Hope it helps someone :)
Neil
0
 
LVL 3

Author Closing Comment

by:Neil Thompson
ID: 40531158
solved issues and posted complete, commented solution to assist others
0

Featured Post

Master Your Team's Linux and Cloud Stack!

The average business loses $13.5M per year to ineffective training (per 1,000 employees). Keep ahead of the competition and combine in-person quality with online cost and flexibility by training with Linux Academy.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

In this article you'll learn how to use Ajax calls within your CodeIgniter application. To explain this, I'll illustrate how to implement a simple contact form to allow visitors to send you an email through your web site.
I found this questions asking how to do this in many different forums, so I will describe here how to implement a solution using PHP and AJAX. The logical flow for the problem should be: Write an event handler for the first drop down box to get …
The viewer will learn the basics of jQuery, including how to invoke it on a web page. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery.: (CODE)
The viewer will learn the basics of jQuery including how to code hide show and toggles. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery…

860 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question