{% markdown %}
## Core
{% endmarkdown %}
+
+{{
+alert("If you pass a large `Blob` that was created using JavaScript in the browser into `addFiles`, you should consider calling the [`removeFileRef` method](#removeFileRef) after the file has been successfully uploaded to free up any memory consumed by the Blob.")
+}}
+
{{ api_method("addFiles", "addFiles (files[, params[, endpoint]])", "Submit one or more files to the uploader.
A `BlobWrapper` object:
@@ -352,6 +357,15 @@ A `resizeInfo` object, which will be passed to the supplied function, contains t
]) }}
+{{ api_method("removeFileRef", "removeFileRef (id)", "",
+[
+ {
+ "name": "id",
+ "type": "Integer",
+ "description": "Remove internal reference to the associated Blob/File object. For Blobs that are created via JavaScript in the browser, this will free up all consumed memory."
+ }
+]) }}
+
{{ api_method("reset", "reset ()", "Reset Fine Uploader", null, null) }}
{{ api_method("retry", "retry (id)", "Attempt to upload a specific item again.",
@@ -534,6 +548,28 @@ A `resizeInfo` object, which will be passed to your (optional) `customResizer` f
}
], null) }}
+{{ api_method("setStatus", "setStatus (id, newStatus)",
+""" Modify the status of an file.
+
+The status values correspond to those found in the `qq.status` object. Currently, the following status values may be set via this method:
+
+* `qq.status.DELETED`
+* `qq.status.DELETE_FAILED`
+
+""",
+[
+ {
+ "name": "id",
+ "type": "Integer",
+ "description": "The file id."
+ },
+ {
+ "name": "newStatus",
+ "type": "String",
+ "description": "The new `qq.status` value."
+ }
+], null) }}
+
{{ api_method("uploadStoredFiles", "uploadStoredFiles ()", "Begin uploading all queued items. Throws a `NoFilesError` of there are no items to upload.", null, null) }}
diff --git a/docs/features/statistics-and-status-updates.jmd b/docs/features/statistics-and-status-updates.jmd
index ec3ef98e1..6c632d7df 100644
--- a/docs/features/statistics-and-status-updates.jmd
+++ b/docs/features/statistics-and-status-updates.jmd
@@ -1,7 +1,7 @@
{% extends "_templates/base.html" %}
{% set page_title = "Statistics and Status Updates" %}
{% block sidebar %}
-{{ api_links(methods=['getUploads'], events=['statusChange']) }}
+{{ api_links(methods=['getUploads', 'setStatus'], events=['statusChange']) }}
{% endblock %}
{% block content %}
{% markdown %}
diff --git a/package.json b/package.json
index 69415b969..7409ebb47 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,8 @@
"name": "fine-uploader",
"title": "Fine Uploader",
"main": "lib/traditional.js",
- "version": "5.13.0",
+ "types" : "typescript/fine-uploader.d.ts",
+ "version": "5.14.0",
"description": "Multiple file upload plugin with progress-bar, drag-and-drop, direct-to-S3 & Azure uploading, client-side image scaling, preview generation, form support, chunking, auto-resume, and tons of other features.",
"keywords": [
"amazon",
@@ -46,10 +47,10 @@
"url": "https://github.com/FineUploader/fine-uploader/issues"
},
"devDependencies": {
- "clean-css-cli": "4.0.0",
+ "clean-css-cli": "4.0.7",
"jscs": "3.0.7",
"jshint": "2.9.4",
- "karma": "1.4.0",
+ "karma": "1.4.1",
"karma-firefox-launcher": "1.0.0",
"karma-mocha": "1.3.0",
"karma-spec-reporter": "0.0.26",
diff --git a/test/unit/set-status.js b/test/unit/set-status.js
new file mode 100644
index 000000000..ff7fe7fba
--- /dev/null
+++ b/test/unit/set-status.js
@@ -0,0 +1,113 @@
+/* globals describe, beforeEach, qq, qqtest, assert, helpme, it */
+
+describe("set-status.js", function() {
+ "use strict";
+
+ var testUploadEndpoint = "/test/upload",
+ fileTestHelper = helpme.setupFileTests();
+
+ var initialFiles = [{
+ name: "left.jpg",
+ uuid: "e109af57-848b-4c2a-bca8-051374d01db1"
+ }, {
+ name: "right.jpg",
+ uuid: "949d16c3-727a-4c3c-8c0f-23404dcd6f3b"
+ }];
+
+ it("testing status change of DELETED with initialFiles", function() {
+ var uploader = new qq.FineUploaderBasic();
+ uploader.addInitialFiles(initialFiles);
+
+ var uploaderFiles = uploader.getUploads();
+ var file = uploaderFiles[0];
+
+ uploader.setStatus(file.id, qq.status.DELETED);
+
+ uploaderFiles = uploader.getUploads();
+ file = uploaderFiles[0];
+
+ assert.equal(1, uploader.getNetUploads());
+ assert.equal(qq.status.DELETED, file.status);
+
+ // ensure same file can't be "deleted" twice
+ uploader.setStatus(file.id, qq.status.DELETED);
+ assert.equal(1, uploader.getNetUploads());
+ });
+
+ it("testing status change of DELETE_FAILED with initialFiles", function() {
+ var uploader = new qq.FineUploaderBasic();
+ uploader.addInitialFiles(initialFiles);
+
+ var uploaderFiles = uploader.getUploads();
+ var file = uploaderFiles[1];
+
+ uploader.setStatus(file.id, qq.status.DELETE_FAILED);
+
+ uploaderFiles = uploader.getUploads();
+ file = uploaderFiles[1];
+
+ assert.equal(2, uploader.getNetUploads());
+ assert.equal(qq.status.DELETE_FAILED, file.status);
+ });
+
+ it("testing status change of DELETED with mock uploader", function(done) {
+ var uploader = new qq.FineUploaderBasic({
+ autoUpload: true,
+ request: {
+ endpoint: testUploadEndpoint
+ }
+ });
+
+ qqtest.downloadFileAsBlob("up.jpg", "image/jpeg").then(function(blob) {
+ fileTestHelper.mockXhr();
+
+ uploader.addFiles({name: "test", blob: blob});
+ uploader.uploadStoredFiles();
+ fileTestHelper.getRequests()[0].respond(201, null, JSON.stringify({success: true}));
+
+ var uploaderFiles = uploader.getUploads();
+ var file = uploaderFiles[0];
+
+ uploader.setStatus(file.id, qq.status.DELETED);
+
+ uploaderFiles = uploader.getUploads();
+ file = uploaderFiles[0];
+
+ assert.equal(0, uploader.getNetUploads());
+ assert.equal(qq.status.DELETED, file.status);
+ done();
+ });
+
+ });
+
+ it("testing status change of DELETED with mock uploader", function(done) {
+ var uploader = new qq.FineUploaderBasic({
+ autoUpload: true,
+ request: {
+ endpoint: testUploadEndpoint
+ }
+ });
+
+ qqtest.downloadFileAsBlob("up.jpg", "image/jpeg").then(function(blob) {
+ fileTestHelper.mockXhr();
+
+ uploader.addFiles({name: "test", blob: blob});
+ uploader.uploadStoredFiles();
+ fileTestHelper.getRequests()[0].respond(201, null, JSON.stringify({success: true}));
+
+ var uploaderFiles = uploader.getUploads();
+ var file = uploaderFiles[0];
+
+ uploader.setStatus(file.id, qq.status.DELETE_FAILED);
+
+ uploaderFiles = uploader.getUploads();
+ file = uploaderFiles[0];
+
+ assert.equal(1, uploader.getNetUploads());
+ assert.equal(qq.status.DELETE_FAILED, file.status);
+ done();
+ });
+
+ });
+
+});
diff --git a/test/unit/simple-file-uploads.js b/test/unit/simple-file-uploads.js
index 836a3fc46..6da26f4e3 100644
--- a/test/unit/simple-file-uploads.js
+++ b/test/unit/simple-file-uploads.js
@@ -478,5 +478,30 @@ if (qqtest.canDownloadFileAsBlob) {
uploader.addFiles(canvasWrapper);
});
});
+
+ it("removes reference to a Blob via API", function(done) {
+ qqtest.downloadFileAsBlob("up.jpg", "image/jpeg").then(function(blob) {
+ fileTestHelper.mockXhr();
+
+ var request,
+ uploader = new qq.FineUploaderBasic({
+ autoUpload: false,
+ request: { endpoint: testUploadEndpoint },
+ callbacks: {
+ onComplete: function(id) {
+ assert.ok(uploader.getFile(id));
+ uploader.removeFileRef(id);
+ assert.ok(!uploader.getFile(id));
+ done();
+ }
+ }
+ });
+
+ uploader.addFiles({name: "test", blob: blob});
+ uploader.uploadStoredFiles();
+
+ fileTestHelper.getRequests()[0].respond(200, null, JSON.stringify({success: true}));
+ });
+ });
});
}