Mercurial > hg > soundsoftware-site
comparison public/javascripts/attachments.js @ 1295:622f24f53b42 redmine-2.3
Update to Redmine SVN revision 11972 on 2.3-stable branch
author | Chris Cannam |
---|---|
date | Fri, 14 Jun 2013 09:02:21 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
1294:3e4c3460b6ca | 1295:622f24f53b42 |
---|---|
1 /* Redmine - project management software | |
2 Copyright (C) 2006-2013 Jean-Philippe Lang */ | |
3 | |
4 function addFile(inputEl, file, eagerUpload) { | |
5 | |
6 if ($('#attachments_fields').children().length < 10) { | |
7 | |
8 var attachmentId = addFile.nextAttachmentId++; | |
9 | |
10 var fileSpan = $('<span>', { id: 'attachments_' + attachmentId }); | |
11 | |
12 fileSpan.append( | |
13 $('<input>', { type: 'text', 'class': 'filename readonly', name: 'attachments[' + attachmentId + '][filename]', readonly: 'readonly'} ).val(file.name), | |
14 $('<input>', { type: 'text', 'class': 'description', name: 'attachments[' + attachmentId + '][description]', maxlength: 255, placeholder: $(inputEl).data('description-placeholder') } ).toggle(!eagerUpload), | |
15 $('<a> </a>').attr({ href: "#", 'class': 'remove-upload' }).click(removeFile).toggle(!eagerUpload) | |
16 ).appendTo('#attachments_fields'); | |
17 | |
18 if(eagerUpload) { | |
19 ajaxUpload(file, attachmentId, fileSpan, inputEl); | |
20 } | |
21 | |
22 return attachmentId; | |
23 } | |
24 return null; | |
25 } | |
26 | |
27 addFile.nextAttachmentId = 1; | |
28 | |
29 function ajaxUpload(file, attachmentId, fileSpan, inputEl) { | |
30 | |
31 function onLoadstart(e) { | |
32 fileSpan.removeClass('ajax-waiting'); | |
33 fileSpan.addClass('ajax-loading'); | |
34 $('input:submit', $(this).parents('form')).attr('disabled', 'disabled'); | |
35 } | |
36 | |
37 function onProgress(e) { | |
38 if(e.lengthComputable) { | |
39 this.progressbar( 'value', e.loaded * 100 / e.total ); | |
40 } | |
41 } | |
42 | |
43 function actualUpload(file, attachmentId, fileSpan, inputEl) { | |
44 | |
45 ajaxUpload.uploading++; | |
46 | |
47 uploadBlob(file, $(inputEl).data('upload-path'), attachmentId, { | |
48 loadstartEventHandler: onLoadstart.bind(progressSpan), | |
49 progressEventHandler: onProgress.bind(progressSpan) | |
50 }) | |
51 .done(function(result) { | |
52 progressSpan.progressbar( 'value', 100 ).remove(); | |
53 fileSpan.find('input.description, a').css('display', 'inline-block'); | |
54 }) | |
55 .fail(function(result) { | |
56 progressSpan.text(result.statusText); | |
57 }).always(function() { | |
58 ajaxUpload.uploading--; | |
59 fileSpan.removeClass('ajax-loading'); | |
60 var form = fileSpan.parents('form'); | |
61 if (form.queue('upload').length == 0 && ajaxUpload.uploading == 0) { | |
62 $('input:submit', form).removeAttr('disabled'); | |
63 } | |
64 form.dequeue('upload'); | |
65 }); | |
66 } | |
67 | |
68 var progressSpan = $('<div>').insertAfter(fileSpan.find('input.filename')); | |
69 progressSpan.progressbar(); | |
70 fileSpan.addClass('ajax-waiting'); | |
71 | |
72 var maxSyncUpload = $(inputEl).data('max-concurrent-uploads'); | |
73 | |
74 if(maxSyncUpload == null || maxSyncUpload <= 0 || ajaxUpload.uploading < maxSyncUpload) | |
75 actualUpload(file, attachmentId, fileSpan, inputEl); | |
76 else | |
77 $(inputEl).parents('form').queue('upload', actualUpload.bind(this, file, attachmentId, fileSpan, inputEl)); | |
78 } | |
79 | |
80 ajaxUpload.uploading = 0; | |
81 | |
82 function removeFile() { | |
83 $(this).parent('span').remove(); | |
84 return false; | |
85 } | |
86 | |
87 function uploadBlob(blob, uploadUrl, attachmentId, options) { | |
88 | |
89 var actualOptions = $.extend({ | |
90 loadstartEventHandler: $.noop, | |
91 progressEventHandler: $.noop | |
92 }, options); | |
93 | |
94 uploadUrl = uploadUrl + '?attachment_id=' + attachmentId; | |
95 if (blob instanceof window.File) { | |
96 uploadUrl += '&filename=' + encodeURIComponent(blob.name); | |
97 } | |
98 | |
99 return $.ajax(uploadUrl, { | |
100 type: 'POST', | |
101 contentType: 'application/octet-stream', | |
102 beforeSend: function(jqXhr) { | |
103 jqXhr.setRequestHeader('Accept', 'application/js'); | |
104 }, | |
105 xhr: function() { | |
106 var xhr = $.ajaxSettings.xhr(); | |
107 xhr.upload.onloadstart = actualOptions.loadstartEventHandler; | |
108 xhr.upload.onprogress = actualOptions.progressEventHandler; | |
109 return xhr; | |
110 }, | |
111 data: blob, | |
112 cache: false, | |
113 processData: false | |
114 }); | |
115 } | |
116 | |
117 function addInputFiles(inputEl) { | |
118 var clearedFileInput = $(inputEl).clone().val(''); | |
119 | |
120 if (inputEl.files) { | |
121 // upload files using ajax | |
122 uploadAndAttachFiles(inputEl.files, inputEl); | |
123 $(inputEl).remove(); | |
124 } else { | |
125 // browser not supporting the file API, upload on form submission | |
126 var attachmentId; | |
127 var aFilename = inputEl.value.split(/\/|\\/); | |
128 attachmentId = addFile(inputEl, { name: aFilename[ aFilename.length - 1 ] }, false); | |
129 if (attachmentId) { | |
130 $(inputEl).attr({ name: 'attachments[' + attachmentId + '][file]', style: 'display:none;' }).appendTo('#attachments_' + attachmentId); | |
131 } | |
132 } | |
133 | |
134 clearedFileInput.insertAfter('#attachments_fields'); | |
135 } | |
136 | |
137 function uploadAndAttachFiles(files, inputEl) { | |
138 | |
139 var maxFileSize = $(inputEl).data('max-file-size'); | |
140 var maxFileSizeExceeded = $(inputEl).data('max-file-size-message'); | |
141 | |
142 var sizeExceeded = false; | |
143 $.each(files, function() { | |
144 if (this.size && maxFileSize && this.size > parseInt(maxFileSize)) {sizeExceeded=true;} | |
145 }); | |
146 if (sizeExceeded) { | |
147 window.alert(maxFileSizeExceeded); | |
148 } else { | |
149 $.each(files, function() {addFile(inputEl, this, true);}); | |
150 } | |
151 } | |
152 | |
153 function handleFileDropEvent(e) { | |
154 | |
155 $(this).removeClass('fileover'); | |
156 blockEventPropagation(e); | |
157 | |
158 if ($.inArray('Files', e.dataTransfer.types) > -1) { | |
159 uploadAndAttachFiles(e.dataTransfer.files, $('input:file.file_selector')); | |
160 } | |
161 } | |
162 | |
163 function dragOverHandler(e) { | |
164 $(this).addClass('fileover'); | |
165 blockEventPropagation(e); | |
166 } | |
167 | |
168 function dragOutHandler(e) { | |
169 $(this).removeClass('fileover'); | |
170 blockEventPropagation(e); | |
171 } | |
172 | |
173 function setupFileDrop() { | |
174 if (window.File && window.FileList && window.ProgressEvent && window.FormData) { | |
175 | |
176 $.event.fixHooks.drop = { props: [ 'dataTransfer' ] }; | |
177 | |
178 $('form div.box').has('input:file').each(function() { | |
179 $(this).on({ | |
180 dragover: dragOverHandler, | |
181 dragleave: dragOutHandler, | |
182 drop: handleFileDropEvent | |
183 }); | |
184 }); | |
185 } | |
186 } | |
187 | |
188 $(document).ready(setupFileDrop); |