Review
In the previous section, we have declared and written the necessary configuration files. In this section, we will write the HTML form and JavaScript code for composing and sending emails with attachments.Table of Contents
Part 1: Introduction and Functional SpecsPart 2: Java classes
Part 3: XML configuration
Part 4: HTML form
Part 5: Running the Application
jQuery-File-Upload
To achieve a seamless AJAX-like file upload experience, we will rely on blueimp's jQuery plugin jQuery-File-Upload for managing attachments.What is jQuery-File-Upload?
File Upload widget with multiple file selection, drag&drop support, progress bars and preview images for jQuery. Supports cross-domain, chunked and resumable file uploads and client-side image resizing. Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads.
Source: https://github.com/blueimp/jQuery-File-Upload
File Upload widget with multiple file selection, drag&drop support, progress bars and preview images for jQuery. Supports cross-domain, chunked and resumable file uploads and client-side image resizing. Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads.
Source: https://github.com/blueimp/jQuery-File-Upload
To view a demo of this plugin, please visit the following resources:
- Demo File Upload
- How to setup the plugin on your website
- How to use only the basic plugin (minimal setup guide).
For our purposes, we will follow the minimal setup guide, so that we can create our custom UI and eliminate extraneous steps.
Warning!
Make sure to test the plugin on different browsers because some browsers behave in unexpected ways. In my opinion, Chrome and Firefox are the best browsers for development.
Make sure to test the plugin on different browsers because some browsers behave in unexpected ways. In my opinion, Chrome and Firefox are the best browsers for development.
Email Form
Here's our email form again:And here's the full source:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> | |
<c:url value="/email/send" var="sendUrl"/> | |
<c:url value="/email/fileupload" var="uploadUrl"/> | |
<html> | |
<head> | |
<link rel="stylesheet" type="text/css" media="screen" href='<c:url value="/resources/css/jquery-ui/pepper-grinder/jquery-ui-1.8.16.custom.css"/>'/> | |
<link rel="stylesheet" type="text/css" media="screen" href='<c:url value="/resources/css/style.css"/>'/> | |
<script type='text/javascript' src='<c:url value="/resources/js/jquery-1.6.4.min.js"/>'></script> | |
<script type='text/javascript' src='<c:url value="/resources/js/jquery-ui-1.8.16.custom.min.js"/>'></script> | |
<script type='text/javascript' src='<c:url value="/resources/js/util.js"/>'></script> | |
<script type='text/javascript' src='<c:url value="/resources/js/jquery-fileupload/vendor/jquery.ui.widget.js"/>'></script> | |
<script type='text/javascript' src='<c:url value="/resources/js/jquery-fileupload/jquery.iframe-transport.js"/>'></script> | |
<script type='text/javascript' src='<c:url value="/resources/js/jquery-fileupload/jquery.fileupload.js"/>'></script> | |
<title>Email</title> | |
<script type='text/javascript'> | |
$(function() { | |
init(); | |
}); | |
function init() { | |
$('input:button').button(); | |
$('#submit').button(); | |
$('#emailForm').submit(function(event) { | |
event.preventDefault(); | |
$.postJSON('${sendUrl}', { | |
senderName: $('#senderName').val(), | |
senderEmail: $('#senderEmail').val(), | |
ccEmail: $('#ccEmail').val(), | |
subject: $('#subject').val(), | |
body: $('#textBody').val(), | |
receiverName: $('#receiverName').val(), | |
receiverEmail: $('#receiverEmail').val(), | |
filename: getFilelist() | |
}, | |
function(result) { | |
if (result.success == true) { | |
dialog('Success', 'Email has been sent!'); | |
} else { | |
dialog('Failure', 'Email has not been sent!'); | |
} | |
}); | |
}); | |
$('#reset').click(function() { | |
clearForm(); | |
dialog('Success', 'Fields have been cleared!'); | |
}); | |
$('#upload').fileupload({ | |
dataType: 'json', | |
done: function (e, data) { | |
$.each(data.result, function (index, file) { | |
$('body').data('filelist').push(file); | |
$('#filename').append(formatFileDisplay(file)); | |
$('#attach').empty().append('Attach another file'); | |
}); | |
} | |
}); | |
// Technique borrowed from http://stackoverflow.com/questions/1944267/how-to-change-the-button-text-of-input-type-file | |
// http://stackoverflow.com/questions/210643/in-javascript-can-i-make-a-click-event-fire-programmatically-for-a-file-input | |
$("#attach").click(function () { | |
$("#upload").trigger('click'); | |
}); | |
$('body').data('filelist', new Array()); | |
} | |
function formatFileDisplay(file) { | |
var size = '<span style="font-style:italic">'+(file.size/1000).toFixed(2)+'K</span>'; | |
return file.name + ' ('+ size +')<br/>'; | |
} | |
function getFilelist() { | |
var files = $('body').data('filelist'); | |
var filenames = ''; | |
for (var i=0; i<files.length; i<i++) { | |
var suffix = (i==files.length-1) ? '' : ','; | |
filenames += files[i].name + suffix; | |
} | |
return filenames; | |
} | |
function dialog(title, text) { | |
$('#msgbox').text(text); | |
$('#msgbox').dialog( | |
{ title: title, | |
modal: true, | |
buttons: {"Ok": function() { | |
$(this).dialog("close");} | |
} | |
}); | |
} | |
function clearForm() { | |
$('#receiverName').val(''); | |
$('#receiverEmail').val(''); | |
$('#ccEmail').val(''); | |
$('#senderName').val(''); | |
$('#senderEmail').val(''); | |
$('#subject').val(''); | |
$('#textBody').val(''); | |
$('#filename').empty(); | |
$('#attach').empty().append('Attach a file'); | |
$('body').data('filelist', new Array()); | |
} | |
</script> | |
</head> | |
<body> | |
<h1 id='banner'>Compose Email</h1> | |
<div> | |
<form id='emailForm'> | |
<fieldset> | |
<legend>New Email</legend> | |
<label for='receiverName'>To (name):</label><input type='text' id='receiverName'/><br/> | |
<label for='receiverEmail'>To (email)</label><input type='text' id='receiverEmail'/><br/> | |
<label for='ccEmail'>Cc (email):</label><input type='text' id='ccEmail'/><br/> | |
<label for='senderName'>From (name):</label><input type='text' id='senderName'/><br/> | |
<label for='senderEmail'>From (email):</label><input type='text' id='senderEmail'/><br/> | |
<label for='subject'>Subject:</label><input type='text' id='subject'/><br/> | |
<label for='textBody' style="display:break">Message</label> | |
<textarea name="textBody" id="textBody">Email message here</textarea><br/> | |
<span id='filename'></span><br/> | |
<a href='#' id='attach'>Attach a file</a><br/> | |
<input id="upload" type="file" name="file" data-url="${uploadUrl}" multiple style="opacity: 0; filter:alpha(opacity: 0);"><br/> | |
<input type='button' value='Reset' id='reset' /> | |
<input type='submit' value='Send' id='submit'/> | |
</fieldset> | |
</form> | |
</div> | |
<div id='msgbox' title='' style='display:none'></div> | |
</body> | |
</html> |
Explanation
Let's dissect and examine this lengthy source code. We're basically declaring the following:- Endpoint Urls
- Import Scripts
- Initialization Function
- File Display Function
- File List Function
- Dialog Function
- Clear Function
Endpoint Urls
We've declared two global urls: sendUrl and uploadUrl. These are the endpoints for sending messages and uploading files respectively.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<c:url value="/email/send" var="sendUrl"/> | |
<c:url value="/email/fileupload" var="uploadUrl"/> |
Import Scripts
Based on the jQuery-File-Upload basic plugin guide, we need to import the following scripts: jquery.ui.widget.js, jquery.iframe-transport.js, and jquery.fileupload.js. The util.js contains a method for posting JSON objects. The remaining scripts are for the jQuery framework itself.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script type='text/javascript' src='<c:url value="/resources/js/jquery-1.6.4.min.js"/>'></script> | |
<script type='text/javascript' src='<c:url value="/resources/js/jquery-ui-1.8.16.custom.min.js"/>'></script> | |
<script type='text/javascript' src='<c:url value="/resources/js/util.js"/>'></script> | |
<script type='text/javascript' src='<c:url value="/resources/js/jquery-fileupload/vendor/jquery.ui.widget.js"/>'></script> | |
<script type='text/javascript' src='<c:url value="/resources/js/jquery-fileupload/jquery.iframe-transport.js"/>'></script> | |
<script type='text/javascript' src='<c:url value="/resources/js/jquery-fileupload/jquery.fileupload.js"/>'></script> |
Initialization Function
This function contains the following initialization steps:
- Beautify buttons
- Attach submit function
- Attach clear function
- Attach file upload function
- Initialize filelist data
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function init() { | |
$('input:button').button(); | |
$('#submit').button(); | |
$('#emailForm').submit(function(event) { | |
event.preventDefault(); | |
$.postJSON('${sendUrl}', { | |
senderName: $('#senderName').val(), | |
senderEmail: $('#senderEmail').val(), | |
ccEmail: $('#ccEmail').val(), | |
subject: $('#subject').val(), | |
body: $('#textBody').val(), | |
receiverName: $('#receiverName').val(), | |
receiverEmail: $('#receiverEmail').val(), | |
filename: getFilelist() | |
}, | |
function(result) { | |
if (result.success == true) { | |
dialog('Success', 'Email has been sent!'); | |
} else { | |
dialog('Failure', 'Email has not been sent!'); | |
} | |
}); | |
}); | |
$('#reset').click(function() { | |
clearForm(); | |
dialog('Success', 'Fields have been cleared!'); | |
}); | |
$('#upload').fileupload({ | |
dataType: 'json', | |
done: function (e, data) { | |
$.each(data.result, function (index, file) { | |
$('body').data('filelist').push(file); | |
$('#filename').append(formatFileDisplay(file)); | |
$('#attach').empty().append('Attach another file'); | |
}); | |
} | |
}); | |
// Technique borrowed from http://stackoverflow.com/questions/1944267/how-to-change-the-button-text-of-input-type-file | |
// http://stackoverflow.com/questions/210643/in-javascript-can-i-make-a-click-event-fire-programmatically-for-a-file-input | |
$("#attach").click(function () { | |
$("#upload").trigger('click'); | |
}); | |
$('body').data('filelist', new Array()); | |
} |
File Display Function
This is used for formatting filenames. The output is similar to the following: filename (256.50K)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function formatFileDisplay(file) { | |
var size = '<span style="font-style:italic">'+(file.size/1000).toFixed(2)+'K</span>'; | |
return file.name + ' ('+ size +')<br/>'; | |
} |
File List Function
This is used to retrieved the list of filenames. The output is comma-delimited, which is similar to the following: filename1.jpg,filename2.doc,filename3.txt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function getFilelist() { | |
var files = $('body').data('filelist'); | |
var filenames = ''; | |
for (var i=0; i<files.length; i<i++) { | |
var suffix = (i==files.length-1) ? '' : ','; | |
filenames += files[i].name + suffix; | |
} | |
return filenames; | |
} |
Dialog Function
This is a helper function for displaying dialog boxes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function dialog(title, text) { | |
$('#msgbox').text(text); | |
$('#msgbox').dialog( | |
{ title: title, | |
modal: true, | |
buttons: {"Ok": function() { | |
$(this).dialog("close");} | |
} | |
}); | |
} |
Clear Function
This clears the form of its contents.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function clearForm() { | |
$('#receiverName').val(''); | |
$('#receiverEmail').val(''); | |
$('#ccEmail').val(''); | |
$('#senderName').val(''); | |
$('#senderEmail').val(''); | |
$('#subject').val(''); | |
$('#textBody').val(''); | |
$('#filename').empty(); | |
$('#attach').empty().append('Attach a file'); | |
$('body').data('filelist', new Array()); | |
} |
Form
This is the form itself. Notice we've set the file input's opacity to zero to hide it and make it work under Safari and Opera (try removing the opacity and hide the file input via display:none to see an unwanted effect).
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<form id='emailForm'> | |
<fieldset> | |
<legend>New Email</legend> | |
<label for='receiverName'>To (name):</label><input type='text' id='receiverName'/><br/> | |
<label for='receiverEmail'>To (email)</label><input type='text' id='receiverEmail'/><br/> | |
<label for='ccEmail'>Cc (email):</label><input type='text' id='ccEmail'/><br/> | |
<label for='senderName'>From (name):</label><input type='text' id='senderName'/><br/> | |
<label for='senderEmail'>From (email):</label><input type='text' id='senderEmail'/><br/> | |
<label for='subject'>Subject:</label><input type='text' id='subject'/><br/> | |
<label for='textBody' style="display:break">Message</label> | |
<textarea name="textBody" id="textBody">Email message here</textarea><br/> | |
<span id='filename'></span><br/> | |
<a href='#' id='attach'>Attach a file</a><br/> | |
<input id="upload" type="file" name="file" data-url="${uploadUrl}" multiple style="opacity: 0; filter:alpha(opacity: 0);"><br/> | |
<input type='button' value='Reset' id='reset' /> | |
<input type='submit' value='Send' id='submit'/> | |
</fieldset> | |
</form> |
By setting the file input's opacity to 0, we have successfully hidden the input. But how do we access it now? Notice the "Add a file" link? We've attached a click trigger function on that link to fire up the file input. If we removed the opacity, here's what we will see:
Chrome 19.0.1084.56

Firefox 9.0.1

Internet Explorer 9.0.8112.16421

Browser Bugs
Even though the jQuery-File-Upload plugin has great cross-browser support, some browsers still behave erratically. Here's what I've discovered so far:Internet Explorer 9.0.8112.16421
- Does not upload file
- Does not upload message
Opera 11.60
- Attach link does not work if file input has display:none
- To make it work, set the opacity instead
Safari 5.1.2
- Attach link does not work if file input has display:none
- To make it work, set the opacity instead
0 komentar:
Post a Comment