Take the 2-minute tour ×
Drupal Answers is a question and answer site for Drupal developers and administrators. It's 100% free, no registration required.

I'm trying to implement XHR level 2 (file API upload) using Drupal 7's JQuery $.ajax implementation. I've got the feeling I'm almost there.

First of all, I got XHR.send() working according to orginal example on HTML5 demos. But now, I want to use Drupal 7's built in ajax framework.

I found some examples how do this with JQuery but I can't get it working for Drupal 7 with a custom ajax responce. I also found a related (D8) discussion about this on drupal.org.

Here's the code, which returns a ajax error "Illegal invocation". Probably because formData is not in a proper format?

    // 'files' below is a correct object with at least one file

    var file = files[0];
    var formData = new FormData();

    formData.append('file', files[0]);

    // element_settings: see ajax.js in drupal
    var element_settings = {};

    element_settings.progress = { 'type': 'none' }; 
    element_settings.url = '/mymodule/save/ajax';
    element_settings.data = file;
    element_settings.cache = false; 
    element_settings.contentType = file.type;
    element_settings.processData = false;
    element_settings.submit = {
      'savedata': formData
    };

    element_settings.xhr = function() {
      myXhr = $.ajaxSettings.xhr();
      if (myXhr.upload) {
        myXhr.upload.addEventListener('progress', progressHandlerFunction, false);
      } else {
        console.log("Upload progress is not supported.");
      }
      return myXhr;
    };


    var base = '#myelement';
    ajax = new Drupal.ajax(base, $('#myelement'), element_settings); 
    ajax.eventResponse($(ajax.element));

On the server site, I'm using a menu hook with ajax_deliver as delivery callback. This works, but I can't access $_FILES in the same way which is possible if you use xhr.send().

By, the way, I'm aware this only works in modern browsers. I'm using Chrome.

share|improve this question

migrated from stackoverflow.com Dec 24 '12 at 22:04

This question came from our site for professional and enthusiast programmers.

    
Does jQuery's $.ajax even know how to send a FormData? If it doesn't, neither will Drupal's Drupal.ajax... –  Rudie Dec 25 '12 at 0:12
    
Yes, if options.processData = false and options.data = FormData. –  Rudie Dec 25 '12 at 0:28
    
Yes, that is one of the workarounds mentioned in the links (under "examples") in the description. –  askibinski Dec 25 '12 at 12:52
    
I didn't read all that =) I was just thinking out loud. The problem won't be to make jQuery do what you want. The problem will be making Drupal.ajax and its messed up pageState 'system' do what you want. I've tried this once too. You should inspect a normal 'ajax' file upload. You'll give up soon enough ;) –  Rudie Dec 25 '12 at 22:51
    
Yes, I suspect it might be impossible to do this unless you do some serious hacking in Ajax.js and ajax.inc. –  askibinski Dec 26 '12 at 11:11
show 1 more comment

1 Answer 1

up vote 3 down vote accepted

I think your approach is flawed. You should use as much of Drupal's ajax system as possible, even though is wildly uncomprehensible and weird. Don't create your own Drupal.ajax object. Let Drupal handle that and the events and triggers that come with that.

Then there are only 2 problems left:

  1. Don't create an iframe and a fake form and submit that. Use Ajax.
  2. Don't serialize and preprocess that request. Use only what I'm giving you.

They're combined in jquery.form.js apparently. So all you have to do, is override where ajax.form.ajaxSubmit(ajax.options); is called: Drupal.ajax.prototype.eventResponse.

The result inside my failed-attempt-module.

It's an override of Drupal.ajax.prototype.eventResponse. I've added everything inside if ( 'FormData' in window )

My original plan (as the module name says) was to make all file fields drop containers for HTML5 File drag/drop. My approach was flawed too. I think with this approach, it's not so difficult. Just extend the FormData object at the right time.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.