anchor.diff:          $('#spinner').removeClass('hidden')
   
           if ($('.s3-file').length > 0) {
  -          var channelID = '<%= SecureRandom.uuid %>'
  -
  -          $.ajax({
  -            type: $(this).attr('method'),
  -            url: $(this).attr('action'),
  -            data: $(this).serialize() + '&async=true&channel_id=' + channelID,
  -            success: function() {
  -              Pusher.host = 'ws-eu.pusher.com';
  -              Pusher.sockjs_host = 'sockjs-eu.pusher.com';
  -
  -              var pusher = new Pusher('<%= Pusher.key %>');
  -              var channel = pusher.subscribe(channelID);
  -
  -              channel.bind('dataset_created', function(data) {
  -                window.location = '/dashboard?success=true'
  -              })
  -
  -              channel.bind('dataset_failed', function(data) {
  -                $('#spinner').addClass('hidden')
  -                $('body').scrollTop(0)
  -                $(data).each(function(i, message) {
  -                  alert = $('<div class="alert alert-danger" role="alert">').text(message)
  -                  $('#main').prepend(alert)
  -                })
  -
  -                $('.bg-upload').each(function(i, elem) {
  -                  bgUpload(elem)
  -                });
  -
  -                // Destroy any existing progress bars
  -                $('.progress').addClass('hidden')
  -              })
  -            }
  -          })
  +          postForm($(this))
           } else {
             $('body').scrollTop(0)
  -          alert = $('<div class="alert alert-danger" role="alert">').text('You must add at least one file')
  -          $('#main').prepend(alert)
  +          addError('You must add at least one file')
             $('#spinner').addClass('hidden')
           }
   
           e.preventDefault();
         })
  -
  -      function bgUpload(elem) {
  -        var container    = $(elem)
  -        var fileInput    = $(elem).find('input[type="file"]');
  -        var form         = $(fileInput.parents('form:first'));
  -        var submitButton = form.find('button[type="submit"]');
  -        var progressBar  = $("<div class='progress-bar progress-bar-success progress-bar-striped active' role='progressbar' aria-valuenow='0' aria-valuemin='0' aria-valuemax='100'></div>");
  -        var barContainer = $("<div class='progress hidden'></div>").append(progressBar);
  -        fileInput.after(barContainer);
  -        // Remove existing hidden fields
  -        container.find('.s3-file').remove()
  -        fileInput.fileupload({
  -          fileInput:       fileInput,
  -          url:             form.data('url'),
  -          type:            'POST',
  -          autoUpload:       true,
  -          formData:         form.data('form-data'),
  -          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
  -          replaceFileInput: false,
  -          progressall: function (e, data) {
  -            var progress = parseInt(data.loaded / data.total * 100, 10);
  -            progressBar.css('width', progress + '%')
  -            progressBar.attr('aria-valuenow', progress)
  -            progressBar.text(progress + '%')
  -          },
  -          start: function (e) {
  -            submitButton.prop('disabled', true);
  -
  -            barContainer.removeClass('hidden')
  -
  -            progressBar.
  -              css('width', '0%')
  -          },
  -          done: function(e, data) {
  -            submitButton.prop('disabled', false);
  -            progressBar.text("Done");
  -            progressBar.removeClass('active')
  -            // extract key and generate URL from response
  -            var key   = $(data.jqXHR.responseXML).find("Key").text();
  -            var url   = '//' + form.data('host') + '/' + key;
  -
  -            // create hidden field
  -            var input = $("<input />", { type:'hidden', name: fileInput.attr('name'), value: url, class: 's3-file' })
  -            container.append(input);
  -          },
  -          fail: function(e, data) {
  -            submitButton.prop('disabled', false);
  -            progressBar.removeClass('progress-bar-success')
  -            progressBar.addClass('progress-bar-danger')
  -
  -            progressBar.
  -              css("background", "red").
  -              text("Upload Failed");
  -          }
  -        });
  -      }
   
         $('input.change-file').on('click', function(e) {
           $(this).attr('style', 'color:red')
  
positive.code:         container.find('.filename-wrapper').append('<div class="form-group"><label class="control-label" for="files[][file]">File</label><input class="bg-upload" id="_files[][file]" label="File" name="[files[][file]]" type="file" accept=".csv" /></div>');
          bgUpload(container)
        })
  
      });
    </script>
  <% end %>
  
negative.code: <% content_for :extra_js do %>
    <script src="//js.pusher.com/2.2/pusher.min.js"></script>
    <script>
      function bgUpload(elem) {
        var container    = $(elem)
        var fileInput    = $(elem).find('input[type="file"]');
        var form         = $(fileInput.parents('form:first'));
        var submitButton = form.find('button[type="submit"]');
        var progressBar  = $("<div class='progress-bar progress-bar-success progress-bar-striped active' role='progressbar' aria-valuenow='0' aria-valuemin='0' aria-valuemax='100'></div>");
        var barContainer = $("<div class='progress hidden'></div>").append(progressBar);
        fileInput.after(barContainer);
        // Remove existing hidden fields
        container.find('.s3-file').remove()
        fileInput.fileupload({
          fileInput:       fileInput,
          url:             form.data('url'),
          type:            'POST',
          autoUpload:       true,
          formData:         form.data('form-data'),
          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
          replaceFileInput: false,
          progressall: function (e, data) {
            var progress = parseInt(data.loaded / data.total * 100, 10);
            progressBar.css('width', progress + '%')
            progressBar.attr('aria-valuenow', progress)
            progressBar.text(progress + '%')
          },
          start: function (e) {
            submitButton.prop('disabled', true);
  
            barContainer.removeClass('hidden')
  
            progressBar.
              css('width', '0%')
          },
          done: function(e, data) {
            submitButton.prop('disabled', false);
            progressBar.text("Done");
            progressBar.removeClass('active')
            // extract key and generate URL from response
            var key   = $(data.jqXHR.responseXML).find("Key").text();
            var url   = '//' + form.data('host') + '/' + key;
  
            // create hidden field
            var input = $("<input />", { type:'hidden', name: fileInput.attr('name'), value: url, class: 's3-file' })
            container.append(input);
          },
          fail: function(e, data) {
            submitButton.prop('disabled', false);
            progressBar.removeClass('progress-bar-success')
            progressBar.addClass('progress-bar-danger')
  
            progressBar.
              css("background", "red").
              text("Upload Failed");
          }
        });
      }
  
      function postForm(form) {
        var channelID = '<%= SecureRandom.uuid %>'
  
        $.ajax({
          type: form.attr('method'),
          url: form.attr('action'),
          data: form.serialize() + '&async=true&channel_id=' + channelID,
          success: bindToPusher(channelID)
        })
      }
  
      function bindToPusher(channelID) {
        Pusher.host = 'ws-eu.pusher.com';
        Pusher.sockjs_host = 'sockjs-eu.pusher.com';
  
        var pusher = new Pusher('<%= Pusher.key %>');
        var channel = pusher.subscribe(channelID);
  
        channel.bind('dataset_created', function(data) {
          window.location = '/dashboard?success=true'
        })
        channel.bind('dataset_failed', function(data) {
          addErrors(data)
        })
      }
  
      function addErrors(data) {
        $('#spinner').addClass('hidden')
        $('body').scrollTop(0)
        $(data).each(function(i, message) {
          addError(message)
        })
  
        $('.bg-upload').each(function(i, elem) {
          bgUpload(elem)
        });
  
        // Destroy any existing progress bars
        $('.progress').addClass('hidden')
      }
  
      function addError(message) {
        alert = $('<div class="alert alert-danger" role="alert">').text(message)
        $('#main').prepend(alert)
      }
  
      $(document).ready(function() {
        var file = $('.file:first').clone();
  
  