-
Notifications
You must be signed in to change notification settings - Fork 0
Design
- Events & the
Event
object - Core Library
- Extending the library with plug-ins
-
Initial Plug-ins
- Base Uploader
- HTTP request handler
- Message logger
- File input support
- Dropped file/folder support
- Paste to upload support
- Upload
<canvas>
- Upload
ArrayBuffer
- Scaled image uploader
- Chunk uploader
- S3 uploader
- Failed upload handler (auto/manual retry)
- File size validator
- File type validator
- File count validator
- Image validator
- Image preview generator
- UI w/ flexible templating
- File deleter
- Uploader pause/resume
- Filename editor
- Form support
- Initial file list support
- Azure uploader
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 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
orfalse
. -
informational
(read-only):true
orfalse
. 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.
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
.
-
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.
-
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.
-
added
: Triggered after one or more items are successfully added. Items added at once via theadd
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.
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.
All plugins must meet the specifications outlined in this section.
-
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, orthrow
anError
to indicate failure. APromise
may also be returned and `resolve`d or `reject`ed to indicate success/failure as well.
These should probably be implemented as getter functions to ensure they are constant.
-
name
: Plugin name. -
version
: Plugin version.
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.
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.
-
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.
-
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.
Initiates and manages HTTP requests and connections for other plug-ins.
-
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 eventpayload
. 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.
-
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.
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:
-
debug
-
info
-
warn
-
error
-
Possible all other events if the
logAllEvents
option is set totrue
. -
log
: Log a message to the console.
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.
-
makeFileInput
: Theresult
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 eventpayload
. 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 singleadd
event.
Accepts an element which is then monitored for dropped files. Multiple elements can be monitored - 1 per API call.
-
makeDropZone
: Accepts an HTML element to monitor for drop events (attached to the eventpayload
). 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.
-
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.
Accepts an element which is then monitored for pasted files. Multiple elements can be monitored - 1 per API call.
-
watchForPastedFiles
: Accepts an HTML element to monitor for paste events (included in the eventpayload
). Each pasted file is added to the uploader via an "add" event. Groups are respected as well.
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.
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
.
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.
-
added
: An originalBlob
has been added. One or more "templates" for aBlob
will be added to the uploader via anadd
event. These templates will represent a scaledBlob
which, onupload
will be transformed into a scaled version of the originalBlob
just before the upload request is sent. See the uploader module for more information regardingBlob
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 scaledBlob
objects, and if the scaled images will be re-oriented according to EXIF data. -
uploadSuccess
: Destroys the associated created scaled imageBlob
object via anupdated
event. This is done to prevent memory exhaustion. -
uploadFailure
: Same asuploadSuccess
logic.
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.
-
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 passedresetChunks
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.
-
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 anuploadChunkFailure
. 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.
Sends Blob
objects to an S3 bucket. To accomplish this, an available uploader module is used to send the actual Blob
.
-
upload
: When anupload
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.