annotate .svn/pristine/c9/c9a4606fd56695d0574a554ddcfcebb976dd9120.svn-base @ 1519:afce8026aaeb redmine-2.4-integration

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