Course drag and drop upload

Jump to: navigation, search

This is a proposed design for adding Drag and Drop upload to course pages, in a similar way (from the user's perspective) to the Drag and Drop upload block.


  • Allow users, with appropriate editing capabilities, to directly drag files (and links / blocks of text / other data types?) onto a course page and have them appear in the course as appropriate resource / activity types
    • There should be as little 'friction' as possible to getting files uploaded - sensible defaults should be automatically applied as much as possible
  • Allow different modules to register as handlers of certain file types (based on the file extension) and/or data types (for when a link or some text is dragged & dropped from another application/browser window)
    • If there are multiple handlers for any given file/data type (e.g. a 'zip' file could be file resource, be unzipped to create a folder resource or be treated as a SCORM package), then the user should be presented with a list of ways of treating the file and be asked to choose one.
    • Default handlers should be included in appropriate core modules (e.g. 'file resource' should handle all file types, 'page resource' should handle dropped text/html, 'link resource' should handle dropped URLs)


A class called dndupload_handler will handle the registration of all the different modules with the file/data types that they handle. When an instance of this class is created, it will search for the 'lib.php' file in each subdirectory of '/mod' and then look for a function '[modname]_dndupload_register'. If found, this function will be called and the dndupload_handler object will be passed in as a parameter. This will allow the modules to register the following information:

  • For files:
    • the extension ('*' to handle all extensions)
    • the name of the module to handle this type
    • the message to display to users if there is a choice of modules to handle a particular file
  • For data types, there are two stages:
    • Register the type:
      • an identifier to know it by
      • an array of mime types that it maps to (e.g. 'url' data type can be declared as 'url', 'text/uri-list' depending on browser implementations)
      • the helper text to display when dragging the type over the course (e.g. 'add a link here')
      • the text to display when asking the user for a name for the dropped object (e.g. 'what do you want to call this link?') - needed as, unlike files, dragged urls/text blocks do not have an inherent name
      • a priority (so that 'url' can take priority over 'text/html' and 'text/plain', as often dropped items provide fallback data types)
      • Note some default types - url, text/html, text - will be registered by default within the library code
    • Register a type handler:
      • the identifier of the type
      • the module to handle this type
      • the message to display to the user if there is a choice of modules to handle this type

The details about the different types that can be handled will need to be passed onto the initialisation code for the drag and drop javascript code on the page.

The drag and drop code on the page will do the following (most of these are already implemented in the drag and drop upload block):

  1. Add the necessary dragenter, dragleave, dragover and drop handlers to each course section
  2. When a drag event is detected for a course section, examine the attached data types and, if it is a recognised type (e.g. 'File', 'text/plain'), display an appropriate message within the course section (e.g. 'Add file(s) here')
  3. When a drop event is detected, check to see how many handlers are registered for that type (based on the data handed in during initialisation), if none - do nothing, if 1 then fire off an AJAX message to the server with the data and the name of the registered module, if more than 1 handler, then present the user with a YUI dialog with a list of ways to handle the type (using the string registered with the handler, above)
    1. For non-file types, there will need to be an intermediate step where a YUI dialog is shown to ask the user what to call the resource - where there is also choice of handlers, the two dialogs should be integrated together (e.g. What do you want to call this link? _________ Do you want to create a: [ ] Link to webpage [ ] Link to LTI provider)
  4. Show a suitable placeholder (the name of the item you are creating) & progress bar / spinner as the file/data is sent to the server
  5. Replace the placeholder with the name of the item as returned by the server, linked to the newly created module instance, with the standard edit tools initialised beside it

On the server side, the following steps will take place:

  1. When the AJAX data is received, do the standard checks (e.g. user permissions, sesskey checks, etc)
  2. Check whether the data is a file or another data type
    1. For files create a draft files area, note the id of the area and use the 'upload' repository to add the file to this area
    2. For other data types, just store the data in a variable
  3. Double-check that the module named in the AJAX data is a registered handler for the type of data in the call
  4. Create a course module instance for the chosen module (just as if the user had saved the 'add new X module form'), in the course/section detailed in the AJAX data
  5. Load the lib.php file for the module and call the function [modname]_dndupload_handle, passing in the appropriate data from the browser:
    1. The draft area id / data (depending on whether it is a file or some other data type)
    2. The display name (taken from the file name)
    3. The type (e.g. 'file', 'text/html', 'url')
  6. The module should then handle all its internal initialisation (equivalent to [modname]_add_instance - but with most values using defaults, instead of getting data from the 'mod_edit.php' form)
  7. Return the necessary data to the browser - the cleaned module name, the icon, the 'view' URL to link to and the standard editing tools (which can then be overwritten by the AJAX tools on the client side)