Skip to content
This repository was archived by the owner on Nov 19, 2018. It is now read-only.
Ray Nicholus edited this page May 7, 2016 · 37 revisions

Modern Uploader will be composed of two pieces: the core uploader, and a variable number of modular plugins (both custom and internally developed) that provide functionality above and beyond the core library. Among the core library and other plugin modules, the library will be entirely controlled by an extensible API and/or and extensible events system. The core library will provide some events and methods. Plugins can extend or override core events and even events provided by lower-level plugins.

Events & the Event object

Events are a critical component of Modern Uploader. Most tasks are accomplished through events. Modules will observe and create events to accomplish a variety of tasks. Modules are registered in a specific order. Events bubble through these modules, starting with the last registered event handler, and ending with the first handler. Any module will have the opportunity to cancel actionable events or mutate the data passed by actionable event handlers to subsequent modules during the even bubbling phase.

An example of an actionable event is "remove", which informs all modules that an item is about to be removed from the system. A module observing this event can prevent the item from being removed. But once the event has completed the bubbling phase and has visited all registered event listeners, the item will be removed and a "removed" event will be subsequently sent out to the system. This "removed" event is informational and not actionable.

Each module that receives an event can also influence the return value passed to previous/lower-level plugins during the bubbling phase. Each module will be able to determine if the event has been cancelled before taking further action to influence the return value passed to the previous module. Dynamic configuration can be provided as a response to events.

Each registered event handler will be passed an Event object with the following properties:

  • cancelled (read-only): true or false.

  • informational (read-only): true or false. Indicates if the event is actionable, or purely triggered to provide information.

  • returnValue (read-only): Data returned by previous handlers.

  • type (read-only): The event name.

Handlers may return false to cancel the event, null or undefined to ignore the event, data needed by other plugins via an Object, or a Promise that will cancel the event on reject or provide a return value on resolve. Any "item" associated with the event can be modified by including an item property with the modified item (Blob, File, etc) in the object returned by an event handler. Other events will follow similar conventions to allow modules handling the event to influence values associated with the module that triggered the original event.

Core Library

The core library will provide the most basic low-level API methods and events. Configuration will be provided by plugins by observing events and returning an object with appropriate configuration properties. All events will accept promissory return values so that asynchronous tasks may be used to respond. An event can be cancelled by returning false or rejecting a returned Promise.

Methods

  • A constructor function will accept an array of plugin instances to load. The order of these plugins is important, as it will dictate the order in which they are loaded.

  • fire: Fire an event to all other registered listeners.

  • get: Retrieve one or more item entries. Each item entry includes the item along with any associated metadata.

  • on: Register a listener for a specific event.

  • onAll: Register a listener for all events.

Observed Events

  • add: Add one or more items. The type of object is not important to the core library. Other modules will focus on handling one or more specific types of objects.

  • remove: Remove one or more items.

  • reset: Reset the library.

  • update: Update data associated with a specific item.

Created Events

  • added: Triggered after one or more items are successfully added. Items added at once via the add method are grouped together in one event.

  • removed: Triggered after one or more items are successfully removed.

  • resetComplete: Triggered after the library is successfully reset.

  • updated: Triggered after data associated with one or more items has been updated.

  • allModulesLoaded: Triggered when all plugins/modules (including the core library) are ready to be used.

Extending the library with plug-ins

As you can see by the list below, most of the features present in Fine Uploader will be implemented as Modern Uploader plugins. This dogfooding will not only strengthen Modern Uploader’s plugin architecture, but will also provide a great number of examples for 3rd-party Modern Uploader plugin developers. Developing a custom plugin to suit your application’s specific uploading needs will be as easy as possible.

Plugin Interface

All plugins must meet the specifications outlined in this section.

Methods

  • constructor: Any one-time configuration items specific to each module can be passed when constructing the plug-in instance. Configuration should be contained in a single object.

  • load: Called by the core module to initialize the plugin. Plugin may return nothing (undefined/null) to indicate success, or throw an Error to indicate failure. A Promise may also be returned and `resolve`d or `reject`ed to indicate success/failure as well.

Properties

These should probably be implemented as getter functions to ensure they are constant.

  • name: Plugin name.

  • version: Plugin version.

Initial Plug-ins

While custom plugins can be developed for Modern Uploader (and this will be strongly encouraged), a set of critical internally-developed and maintained plugins will accompany the core library. Each of these "base" plugins will focus on a specific feature.

Base Uploader

The uploader plugin will be responsible for sending one or more File or Blob objects to a specific endpoint or endpoints. It exposes a set of events that facilitates uploading items that have already been submitted to the core library. In addition to File and Blob objects, the uploader can also handle Blob "templates", which are functions that must perform some on-demand async operation to create a Blob. These templates return a Promise. Once the Promise is resolved, the upload request will be sent with the resulting Blob.

The core add event is observed by the upload plugin so that it can receive useful per-item configuration returned from other plugins observing this event regarding an added file. It can also react to items added by queuing them immediately, if desired.

Observed Events

  • add: Potentially queue this file or files for upload. Expected configuration includes a boolean indicating if this item or items should be immediately queued or not.

  • cancel: Stop a file that is in progress or waiting to be uploaded.

  • cancelAll: Prevent all files from being uploaded.

  • queue: Adds an item to the upload queue. Once an available connection is free, a request will be sent to the appropriate endpoint. A failed item may be re-queued for a new upload attempt using this event.

  • queueAll: Adds all valid items to the upload queue. Once an available connection is free, a request will be sent to the appropriate endpoint for each item. A failed item may be re-queued for a new upload attempt using this event.

Created Events

  • progress: Triggered periodically as an item is uploading.

  • upload: Triggered before an upload request is sent. A configuration object containing the destination endpoint, custom headers, the desired request method, custom request parameters, the parameter name for the file itself and a boolean indicating whether this will be multipart encoded or not is expected from an event handler.

  • uploading: Triggered just after an upload request has been sent.

  • uploadRequestComplete: Triggered after the request has completed. This does not necessarily indicate success or failure. It provides an opportunity for interested listeners to observe the response and let custom logic determine the outcome of the request.

  • uploadSuccess: Triggered when an upload request completes favorably.

  • uploadFailure: Triggered when an upload request has failed.

  • canceled: Triggered after an item has been cancelled.

  • queued Triggered after an item is added to the uploads queue.

HTTP request handler

Initiates and manages HTTP requests and connections for other plug-ins.

Observed Events

  • sendRequest: Sends an HTTP request (or queues it if there are no free connections). Headers, body, method, url, and acceptable response codes may be supplied in the event payload. The returned promise will be resolved according to the request outcome. You may also instruct the plug-in to observe request progress events and rebroadcast them via the event system.

Created Events

  • progress: Fired when a request publishes progress information, such as with a file upload.

  • requestFail: Fired when an HTTP request has failed.

  • requestSuccess: Fired when an HTTP request has succeeded.

  • sentRequest: Fired when an HTTP request has been sent.

Constructor configuration

{
   maxRequests: 3
}

Message logger

The logger plug-in establishes a base set of message logging behaviors. This plug-in (like all other plug-ins) can be overridden or extended by another logging plug-in if desired. It simply delegates to the console object for all logging needs when a log event is handled (which can be triggered by any module). In this sense, it is a passive module. The console method called depends on the type of message. For example, an error message is logged using console.error (if available, otherwise console.log with an '[ERROR]' prefix on the message text). Another logging plug-in that extends or replaces this one may, for example, send all error log messages to some server for further processing by observing the same event.

The message logger plug-in supports the following levels, ordered by severity:

  1. debug

  2. info

  3. warn

  4. error

Observed Events

  • Possible all other events if the logAllEvents option is set to true.

  • log: Log a message to the console.

Constructor configuration

{
   logAllEvents: false, // true to log all triggered events at debug level
   minimumLevel: 'info', // null to disable logging entirely
   pluginInfo: true, // include information about the associated plug-in in the message
   timestamp: true
}

File input support

In order for users to select one or more files via a file chooser dialog, an <input type="file"> must be used. When this element is selected, the OS-specific dialog will open and the files selected by the user will be added to the instance of the library. This initial module will provide an API for creating file input elements that are wrapped such that they can be easily styled. A number of options/attributes can be specified on each individual file input to control behaviors such as multiple file selection. Furthermore, these file inputs will be monitored for changes. When one or more files are selected, they will be added by triggering an add event.

Observed Events

  • makeFileInput: The result of this event will be set to an <input type="file"> element. It can be made invisible by including an appropriate payload property such that it can be easily styled with a wrapper element. Other attributes to be attached to the file input may also be passed in as properties in a JavaScript object on the event payload. Boolean attributes must be paired with a boolean value. When one or more files are selected, they will be passed to the associated uploader instance via an "add" event. Groups are respected such that multiple files selected at once are all passed to the uploader in a single add event.

Created Events

  • add: Add one or more selected files to the library.

Dropped file/folder support

Accepts an element which is then monitored for dropped files. Multiple elements can be monitored - 1 per API call.

Observed Events

  • makeDropZone: Accepts an HTML element to monitor for drop events (attached to the event payload). Optionally handles dropped folders as well (where supported). Each dropped file is added to the uploader by firing an "add" event. Groups are respected as well, like the file input module.

Created Events

  • add: Add one or more dropped files to the library.

  • dragOver: Triggered when an item is dragged over one of the drop zones.

  • dragOut: Triggered when an item is dragged outside of one of the drop zones.

  • dropped: Triggered when a file, files, or folder are dropped in one of the drop zones. The zone will be specified, as well as the specific element when the drop event occurred.

Paste to upload support

Accepts an element which is then monitored for pasted files. Multiple elements can be monitored - 1 per API call.

Observed Events

  • watchForPastedFiles: Accepts an HTML element to monitor for paste events (included in the event payload). Each pasted file is added to the uploader via an "add" event. Groups are respected as well.

Created Events

  • add: Add one or more dropped files to the library.

  • filePasted: Triggered when a file is pasted into one of the watched elements.

Upload <canvas>

This module converts added <canvas> elements to Blob objects when an attempt is made to add them to the library. It does this by returning the converted Blob when it detects that the added item is a <canvas> element.

Observed Events

  • add: Add one or more <canvas> elements. These are converted to Blob objects for lower-level modules.

Upload ArrayBuffer

This is another passive module (similar to the <canvas> module) that converts added ArrayBuffer objects to Blob objects when an attempt is made to add them to the core uploader. It does this by returning the converted Blob when it detects that the added item is an ArrayBuffer.

Observed Events

  • add: Add one or more ArrayBuffer objects. These are converted to Blob objects for lower-level modules.

Scaled image uploader

Converts an added image Blob objects to one or more scaled image Blob objects. Since these scaled Blob objects will consume memory, this only occurs just as an original Blob is about to be uploaded.

Observed Events

  • added: An original Blob has been added. One or more "templates" for a Blob will be added to the uploader via an add event. These templates will represent a scaled Blob which, on upload will be transformed into a scaled version of the original Blob just before the upload request is sent. See the uploader module for more information regarding Blob templates. Accepts configuration that sets the quality, size, and type (JPEG/PNG) of the scaled images, as well as booleans to determine if the EXIF data from the original image will be transferred to the scaled Blob objects, and if the scaled images will be re-oriented according to EXIF data.

  • uploadSuccess: Destroys the associated created scaled image Blob object via an updated event. This is done to prevent memory exhaustion.

  • uploadFailure: Same as uploadSuccess logic.

Chunk uploader

Takes an added Blob and breaks it into smaller chunks, which are uploaded instead of the added Blob. This module conflicts with the "base uploader" module, and the two should not exist together in the same modern uploader instance. In other words, choose the base uploader module or this chunk uploader module, but not both.

Observed Events

  • add: Potentially queue this file or files for upload. Expected configuration includes a boolean indicating if this item or items should be immediately queued or not.

  • cancel: Stop a file that is in progress or waiting to be uploaded.

  • cancelAll: Prevent all files from being uploaded.

  • queue: Adds an item to the upload queue. Once an available connection is free, the file will be uploaded, chunk by chunk. A failed item may be re-queued for a new upload attempt using this event. The upload will be resumed with the last failed chunk, but the upload can be restarted with the first chunk using a passed resetChunks configuration option.

  • queueAll: Adds all valid items to the upload queue. Once an available connection is free, a request will be sent to the appropriate endpoint for each item for each chunk. A failed item may be re-queued for a new upload attempt using this event.

Created Events

  • progress: Triggered periodically as an item is uploading.

  • upload: Triggered before an upload request is sent. A configuration object containing the destination endpoint, custom headers, the desired request method, custom request parameters, the parameter name for the file itself, a boolean indicating whether this will be multipart encoded or not, and the chunk size is expected from an event handler.

  • uploading: Triggered just after an upload request has been sent.

  • uploadChunk: Triggered just before a chunk request is sent to the endpoint. Each chunk can be diverted to an a different endpoint. Parameters & headers can also be set per-chunk. All of this can be accomplished by returning an object with appropriate properties when handling this event.

  • uploadChunkRequestComplete: Triggered after the request has completed. This does not necessarily indicate success or failure. It provides an opportunity for interested listeners to observe the response and let custom logic determine the outcome of the request.

  • uploadChunkSuccess: Triggered when a chunk has uploaded successfully.

  • uploadSuccess: Triggered when an entire item upload completes favorably.

  • uploadChunkFailure: Triggered when a chunk upload request has failed.

  • uploadFailure: Triggered when an upload request has failed. This will always follow an uploadChunkFailure. It exists to offer parity with the base uploader plugin’s event offerings.

  • canceled: Triggered after an item has been cancelled.

  • queued Triggered after an item is added to the uploads queue.

Constructor configuration

{
   maxRequests: 3
}

The maximum allowable number of concurrent HTTP requests (the maxRequests option) can be supplied as configuration to this plug-in by an allModulesLoaded event observer. The default value is described above.

S3 uploader

Sends Blob objects to an S3 bucket. To accomplish this, an available uploader module is used to send the actual Blob.

Observed Events

  • upload: When an upload event is encountered for a non-chunked item, appropriate header and params are returned to initiate an HTML Form POST upload. The request must be multipart encoded, consistent with a <form> submission. For a chunked item, the Multipart Upload API must be used, which means an initiate multipart upload request must be sent before the upload starts. In either case, a signature request must also be sent to the signature server first. This signature is used to construct the appropriate headers and parameters sent with the initiate request or the upload POST request. Acceptable configuration includes the signature version number (2 or 4), along with the bucket URL (endpoint), access key, the s3 object key, the AWS region, the acl, and headers/endpoint for the signature request.

  • uploadChunk: Before each chunk is uploaded, a request must be sent to the provided signature server. This signature is then used to influence the headers sent with the chunked upload request. Acceptable configuration includes the headers/endpoint for the signature request.

Constructor configuration

{
   clockDrift: 0
}

Failed upload handler (auto/manual retry)

TODO

File size validator

TODO

File type validator

TODO

File count validator

TODO

Image validator

TODO

Image preview generator

TODO

UI w/ flexible templating

TODO

File deleter

TODO

Uploader pause/resume

TODO

Filename editor

TODO

Form support

TODO

Initial file list support

TODO

Azure uploader

TODO