2015-03-15 3 views
0

У меня есть модель для лошадей и фотомодель. Я использую загрузку файла jQuery для изменения размера (на стороне клиента) изображений и сохранения на Amazon s3 напрямую, так как я использую Heroku.jQuery Загрузка файла в Rails 4.x Вложенная форма

Я видел другие вопросы, подобные тем, которые используют несущую волну, скрепку или очень старые. Я не уверен, почему вы будете использовать carrierwave/paperclip, но я думаю, что, основываясь на том, что говорит героику, я не хочу, чтобы изображения попадали в сервер, потенциально вызывая тайм-ауты.

Heroku recommends с использованием загрузки файла jQuery и показывает js, добавляющий новый ввод файла со значением ссылки изображения (возвращенной с amazon s3). У меня это работает при сохранении фотографии отдельно. Теперь я хочу заставить его работать в вложенной форме для Лошади, но js не находит вход (поскольку он еще не существует, потому что он вложен, я полагаю).

Я использую Cocoon для вложенных форм (я открыт для всего, что будет работать лучше). Я не слишком хорошо знаком с javascript/jQuery, но, насколько я могу судить, Cocoon «скрывает» вложенный элемент, пока я не нажму, чтобы добавить его через add_association.

Haml код вид:

= link_to_add_association 'add photo', f, :photos 

HTML источник перед нажатием кнопки 'Добавить фотографию'

<div class='links'> 
<a class="btn btn-default btn-sm add_fields" data-association-insertion-method="after" data-association="photo" data-associations="photos" data-association-insertion-template="&lt;div class=&#39;nested-fields&#39;&gt; 
    &lt;fieldset class=&quot;inputs&quot;&gt;&lt;ol&gt;&lt;input type=&quot;file&quot; name=&quot;horse[photos_attributes][new_photos][url]&quot; id=&quot;horse_photos_attributes_new_photos_url&quot; /&gt; 
    &lt;input type=&quot;hidden&quot; name=&quot;horse[photos_attributes][new_photos][_destroy]&quot; id=&quot;horse_photos_attributes_new_photos__destroy&quot; value=&quot;false&quot; /&gt;&lt;a class=&quot;remove_fields dynamic&quot; href=&quot;#&quot;&gt;remove photo&lt;/a&gt; 
    &lt;/ol&gt;&lt;/fieldset&gt; 
&lt;/div&gt; 
" href="#">add photo</a> 

Как работать с этим входом и как обрабатывать загрузки нескольких файлов, как они добавлены правильно?

Мои текущие загрузки JS:

$(function() { 
    if ($('#new_horse').length > 0) { 
    $.get("/presign", function(s3params) { 

    $('.direct-upload').find("input:file").each(function(i, elem) { 
    var fileInput = $(elem); 
    var form   = $(fileInput.parents('form:first')); 
    var submitButton = form.find('input[type="submit"]'); 
    var progressBar = $("<div class='bar'></div>"); 
    var barContainer = $("<div class='progress'></div>").append(progressBar); 

    fileInput.fileupload({ 
     fileInput:  fileInput, 
     url:    "http://" + s3params.url.host, 
     type:   'POST', 
     autoUpload:  true, 
     formData:   s3params.fields, 
     paramName:  'file', // S3 does not like nested name fields i.e. name="user[avatar_url]" 
     dataType:   'XML', // S3 returns XML if success_action_status is set to 201 
     disableImageResize: false, 
     imageQuality: 0.5, 
     disableImageResize: /Android(?!.*Chrome)|Opera/ 
     .test(window.navigator && navigator.userAgent), 
     imageMaxWidth: 500, 
     imageMaxHeight: 1000, 
     imageOrientation: true, //auto rotates images 
     acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i, //I added this to jquery.fileupload-validate: alert('Must Be JPG GIF or PNG Image') 
     replaceFileInput: false, 
     progressall: function (e, data) { 
     var progress = parseInt(data.loaded/data.total * 100, 10); 
     progressBar.css('width', progress + '%') 
     }, 
     start: function (e) { 
     submitButton.prop('disabled', true); 
     fileInput.after(barContainer); 
     progressBar. 
      css('background', 'green'). 
      css('display', 'block'). 
      css('width', '0%'). 
      text("Loading..."); 
     }, 
     done: function(e, data) { 
     submitButton.prop('disabled', false); 
     progressBar.text("Pre-uploading done... Please Save or Cancel"); 

     // extract key and generate URL from response 
     var key = $(data.jqXHR.responseXML).find("Key").text(); 
     var url = 'https://' + s3params.url.host +'/' + key; 

     // remove first input to prevent phantom upload delay 
     fileInput.remove(); 

     // create new hidden input with image url 
     var input = $("<input />", { type:'hidden', name: fileInput.attr('name'), value: url }) 
     var imgPreview = '<img src="' + url + '">'; 

     form.append(input); 
     form.append(imgPreview); 
     }, 
     fail: function(e, data) { 
     submitButton.prop('disabled', false); 

     progressBar. 
      css("background", "red"). 
      text("Failed"); 
     } 
    }); 
    }); 

    }, 'json'); 
    } 
}); 

ответ

1

Я предполагаю, что я должен был выглядеть в кокон документации первой: http://www.rubydoc.info/gems/cocoon#Callbacks__upon_insert_and_remove_of_items_ http://www.rubydoc.info/gems/cocoon/1.2.6

Я изменил мой файл upload.js к следующему и он работал на нескольких файлы в вложенных формах отлично:

// added for file uploading 
// https://devcenter.heroku.com/articles/direct-to-s3-image-uploads-in-rails 
// Get our s3params from our endpoint 

$(document).on('ready page:load', function() { 
    $('.direct-upload') 
    .on('cocoon:after-insert', function(e, photo) { 
     console.log('inside cocoon image function'); 

     $.get("/presign", function(s3params) { 
     $('.direct-upload').find("input:file").each(function(i, elem) { 
      console.log('inside nested-fields photo input form'); 

      var fileInput = $(elem); 
      var form   = $(fileInput.parents('form:first')); 
      var submitButton = form.find('input[type="submit"]'); 
      var progressBar = $("<div class='bar'></div>"); 
      var barContainer = $("<div class='progress'></div>").append(progressBar); 

      fileInput.fileupload({ 
      fileInput:  fileInput, 
      url:    "http://" + s3params.url.host, 
      type:   'POST', 
      autoUpload:  true, 
      formData:   s3params.fields, 
      paramName:  'file', // S3 does not like nested name fields i.e. name="user[avatar_url]" 
      dataType:   'XML', // S3 returns XML if success_action_status is set to 201 
      disableImageResize: false, 
      imageQuality: 0.5, 
      disableImageResize: /Android(?!.*Chrome)|Opera/ 
       .test(window.navigator && navigator.userAgent), 
      imageMaxWidth: 500, 
      imageMaxHeight: 1000, 
      imageOrientation: true, //auto rotates images 
      acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i, //I added this to jquery.fileupload-validate: alert('Must Be JPG GIF or PNG Image') 
      replaceFileInput: false, 
      previewMaxWidth: 100, 
      previewMaxHeight: 100, 
      previewCrop: true, 
      progressall: function (e, data) { 
       var progress = parseInt(data.loaded/data.total * 100, 10); 
       progressBar.css('width', progress + '%') 
      }, 
      start: function (e) { 
       submitButton.prop('disabled', true); 
       fileInput.after(barContainer); 
       progressBar. 
       css('background', 'green'). 
       css('display', 'block'). 
       css('width', '0%'). 
       text("Loading..."); 
      }, 
      done: function(e, data) { 
       submitButton.prop('disabled', false); 
       progressBar.text("Photo Uploaded"); 

       // extract key and generate URL from response 
       var key = $(data.jqXHR.responseXML).find("Key").text(); 
       var url = 'https://' + s3params.url.host +'/' + key; 

       // remove first input to prevent phantom upload delay 
      fileInput.remove(); 

       // create new hidden input with image url 
       var input = $("<input />", { type:'hidden', name: fileInput.attr('name'), value: url }) 
       var imgPreview = '<img src="' + url + '">'; 

       form.append(input); 
       form.append(imgPreview); 
      }, 
      fail: function(e, data) { 
       submitButton.prop('disabled', false); 
       progressBar. 
       css("background", "red"). 
       text("Failed"); 
      } 

    }, 'json'); //fileupload 
    }); //each file 

}); //presign call 

}); // function cocoon 
}); // page ready 

Я полагаю, что Google и хорошо документированный драгоценный камень может заменить знание JS в ближайшей перспективе :-) Я уверен, что это не так уж сложно, так как это может быть так, пожалуйста, предложите любые улучшения.

Смежные вопросы