infusion
Version:
Infusion is an application framework for developing flexible stuff with JavaScript
815 lines (726 loc) • 32.7 kB
JavaScript
/*
Copyright 2008-2009 University of Toronto
Copyright 2008-2009 University of California, Berkeley
Copyright 2010-2014 OCAD University
Copyright 2011 Lucendo Development Ltd.
Copyright 2013 Raising the Floor - US
Copyright 2015 Raising the Floor - International
Licensed under the Educational Community License (ECL), Version 2.0 or the New
BSD license. You may not use this file except in compliance with one these
Licenses.
You may obtain a copy of the ECL 2.0 License and BSD License at
https://github.com/fluid-project/infusion/raw/master/Infusion-LICENSE.txt
*/
var fluid_2_0_0 = fluid_2_0_0 || {};
/************
* Uploader *
************/
(function ($, fluid) {
"use strict";
fluid.enhance.supportsBinaryXHR = function () {
return window.FormData || (window.XMLHttpRequest && window.XMLHttpRequest.prototype && window.XMLHttpRequest.prototype.sendAsBinary);
};
fluid.enhance.supportsFormData = function () {
return !!window.FormData;
};
fluid.contextAware.makeChecks({
"fluid.browser.supportsBinaryXHR": {
funcName: "fluid.enhance.supportsBinaryXHR"
},
"fluid.browser.supportsFormData": {
funcName: "fluid.enhance.supportsFormData"
}
});
fluid.registerNamespace("fluid.uploader");
fluid.uploader.fileOrFiles = function (that, numFiles) {
return (numFiles === 1) ? that.options.strings.progress.singleFile :
that.options.strings.progress.pluralFiles;
};
// TODO: Use of these four utilities should be replaced by use of the "visibility model" described in FLUID-4928
fluid.uploader.enableElement = function (that, elm) {
elm.prop("disabled", false);
elm.removeClass(that.options.styles.dim);
};
fluid.uploader.disableElement = function (that, elm) {
elm.prop("disabled", true);
elm.addClass(that.options.styles.dim);
};
fluid.uploader.showElement = function (that, elm) {
elm.removeClass(that.options.styles.hidden);
};
fluid.uploader.hideElement = function (that, elm) {
elm.addClass(that.options.styles.hidden);
};
fluid.uploader.maxFilesUploaded = function (that) {
var fileUploadLimit = that.queue.getUploadedFiles().length + that.queue.getReadyFiles().length + that.queue.getErroredFiles().length;
return (fileUploadLimit === that.options.queueSettings.fileUploadLimit);
};
fluid.uploader.setTotalProgressStyle = function (that, didError) {
didError = didError || false;
var indicator = that.totalProgress.indicator;
indicator.toggleClass(that.options.styles.totalProgress, !didError);
indicator.toggleClass(that.options.styles.totalProgressError, didError);
};
fluid.uploader.setStateEmpty = function (that) {
fluid.uploader.disableElement(that, that.locate("uploadButton"));
// If the queue is totally empty, treat it specially.
if (that.queue.files.length === 0) {
that.locate("browseButtonText").text(that.options.strings.buttons.browse);
that.locate("browseButton").removeClass(that.options.styles.browseButton);
fluid.uploader.showElement(that, that.locate("instructions"));
}
};
// Only enable the browse button if the fileUploadLimit
// has not been reached
fluid.uploader.enableBrowseButton = function (that) {
if (!fluid.uploader.maxFilesUploaded(that)) {
fluid.uploader.enableElement(that, that.locate("browseButton"));
that.strategy.local.enableBrowseButton();
}
};
// See above comment: All of this wasted logic should be replaced by a model mapping system
fluid.uploader.setStateDone = function (that) {
fluid.uploader.disableElement(that, that.locate("uploadButton"));
fluid.uploader.hideElement(that, that.locate("pauseButton"));
fluid.uploader.showElement(that, that.locate("uploadButton"));
fluid.uploader.enableBrowseButton(that);
};
fluid.uploader.setStateLoaded = function (that) {
that.locate("browseButtonText").text(that.options.strings.buttons.addMore);
that.locate("browseButton").addClass(that.options.styles.browseButton);
fluid.uploader.hideElement(that, that.locate("pauseButton"));
fluid.uploader.showElement(that, that.locate("uploadButton"));
fluid.uploader.enableElement(that, that.locate("uploadButton"));
fluid.uploader.hideElement(that, that.locate("instructions"));
that.totalProgress.hide();
fluid.uploader.enableBrowseButton(that);
};
fluid.uploader.setStateUploading = function (that) {
that.totalProgress.hide(false, false);
fluid.uploader.setTotalProgressStyle(that);
fluid.uploader.hideElement(that, that.locate("uploadButton"));
fluid.uploader.disableElement(that, that.locate("browseButton"));
that.strategy.local.disableBrowseButton();
fluid.uploader.enableElement(that, that.locate("pauseButton"));
fluid.uploader.showElement(that, that.locate("pauseButton"));
};
fluid.uploader.setStateFull = function (that) {
that.locate("browseButtonText").text(that.options.strings.buttons.addMore);
that.locate("browseButton").addClass(that.options.styles.browseButton);
fluid.uploader.hideElement(that, that.locate("pauseButton"));
fluid.uploader.showElement(that, that.locate("uploadButton"));
fluid.uploader.enableElement(that, that.locate("uploadButton"));
fluid.uploader.disableElement(that, that.locate("browseButton"));
that.strategy.local.disableBrowseButton();
fluid.uploader.hideElement(that, that.locate("instructions"));
that.totalProgress.hide();
};
fluid.uploader.renderUploadTotalMessage = function (that) {
// Preservered for backwards compatibility, should be refactored post v1.5
var numReadyFiles = that.queue.getReadyFiles().length;
var bytesReadyFiles = that.queue.sizeOfReadyFiles();
var fileLabelStr = fluid.uploader.fileOrFiles(that, numReadyFiles);
var totalCount = that.queue.files.length;
var noFilesMsg = that.options.strings.progress.noFiles;
var totalStateStr = fluid.stringTemplate(that.options.strings.progress.toUploadLabel, {
fileCount: numReadyFiles,
fileLabel: fileLabelStr,
totalBytes: fluid.uploader.formatFileSize(bytesReadyFiles),
uploadedCount: that.queue.getUploadedFiles().length,
uploadedSize: fluid.uploader.formatFileSize(that.queue.sizeOfUploadedFiles()),
totalCount: totalCount,
totalSize: fluid.uploader.formatFileSize(that.queue.totalBytes())
});
if (!totalCount && noFilesMsg) {
totalStateStr = noFilesMsg;
}
that.locate("totalFileStatusText").html(totalStateStr);
};
fluid.uploader.renderFileUploadLimit = function (that) {
if (that.options.queueSettings.fileUploadLimit > 0) {
var fileUploadLimitText = fluid.stringTemplate(that.options.strings.progress.fileUploadLimitLabel, {
fileUploadLimit: that.options.queueSettings.fileUploadLimit,
fileLabel: fluid.uploader.fileOrFiles(that, that.options.queueSettings.fileUploadLimit)
});
that.locate("fileUploadLimitText").html(fileUploadLimitText);
}
};
/**
* Pretty prints a file's size, converting from bytes to kilobytes or megabytes.
*
* @param {Number} bytes the files size, specified as in number bytes.
*/
fluid.uploader.formatFileSize = function (bytes) {
if (typeof (bytes) === "number") {
if (bytes === 0) {
return "0.0 KB";
} else if (bytes > 0) {
if (bytes < 1048576) {
return (Math.ceil(bytes / 1024 * 10) / 10).toFixed(1) + " KB";
} else {
return (Math.ceil(bytes / 1048576 * 10) / 10).toFixed(1) + " MB";
}
}
}
return "";
};
fluid.uploader.derivePercent = function (num, total) {
return Math.round((num * 100) / total);
};
fluid.uploader.updateTotalProgress = function (that) {
// Preservered for backwards compatibility, should be refactored post v1.5
var batch = that.queue.currentBatch;
var totalPercent = fluid.uploader.derivePercent(batch.totalBytesUploaded, batch.totalBytes);
var numFilesInBatch = batch.files.length;
var fileLabelStr = fluid.uploader.fileOrFiles(that, numFilesInBatch);
var uploadingSize = batch.totalBytesUploaded + that.queue.sizeOfUploadedFiles();
var totalProgressStr = fluid.stringTemplate(that.options.strings.progress.totalProgressLabel, {
curFileN: batch.fileIdx,
totalFilesN: numFilesInBatch,
fileLabel: fileLabelStr,
currBytes: fluid.uploader.formatFileSize(batch.totalBytesUploaded),
totalBytes: fluid.uploader.formatFileSize(batch.totalBytes),
uploadedCount: that.queue.getUploadedFiles().length,
uploadedSize: fluid.uploader.formatFileSize(uploadingSize),
totalCount: that.queue.files.length,
totalSize: fluid.uploader.formatFileSize(that.queue.totalBytes())
});
that.totalProgress.update(totalPercent, totalProgressStr);
};
fluid.uploader.updateTotalAtCompletion = function (that) {
// Preservered for backwards compatibility, should be refactored post v1.5
var numErroredFiles = that.queue.getErroredFiles().length;
var numTotalFiles = that.queue.files.length;
var fileLabelStr = fluid.uploader.fileOrFiles(that, numTotalFiles);
var errorStr = "";
// if there are errors then change the total progress bar
// and set up the errorStr so that we can use it in the totalProgressStr
if (numErroredFiles > 0) {
var errorLabelString = (numErroredFiles === 1) ? that.options.strings.progress.singleError :
that.options.strings.progress.pluralErrors;
fluid.uploader.setTotalProgressStyle(that, true);
errorStr = fluid.stringTemplate(that.options.strings.progress.numberOfErrors, {
errorsN: numErroredFiles,
errorLabel: errorLabelString
});
}
var totalProgressStr = fluid.stringTemplate(that.options.strings.progress.completedLabel, {
curFileN: that.queue.getUploadedFiles().length,
totalFilesN: numTotalFiles,
errorString: errorStr,
fileLabel: fileLabelStr,
totalCurrBytes: fluid.uploader.formatFileSize(that.queue.sizeOfUploadedFiles()),
uploadedCount: that.queue.getUploadedFiles().length,
uploadedSize: fluid.uploader.formatFileSize(that.queue.sizeOfUploadedFiles()),
totalCount: that.queue.files.length,
totalSize: fluid.uploader.formatFileSize(that.queue.totalBytes())
});
that.totalProgress.update(100, totalProgressStr);
};
fluid.uploader.updateStateAfterFileDialog = function (that) {
var queueLength = that.queue.getReadyFiles().length;
if (queueLength > 0) {
fluid.uploader[queueLength === that.options.queueSettings.fileUploadLimit ? "setStateFull" : "setStateLoaded"](that);
fluid.uploader.renderUploadTotalMessage(that);
that.locate(that.options.focusWithEvent.afterFileDialog).focus();
}
};
fluid.uploader.updateStateAfterFileRemoval = function (that) {
fluid.uploader[that.queue.getReadyFiles().length === 0 ? "setStateEmpty" : "setStateLoaded"] (that);
fluid.uploader.renderUploadTotalMessage(that);
};
fluid.uploader.updateStateAfterCompletion = function (that) {
fluid.uploader[that.queue.getReadyFiles().length === 0 ? "setStateDone" : "setStateLoaded"] (that);
fluid.uploader.updateTotalAtCompletion(that);
};
fluid.uploader.uploadNextOrFinish = function (that) {
if (that.queue.shouldUploadNextFile()) {
that.strategy.remote.uploadNextFile();
} else {
that.events.afterUploadComplete.fire(that.queue.currentBatch.files);
that.queue.clearCurrentBatch();
}
};
// Standard event listening functions
fluid.uploader.onFileStart = function (file, queue) {
file.filestatus = fluid.uploader.fileStatusConstants.IN_PROGRESS;
queue.startFile();
};
// TODO: Improve the dependency profile of this listener and "updateTotalProgress"
fluid.uploader.onFileProgress = function (that, currentBytes) {
that.queue.updateBatchStatus(currentBytes);
fluid.uploader.updateTotalProgress(that);
};
fluid.uploader.onFileComplete = function (file, that) {
that.queue.finishFile(file);
that.events.afterFileComplete.fire(file);
fluid.uploader.uploadNextOrFinish(that);
};
// TODO: Avoid reaching directly into the FileQueue and manipulating its state from this and the next two listeners
fluid.uploader.onFileSuccess = function (file, that) {
file.filestatus = fluid.uploader.fileStatusConstants.COMPLETE;
if (that.queue.currentBatch.bytesUploadedForFile === 0) {
that.queue.currentBatch.totalBytesUploaded += file.size;
}
fluid.uploader.updateTotalProgress(that);
};
fluid.uploader.onFileError = function (file, error, that) {
if (error === fluid.uploader.errorConstants.UPLOAD_STOPPED) {
file.filestatus = fluid.uploader.fileStatusConstants.CANCELLED;
} else {
file.filestatus = fluid.uploader.fileStatusConstants.ERROR;
if (that.queue.isUploading) {
that.queue.currentBatch.totalBytesUploaded += file.size;
that.queue.currentBatch.numFilesErrored++;
fluid.uploader.uploadNextOrFinish(that);
}
}
};
fluid.uploader.afterUploadComplete = function (that) {
that.queue.isUploading = false;
fluid.uploader.updateStateAfterCompletion(that);
};
/**
* Instantiates a new Uploader component.
*
* @param {Object} container the DOM element in which the Uploader lives
* @param {Object} options configuration options for the component.
*/
fluid.defaults("fluid.uploader", {
gradeNames: ["fluid.viewComponent", "fluid.contextAware"],
contextAwareness: {
technology: {
defaultGradeNames: "fluid.uploader.singleFile"
},
liveness: {
priority: "before:technology",
checks: {
localDemoOption: {
contextValue: "{uploader}.options.demo",
gradeNames: "fluid.uploader.demo"
}
},
defaultGradeNames: "fluid.uploader.live"
}
}
});
fluid.defaults("fluid.uploader.builtinStrategyDistributor", {
gradeNames: ["fluid.component"],
distributeOptions: {
record: {
contextValue: "{fluid.browser.supportsBinaryXHR}",
gradeNames: "fluid.uploader.html5"
},
target: "{/ fluid.uploader}.options.contextAwareness.technology.checks.supportsBinaryXHR"
}
});
fluid.constructSingle([], "fluid.uploader.builtinStrategyDistributor");
// Implementation of standard public invoker methods
fluid.uploader.browse = function (queue, localStrategy) {
if (!queue.isUploading) {
localStrategy.browse();
}
};
fluid.uploader.removeFile = function (queue, localStrategy, afterFileRemoved, file) {
queue.removeFile(file);
localStrategy.removeFile(file);
afterFileRemoved.fire(file);
};
fluid.uploader.start = function (queue, remoteStrategy, onUploadStart) {
queue.start();
onUploadStart.fire(queue.currentBatch.files);
remoteStrategy.uploadNextFile();
};
fluid.uploader.stop = function (remoteStrategy, onUploadStop) {
onUploadStop.fire();
remoteStrategy.stop();
};
fluid.uploader.defaultQueueSettings = {
uploadURL: "",
postParams: {},
fileSizeLimit: "20480",
fileTypes: null,
fileTypesDescription: null,
fileUploadLimit: 0,
fileQueueLimit: 0
};
// Automatically bind a listener transferring focus to those DOM elements requested for component events
fluid.uploader.bindFocus = function (focusWithEvent, noAutoFocus, events, dom) {
fluid.each(focusWithEvent, function (element, event) {
if (!noAutoFocus[event]) {
events[event].addListener(function () {
dom.locate(element).focus();
});
}
});
};
/**
* Multiple file Uploader implementation. Encapsulates logic which is common across all configurations supporing multiple
* file uploads - HTML5 (and historically Flash)
*/
fluid.defaults("fluid.uploader.multiFileUploader", {
gradeNames: ["fluid.viewComponent"],
members: {
totalFileStatusTextId: {
expander: {
// create an id for that.dom.container, if it does not have one already,
// and set that.totalFileStatusTextIdId to the id value
funcName: "fluid.allocateSimpleId",
args: "{that}.dom.totalFileStatusText"
}
}
},
invokers: {
/**
* Opens the native OS browse file dialog.
*/
browse: {
funcName: "fluid.uploader.browse",
args: ["{that}.queue", "{that}.strategy.local"]
},
/**
* Removes the specified file from the upload queue.
*
* @param {File} file the file to remove
*/
removeFile: {
funcName: "fluid.uploader.removeFile",
args: ["{that}.queue", "{that}.strategy.local", "{that}.events.afterFileRemoved", "{arguments}.0"]
},
/**
* Starts uploading all queued files to the server.
*/
start: {
funcName: "fluid.uploader.start",
args: ["{that}.queue", "{that}.strategy.remote", "{that}.events.onUploadStart"]
},
/**
* Cancels an in-progress upload.
*/
stop: {
funcName: "fluid.uploader.stop",
args: ["{that}.strategy.remote", "{that}.events.onUploadStop"]
}
},
components: {
queue: {
type: "fluid.uploader.fileQueue"
},
strategy: {
type: "fluid.uploader.strategy"
},
errorPanel: {
type: "fluid.uploader.errorPanel",
container: "{uploader}.dom.errorsPanel",
options: {
gradeNames: "fluid.uploader.errorPanel.bindUploader"
}
},
fileQueueView: {
type: "fluid.uploader.fileQueueView",
container: "{uploader}.dom.fileQueue",
options: {
gradeNames: "fluid.uploader.fileQueueView.bindUploader",
members: { // TODO: This amounts to the entire model idiom for fileQueueView
queueFiles: "{uploader}.queue.files"
},
uploaderContainer: "{uploader}.container",
strings: {
buttons: {
remove: "{uploader}.options.strings.buttons.remove"
}
}
}
},
totalProgress: {
type: "fluid.progress",
container: "{uploader}.container",
options: {
selectors: {
progressBar: ".flc-uploader-queue-footer",
displayElement: ".flc-uploader-total-progress",
label: ".flc-uploader-total-progress-text",
indicator: ".flc-uploader-total-progress",
ariaElement: ".flc-uploader-total-progress"
}
}
}
},
queueSettings: fluid.uploader.defaultQueueSettings,
demo: false,
selectors: {
fileQueue: ".flc-uploader-queue",
browseButton: ".flc-uploader-button-browse",
browseButtonText: ".flc-uploader-button-browse-text",
uploadButton: ".flc-uploader-button-upload",
pauseButton: ".flc-uploader-button-pause",
totalFileStatusText: ".flc-uploader-total-progress-text",
fileUploadLimitText: ".flc-uploader-upload-limit-text",
instructions: ".flc-uploader-browse-instructions",
errorsPanel: ".flc-uploader-errorsPanel"
},
noAutoFocus: { // Specifies a member of "focusWithEvent" which the uploader will not attempt to automatically honour
afterFileDialog: true
},
// Specifies a selector name to move keyboard focus to when a particular event fires.
// Event listeners must already be implemented to use these options.
focusWithEvent: {
afterFileDialog: "uploadButton",
onUploadStart: "pauseButton",
onUploadStop: "uploadButton"
},
styles: {
disabled: "fl-uploader-disabled",
hidden: "fl-uploader-hidden",
dim: "fl-uploader-dim",
totalProgress: "fl-uploader-total-progress-okay",
totalProgressError: "fl-uploader-total-progress-errored",
browseButton: "fl-uploader-browseMore"
},
events: {
// TODO: this event "afterReady" was only fired by the Flash Uploader.
// It should either be removed or refactored post v1.5
afterReady: null,
onFileDialog: null,
onFilesSelected: null,
onFileQueued: null, // file
afterFileQueued: null, // file
onFileRemoved: null, // file
afterFileRemoved: null, // file
afterFileDialog: null,
onUploadStart: null,
onUploadStop: null,
onFileStart: null, // file
onFileProgress: null, // file, currentBytes, totalBytes
onFileError: null, // file, error
onQueueError: null,
onFileSuccess: null,
onFileComplete: null,
afterFileComplete: null,
afterUploadComplete: null
},
listeners: {
"onCreate": [{
listener: "fluid.uploader.bindFocus",
args: ["{that}.options.focusWithEvent", "{that}.options.noAutoFocus", "{that}.events", "{that}.dom"]
}, {
funcName: "fluid.uploader.multiFileUploader.setupMarkup",
namespace: "setupMarkup"
},
{ // TODO: These two part of the "new renderer" as "new decorators"
"this": "{that}.dom.uploadButton",
method: "click",
args: "{that}.start"
}, {
"this": "{that}.dom.pauseButton",
method: "click",
args: "{that}.stop"
}, {
"this": "{that}.dom.totalFileStatusText",
method: "attr",
args: [{
"role": "log",
"aria-live": "assertive",
"aria-relevant": "text",
"aria-atomic": "true"
}]
}, {
"this": "{that}.dom.fileQueue",
method: "attr",
args: [{
"aria-controls": "{that}.totalFileStatusTextId",
"aria-labelledby": "{that}.totalFileStatusTextId"
}]
}],
// Namespace all our standard listeners so they are easy to override
"afterFileDialog.uploader": {
listener: "fluid.uploader.updateStateAfterFileDialog",
args: "{that}"
},
"afterFileQueued.uploader": {
listener: "{that}.queue.addFile",
args: "{arguments}.0" // file
},
"onFileRemoved.uploader": {
listener: "{that}.removeFile",
args: "{arguments}.0" // file
},
"afterFileRemoved.uploader": {
listener: "fluid.uploader.updateStateAfterFileRemoval",
args: "{that}"
},
"onUploadStart.uploader": {
listener: "fluid.uploader.setStateUploading",
args: "{that}"
},
"onFileStart.uploader": {
listener: "fluid.uploader.onFileStart",
args: ["{arguments}.0", "{that}.queue"]
},
"onFileProgress.uploader": {
listener: "fluid.uploader.onFileProgress",
args: ["{that}", "{arguments}.1"] // 1: currentBytes
},
"onFileComplete.uploader": {
listener: "fluid.uploader.onFileComplete",
args: ["{arguments}.0", "{that}"]
},
"onFileSuccess.uploader": {
listener: "fluid.uploader.onFileSuccess",
args: ["{arguments}.0", "{that}"]
},
"onFileError.uploader": {
listener: "fluid.uploader.onFileError",
args: ["{arguments}.0", "{arguments}.1", "{that}"]
},
"afterUploadComplete.uploader": {
listener: "fluid.uploader.afterUploadComplete",
args: "{that}"
}
},
strings: {
progress: {
fileUploadLimitLabel: "%fileUploadLimit %fileLabel maximum",
noFiles: "0 files",
toUploadLabel: "%uploadedCount out of %totalCount files uploaded (%uploadedSize of %totalSize)",
totalProgressLabel: "%uploadedCount out of %totalCount files uploaded (%uploadedSize of %totalSize)",
completedLabel: "%uploadedCount out of %totalCount files uploaded (%uploadedSize of %totalSize)%errorString",
numberOfErrors: ", %errorsN %errorLabel",
singleFile: "file",
pluralFiles: "files",
singleError: "error",
pluralErrors: "errors"
},
buttons: {
browse: "Browse Files",
addMore: "Add More",
stopUpload: "Stop Upload",
cancelRemaning: "Cancel remaining Uploads",
resumeUpload: "Resume Upload",
remove: "Remove"
}
}
});
fluid.uploader.multiFileUploader.setupMarkup = function (that) {
// Upload button should not be enabled until there are files to upload
fluid.uploader.disableElement(that, that.locate("uploadButton"));
fluid.uploader.renderFileUploadLimit(that);
// placed here for backwards compatibility, as a noFiles string
// may not be defined.
var noFilesMsg = that.options.strings.progress.noFiles;
if (noFilesMsg) {
that.locate("totalFileStatusText").text(noFilesMsg);
}
};
fluid.defaults("fluid.uploader.strategy", {
gradeNames: ["fluid.component"],
components: {
local: {
type: "fluid.uploader.local"
},
remote: {
type: "fluid.uploader.remote"
}
}
});
fluid.defaults("fluid.uploader.local", {
gradeNames: ["fluid.component"],
queueSettings: "{uploader}.options.queueSettings",
members: {
queue: "{uploader}.queue"
},
events: {
onFileDialog: "{uploader}.events.onFileDialog",
onFilesSelected: "{uploader}.events.onFilesSelected",
afterFileDialog: "{uploader}.events.afterFileDialog",
afterFileQueued: "{uploader}.events.afterFileQueued",
onQueueError: "{uploader}.events.onQueueError"
},
invokers: {
enableBrowseButton: "fluid.uploader.local.enableBrowseButton", // TODO: FLUID-4928 "visibility model"
disableBrowseButton: "fluid.uploader.local.disableBrowseButton"
}
});
fluid.defaults("fluid.uploader.remote", {
gradeNames: ["fluid.component"],
members: {
queue: "{uploader}.queue", // TODO: explosions, see FLUID-4925
queueSettings: "{uploader}.options.queueSettings"
},
events: {
onFileStart: "{uploader}.events.onFileStart",
onFileProgress: "{uploader}.events.onFileProgress",
onFileSuccess: "{uploader}.events.onFileSuccess",
onFileError: "{uploader}.events.onFileError",
onFileComplete: "{uploader}.events.onFileComplete",
onUploadStop: "{uploader}.events.onUploadStop",
afterFileComplete: "{uploader}.events.afterFileComplete",
afterUploadComplete: "{uploader}.events.afterUploadComplete"
},
invokers: {
uploadNextFile: "fluid.uploader.uploadNextFile",
stop: "fluid.uploader.stop"
}
});
/**************************************************
* Error constants for the Uploader *
**************************************************/
// Partial TODO: The values of these keys are now our own - however, the key
// values themselves still align with those from SWFUpload
fluid.uploader.queueErrorConstants = {
QUEUE_LIMIT_EXCEEDED: "queue limit exceeded",
FILE_EXCEEDS_SIZE_LIMIT: "file exceeds size limit",
ZERO_BYTE_FILE: "zero byte file",
INVALID_FILETYPE: "invalid filetype"
};
fluid.uploader.errorConstants = {
HTTP_ERROR: "HTTP error",
MISSING_UPLOAD_URL: "Missing upload URL",
IO_ERROR: "I/O error",
SECURITY_ERROR: "Security error",
UPLOAD_LIMIT_EXCEEDED: "Upload limit exceeded",
UPLOAD_FAILED: "Uploader failed",
SPECIFIED_FILE_ID_NOT_FOUND: "Specified file ID not found",
FILE_VALIDATION_FAILED: "File validation failed",
FILE_CANCELLED: "File cancelled",
UPLOAD_STOPPED: "Upload stopped"
};
fluid.uploader.fileStatusConstants = {
QUEUED: "queued",
IN_PROGRESS: "in progress",
ERROR: "error",
COMPLETE: "complete",
CANCELLED: "cancelled"
};
/**
* Single file Uploader implementation. Use fluid.uploader() for IoC-resolved, progressively
* enhanceable Uploader, or call this directly if you only want a standard single file uploader.
* But why would you want that?
*
* @param {jQueryable} container the component's container
* @param {Object} options configuration options
*/
fluid.defaults("fluid.uploader.singleFile", {
gradeNames: ["fluid.viewComponent"],
selectors: {
basicUpload: ".fl-progEnhance-basic"
},
listeners: {
"onCreate.showMarkup": "fluid.uploader.singleFile.showMarkup"
}
});
fluid.uploader.singleFile.toggleVisibility = function (toShow, toHide) {
// For FLUID-2789: hide() doesn't work in Opera
if (window.opera) {
toShow.show().removeClass("hideUploaderForOpera");
toHide.show().addClass("hideUploaderForOpera");
} else {
toShow.show();
toHide.hide();
}
};
fluid.uploader.singleFile.showMarkup = function (that) {
// TODO: direct DOM fascism that will fail with multiple uploaders on a single page.
fluid.uploader.singleFile.toggleVisibility($(that.options.selectors.basicUpload), that.container);
};
})(jQuery, fluid_2_0_0);