Improve upload of attachments to messages
parent
1a900b05d9
commit
7369a82bab
4
NEWS
4
NEWS
|
@ -4,12 +4,14 @@
|
|||
New features
|
||||
- it's now possible to set a default reminder for calendar components
|
||||
using SOGoCalendarDefaultReminder
|
||||
- select multiple files to attach to a message or drag'n'drop files onto the
|
||||
mail editor; will also now display progress of uploads
|
||||
|
||||
Enhancements
|
||||
- we now automatically convert <img src=data...> into file attachments
|
||||
using CIDs. This prevents Outlook issues.
|
||||
- updated Finnish translation
|
||||
- XMLHttpRequest is now loaded conditionaly (< IE9)
|
||||
- XMLHttpRequest.js is now loaded conditionaly (< IE9)
|
||||
|
||||
Bug fixes
|
||||
-
|
||||
|
|
|
@ -15,13 +15,6 @@
|
|||
cssClass = "tbicon_addressbook";
|
||||
label = "Contacts";
|
||||
tooltip = "Select a recipient from an Address Book"; },
|
||||
{ link = "#";
|
||||
isSafe = NO;
|
||||
onclick = "return clickedEditorAttach(this)";
|
||||
image = "tb-compose-attach-flat-24x24.png";
|
||||
cssClass = "tbicon_attach single-window-not-conditional";
|
||||
label = "Attach";
|
||||
tooltip = "Include an attachment"; },
|
||||
{ link = "#";
|
||||
isSafe = NO;
|
||||
onclick = "return clickedEditorSave(this);";
|
||||
|
|
|
@ -56,6 +56,7 @@
|
|||
#import <SOGo/WOResourceManager+SOGo.h>
|
||||
#import <SOGoUI/UIxComponent.h>
|
||||
#import <Mailer/SOGoDraftObject.h>
|
||||
#import <Mailer/SOGoMailObject+Draft.h>
|
||||
#import <Mailer/SOGoMailFolder.h>
|
||||
#import <Mailer/SOGoMailAccount.h>
|
||||
#import <Mailer/SOGoMailAccounts.h>
|
||||
|
@ -63,6 +64,8 @@
|
|||
#import <Contacts/SOGoContactFolder.h>
|
||||
#import <Contacts/SOGoContactSourceFolder.h>
|
||||
|
||||
#import <UI/MailPartViewers/UIxMailSizeFormatter.h>
|
||||
|
||||
/*
|
||||
UIxMailEditor
|
||||
|
||||
|
@ -89,8 +92,9 @@
|
|||
id currentFolder;
|
||||
|
||||
/* these are for the inline attachment list */
|
||||
NSString *attachmentName;
|
||||
NSArray *attachmentNames;
|
||||
NSDictionary *attachment;
|
||||
NSArray *attachmentAttrs;
|
||||
NSString *currentAttachment;
|
||||
NSMutableArray *attachedFiles;
|
||||
}
|
||||
|
||||
|
@ -117,6 +121,9 @@ static NSArray *infoKeys = nil;
|
|||
priority = @"NORMAL";
|
||||
receipt = nil;
|
||||
currentFolder = nil;
|
||||
currentAttachment = nil;
|
||||
attachmentAttrs = nil;
|
||||
attachedFiles = nil;
|
||||
}
|
||||
|
||||
return self;
|
||||
|
@ -137,8 +144,9 @@ static NSArray *infoKeys = nil;
|
|||
[bcc release];
|
||||
[sourceUID release];
|
||||
[sourceFolder release];
|
||||
[attachmentName release];
|
||||
[attachmentNames release];
|
||||
[attachment release];
|
||||
[currentAttachment release];
|
||||
[attachmentAttrs release];
|
||||
[attachedFiles release];
|
||||
[currentFolder release];
|
||||
[super dealloc];
|
||||
|
@ -369,14 +377,19 @@ static NSArray *infoKeys = nil;
|
|||
return (([to count] + [cc count] + [bcc count]) > 0);
|
||||
}
|
||||
|
||||
- (void) setAttachmentName: (NSString *) newAttachmentName
|
||||
- (void) setAttachment: (NSDictionary *) newAttachment
|
||||
{
|
||||
ASSIGN (attachmentName, newAttachmentName);
|
||||
ASSIGN (attachment, newAttachment);
|
||||
}
|
||||
|
||||
- (NSString *) attachmentName
|
||||
- (NSFormatter *) sizeFormatter
|
||||
{
|
||||
return attachmentName;
|
||||
return [UIxMailSizeFormatter sharedMailSizeFormatter];
|
||||
}
|
||||
|
||||
- (NSDictionary *) attachment
|
||||
{
|
||||
return attachment;
|
||||
}
|
||||
|
||||
/* from addresses */
|
||||
|
@ -517,8 +530,8 @@ static NSArray *infoKeys = nil;
|
|||
|
||||
- (NSDictionary *) _scanAttachmentFilenamesInRequest: (id) httpBody
|
||||
{
|
||||
NSMutableDictionary *filenames;
|
||||
NSDictionary *attachment;
|
||||
NSMutableDictionary *files;
|
||||
NSDictionary *file;
|
||||
NSArray *parts;
|
||||
unsigned int count, max;
|
||||
NGMimeBodyPart *part;
|
||||
|
@ -527,112 +540,136 @@ static NSArray *infoKeys = nil;
|
|||
|
||||
parts = [httpBody parts];
|
||||
max = [parts count];
|
||||
filenames = [NSMutableDictionary dictionaryWithCapacity: max];
|
||||
files = [NSMutableDictionary dictionaryWithCapacity: max];
|
||||
|
||||
for (count = 0; count < max; count++)
|
||||
{
|
||||
part = [parts objectAtIndex: count];
|
||||
header = (NGMimeContentDispositionHeaderField *)
|
||||
[part headerForKey: @"content-disposition"];
|
||||
mimeType = [(NGMimeType *)
|
||||
[part headerForKey: @"content-type"] stringValue];
|
||||
filename = [self _fixedFilename: [header filename]];
|
||||
attachment = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
filename, @"filename",
|
||||
mimeType, @"mimetype", nil];
|
||||
[filenames setObject: attachment forKey: [header name]];
|
||||
}
|
||||
|
||||
return filenames;
|
||||
}
|
||||
|
||||
- (BOOL) _saveAttachments
|
||||
header = (NGMimeContentDispositionHeaderField *)[part headerForKey: @"content-disposition"];
|
||||
if ([[header name] hasPrefix: @"attachments"])
|
||||
{
|
||||
mimeType = [(NGMimeType *)[part headerForKey: @"content-type"] stringValue];
|
||||
filename = [self _fixedFilename: [header filename]];
|
||||
file = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
filename, @"filename",
|
||||
mimeType, @"mimetype",
|
||||
[part body], @"body",
|
||||
nil];
|
||||
[files setObject: file forKey: [NSString stringWithFormat: @"%@_%@", [header name], filename]];
|
||||
}
|
||||
}
|
||||
|
||||
return files;
|
||||
}
|
||||
|
||||
- (NSException *) _saveAttachments
|
||||
{
|
||||
NSException *error;
|
||||
WORequest *request;
|
||||
NSEnumerator *allKeys;
|
||||
NSString *key;
|
||||
BOOL success;
|
||||
NSDictionary *filenames;
|
||||
NSEnumerator *allAttachments;
|
||||
NSDictionary *attrs, *filenames;
|
||||
NGMimeType *mimeType;
|
||||
id httpBody;
|
||||
SOGoDraftObject *co;
|
||||
|
||||
success = YES;
|
||||
error = nil;
|
||||
request = [context request];
|
||||
|
||||
mimeType = [[request httpRequest] contentType];
|
||||
if ([[mimeType type] isEqualToString: @"multipart"])
|
||||
{
|
||||
httpBody = [[request httpRequest] body];
|
||||
filenames = [self _scanAttachmentFilenamesInRequest: httpBody];
|
||||
|
||||
co = [self clientObject];
|
||||
allKeys = [[request formValueKeys] objectEnumerator];
|
||||
while ((key = [allKeys nextObject]) && success)
|
||||
if ([key hasPrefix: @"attachment"])
|
||||
success
|
||||
= (![co saveAttachment: (NSData *) [request formValueForKey: key]
|
||||
withMetadata: [filenames objectForKey: key]]);
|
||||
|
||||
return success;
|
||||
allAttachments = [filenames objectEnumerator];
|
||||
while ((attrs = [allAttachments nextObject]) && !error)
|
||||
{
|
||||
error = [co saveAttachment: (NSData *) [attrs objectForKey: @"body"]
|
||||
withMetadata: attrs];
|
||||
// Keep the name of the last attachment saved
|
||||
ASSIGN(currentAttachment, [attrs objectForKey: @"filename"]);
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL) _saveFormInfo
|
||||
return error;
|
||||
}
|
||||
|
||||
- (NSException *) _saveFormInfo
|
||||
{
|
||||
NSDictionary *info;
|
||||
NSException *error;
|
||||
BOOL success;
|
||||
SOGoDraftObject *co;
|
||||
|
||||
co = [self clientObject];
|
||||
[co fetchInfo];
|
||||
|
||||
success = YES;
|
||||
|
||||
if ([self _saveAttachments])
|
||||
error = [self _saveAttachments];
|
||||
if (!error)
|
||||
{
|
||||
info = [self storeInfo];
|
||||
[co setHeaders: info];
|
||||
[co setIsHTML: isHTML];
|
||||
[co setText: (isHTML ? [NSString stringWithFormat: @"<html>%@</html>", text] : text)];;
|
||||
error = [co storeInfo];
|
||||
if (error)
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
- (id) failedToSaveFormResponse: (NSString *) msg
|
||||
{
|
||||
[self errorWithFormat: @"failed to store draft: %@", error];
|
||||
// TODO: improve error handling
|
||||
success = NO;
|
||||
}
|
||||
}
|
||||
else
|
||||
success = NO;
|
||||
NSDictionary *d;
|
||||
|
||||
// TODO: wrap content
|
||||
d = [NSDictionary dictionaryWithObjectsAndKeys: msg, @"textStatus", nil];
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
- (id) failedToSaveFormResponse
|
||||
{
|
||||
// TODO: improve error handling
|
||||
return [NSException exceptionWithHTTPStatus:500 /* server error */
|
||||
reason:@"failed to store draft object on server!"];
|
||||
return [self responseWithStatus: 500
|
||||
andString: [d jsonRepresentation]];
|
||||
}
|
||||
|
||||
/* attachment helper */
|
||||
|
||||
- (NSArray *) attachmentNames
|
||||
- (NSArray *) attachmentAttrs
|
||||
{
|
||||
NSArray *a;
|
||||
SOGoDraftObject *co;
|
||||
SOGoMailObject *mail;
|
||||
|
||||
if (!attachmentNames)
|
||||
co = [self clientObject];
|
||||
if (!attachmentAttrs || ![co imap4URL])
|
||||
{
|
||||
a = [[self clientObject] fetchAttachmentNames];
|
||||
ASSIGN (attachmentNames,
|
||||
[a sortedArrayUsingSelector: @selector (compare:)]);
|
||||
[co fetchInfo];
|
||||
if ([co IMAP4ID] > -1)
|
||||
{
|
||||
mail = [[[SOGoMailObject alloc] initWithImap4URL: [co imap4URL] inContainer: [co container]] autorelease];
|
||||
a = [mail fetchFileAttachmentKeys];
|
||||
ASSIGN (attachmentAttrs, a);
|
||||
}
|
||||
}
|
||||
|
||||
return attachmentNames;
|
||||
if (currentAttachment)
|
||||
{
|
||||
// When currentAttachment is defined, only return the attributes of the last
|
||||
// attachment saved
|
||||
NSEnumerator *allAttachments;
|
||||
NSDictionary* attrs;
|
||||
|
||||
allAttachments = [attachmentAttrs objectEnumerator];
|
||||
while ((attrs = [allAttachments nextObject]))
|
||||
{
|
||||
if ([[attrs objectForKey: @"filename"] isEqualToString: currentAttachment])
|
||||
{
|
||||
return [NSArray arrayWithObject: attrs];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return attachmentAttrs;
|
||||
}
|
||||
|
||||
- (BOOL) hasAttachments
|
||||
{
|
||||
return [[self attachmentNames] count] > 0 ? YES : NO;
|
||||
return [[self attachmentAttrs] count] > 0 ? YES : NO;
|
||||
}
|
||||
|
||||
- (NSString *) uid
|
||||
|
@ -658,14 +695,20 @@ static NSArray *infoKeys = nil;
|
|||
{
|
||||
id result;
|
||||
|
||||
if ([self _saveFormInfo])
|
||||
result = [self _saveFormInfo];
|
||||
if (!result)
|
||||
{
|
||||
result = [[self clientObject] save];
|
||||
}
|
||||
if (!result)
|
||||
result = [self responseWith204];
|
||||
{
|
||||
attachmentAttrs = nil;
|
||||
NSArray *attrs = [self attachmentAttrs];
|
||||
result = [self responseWithStatus: 200
|
||||
andString: [attrs jsonRepresentation]];
|
||||
}
|
||||
else
|
||||
result = [self failedToSaveFormResponse];
|
||||
result = [self failedToSaveFormResponse: [result reason]];
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -740,10 +783,11 @@ static NSArray *infoKeys = nil;
|
|||
error = [self validateForSend];
|
||||
if (!error)
|
||||
{
|
||||
if ([self _saveFormInfo])
|
||||
error = [self _saveFormInfo];
|
||||
if (!error)
|
||||
error = [co sendMail];
|
||||
else
|
||||
error = [self failedToSaveFormResponse];
|
||||
error = [self failedToSaveFormResponse: [error reason]];
|
||||
}
|
||||
|
||||
if (error)
|
||||
|
|
|
@ -11,26 +11,18 @@
|
|||
title="panelTitle"
|
||||
const:popup="YES"
|
||||
const:userDefaultsKeys="SOGoMailComposeMessageType,SOGoMailReplyPlacement,SOGoMailSignature"
|
||||
const:jsFiles="UIxMailToSelection.js,ckeditor/ckeditor.js,SOGoAutoCompletion.js,ContactsUI.js">
|
||||
const:jsFiles="UIxMailToSelection.js,ckeditor/ckeditor.js,SOGoAutoCompletion.js,ContactsUI.js,jquery-ui.js,jquery.fileupload.js,jquery.iframe-transport.js"
|
||||
const:cssFiles="jquery.fileupload.css">
|
||||
<script type="text/javascript">
|
||||
var mailIsReply = <var:string value="isMailReply"/>;
|
||||
var sourceUID = <var:string value="sourceUID"/>;
|
||||
var sourceFolder = '<var:string value="sourceFolder" const:escapeHTML="NO"/>';
|
||||
var localeCode = '<var:string value="localeCode"/>';
|
||||
</script>
|
||||
|
||||
<div class="popupMenu" id="contactsMenu">
|
||||
<ul><!-- space --></ul>
|
||||
</div>
|
||||
<div class="menu" id="attachmentsMenu">
|
||||
<ul>
|
||||
<li><var:string label:value="Open"/></li>
|
||||
<li><var:string label:value="Delete" /></li>
|
||||
<li><var:string label:value="Select All" /></li>
|
||||
<li><!-- separator --></li>
|
||||
<li><var:string label:value="Attach File(s)..." /></li>
|
||||
<li><var:string label:value="Attach Web Page..." /></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="menu" id="optionsMenu">
|
||||
<ul class="choiceMenu">
|
||||
|
@ -101,20 +93,11 @@
|
|||
</div>
|
||||
|
||||
<div id="rightPanel">
|
||||
<form const:href="" name="pageform" enctype="multipart/form-data" autocomplete="off">
|
||||
<form href="save" name="pageform" enctype="multipart/form-data" autocomplete="off">
|
||||
<input type="hidden" name="priority" id="priority" var:value="priority"/>
|
||||
<input type="hidden" name="receipt" id="receipt" var:value="receipt"/>
|
||||
<input type="hidden" name="isHTML" id="isHTML" var:value="isHTML"/>
|
||||
|
||||
<div id="attachmentsArea">
|
||||
<var:string label:value="Attachments:" />
|
||||
<ul id="attachments">
|
||||
<var:foreach list="attachmentNames" item="attachmentName"
|
||||
><li var:title="attachmentName"><img rsrc:src="attachment.gif"
|
||||
/><var:string value="attachmentName"
|
||||
/></li></var:foreach>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="headerArea">
|
||||
<span class="headerField" const:id="fromField"><var:string label:value="From" />:</span>
|
||||
<var:popup const:name="from" const:id="fromSelect"
|
||||
|
@ -126,19 +109,23 @@
|
|||
<var:component className="UIxMailToSelection"
|
||||
to="to" cc="cc" bcc="bcc" />
|
||||
</div>
|
||||
<div class="addressListElement" id="subjectRow"
|
||||
><span class="headerField"><var:string label:value="Subject"
|
||||
/>:</span
|
||||
>
|
||||
<input name="subject"
|
||||
type="text"
|
||||
class="textField"
|
||||
var:value="subject"
|
||||
/></div>
|
||||
<!-- separator line --><hr class="fieldSeparator"/>
|
||||
<div id="subjectRow">
|
||||
<span class="headerField"><var:string label:value="Subject"/>:</span>
|
||||
<input name="subject" type="text" class="textField" var:value="subject"/>
|
||||
</div>
|
||||
<div id="fileupload">
|
||||
<ul id="attachments">
|
||||
<li class="attachButton"><span class="button fileinput-button"><span><img rsrc:src="title_attachment_14x14.png" /> <var:string label:value="Attach"/></span><input id="fileUpload" type="file" name="attachments" const:multiple="multiple"/></span></li>
|
||||
<var:foreach list="attachmentAttrs" item="attachment"
|
||||
><li class="progressDone" var:data-filename="attachment.filename">
|
||||
<i class="icon-attachment"><!-- icon --></i><a var:href="attachment.url" target="_new"><var:string value="attachment.filename"/></a><span class="muted">(<var:string value="attachment.size" formatter="sizeFormatter" />)</span>
|
||||
</li></var:foreach>
|
||||
</ul>
|
||||
</div>
|
||||
</div><!-- #headerArea -->
|
||||
<textarea id="text" name="text" rows="30" var:value="text"></textarea>
|
||||
<!-- img rsrc:src="tbird_073_compose.png" alt="screenshot" / -->
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div id="dropZone" style="display: none;"><!-- dropzone --></div>
|
||||
</var:component>
|
||||
|
|
|
@ -104,24 +104,6 @@ div#headerArea div.addressList
|
|||
overflow: auto;
|
||||
overflow-x: hidden; }
|
||||
|
||||
div#attachmentsArea
|
||||
{ display: none;
|
||||
float: right;
|
||||
width: 200px;
|
||||
padding: 2px 5px 0;
|
||||
margin: auto;
|
||||
border-left: 1px solid #888; }
|
||||
|
||||
hr.fieldSeparator
|
||||
{ background-color: #848284;
|
||||
border: 0;
|
||||
clear: both;
|
||||
color: #848284;
|
||||
height: 1px;
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
width: 100%; }
|
||||
|
||||
input.currentAttachment
|
||||
{ position: fixed;
|
||||
top: 1em;
|
||||
|
@ -131,30 +113,42 @@ input.attachment
|
|||
{ position: absolute;
|
||||
left: -1000px; }
|
||||
|
||||
div#compose_attachments_list
|
||||
{ background-color: #ffffff;
|
||||
margin-left: 0px;
|
||||
padding: 2px;
|
||||
border-bottom: 1px solid #fff;
|
||||
border-right: 1px solid #fff;
|
||||
border-top: 2px solid #222;
|
||||
border-left: 2px solid #222;
|
||||
-moz-border-top-colors: #9c9a94 #000 transparent;
|
||||
-moz-border-left-colors: #9c9a94 #000 transparent; }
|
||||
#dropZone
|
||||
{ position: absolute;
|
||||
background: #000 url('upload_document.png') no-repeat center center;
|
||||
opacity: 0.6;
|
||||
border: 4px dashed #fff;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
top: 0px;
|
||||
bottom: 0px;
|
||||
z-index: 999; }
|
||||
|
||||
#dropZone div
|
||||
{ position: absolute;
|
||||
color: #fff;
|
||||
font-size: 18px;
|
||||
height: 100px;
|
||||
width: 300px;
|
||||
margin: 60px 0 0 -150px;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#fileupload {
|
||||
margin-top: 5px;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.button.fileinput-button
|
||||
{ display: inline-block;
|
||||
float: none; }
|
||||
|
||||
UL#attachments
|
||||
{ cursor: default;
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
height: 100%;
|
||||
border-bottom: 1px solid #eee;
|
||||
border-right: 1px solid #eee;
|
||||
border-top: 1px solid #222;
|
||||
border-left: 1px solid #222;
|
||||
background-color: #CCDDEC;
|
||||
background-image: url("input_bg.gif");
|
||||
-moz-border-top-colors: #9c9a94 #000 transparent;
|
||||
-moz-border-left-colors: #9c9a94 #000 transparent;
|
||||
list-style-type: none;
|
||||
list-style-image: none;
|
||||
overflow: auto;
|
||||
|
@ -163,11 +157,44 @@ UL#attachments
|
|||
-khtml-user-select: none; }
|
||||
|
||||
UL#attachments LI
|
||||
{ float: left; }
|
||||
|
||||
UL#attachments LI[data-filename]
|
||||
{ white-space: nowrap;
|
||||
padding-bottom: 1px; }
|
||||
line-height: 18px;
|
||||
margin: 3px 6px; }
|
||||
|
||||
UL#attachments LI[data-filename] SPAN
|
||||
{ margin-left: 5px; }
|
||||
|
||||
UL#attachments LI[data-filename] A,
|
||||
UL#attachments LI[data-filename] SPAN
|
||||
{ padding-left: 2px;
|
||||
vertical-align: top; }
|
||||
|
||||
UL#attachments LI IMG
|
||||
{ vertical-align: bottom; }
|
||||
{ vertical-align: top; }
|
||||
|
||||
UL#attachments .icon-attachment
|
||||
{ background: url('attachment.png') no-repeat top left;
|
||||
display: inline-block;
|
||||
width: 16px;
|
||||
height: 16px; }
|
||||
UL#attachments .progress0 .icon-attachment
|
||||
{ background-position: 0px 0px; }
|
||||
UL#attachments .progress1 .icon-attachment
|
||||
{ background-position: -16px 0px; }
|
||||
UL#attachments .progress2 .icon-attachment
|
||||
{ background-position: -32px 0px; }
|
||||
UL#attachments .progress3 .icon-attachment
|
||||
{ background-position: -48px 0px; }
|
||||
UL#attachments .progress4 .icon-attachment
|
||||
{ background-position: -64px 0px; }
|
||||
UL#attachments .progressDone .icon-attachment
|
||||
{ background-position: -80px 0px; }
|
||||
UL#attachments .progressDone .icon-attachment:hover
|
||||
{ background-position: -96px 0px;
|
||||
cursor: pointer; }
|
||||
|
||||
#pageContent TEXTAREA
|
||||
{ width: 99%; }
|
||||
|
@ -176,6 +203,9 @@ TEXTAREA#text
|
|||
{ display: none;
|
||||
background: #fff; }
|
||||
|
||||
#cke_text
|
||||
{ clear: both; }
|
||||
|
||||
/* Contacts search pane */
|
||||
|
||||
DIV#contactsSearch
|
||||
|
|
|
@ -134,13 +134,10 @@ function onValidateDone(onSuccess) {
|
|||
var safetyNet = createElement("div", "javascriptSafetyNet");
|
||||
$('pageContent').insert({top: safetyNet});
|
||||
|
||||
var input = currentAttachmentInput();
|
||||
if (input)
|
||||
input.parentNode.removeChild(input);
|
||||
|
||||
if (!document.busyAnim) {
|
||||
var toolbar = document.getElementById("toolbar");
|
||||
if (!document.busyAnim)
|
||||
document.busyAnim = startAnimation(toolbar);
|
||||
}
|
||||
|
||||
var lastRow = $("lastRow");
|
||||
lastRow.down("select").name = "popup_last";
|
||||
|
@ -149,8 +146,6 @@ function onValidateDone(onSuccess) {
|
|||
|
||||
document.pageform.action = "send";
|
||||
|
||||
AIM.submit($(document.pageform), {'onComplete' : onPostComplete});
|
||||
|
||||
if (typeof onSuccess == 'function')
|
||||
onSuccess();
|
||||
|
||||
|
@ -159,7 +154,8 @@ function onValidateDone(onSuccess) {
|
|||
return true;
|
||||
}
|
||||
|
||||
function onPostComplete(response) {
|
||||
function onPostComplete(http) {
|
||||
var response = http.responseText;
|
||||
if (response && response.length > 0) {
|
||||
var jsonResponse = response.evalJSON();
|
||||
if (jsonResponse["status"] == "success") {
|
||||
|
@ -192,93 +188,67 @@ function onPostComplete(response) {
|
|||
|
||||
function clickedEditorSend() {
|
||||
onValidate(function() {
|
||||
document.pageform.submit();
|
||||
triggerAjaxRequest(document.pageform.action,
|
||||
onPostComplete,
|
||||
null,
|
||||
Form.serialize(document.pageform), // excludes the file input
|
||||
{ "Content-type": "application/x-www-form-urlencoded" });
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function currentAttachmentInput() {
|
||||
var input = null;
|
||||
|
||||
var inputs = $("attachmentsArea").getElementsByTagName("input");
|
||||
var i = 0;
|
||||
while (!input && i < inputs.length)
|
||||
if ($(inputs[i]).hasClassName("currentAttachment"))
|
||||
input = inputs[i];
|
||||
else
|
||||
i++;
|
||||
|
||||
return input;
|
||||
function formatBytes(bytes, si) {
|
||||
var thresh = si ? 1000 : 1024;
|
||||
if (bytes < thresh) return bytes + ' B';
|
||||
var units = si ? ['KiB','MiB','GiB'] : ['KB','MB','GB'];
|
||||
var u = -1;
|
||||
do {
|
||||
bytes /= thresh;
|
||||
++u;
|
||||
} while (bytes >= thresh);
|
||||
return bytes.toFixed(1) + ' ' + units[u];
|
||||
}
|
||||
|
||||
function clickedEditorAttach() {
|
||||
var input = currentAttachmentInput();
|
||||
if (!input) {
|
||||
var area = $("attachmentsArea");
|
||||
function createAttachment(file) {
|
||||
var list = $('attachments');
|
||||
var attachment;
|
||||
if (list.select('[data-filename="'+file.name+'"]').length == 0) {
|
||||
// File is not already uploaded
|
||||
var attachment = createElement('li', null, ['muted progress0'], null, { 'data-filename': file.name }, list);
|
||||
attachment.appendChild(new Element('i', { 'class': 'icon-attachment' }));
|
||||
var a = createElement('a', null, null, null, {'href': '#', 'target': '_new' }, attachment);
|
||||
|
||||
if (!area.style.display) {
|
||||
area.setStyle({ display: "block" });
|
||||
onWindowResize(null);
|
||||
}
|
||||
var inputs = area.getElementsByTagName("input");
|
||||
var attachmentName = "attachment" + attachmentCount;
|
||||
var newAttachment = createElement("input", attachmentName,
|
||||
"currentAttachment", null,
|
||||
{ type: "file",
|
||||
name: attachmentName },
|
||||
area);
|
||||
attachmentCount++;
|
||||
newAttachment.observe("change",
|
||||
onAttachmentChange.bindAsEventListener(newAttachment));
|
||||
a.appendChild(document.createTextNode(file.name));
|
||||
if (file.size)
|
||||
attachment.appendChild(new Element('span', { 'class': 'muted' }).update('(' + formatBytes(file.size, true) + ')'));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function onAttachmentChange(event) {
|
||||
if (this.value == "")
|
||||
this.parentNode.removeChild(this);
|
||||
else {
|
||||
this.addClassName("attachment");
|
||||
this.removeClassName("currentAttachment");
|
||||
var list = $("attachments");
|
||||
createAttachment(this, list);
|
||||
clickedEditorAttach(null);
|
||||
}
|
||||
}
|
||||
|
||||
function createAttachment(node, list) {
|
||||
var attachment = createElement("li", null, null, { node: node }, null, list);
|
||||
createElement("img", null, null, { src: ResourcesURL + "/attachment.gif" },
|
||||
null, attachment);
|
||||
|
||||
var filename = node.value;
|
||||
var separator;
|
||||
if (navigator.appVersion.indexOf("Windows") > -1)
|
||||
separator = "\\";
|
||||
else
|
||||
separator = "/";
|
||||
var fileArray = filename.split(separator);
|
||||
var attachmentName = document.createTextNode(fileArray[fileArray.length-1]);
|
||||
attachment.appendChild(attachmentName);
|
||||
attachment.writeAttribute("title", fileArray[fileArray.length-1]);
|
||||
return attachment;
|
||||
}
|
||||
|
||||
function clickedEditorSave() {
|
||||
var input = currentAttachmentInput();
|
||||
if (input)
|
||||
input.parentNode.removeChild(input);
|
||||
|
||||
var lastRow = $("lastRow");
|
||||
lastRow.down("select").name = "popup_last";
|
||||
|
||||
window.shouldPreserve = true;
|
||||
document.pageform.action = "save";
|
||||
document.pageform.submit();
|
||||
|
||||
triggerAjaxRequest(document.pageform.action, function (http) {
|
||||
if (http.readyState == 4) {
|
||||
if (http.status == 200) {
|
||||
if (window.opener && window.opener.open && !window.opener.closed)
|
||||
window.opener.refreshFolderByType('draft');
|
||||
}
|
||||
else {
|
||||
var response = http.responseText.evalJSON(true);
|
||||
showAlertDialog("Error while saving the draft: " + response.textStatus);
|
||||
}
|
||||
}
|
||||
},
|
||||
null,
|
||||
Form.serialize(document.pageform), // excludes the file input
|
||||
{ "Content-type": "application/x-www-form-urlencoded" });
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -301,10 +271,6 @@ function onTextFocus(event) {
|
|||
}
|
||||
MailEditor.textFirstFocus = false;
|
||||
}
|
||||
|
||||
var input = currentAttachmentInput();
|
||||
if (input)
|
||||
input.parentNode.removeChild(input);
|
||||
}
|
||||
|
||||
function onTextKeyDown(event) {
|
||||
|
@ -397,7 +363,6 @@ function onHTMLFocus(event) {
|
|||
|
||||
function initAddresses() {
|
||||
var addressList = $("addressList");
|
||||
var i = 1;
|
||||
addressList.select("input.textField").each(function (input) {
|
||||
if (!input.readAttribute("readonly")) {
|
||||
input.addInterface(SOGoAutoCompletionInterface);
|
||||
|
@ -424,23 +389,84 @@ function configureDragHandle() {
|
|||
}
|
||||
}
|
||||
|
||||
function configureAttachments() {
|
||||
var list = $("attachments");
|
||||
|
||||
if (!list) return;
|
||||
|
||||
list.on('click', 'a', function (event, element) {
|
||||
if (!element.up('li').hasClassName('progressDone'))
|
||||
return false;
|
||||
});
|
||||
|
||||
list.on('click', 'i.icon-attachment', function (event, element) {
|
||||
var item = element.up('li');
|
||||
if (item.hasClassName('progressDone')) {
|
||||
var filename = item.readAttribute('data-filename');
|
||||
var url = "" + window.location;
|
||||
var parts = url.split("/");
|
||||
parts[parts.length-1] = "deleteAttachment?filename=" + encodeURIComponent(filename);
|
||||
url = parts.join("/");
|
||||
triggerAjaxRequest(url, attachmentDeleteCallback, item);
|
||||
}
|
||||
});
|
||||
|
||||
var dropzone = jQuery('#dropZone');
|
||||
jQuery('#fileUpload').fileupload({
|
||||
// With singleFileUploads option enabled, the 'add' and 'done' (or 'fail') callbacks
|
||||
// are called once for each file in the selection for XHR file uploads
|
||||
singleFileUploads: true,
|
||||
dataType: 'json',
|
||||
add: function (e, data) {
|
||||
var file = data.files[0];
|
||||
var attachment = createAttachment(file);
|
||||
if (attachment) {
|
||||
file.attachment = attachment;
|
||||
data.submit();
|
||||
}
|
||||
if (dropzone.is(":visible"))
|
||||
dropzone.fadeOut('fast');
|
||||
},
|
||||
done: function (e, data) {
|
||||
var attachment = data.files[0].attachment;
|
||||
var attrs = data.result[data.result.length-1];
|
||||
attachment.className = 'progressDone';
|
||||
attachment.down('a').setAttribute('href', attrs.url);
|
||||
if (window.opener && window.opener.open && !window.opener.closed)
|
||||
window.opener.refreshFolderByType('draft');
|
||||
},
|
||||
fail: function (e, data) {
|
||||
var attachment = data.files[0].attachment;
|
||||
var filename = data.files[0].name;
|
||||
var response = data.xhr().response.evalJSON();
|
||||
showAlertDialog("Error while uploading the file " + filename + ": " + response.textStatus);
|
||||
attachment.remove();
|
||||
},
|
||||
dragover: function (e, data) {
|
||||
if (!dropzone.is(":visible"))
|
||||
dropzone.show();
|
||||
},
|
||||
progress: function (e, data) {
|
||||
var progress = parseInt(data.loaded / data.total * 4, 10);
|
||||
var attachment = data.files[0].attachment;
|
||||
attachment.className = 'muted progress' + progress;
|
||||
}
|
||||
});
|
||||
|
||||
dropzone.on('dragleave', function (e) {
|
||||
dropzone.fadeOut('fast');
|
||||
});
|
||||
}
|
||||
|
||||
function initMailEditor() {
|
||||
if (composeMode != "html" && $("text"))
|
||||
$("text").style.display = "block";
|
||||
|
||||
var list = $("attachments");
|
||||
if (!list) return;
|
||||
list.multiselect = true;
|
||||
list.on("click", onRowClick);
|
||||
list.attachMenu("attachmentsMenu");
|
||||
var elements = $(list).childNodesWithTag("li");
|
||||
if (elements.length > 0)
|
||||
$("attachmentsArea").setStyle({ display: "block" });
|
||||
|
||||
var textarea = $("text");
|
||||
configureAttachments();
|
||||
|
||||
initAddresses();
|
||||
|
||||
var textarea = $("text");
|
||||
var focusField = textarea;
|
||||
if (!mailIsReply) {
|
||||
focusField = $("addr_0");
|
||||
|
@ -546,10 +572,6 @@ function onMenuCheckReturnReceipt(event) {
|
|||
|
||||
function getMenus() {
|
||||
return {
|
||||
"attachmentsMenu": [ null, onRemoveAttachments,
|
||||
onSelectAllAttachments,
|
||||
"-",
|
||||
clickedEditorAttach, null],
|
||||
"optionsMenu": [ onMenuCheckReturnReceipt,
|
||||
"-",
|
||||
"priorityMenu" ],
|
||||
|
@ -561,27 +583,6 @@ function getMenus() {
|
|||
};
|
||||
}
|
||||
|
||||
function onRemoveAttachments() {
|
||||
var list = $("attachments");
|
||||
var nodes = list.getSelectedNodes();
|
||||
for (var i = nodes.length-1; i > -1; i--) {
|
||||
var input = $(nodes[i]).node;
|
||||
if (input) {
|
||||
input.parentNode.removeChild(input);
|
||||
list.removeChild(nodes[i]);
|
||||
}
|
||||
else {
|
||||
var filename = nodes[i].title;
|
||||
var url = "" + window.location;
|
||||
var parts = url.split("/");
|
||||
parts[parts.length-1] = "deleteAttachment?filename=" + encodeURIComponent(filename);
|
||||
url = parts.join("/");
|
||||
triggerAjaxRequest(url, attachmentDeleteCallback,
|
||||
nodes[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function attachmentDeleteCallback(http) {
|
||||
if (http.readyState == 4) {
|
||||
if (isHttpStatus204(http.status)) {
|
||||
|
@ -623,10 +624,6 @@ function onMenuSetPriority(event) {
|
|||
priorityInput.value = priority;
|
||||
}
|
||||
|
||||
function onSelectAllAttachments() {
|
||||
$("attachments").selectAll();
|
||||
}
|
||||
|
||||
function onSelectOptions(event) {
|
||||
if (event.button == 0 || (isWebKit() && event.button == 1)) {
|
||||
var node = getTarget(event);
|
||||
|
@ -645,39 +642,21 @@ function onWindowResize(event) {
|
|||
var headerarea = $("headerArea");
|
||||
var totalwidth = $("rightPanel").getWidth();
|
||||
|
||||
var attachmentsarea = $("attachmentsArea");
|
||||
var attachmentswidth = 0;
|
||||
var subjectfield = headerarea.down("div#subjectRow span.headerField");
|
||||
var subjectinput = headerarea.down("div#subjectRow input.textField");
|
||||
if (attachmentsarea.style.display) {
|
||||
// Resize attachments list
|
||||
attachmentswidth = attachmentsarea.getWidth();
|
||||
fromfield = $(document).getElementsByClassName('headerField', headerarea)[0];
|
||||
var height = headerarea.getHeight() - fromfield.getHeight() - subjectfield.getHeight() - 10;
|
||||
if (Prototype.Browser.IE)
|
||||
$("attachments").setStyle({ height: (height - 13) + 'px' });
|
||||
else
|
||||
$("attachments").setStyle({ height: height + 'px' });
|
||||
}
|
||||
|
||||
// Resize subject field
|
||||
subjectinput.setStyle({ width: (totalwidth
|
||||
- $(subjectfield).getWidth()
|
||||
- attachmentswidth
|
||||
- 17) + 'px' });
|
||||
// Resize from field
|
||||
$("fromSelect").setStyle({ width: (totalwidth
|
||||
- $("fromField").getWidth()
|
||||
- attachmentswidth
|
||||
- 15) + 'px' });
|
||||
|
||||
// Resize address fields
|
||||
var addresslist = $('addressList');
|
||||
addresslist.setStyle({ width: (totalwidth - attachmentswidth - 10) + 'px' });
|
||||
|
||||
// Set textarea position
|
||||
var hr = headerarea.select("hr").first();
|
||||
textarea.setStyle({ 'top': hr.offsetTop + 'px' });
|
||||
// var addresslist = $('addressList');
|
||||
// addresslist.setStyle({ width: (totalwidth - 10) + 'px' });
|
||||
|
||||
// Resize the textarea (message content)
|
||||
var offsetTop = $('rightPanel').offsetTop + headerarea.getHeight();
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 1.8 KiB |
|
@ -714,7 +714,7 @@ DIV, TEXTAREA, INPUT, SELECT
|
|||
font-size: 8pt;
|
||||
font-size: inherit; }
|
||||
|
||||
INPUT[type="text"], INPUT[type="password"], INPUT[type="file"],
|
||||
INPUT[type="text"], INPUT[type="password"],
|
||||
TEXTAREA
|
||||
{ border-top: 1px solid #909090;
|
||||
border-left: 1px solid #909090;
|
||||
|
@ -730,7 +730,7 @@ TEXTAREA[disabled], TEXTAREA[readonly]
|
|||
border-color: #ccc;
|
||||
color: #9ABCD8; }
|
||||
|
||||
INPUT[type="text"], INPUT[type="password"], INPUT[type="file"], TEXTAREA
|
||||
INPUT[type="text"], INPUT[type="password"], TEXTAREA
|
||||
{ background: url("input_bg.gif"); }
|
||||
|
||||
TEXTAREA
|
||||
|
@ -788,7 +788,7 @@ INPUT[name="search"]
|
|||
* Avoid using DIVS as buttons, they're only helpful when they have multiple
|
||||
* listeners for "onclick"
|
||||
*/
|
||||
A.button {
|
||||
.button, a.button {
|
||||
padding: 0px 0.5em;
|
||||
background: transparent url('btn_a_bg.png') no-repeat scroll top right;
|
||||
display: block;
|
||||
|
@ -801,28 +801,30 @@ A.button {
|
|||
cursor: pointer;
|
||||
}
|
||||
|
||||
A.button SPAN {
|
||||
.button SPAN {
|
||||
background: transparent url('btn_span_bg.png') no-repeat;
|
||||
display: block;
|
||||
line-height: 13px;
|
||||
height: 13px;
|
||||
padding: 5px 2px 5px 5px;
|
||||
cursor: pointer;
|
||||
min-width: 70px;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
A.button.actionButton SPAN
|
||||
.button.actionButton SPAN
|
||||
{ font-weight: bold; }
|
||||
|
||||
A.button:active SPAN
|
||||
.button:active SPAN
|
||||
{ background-position: bottom left;
|
||||
padding: 6px 2px 4px 5px; }
|
||||
|
||||
A.disabled.button,
|
||||
A.disabled.button:active,
|
||||
A.disabled.button SPAN
|
||||
.disabled.button,
|
||||
.disabled.button:active,
|
||||
.disabled.button SPAN
|
||||
{ color: #999; }
|
||||
|
||||
A.disabled.button:active SPAN
|
||||
.disabled.button:active SPAN
|
||||
{ background-position: top left;
|
||||
padding: 5px 2px 5px 5px; }
|
||||
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
@charset "UTF-8";
|
||||
/*
|
||||
* jQuery File Upload Plugin CSS 1.3.0
|
||||
* https://github.com/blueimp/jQuery-File-Upload
|
||||
*
|
||||
* Copyright 2013, Sebastian Tschan
|
||||
* https://blueimp.net
|
||||
*
|
||||
* Licensed under the MIT license:
|
||||
* http://www.opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
.fileinput-button {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
.fileinput-button input {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
margin: 0;
|
||||
opacity: 0;
|
||||
-ms-filter: 'alpha(opacity=0)';
|
||||
font-size: 200px;
|
||||
direction: ltr;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* Fixes for IE < 8 */
|
||||
@media screen\9 {
|
||||
.fileinput-button input {
|
||||
filter: alpha(opacity=0);
|
||||
font-size: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,210 @@
|
|||
/*
|
||||
* jQuery Iframe Transport Plugin 1.8.1
|
||||
* https://github.com/blueimp/jQuery-File-Upload
|
||||
*
|
||||
* Copyright 2011, Sebastian Tschan
|
||||
* https://blueimp.net
|
||||
*
|
||||
* Licensed under the MIT license:
|
||||
* http://www.opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
/*jslint unparam: true, nomen: true */
|
||||
/*global define, window, document */
|
||||
|
||||
(function (factory) {
|
||||
'use strict';
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// Register as an anonymous AMD module:
|
||||
define(['jquery'], factory);
|
||||
} else {
|
||||
// Browser globals:
|
||||
factory(window.jQuery);
|
||||
}
|
||||
}(function ($) {
|
||||
'use strict';
|
||||
|
||||
// Helper variable to create unique names for the transport iframes:
|
||||
var counter = 0;
|
||||
|
||||
// The iframe transport accepts four additional options:
|
||||
// options.fileInput: a jQuery collection of file input fields
|
||||
// options.paramName: the parameter name for the file form data,
|
||||
// overrides the name property of the file input field(s),
|
||||
// can be a string or an array of strings.
|
||||
// options.formData: an array of objects with name and value properties,
|
||||
// equivalent to the return data of .serializeArray(), e.g.:
|
||||
// [{name: 'a', value: 1}, {name: 'b', value: 2}]
|
||||
// options.initialIframeSrc: the URL of the initial iframe src,
|
||||
// by default set to "javascript:false;"
|
||||
$.ajaxTransport('iframe', function (options) {
|
||||
if (options.async) {
|
||||
// javascript:false as initial iframe src
|
||||
// prevents warning popups on HTTPS in IE6:
|
||||
/*jshint scripturl: true */
|
||||
var initialIframeSrc = options.initialIframeSrc || 'javascript:false;',
|
||||
/*jshint scripturl: false */
|
||||
form,
|
||||
iframe,
|
||||
addParamChar;
|
||||
return {
|
||||
send: function (_, completeCallback) {
|
||||
form = $('<form style="display:none;"></form>');
|
||||
form.attr('accept-charset', options.formAcceptCharset);
|
||||
addParamChar = /\?/.test(options.url) ? '&' : '?';
|
||||
// XDomainRequest only supports GET and POST:
|
||||
if (options.type === 'DELETE') {
|
||||
options.url = options.url + addParamChar + '_method=DELETE';
|
||||
options.type = 'POST';
|
||||
} else if (options.type === 'PUT') {
|
||||
options.url = options.url + addParamChar + '_method=PUT';
|
||||
options.type = 'POST';
|
||||
} else if (options.type === 'PATCH') {
|
||||
options.url = options.url + addParamChar + '_method=PATCH';
|
||||
options.type = 'POST';
|
||||
}
|
||||
// IE versions below IE8 cannot set the name property of
|
||||
// elements that have already been added to the DOM,
|
||||
// so we set the name along with the iframe HTML markup:
|
||||
counter += 1;
|
||||
iframe = $(
|
||||
'<iframe src="' + initialIframeSrc +
|
||||
'" name="iframe-transport-' + counter + '"></iframe>'
|
||||
).bind('load', function () {
|
||||
var fileInputClones,
|
||||
paramNames = $.isArray(options.paramName) ?
|
||||
options.paramName : [options.paramName];
|
||||
iframe
|
||||
.unbind('load')
|
||||
.bind('load', function () {
|
||||
var response;
|
||||
// Wrap in a try/catch block to catch exceptions thrown
|
||||
// when trying to access cross-domain iframe contents:
|
||||
try {
|
||||
response = iframe.contents();
|
||||
// Google Chrome and Firefox do not throw an
|
||||
// exception when calling iframe.contents() on
|
||||
// cross-domain requests, so we unify the response:
|
||||
if (!response.length || !response[0].firstChild) {
|
||||
throw new Error();
|
||||
}
|
||||
} catch (e) {
|
||||
response = undefined;
|
||||
}
|
||||
// The complete callback returns the
|
||||
// iframe content document as response object:
|
||||
completeCallback(
|
||||
200,
|
||||
'success',
|
||||
{'iframe': response}
|
||||
);
|
||||
// Fix for IE endless progress bar activity bug
|
||||
// (happens on form submits to iframe targets):
|
||||
$('<iframe src="' + initialIframeSrc + '"></iframe>')
|
||||
.appendTo(form);
|
||||
window.setTimeout(function () {
|
||||
// Removing the form in a setTimeout call
|
||||
// allows Chrome's developer tools to display
|
||||
// the response result
|
||||
form.remove();
|
||||
}, 0);
|
||||
});
|
||||
form
|
||||
.prop('target', iframe.prop('name'))
|
||||
.prop('action', options.url)
|
||||
.prop('method', options.type);
|
||||
if (options.formData) {
|
||||
$.each(options.formData, function (index, field) {
|
||||
$('<input type="hidden"/>')
|
||||
.prop('name', field.name)
|
||||
.val(field.value)
|
||||
.appendTo(form);
|
||||
});
|
||||
}
|
||||
if (options.fileInput && options.fileInput.length &&
|
||||
options.type === 'POST') {
|
||||
fileInputClones = options.fileInput.clone();
|
||||
// Insert a clone for each file input field:
|
||||
options.fileInput.after(function (index) {
|
||||
return fileInputClones[index];
|
||||
});
|
||||
if (options.paramName) {
|
||||
options.fileInput.each(function (index) {
|
||||
$(this).prop(
|
||||
'name',
|
||||
paramNames[index] || options.paramName
|
||||
);
|
||||
});
|
||||
}
|
||||
// Appending the file input fields to the hidden form
|
||||
// removes them from their original location:
|
||||
form
|
||||
.append(options.fileInput)
|
||||
.prop('enctype', 'multipart/form-data')
|
||||
// enctype must be set as encoding for IE:
|
||||
.prop('encoding', 'multipart/form-data');
|
||||
}
|
||||
form.submit();
|
||||
// Insert the file input fields at their original location
|
||||
// by replacing the clones with the originals:
|
||||
if (fileInputClones && fileInputClones.length) {
|
||||
options.fileInput.each(function (index, input) {
|
||||
var clone = $(fileInputClones[index]);
|
||||
$(input).prop('name', clone.prop('name'));
|
||||
clone.replaceWith(input);
|
||||
});
|
||||
}
|
||||
});
|
||||
form.append(iframe).appendTo(document.body);
|
||||
},
|
||||
abort: function () {
|
||||
if (iframe) {
|
||||
// javascript:false as iframe src aborts the request
|
||||
// and prevents warning popups on HTTPS in IE6.
|
||||
// concat is used to avoid the "Script URL" JSLint error:
|
||||
iframe
|
||||
.unbind('load')
|
||||
.prop('src', initialIframeSrc);
|
||||
}
|
||||
if (form) {
|
||||
form.remove();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
// The iframe transport returns the iframe content document as response.
|
||||
// The following adds converters from iframe to text, json, html, xml
|
||||
// and script.
|
||||
// Please note that the Content-Type for JSON responses has to be text/plain
|
||||
// or text/html, if the browser doesn't include application/json in the
|
||||
// Accept header, else IE will show a download dialog.
|
||||
// The Content-Type for XML responses on the other hand has to be always
|
||||
// application/xml or text/xml, so IE properly parses the XML response.
|
||||
// See also
|
||||
// https://github.com/blueimp/jQuery-File-Upload/wiki/Setup#content-type-negotiation
|
||||
$.ajaxSetup({
|
||||
converters: {
|
||||
'iframe text': function (iframe) {
|
||||
return iframe && $(iframe[0].body).text();
|
||||
},
|
||||
'iframe json': function (iframe) {
|
||||
return iframe && $.parseJSON($(iframe[0].body).text());
|
||||
},
|
||||
'iframe html': function (iframe) {
|
||||
return iframe && $(iframe[0].body).html();
|
||||
},
|
||||
'iframe xml': function (iframe) {
|
||||
var xmlDoc = iframe && iframe[0];
|
||||
return xmlDoc && $.isXMLDoc(xmlDoc) ? xmlDoc :
|
||||
$.parseXML((xmlDoc.XMLDocument && xmlDoc.XMLDocument.xml) ||
|
||||
$(xmlDoc.body).html());
|
||||
},
|
||||
'iframe script': function (iframe) {
|
||||
return iframe && $.globalEval($(iframe[0].body).text());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}));
|
Binary file not shown.
After Width: | Height: | Size: 1.3 KiB |
Loading…
Reference in New Issue