{% markdown %}
# Options
UI {: .page-header }
## UI
Fine Uploader [UI mode](../modes/ui.html) has a few different options as well as some options
pertaining specifically to the UI which [core mode](../modes/core.html) does not have.
Any options that exist in Core mode also exist in UI mode, and, in most cases,
can be overridden.
{% endmarkdown %}
{{ api_option("element", "element", "Container element for the default drop zone", "HTMLElement", "null") }}
{{ api_option("listElement", "listElement", "Container element for the item list.", "HTMLElement", "null") }}
{{ api_option("multiple", "multiple", "When `false` this will prevent the user from simultaneously selecting or dropping more than one item. Dropping or selecting another item will clear the upload list. If another is already uploading, it will be canceled. To ignore rather than cancel, simply return `false` in the 'validate' or 'submit' event handlers.", "Boolean", "true") }}
{{ api_option("showMessage", "showMessage", "Provide a function here to display a message to the user when the uploader receives an error or the user attempts to leave the page. The provided function may return a promise if one wishes to do asynchronous work whilst waiting for user input.", "Function", "function(message) { window.alert(message); }") }}
{{ api_option("showConfirm", "showConfirm", "Provide a function here to prompt the user to confirm deletion of a file. The provided function may return a promise if one wishes to do asynchronous work whilst waiting for user input.", "Function", "function(message) { window.confirm(message); }") }}
{{ api_option("showPrompt", "showPrompt", "Provide a function here to prompt the user for a filename when pasting file(s). The provided function may return a promise if one wishes to do asynchronous work whilst waiting for user input.", "Function", "function(message, defaultValue) { window.prompt(message, defaultValue); }") }}
{{ api_option("template", "template", "This points to the container element that contains the template to use for one or more Fine Uploader UI instances. You can either specify a string, which is the element ID (the ID of the container element on the page) or an `Element` that points to the container element.", "String or Element", "qq-template") }}
{{ api_parent_option("deleteFile", "deleteFile",
"This section defines UI specific options for [the core `deleteFile` option](options.html#deleteFile).",
(
("deleteFile.confirmMessage", "confirmMessage", "The message displayed in the confirm delete dialog.", "String", "Are you sure you want to delete {filename}?",),
("deleteFile.deletingFailedText", "deletingFailedText", "The status message to appear next to a file that has failed to delete.", "String", "Delete failed",),
("deleteFile.deletingStatusText", "deletingStatusText", "The status message to appear next to a file that is pending deletion.", "String", "Deleting...",),
("deleteFile.forceConfirm", "forceConfirm", "If this value is set to `true`, the user will be required to confirm the file delete request via a confirmation dialog.", "Boolean", "false",),
)
)}}
{{ api_parent_option("display", "display", "",
(
("display.fileSizeOnSubmit", "fileSizeOnSubmit", "Enable or disable the display of the file size next to the file after it has been submitted.", "Boolean", "false",),
("display.prependFiles", "prependFiles", "When `true` batches of files are added to the top of the UI's file list. The default is to append file(s) to the bottom of the list.", "Boolean", "false",),
)
)}}
{{ api_parent_option("dragAndDrop", "dragAndDrop", "",
(
("dragAndDrop.extraDropzones", "extraDropzones", "Designate additional drop zones for file input.", "Array", "[]",),
("dragAndDrop.reportDirectoryPaths", "reportDirectoryPaths", "Include the path of dropped files (starting with the top-level dropped directory). This value will be sent along with the request as a qqpath parameter.", "Boolean", "false",),
)
)}}
{{ api_parent_option("failedUploadTextDisplay", "failedUploadTextDisplay", "",
(
("failedUploadTextDisplay.enableTooltip", "enableTooltip", "Enable or disable a tooltip that will display the full contents of the error message when the mouse pointer hovers over the failed item.", "Boolean", "true",),
("failedUploadTextDisplay.mode", "mode", "Set the message to display next to each failed file. One of: `'default'` which displays the `failedUploadText`, `'custom'` which displays the error response from the server, or `'none'` which displays no text.", "String", "default",),
("failedUploadTextDisplay.responseProperty", "responseProperty", "The property from the server response that contains the error text to display next to a failed item. Ignored unless `mode` is `'custom'`", "String", "error",),
)
)}}
{{ api_parent_option("messages", "messages", "",
(
("messages.tooManyFilesError", "tooManyFilesError", "Text sent to [`showMessage`](#showMessage) when `multiple` is `false` and more than one file is dropped at once.", "String", "You may only drop one file.",),
("messages.unsupportedBrowser", "unsupportedBrowser", "Text displayed to users who have ancient browsers.", "String", "Unrecoverable error - the browser does not permit uploading of any kind.",),
)
)}}
{{ alert(
"""`messages` is also in the Core mode options. This section defines UI specific
options for `messages`""", "info", "Note:") }}
{{ api_parent_option("retry", "retry", "This section defines UI specific options for [the core `retry` option](options.html#retry)",
(
("retry.autoRetryNote", "autoRetryNote", "The text of the note that will optionally appear next to the item during automatic retry attempts. Ignored if `showAutoRetryNote` is false.", "String", "Retrying {retryNum}/{maxAuto} ...",),
("retry.showButton", "showButton", "Enable or disable the showing of a button/link next to the failed item after all retry attempts have been exhausted. Clicking the button/link will force the uploader to make another attempt.", "Boolean", "false",),
("retry.showAutoRetryNote", "showAutoRetryNote", "Enable or disable a status message appearing next to the item during auto retry attempts.", "Boolean", "true",),
)
)}}
{{ api_parent_option("thumbnails", "thumbnails", "",
(
("thumbnails.customResizer", "customResizer", """Ignored if the current browser does not [support image previews](../browser-support.html). If you want to use an alternate library to resize the image, you must contribute a function for this option that returns a `Promise`. Once the resize is complete, your promise must be fulfilled. You may, of course, reject your returned `Promise` is the resize fails in some way.
A `resizeInfo` object, which will be passed to the supplied function, contains the following properties:
* `blob` - The original `File` or `Blob` object, if available.
* `height` - Desired height of the image after the resize operation.
* `image` - The original `HTMLImageElement` object, if available.
* `sourceCanvas` - `HTMLCanvasElement` element containing the original image data (not resized).
* `targetCanvas` - `HTMLCanvasElement` element containing the `HTMLCanvasElement` that should contain the resized image.
* `width` - Desired width of the image after the resize operation.
",
"Function", "undefined"),
("thumbnails.maxCount", "maxCount", "Maximum number of previews to render per Fine Uploader instance. A call to the reset method resets this value as well.", "Integer", "0",),
("thumbnails.timeBetweenThumbs", "timeBetweenThumbs", "The amount of time, in milliseconds, to pause between each preview generation process. This is in place to prevent the UI thread from locking up for a continuously long period of time, as preview generation can be a resource-intensive process.", "Integer", "750",),
)
)}}
{{ api_parent_option("thumbnails.placeholders", "thumbnails.placeholders", "",
(
("thumbnails.placeholders.notAvailablePath", "notAvailablePath", "Absolute URL or relative path to the image to display if the preview/thumbnail could not be generated/displayed.", "String", "null",),
("thumbnails.placeholders.waitingPath", "waitingPath", "Absolute URL or relative path to the image to display during preview generation (modern browsers) or until the server response has been parsed (older browsers).", "String", "null",),
("thumbnails.placeholders.waitUntilResponse", "waitUntilResponse", "Set this to `true` if you want the 'waiting' placeholder image to remain in place until the server response has been parsed. This is useful if you expect to return thumbnail URLs in your upload responses for files types that cannot be previewed. This option is ignored in older browsers where client-side previews cannot be generated.", "Boolean", "false",),
)
)}}
{{ api_parent_option("paste", "paste", "",
(
("paste.namePromptMessage", "namePromptMessage", "Text that will appear in [the `showPrompt` dialog](#showPrompt).", "String", "Please name this image",),
("paste.promptForName", "promptForName", "Enable or disable the usage of [`showPrompt`](#showPrompt) by Fine Uploader to prompt the user for a filename for a pasted file.", "Boolean", "false",),
)
)}}
{{ api_parent_option("scaling", "scaling", "See the [Upload Scaled Images feature page](../features/scaling.html) for more details.",
(
("scaling.failureText", "failureText", "Text that will appear next to a scaled image that could not be generated. This is in addition to the behavior associated with this property provided by Fine Uploader Core.", "String", "Failed to scale",),
("scaling.hideScaled", "hideScaled", "Set this to true if you do not want any scaled images to be displayed in the file list.", "Boolean", "false",),
)
)
}}
{{ api_parent_option("text", "text", "",
(
("text.failUpload", "failUpload", "Text that appears next to a failed item", "String", "Upload failed",),
("text.formatProgress", "formatProgress", "Appears next to a currently uploading item", "String", "{percent}% of {total_size}",),
("text.paused", "paused", "Appears next to a paused item", "String", "Paused",),
("text.waitingForResponse", "waitingForResponse", "Appears next to item once the last bytes have been sent (differs on the user-agent)", "String", "Processing...",),
)
)}}
{% endblock %}
================================================
FILE: docs/api/options.jmd
================================================
{% extends "_templates/base.html" %}
{% set page_title = "Core Options" %}
{% block sidebar %}
{% endblock %}
{% block js_head %}
{% endblock %}
{% block js_footer %}
{% endblock %}
{% block content %}
{% markdown %}
[forms]: ../features/forms.html
# Options Core {: .page-header }
Fine Uploader has a **plethora** of options. Many of these options change meaning
depending on what sort of uploader you are using. Pay close attention to the
mode you are in and keep that in mind when determining the meaning of a particular option.
## Core
{% endmarkdown %}
{{ api_option("autoUpload", "autoUpload", "Set to `false` if you want to be able to upload queued items later by calling the [`uploadStoredFiles()` method](methods.html#uploadStoredFiles).", "Boolean", "true") }}
{{ api_option("button", "button", "Specify an element to use as the 'select files' button. [Cannot be a `
{% endblock %}
================================================
FILE: docs/api/qq.jmd
================================================
{% extends "_templates/base.html" %}
{% set page_title = "qq API" %}
{% block content %}
{% markdown %}
# Utilities {: .page-header }
Fine Uploader contains a number of utility functions and shims to keep
it dependency free and lightweight. These functions are found in the same
namespace as Fine Uploader, `qq`.
## qQuery
The qQuery object is much like a poor man's jQuery. If you cannot or do not
want to import a 3rd-party library such as jQuery or Zepto to do cross-browser
DOM manipulation, then qQuery will be your friend.
{% endmarkdown %}
{{
api_method("qq", "qq (element)",
"""Selects an `HTMLElement` and returns a `qq` 'wrapped object.'
""",
[
{
"name": "element",
"type": "HTMLElement",
"description": "A HTML element."
},
],
[
{
"type": "qq instance",
"description": "A wrapped DOM object with a variety of cross-browser shims as methods."
},
])
}}
{% markdown %}
`qq` functions similar to the `jQuery` function in terms of the operations
it can perform. For now, though, `qq` only accepts `HTMLElements` as input.
To be able to use the `qq` methods, first one must wrap some `HTMLElement`
in the `qq` function as such:
For example, if you wanted to hide an element with the id of "myDiv":
```javascript
var myDiv, qqMyDiv;
myDiv = document.getElementById("myDiv");
qqMyDiv = qq(myDiv);
// Now we can call other qq methods:
qqMyDiv.hide();
var children = qqMyDiv.children();
// etc ...
```
Once you've wrapped an element, you have access to a wealth of cross-browser
shims that will let you manipulate the DOM and CSS as you please. Just make
sure to wrap any elements before calling these methods on them.
### DOM Selection and Traversal
{% endmarkdown %}
{{ api_method("qq.children", "children (element)", "Returns an array of all immediate children of this element.",
[
{
"name": "element",
"type": "HTMLElement",
"description": "An HTMLElement or an already wrapped `qq` object."
}
],
[
{
"type": "Array",
"description": "An array of HTMLElements who are children of the `element` parameter."
}
]) }}
{{ api_method("qq.contains", "contains (element)", "Returns `true` if the element contains the passed element.",
[
{
"name": "element",
"type": "HTMLElement",
"description": "An HTMLElement or an already wrapped `qq` object."
}
],
[
{
"type": "Boolean",
"description": "The result of the contains test."
}
]
) }}
{{ api_method("qq.hasAttribute", "hasAttribute (attributeName)", "Returns `true` if the attribute exists on the element and the value of the attribute is not 'false' case-insensitive.",
[
{
"name": "attributeName",
"type": "String",
"description": "An attribute to test for."
}
],
[
{
"type": "Boolean",
"description": "The result of the `hasAttribute` test."
}
]) }}
{% markdown %}
### DOM Manipulation
{% endmarkdown %}
{{ api_method("qq.clearText", "clearText ()", "Clears all text for this element") }}
{{ api_method("qq.insertBefore", "insertBefore (element)", "Inserts the element directly before the passed element in the DOM.",
[
{
"name": "element",
"type": "HTMLElement",
"description:": "The element that will be inserted."
}
]) }}
{{ api_method("qq.remove", "remove ()", "Removes the element from the DOM.") }}
{{ api_method("qq.setText", "setText (text)", "Sets the inner text for this element.",
[
{
"name": "text",
"type": "String",
"description": "The text to set."
}
]) }}
{% markdown %}
### CSS Operations
{% endmarkdown %}
{{ api_method("qq.addClass", "addClass (className)", "Add a class to this element.",
[
{
"name": "className",
"type": "String",
"description": "The name of the class to add to the element."
}
]) }}
{{ api_method("qq.css", "css (styles)", "Add CSS style(s) to this element.",
[
{
"name": "styles",
"type": "Object",
"description": "An object with styles to apply to this element."
}
],
[
{
"type": "Object",
"description": "Returns the current context to allow method chaining."
}
]
) }}
{{ api_method("qq.getByClass", "getByClass (className)", "Returns an array of all descendants of this element that contain a specific class name.",
[
{
"name": "className",
"type": "String",
"description": "The name of the class to look for in each element."
}
],
[
{
"type": "Array",
"description": "An array of `HTMLElements`"
}
]) }}
{{ api_method("qq.hasClass", "hasClass (className)", "Returns `true` if the element has the class name",
[
{
"name": "className",
"type": "String",
"description": "The name of the class to look for in each element."
}
],
[
{
"type": "Boolean",
"description": "Result of the `hasClass` test"
}
]) }}
{{ api_method("qq.hide", "hide ()", "Hide this element.",
[],
[
{
"type": "Object",
"description": "Returns the current context to allow method chaining."
}
]
) }}
{{ api_method("qq.removeClass", "removeClass (className)", "Remove the provided class from the element",
[
{
"name": "className",
"type": "String",
"description": "The name of the class to look for in each element."
}
],
[
{
"type": "Object",
"description": "Returns the current context to allow method chaining."
}
]
)
}}
{% markdown %}
### Event Attaching and Detaching
{% endmarkdown %}
{{ api_method("qq.attach", "attach (event, handler)", "Attach an event handler to this element for a specific DOM event.",
[
{
"name": "event",
"type": "String",
"description": "A valid `DOM Event`"
},
{
"name": "handler",
"type": "Function",
"description": "A function that will be invoked whenever the respective event occurs"
},
],
[
{
"type": "Function",
"description": "Call this function to detach the event."
}
])}}
{{ api_method("qq.detach", "detach (event, originalHandler)", "Detach an already attached event handler from this element for a specific DOM event.",
[
{
"name": "event",
"type": "String",
"description": "A valid `DOM Event`"
},
{
"name": "originalHandler",
"type": "Function",
"description": "A function that will be detached from this event."
},
],
[
{
"type": "Object",
"description": "Returns the current context to allow method chaining."
}
]
)}}
{% markdown %}
## Utility Functions
{% endmarkdown %}
{{ api_method("qq.bind", "bind (oldFunc, context)", "Shim for `Function.prototype.bind`. Creates a new function that, when called, has its `this` keyword set to the provided `context`. Pass comma-separated values after the `context parameter for all arguments to be passed into the new function (when invoked). you can still pass in additional arguments during invocation.",
[
{
"name": "oldFunc",
"type": "Function",
"description": "The function that will be bound to."
},
{
"name": "context",
"type": "Object",
"description": "The context the function will assume."
},
],
[
{
"type": "Function",
"description": "A new function, same as the old one, but bound to the passed in`context`."
}
]) }}
{{ api_method("qq.each", "each (iterable, callback)", "Iterates through a collection, passing the key and value into the provided callback. `return false;` to stop iteration.",
[
{
"name": "iterable",
"type": "Array or Object",
"description": "The array or object containing items/properties to loop through."
},
{
"name": "callback",
"type": "Function",
"description": "A function that will be called for each item returned by looping through the iterable. This function takes an index and an item."
}
]) }}
{{ api_method("qq.extend", "extend (firstObj, secondObj[, extendNested])", "Shallowly copies the parameters of `secondobj` to `firstobj`. if `extendnested` is true then a deep-copy is performed.",
[
{
"name": "firstObj",
"type": "Object",
"description": "The object to copy parameters to."
},
{
"name": "secondObj",
"type": "Object",
"description": "The object to copy parameters from."
},
{
"name": "extendNested",
"type": "Boolean",
"description": "If `true` then a deep-copy is performed, else a shallow copy."
},
],
[
{
"type": "Object",
"description": "The new object created by the extension."
}
]) }}
{{ api_method("qq.format", "format (message)", "Returns a string, swapping argument values with the associated occurrence of {} in the passed string.",
[
{
"name": "message",
"type": "String",
"description": ""
}
],
[
{
"type": "String",
"description": "The formatted string"
}
]) }}
{{ api_method("qq.getextension", "getExtension (filename)", "Return the extension for the filename, if any.", [ { "name": "filename", "type": "String", "description": "The file's name to rip the extension off of." } ],
[ { "type": "String", "description": "The new filename" }] )}}
{{ api_method("qq.getUniqueId ()", "getUniqueId", "Returns a version4 uuid", [],
[ { "type": "String", "description": "A version 4 unique identifier" } ]) }}
{{ api_method("qq.indexof", "indexOf (array, item[, startingIndex])", "Returns the index of `item` in the `Array` starting the search from `startingindex`.",
[
{
"name": "array",
"type": "Array",
"description": ""
},
{
"name": "item",
"type": "Object",
"description": ""
},
{
"name": "startingIndex",
"type": "Integer",
"description": ""
}
],
[
{
"type": "Integer",
"description": "The index of `item` in the array."
}
]) }}
{{ api_method("qq.isfunction", "isFunction (func)", "`true` if the parameter is a function.",
[ { "name": "func", "type": "Object", "description": "The Object to test." } ],
[ { "type": "Boolean", "description": "The result of the `isfunction` test." } ]) }}
{{ api_method("qq.isobject", "isObject (obj)", "`true` if the parameter is a 'simple' object.",
[ { "name": "obj", "type": "Object", "description": "The 'thing' to test."}],
[ { "type": "Boolean", "description": "Result of the `isobject` test" }]) }}
{{ api_method("qq.isstring", "isString (str)", "`true` if the parameter is a string.",
[ { "name": "str", "type": "Object", "description": "The Object to test" } ],
[ { "type": "Boolean", "description": "The result of the `isstring` test." } ]) }}
{{ api_method("qq.log", "log (logMessage[, logLevel])", "Log a message to the console. no-op if console logging is not supported. shim for `console.log`.",
[ { "name": "logmessage", "type": "String", "description": "The message to log." },
{ "name": "logLevel", "type": "String", "description": "The logging level, such as 'warn' and 'info'. If `null`, then 'info' is assumed." } ]) }}
{{ api_method("qq.preventdefault", "preventDefault (event)", "Prevent the browser's default action on an event.",
[
{
"name": "event",
"type": "String",
"description": "The name of the default event to prevent."
}
]) }}
{{ api_method("qq.toelement", "toElement (str)", "Creates and returns a new `
` element",
[ { "name": "str", "type": "String", "description": "Valid HTML that can be parsed by a browser." }],
[ { "type": "HTMLElement", "description": "An newly created `HTMLElement` from the input." } ]) }}
{{ api_method("qq.trimstr", "trimstr (str)", "Removes whitespace from the ends of a string. Shim for `String.prototype.trim`.",
[ { "name": "str", "type": "String", "description": "The string to remove whitespace from." } ],
[ { "type" : "String", "description": "The new string sans whitespace." } ]) }}
{% endblock %}
================================================
FILE: docs/browser-support.jmd
================================================
{% extends "_templates/base.html" %}
{% block content %}
{% markdown %}
# Browser Support {: .page-header }
Currently, Fine Uploader supports the following browsers:
* Chrome
* Firefox
* Microsoft Edge 13.10586+
* Opera 15+
* Android 2.3.x+
* iOS 6+
* Safari 5+ (OS X)
* Chrome mobile (iOS & Android)
* Internet Explorer 8+
## Feature Support Matrix
Note: Any features not listed here are supported in all browsers.
| Browser |
XHR2 |
Multiple File Selection |
File Drop |
Folder Drop |
Folder Selection |
Chunking / Resume |
Non-MPE Requests |
Upload via Paste |
CORS |
Size Validation |
Progress reporting |
Image Previews |
Image Scaling |
Image Validation |
Pause Uploads |
S3 Uploads |
Azure Uploads |
| Chrome |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
| Chrome iOS 6+ |
{{ label('√', "success") }} |
{{ label('√', "success") }}* |
{{ label('-', "") }} |
{{ label('-', "") }} |
{{ label('-', "") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('-', "") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('x', "important") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
| Chrome Android 4+ |
{{ label('√', "success") }} |
{{ label('x', "important") }} |
{{ label('-', "") }} |
{{ label('-', "") }} |
{{ label('-', "") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('-', "") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
| Opera 15+ |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
| Firefox |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "important") }} |
{{ label('x', "important") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('x', "important") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
| Edge |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "important") }} |
{{ label('x', "important") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('x', "important") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
| IE 11 |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('x', "important") }} |
{{ label('x', "important") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('x', "important") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
| IE 10 |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('x', "important") }} |
{{ label('x', "important") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('x', "important") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
| IE 9 |
{{ label('x', "important") }} |
{{ label('x', "important") }} |
{{ label('x', "important") }} |
{{ label('x', "important") }} |
{{ label('x', "important") }} |
{{ label('x', "important") }} |
{{ label('x', "important") }} |
{{ label('x', "important") }} |
{{ label('√', "success") }} |
{{ label('x', "important") }} |
{{ label('x', "important") }} |
{{ label('x', "important") }} |
{{ label('x', "important") }} |
{{ label('x', "important") }} |
{{ label('x', "important") }} |
{{ label('√', "success") }} |
{{ label('x', "important") }} |
| IE 8 |
{{ label('x', "important") }} |
{{ label('x', "important") }} |
{{ label('x', "important") }} |
{{ label('x', "important") }} |
{{ label('x', "important") }} |
{{ label('x', "important") }} |
{{ label('x', "important") }} |
{{ label('x', "important") }} |
{{ label('√', "success") }} |
{{ label('x', "important") }} |
{{ label('x', "important") }} |
{{ label('x', "important") }} |
{{ label('x', "important") }} |
{{ label('x', "important") }} |
{{ label('x', "important") }} |
{{ label('√', "success") }} |
{{ label('x', "important") }} |
| Android
4+ stock |
{{ label('√', "success") }} |
{{ label('x', "important") }} |
{{ label('x', "important") }} |
{{ label('-', "") }} |
{{ label('-', "") }} |
{{ label('x', "important") }} |
{{ label('√', "success") }} |
{{ label('x', "important") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('x', "important") }} |
{{ label('√', "success") }} |
{{ label('x', "important") }} |
{{ label('√', "success") }} |
{{ label('x', "important") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
| Android
2.3.x stock |
{{ label('x', "important") }} |
{{ label('x', "important") }} |
{{ label('-', "") }} |
{{ label('-', "") }} |
{{ label('-', "") }} |
{{ label('x', "important") }} |
{{ label('x', "important") }} |
{{ label('x', "important") }} |
{{ label('y', "success") }} |
{{ label('x', "important") }} |
{{ label('x', "important") }} |
{{ label('x', "important") }} |
{{ label('x', "important") }} |
{{ label('x', "important") }} |
{{ label('x', "important") }} |
{{ label('√', "success") }} |
{{ label('x', "important") }} |
| iOS
6+ |
{{ label('√', "success") }} |
{{ label('√', "success") }}* |
{{ label('-', "") }} |
{{ label('-', "") }} |
{{ label('-', "") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('x', "important") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
| Safari
6+ |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('x', "important") }} |
{{ label('x', "important") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('x', "important") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
| Safari
5.1 |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('x', "important") }} |
{{ label('x', "important") }} |
{{ label('x', "important") }} |
{{ label('√', "success") }} |
{{ label('x', "important") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
{{ label('x', "important") }} |
{{ label('x', "important") }} |
{{ label('x', "important") }} |
{{ label('x', "important") }} |
{{ label('√', "success") }} |
{{ label('√', "success") }} |
* - Some iOS browsers are unable to upload multiple files when video files are allowed to be uploaded due to a long-standing iOS bug. See case #990 on our bug tracker for more details.
### Upload size Limitations
Upload size limitations are present in all browsers, but are most likely to affect the users of older browsers
which do not support the [File API](http://caniuse.com/fileapi). Fine Uploader uses [chunking]({{ URL_ROOT }}/features/chunking.html) to work around
the maximum upload size limit in browsers that do support the File API. When you are designing your upload form
for users of these older browsers, or if you are not using chunking, make sure you keep the imposed file size limits in mind:
| Browser |
Upload Limit |
| IE8 |
2GB |
| IE9 |
4GB |
[Source](http://blogs.msdn.com/b/ieinternals/archive/2011/03/10/wininet-internet-explorer-file-download-and-upload-maximum-size-limits.aspx)
# Feature Detection
You can programmatically detect support for all of Fine Uploader's features at runtime by checking the bundled `qq.supportedFeatures` object.
## Feature Flags
Fine Uploader provides a set of flags that can be used to determine which
features are supported in the current browser. These flags are set during
initialization of the uploader.
Reading the feature flags in the feature detection module is easy. Each flag
has a boolean value. Simply call `qq.supportedFeatures.{featureFlagName}`
and examine the return value. For example, if you'd like to check if the
current user agent supports dropping folders, call `qq.supportedFeatures.folderDrop`.
Feature | Description
------------|------------
`ajaxUploading` | Is uploading via XHR2 supported? Indicates File API support
`blobUploading` | Is it possible to upload `Blob` objects in this browser?
`canDetermineSize` | Can file size be determined client-side?
`chunking` | Is chunking supported?
`dialogElement` | Does this browser support the `