to contain the preview\n * @param options possible properties include `maxSize` (int), `orient` (bool - default true), resize` (bool - default true), and `customResizeFunction`.\n * @returns qq.Promise fulfilled when the preview has been drawn, or the attempt has failed\n */\n generate: function(fileBlobOrUrl, container, options) {\n if (qq.isString(fileBlobOrUrl)) {\n log(\"Attempting to update thumbnail based on server response.\");\n return drawFromUrl(fileBlobOrUrl, container, options || {});\n }\n else {\n log(\"Attempting to draw client-side image preview.\");\n return draw(fileBlobOrUrl, container, options || {});\n }\n }\n });\n\n /**/\n this._testing = {};\n this._testing.isImg = isImg;\n this._testing.isCanvas = isCanvas;\n this._testing.isCrossOrigin = isCrossOrigin;\n this._testing.determineMimeOfFileName = determineMimeOfFileName;\n /* */\n};\n","/*globals qq */\n/**\n * EXIF image data parser. Currently only parses the Orientation tag value,\n * but this may be expanded to other tags in the future.\n *\n * @param fileOrBlob Attempt to parse EXIF data in this `Blob`\n * @constructor\n */\nqq.Exif = function(fileOrBlob, log) {\n \"use strict\";\n\n // Orientation is the only tag parsed here at this time.\n var TAG_IDS = [274],\n TAG_INFO = {\n 274: {\n name: \"Orientation\",\n bytes: 2\n }\n };\n\n // Convert a little endian (hex string) to big endian (decimal).\n function parseLittleEndian(hex) {\n var result = 0,\n pow = 0;\n\n while (hex.length > 0) {\n result += parseInt(hex.substring(0, 2), 16) * Math.pow(2, pow);\n hex = hex.substring(2, hex.length);\n pow += 8;\n }\n\n return result;\n }\n\n // Find the byte offset, of Application Segment 1 (EXIF).\n // External callers need not supply any arguments.\n function seekToApp1(offset, promise) {\n var theOffset = offset,\n thePromise = promise;\n if (theOffset === undefined) {\n theOffset = 2;\n thePromise = new qq.Promise();\n }\n\n qq.readBlobToHex(fileOrBlob, theOffset, 4).then(function(hex) {\n var match = /^ffe([0-9])/.exec(hex),\n segmentLength;\n\n if (match) {\n if (match[1] !== \"1\") {\n segmentLength = parseInt(hex.slice(4, 8), 16);\n seekToApp1(theOffset + segmentLength + 2, thePromise);\n }\n else {\n thePromise.success(theOffset);\n }\n }\n else {\n thePromise.failure(\"No EXIF header to be found!\");\n }\n });\n\n return thePromise;\n }\n\n // Find the byte offset of Application Segment 1 (EXIF) for valid JPEGs only.\n function getApp1Offset() {\n var promise = new qq.Promise();\n\n qq.readBlobToHex(fileOrBlob, 0, 6).then(function(hex) {\n if (hex.indexOf(\"ffd8\") !== 0) {\n promise.failure(\"Not a valid JPEG!\");\n }\n else {\n seekToApp1().then(function(offset) {\n promise.success(offset);\n },\n function(error) {\n promise.failure(error);\n });\n }\n });\n\n return promise;\n }\n\n // Determine the byte ordering of the EXIF header.\n function isLittleEndian(app1Start) {\n var promise = new qq.Promise();\n\n qq.readBlobToHex(fileOrBlob, app1Start + 10, 2).then(function(hex) {\n promise.success(hex === \"4949\");\n });\n\n return promise;\n }\n\n // Determine the number of directory entries in the EXIF header.\n function getDirEntryCount(app1Start, littleEndian) {\n var promise = new qq.Promise();\n\n qq.readBlobToHex(fileOrBlob, app1Start + 18, 2).then(function(hex) {\n if (littleEndian) {\n return promise.success(parseLittleEndian(hex));\n }\n else {\n promise.success(parseInt(hex, 16));\n }\n });\n\n return promise;\n }\n\n // Get the IFD portion of the EXIF header as a hex string.\n function getIfd(app1Start, dirEntries) {\n var offset = app1Start + 20,\n bytes = dirEntries * 12;\n\n return qq.readBlobToHex(fileOrBlob, offset, bytes);\n }\n\n // Obtain an array of all directory entries (as hex strings) in the EXIF header.\n function getDirEntries(ifdHex) {\n var entries = [],\n offset = 0;\n\n while (offset + 24 <= ifdHex.length) {\n entries.push(ifdHex.slice(offset, offset + 24));\n offset += 24;\n }\n\n return entries;\n }\n\n // Obtain values for all relevant tags and return them.\n function getTagValues(littleEndian, dirEntries) {\n var TAG_VAL_OFFSET = 16,\n tagsToFind = qq.extend([], TAG_IDS),\n vals = {};\n\n qq.each(dirEntries, function(idx, entry) {\n var idHex = entry.slice(0, 4),\n id = littleEndian ? parseLittleEndian(idHex) : parseInt(idHex, 16),\n tagsToFindIdx = tagsToFind.indexOf(id),\n tagValHex, tagName, tagValLength;\n\n if (tagsToFindIdx >= 0) {\n tagName = TAG_INFO[id].name;\n tagValLength = TAG_INFO[id].bytes;\n tagValHex = entry.slice(TAG_VAL_OFFSET, TAG_VAL_OFFSET + (tagValLength * 2));\n vals[tagName] = littleEndian ? parseLittleEndian(tagValHex) : parseInt(tagValHex, 16);\n\n tagsToFind.splice(tagsToFindIdx, 1);\n }\n\n if (tagsToFind.length === 0) {\n return false;\n }\n });\n\n return vals;\n }\n\n qq.extend(this, {\n /**\n * Attempt to parse the EXIF header for the `Blob` associated with this instance.\n *\n * @returns {qq.Promise} To be fulfilled when the parsing is complete.\n * If successful, the parsed EXIF header as an object will be included.\n */\n parse: function() {\n var parser = new qq.Promise(),\n onParseFailure = function(message) {\n log(qq.format(\"EXIF header parse failed: '{}' \", message));\n parser.failure(message);\n };\n\n getApp1Offset().then(function(app1Offset) {\n log(qq.format(\"Moving forward with EXIF header parsing for '{}'\", fileOrBlob.name === undefined ? \"blob\" : fileOrBlob.name));\n\n isLittleEndian(app1Offset).then(function(littleEndian) {\n\n log(qq.format(\"EXIF Byte order is {} endian\", littleEndian ? \"little\" : \"big\"));\n\n getDirEntryCount(app1Offset, littleEndian).then(function(dirEntryCount) {\n\n log(qq.format(\"Found {} APP1 directory entries\", dirEntryCount));\n\n getIfd(app1Offset, dirEntryCount).then(function(ifdHex) {\n var dirEntries = getDirEntries(ifdHex),\n tagValues = getTagValues(littleEndian, dirEntries);\n\n log(\"Successfully parsed some EXIF tags\");\n\n parser.success(tagValues);\n }, onParseFailure);\n }, onParseFailure);\n }, onParseFailure);\n }, onParseFailure);\n\n return parser;\n }\n });\n\n /**/\n this._testing = {};\n this._testing.parseLittleEndian = parseLittleEndian;\n /* */\n};\n","/*globals qq */\nqq.Identify = function(fileOrBlob, log) {\n \"use strict\";\n\n function isIdentifiable(magicBytes, questionableBytes) {\n var identifiable = false,\n magicBytesEntries = [].concat(magicBytes);\n\n qq.each(magicBytesEntries, function(idx, magicBytesArrayEntry) {\n if (questionableBytes.indexOf(magicBytesArrayEntry) === 0) {\n identifiable = true;\n return false;\n }\n });\n\n return identifiable;\n }\n\n qq.extend(this, {\n /**\n * Determines if a Blob can be displayed natively in the current browser. This is done by reading magic\n * bytes in the beginning of the file, so this is an asynchronous operation. Before we attempt to read the\n * file, we will examine the blob's type attribute to save CPU cycles.\n *\n * @returns {qq.Promise} Promise that is fulfilled when identification is complete.\n * If successful, the MIME string is passed to the success handler.\n */\n isPreviewable: function() {\n var self = this,\n identifier = new qq.Promise(),\n previewable = false,\n name = fileOrBlob.name === undefined ? \"blob\" : fileOrBlob.name;\n\n log(qq.format(\"Attempting to determine if {} can be rendered in this browser\", name));\n\n log(\"First pass: check type attribute of blob object.\");\n\n if (this.isPreviewableSync()) {\n log(\"Second pass: check for magic bytes in file header.\");\n\n qq.readBlobToHex(fileOrBlob, 0, 4).then(function(hex) {\n qq.each(self.PREVIEWABLE_MIME_TYPES, function(mime, bytes) {\n if (isIdentifiable(bytes, hex)) {\n // Safari is the only supported browser that can deal with TIFFs natively,\n // so, if this is a TIFF and the UA isn't Safari, declare this file \"non-previewable\".\n if (mime !== \"image/tiff\" || qq.supportedFeatures.tiffPreviews) {\n previewable = true;\n identifier.success(mime);\n }\n\n return false;\n }\n });\n\n log(qq.format(\"'{}' is {} able to be rendered in this browser\", name, previewable ? \"\" : \"NOT\"));\n\n if (!previewable) {\n identifier.failure();\n }\n },\n function() {\n log(\"Error reading file w/ name '\" + name + \"'. Not able to be rendered in this browser.\");\n identifier.failure();\n });\n }\n else {\n identifier.failure();\n }\n\n return identifier;\n },\n\n /**\n * Determines if a Blob can be displayed natively in the current browser. This is done by checking the\n * blob's type attribute. This is a synchronous operation, useful for situations where an asynchronous operation\n * would be challenging to support. Note that the blob's type property is not as accurate as reading the\n * file's magic bytes.\n *\n * @returns {Boolean} true if the blob can be rendered in the current browser\n */\n isPreviewableSync: function() {\n var fileMime = fileOrBlob.type,\n // Assumption: This will only ever be executed in browsers that support `Object.keys`.\n isRecognizedImage = qq.indexOf(Object.keys(this.PREVIEWABLE_MIME_TYPES), fileMime) >= 0,\n previewable = false,\n name = fileOrBlob.name === undefined ? \"blob\" : fileOrBlob.name;\n\n if (isRecognizedImage) {\n if (fileMime === \"image/tiff\") {\n previewable = qq.supportedFeatures.tiffPreviews;\n }\n else {\n previewable = true;\n }\n }\n\n !previewable && log(name + \" is not previewable in this browser per the blob's type attr\");\n\n return previewable;\n }\n });\n};\n\nqq.Identify.prototype.PREVIEWABLE_MIME_TYPES = {\n \"image/jpeg\": \"ffd8ff\",\n \"image/gif\": \"474946\",\n \"image/png\": \"89504e\",\n \"image/bmp\": \"424d\",\n \"image/tiff\": [\"49492a00\", \"4d4d002a\"]\n};\n","/*globals qq*/\n/**\n * Attempts to validate an image, wherever possible.\n *\n * @param blob File or Blob representing a user-selecting image.\n * @param log Uses this to post log messages to the console.\n * @constructor\n */\nqq.ImageValidation = function(blob, log) {\n \"use strict\";\n\n /**\n * @param limits Object with possible image-related limits to enforce.\n * @returns {boolean} true if at least one of the limits has a non-zero value\n */\n function hasNonZeroLimits(limits) {\n var atLeastOne = false;\n\n qq.each(limits, function(limit, value) {\n if (value > 0) {\n atLeastOne = true;\n return false;\n }\n });\n\n return atLeastOne;\n }\n\n /**\n * @returns {qq.Promise} The promise is a failure if we can't obtain the width & height.\n * Otherwise, `success` is called on the returned promise with an object containing\n * `width` and `height` properties.\n */\n function getWidthHeight() {\n var sizeDetermination = new qq.Promise();\n\n new qq.Identify(blob, log).isPreviewable().then(function() {\n var image = new Image(),\n url = window.URL && window.URL.createObjectURL ? window.URL :\n window.webkitURL && window.webkitURL.createObjectURL ? window.webkitURL :\n null;\n\n if (url) {\n image.onerror = function() {\n log(\"Cannot determine dimensions for image. May be too large.\", \"error\");\n sizeDetermination.failure();\n };\n\n image.onload = function() {\n sizeDetermination.success({\n width: this.width,\n height: this.height\n });\n };\n\n image.src = url.createObjectURL(blob);\n }\n else {\n log(\"No createObjectURL function available to generate image URL!\", \"error\");\n sizeDetermination.failure();\n }\n }, sizeDetermination.failure);\n\n return sizeDetermination;\n }\n\n /**\n *\n * @param limits Object with possible image-related limits to enforce.\n * @param dimensions Object containing `width` & `height` properties for the image to test.\n * @returns {String || undefined} The name of the failing limit. Undefined if no failing limits.\n */\n function getFailingLimit(limits, dimensions) {\n var failingLimit;\n\n qq.each(limits, function(limitName, limitValue) {\n if (limitValue > 0) {\n var limitMatcher = /(max|min)(Width|Height)/.exec(limitName),\n dimensionPropName = limitMatcher[2].charAt(0).toLowerCase() + limitMatcher[2].slice(1),\n actualValue = dimensions[dimensionPropName];\n\n /*jshint -W015*/\n switch (limitMatcher[1]) {\n case \"min\":\n if (actualValue < limitValue) {\n failingLimit = limitName;\n return false;\n }\n break;\n case \"max\":\n if (actualValue > limitValue) {\n failingLimit = limitName;\n return false;\n }\n break;\n }\n }\n });\n\n return failingLimit;\n }\n\n /**\n * Validate the associated blob.\n *\n * @param limits\n * @returns {qq.Promise} `success` is called on the promise is the image is valid or\n * if the blob is not an image, or if the image is not verifiable.\n * Otherwise, `failure` with the name of the failing limit.\n */\n this.validate = function(limits) {\n var validationEffort = new qq.Promise();\n\n log(\"Attempting to validate image.\");\n\n if (hasNonZeroLimits(limits)) {\n getWidthHeight().then(function(dimensions) {\n var failingLimit = getFailingLimit(limits, dimensions);\n\n if (failingLimit) {\n validationEffort.failure(failingLimit);\n }\n else {\n validationEffort.success();\n }\n }, validationEffort.success);\n }\n else {\n validationEffort.success();\n }\n\n return validationEffort;\n };\n};\n","/* globals qq */\n/**\n * Module used to control populating the initial list of files.\n *\n * @constructor\n */\nqq.Session = function(spec) {\n \"use strict\";\n\n var options = {\n endpoint: null,\n params: {},\n customHeaders: {},\n cors: {},\n addFileRecord: function(sessionData) {},\n log: function(message, level) {}\n };\n\n qq.extend(options, spec, true);\n\n function isJsonResponseValid(response) {\n if (qq.isArray(response)) {\n return true;\n }\n\n options.log(\"Session response is not an array.\", \"error\");\n }\n\n function handleFileItems(fileItems, success, xhrOrXdr, promise) {\n var someItemsIgnored = false;\n\n success = success && isJsonResponseValid(fileItems);\n\n if (success) {\n qq.each(fileItems, function(idx, fileItem) {\n /* jshint eqnull:true */\n if (fileItem.uuid == null) {\n someItemsIgnored = true;\n options.log(qq.format(\"Session response item {} did not include a valid UUID - ignoring.\", idx), \"error\");\n }\n else if (fileItem.name == null) {\n someItemsIgnored = true;\n options.log(qq.format(\"Session response item {} did not include a valid name - ignoring.\", idx), \"error\");\n }\n else {\n try {\n options.addFileRecord(fileItem);\n return true;\n }\n catch (err) {\n someItemsIgnored = true;\n options.log(err.message, \"error\");\n }\n }\n\n return false;\n });\n }\n\n promise[success && !someItemsIgnored ? \"success\" : \"failure\"](fileItems, xhrOrXdr);\n }\n\n // Initiate a call to the server that will be used to populate the initial file list.\n // Returns a `qq.Promise`.\n this.refresh = function() {\n /*jshint indent:false */\n var refreshEffort = new qq.Promise(),\n refreshCompleteCallback = function(response, success, xhrOrXdr) {\n handleFileItems(response, success, xhrOrXdr, refreshEffort);\n },\n requesterOptions = qq.extend({}, options),\n requester = new qq.SessionAjaxRequester(\n qq.extend(requesterOptions, {onComplete: refreshCompleteCallback})\n );\n\n requester.queryServer();\n\n return refreshEffort;\n };\n};\n","/*globals qq, XMLHttpRequest*/\n/**\n * Thin module used to send GET requests to the server, expecting information about session\n * data used to initialize an uploader instance.\n *\n * @param spec Various options used to influence the associated request.\n * @constructor\n */\nqq.SessionAjaxRequester = function(spec) {\n \"use strict\";\n\n var requester,\n options = {\n endpoint: null,\n customHeaders: {},\n params: {},\n cors: {\n expected: false,\n sendCredentials: false\n },\n onComplete: function(response, success, xhrOrXdr) {},\n log: function(str, level) {}\n };\n\n qq.extend(options, spec);\n\n function onComplete(id, xhrOrXdr, isError) {\n var response = null;\n\n /* jshint eqnull:true */\n if (xhrOrXdr.responseText != null) {\n try {\n response = qq.parseJson(xhrOrXdr.responseText);\n }\n catch (err) {\n options.log(\"Problem parsing session response: \" + err.message, \"error\");\n isError = true;\n }\n }\n\n options.onComplete(response, !isError, xhrOrXdr);\n }\n\n requester = qq.extend(this, new qq.AjaxRequester({\n acceptHeader: \"application/json\",\n validMethods: [\"GET\"],\n method: \"GET\",\n endpointStore: {\n get: function() {\n return options.endpoint;\n }\n },\n customHeaders: options.customHeaders,\n log: options.log,\n onComplete: onComplete,\n cors: options.cors\n }));\n\n qq.extend(this, {\n queryServer: function() {\n var params = qq.extend({}, options.params);\n\n options.log(\"Session query request.\");\n\n requester.initTransport(\"sessionRefresh\")\n .withParams(params)\n .withCacheBuster()\n .send();\n }\n });\n};\n","/* globals qq, ExifRestorer */\n/**\n * Controls generation of scaled images based on a reference image encapsulated in a `File` or `Blob`.\n * Scaled images are generated and converted to blobs on-demand.\n * Multiple scaled images per reference image with varying sizes and other properties are supported.\n *\n * @param spec Information about the scaled images to generate.\n * @param log Logger instance\n * @constructor\n */\nqq.Scaler = function(spec, log) {\n \"use strict\";\n\n var self = this,\n customResizeFunction = spec.customResizer,\n includeOriginal = spec.sendOriginal,\n orient = spec.orient,\n defaultType = spec.defaultType,\n defaultQuality = spec.defaultQuality / 100,\n failedToScaleText = spec.failureText,\n includeExif = spec.includeExif,\n sizes = this._getSortedSizes(spec.sizes);\n\n // Revealed API for instances of this module\n qq.extend(this, {\n // If no targeted sizes have been declared or if this browser doesn't support\n // client-side image preview generation, there is no scaling to do.\n enabled: qq.supportedFeatures.scaling && sizes.length > 0,\n\n getFileRecords: function(originalFileUuid, originalFileName, originalBlobOrBlobData) {\n var self = this,\n records = [],\n originalBlob = originalBlobOrBlobData.blob ? originalBlobOrBlobData.blob : originalBlobOrBlobData,\n identifier = new qq.Identify(originalBlob, log);\n\n // If the reference file cannot be rendered natively, we can't create scaled versions.\n if (identifier.isPreviewableSync()) {\n // Create records for each scaled version & add them to the records array, smallest first.\n qq.each(sizes, function(idx, sizeRecord) {\n var outputType = self._determineOutputType({\n defaultType: defaultType,\n requestedType: sizeRecord.type,\n refType: originalBlob.type\n });\n\n records.push({\n uuid: qq.getUniqueId(),\n name: self._getName(originalFileName, {\n name: sizeRecord.name,\n type: outputType,\n refType: originalBlob.type\n }),\n blob: new qq.BlobProxy(originalBlob,\n qq.bind(self._generateScaledImage, self, {\n customResizeFunction: customResizeFunction,\n maxSize: sizeRecord.maxSize,\n orient: orient,\n type: outputType,\n quality: defaultQuality,\n failedText: failedToScaleText,\n includeExif: includeExif,\n log: log\n }))\n });\n });\n\n records.push({\n uuid: originalFileUuid,\n name: originalFileName,\n size: originalBlob.size,\n blob: includeOriginal ? originalBlob : null\n });\n }\n else {\n records.push({\n uuid: originalFileUuid,\n name: originalFileName,\n size: originalBlob.size,\n blob: originalBlob\n });\n }\n\n return records;\n },\n\n handleNewFile: function(file, name, uuid, size, fileList, batchId, uuidParamName, api) {\n var self = this,\n buttonId = file.qqButtonId || (file.blob && file.blob.qqButtonId),\n scaledIds = [],\n originalId = null,\n addFileToHandler = api.addFileToHandler,\n uploadData = api.uploadData,\n paramsStore = api.paramsStore,\n proxyGroupId = qq.getUniqueId();\n\n qq.each(self.getFileRecords(uuid, name, file), function(idx, record) {\n var blobSize = record.size,\n id;\n\n if (record.blob instanceof qq.BlobProxy) {\n blobSize = -1;\n }\n\n id = uploadData.addFile({\n uuid: record.uuid,\n name: record.name,\n size: blobSize,\n batchId: batchId,\n proxyGroupId: proxyGroupId\n });\n\n if (record.blob instanceof qq.BlobProxy) {\n scaledIds.push(id);\n }\n else {\n originalId = id;\n }\n\n if (record.blob) {\n addFileToHandler(id, record.blob);\n fileList.push({id: id, file: record.blob});\n }\n else {\n uploadData.setStatus(id, qq.status.REJECTED);\n }\n });\n\n // If we are potentially uploading an original file and some scaled versions,\n // ensure the scaled versions include reference's to the parent's UUID and size\n // in their associated upload requests.\n if (originalId !== null) {\n qq.each(scaledIds, function(idx, scaledId) {\n var params = {\n qqparentuuid: uploadData.retrieve({id: originalId}).uuid,\n qqparentsize: uploadData.retrieve({id: originalId}).size\n };\n\n // Make sure the UUID for each scaled image is sent with the upload request,\n // to be consistent (since we may need to ensure it is sent for the original file as well).\n params[uuidParamName] = uploadData.retrieve({id: scaledId}).uuid;\n\n uploadData.setParentId(scaledId, originalId);\n paramsStore.addReadOnly(scaledId, params);\n });\n\n // If any scaled images are tied to this parent image, be SURE we send its UUID as an upload request\n // parameter as well.\n if (scaledIds.length) {\n (function() {\n var param = {};\n param[uuidParamName] = uploadData.retrieve({id: originalId}).uuid;\n paramsStore.addReadOnly(originalId, param);\n }());\n }\n }\n }\n });\n};\n\nqq.extend(qq.Scaler.prototype, {\n scaleImage: function(id, specs, api) {\n \"use strict\";\n\n if (!qq.supportedFeatures.scaling) {\n throw new qq.Error(\"Scaling is not supported in this browser!\");\n }\n\n var scalingEffort = new qq.Promise(),\n log = api.log,\n file = api.getFile(id),\n uploadData = api.uploadData.retrieve({id: id}),\n name = uploadData && uploadData.name,\n uuid = uploadData && uploadData.uuid,\n scalingOptions = {\n customResizer: specs.customResizer,\n sendOriginal: false,\n orient: specs.orient,\n defaultType: specs.type || null,\n defaultQuality: specs.quality,\n failedToScaleText: \"Unable to scale\",\n sizes: [{name: \"\", maxSize: specs.maxSize}]\n },\n scaler = new qq.Scaler(scalingOptions, log);\n\n if (!qq.Scaler || !qq.supportedFeatures.imagePreviews || !file) {\n scalingEffort.failure();\n\n log(\"Could not generate requested scaled image for \" + id + \". \" +\n \"Scaling is either not possible in this browser, or the file could not be located.\", \"error\");\n }\n else {\n (qq.bind(function() {\n // Assumption: There will never be more than one record\n var record = scaler.getFileRecords(uuid, name, file)[0];\n\n if (record && record.blob instanceof qq.BlobProxy) {\n record.blob.create().then(scalingEffort.success, scalingEffort.failure);\n }\n else {\n log(id + \" is not a scalable image!\", \"error\");\n scalingEffort.failure();\n }\n }, this)());\n }\n\n return scalingEffort;\n },\n\n // NOTE: We cannot reliably determine at this time if the UA supports a specific MIME type for the target format.\n // image/jpeg and image/png are the only safe choices at this time.\n _determineOutputType: function(spec) {\n \"use strict\";\n\n var requestedType = spec.requestedType,\n defaultType = spec.defaultType,\n referenceType = spec.refType;\n\n // If a default type and requested type have not been specified, this should be a\n // JPEG if the original type is a JPEG, otherwise, a PNG.\n if (!defaultType && !requestedType) {\n if (referenceType !== \"image/jpeg\") {\n return \"image/png\";\n }\n return referenceType;\n }\n\n // A specified default type is used when a requested type is not specified.\n if (!requestedType) {\n return defaultType;\n }\n\n // If requested type is specified, use it, as long as this recognized type is supported by the current UA\n if (qq.indexOf(Object.keys(qq.Identify.prototype.PREVIEWABLE_MIME_TYPES), requestedType) >= 0) {\n if (requestedType === \"image/tiff\") {\n return qq.supportedFeatures.tiffPreviews ? requestedType : defaultType;\n }\n\n return requestedType;\n }\n\n return defaultType;\n },\n\n // Get a file name for a generated scaled file record, based on the provided scaled image description\n _getName: function(originalName, scaledVersionProperties) {\n \"use strict\";\n\n var startOfExt = originalName.lastIndexOf(\".\"),\n versionType = scaledVersionProperties.type || \"image/png\",\n referenceType = scaledVersionProperties.refType,\n scaledName = \"\",\n scaledExt = qq.getExtension(originalName),\n nameAppendage = \"\";\n\n if (scaledVersionProperties.name && scaledVersionProperties.name.trim().length) {\n nameAppendage = \" (\" + scaledVersionProperties.name + \")\";\n }\n\n if (startOfExt >= 0) {\n scaledName = originalName.substr(0, startOfExt);\n\n if (referenceType !== versionType) {\n scaledExt = versionType.split(\"/\")[1];\n }\n\n scaledName += nameAppendage + \".\" + scaledExt;\n }\n else {\n scaledName = originalName + nameAppendage;\n }\n\n return scaledName;\n },\n\n // We want the smallest scaled file to be uploaded first\n _getSortedSizes: function(sizes) {\n \"use strict\";\n\n sizes = qq.extend([], sizes);\n\n return sizes.sort(function(a, b) {\n if (a.maxSize > b.maxSize) {\n return 1;\n }\n if (a.maxSize < b.maxSize) {\n return -1;\n }\n return 0;\n });\n },\n\n _generateScaledImage: function(spec, sourceFile) {\n \"use strict\";\n\n var self = this,\n customResizeFunction = spec.customResizeFunction,\n log = spec.log,\n maxSize = spec.maxSize,\n orient = spec.orient,\n type = spec.type,\n quality = spec.quality,\n failedText = spec.failedText,\n includeExif = spec.includeExif && sourceFile.type === \"image/jpeg\" && type === \"image/jpeg\",\n scalingEffort = new qq.Promise(),\n imageGenerator = new qq.ImageGenerator(log),\n canvas = document.createElement(\"canvas\");\n\n log(\"Attempting to generate scaled version for \" + sourceFile.name);\n\n imageGenerator.generate(sourceFile, canvas, {maxSize: maxSize, orient: orient, customResizeFunction: customResizeFunction}).then(function() {\n var scaledImageDataUri = canvas.toDataURL(type, quality),\n signalSuccess = function() {\n log(\"Success generating scaled version for \" + sourceFile.name);\n var blob = qq.dataUriToBlob(scaledImageDataUri);\n scalingEffort.success(blob);\n };\n\n if (includeExif) {\n self._insertExifHeader(sourceFile, scaledImageDataUri, log).then(function(scaledImageDataUriWithExif) {\n scaledImageDataUri = scaledImageDataUriWithExif;\n signalSuccess();\n },\n function() {\n log(\"Problem inserting EXIF header into scaled image. Using scaled image w/out EXIF data.\", \"error\");\n signalSuccess();\n });\n }\n else {\n signalSuccess();\n }\n }, function() {\n log(\"Failed attempt to generate scaled version for \" + sourceFile.name, \"error\");\n scalingEffort.failure(failedText);\n });\n\n return scalingEffort;\n },\n\n // Attempt to insert the original image's EXIF header into a scaled version.\n _insertExifHeader: function(originalImage, scaledImageDataUri, log) {\n \"use strict\";\n\n var reader = new FileReader(),\n insertionEffort = new qq.Promise(),\n originalImageDataUri = \"\";\n\n reader.onload = function() {\n originalImageDataUri = reader.result;\n insertionEffort.success(qq.ExifRestorer.restore(originalImageDataUri, scaledImageDataUri));\n };\n\n reader.onerror = function() {\n log(\"Problem reading \" + originalImage.name + \" during attempt to transfer EXIF data to scaled version.\", \"error\");\n insertionEffort.failure();\n };\n\n reader.readAsDataURL(originalImage);\n\n return insertionEffort;\n },\n\n _dataUriToBlob: function(dataUri) {\n \"use strict\";\n\n var byteString, mimeString, arrayBuffer, intArray;\n\n // convert base64 to raw binary data held in a string\n if (dataUri.split(\",\")[0].indexOf(\"base64\") >= 0) {\n byteString = atob(dataUri.split(\",\")[1]);\n }\n else {\n byteString = decodeURI(dataUri.split(\",\")[1]);\n }\n\n // extract the MIME\n mimeString = dataUri.split(\",\")[0]\n .split(\":\")[1]\n .split(\";\")[0];\n\n // write the bytes of the binary string to an ArrayBuffer\n arrayBuffer = new ArrayBuffer(byteString.length);\n intArray = new Uint8Array(arrayBuffer);\n qq.each(byteString, function(idx, character) {\n intArray[idx] = character.charCodeAt(0);\n });\n\n return this._createBlob(arrayBuffer, mimeString);\n },\n\n _createBlob: function(data, mime) {\n \"use strict\";\n\n var BlobBuilder = window.BlobBuilder ||\n window.WebKitBlobBuilder ||\n window.MozBlobBuilder ||\n window.MSBlobBuilder,\n blobBuilder = BlobBuilder && new BlobBuilder();\n\n if (blobBuilder) {\n blobBuilder.append(data);\n return blobBuilder.getBlob(mime);\n }\n else {\n return new Blob([data], {type: mime});\n }\n }\n});\n","//Based on MinifyJpeg\n//http://elicon.blog57.fc2.com/blog-entry-206.html\n\nqq.ExifRestorer = (function()\n{\n \n\tvar ExifRestorer = {};\n\t \n ExifRestorer.KEY_STR = \"ABCDEFGHIJKLMNOP\" +\n \"QRSTUVWXYZabcdef\" +\n \"ghijklmnopqrstuv\" +\n \"wxyz0123456789+/\" +\n \"=\";\n\n ExifRestorer.encode64 = function(input)\n {\n var output = \"\",\n chr1, chr2, chr3 = \"\",\n enc1, enc2, enc3, enc4 = \"\",\n i = 0;\n\n do {\n chr1 = input[i++];\n chr2 = input[i++];\n chr3 = input[i++];\n\n enc1 = chr1 >> 2;\n enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);\n enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);\n enc4 = chr3 & 63;\n\n if (isNaN(chr2)) {\n enc3 = enc4 = 64;\n } else if (isNaN(chr3)) {\n enc4 = 64;\n }\n\n output = output +\n this.KEY_STR.charAt(enc1) +\n this.KEY_STR.charAt(enc2) +\n this.KEY_STR.charAt(enc3) +\n this.KEY_STR.charAt(enc4);\n chr1 = chr2 = chr3 = \"\";\n enc1 = enc2 = enc3 = enc4 = \"\";\n } while (i < input.length);\n\n return output;\n };\n \n ExifRestorer.restore = function(origFileBase64, resizedFileBase64)\n {\n var expectedBase64Header = \"data:image/jpeg;base64,\";\n\n if (!origFileBase64.match(expectedBase64Header))\n {\n \treturn resizedFileBase64;\n } \n \n var rawImage = this.decode64(origFileBase64.replace(expectedBase64Header, \"\"));\n var segments = this.slice2Segments(rawImage);\n \n var image = this.exifManipulation(resizedFileBase64, segments);\n \n return expectedBase64Header + this.encode64(image);\n \n };\n\n\n ExifRestorer.exifManipulation = function(resizedFileBase64, segments)\n {\n var exifArray = this.getExifArray(segments),\n newImageArray = this.insertExif(resizedFileBase64, exifArray),\n aBuffer = new Uint8Array(newImageArray);\n\n return aBuffer;\n };\n\n\n ExifRestorer.getExifArray = function(segments)\n {\n var seg;\n for (var x = 0; x < segments.length; x++)\n {\n seg = segments[x];\n if (seg[0] == 255 & seg[1] == 225) //(ff e1)\n {\n return seg;\n }\n }\n return [];\n };\n\n\n ExifRestorer.insertExif = function(resizedFileBase64, exifArray)\n {\n var imageData = resizedFileBase64.replace(\"data:image/jpeg;base64,\", \"\"),\n buf = this.decode64(imageData),\n separatePoint = buf.indexOf(255,3),\n mae = buf.slice(0, separatePoint),\n ato = buf.slice(separatePoint),\n array = mae;\n\n array = array.concat(exifArray);\n array = array.concat(ato);\n return array;\n };\n\n\n \n ExifRestorer.slice2Segments = function(rawImageArray)\n {\n var head = 0,\n segments = [];\n\n while (1)\n {\n if (rawImageArray[head] == 255 & rawImageArray[head + 1] == 218){break;}\n if (rawImageArray[head] == 255 & rawImageArray[head + 1] == 216)\n {\n head += 2;\n }\n else\n {\n var length = rawImageArray[head + 2] * 256 + rawImageArray[head + 3],\n endPoint = head + length + 2,\n seg = rawImageArray.slice(head, endPoint);\n segments.push(seg);\n head = endPoint;\n }\n if (head > rawImageArray.length){break;}\n }\n\n return segments;\n };\n\n\n \n ExifRestorer.decode64 = function(input) \n {\n var output = \"\",\n chr1, chr2, chr3 = \"\",\n enc1, enc2, enc3, enc4 = \"\",\n i = 0,\n buf = [];\n\n // remove all characters that are not A-Z, a-z, 0-9, +, /, or =\n var base64test = /[^A-Za-z0-9\\+\\/\\=]/g;\n if (base64test.exec(input)) {\n throw new Error(\"There were invalid base64 characters in the input text. \" +\n \"Valid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='\");\n }\n input = input.replace(/[^A-Za-z0-9\\+\\/\\=]/g, \"\");\n\n do {\n enc1 = this.KEY_STR.indexOf(input.charAt(i++));\n enc2 = this.KEY_STR.indexOf(input.charAt(i++));\n enc3 = this.KEY_STR.indexOf(input.charAt(i++));\n enc4 = this.KEY_STR.indexOf(input.charAt(i++));\n\n chr1 = (enc1 << 2) | (enc2 >> 4);\n chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);\n chr3 = ((enc3 & 3) << 6) | enc4;\n\n buf.push(chr1);\n\n if (enc3 != 64) {\n buf.push(chr2);\n }\n if (enc4 != 64) {\n buf.push(chr3);\n }\n\n chr1 = chr2 = chr3 = \"\";\n enc1 = enc2 = enc3 = enc4 = \"\";\n\n } while (i < input.length);\n\n return buf;\n };\n\n \n return ExifRestorer;\n})();\n","/* globals qq */\n/**\n * Keeps a running tally of total upload progress for a batch of files.\n *\n * @param callback Invoked when total progress changes, passing calculated total loaded & total size values.\n * @param getSize Function that returns the size of a file given its ID\n * @constructor\n */\nqq.TotalProgress = function(callback, getSize) {\n \"use strict\";\n\n var perFileProgress = {},\n totalLoaded = 0,\n totalSize = 0,\n\n lastLoadedSent = -1,\n lastTotalSent = -1,\n callbackProxy = function(loaded, total) {\n if (loaded !== lastLoadedSent || total !== lastTotalSent) {\n callback(loaded, total);\n }\n\n lastLoadedSent = loaded;\n lastTotalSent = total;\n },\n\n /**\n * @param failed Array of file IDs that have failed\n * @param retryable Array of file IDs that are retryable\n * @returns true if none of the failed files are eligible for retry\n */\n noRetryableFiles = function(failed, retryable) {\n var none = true;\n\n qq.each(failed, function(idx, failedId) {\n if (qq.indexOf(retryable, failedId) >= 0) {\n none = false;\n return false;\n }\n });\n\n return none;\n },\n\n onCancel = function(id) {\n updateTotalProgress(id, -1, -1);\n delete perFileProgress[id];\n },\n\n onAllComplete = function(successful, failed, retryable) {\n if (failed.length === 0 || noRetryableFiles(failed, retryable)) {\n callbackProxy(totalSize, totalSize);\n this.reset();\n }\n },\n\n onNew = function(id) {\n var size = getSize(id);\n\n // We might not know the size yet, such as for blob proxies\n if (size > 0) {\n updateTotalProgress(id, 0, size);\n perFileProgress[id] = {loaded: 0, total: size};\n }\n },\n\n /**\n * Invokes the callback with the current total progress of all files in the batch. Called whenever it may\n * be appropriate to re-calculate and disseminate this data.\n *\n * @param id ID of a file that has changed in some important way\n * @param newLoaded New loaded value for this file. -1 if this value should no longer be part of calculations\n * @param newTotal New total size of the file. -1 if this value should no longer be part of calculations\n */\n updateTotalProgress = function(id, newLoaded, newTotal) {\n var oldLoaded = perFileProgress[id] ? perFileProgress[id].loaded : 0,\n oldTotal = perFileProgress[id] ? perFileProgress[id].total : 0;\n\n if (newLoaded === -1 && newTotal === -1) {\n totalLoaded -= oldLoaded;\n totalSize -= oldTotal;\n }\n else {\n if (newLoaded) {\n totalLoaded += newLoaded - oldLoaded;\n }\n if (newTotal) {\n totalSize += newTotal - oldTotal;\n }\n }\n\n callbackProxy(totalLoaded, totalSize);\n };\n\n qq.extend(this, {\n // Called when a batch of files has completed uploading.\n onAllComplete: onAllComplete,\n\n // Called when the status of a file has changed.\n onStatusChange: function(id, oldStatus, newStatus) {\n if (newStatus === qq.status.CANCELED || newStatus === qq.status.REJECTED) {\n onCancel(id);\n }\n else if (newStatus === qq.status.SUBMITTING) {\n onNew(id);\n }\n },\n\n // Called whenever the upload progress of an individual file has changed.\n onIndividualProgress: function(id, loaded, total) {\n updateTotalProgress(id, loaded, total);\n perFileProgress[id] = {loaded: loaded, total: total};\n },\n\n // Called whenever the total size of a file has changed, such as when the size of a generated blob is known.\n onNewSize: function(id) {\n onNew(id);\n },\n\n reset: function() {\n perFileProgress = {};\n totalLoaded = 0;\n totalSize = 0;\n }\n });\n};\n","/*globals qq*/\nqq.PasteSupport = function(o) {\n \"use strict\";\n\n var options, detachPasteHandler;\n\n options = {\n targetElement: null,\n callbacks: {\n log: function(message, level) {},\n pasteReceived: function(blob) {}\n }\n };\n\n function isImage(item) {\n return item.type &&\n item.type.indexOf(\"image/\") === 0;\n }\n\n function registerPasteHandler() {\n detachPasteHandler = qq(options.targetElement).attach(\"paste\", function(event) {\n var clipboardData = event.clipboardData;\n\n if (clipboardData) {\n qq.each(clipboardData.items, function(idx, item) {\n if (isImage(item)) {\n var blob = item.getAsFile();\n options.callbacks.pasteReceived(blob);\n }\n });\n }\n });\n }\n\n function unregisterPasteHandler() {\n if (detachPasteHandler) {\n detachPasteHandler();\n }\n }\n\n qq.extend(options, o);\n registerPasteHandler();\n\n qq.extend(this, {\n reset: function() {\n unregisterPasteHandler();\n }\n });\n};\n","/* globals qq */\n/**\n * Module that handles support for existing forms.\n *\n * @param options Options passed from the integrator-supplied options related to form support.\n * @param startUpload Callback to invoke when files \"stored\" should be uploaded.\n * @param log Proxy for the logger\n * @constructor\n */\nqq.FormSupport = function(options, startUpload, log) {\n \"use strict\";\n var self = this,\n interceptSubmit = options.interceptSubmit,\n formEl = options.element,\n autoUpload = options.autoUpload;\n\n // Available on the public API associated with this module.\n qq.extend(this, {\n // To be used by the caller to determine if the endpoint will be determined by some processing\n // that occurs in this module, such as if the form has an action attribute.\n // Ignore if `attachToForm === false`.\n newEndpoint: null,\n\n // To be used by the caller to determine if auto uploading should be allowed.\n // Ignore if `attachToForm === false`.\n newAutoUpload: autoUpload,\n\n // true if a form was detected and is being tracked by this module\n attachedToForm: false,\n\n // Returns an object with names and values for all valid form elements associated with the attached form.\n getFormInputsAsObject: function() {\n /* jshint eqnull:true */\n if (formEl == null) {\n return null;\n }\n\n return self._form2Obj(formEl);\n }\n });\n\n // If the form contains an action attribute, this should be the new upload endpoint.\n function determineNewEndpoint(formEl) {\n if (formEl.getAttribute(\"action\")) {\n self.newEndpoint = formEl.getAttribute(\"action\");\n }\n }\n\n // Return true only if the form is valid, or if we cannot make this determination.\n // If the form is invalid, ensure invalid field(s) are highlighted in the UI.\n function validateForm(formEl, nativeSubmit) {\n if (formEl.checkValidity && !formEl.checkValidity()) {\n log(\"Form did not pass validation checks - will not upload.\", \"error\");\n nativeSubmit();\n }\n else {\n return true;\n }\n }\n\n // Intercept form submit attempts, unless the integrator has told us not to do this.\n function maybeUploadOnSubmit(formEl) {\n var nativeSubmit = formEl.submit;\n\n // Intercept and squelch submit events.\n qq(formEl).attach(\"submit\", function(event) {\n event = event || window.event;\n\n if (event.preventDefault) {\n event.preventDefault();\n }\n else {\n event.returnValue = false;\n }\n\n validateForm(formEl, nativeSubmit) && startUpload();\n });\n\n // The form's `submit()` function may be called instead (i.e. via jQuery.submit()).\n // Intercept that too.\n formEl.submit = function() {\n validateForm(formEl, nativeSubmit) && startUpload();\n };\n }\n\n // If the element value passed from the uploader is a string, assume it is an element ID - select it.\n // The rest of the code in this module depends on this being an HTMLElement.\n function determineFormEl(formEl) {\n if (formEl) {\n if (qq.isString(formEl)) {\n formEl = document.getElementById(formEl);\n }\n\n if (formEl) {\n log(\"Attaching to form element.\");\n determineNewEndpoint(formEl);\n interceptSubmit && maybeUploadOnSubmit(formEl);\n }\n }\n\n return formEl;\n }\n\n formEl = determineFormEl(formEl);\n this.attachedToForm = !!formEl;\n};\n\nqq.extend(qq.FormSupport.prototype, {\n // Converts all relevant form fields to key/value pairs. This is meant to mimic the data a browser will\n // construct from a given form when the form is submitted.\n _form2Obj: function(form) {\n \"use strict\";\n var obj = {},\n notIrrelevantType = function(type) {\n var irrelevantTypes = [\n \"button\",\n \"image\",\n \"reset\",\n \"submit\"\n ];\n\n return qq.indexOf(irrelevantTypes, type.toLowerCase()) < 0;\n },\n radioOrCheckbox = function(type) {\n return qq.indexOf([\"checkbox\", \"radio\"], type.toLowerCase()) >= 0;\n },\n ignoreValue = function(el) {\n if (radioOrCheckbox(el.type) && !el.checked) {\n return true;\n }\n\n return el.disabled && el.type.toLowerCase() !== \"hidden\";\n },\n selectValue = function(select) {\n var value = null;\n\n qq.each(qq(select).children(), function(idx, child) {\n if (child.tagName.toLowerCase() === \"option\" && child.selected) {\n value = child.value;\n return false;\n }\n });\n\n return value;\n };\n\n qq.each(form.elements, function(idx, el) {\n if ((qq.isInput(el, true) || el.tagName.toLowerCase() === \"textarea\") &&\n notIrrelevantType(el.type) &&\n !ignoreValue(el)) {\n\n obj[el.name] = el.value;\n }\n else if (el.tagName.toLowerCase() === \"select\" && !ignoreValue(el)) {\n var value = selectValue(el);\n\n if (value !== null) {\n obj[el.name] = value;\n }\n }\n });\n\n return obj;\n }\n});\n","/*globals qq*/\n/**\n * Upload handler used that assumes the current user agent does not have any support for the\n * File API, and, therefore, makes use of iframes and forms to submit the files directly to\n * a generic server.\n *\n * @param options Options passed from the base handler\n * @param proxy Callbacks & methods used to query for or push out data/changes\n */\nqq.traditional = qq.traditional || {};\nqq.traditional.FormUploadHandler = function(options, proxy) {\n \"use strict\";\n\n var handler = this,\n getName = proxy.getName,\n getUuid = proxy.getUuid,\n log = proxy.log;\n\n /**\n * Returns json object received by iframe from server.\n */\n function getIframeContentJson(id, iframe) {\n /*jshint evil: true*/\n\n var response, doc, innerHtml;\n\n //IE may throw an \"access is denied\" error when attempting to access contentDocument on the iframe in some cases\n try {\n // iframe.contentWindow.document - for IE<7\n doc = iframe.contentDocument || iframe.contentWindow.document;\n innerHtml = doc.body.innerHTML;\n\n log(\"converting iframe's innerHTML to JSON\");\n log(\"innerHTML = \" + innerHtml);\n //plain text response may be wrapped in tag\n if (innerHtml && innerHtml.match(/^=0?atob(e.split(",")[1]):decodeURI(e.split(",")[1]),o=e.split(",")[0].split(":")[1].split(";")[0],t=new ArrayBuffer(n.length),i=new Uint8Array(t),qq.each(n,function(e,t){i[e]=t.charCodeAt(0)}),r(t,o)},qq.log=function(e,t){window.console&&(t&&"info"!==t?window.console[t]?window.console[t](e):window.console.log("<"+t+"> "+e):window.console.log(e))},qq.isObject=function(e){return e&&!e.nodeType&&"[object Object]"===Object.prototype.toString.call(e)},qq.isFunction=function(e){return"function"==typeof e},qq.isArray=function(e){return"[object Array]"===Object.prototype.toString.call(e)||e&&window.ArrayBuffer&&e.buffer&&e.buffer.constructor===ArrayBuffer},qq.isItemList=function(e){return"[object DataTransferItemList]"===Object.prototype.toString.call(e)},qq.isNodeList=function(e){return"[object NodeList]"===Object.prototype.toString.call(e)||e.item&&e.namedItem},qq.isString=function(e){return"[object String]"===Object.prototype.toString.call(e)},qq.trimStr=function(e){return String.prototype.trim?e.trim():e.replace(/^\s+|\s+$/g,"")},qq.format=function(e){var t=Array.prototype.slice.call(arguments,1),n=e,i=n.indexOf("{}");return qq.each(t,function(e,t){var o=n.substring(0,i),r=n.substring(i+2);if(n=o+t+r,i=n.indexOf("{}",i+t.length),i<0)return!1}),n},qq.isFile=function(e){return window.File&&"[object File]"===Object.prototype.toString.call(e)},qq.isFileList=function(e){return window.FileList&&"[object FileList]"===Object.prototype.toString.call(e)},qq.isFileOrInput=function(e){return qq.isFile(e)||qq.isInput(e)},qq.isInput=function(e,t){var n=function(e){var n=e.toLowerCase();return t?"file"!==n:"file"===n};return!!(window.HTMLInputElement&&"[object HTMLInputElement]"===Object.prototype.toString.call(e)&&e.type&&n(e.type))||!!(e.tagName&&"input"===e.tagName.toLowerCase()&&e.type&&n(e.type))},qq.isBlob=function(e){if(window.Blob&&"[object Blob]"===Object.prototype.toString.call(e))return!0},qq.isXhrUploadSupported=function(){var e=document.createElement("input");return e.type="file",void 0!==e.multiple&&"undefined"!=typeof File&&"undefined"!=typeof FormData&&"undefined"!=typeof qq.createXhrInstance().upload},qq.createXhrInstance=function(){if(window.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(e){return qq.log("Neither XHR or ActiveX are supported!","error"),null}},qq.isFolderDropSupported=function(e){return e.items&&e.items.length>0&&e.items[0].webkitGetAsEntry},qq.isFileChunkingSupported=function(){return!qq.androidStock()&&qq.isXhrUploadSupported()&&(void 0!==File.prototype.slice||void 0!==File.prototype.webkitSlice||void 0!==File.prototype.mozSlice)},qq.sliceBlob=function(e,t,n){var i=e.slice||e.mozSlice||e.webkitSlice;return i.call(e,t,n)},qq.arrayBufferToHex=function(e){var t="",n=new Uint8Array(e);return qq.each(n,function(e,n){var i=n.toString(16);i.length<2&&(i="0"+i),t+=i}),t},qq.readBlobToHex=function(e,t,n){var i=qq.sliceBlob(e,t,t+n),o=new FileReader,r=new qq.Promise;return o.onload=function(){r.success(qq.arrayBufferToHex(o.result))},o.onerror=r.failure,o.readAsArrayBuffer(i),r},qq.extend=function(e,t,n){return qq.each(t,function(t,i){n&&qq.isObject(i)?(void 0===e[t]&&(e[t]={}),qq.extend(e[t],i,!0)):e[t]=i}),e},qq.override=function(e,t){var n={},i=t(n);return qq.each(i,function(t,i){void 0!==e[t]&&(n[t]=e[t]),e[t]=i}),e},qq.indexOf=function(e,t,n){if(e.indexOf)return e.indexOf(t,n);n=n||0;var i=e.length;for(n<0&&(n+=i);n=0},qq.safari=function(){return void 0!==navigator.vendor&&navigator.vendor.indexOf("Apple")!==-1},qq.chrome=function(){return void 0!==navigator.vendor&&navigator.vendor.indexOf("Google")!==-1},qq.opera=function(){return void 0!==navigator.vendor&&navigator.vendor.indexOf("Opera")!==-1},qq.firefox=function(){return!qq.edge()&&!qq.ie11()&&navigator.userAgent.indexOf("Mozilla")!==-1&&void 0!==navigator.vendor&&""===navigator.vendor},qq.windows=function(){return"Win32"===navigator.platform},qq.android=function(){return navigator.userAgent.toLowerCase().indexOf("android")!==-1},qq.androidStock=function(){return qq.android()&&navigator.userAgent.toLowerCase().indexOf("chrome")<0},qq.ios6=function(){return qq.ios()&&navigator.userAgent.indexOf(" OS 6_")!==-1},qq.ios7=function(){return qq.ios()&&navigator.userAgent.indexOf(" OS 7_")!==-1},qq.ios8=function(){return qq.ios()&&navigator.userAgent.indexOf(" OS 8_")!==-1},qq.ios800=function(){return qq.ios()&&navigator.userAgent.indexOf(" OS 8_0 ")!==-1},qq.ios=function(){return navigator.userAgent.indexOf("iPad")!==-1||navigator.userAgent.indexOf("iPod")!==-1||navigator.userAgent.indexOf("iPhone")!==-1},qq.iosChrome=function(){return qq.ios()&&navigator.userAgent.indexOf("CriOS")!==-1},qq.iosSafari=function(){return qq.ios()&&!qq.iosChrome()&&navigator.userAgent.indexOf("Safari")!==-1},qq.iosSafariWebView=function(){return qq.ios()&&!qq.iosChrome()&&!qq.iosSafari()},qq.preventDefault=function(e){e.preventDefault?e.preventDefault():e.returnValue=!1},qq.toElement=function(){var e=document.createElement("div");return function(t){e.innerHTML=t;var n=e.firstChild;return e.removeChild(n),n}}(),qq.each=function(e,t){var n,i;if(e)if(window.Storage&&e.constructor===window.Storage)for(n=0;n0)return e.substr(t,e.length-t)},qq.getFilename=function(e){return qq.isInput(e)?e.value.replace(/.*(\/|\\)/,""):qq.isFile(e)&&null!==e.fileName&&void 0!==e.fileName?e.fileName:e.name},qq.DisposeSupport=function(){var e=[];return{dispose:function(){var t;do t=e.shift(),t&&t();while(t)},attach:function(){var e=arguments;this.addDisposer(qq(e[0]).attach.apply(this,Array.prototype.slice.call(arguments,1)))},addDisposer:function(t){e.push(t)}}}}(),function(){"use strict";"function"==typeof define&&define.amd?define(function(){return qq}):"undefined"!=typeof module&&module.exports?module.exports=qq:global.qq=qq}(),function(){"use strict";qq.Error=function(e){this.message="[Fine Uploader "+qq.version+"] "+e},qq.Error.prototype=new Error}(),qq.version="5.12.0",qq.supportedFeatures=function(){"use strict";function e(){var e,t=!0;try{e=document.createElement("input"),e.type="file",qq(e).hide(),e.disabled&&(t=!1)}catch(e){t=!1}return t}function t(){return(qq.chrome()||qq.opera())&&void 0!==navigator.userAgent.match(/Chrome\/[2][1-9]|Chrome\/[3-9][0-9]/)}function n(){return(qq.chrome()||qq.opera())&&void 0!==navigator.userAgent.match(/Chrome\/[1][4-9]|Chrome\/[2-9][0-9]/)}function i(){if(window.XMLHttpRequest){var e=qq.createXhrInstance();return void 0!==e.withCredentials}return!1}function o(){return void 0!==window.XDomainRequest}function r(){return!!i()||o()}function a(){return void 0!==document.createElement("input").webkitdirectory}function s(){try{return!!window.localStorage&&qq.isFunction(window.localStorage.setItem)}catch(e){return!1}}function u(){var e=document.createElement("span");return("draggable"in e||"ondragstart"in e&&"ondrop"in e)&&!qq.android()&&!qq.ios()}var l,c,d,p,f,q,h,m,g,_,b,v,S,w,y;return l=e(),p=l&&qq.isXhrUploadSupported(),c=p&&!qq.androidStock(),d=p&&u(),f=d&&t(),q=p&&qq.isFileChunkingSupported(),h=p&&q&&s(),m=p&&n(),g=l&&(void 0!==window.postMessage||p),b=i(),_=o(),v=r(),S=a(),w=p&&void 0!==window.FileReader,y=function(){return!!p&&(!qq.androidStock()&&!qq.iosChrome())}(),{ajaxUploading:p,blobUploading:c,canDetermineSize:p,chunking:q,deleteFileCors:v,deleteFileCorsXdr:_,deleteFileCorsXhr:b,dialogElement:!!window.HTMLDialogElement,fileDrop:d,folderDrop:f,folderSelection:S,imagePreviews:w,imageValidation:w,itemSizeValidation:p,pause:q,progressBar:y,resume:h,scaling:w&&c,tiffPreviews:qq.safari(),unlimitedScaledImageSize:!qq.ios(),uploading:l,uploadCors:g,uploadCustomHeaders:p,uploadNonMultipart:p,uploadViaPaste:m}}(),qq.isGenericPromise=function(e){"use strict";return!!(e&&e.then&&qq.isFunction(e.then))},qq.Promise=function(){"use strict";var e,t,n=[],i=[],o=[],r=0;qq.extend(this,{then:function(o,a){return 0===r?(o&&n.push(o),a&&i.push(a)):r===-1?a&&a.apply(null,t):o&&o.apply(null,e),this},done:function(n){return 0===r?o.push(n):n.apply(null,void 0===t?e:t),this},success:function(){return r=1,e=arguments,n.length&&qq.each(n,function(t,n){n.apply(null,e)}),o.length&&qq.each(o,function(t,n){n.apply(null,e)}),this},failure:function(){return r=-1,t=arguments,i.length&&qq.each(i,function(e,n){n.apply(null,t)}),o.length&&qq.each(o,function(e,n){n.apply(null,t)}),this}})},qq.BlobProxy=function(e,t){"use strict";qq.extend(this,{referenceBlob:e,create:function(){return t(e)}})},qq.UploadButton=function(e){"use strict";function t(){var e=document.createElement("input");return e.setAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME,i),e.setAttribute("title",a.title),o.setMultiple(a.multiple,e),a.folders&&qq.supportedFeatures.folderSelection&&e.setAttribute("webkitdirectory",""),a.acceptFiles&&e.setAttribute("accept",a.acceptFiles),e.setAttribute("type","file"),e.setAttribute("name",a.name),qq(e).css({position:"absolute",right:0,top:0,fontFamily:"Arial",fontSize:qq.ie()&&!qq.ie8()?"3500px":"118px",margin:0,padding:0,cursor:"pointer",opacity:0}),!qq.ie7()&&qq(e).css({height:"100%"}),a.element.appendChild(e),r.attach(e,"change",function(){a.onChange(e)}),r.attach(e,"mouseover",function(){qq(a.element).addClass(a.hoverClass)}),r.attach(e,"mouseout",function(){qq(a.element).removeClass(a.hoverClass)}),r.attach(e,"focus",function(){qq(a.element).addClass(a.focusClass)}),r.attach(e,"blur",function(){qq(a.element).removeClass(a.focusClass)}),e}var n,i,o=this,r=new qq.DisposeSupport,a={acceptFiles:null,element:null,focusClass:"qq-upload-button-focus",folders:!1,hoverClass:"qq-upload-button-hover",ios8BrowserCrashWorkaround:!1,multiple:!1,name:"qqfile",onChange:function(e){},title:null};qq.extend(a,e),i=qq.getUniqueId(),qq(a.element).css({position:"relative",overflow:"hidden",direction:"ltr"}),qq.extend(this,{getInput:function(){return n},getButtonId:function(){return i},setMultiple:function(e,t){var n=t||this.getInput();a.ios8BrowserCrashWorkaround&&qq.ios8()&&(qq.iosChrome()||qq.iosSafariWebView())?n.setAttribute("multiple",""):e?n.setAttribute("multiple",""):n.removeAttribute("multiple")},setAcceptFiles:function(e){e!==a.acceptFiles&&n.setAttribute("accept",e)},reset:function(){n.parentNode&&qq(n).remove(),qq(a.element).removeClass(a.focusClass),n=null,n=t()}}),n=t()},qq.UploadButton.BUTTON_ID_ATTR_NAME="qq-button-id",qq.UploadData=function(e){"use strict";function t(e){if(qq.isArray(e)){var t=[];return qq.each(e,function(e,n){t.push(o[n])}),t}return o[e]}function n(e){if(qq.isArray(e)){var t=[];return qq.each(e,function(e,n){t.push(o[r[n]])}),t}return o[r[e]]}function i(e){var t=[],n=[].concat(e);return qq.each(n,function(e,n){var i=a[n];void 0!==i&&qq.each(i,function(e,n){t.push(o[n])})}),t}var o=[],r={},a={},s={},u={};qq.extend(this,{addFile:function(t){var n=t.status||qq.status.SUBMITTING,i=o.push({name:t.name,originalName:t.name,uuid:t.uuid,size:null==t.size?-1:t.size,status:n})-1;return t.batchId&&(o[i].batchId=t.batchId,void 0===u[t.batchId]&&(u[t.batchId]=[]),u[t.batchId].push(i)),t.proxyGroupId&&(o[i].proxyGroupId=t.proxyGroupId,void 0===s[t.proxyGroupId]&&(s[t.proxyGroupId]=[]),s[t.proxyGroupId].push(i)),o[i].id=i,r[t.uuid]=i,void 0===a[n]&&(a[n]=[]),a[n].push(i),e.onStatusChange(i,null,n),i},retrieve:function(e){return qq.isObject(e)&&o.length?void 0!==e.id?t(e.id):void 0!==e.uuid?n(e.uuid):e.status?i(e.status):void 0:qq.extend([],o,!0)},reset:function(){o=[],r={},a={},u={}},setStatus:function(t,n){var i=o[t].status,r=qq.indexOf(a[i],t);a[i].splice(r,1),o[t].status=n,void 0===a[n]&&(a[n]=[]),a[n].push(t),e.onStatusChange(t,i,n)},uuidChanged:function(e,t){var n=o[e].uuid;o[e].uuid=t,r[t]=e,delete r[n]},updateName:function(e,t){o[e].name=t},updateSize:function(e,t){o[e].size=t},setParentId:function(e,t){o[e].parentId=t},getIdsInProxyGroup:function(e){var t=o[e].proxyGroupId;return t?s[t]:[]},getIdsInBatch:function(e){var t=o[e].batchId;return u[t]}})},qq.status={SUBMITTING:"submitting",SUBMITTED:"submitted",REJECTED:"rejected",QUEUED:"queued",CANCELED:"canceled",PAUSED:"paused",UPLOADING:"uploading",UPLOAD_RETRYING:"retrying upload",UPLOAD_SUCCESSFUL:"upload successful",UPLOAD_FAILED:"upload failed",DELETE_FAILED:"delete failed",DELETING:"deleting",DELETED:"deleted"},function(){"use strict";qq.basePublicApi={addBlobs:function(e,t,n){this.addFiles(e,t,n)},addInitialFiles:function(e){var t=this;qq.each(e,function(e,n){t._addCannedFile(n)})},addFiles:function(e,t,n){this._maybeHandleIos8SafariWorkaround();var i=0===this._storedIds.length?qq.getUniqueId():this._currentBatchId,o=qq.bind(function(e){this._handleNewFile({blob:e,name:this._options.blobs.defaultName},i,d)},this),r=qq.bind(function(e){this._handleNewFile(e,i,d)},this),a=qq.bind(function(e){var t=qq.canvasToBlob(e);this._handleNewFile({blob:t,name:this._options.blobs.defaultName+".png"},i,d)},this),s=qq.bind(function(e){var t=e.quality&&e.quality/100,n=qq.canvasToBlob(e.canvas,e.type,t);this._handleNewFile({blob:n,name:e.name},i,d)},this),u=qq.bind(function(e){if(qq.isInput(e)&&qq.supportedFeatures.ajaxUploading){var t=Array.prototype.slice.call(e.files),n=this;qq.each(t,function(e,t){n._handleNewFile(t,i,d)})}else this._handleNewFile(e,i,d)},this),l=function(){qq.isFileList(e)&&(e=Array.prototype.slice.call(e)),e=[].concat(e)},c=this,d=[];this._currentBatchId=i,e&&(l(),qq.each(e,function(e,t){qq.isFileOrInput(t)?u(t):qq.isBlob(t)?o(t):qq.isObject(t)?t.blob&&t.name?r(t):t.canvas&&t.name&&s(t):t.tagName&&"canvas"===t.tagName.toLowerCase()?a(t):c.log(t+" is not a valid file container! Ignoring!","warn")}),this.log("Received "+d.length+" files."),this._prepareItemsForUpload(d,t,n))},cancel:function(e){this._handler.cancel(e)},cancelAll:function(){var e=[],t=this;qq.extend(e,this._storedIds),qq.each(e,function(e,n){t.cancel(n)}),this._handler.cancelAll()},clearStoredFiles:function(){this._storedIds=[]},continueUpload:function(e){var t=this._uploadData.retrieve({id:e});return!(!qq.supportedFeatures.pause||!this._options.chunking.enabled)&&(t.status===qq.status.PAUSED?(this.log(qq.format("Paused file ID {} ({}) will be continued. Not paused.",e,this.getName(e))),this._uploadFile(e),!0):(this.log(qq.format("Ignoring continue for file ID {} ({}). Not paused.",e,this.getName(e)),"error"),!1))},deleteFile:function(e){return this._onSubmitDelete(e)},doesExist:function(e){return this._handler.isValid(e)},drawThumbnail:function(e,t,n,i,o){var r,a,s=new qq.Promise;return this._imageGenerator?(r=this._thumbnailUrls[e],a={customResizeFunction:o,maxSize:n>0?n:null,scale:n>0},!i&&qq.supportedFeatures.imagePreviews&&(r=this.getFile(e)),null==r?s.failure({container:t,error:"File or URL not found."}):this._imageGenerator.generate(r,t,a).then(function(e){s.success(e)},function(e,t){s.failure({container:e,error:t||"Problem generating thumbnail"})})):s.failure({container:t,error:"Missing image generator module"}),s},getButton:function(e){return this._getButton(this._buttonIdsForFileIds[e])},getEndpoint:function(e){return this._endpointStore.get(e)},getFile:function(e){return this._handler.getFile(e)||null},getInProgress:function(){return this._uploadData.retrieve({status:[qq.status.UPLOADING,qq.status.UPLOAD_RETRYING,qq.status.QUEUED]}).length},getName:function(e){return this._uploadData.retrieve({id:e}).name},getParentId:function(e){var t=this.getUploads({id:e}),n=null;return t&&void 0!==t.parentId&&(n=t.parentId),n},getResumableFilesData:function(){return this._handler.getResumableFilesData()},getSize:function(e){return this._uploadData.retrieve({id:e}).size},getNetUploads:function(){return this._netUploaded},getRemainingAllowedItems:function(){var e=this._currentItemLimit;return e>0?e-this._netUploadedOrQueued:null},getUploads:function(e){return this._uploadData.retrieve(e)},getUuid:function(e){return this._uploadData.retrieve({id:e}).uuid},log:function(e,t){!this._options.debug||t&&"info"!==t?t&&"info"!==t&&qq.log("[Fine Uploader "+qq.version+"] "+e,t):qq.log("[Fine Uploader "+qq.version+"] "+e)},pauseUpload:function(e){var t=this._uploadData.retrieve({id:e});if(!qq.supportedFeatures.pause||!this._options.chunking.enabled)return!1;if(qq.indexOf([qq.status.UPLOADING,qq.status.UPLOAD_RETRYING],t.status)>=0){if(this._handler.pause(e))return this._uploadData.setStatus(e,qq.status.PAUSED),!0;this.log(qq.format("Unable to pause file ID {} ({}).",e,this.getName(e)),"error")}else this.log(qq.format("Ignoring pause for file ID {} ({}). Not in progress.",e,this.getName(e)),"error");return!1},reset:function(){this.log("Resetting uploader..."),this._handler.reset(),this._storedIds=[],this._autoRetries=[],this._retryTimeouts=[],this._preventRetries=[],this._thumbnailUrls=[],qq.each(this._buttons,function(e,t){t.reset()}),this._paramsStore.reset(),this._endpointStore.reset(),this._netUploadedOrQueued=0,this._netUploaded=0,this._uploadData.reset(),this._buttonIdsForFileIds=[],this._pasteHandler&&this._pasteHandler.reset(),this._options.session.refreshOnReset&&this._refreshSessionData(),this._succeededSinceLastAllComplete=[],this._failedSinceLastAllComplete=[],this._totalProgress&&this._totalProgress.reset()},retry:function(e){return this._manualRetry(e)},scaleImage:function(e,t){var n=this;return qq.Scaler.prototype.scaleImage(e,t,{log:qq.bind(n.log,n),getFile:qq.bind(n.getFile,n),uploadData:n._uploadData})},setCustomHeaders:function(e,t){this._customHeadersStore.set(e,t)},setDeleteFileCustomHeaders:function(e,t){this._deleteFileCustomHeadersStore.set(e,t)},setDeleteFileEndpoint:function(e,t){this._deleteFileEndpointStore.set(e,t)},setDeleteFileParams:function(e,t){this._deleteFileParamsStore.set(e,t)},setEndpoint:function(e,t){this._endpointStore.set(e,t)},setForm:function(e){this._updateFormSupportAndParams(e)},setItemLimit:function(e){this._currentItemLimit=e},setName:function(e,t){this._uploadData.updateName(e,t)},setParams:function(e,t){this._paramsStore.set(e,t)},setUuid:function(e,t){return this._uploadData.uuidChanged(e,t)},uploadStoredFiles:function(){0===this._storedIds.length?this._itemError("noFilesError"):this._uploadStoredFiles()}},qq.basePrivateApi={_addCannedFile:function(e){var t=this._uploadData.addFile({uuid:e.uuid,name:e.name,size:e.size,status:qq.status.UPLOAD_SUCCESSFUL});return e.deleteFileEndpoint&&this.setDeleteFileEndpoint(e.deleteFileEndpoint,t),e.deleteFileParams&&this.setDeleteFileParams(e.deleteFileParams,t),e.thumbnailUrl&&(this._thumbnailUrls[t]=e.thumbnailUrl),this._netUploaded++,this._netUploadedOrQueued++,t},_annotateWithButtonId:function(e,t){qq.isFile(e)&&(e.qqButtonId=this._getButtonId(t))},_batchError:function(e){this._options.callbacks.onError(null,null,e,void 0)},_createDeleteHandler:function(){var e=this;return new qq.DeleteFileAjaxRequester({method:this._options.deleteFile.method.toUpperCase(),maxConnections:this._options.maxConnections,uuidParamName:this._options.request.uuidName,customHeaders:this._deleteFileCustomHeadersStore,paramsStore:this._deleteFileParamsStore,endpointStore:this._deleteFileEndpointStore,cors:this._options.cors,log:qq.bind(e.log,e),onDelete:function(t){e._onDelete(t),e._options.callbacks.onDelete(t)},onDeleteComplete:function(t,n,i){e._onDeleteComplete(t,n,i),e._options.callbacks.onDeleteComplete(t,n,i)}})},_createPasteHandler:function(){var e=this;return new qq.PasteSupport({targetElement:this._options.paste.targetElement,callbacks:{log:qq.bind(e.log,e),pasteReceived:function(t){e._handleCheckedCallback({name:"onPasteReceived",callback:qq.bind(e._options.callbacks.onPasteReceived,e,t),onSuccess:qq.bind(e._handlePasteSuccess,e,t),identifier:"pasted image"})}}})},_createStore:function(e,t){var n={},i=e,o={},r=t,a=function(e){return qq.isObject(e)?qq.extend({},e):e},s=function(){return qq.isFunction(r)?r():r},u=function(e,t){r&&qq.isObject(t)&&qq.extend(t,s()),o[e]&&qq.extend(t,o[e])};return{set:function(e,t){null==t?(n={},i=a(e)):n[t]=a(e)},get:function(e){var t;return t=null!=e&&n[e]?n[e]:a(i),u(e,t),a(t)},addReadOnly:function(e,t){qq.isObject(n)&&(null===e?qq.isFunction(t)?r=t:(r=r||{},qq.extend(r,t)):(o[e]=o[e]||{},qq.extend(o[e],t)))},remove:function(e){return delete n[e]},reset:function(){n={},o={},i=e}}},_createUploadDataTracker:function(){var e=this;return new qq.UploadData({getName:function(t){return e.getName(t)},getUuid:function(t){return e.getUuid(t)},getSize:function(t){return e.getSize(t)},onStatusChange:function(t,n,i){e._onUploadStatusChange(t,n,i),e._options.callbacks.onStatusChange(t,n,i),e._maybeAllComplete(t,i),e._totalProgress&&setTimeout(function(){e._totalProgress.onStatusChange(t,n,i)},0)}})},_createUploadButton:function(e){function t(){return!!qq.supportedFeatures.ajaxUploading&&(!(i._options.workarounds.iosEmptyVideos&&qq.ios()&&!qq.ios6()&&i._isAllowedExtension(r,".mov"))&&(void 0===e.multiple?i._options.multiple:e.multiple))}var n,i=this,o=e.accept||this._options.validation.acceptFiles,r=e.allowedExtensions||this._options.validation.allowedExtensions;return n=new qq.UploadButton({acceptFiles:o,element:e.element,focusClass:this._options.classes.buttonFocus,folders:e.folders,hoverClass:this._options.classes.buttonHover,ios8BrowserCrashWorkaround:this._options.workarounds.ios8BrowserCrash,multiple:t(),name:this._options.request.inputName,onChange:function(e){i._onInputChange(e)},title:null==e.title?this._options.text.fileInputTitle:e.title}),this._disposeSupport.addDisposer(function(){n.dispose()}),i._buttons.push(n),n},_createUploadHandler:function(e,t){var n=this,i={},o={debug:this._options.debug,maxConnections:this._options.maxConnections,cors:this._options.cors,paramsStore:this._paramsStore,endpointStore:this._endpointStore,chunking:this._options.chunking,resume:this._options.resume,blobs:this._options.blobs,log:qq.bind(n.log,n),preventRetryParam:this._options.retry.preventRetryResponseProperty,onProgress:function(e,t,o,r){o<0||r<0||(i[e]?i[e].loaded===o&&i[e].total===r||(n._onProgress(e,t,o,r),n._options.callbacks.onProgress(e,t,o,r)):(n._onProgress(e,t,o,r),n._options.callbacks.onProgress(e,t,o,r)),i[e]={loaded:o,total:r})},onComplete:function(e,t,o,r){delete i[e];var a,s=n.getUploads({id:e}).status;s!==qq.status.UPLOAD_SUCCESSFUL&&s!==qq.status.UPLOAD_FAILED&&(a=n._onComplete(e,t,o,r),a instanceof qq.Promise?a.done(function(){n._options.callbacks.onComplete(e,t,o,r)}):n._options.callbacks.onComplete(e,t,o,r))},onCancel:function(e,t,i){var o=new qq.Promise;return n._handleCheckedCallback({name:"onCancel",callback:qq.bind(n._options.callbacks.onCancel,n,e,t),onFailure:o.failure,onSuccess:function(){i.then(function(){n._onCancel(e,t)}),o.success()},identifier:e}),o},onUploadPrep:qq.bind(this._onUploadPrep,this),onUpload:function(e,t){n._onUpload(e,t),n._options.callbacks.onUpload(e,t)},onUploadChunk:function(e,t,i){n._onUploadChunk(e,i),n._options.callbacks.onUploadChunk(e,t,i)},onUploadChunkSuccess:function(e,t,i,o){n._options.callbacks.onUploadChunkSuccess.apply(n,arguments)},onResume:function(e,t,i){return n._options.callbacks.onResume(e,t,i)},onAutoRetry:function(e,t,i,o){return n._onAutoRetry.apply(n,arguments)},onUuidChanged:function(e,t){n.log("Server requested UUID change from '"+n.getUuid(e)+"' to '"+t+"'"),n.setUuid(e,t)},getName:qq.bind(n.getName,n),getUuid:qq.bind(n.getUuid,n),getSize:qq.bind(n.getSize,n),setSize:qq.bind(n._setSize,n),getDataByUuid:function(e){return n.getUploads({uuid:e})},isQueued:function(e){var t=n.getUploads({id:e}).status;return t===qq.status.QUEUED||t===qq.status.SUBMITTED||t===qq.status.UPLOAD_RETRYING||t===qq.status.PAUSED},getIdsInProxyGroup:n._uploadData.getIdsInProxyGroup,getIdsInBatch:n._uploadData.getIdsInBatch};return qq.each(this._options.request,function(e,t){o[e]=t}),o.customHeaders=this._customHeadersStore,e&&qq.each(e,function(e,t){o[e]=t}),new qq.UploadHandlerController(o,t)},_fileOrBlobRejected:function(e){this._netUploadedOrQueued--,this._uploadData.setStatus(e,qq.status.REJECTED)},_formatSize:function(e){if(0===e)return e+this._options.text.sizeSymbols[0];var t=-1;do e/=1e3,t++;while(e>999);return Math.max(e,.1).toFixed(1)+this._options.text.sizeSymbols[t]},_generateExtraButtonSpecs:function(){var e=this;this._extraButtonSpecs={},qq.each(this._options.extraButtons,function(t,n){var i=n.multiple,o=qq.extend({},e._options.validation,!0),r=qq.extend({},n);void 0===i&&(i=e._options.multiple),r.validation&&qq.extend(o,n.validation,!0),qq.extend(r,{multiple:i,validation:o},!0),e._initExtraButton(r)})},_getButton:function(e){var t=this._extraButtonSpecs[e];return t?t.element:e===this._defaultButtonId?this._options.button:void 0},_getButtonId:function(e){var t,n,i=e;if(i instanceof qq.BlobProxy&&(i=i.referenceBlob),i&&!qq.isBlob(i)){if(qq.isFile(i))return i.qqButtonId;if("input"===i.tagName.toLowerCase()&&"file"===i.type.toLowerCase())return i.getAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME);if(t=i.getElementsByTagName("input"),qq.each(t,function(e,t){if("file"===t.getAttribute("type"))return n=t,!1}),n)return n.getAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME)}},_getNotFinished:function(){return this._uploadData.retrieve({status:[qq.status.UPLOADING,qq.status.UPLOAD_RETRYING,qq.status.QUEUED,qq.status.SUBMITTING,qq.status.SUBMITTED,qq.status.PAUSED]}).length},_getValidationBase:function(e){var t=this._extraButtonSpecs[e];return t?t.validation:this._options.validation},_getValidationDescriptor:function(e){return e.file instanceof qq.BlobProxy?{name:qq.getFilename(e.file.referenceBlob),size:e.file.referenceBlob.size}:{name:this.getUploads({id:e.id}).name,size:this.getUploads({id:e.id}).size}},_getValidationDescriptors:function(e){var t=this,n=[];return qq.each(e,function(e,i){n.push(t._getValidationDescriptor(i))}),n},_handleCameraAccess:function(){if(this._options.camera.ios&&qq.ios()){var e="image/*;capture=camera",t=this._options.camera.button,n=t?this._getButtonId(t):this._defaultButtonId,i=this._options;n&&n!==this._defaultButtonId&&(i=this._extraButtonSpecs[n]),i.multiple=!1,null===i.validation.acceptFiles?i.validation.acceptFiles=e:i.validation.acceptFiles+=","+e,qq.each(this._buttons,function(e,t){if(t.getButtonId()===n)return t.setMultiple(i.multiple),t.setAcceptFiles(i.acceptFiles),!1})}},_handleCheckedCallback:function(e){var t=this,n=e.callback();return qq.isGenericPromise(n)?(this.log(e.name+" - waiting for "+e.name+" promise to be fulfilled for "+e.identifier),n.then(function(n){t.log(e.name+" promise success for "+e.identifier),e.onSuccess(n)},function(){e.onFailure?(t.log(e.name+" promise failure for "+e.identifier),e.onFailure()):t.log(e.name+" promise failure for "+e.identifier)})):(n!==!1?e.onSuccess(n):e.onFailure?(this.log(e.name+" - return value was 'false' for "+e.identifier+". Invoking failure callback."),e.onFailure()):this.log(e.name+" - return value was 'false' for "+e.identifier+". Will not proceed."),n)},_handleNewFile:function(e,t,n){var i=this,o=qq.getUniqueId(),r=-1,a=qq.getFilename(e),s=e.blob||e,u=this._customNewFileHandler?this._customNewFileHandler:qq.bind(i._handleNewFileGeneric,i);!qq.isInput(s)&&s.size>=0&&(r=s.size),u(s,a,o,r,n,t,this._options.request.uuidName,{uploadData:i._uploadData,paramsStore:i._paramsStore,addFileToHandler:function(e,t){i._handler.add(e,t),i._netUploadedOrQueued++,i._trackButton(e);
-}})},_handleNewFileGeneric:function(e,t,n,i,o,r){var a=this._uploadData.addFile({uuid:n,name:t,size:i,batchId:r});this._handler.add(a,e),this._trackButton(a),this._netUploadedOrQueued++,o.push({id:a,file:e})},_handlePasteSuccess:function(e,t){var n=e.type.split("/")[1],i=t;null==i&&(i=this._options.paste.defaultName),i+="."+n,this.addFiles({name:i,blob:e})},_initExtraButton:function(e){var t=this._createUploadButton({accept:e.validation.acceptFiles,allowedExtensions:e.validation.allowedExtensions,element:e.element,folders:e.folders,multiple:e.multiple,title:e.fileInputTitle});this._extraButtonSpecs[t.getButtonId()]=e},_initFormSupportAndParams:function(){this._formSupport=qq.FormSupport&&new qq.FormSupport(this._options.form,qq.bind(this.uploadStoredFiles,this),qq.bind(this.log,this)),this._formSupport&&this._formSupport.attachedToForm?(this._paramsStore=this._createStore(this._options.request.params,this._formSupport.getFormInputsAsObject),this._options.autoUpload=this._formSupport.newAutoUpload,this._formSupport.newEndpoint&&(this._options.request.endpoint=this._formSupport.newEndpoint)):this._paramsStore=this._createStore(this._options.request.params)},_isDeletePossible:function(){return!(!qq.DeleteFileAjaxRequester||!this._options.deleteFile.enabled)&&(!this._options.cors.expected||(!!qq.supportedFeatures.deleteFileCorsXhr||!(!qq.supportedFeatures.deleteFileCorsXdr||!this._options.cors.allowXdr)))},_isAllowedExtension:function(e,t){var n=!1;return!e.length||(qq.each(e,function(e,i){if(qq.isString(i)){var o=new RegExp("\\."+i+"$","i");if(null!=t.match(o))return n=!0,!1}}),n)},_itemError:function(e,t,n){function i(e,t){a=a.replace(e,t)}var o,r,a=this._options.messages[e],s=[],u=[].concat(t),l=u[0],c=this._getButtonId(n),d=this._getValidationBase(c);return qq.each(d.allowedExtensions,function(e,t){qq.isString(t)&&s.push(t)}),o=s.join(", ").toLowerCase(),i("{file}",this._options.formatFileName(l)),i("{extensions}",o),i("{sizeLimit}",this._formatSize(d.sizeLimit)),i("{minSizeLimit}",this._formatSize(d.minSizeLimit)),r=a.match(/(\{\w+\})/g),null!==r&&qq.each(r,function(e,t){i(t,u[e])}),this._options.callbacks.onError(null,l,a,void 0),a},_manualRetry:function(e,t){if(this._onBeforeManualRetry(e))return this._netUploadedOrQueued++,this._uploadData.setStatus(e,qq.status.UPLOAD_RETRYING),t?t(e):this._handler.retry(e),!0},_maybeAllComplete:function(e,t){var n=this,i=this._getNotFinished();t===qq.status.UPLOAD_SUCCESSFUL?this._succeededSinceLastAllComplete.push(e):t===qq.status.UPLOAD_FAILED&&this._failedSinceLastAllComplete.push(e),0===i&&(this._succeededSinceLastAllComplete.length||this._failedSinceLastAllComplete.length)&&setTimeout(function(){n._onAllComplete(n._succeededSinceLastAllComplete,n._failedSinceLastAllComplete)},0)},_maybeHandleIos8SafariWorkaround:function(){var e=this;if(this._options.workarounds.ios8SafariUploads&&qq.ios800()&&qq.iosSafari())throw setTimeout(function(){window.alert(e._options.messages.unsupportedBrowserIos8Safari)},0),new qq.Error(this._options.messages.unsupportedBrowserIos8Safari)},_maybeParseAndSendUploadError:function(e,t,n,i){if(!n.success)if(i&&200!==i.status&&!n.error)this._options.callbacks.onError(e,t,"XHR returned response code "+i.status,i);else{var o=n.error?n.error:this._options.text.defaultResponseError;this._options.callbacks.onError(e,t,o,i)}},_maybeProcessNextItemAfterOnValidateCallback:function(e,t,n,i,o){var r=this;if(t.length>n)if(e||!this._options.validation.stopOnFirstInvalidFile)setTimeout(function(){var e=r._getValidationDescriptor(t[n]),a=r._getButtonId(t[n].file),s=r._getButton(a);r._handleCheckedCallback({name:"onValidate",callback:qq.bind(r._options.callbacks.onValidate,r,e,s),onSuccess:qq.bind(r._onValidateCallbackSuccess,r,t,n,i,o),onFailure:qq.bind(r._onValidateCallbackFailure,r,t,n,i,o),identifier:"Item '"+e.name+"', size: "+e.size})},0);else if(!e)for(;n0&&this._netUploadedOrQueued+1>n?(this._itemError("retryFailTooManyItems"),!1):(this.log("Retrying upload for '"+t+"' (id: "+e+")..."),!0))):(this.log("'"+e+"' is not a valid file ID","error"),!1)},_onCancel:function(e,t){this._netUploadedOrQueued--,clearTimeout(this._retryTimeouts[e]);var n=qq.indexOf(this._storedIds,e);!this._options.autoUpload&&n>=0&&this._storedIds.splice(n,1),this._uploadData.setStatus(e,qq.status.CANCELED)},_onComplete:function(e,t,n,i){return n.success?(n.thumbnailUrl&&(this._thumbnailUrls[e]=n.thumbnailUrl),this._netUploaded++,this._uploadData.setStatus(e,qq.status.UPLOAD_SUCCESSFUL)):(this._netUploadedOrQueued--,this._uploadData.setStatus(e,qq.status.UPLOAD_FAILED),n[this._options.retry.preventRetryResponseProperty]===!0&&(this._preventRetries[e]=!0)),this._maybeParseAndSendUploadError(e,t,n,i),!!n.success},_onDelete:function(e){this._uploadData.setStatus(e,qq.status.DELETING)},_onDeleteComplete:function(e,t,n){var i=this.getName(e);n?(this._uploadData.setStatus(e,qq.status.DELETE_FAILED),this.log("Delete request for '"+i+"' has failed.","error"),void 0===t.withCredentials?this._options.callbacks.onError(e,i,"Delete request failed",t):this._options.callbacks.onError(e,i,"Delete request failed with response code "+t.status,t)):(this._netUploadedOrQueued--,this._netUploaded--,this._handler.expunge(e),this._uploadData.setStatus(e,qq.status.DELETED),this.log("Delete request for '"+i+"' has succeeded."))},_onInputChange:function(e){var t;if(qq.supportedFeatures.ajaxUploading){for(t=0;t0&&this.addFiles(e);qq.each(this._buttons,function(e,t){t.reset()})},_onProgress:function(e,t,n,i){this._totalProgress&&this._totalProgress.onIndividualProgress(e,n,i)},_onSubmit:function(e,t){},_onSubmitCallbackSuccess:function(e,t){this._onSubmit.apply(this,arguments),this._uploadData.setStatus(e,qq.status.SUBMITTED),this._onSubmitted.apply(this,arguments),this._options.autoUpload?(this._options.callbacks.onSubmitted.apply(this,arguments),this._uploadFile(e)):(this._storeForLater(e),this._options.callbacks.onSubmitted.apply(this,arguments))},_onSubmitDelete:function(e,t,n){var i,o=this.getUuid(e);return t&&(i=qq.bind(t,this,e,o,n)),this._isDeletePossible()?(this._handleCheckedCallback({name:"onSubmitDelete",callback:qq.bind(this._options.callbacks.onSubmitDelete,this,e),onSuccess:i||qq.bind(this._deleteHandler.sendDelete,this,e,o,n),identifier:e}),!0):(this.log("Delete request ignored for ID "+e+", delete feature is disabled or request not possible due to CORS on a user agent that does not support pre-flighting.","warn"),!1)},_onSubmitted:function(e){},_onTotalProgress:function(e,t){this._options.callbacks.onTotalProgress(e,t)},_onUploadPrep:function(e){},_onUpload:function(e,t){this._uploadData.setStatus(e,qq.status.UPLOADING)},_onUploadChunk:function(e,t){},_onUploadStatusChange:function(e,t,n){n===qq.status.PAUSED&&clearTimeout(this._retryTimeouts[e])},_onValidateBatchCallbackFailure:function(e){var t=this;qq.each(e,function(e,n){t._fileOrBlobRejected(n.id)})},_onValidateBatchCallbackSuccess:function(e,t,n,i,o){var r,a=this._currentItemLimit,s=this._netUploadedOrQueued;0===a||s<=a?t.length>0?this._handleCheckedCallback({name:"onValidate",callback:qq.bind(this._options.callbacks.onValidate,this,e[0],o),onSuccess:qq.bind(this._onValidateCallbackSuccess,this,t,0,n,i),onFailure:qq.bind(this._onValidateCallbackFailure,this,t,0,n,i),identifier:"Item '"+t[0].file.name+"', size: "+t[0].file.size}):this._itemError("noFilesError"):(this._onValidateBatchCallbackFailure(t),r=this._options.messages.tooManyItemsError.replace(/\{netItems\}/g,s).replace(/\{itemLimit\}/g,a),this._batchError(r))},_onValidateCallbackFailure:function(e,t,n,i){var o=t+1;this._fileOrBlobRejected(e[t].id,e[t].file.name),this._maybeProcessNextItemAfterOnValidateCallback(!1,e,o,n,i)},_onValidateCallbackSuccess:function(e,t,n,i){var o=this,r=t+1,a=this._getValidationDescriptor(e[t]);this._validateFileOrBlobData(e[t],a).then(function(){o._upload(e[t].id,n,i),o._maybeProcessNextItemAfterOnValidateCallback(!0,e,r,n,i)},function(){o._maybeProcessNextItemAfterOnValidateCallback(!1,e,r,n,i)})},_prepareItemsForUpload:function(e,t,n){if(0===e.length)return void this._itemError("noFilesError");var i=this._getValidationDescriptors(e),o=this._getButtonId(e[0].file),r=this._getButton(o);this._handleCheckedCallback({name:"onValidateBatch",callback:qq.bind(this._options.callbacks.onValidateBatch,this,i,r),onSuccess:qq.bind(this._onValidateBatchCallbackSuccess,this,i,e,t,n,r),onFailure:qq.bind(this._onValidateBatchCallbackFailure,this,e),identifier:"batch validation"})},_preventLeaveInProgress:function(){var e=this;this._disposeSupport.attach(window,"beforeunload",function(t){if(e.getInProgress())return t=t||window.event,t.returnValue=e._options.messages.onLeave,e._options.messages.onLeave})},_refreshSessionData:function(){var e=this,t=this._options.session;qq.Session&&null!=this._options.session.endpoint&&(this._session||(qq.extend(t,{cors:this._options.cors}),t.log=qq.bind(this.log,this),t.addFileRecord=qq.bind(this._addCannedFile,this),this._session=new qq.Session(t)),setTimeout(function(){e._session.refresh().then(function(t,n){e._sessionRequestComplete(),e._options.callbacks.onSessionRequestComplete(t,!0,n)},function(t,n){e._options.callbacks.onSessionRequestComplete(t,!1,n)})},0))},_sessionRequestComplete:function(){},_setSize:function(e,t){this._uploadData.updateSize(e,t),this._totalProgress&&this._totalProgress.onNewSize(e)},_shouldAutoRetry:function(e,t,n){var i=this._uploadData.retrieve({id:e});return!!(!this._preventRetries[e]&&this._options.retry.enableAuto&&i.status!==qq.status.PAUSED&&(void 0===this._autoRetries[e]&&(this._autoRetries[e]=0),this._autoRetries[e]0&&s.sizeLimit&&r>s.sizeLimit?(this._itemError("sizeError",o,i),u.failure()):r>0&&r=0}function n(e){var t=!1;return qq.each(t,function(e,n){if(qq.indexOf(["Accept","Accept-Language","Content-Language","Content-Type"],n)<0)return t=!0,!1}),t}function i(e){return w.cors.expected&&void 0===e.withCredentials}function o(){var e;return(window.XMLHttpRequest||window.ActiveXObject)&&(e=qq.createXhrInstance(),void 0===e.withCredentials&&(e=new XDomainRequest,e.onload=function(){},e.onerror=function(){},e.ontimeout=function(){},e.onprogress=function(){})),e}function r(e,t){var n=S[e].xhr;return n||(n=t?t:w.cors.expected?o():qq.createXhrInstance(),S[e].xhr=n),n}function a(e){var t,n=qq.indexOf(v,e),i=w.maxConnections;delete S[e],v.splice(n,1),v.length>=i&&n=0?o.send(qq.obj2url(s,"")):s&&w.contentType&&w.contentType.toLowerCase().indexOf("application/json")>=0?o.send(JSON.stringify(s)):o.send(s),o}function c(e,t,n){var i=w.endpointStore.get(e),o=S[e].addToPath;return void 0!=o&&(i+="/"+o),b&&t&&(i=qq.obj2url(t,i)),n&&(i=qq.obj2url(n,i)),i}function d(e){return function(){4===r(e).readyState&&s(e)}}function p(e){var t=w.onProgress;t&&(r(e).upload.onprogress=function(n){n.lengthComputable&&t(e,n.loaded,n.total)})}function f(e){return function(){s(e)}}function q(e){return function(){s(e,!0)}}function h(e){var o=r(e),a=w.customHeaders,s=S[e].additionalHeaders||{},u=w.method,l={};i(o)||(w.acceptHeader&&o.setRequestHeader("Accept",w.acceptHeader),w.allowXRequestedWithAndCacheControl&&(w.cors.expected&&t()&&!n(a)||(o.setRequestHeader("X-Requested-With","XMLHttpRequest"),o.setRequestHeader("Cache-Control","no-cache"))),!w.contentType||"POST"!==u&&"PUT"!==u||o.setRequestHeader("Content-Type",w.contentType),qq.extend(l,qq.isFunction(a)?a(e):a),qq.extend(l,s),qq.each(l,function(e,t){o.setRequestHeader(e,t)}))}function m(e){return qq.indexOf(w.successfulResponseCodes[w.method],e)>=0}function g(e,t,n,i,o,r,a){S[e]={addToPath:n,additionalParams:i,additionalQueryParams:o,additionalHeaders:r,payload:a};var s=v.push(e);if(s<=w.maxConnections)return l(e,t)}var _,b,v=[],S={},w={acceptHeader:null,validMethods:["PATCH","POST","PUT"],method:"POST",contentType:"application/x-www-form-urlencoded",maxConnections:3,customHeaders:{},endpointStore:{},paramsStore:{},mandatedParams:{},allowXRequestedWithAndCacheControl:!0,successfulResponseCodes:{DELETE:[200,202,204],PATCH:[200,201,202,203,204],POST:[200,201,202,203,204],PUT:[200,201,202,203,204],GET:[200]},cors:{expected:!1,sendCredentials:!1},log:function(e,t){},onSend:function(e){},onComplete:function(e,t,n){},onProgress:null};if(qq.extend(w,e),_=w.log,qq.indexOf(w.validMethods,w.method)<0)throw new Error("'"+w.method+"' is not a supported method for this type of request!");b="GET"===w.method||"DELETE"===w.method,qq.extend(this,{initTransport:function(e){var t,n,i,o,r,a;return{withPath:function(e){return t=e,this},withParams:function(e){return n=e,this},withQueryParams:function(e){return a=e,this},withHeaders:function(e){return i=e,this},withPayload:function(e){return o=e,this},withCacheBuster:function(){return r=!0,this},send:function(s){return r&&qq.indexOf(["GET","DELETE"],w.method)>=0&&(n.qqtimestamp=(new Date).getTime()),g(e,s,t,n,a,i,o)}}},canceled:function(e){a(e)}})},qq.UploadHandler=function(e){"use strict";var t=e.proxy,n={},i=t.onCancel,o=t.getName;qq.extend(this,{add:function(e,t){n[e]=t,n[e].temp={}},cancel:function(e){var t=this,r=new qq.Promise,a=i(e,o(e),r);a.then(function(){t.isValid(e)&&(n[e].canceled=!0,t.expunge(e)),r.success()})},expunge:function(e){delete n[e]},getThirdPartyFileId:function(e){return n[e].key},isValid:function(e){return void 0!==n[e]},reset:function(){n={}},_getFileState:function(e){return n[e]},_setThirdPartyFileId:function(e,t){n[e].key=t},_wasCanceled:function(e){return!!n[e].canceled}})},qq.UploadHandlerController=function(e,t){"use strict";var n,i,o,r=this,a=!1,s=!1,u={paramsStore:{},maxConnections:3,chunking:{enabled:!1,multiple:{enabled:!1}},log:function(e,t){},onProgress:function(e,t,n,i){},onComplete:function(e,t,n,i){},onCancel:function(e,t){},onUploadPrep:function(e){},onUpload:function(e,t){},onUploadChunk:function(e,t,n){},onUploadChunkSuccess:function(e,t,n,i){},onAutoRetry:function(e,t,n,i){},onResume:function(e,t,n){},onUuidChanged:function(e,t){},getName:function(e){},setSize:function(e,t){},isQueued:function(e){},getIdsInProxyGroup:function(e){},getIdsInBatch:function(e){}},l={done:function(e,t,n,i){var r=o._getChunkData(e,t);o._getFileState(e).attemptingResume=!1,delete o._getFileState(e).temp.chunkProgress[t],o._getFileState(e).loaded+=r.size,u.onUploadChunkSuccess(e,o._getChunkDataForCallback(r),n,i)},finalize:function(e){var t=u.getSize(e),n=u.getName(e);i("All chunks have been uploaded for "+e+" - finalizing...."),o.finalizeChunks(e).then(function(r,a){i("Finalize successful for "+e);var s=p.normalizeResponse(r,!0);u.onProgress(e,n,t,t),o._maybeDeletePersistedChunkData(e),p.cleanup(e,s,a)},function(t,o){var r=p.normalizeResponse(t,!1);i("Problem finalizing chunks for file ID "+e+" - "+r.error,"error"),r.reset&&l.reset(e),u.onAutoRetry(e,n,r,o)||p.cleanup(e,r,o)})},handleFailure:function(e,t,n,r){var a=u.getName(t);i("Chunked upload request failed for "+t+", chunk "+e),o.clearCachedChunk(t,e);var d,f=p.normalizeResponse(n,!1);f.reset?l.reset(t):(d=qq.indexOf(o._getFileState(t).chunking.inProgress,e),d>=0&&(o._getFileState(t).chunking.inProgress.splice(d,1),o._getFileState(t).chunking.remaining.unshift(e))),o._getFileState(t).temp.ignoreFailure||(s&&(o._getFileState(t).temp.ignoreFailure=!0,i(qq.format("Going to attempt to abort these chunks: {}. These are currently in-progress: {}.",JSON.stringify(Object.keys(o._getXhrs(t))),JSON.stringify(o._getFileState(t).chunking.inProgress))),qq.each(o._getXhrs(t),function(e,n){i(qq.format("Attempting to abort file {}.{}. XHR readyState {}. ",t,e,n.readyState)),n.abort(),n._cancelled=!0}),o.moveInProgressToRemaining(t),c.free(t,!0)),u.onAutoRetry(t,a,f,r)||p.cleanup(t,f,r))},hasMoreParts:function(e){return!!o._getFileState(e).chunking.remaining.length},nextPart:function(e){var t=o._getFileState(e).chunking.remaining.shift();return t>=o._getTotalChunks(e)&&(t=null),t},reset:function(e){i("Server or callback has ordered chunking effort to be restarted on next attempt for item ID "+e,"error"),o._maybeDeletePersistedChunkData(e),o.reevaluateChunking(e),o._getFileState(e).loaded=0},sendNext:function(e){var t=u.getSize(e),n=u.getName(e),r=l.nextPart(e),a=o._getChunkData(e,r),d=o._getFileState(e).attemptingResume,f=o._getFileState(e).chunking.inProgress||[];null==o._getFileState(e).loaded&&(o._getFileState(e).loaded=0),d&&u.onResume(e,n,a)===!1&&(l.reset(e),r=l.nextPart(e),a=o._getChunkData(e,r),d=!1),null==r&&0===f.length?l.finalize(e):(i(qq.format("Sending chunked upload request for item {}.{}, bytes {}-{} of {}.",e,r,a.start+1,a.end,t)),u.onUploadChunk(e,n,o._getChunkDataForCallback(a)),f.push(r),o._getFileState(e).chunking.inProgress=f,s&&c.open(e,r),s&&c.available()&&o._getFileState(e).chunking.remaining.length&&l.sendNext(e),0===a.blob.size?(i(qq.format("Chunk {} for file {} will not be uploaded, zero sized chunk.",r,e),"error"),l.handleFailure(r,e,"File is no longer available",null)):o.uploadChunk(e,r,d).then(function(t,n){i("Chunked upload request succeeded for "+e+", chunk "+r),o.clearCachedChunk(e,r);var a=o._getFileState(e).chunking.inProgress||[],s=p.normalizeResponse(t,!0),u=qq.indexOf(a,r);i(qq.format("Chunk {} for file {} uploaded successfully.",r,e)),l.done(e,r,s,n),u>=0&&a.splice(u,1),o._maybePersistChunkedState(e),l.hasMoreParts(e)||0!==a.length?l.hasMoreParts(e)?l.sendNext(e):i(qq.format("File ID {} has no more chunks to send and these chunk indexes are still marked as in-progress: {}",e,JSON.stringify(a))):l.finalize(e)},function(t,n){l.handleFailure(r,e,t,n)}).done(function(){o.clearXhr(e,r)}))}},c={_open:[],_openChunks:{},_waiting:[],available:function(){var e=u.maxConnections,t=0,n=0;return qq.each(c._openChunks,function(e,i){t++,n+=i.length}),e-(c._open.length-t+n)},free:function(e,t){var n,r=!t,a=qq.indexOf(c._waiting,e),s=qq.indexOf(c._open,e);delete c._openChunks[e],p.getProxyOrBlob(e)instanceof qq.BlobProxy&&(i("Generated blob upload has ended for "+e+", disposing generated blob."),delete o._getFileState(e).file),a>=0?c._waiting.splice(a,1):r&&s>=0&&(c._open.splice(s,1),n=c._waiting.shift(),n>=0&&(c._open.push(n),p.start(n)))},getWaitingOrConnected:function(){var e=[];return qq.each(c._openChunks,function(t,n){n&&n.length&&e.push(parseInt(t))}),qq.each(c._open,function(t,n){c._openChunks[n]||e.push(parseInt(n))}),e=e.concat(c._waiting)},isUsingConnection:function(e){return qq.indexOf(c._open,e)>=0},open:function(e,t){return null==t&&c._waiting.push(e),!!c.available()&&(null==t?(c._waiting.pop(),c._open.push(e)):!function(){var n=c._openChunks[e]||[];n.push(t),c._openChunks[e]=n}(),!0)},reset:function(){c._waiting=[],c._open=[]}},d={send:function(e,t){o._getFileState(e).loaded=0,i("Sending simple upload request for "+e),o.uploadFile(e).then(function(n,o){i("Simple upload request succeeded for "+e);var r=p.normalizeResponse(n,!0),a=u.getSize(e);u.onProgress(e,t,a,a),p.maybeNewUuid(e,r),p.cleanup(e,r,o)},function(n,o){i("Simple upload request failed for "+e);var r=p.normalizeResponse(n,!1);u.onAutoRetry(e,t,r,o)||p.cleanup(e,r,o)})}},p={cancel:function(e){i("Cancelling "+e),u.paramsStore.remove(e),c.free(e)},cleanup:function(e,t,n){var i=u.getName(e);u.onComplete(e,i,t,n),o._getFileState(e)&&o._clearXhrs&&o._clearXhrs(e),c.free(e)},getProxyOrBlob:function(e){return o.getProxy&&o.getProxy(e)||o.getFile&&o.getFile(e)},initHandler:function(){var e=t?qq[t]:qq.traditional,n=qq.supportedFeatures.ajaxUploading?"Xhr":"Form";o=new e[n+"UploadHandler"](u,{getDataByUuid:u.getDataByUuid,getName:u.getName,getSize:u.getSize,getUuid:u.getUuid,log:i,onCancel:u.onCancel,onProgress:u.onProgress,onUuidChanged:u.onUuidChanged}),o._removeExpiredChunkingRecords&&o._removeExpiredChunkingRecords()},isDeferredEligibleForUpload:function(e){return u.isQueued(e)},maybeDefer:function(e,t){return t&&!o.getFile(e)&&t instanceof qq.BlobProxy?(u.onUploadPrep(e),i("Attempting to generate a blob on-demand for "+e),t.create().then(function(t){i("Generated an on-demand blob for "+e),o.updateBlob(e,t),u.setSize(e,t.size),o.reevaluateChunking(e),p.maybeSendDeferredFiles(e)},function(t){var o={};t&&(o.error=t),i(qq.format("Failed to generate blob for ID {}. Error message: {}.",e,t),"error"),u.onComplete(e,u.getName(e),qq.extend(o,n),null),p.maybeSendDeferredFiles(e),c.free(e)}),!1):p.maybeSendDeferredFiles(e)},maybeSendDeferredFiles:function(e){var t=u.getIdsInProxyGroup(e),n=!1;return t&&t.length?(i("Maybe ready to upload proxy group file "+e),qq.each(t,function(t,i){if(p.isDeferredEligibleForUpload(i)&&o.getFile(i))n=i===e,p.now(i);else if(p.isDeferredEligibleForUpload(i))return!1})):(n=!0,p.now(e)),n},maybeNewUuid:function(e,t){void 0!==t.newUuid&&u.onUuidChanged(e,t.newUuid)},normalizeResponse:function(e,t){var n=e;return qq.isObject(e)||(n={},qq.isString(e)&&!t&&(n.error=e)),n.success=t,n},now:function(e){var t=u.getName(e);if(!r.isValid(e))throw new qq.Error(e+" is not a valid file ID to upload!");u.onUpload(e,t),a&&o._shouldChunkThisFile(e)?l.sendNext(e):d.send(e,t)},start:function(e){var t=p.getProxyOrBlob(e);return t?p.maybeDefer(e,t):(p.now(e),!0)}};qq.extend(this,{add:function(e,t){o.add.apply(this,arguments)},upload:function(e){return!!c.open(e)&&p.start(e)},retry:function(e){return s&&(o._getFileState(e).temp.ignoreFailure=!1),c.isUsingConnection(e)?p.start(e):r.upload(e)},cancel:function(e){var t=o.cancel(e);qq.isGenericPromise(t)?t.then(function(){p.cancel(e)}):t!==!1&&p.cancel(e)},cancelAll:function(){var e,t=c.getWaitingOrConnected();if(t.length)for(e=t.length-1;e>=0;e--)r.cancel(t[e]);c.reset()},getFile:function(e){return o.getProxy&&o.getProxy(e)?o.getProxy(e).referenceBlob:o.getFile&&o.getFile(e);
-},isProxied:function(e){return!(!o.getProxy||!o.getProxy(e))},getInput:function(e){if(o.getInput)return o.getInput(e)},reset:function(){i("Resetting upload handler"),r.cancelAll(),c.reset(),o.reset()},expunge:function(e){if(r.isValid(e))return o.expunge(e)},isValid:function(e){return o.isValid(e)},getResumableFilesData:function(){return o.getResumableFilesData?o.getResumableFilesData():[]},getThirdPartyFileId:function(e){if(r.isValid(e))return o.getThirdPartyFileId(e)},pause:function(e){return!!(r.isResumable(e)&&o.pause&&r.isValid(e)&&o.pause(e))&&(c.free(e),o.moveInProgressToRemaining(e),!0)},isResumable:function(e){return!!o.isResumable&&o.isResumable(e)}}),qq.extend(u,e),i=u.log,a=u.chunking.enabled&&qq.supportedFeatures.chunking,s=a&&u.chunking.concurrent.enabled,n=function(){var e={};return e[u.preventRetryParam]=!0,e}(),p.initHandler()},qq.WindowReceiveMessage=function(e){"use strict";var t={log:function(e,t){}},n={};qq.extend(t,e),qq.extend(this,{receiveMessage:function(e,t){var i=function(e){t(e.data)};window.postMessage?n[e]=qq(window).attach("message",i):log("iframe message passing not supported in this browser!","error")},stopReceivingMessages:function(e){if(window.postMessage){var t=n[e];t&&t()}}})},qq.FormUploadHandler=function(e){"use strict";function t(e){delete c[e],p&&(clearTimeout(d[e]),delete d[e],m.stopReceivingMessages(e));var t=document.getElementById(a._getIframeName(e));t&&(t.setAttribute("src","javascript:false;"),qq(t).remove())}function n(e){return e.split("_")[0]}function i(e){var t=qq.toElement("");return t.setAttribute("id",e),t.style.display="none",document.body.appendChild(t),t}function o(e,t){var i=e.id,o=n(i),r=q(o);l[r]=t,c[o]=qq(e).attach("load",function(){a.getInput(o)&&(h("Received iframe load event for CORS upload request (iframe name "+i+")"),d[i]=setTimeout(function(){var e="No valid message received from loaded iframe for iframe name "+i;h(e,"error"),t({error:e})},1e3))}),m.receiveMessage(i,function(e){h("Received the following window message: '"+e+"'");var t,o=(n(i),a._parseJsonResponse(e)),r=o.uuid;r&&l[r]?(h("Handling response for iframe name "+i),clearTimeout(d[i]),delete d[i],a._detachLoadEvent(i),t=l[r],delete l[r],m.stopReceivingMessages(i),t(o)):r||h("'"+e+"' does not contain a UUID - ignoring.")})}var r=e.options,a=this,s=e.proxy,u=qq.getUniqueId(),l={},c={},d={},p=r.isCors,f=r.inputName,q=s.getUuid,h=s.log,m=new qq.WindowReceiveMessage({log:h});qq.extend(this,new qq.UploadHandler(e)),qq.override(this,function(e){return{add:function(t,n){e.add(t,{input:n}),n.setAttribute("name",f),n.parentNode&&qq(n).remove()},expunge:function(n){t(n),e.expunge(n)},isValid:function(t){return e.isValid(t)&&void 0!==a._getFileState(t).input}}}),qq.extend(this,{getInput:function(e){return a._getFileState(e).input},_attachLoadEvent:function(e,t){var n;p?o(e,t):c[e.id]=qq(e).attach("load",function(){if(h("Received response for "+e.id),e.parentNode){try{if(e.contentDocument&&e.contentDocument.body&&"false"==e.contentDocument.body.innerHTML)return}catch(e){h("Error when attempting to access iframe during handling of upload response ("+e.message+")","error"),n={success:!1}}t(n)}})},_createIframe:function(e){var t=a._getIframeName(e);return i(t)},_detachLoadEvent:function(e){void 0!==c[e]&&(c[e](),delete c[e])},_getIframeName:function(e){return e+"_"+u},_initFormForUpload:function(e){var t=e.method,n=e.endpoint,i=e.params,o=e.paramsInBody,r=e.targetName,a=qq.toElement(""),s=n;return o?qq.obj2Inputs(i,a):s=qq.obj2url(i,n),a.setAttribute("action",s),a.setAttribute("target",r),a.style.display="none",document.body.appendChild(a),a},_parseJsonResponse:function(e){var t={};try{t=qq.parseJson(e)}catch(e){h("Error when attempting to parse iframe upload response ("+e.message+")","error")}return t}})},qq.XhrUploadHandler=function(e){"use strict";function t(e){qq.each(n._getXhrs(e),function(t,i){var o=n._getAjaxRequester(e,t);i.onreadystatechange=null,i.upload.onprogress=null,i.abort(),o&&o.canceled&&o.canceled(e)})}var n=this,i=e.options.namespace,o=e.proxy,r=e.options.chunking,a=e.options.resume,s=r&&e.options.chunking.enabled&&qq.supportedFeatures.chunking,u=a&&e.options.resume.enabled&&s&&qq.supportedFeatures.resume,l=o.getName,c=o.getSize,d=o.getUuid,p=o.getEndpoint,f=o.getDataByUuid,q=o.onUuidChanged,h=o.onProgress,m=o.log;qq.extend(this,new qq.UploadHandler(e)),qq.override(this,function(e){return{add:function(t,i){if(qq.isFile(i)||qq.isBlob(i))e.add(t,{file:i});else{if(!(i instanceof qq.BlobProxy))throw new Error("Passed obj is not a File, Blob, or proxy");e.add(t,{proxy:i})}n._initTempState(t),u&&n._maybePrepareForResume(t)},expunge:function(i){t(i),n._maybeDeletePersistedChunkData(i),n._clearXhrs(i),e.expunge(i)}}}),qq.extend(this,{clearCachedChunk:function(e,t){delete n._getFileState(e).temp.cachedChunks[t]},clearXhr:function(e,t){var i=n._getFileState(e).temp;i.xhrs&&delete i.xhrs[t],i.ajaxRequesters&&delete i.ajaxRequesters[t]},finalizeChunks:function(e,t){var i=n._getTotalChunks(e)-1,o=n._getXhr(e,i);return t?(new qq.Promise).success(t(o),o):(new qq.Promise).success({},o)},getFile:function(e){return n.isValid(e)&&n._getFileState(e).file},getProxy:function(e){return n.isValid(e)&&n._getFileState(e).proxy},getResumableFilesData:function(){var e=[];return n._iterateResumeRecords(function(t,i){n.moveInProgressToRemaining(null,i.chunking.inProgress,i.chunking.remaining);var o={name:i.name,remaining:i.chunking.remaining,size:i.size,uuid:i.uuid};i.key&&(o.key=i.key),e.push(o)}),e},isResumable:function(e){return!!r&&n.isValid(e)&&!n._getFileState(e).notResumable},moveInProgressToRemaining:function(e,t,i){var o=t||n._getFileState(e).chunking.inProgress,r=i||n._getFileState(e).chunking.remaining;o&&(m(qq.format("Moving these chunks from in-progress {}, to remaining.",JSON.stringify(o))),o.reverse(),qq.each(o,function(e,t){r.unshift(t)}),o.length=0)},pause:function(e){if(n.isValid(e))return m(qq.format("Aborting XHR upload for {} '{}' due to pause instruction.",e,l(e))),n._getFileState(e).paused=!0,t(e),!0},reevaluateChunking:function(e){if(r&&n.isValid(e)){var t,i,o=n._getFileState(e);if(delete o.chunking,o.chunking={},t=n._getTotalChunks(e),t>1||r.mandatory){for(o.chunking.enabled=!0,o.chunking.parts=t,o.chunking.remaining=[],i=0;i=o?o:s+i,l=n._getTotalChunks(e),d=this._getFileState(e).temp.cachedChunks,p=d[t]||qq.sliceBlob(a,s,u);return d[t]=p,{part:t,start:s,end:u,count:l,blob:p,size:u-s}},_getChunkDataForCallback:function(e){return{partIndex:e.part,startByte:e.start+1,endByte:e.end,totalParts:e.count}},_getLocalStorageId:function(e){var t="5.0",n=l(e),o=c(e),a=r.partSize,s=p(e);return qq.format("qq{}resume{}-{}-{}-{}-{}",i,t,n,o,a,s)},_getMimeType:function(e){return n.getFile(e).type},_getPersistableData:function(e){return n._getFileState(e).chunking},_getTotalChunks:function(e){if(r){var t=c(e),n=r.partSize;return Math.ceil(t/n)}},_getXhr:function(e,t){var i=null==t?-1:t;return n._getFileState(e).temp.xhrs[i]},_getXhrs:function(e){return n._getFileState(e).temp.xhrs},_iterateResumeRecords:function(e){u&&qq.each(localStorage,function(t,n){if(0===t.indexOf(qq.format("qq{}resume",i))){var o=JSON.parse(n);e(t,o)}})},_initTempState:function(e){n._getFileState(e).temp={ajaxRequesters:{},chunkProgress:{},xhrs:{},cachedChunks:{}}},_markNotResumable:function(e){n._getFileState(e).notResumable=!0},_maybeDeletePersistedChunkData:function(e){var t;return!!(u&&n.isResumable(e)&&(t=n._getLocalStorageId(e),t&&localStorage.getItem(t)))&&(localStorage.removeItem(t),!0)},_maybePrepareForResume:function(e){var t,i,o=n._getFileState(e);u&&void 0===o.key&&(t=n._getLocalStorageId(e),i=localStorage.getItem(t),i&&(i=JSON.parse(i),f(i.uuid)?n._markNotResumable(e):(m(qq.format("Identified file with ID {} and name of {} as resumable.",e,l(e))),q(e,i.uuid),o.key=i.key,o.chunking=i.chunking,o.loaded=i.loaded,o.attemptingResume=!0,n.moveInProgressToRemaining(e))))},_maybePersistChunkedState:function(e){var t,i,o=n._getFileState(e);if(u&&n.isResumable(e)){t=n._getLocalStorageId(e),i={name:l(e),size:c(e),uuid:d(e),key:o.key,chunking:o.chunking,loaded:o.loaded,lastUpdated:Date.now()};try{localStorage.setItem(t,JSON.stringify(i))}catch(t){m(qq.format("Unable to save resume data for '{}' due to error: '{}'.",e,t.toString()),"warn")}}},_registerProgressHandler:function(e,t,i){var o=n._getXhr(e,t),r=l(e),a={simple:function(t,n){var i=c(e);t===n?h(e,r,i,i):h(e,r,t>=i?i-1:t,i)},chunked:function(o,a){var s=n._getFileState(e).temp.chunkProgress,u=n._getFileState(e).loaded,l=o,d=a,p=c(e),f=l-(d-i),q=u;s[t]=f,qq.each(s,function(e,t){q+=t}),h(e,r,q,p)}};o.upload.onprogress=function(e){if(e.lengthComputable){var t=null==i?"simple":"chunked";a[t](e.loaded,e.total)}}},_registerXhr:function(e,t,i,o){var r=null==t?-1:t,a=n._getFileState(e).temp;return a.xhrs=a.xhrs||{},a.ajaxRequesters=a.ajaxRequesters||{},a.xhrs[r]=i,o&&(a.ajaxRequesters[r]=o),i},_removeExpiredChunkingRecords:function(){var e=a.recordsExpireIn;n._iterateResumeRecords(function(t,n){var i=new Date(n.lastUpdated);i.setDate(i.getDate()+e),i.getTime()<=Date.now()&&(m("Removing expired resume record with key "+t),localStorage.removeItem(t))})},_shouldChunkThisFile:function(e){var t=n._getFileState(e);return t.chunking||n.reevaluateChunking(e),t.chunking.enabled}})},qq.DeleteFileAjaxRequester=function(e){"use strict";function t(){return"POST"===i.method.toUpperCase()?{_method:"DELETE"}:{}}var n,i={method:"DELETE",uuidParamName:"qquuid",endpointStore:{},maxConnections:3,customHeaders:function(e){return{}},paramsStore:{},cors:{expected:!1,sendCredentials:!1},log:function(e,t){},onDelete:function(e){},onDeleteComplete:function(e,t,n){}};qq.extend(i,e),n=qq.extend(this,new qq.AjaxRequester({acceptHeader:"application/json",validMethods:["POST","DELETE"],method:i.method,endpointStore:i.endpointStore,paramsStore:i.paramsStore,mandatedParams:t(),maxConnections:i.maxConnections,customHeaders:function(e){return i.customHeaders.get(e)},log:i.log,onSend:i.onDelete,onComplete:i.onDeleteComplete,cors:i.cors})),qq.extend(this,{sendDelete:function(e,t,o){var r=o||{};i.log("Submitting delete file request for "+e),"DELETE"===i.method?n.initTransport(e).withPath(t).withParams(r).send():(r[i.uuidParamName]=t,n.initTransport(e).withParams(r).send())}})},function(){function e(e){var t,n=e.naturalWidth,i=e.naturalHeight,o=document.createElement("canvas");return n*i>1048576&&(o.width=o.height=1,t=o.getContext("2d"),t.drawImage(e,-n+1,0),0===t.getImageData(0,0,1,1).data[3])}function t(e,t,n){var i,o,r,a,s=document.createElement("canvas"),u=0,l=n,c=n;for(s.width=1,s.height=n,i=s.getContext("2d"),i.drawImage(e,0,0),o=i.getImageData(0,0,1,n).data;c>u;)r=o[4*(c-1)+3],0===r?l=c:u=c,c=l+u>>1;return a=c/n,0===a?1:a}function n(e,t,n,i){var r=document.createElement("canvas"),a=n.mime||"image/jpeg",s=new qq.Promise;return o(e,t,r,n,i).then(function(){s.success(r.toDataURL(a,n.quality||.8))}),s}function i(e){var t=5241e3;if(!qq.ios())throw new qq.Error("Downsampled dimensions can only be reliably calculated for iOS!");if(e.origHeight*e.origWidth>t)return{newHeight:Math.round(Math.sqrt(t*(e.origHeight/e.origWidth))),newWidth:Math.round(Math.sqrt(t*(e.origWidth/e.origHeight)))}}function o(n,o,s,u,l){var c,d=n.naturalWidth,p=n.naturalHeight,f=u.width,q=u.height,h=s.getContext("2d"),m=new qq.Promise;return h.save(),u.resize?r({blob:o,canvas:s,image:n,imageHeight:p,imageWidth:d,orientation:u.orientation,resize:u.resize,targetHeight:q,targetWidth:f}):(qq.supportedFeatures.unlimitedScaledImageSize||(c=i({origWidth:f,origHeight:q}),c&&(qq.log(qq.format("Had to reduce dimensions due to device limitations from {}w / {}h to {}w / {}h",f,q,c.newWidth,c.newHeight),"warn"),f=c.newWidth,q=c.newHeight)),a(s,f,q,u.orientation),qq.ios()?!function(){e(n)&&(d/=2,p/=2);var i,o,r,a=1024,s=document.createElement("canvas"),u=l?t(n,d,p):1,c=Math.ceil(a*f/d),m=Math.ceil(a*q/p/u),g=0,_=0;for(s.width=s.height=a,i=s.getContext("2d");gc&&(u=c,l=s*u/a<<0),d&&l>d&&(l=d,u=a*l/s<<0),i={width:u,height:l},qq.each(t,function(e,t){i[e]=t}),"img"===f?!function(){var t=e.src;n(r.srcImage,r.blob,i,p).then(function(n){e.src=n,t===e.src&&e.onload()})}():"canvas"===f&&o(this.srcImage,this.blob,e,i,p),void("function"==typeof this.onrender&&this.onrender(e)))},qq.MegaPixImage=s}(),qq.ImageGenerator=function(e){"use strict";function t(e){return"img"===e.tagName.toLowerCase()}function n(e){return"canvas"===e.tagName.toLowerCase()}function i(){return void 0!==(new Image).crossOrigin}function o(){var e=document.createElement("canvas");return e.getContext&&e.getContext("2d")}function r(e){var t=e.split("/"),n=t[t.length-1].split("?")[0],i=qq.getExtension(n);switch(i=i&&i.toLowerCase()){case"jpeg":case"jpg":return"image/jpeg";case"png":return"image/png";case"bmp":return"image/bmp";case"gif":return"image/gif";case"tiff":case"tif":return"image/tiff"}}function a(e){var t,n,i,o=document.createElement("a");return o.href=e,t=o.protocol,i=o.port,n=o.hostname,t.toLowerCase()!==window.location.protocol.toLowerCase()||(n.toLowerCase()!==window.location.hostname.toLowerCase()||i!==window.location.port&&!qq.ie())}function s(t,n){t.onload=function(){t.onload=null,t.onerror=null,n.success(t)},t.onerror=function(){t.onload=null,t.onerror=null,e("Problem drawing thumbnail!","error"),n.failure(t,"Problem drawing thumbnail!")}}function u(e,t){e.qqImageRendered=function(){t.success(e)}}function l(i,o){var r=t(i)||n(i);return t(i)?s(i,o):n(i)?u(i,o):(o.failure(i),e(qq.format("Element container of type {} is not supported!",i.tagName),"error")),r}function c(t,n,i){var o=new qq.Promise,r=new qq.Identify(t,e),a=i.maxSize,s=null==i.orient||i.orient,u=function(){n.onerror=null,n.onload=null,e("Could not render preview, file may be too large!","error"),o.failure(n,"Browser cannot render image!")};return r.isPreviewable().then(function(r){var c={parse:function(){return(new qq.Promise).success()}},d=s?new qq.Exif(t,e):c,p=new qq.MegaPixImage(t,u);l(n,o)&&d.parse().then(function(e){var t=e&&e.Orientation;p.render(n,{maxWidth:a,maxHeight:a,orientation:t,mime:r,resize:i.customResizeFunction})},function(t){e(qq.format("EXIF data could not be parsed ({}). Assuming orientation = 1.",t)),p.render(n,{maxWidth:a,maxHeight:a,mime:r,resize:i.customResizeFunction})})},function(){e("Not previewable"),o.failure(n,"Not previewable")}),o}function d(e,t,n,i,o){var s=new Image,u=new qq.Promise;l(s,u),a(e)&&(s.crossOrigin="anonymous"),s.src=e,u.then(function(){l(t,n);var a=new qq.MegaPixImage(s);a.render(t,{maxWidth:i,maxHeight:i,mime:r(e),resize:o})},n.failure)}function p(e,t,n,i){l(t,n),qq(t).css({maxWidth:i+"px",maxHeight:i+"px"}),t.src=e}function f(e,r,s){var u=new qq.Promise,c=s.scale,f=c?s.maxSize:null;return c&&t(r)?o()?a(e)&&!i()?p(e,r,u,f):d(e,r,u,f):p(e,r,u,f):n(r)?d(e,r,u,f):l(r,u)&&(r.src=e),u}qq.extend(this,{generate:function(t,n,i){return qq.isString(t)?(e("Attempting to update thumbnail based on server response."),f(t,n,i||{})):(e("Attempting to draw client-side image preview."),c(t,n,i||{}))}}),this._testing={},this._testing.isImg=t,this._testing.isCanvas=n,this._testing.isCrossOrigin=a,this._testing.determineMimeOfFileName=r},qq.Exif=function(e,t){"use strict";function n(e){for(var t=0,n=0;e.length>0;)t+=parseInt(e.substring(0,2),16)*Math.pow(2,n),e=e.substring(2,e.length),n+=8;return t}function i(t,n){var o=t,r=n;return void 0===o&&(o=2,r=new qq.Promise),qq.readBlobToHex(e,o,4).then(function(e){var t,n=/^ffe([0-9])/.exec(e);n?"1"!==n[1]?(t=parseInt(e.slice(4,8),16),i(o+t+2,r)):r.success(o):r.failure("No EXIF header to be found!")}),r}function o(){var t=new qq.Promise;return qq.readBlobToHex(e,0,6).then(function(e){0!==e.indexOf("ffd8")?t.failure("Not a valid JPEG!"):i().then(function(e){t.success(e)},function(e){t.failure(e)})}),t}function r(t){var n=new qq.Promise;return qq.readBlobToHex(e,t+10,2).then(function(e){n.success("4949"===e)}),n}function a(t,i){var o=new qq.Promise;return qq.readBlobToHex(e,t+18,2).then(function(e){return i?o.success(n(e)):void o.success(parseInt(e,16))}),o}function s(t,n){var i=t+20,o=12*n;return qq.readBlobToHex(e,i,o)}function u(e){for(var t=[],n=0;n+24<=e.length;)t.push(e.slice(n,n+24)),n+=24;return t}function l(e,t){var i=16,o=qq.extend([],c),r={};return qq.each(t,function(t,a){var s,u,l,c=a.slice(0,4),p=e?n(c):parseInt(c,16),f=o.indexOf(p);if(f>=0&&(u=d[p].name,l=d[p].bytes,s=a.slice(i,i+2*l),r[u]=e?n(s):parseInt(s,16),o.splice(f,1)),0===o.length)return!1}),r}var c=[274],d={274:{name:"Orientation",bytes:2}};qq.extend(this,{parse:function(){var n=new qq.Promise,i=function(e){t(qq.format("EXIF header parse failed: '{}' ",e)),n.failure(e)};return o().then(function(o){t(qq.format("Moving forward with EXIF header parsing for '{}'",void 0===e.name?"blob":e.name)),r(o).then(function(e){t(qq.format("EXIF Byte order is {} endian",e?"little":"big")),a(o,e).then(function(r){t(qq.format("Found {} APP1 directory entries",r)),s(o,r).then(function(i){var o=u(i),r=l(e,o);t("Successfully parsed some EXIF tags"),n.success(r)},i)},i)},i)},i),n}}),this._testing={},this._testing.parseLittleEndian=n},qq.Identify=function(e,t){"use strict";function n(e,t){var n=!1,i=[].concat(e);return qq.each(i,function(e,i){if(0===t.indexOf(i))return n=!0,!1}),n}qq.extend(this,{isPreviewable:function(){var i=this,o=new qq.Promise,r=!1,a=void 0===e.name?"blob":e.name;return t(qq.format("Attempting to determine if {} can be rendered in this browser",a)),t("First pass: check type attribute of blob object."),this.isPreviewableSync()?(t("Second pass: check for magic bytes in file header."),qq.readBlobToHex(e,0,4).then(function(e){qq.each(i.PREVIEWABLE_MIME_TYPES,function(t,i){if(n(i,e))return("image/tiff"!==t||qq.supportedFeatures.tiffPreviews)&&(r=!0,o.success(t)),!1}),t(qq.format("'{}' is {} able to be rendered in this browser",a,r?"":"NOT")),r||o.failure()},function(){t("Error reading file w/ name '"+a+"'. Not able to be rendered in this browser."),o.failure()})):o.failure(),o},isPreviewableSync:function(){var n=e.type,i=qq.indexOf(Object.keys(this.PREVIEWABLE_MIME_TYPES),n)>=0,o=!1,r=void 0===e.name?"blob":e.name;return i&&(o="image/tiff"!==n||qq.supportedFeatures.tiffPreviews),!o&&t(r+" is not previewable in this browser per the blob's type attr"),o}})},qq.Identify.prototype.PREVIEWABLE_MIME_TYPES={"image/jpeg":"ffd8ff","image/gif":"474946","image/png":"89504e","image/bmp":"424d","image/tiff":["49492a00","4d4d002a"]},qq.ImageValidation=function(e,t){"use strict";function n(e){var t=!1;return qq.each(e,function(e,n){if(n>0)return t=!0,!1}),t}function i(){var n=new qq.Promise;return new qq.Identify(e,t).isPreviewable().then(function(){var i=new Image,o=window.URL&&window.URL.createObjectURL?window.URL:window.webkitURL&&window.webkitURL.createObjectURL?window.webkitURL:null;o?(i.onerror=function(){t("Cannot determine dimensions for image. May be too large.","error"),n.failure()},i.onload=function(){n.success({width:this.width,height:this.height})},i.src=o.createObjectURL(e)):(t("No createObjectURL function available to generate image URL!","error"),n.failure())},n.failure),n}function o(e,t){var n;return qq.each(e,function(e,i){if(i>0){var o=/(max|min)(Width|Height)/.exec(e),r=o[2].charAt(0).toLowerCase()+o[2].slice(1),a=t[r];switch(o[1]){case"min":if(ai)return n=e,!1}}}),n}this.validate=function(e){var r=new qq.Promise;return t("Attempting to validate image."),n(e)?i().then(function(t){var n=o(e,t);n?r.failure(n):r.success()},r.success):r.success(),r}},qq.Session=function(e){"use strict";function t(e){return!!qq.isArray(e)||void i.log("Session response is not an array.","error")}function n(e,n,o,r){var a=!1;n=n&&t(e),n&&qq.each(e,function(e,t){if(null==t.uuid)a=!0,i.log(qq.format("Session response item {} did not include a valid UUID - ignoring.",e),"error");else if(null==t.name)a=!0,i.log(qq.format("Session response item {} did not include a valid name - ignoring.",e),"error");else try{return i.addFileRecord(t),!0}catch(e){a=!0,i.log(e.message,"error")}return!1}),r[n&&!a?"success":"failure"](e,o)}var i={endpoint:null,params:{},customHeaders:{},cors:{},addFileRecord:function(e){},log:function(e,t){}};qq.extend(i,e,!0),this.refresh=function(){var e=new qq.Promise,t=function(t,i,o){n(t,i,o,e)},o=qq.extend({},i),r=new qq.SessionAjaxRequester(qq.extend(o,{onComplete:t}));return r.queryServer(),e}},qq.SessionAjaxRequester=function(e){"use strict";function t(e,t,n){var o=null;if(null!=t.responseText)try{o=qq.parseJson(t.responseText)}catch(e){i.log("Problem parsing session response: "+e.message,"error"),n=!0}i.onComplete(o,!n,t)}var n,i={endpoint:null,customHeaders:{},params:{},cors:{expected:!1,sendCredentials:!1},onComplete:function(e,t,n){},log:function(e,t){}};qq.extend(i,e),n=qq.extend(this,new qq.AjaxRequester({acceptHeader:"application/json",validMethods:["GET"],method:"GET",endpointStore:{get:function(){return i.endpoint}},customHeaders:i.customHeaders,log:i.log,onComplete:t,cors:i.cors})),qq.extend(this,{queryServer:function(){var e=qq.extend({},i.params);i.log("Session query request."),n.initTransport("sessionRefresh").withParams(e).withCacheBuster().send()}})},qq.Scaler=function(e,t){"use strict";var n=e.customResizer,i=e.sendOriginal,o=e.orient,r=e.defaultType,a=e.defaultQuality/100,s=e.failureText,u=e.includeExif,l=this._getSortedSizes(e.sizes);qq.extend(this,{enabled:qq.supportedFeatures.scaling&&l.length>0,getFileRecords:function(e,c,d){var p=this,f=[],q=d.blob?d.blob:d,h=new qq.Identify(q,t);return h.isPreviewableSync()?(qq.each(l,function(e,i){var l=p._determineOutputType({defaultType:r,requestedType:i.type,refType:q.type});f.push({uuid:qq.getUniqueId(),name:p._getName(c,{name:i.name,type:l,refType:q.type}),blob:new qq.BlobProxy(q,qq.bind(p._generateScaledImage,p,{customResizeFunction:n,maxSize:i.maxSize,orient:o,type:l,quality:a,failedText:s,includeExif:u,log:t}))})}),f.push({uuid:e,name:c,size:q.size,blob:i?q:null})):f.push({uuid:e,name:c,size:q.size,blob:q}),f},handleNewFile:function(e,t,n,i,o,r,a,s){var u=this,l=(e.qqButtonId||e.blob&&e.blob.qqButtonId,[]),c=null,d=s.addFileToHandler,p=s.uploadData,f=s.paramsStore,q=qq.getUniqueId();qq.each(u.getFileRecords(n,t,e),function(e,t){var n,i=t.size;t.blob instanceof qq.BlobProxy&&(i=-1),n=p.addFile({uuid:t.uuid,name:t.name,size:i,batchId:r,proxyGroupId:q}),t.blob instanceof qq.BlobProxy?l.push(n):c=n,t.blob?(d(n,t.blob),o.push({id:n,file:t.blob})):p.setStatus(n,qq.status.REJECTED)}),null!==c&&(qq.each(l,function(e,t){var n={qqparentuuid:p.retrieve({id:c}).uuid,qqparentsize:p.retrieve({id:c}).size};n[a]=p.retrieve({id:t}).uuid,p.setParentId(t,c),f.addReadOnly(t,n)}),l.length&&!function(){var e={};e[a]=p.retrieve({id:c}).uuid,f.addReadOnly(c,e)}())}})},qq.extend(qq.Scaler.prototype,{scaleImage:function(e,t,n){"use strict";if(!qq.supportedFeatures.scaling)throw new qq.Error("Scaling is not supported in this browser!");var i=new qq.Promise,o=n.log,r=n.getFile(e),a=n.uploadData.retrieve({id:e}),s=a&&a.name,u=a&&a.uuid,l={customResizer:t.customResizer,sendOriginal:!1,orient:t.orient,defaultType:t.type||null,defaultQuality:t.quality,failedToScaleText:"Unable to scale",sizes:[{name:"",maxSize:t.maxSize}]},c=new qq.Scaler(l,o);return qq.Scaler&&qq.supportedFeatures.imagePreviews&&r?qq.bind(function(){var t=c.getFileRecords(u,s,r)[0];t&&t.blob instanceof qq.BlobProxy?t.blob.create().then(i.success,i.failure):(o(e+" is not a scalable image!","error"),i.failure())},this)():(i.failure(),o("Could not generate requested scaled image for "+e+". Scaling is either not possible in this browser, or the file could not be located.","error")),i},_determineOutputType:function(e){"use strict";var t=e.requestedType,n=e.defaultType,i=e.refType;return n||t?t&&qq.indexOf(Object.keys(qq.Identify.prototype.PREVIEWABLE_MIME_TYPES),t)>=0?"image/tiff"===t?qq.supportedFeatures.tiffPreviews?t:n:t:n:"image/jpeg"!==i?"image/png":i},_getName:function(e,t){"use strict";var n=e.lastIndexOf("."),i=t.type||"image/png",o=t.refType,r="",a=qq.getExtension(e),s="";return t.name&&t.name.trim().length&&(s=" ("+t.name+")"),n>=0?(r=e.substr(0,n),o!==i&&(a=i.split("/")[1]),r+=s+"."+a):r=e+s,r},_getSortedSizes:function(e){"use strict";return e=qq.extend([],e),e.sort(function(e,t){return e.maxSize>t.maxSize?1:e.maxSize=0?atob(e.split(",")[1]):decodeURI(e.split(",")[1]),n=e.split(",")[0].split(":")[1].split(";")[0],i=new ArrayBuffer(t.length),o=new Uint8Array(i),qq.each(t,function(e,t){o[e]=t.charCodeAt(0)}),this._createBlob(i,n)},_createBlob:function(e,t){"use strict";var n=window.BlobBuilder||window.WebKitBlobBuilder||window.MozBlobBuilder||window.MSBlobBuilder,i=n&&new n;return i?(i.append(e),i.getBlob(t)):new Blob([e],{type:t})}}),qq.ExifRestorer=function(){var e={};return e.KEY_STR="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",e.encode64=function(e){var t,n,i,o,r,a="",s="",u="",l=0;do t=e[l++],n=e[l++],s=e[l++],i=t>>2,o=(3&t)<<4|n>>4,r=(15&n)<<2|s>>6,u=63&s,isNaN(n)?r=u=64:isNaN(s)&&(u=64),a=a+this.KEY_STR.charAt(i)+this.KEY_STR.charAt(o)+this.KEY_STR.charAt(r)+this.KEY_STR.charAt(u),t=n=s="",i=o=r=u="";while(le.length)break}return n},e.decode64=function(e){var t,n,i,o,r,a="",s="",u=0,l=[],c=/[^A-Za-z0-9\+\/\=]/g;if(c.exec(e))throw new Error("There were invalid base64 characters in the input text. Valid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='");e=e.replace(/[^A-Za-z0-9\+\/\=]/g,"");do i=this.KEY_STR.indexOf(e.charAt(u++)),o=this.KEY_STR.indexOf(e.charAt(u++)),r=this.KEY_STR.indexOf(e.charAt(u++)),s=this.KEY_STR.indexOf(e.charAt(u++)),t=i<<2|o>>4,n=(15&o)<<4|r>>2,a=(3&r)<<6|s,l.push(t),64!=r&&l.push(n),64!=s&&l.push(a),t=n=a="",i=o=r=s="";while(u=0)return n=!1,!1}),n},l=function(e){p(e,-1,-1),delete n[e]},c=function(e,t,n){(0===t.length||u(t,n))&&(s(o,o),this.reset())},d=function(e){var i=t(e);i>0&&(p(e,0,i),n[e]={loaded:0,total:i})},p=function(e,t,r){var a=n[e]?n[e].loaded:0,u=n[e]?n[e].total:0;t===-1&&r===-1?(i-=a,o-=u):(t&&(i+=t-a),r&&(o+=r-u)),s(i,o)};qq.extend(this,{onAllComplete:c,onStatusChange:function(e,t,n){n===qq.status.CANCELED||n===qq.status.REJECTED?l(e):n===qq.status.SUBMITTING&&d(e)},onIndividualProgress:function(e,t,i){p(e,t,i),n[e]={loaded:t,total:i}},onNewSize:function(e){d(e)},reset:function(){n={},i=0,o=0}})},qq.PasteSupport=function(e){"use strict";function t(e){return e.type&&0===e.type.indexOf("image/")}function n(){r=qq(o.targetElement).attach("paste",function(e){var n=e.clipboardData;n&&qq.each(n.items,function(e,n){if(t(n)){var i=n.getAsFile();o.callbacks.pasteReceived(i)}})})}function i(){r&&r()}var o,r;o={targetElement:null,callbacks:{log:function(e,t){},pasteReceived:function(e){}}},qq.extend(o,e),n(),qq.extend(this,{reset:function(){i()}})},qq.FormSupport=function(e,t,n){"use strict";function i(e){e.getAttribute("action")&&(s.newEndpoint=e.getAttribute("action"))}function o(e,t){return!(e.checkValidity&&!e.checkValidity())||(n("Form did not pass validation checks - will not upload.","error"),void t())}function r(e){var n=e.submit;
-qq(e).attach("submit",function(i){i=i||window.event,i.preventDefault?i.preventDefault():i.returnValue=!1,o(e,n)&&t()}),e.submit=function(){o(e,n)&&t()}}function a(e){return e&&(qq.isString(e)&&(e=document.getElementById(e)),e&&(n("Attaching to form element."),i(e),u&&r(e))),e}var s=this,u=e.interceptSubmit,l=e.element,c=e.autoUpload;qq.extend(this,{newEndpoint:null,newAutoUpload:c,attachedToForm:!1,getFormInputsAsObject:function(){return null==l?null:s._form2Obj(l)}}),l=a(l),this.attachedToForm=!!l},qq.extend(qq.FormSupport.prototype,{_form2Obj:function(e){"use strict";var t={},n=function(e){var t=["button","image","reset","submit"];return qq.indexOf(t,e.toLowerCase())<0},i=function(e){return qq.indexOf(["checkbox","radio"],e.toLowerCase())>=0},o=function(e){return!(!i(e.type)||e.checked)||e.disabled&&"hidden"!==e.type.toLowerCase()},r=function(e){var t=null;return qq.each(qq(e).children(),function(e,n){if("option"===n.tagName.toLowerCase()&&n.selected)return t=n.value,!1}),t};return qq.each(e.elements,function(e,i){if(!qq.isInput(i,!0)&&"textarea"!==i.tagName.toLowerCase()||!n(i.type)||o(i)){if("select"===i.tagName.toLowerCase()&&!o(i)){var a=r(i);null!==a&&(t[i.name]=a)}}else t[i.name]=i.value}),t}}),qq.traditional=qq.traditional||{},qq.traditional.FormUploadHandler=function(e,t){"use strict";function n(e,t){var n,i,r;try{i=t.contentDocument||t.contentWindow.document,r=i.body.innerHTML,s("converting iframe's innerHTML to JSON"),s("innerHTML = "+r),r&&r.match(/^=0?atob(e.split(",")[1]):decodeURI(e.split(",")[1]),o=e.split(",")[0].split(":")[1].split(";")[0],t=new ArrayBuffer(n.length),i=new Uint8Array(t),qq.each(n,function(e,t){i[e]=t.charCodeAt(0)}),r(t,o)},qq.log=function(e,t){window.console&&(t&&"info"!==t?window.console[t]?window.console[t](e):window.console.log("<"+t+"> "+e):window.console.log(e))},qq.isObject=function(e){return e&&!e.nodeType&&"[object Object]"===Object.prototype.toString.call(e)},qq.isFunction=function(e){return"function"==typeof e},qq.isArray=function(e){return"[object Array]"===Object.prototype.toString.call(e)||e&&window.ArrayBuffer&&e.buffer&&e.buffer.constructor===ArrayBuffer},qq.isItemList=function(e){return"[object DataTransferItemList]"===Object.prototype.toString.call(e)},qq.isNodeList=function(e){return"[object NodeList]"===Object.prototype.toString.call(e)||e.item&&e.namedItem},qq.isString=function(e){return"[object String]"===Object.prototype.toString.call(e)},qq.trimStr=function(e){return String.prototype.trim?e.trim():e.replace(/^\s+|\s+$/g,"")},qq.format=function(e){var t=Array.prototype.slice.call(arguments,1),n=e,i=n.indexOf("{}");return qq.each(t,function(e,t){if(n=n.substring(0,i)+t+n.substring(i+2),i=n.indexOf("{}",i+t.length),i<0)return!1}),n},qq.isFile=function(e){return window.File&&"[object File]"===Object.prototype.toString.call(e)},qq.isFileList=function(e){return window.FileList&&"[object FileList]"===Object.prototype.toString.call(e)},qq.isFileOrInput=function(e){return qq.isFile(e)||qq.isInput(e)},qq.isInput=function(e,t){var n=function(e){var n=e.toLowerCase();return t?"file"!==n:"file"===n};return!!(window.HTMLInputElement&&"[object HTMLInputElement]"===Object.prototype.toString.call(e)&&e.type&&n(e.type))||!!(e.tagName&&"input"===e.tagName.toLowerCase()&&e.type&&n(e.type))},qq.isBlob=function(e){if(window.Blob&&"[object Blob]"===Object.prototype.toString.call(e))return!0},qq.isXhrUploadSupported=function(){var e=document.createElement("input");return e.type="file",void 0!==e.multiple&&"undefined"!=typeof File&&"undefined"!=typeof FormData&&void 0!==qq.createXhrInstance().upload},qq.createXhrInstance=function(){if(window.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(e){return qq.log("Neither XHR or ActiveX are supported!","error"),null}},qq.isFolderDropSupported=function(e){return e.items&&e.items.length>0&&e.items[0].webkitGetAsEntry},qq.isFileChunkingSupported=function(){return!qq.androidStock()&&qq.isXhrUploadSupported()&&(void 0!==File.prototype.slice||void 0!==File.prototype.webkitSlice||void 0!==File.prototype.mozSlice)},qq.sliceBlob=function(e,t,n){return(e.slice||e.mozSlice||e.webkitSlice).call(e,t,n)},qq.arrayBufferToHex=function(e){var t="",n=new Uint8Array(e);return qq.each(n,function(e,n){var i=n.toString(16);i.length<2&&(i="0"+i),t+=i}),t},qq.readBlobToHex=function(e,t,n){var i=qq.sliceBlob(e,t,t+n),o=new FileReader,r=new qq.Promise;return o.onload=function(){r.success(qq.arrayBufferToHex(o.result))},o.onerror=r.failure,o.readAsArrayBuffer(i),r},qq.extend=function(e,t,n){return qq.each(t,function(t,i){n&&qq.isObject(i)?(void 0===e[t]&&(e[t]={}),qq.extend(e[t],i,!0)):e[t]=i}),e},qq.override=function(e,t){var n={},i=t(n);return qq.each(i,function(t,i){void 0!==e[t]&&(n[t]=e[t]),e[t]=i}),e},qq.indexOf=function(e,t,n){if(e.indexOf)return e.indexOf(t,n);n=n||0;var i=e.length;for(n<0&&(n+=i);n=0},qq.safari=function(){return void 0!==navigator.vendor&&navigator.vendor.indexOf("Apple")!==-1},qq.chrome=function(){return void 0!==navigator.vendor&&navigator.vendor.indexOf("Google")!==-1},qq.opera=function(){return void 0!==navigator.vendor&&navigator.vendor.indexOf("Opera")!==-1},qq.firefox=function(){return!qq.edge()&&!qq.ie11()&&navigator.userAgent.indexOf("Mozilla")!==-1&&void 0!==navigator.vendor&&""===navigator.vendor},qq.windows=function(){return"Win32"===navigator.platform},qq.android=function(){return navigator.userAgent.toLowerCase().indexOf("android")!==-1},qq.androidStock=function(){return qq.android()&&navigator.userAgent.toLowerCase().indexOf("chrome")<0},qq.ios6=function(){return qq.ios()&&navigator.userAgent.indexOf(" OS 6_")!==-1},qq.ios7=function(){return qq.ios()&&navigator.userAgent.indexOf(" OS 7_")!==-1},qq.ios8=function(){return qq.ios()&&navigator.userAgent.indexOf(" OS 8_")!==-1},qq.ios800=function(){return qq.ios()&&navigator.userAgent.indexOf(" OS 8_0 ")!==-1},qq.ios=function(){return navigator.userAgent.indexOf("iPad")!==-1||navigator.userAgent.indexOf("iPod")!==-1||navigator.userAgent.indexOf("iPhone")!==-1},qq.iosChrome=function(){return qq.ios()&&navigator.userAgent.indexOf("CriOS")!==-1},qq.iosSafari=function(){return qq.ios()&&!qq.iosChrome()&&navigator.userAgent.indexOf("Safari")!==-1},qq.iosSafariWebView=function(){return qq.ios()&&!qq.iosChrome()&&!qq.iosSafari()},qq.preventDefault=function(e){e.preventDefault?e.preventDefault():e.returnValue=!1},qq.toElement=function(){var e=document.createElement("div");return function(t){e.innerHTML=t;var n=e.firstChild;return e.removeChild(n),n}}(),qq.each=function(e,t){var n,i;if(e)if(window.Storage&&e.constructor===window.Storage)for(n=0;n0)return e.substr(t,e.length-t)},qq.getFilename=function(e){return qq.isInput(e)?e.value.replace(/.*(\/|\\)/,""):qq.isFile(e)&&null!==e.fileName&&void 0!==e.fileName?e.fileName:e.name},qq.DisposeSupport=function(){var e=[];return{dispose:function(){var t;do t=e.shift(),t&&t();while(t)},attach:function(){var e=arguments;this.addDisposer(qq(e[0]).attach.apply(this,Array.prototype.slice.call(arguments,1)))},addDisposer:function(t){e.push(t)}}}}(),function(){"use strict";"function"==typeof define&&define.amd?define(function(){return qq}):"undefined"!=typeof module&&module.exports?module.exports=qq:global.qq=qq}(),function(){"use strict";qq.Error=function(e){this.message="[Fine Uploader "+qq.version+"] "+e},qq.Error.prototype=new Error}(),qq.version="5.16.2",qq.supportedFeatures=function(){"use strict";function e(){var e,t=!0;try{e=document.createElement("input"),e.type="file",qq(e).hide(),e.disabled&&(t=!1)}catch(e){t=!1}return t}function t(){return(qq.chrome()||qq.opera())&&void 0!==navigator.userAgent.match(/Chrome\/[1][4-9]|Chrome\/[2-9][0-9]/)}function n(){if(window.XMLHttpRequest){return void 0!==qq.createXhrInstance().withCredentials}return!1}function i(){return void 0!==window.XDomainRequest}function o(){return!!n()||i()}function r(){return void 0!==document.createElement("input").webkitdirectory}function a(){try{return!!window.localStorage&&qq.isFunction(window.localStorage.setItem)}catch(e){return!1}}function s(){var e=document.createElement("span");return("draggable"in e||"ondragstart"in e&&"ondrop"in e)&&!qq.android()&&!qq.ios()}var u,l,c,d,f,p,h,q,m,g,_,b,v,S,w;return u=e(),d=u&&qq.isXhrUploadSupported(),l=d&&!qq.androidStock(),c=d&&s(),f=c&&function(){var e=document.createElement("input");return e.type="file",!!("webkitdirectory"in(e||document.querySelectorAll("input[type=file]")[0]))}(),p=d&&qq.isFileChunkingSupported(),h=d&&p&&a(),q=d&&t(),m=u&&(void 0!==window.postMessage||d),_=n(),g=i(),b=o(),v=r(),S=d&&void 0!==window.FileReader,w=function(){return!!d&&(!qq.androidStock()&&!qq.iosChrome())}(),{ajaxUploading:d,blobUploading:l,canDetermineSize:d,chunking:p,deleteFileCors:b,deleteFileCorsXdr:g,deleteFileCorsXhr:_,dialogElement:!!window.HTMLDialogElement,fileDrop:c,folderDrop:f,folderSelection:v,imagePreviews:S,imageValidation:S,itemSizeValidation:d,pause:p,progressBar:w,resume:h,scaling:S&&l,tiffPreviews:qq.safari(),unlimitedScaledImageSize:!qq.ios(),uploading:u,uploadCors:m,uploadCustomHeaders:d,uploadNonMultipart:d,uploadViaPaste:q}}(),qq.isGenericPromise=function(e){"use strict";return!!(e&&e.then&&qq.isFunction(e.then))},qq.Promise=function(){"use strict";var e,t,n=[],i=[],o=[],r=0;qq.extend(this,{then:function(o,a){return 0===r?(o&&n.push(o),a&&i.push(a)):r===-1?a&&a.apply(null,t):o&&o.apply(null,e),this},done:function(n){return 0===r?o.push(n):n.apply(null,void 0===t?e:t),this},success:function(){return r=1,e=arguments,n.length&&qq.each(n,function(t,n){n.apply(null,e)}),o.length&&qq.each(o,function(t,n){n.apply(null,e)}),this},failure:function(){return r=-1,t=arguments,i.length&&qq.each(i,function(e,n){n.apply(null,t)}),o.length&&qq.each(o,function(e,n){n.apply(null,t)}),this}})},qq.BlobProxy=function(e,t){"use strict";qq.extend(this,{referenceBlob:e,create:function(){return t(e)}})},qq.UploadButton=function(e){"use strict";function t(){var e=document.createElement("input");return e.setAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME,i),e.setAttribute("title",a.title),o.setMultiple(a.multiple,e),a.folders&&qq.supportedFeatures.folderSelection&&e.setAttribute("webkitdirectory",""),a.acceptFiles&&e.setAttribute("accept",a.acceptFiles),e.setAttribute("type","file"),e.setAttribute("name",a.name),qq(e).css({position:"absolute",right:0,top:0,fontFamily:"Arial",fontSize:qq.ie()&&!qq.ie8()?"3500px":"118px",margin:0,padding:0,cursor:"pointer",opacity:0}),!qq.ie7()&&qq(e).css({height:"100%"}),a.element.appendChild(e),r.attach(e,"change",function(){a.onChange(e)}),r.attach(e,"mouseover",function(){qq(a.element).addClass(a.hoverClass)}),r.attach(e,"mouseout",function(){qq(a.element).removeClass(a.hoverClass)}),r.attach(e,"focus",function(){qq(a.element).addClass(a.focusClass)}),r.attach(e,"blur",function(){qq(a.element).removeClass(a.focusClass)}),e}var n,i,o=this,r=new qq.DisposeSupport,a={acceptFiles:null,element:null,focusClass:"qq-upload-button-focus",folders:!1,hoverClass:"qq-upload-button-hover",ios8BrowserCrashWorkaround:!1,multiple:!1,name:"qqfile",onChange:function(e){},title:null};qq.extend(a,e),i=qq.getUniqueId(),qq(a.element).css({position:"relative",overflow:"hidden",direction:"ltr"}),qq.extend(this,{getInput:function(){return n},getButtonId:function(){return i},setMultiple:function(e,t){var n=t||this.getInput();a.ios8BrowserCrashWorkaround&&qq.ios8()&&(qq.iosChrome()||qq.iosSafariWebView())?n.setAttribute("multiple",""):e?n.setAttribute("multiple",""):n.removeAttribute("multiple")},setAcceptFiles:function(e){e!==a.acceptFiles&&n.setAttribute("accept",e)},reset:function(){n.parentNode&&qq(n).remove(),qq(a.element).removeClass(a.focusClass),n=null,n=t()}}),n=t()},qq.UploadButton.BUTTON_ID_ATTR_NAME="qq-button-id",qq.UploadData=function(e){"use strict";function t(e){if(qq.isArray(e)){var t=[];return qq.each(e,function(e,n){t.push(o[n])}),t}return o[e]}function n(e){if(qq.isArray(e)){var t=[];return qq.each(e,function(e,n){t.push(o[r[n]])}),t}return o[r[e]]}function i(e){var t=[],n=[].concat(e);return qq.each(n,function(e,n){var i=a[n];void 0!==i&&qq.each(i,function(e,n){t.push(o[n])})}),t}var o=[],r={},a={},s={},u={};qq.extend(this,{addFile:function(t){var n=t.status||qq.status.SUBMITTING,i=o.push({name:t.name,originalName:t.name,uuid:t.uuid,size:null==t.size?-1:t.size,status:n,file:t.file})-1;return t.batchId&&(o[i].batchId=t.batchId,void 0===u[t.batchId]&&(u[t.batchId]=[]),u[t.batchId].push(i)),t.proxyGroupId&&(o[i].proxyGroupId=t.proxyGroupId,void 0===s[t.proxyGroupId]&&(s[t.proxyGroupId]=[]),s[t.proxyGroupId].push(i)),o[i].id=i,r[t.uuid]=i,void 0===a[n]&&(a[n]=[]),a[n].push(i),t.onBeforeStatusChange&&t.onBeforeStatusChange(i),e.onStatusChange(i,null,n),i},retrieve:function(e){return qq.isObject(e)&&o.length?void 0!==e.id?t(e.id):void 0!==e.uuid?n(e.uuid):e.status?i(e.status):void 0:qq.extend([],o,!0)},removeFileRef:function(e){var n=t(e);n&&delete n.file},reset:function(){o=[],r={},a={},u={}},setStatus:function(t,n){var i=o[t].status,r=qq.indexOf(a[i],t);a[i].splice(r,1),o[t].status=n,void 0===a[n]&&(a[n]=[]),a[n].push(t),e.onStatusChange(t,i,n)},uuidChanged:function(e,t){var n=o[e].uuid;o[e].uuid=t,r[t]=e,delete r[n]},updateName:function(e,t){o[e].name=t},updateSize:function(e,t){o[e].size=t},setParentId:function(e,t){o[e].parentId=t},getIdsInProxyGroup:function(e){var t=o[e].proxyGroupId;return t?s[t]:[]},getIdsInBatch:function(e){return u[o[e].batchId]}})},qq.status={SUBMITTING:"submitting",SUBMITTED:"submitted",REJECTED:"rejected",QUEUED:"queued",CANCELED:"canceled",PAUSED:"paused",UPLOADING:"uploading",UPLOAD_FINALIZING:"upload finalizing",UPLOAD_RETRYING:"retrying upload",UPLOAD_SUCCESSFUL:"upload successful",UPLOAD_FAILED:"upload failed",DELETE_FAILED:"delete failed",DELETING:"deleting",DELETED:"deleted"},function(){"use strict";qq.basePublicApi={addBlobs:function(e,t,n){this.addFiles(e,t,n)},addInitialFiles:function(e){var t=this;qq.each(e,function(e,n){t._addCannedFile(n)})},addFiles:function(e,t,n){this._maybeHandleIos8SafariWorkaround();var i=0===this._storedIds.length?qq.getUniqueId():this._currentBatchId,o=qq.bind(function(e){this._handleNewFile({blob:e,name:this._options.blobs.defaultName},i,d)},this),r=qq.bind(function(e){this._handleNewFile(e,i,d)},this),a=qq.bind(function(e){var t=qq.canvasToBlob(e);this._handleNewFile({blob:t,name:this._options.blobs.defaultName+".png"},i,d)},this),s=qq.bind(function(e){var t=e.quality&&e.quality/100,n=qq.canvasToBlob(e.canvas,e.type,t);this._handleNewFile({blob:n,name:e.name},i,d)},this),u=qq.bind(function(e){if(qq.isInput(e)&&qq.supportedFeatures.ajaxUploading){var t=Array.prototype.slice.call(e.files),n=this;qq.each(t,function(e,t){n._handleNewFile(t,i,d)})}else this._handleNewFile(e,i,d)},this),l=function(){qq.isFileList(e)&&(e=Array.prototype.slice.call(e)),e=[].concat(e)},c=this,d=[];this._currentBatchId=i,e&&(l(),qq.each(e,function(e,t){qq.isFileOrInput(t)?u(t):qq.isBlob(t)?o(t):qq.isObject(t)?t.blob&&t.name?r(t):t.canvas&&t.name&&s(t):t.tagName&&"canvas"===t.tagName.toLowerCase()?a(t):c.log(t+" is not a valid file container! Ignoring!","warn")}),this.log("Received "+d.length+" files."),this._prepareItemsForUpload(d,t,n))},cancel:function(e){var t=this._uploadData.retrieve({id:e});t&&t.status===qq.status.UPLOAD_FINALIZING?this.log(qq.format("Ignoring cancel for file ID {} ({}). Finalizing upload.",e,this.getName(e)),"error"):this._handler.cancel(e)},cancelAll:function(){var e=[],t=this;qq.extend(e,this._storedIds),qq.each(e,function(e,n){t.cancel(n)}),this._handler.cancelAll()},clearStoredFiles:function(){this._storedIds=[]},continueUpload:function(e){var t=this._uploadData.retrieve({id:e});return!(!qq.supportedFeatures.pause||!this._options.chunking.enabled)&&(t.status===qq.status.PAUSED?(this.log(qq.format("Paused file ID {} ({}) will be continued. Not paused.",e,this.getName(e))),this._uploadFile(e),!0):(this.log(qq.format("Ignoring continue for file ID {} ({}). Not paused.",e,this.getName(e)),"error"),!1))},deleteFile:function(e){return this._onSubmitDelete(e)},doesExist:function(e){return this._handler.isValid(e)},drawThumbnail:function(e,t,n,i,o){var r,a,s=new qq.Promise;return this._imageGenerator?(r=this._thumbnailUrls[e],a={customResizeFunction:o,maxSize:n>0?n:null,scale:n>0},!i&&qq.supportedFeatures.imagePreviews&&(r=this.getFile(e)),null==r?s.failure({container:t,error:"File or URL not found."}):this._imageGenerator.generate(r,t,a).then(function(e){s.success(e)},function(e,t){s.failure({container:e,error:t||"Problem generating thumbnail"})})):s.failure({container:t,error:"Missing image generator module"}),s},getButton:function(e){return this._getButton(this._buttonIdsForFileIds[e])},getEndpoint:function(e){return this._endpointStore.get(e)},getFile:function(e){var t,n=this._handler.getFile(e);return n||(t=this._uploadData.retrieve({id:e}),t&&(n=t.file)),n||null},getInProgress:function(){return this._uploadData.retrieve({status:[qq.status.UPLOADING,qq.status.UPLOAD_RETRYING,qq.status.QUEUED]}).length},getName:function(e){return this._uploadData.retrieve({id:e}).name},getParentId:function(e){var t=this.getUploads({id:e}),n=null;return t&&void 0!==t.parentId&&(n=t.parentId),n},getResumableFilesData:function(){return this._handler.getResumableFilesData()},getSize:function(e){return this._uploadData.retrieve({id:e}).size},getNetUploads:function(){return this._netUploaded},getRemainingAllowedItems:function(){var e=this._currentItemLimit;return e>0?e-this._netUploadedOrQueued:null},getUploads:function(e){return this._uploadData.retrieve(e)},getUuid:function(e){return this._uploadData.retrieve({id:e}).uuid},isResumable:function(e){return this._handler.hasResumeRecord(e)},log:function(e,t){!this._options.debug||t&&"info"!==t?t&&"info"!==t&&qq.log("[Fine Uploader "+qq.version+"] "+e,t):qq.log("[Fine Uploader "+qq.version+"] "+e)},pauseUpload:function(e){var t=this._uploadData.retrieve({id:e});if(!qq.supportedFeatures.pause||!this._options.chunking.enabled)return!1;if(qq.indexOf([qq.status.UPLOADING,qq.status.UPLOAD_RETRYING],t.status)>=0){if(this._handler.pause(e))return this._uploadData.setStatus(e,qq.status.PAUSED),!0;this.log(qq.format("Unable to pause file ID {} ({}).",e,this.getName(e)),"error")}else this.log(qq.format("Ignoring pause for file ID {} ({}). Not in progress.",e,this.getName(e)),"error");return!1},removeFileRef:function(e){this._handler.expunge(e),this._uploadData.removeFileRef(e)},reset:function(){this.log("Resetting uploader..."),this._handler.reset(),this._storedIds=[],this._autoRetries=[],this._retryTimeouts=[],this._preventRetries=[],this._thumbnailUrls=[],qq.each(this._buttons,function(e,t){t.reset()}),this._paramsStore.reset(),this._endpointStore.reset(),this._netUploadedOrQueued=0,this._netUploaded=0,this._uploadData.reset(),this._buttonIdsForFileIds=[],this._pasteHandler&&this._pasteHandler.reset(),this._options.session.refreshOnReset&&this._refreshSessionData(),this._succeededSinceLastAllComplete=[],this._failedSinceLastAllComplete=[],this._totalProgress&&this._totalProgress.reset(),this._customResumeDataStore.reset()},retry:function(e){return this._manualRetry(e)},scaleImage:function(e,t){var n=this;return qq.Scaler.prototype.scaleImage(e,t,{log:qq.bind(n.log,n),getFile:qq.bind(n.getFile,n),uploadData:n._uploadData})},setCustomHeaders:function(e,t){this._customHeadersStore.set(e,t)},setCustomResumeData:function(e,t){this._customResumeDataStore.set(t,e)},setDeleteFileCustomHeaders:function(e,t){this._deleteFileCustomHeadersStore.set(e,t)},setDeleteFileEndpoint:function(e,t){this._deleteFileEndpointStore.set(e,t)},setDeleteFileParams:function(e,t){this._deleteFileParamsStore.set(e,t)},setEndpoint:function(e,t){this._endpointStore.set(e,t)},setForm:function(e){this._updateFormSupportAndParams(e)},setItemLimit:function(e){this._currentItemLimit=e},setName:function(e,t){this._uploadData.updateName(e,t)},setParams:function(e,t){this._paramsStore.set(e,t)},setUuid:function(e,t){return this._uploadData.uuidChanged(e,t)},setStatus:function(e,t){if(!this.getUploads({id:e}))throw new qq.Error(e+" is not a valid file ID.");switch(t){case qq.status.DELETED:this._onDeleteComplete(e,null,!1);break;case qq.status.DELETE_FAILED:this._onDeleteComplete(e,null,!0);break;default:var n="Method setStatus called on '"+name+"' not implemented yet for "+t;throw this.log(n),new qq.Error(n)}},uploadStoredFiles:function(){0===this._storedIds.length?this._itemError("noFilesError"):this._uploadStoredFiles()}},qq.basePrivateApi={_addCannedFile:function(e){var t=this;return this._uploadData.addFile({uuid:e.uuid,name:e.name,size:e.size,status:qq.status.UPLOAD_SUCCESSFUL,onBeforeStatusChange:function(n){e.deleteFileEndpoint&&t.setDeleteFileEndpoint(e.deleteFileEndpoint,n),e.deleteFileParams&&t.setDeleteFileParams(e.deleteFileParams,n),e.thumbnailUrl&&(t._thumbnailUrls[n]=e.thumbnailUrl),t._netUploaded++,t._netUploadedOrQueued++}})},_annotateWithButtonId:function(e,t){qq.isFile(e)&&(e.qqButtonId=this._getButtonId(t))},_batchError:function(e){this._options.callbacks.onError(null,null,e,void 0)},_createDeleteHandler:function(){var e=this;return new qq.DeleteFileAjaxRequester({method:this._options.deleteFile.method.toUpperCase(),maxConnections:this._options.maxConnections,uuidParamName:this._options.request.uuidName,customHeaders:this._deleteFileCustomHeadersStore,paramsStore:this._deleteFileParamsStore,endpointStore:this._deleteFileEndpointStore,cors:this._options.cors,log:qq.bind(e.log,e),onDelete:function(t){e._onDelete(t),e._options.callbacks.onDelete(t)},onDeleteComplete:function(t,n,i){e._onDeleteComplete(t,n,i),e._options.callbacks.onDeleteComplete(t,n,i)}})},_createPasteHandler:function(){var e=this;return new qq.PasteSupport({targetElement:this._options.paste.targetElement,callbacks:{log:qq.bind(e.log,e),pasteReceived:function(t){e._handleCheckedCallback({name:"onPasteReceived",callback:qq.bind(e._options.callbacks.onPasteReceived,e,t),onSuccess:qq.bind(e._handlePasteSuccess,e,t),identifier:"pasted image"})}}})},_createStore:function(e,t){var n={},i=e,o={},r=t,a=function(e){return qq.isObject(e)?qq.extend({},e):e},s=function(){return qq.isFunction(r)?r():r},u=function(e,t){r&&qq.isObject(t)&&qq.extend(t,s()),o[e]&&qq.extend(t,o[e])};return{set:function(e,t){null==t?(n={},i=a(e)):n[t]=a(e)},get:function(e){var t;return t=null!=e&&n[e]?n[e]:a(i),u(e,t),a(t)},addReadOnly:function(e,t){qq.isObject(n)&&(null===e?qq.isFunction(t)?r=t:(r=r||{},qq.extend(r,t)):(o[e]=o[e]||{},qq.extend(o[e],t)))},remove:function(e){return delete n[e]},reset:function(){n={},o={},i=e}}},_createUploadDataTracker:function(){var e=this;return new qq.UploadData({getName:function(t){return e.getName(t)},getUuid:function(t){return e.getUuid(t)},getSize:function(t){return e.getSize(t)},onStatusChange:function(t,n,i){e._onUploadStatusChange(t,n,i),e._options.callbacks.onStatusChange(t,n,i),e._maybeAllComplete(t,i),e._totalProgress&&setTimeout(function(){e._totalProgress.onStatusChange(t,n,i)},0)}})},_createUploadButton:function(e){function t(){return!!qq.supportedFeatures.ajaxUploading&&(!(i._options.workarounds.iosEmptyVideos&&qq.ios()&&!qq.ios6()&&i._isAllowedExtension(r,".mov"))&&(void 0===e.multiple?i._options.multiple:e.multiple))}var n,i=this,o=e.accept||this._options.validation.acceptFiles,r=e.allowedExtensions||this._options.validation.allowedExtensions;return n=new qq.UploadButton({acceptFiles:o,element:e.element,focusClass:this._options.classes.buttonFocus,folders:e.folders,hoverClass:this._options.classes.buttonHover,ios8BrowserCrashWorkaround:this._options.workarounds.ios8BrowserCrash,multiple:t(),name:this._options.request.inputName,onChange:function(e){i._onInputChange(e)},title:null==e.title?this._options.text.fileInputTitle:e.title}),this._disposeSupport.addDisposer(function(){n.dispose()}),i._buttons.push(n),n},_createUploadHandler:function(e,t){var n=this,i={},o={debug:this._options.debug,maxConnections:this._options.maxConnections,cors:this._options.cors,paramsStore:this._paramsStore,endpointStore:this._endpointStore,chunking:this._options.chunking,resume:this._options.resume,blobs:this._options.blobs,log:qq.bind(n.log,n),preventRetryParam:this._options.retry.preventRetryResponseProperty,onProgress:function(e,t,o,r){o<0||r<0||(i[e]?i[e].loaded===o&&i[e].total===r||(n._onProgress(e,t,o,r),n._options.callbacks.onProgress(e,t,o,r)):(n._onProgress(e,t,o,r),n._options.callbacks.onProgress(e,t,o,r)),i[e]={loaded:o,total:r})},onComplete:function(e,t,o,r){delete i[e];var a,s=n.getUploads({id:e}).status;s!==qq.status.UPLOAD_SUCCESSFUL&&s!==qq.status.UPLOAD_FAILED&&(a=n._onComplete(e,t,o,r),a instanceof qq.Promise?a.done(function(){n._options.callbacks.onComplete(e,t,o,r)}):n._options.callbacks.onComplete(e,t,o,r))},onCancel:function(e,t,i){var o=new qq.Promise;return n._handleCheckedCallback({name:"onCancel",callback:qq.bind(n._options.callbacks.onCancel,n,e,t),onFailure:o.failure,onSuccess:function(){i.then(function(){n._onCancel(e,t)}),o.success()},identifier:e}),o},onUploadPrep:qq.bind(this._onUploadPrep,this),onUpload:function(e,t){n._onUpload(e,t);var i=n._options.callbacks.onUpload(e,t);return qq.isGenericPromise(i)?(n.log(qq.format("onUpload for {} returned a Promise - waiting for resolution.",e)),i):(new qq.Promise).success()},onUploadChunk:function(e,t,i){n._onUploadChunk(e,i);var o=n._options.callbacks.onUploadChunk(e,t,i);return qq.isGenericPromise(o)?(n.log(qq.format("onUploadChunk for {}.{} returned a Promise - waiting for resolution.",e,i.partIndex)),o):(new qq.Promise).success()},onUploadChunkSuccess:function(e,t,i,o){n._onUploadChunkSuccess(e,t),n._options.callbacks.onUploadChunkSuccess.apply(n,arguments)},onResume:function(e,t,i,o){return n._options.callbacks.onResume(e,t,i,o)},onAutoRetry:function(e,t,i,o){return n._onAutoRetry.apply(n,arguments)},onUuidChanged:function(e,t){n.log("Server requested UUID change from '"+n.getUuid(e)+"' to '"+t+"'"),n.setUuid(e,t)},getName:qq.bind(n.getName,n),getUuid:qq.bind(n.getUuid,n),getSize:qq.bind(n.getSize,n),setSize:qq.bind(n._setSize,n),getDataByUuid:function(e){return n.getUploads({uuid:e})},isQueued:function(e){var t=n.getUploads({id:e}).status;return t===qq.status.QUEUED||t===qq.status.SUBMITTED||t===qq.status.UPLOAD_RETRYING||t===qq.status.PAUSED},getIdsInProxyGroup:n._uploadData.getIdsInProxyGroup,getIdsInBatch:n._uploadData.getIdsInBatch,isInProgress:function(e){return n.getUploads({id:e}).status===qq.status.UPLOADING},getCustomResumeData:qq.bind(n._getCustomResumeData,n),setStatus:function(e,t){n._uploadData.setStatus(e,t)}};return qq.each(this._options.request,function(e,t){o[e]=t}),o.customHeaders=this._customHeadersStore,e&&qq.each(e,function(e,t){o[e]=t}),new qq.UploadHandlerController(o,t)},_fileOrBlobRejected:function(e){this._netUploadedOrQueued--,this._uploadData.setStatus(e,qq.status.REJECTED)},_formatSize:function(e){if(0===e)return e+this._options.text.sizeSymbols[0];var t=-1;do e/=1e3,t++;while(e>999);return Math.max(e,.1).toFixed(1)+this._options.text.sizeSymbols[t]},_generateExtraButtonSpecs:function(){var e=this;this._extraButtonSpecs={},qq.each(this._options.extraButtons,function(t,n){var i=n.multiple,o=qq.extend({},e._options.validation,!0),r=qq.extend({},n);void 0===i&&(i=e._options.multiple),r.validation&&qq.extend(o,n.validation,!0),qq.extend(r,{multiple:i,validation:o},!0),e._initExtraButton(r)})},_getButton:function(e){var t=this._extraButtonSpecs[e];return t?t.element:e===this._defaultButtonId?this._options.button:void 0},_getButtonId:function(e){var t,n,i=e;if(i instanceof qq.BlobProxy&&(i=i.referenceBlob),i&&!qq.isBlob(i)){if(qq.isFile(i))return i.qqButtonId;if("input"===i.tagName.toLowerCase()&&"file"===i.type.toLowerCase())return i.getAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME);if(t=i.getElementsByTagName("input"),qq.each(t,function(e,t){if("file"===t.getAttribute("type"))return n=t,!1}),n)return n.getAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME)}},_getCustomResumeData:function(e){return this._customResumeDataStore.get(e)},_getNotFinished:function(){return this._uploadData.retrieve({status:[qq.status.UPLOADING,qq.status.UPLOAD_RETRYING,qq.status.QUEUED,qq.status.SUBMITTING,qq.status.SUBMITTED,qq.status.PAUSED]}).length},_getValidationBase:function(e){var t=this._extraButtonSpecs[e];return t?t.validation:this._options.validation},_getValidationDescriptor:function(e){return e.file instanceof qq.BlobProxy?{name:qq.getFilename(e.file.referenceBlob),size:e.file.referenceBlob.size}:{name:this.getUploads({id:e.id}).name,size:this.getUploads({id:e.id}).size}},_getValidationDescriptors:function(e){var t=this,n=[]
+;return qq.each(e,function(e,i){n.push(t._getValidationDescriptor(i))}),n},_handleCameraAccess:function(){if(this._options.camera.ios&&qq.ios()){var e=this._options.camera.button,t=e?this._getButtonId(e):this._defaultButtonId,n=this._options;t&&t!==this._defaultButtonId&&(n=this._extraButtonSpecs[t]),n.multiple=!1,null===n.validation.acceptFiles?n.validation.acceptFiles="image/*;capture=camera":n.validation.acceptFiles+=",image/*;capture=camera",qq.each(this._buttons,function(e,i){if(i.getButtonId()===t)return i.setMultiple(n.multiple),i.setAcceptFiles(n.acceptFiles),!1})}},_handleCheckedCallback:function(e){var t=this,n=e.callback();return qq.isGenericPromise(n)?(this.log(e.name+" - waiting for "+e.name+" promise to be fulfilled for "+e.identifier),n.then(function(n){t.log(e.name+" promise success for "+e.identifier),e.onSuccess(n)},function(){e.onFailure?(t.log(e.name+" promise failure for "+e.identifier),e.onFailure()):t.log(e.name+" promise failure for "+e.identifier)})):(n!==!1?e.onSuccess(n):e.onFailure?(this.log(e.name+" - return value was 'false' for "+e.identifier+". Invoking failure callback."),e.onFailure()):this.log(e.name+" - return value was 'false' for "+e.identifier+". Will not proceed."),n)},_handleNewFile:function(e,t,n){var i=this,o=qq.getUniqueId(),r=-1,a=qq.getFilename(e),s=e.blob||e,u=this._customNewFileHandler?this._customNewFileHandler:qq.bind(i._handleNewFileGeneric,i);!qq.isInput(s)&&s.size>=0&&(r=s.size),u(s,a,o,r,n,t,this._options.request.uuidName,{uploadData:i._uploadData,paramsStore:i._paramsStore,addFileToHandler:function(e,t){i._handler.add(e,t),i._netUploadedOrQueued++,i._trackButton(e)}})},_handleNewFileGeneric:function(e,t,n,i,o,r){var a=this._uploadData.addFile({uuid:n,name:t,size:i,batchId:r,file:e});this._handler.add(a,e),this._trackButton(a),this._netUploadedOrQueued++,o.push({id:a,file:e})},_handlePasteSuccess:function(e,t){var n=e.type.split("/")[1],i=t;null==i&&(i=this._options.paste.defaultName),i+="."+n,this.addFiles({name:i,blob:e})},_handleDeleteSuccess:function(e){if(this.getUploads({id:e}).status!==qq.status.DELETED){var t=this.getName(e);this._netUploadedOrQueued--,this._netUploaded--,this._handler.expunge(e),this._uploadData.setStatus(e,qq.status.DELETED),this.log("Delete request for '"+t+"' has succeeded.")}},_handleDeleteFailed:function(e,t){var n=this.getName(e);this._uploadData.setStatus(e,qq.status.DELETE_FAILED),this.log("Delete request for '"+n+"' has failed.","error"),t&&void 0!==t.withCredentials?this._options.callbacks.onError(e,n,"Delete request failed with response code "+t.status,t):this._options.callbacks.onError(e,n,"Delete request failed",t)},_initExtraButton:function(e){var t=this._createUploadButton({accept:e.validation.acceptFiles,allowedExtensions:e.validation.allowedExtensions,element:e.element,folders:e.folders,multiple:e.multiple,title:e.fileInputTitle});this._extraButtonSpecs[t.getButtonId()]=e},_initFormSupportAndParams:function(){this._formSupport=qq.FormSupport&&new qq.FormSupport(this._options.form,qq.bind(this.uploadStoredFiles,this),qq.bind(this.log,this)),this._formSupport&&this._formSupport.attachedToForm?(this._paramsStore=this._createStore(this._options.request.params,this._formSupport.getFormInputsAsObject),this._options.autoUpload=this._formSupport.newAutoUpload,this._formSupport.newEndpoint&&(this._options.request.endpoint=this._formSupport.newEndpoint)):this._paramsStore=this._createStore(this._options.request.params)},_isDeletePossible:function(){return!(!qq.DeleteFileAjaxRequester||!this._options.deleteFile.enabled)&&(!this._options.cors.expected||(!!qq.supportedFeatures.deleteFileCorsXhr||!(!qq.supportedFeatures.deleteFileCorsXdr||!this._options.cors.allowXdr)))},_isAllowedExtension:function(e,t){var n=!1;return!e.length||(qq.each(e,function(e,i){if(qq.isString(i)){var o=new RegExp("\\."+i+"$","i");if(null!=t.match(o))return n=!0,!1}}),n)},_itemError:function(e,t,n){function i(e,t){a=a.replace(e,t)}var o,r,a=this._options.messages[e],s=[],u=[].concat(t),l=u[0],c=this._getButtonId(n),d=this._getValidationBase(c);return qq.each(d.allowedExtensions,function(e,t){qq.isString(t)&&s.push(t)}),o=s.join(", ").toLowerCase(),i("{file}",this._options.formatFileName(l)),i("{extensions}",o),i("{sizeLimit}",this._formatSize(d.sizeLimit)),i("{minSizeLimit}",this._formatSize(d.minSizeLimit)),r=a.match(/(\{\w+\})/g),null!==r&&qq.each(r,function(e,t){i(t,u[e])}),this._options.callbacks.onError(null,l,a,void 0),a},_manualRetry:function(e,t){if(this._onBeforeManualRetry(e))return this._netUploadedOrQueued++,this._uploadData.setStatus(e,qq.status.UPLOAD_RETRYING),t?t(e):this._handler.retry(e),!0},_maybeAllComplete:function(e,t){var n=this,i=this._getNotFinished();t===qq.status.UPLOAD_SUCCESSFUL?this._succeededSinceLastAllComplete.push(e):t===qq.status.UPLOAD_FAILED&&this._failedSinceLastAllComplete.push(e),0===i&&(this._succeededSinceLastAllComplete.length||this._failedSinceLastAllComplete.length)&&setTimeout(function(){n._onAllComplete(n._succeededSinceLastAllComplete,n._failedSinceLastAllComplete)},0)},_maybeHandleIos8SafariWorkaround:function(){var e=this;if(this._options.workarounds.ios8SafariUploads&&qq.ios800()&&qq.iosSafari())throw setTimeout(function(){window.alert(e._options.messages.unsupportedBrowserIos8Safari)},0),new qq.Error(this._options.messages.unsupportedBrowserIos8Safari)},_maybeParseAndSendUploadError:function(e,t,n,i){if(!n.success)if(i&&200!==i.status&&!n.error)this._options.callbacks.onError(e,t,"XHR returned response code "+i.status,i);else{var o=n.error?n.error:this._options.text.defaultResponseError;this._options.callbacks.onError(e,t,o,i)}},_maybeProcessNextItemAfterOnValidateCallback:function(e,t,n,i,o){var r=this;if(t.length>n)if(e||!this._options.validation.stopOnFirstInvalidFile)setTimeout(function(){var e=r._getValidationDescriptor(t[n]),a=r._getButtonId(t[n].file),s=r._getButton(a);r._handleCheckedCallback({name:"onValidate",callback:qq.bind(r._options.callbacks.onValidate,r,e,s),onSuccess:qq.bind(r._onValidateCallbackSuccess,r,t,n,i,o),onFailure:qq.bind(r._onValidateCallbackFailure,r,t,n,i,o),identifier:"Item '"+e.name+"', size: "+e.size})},0);else if(!e)for(;n0&&this._netUploadedOrQueued+1>n?(this._itemError("retryFailTooManyItems"),!1):(this.log("Retrying upload for '"+t+"' (id: "+e+")..."),!0))):(this.log("'"+e+"' is not a valid file ID","error"),!1)},_onCancel:function(e,t){this._netUploadedOrQueued--,clearTimeout(this._retryTimeouts[e]);var n=qq.indexOf(this._storedIds,e);!this._options.autoUpload&&n>=0&&this._storedIds.splice(n,1),this._uploadData.setStatus(e,qq.status.CANCELED)},_onComplete:function(e,t,n,i){return n.success?(n.thumbnailUrl&&(this._thumbnailUrls[e]=n.thumbnailUrl),this._netUploaded++,this._uploadData.setStatus(e,qq.status.UPLOAD_SUCCESSFUL)):(this._netUploadedOrQueued--,this._uploadData.setStatus(e,qq.status.UPLOAD_FAILED),n[this._options.retry.preventRetryResponseProperty]===!0&&(this._preventRetries[e]=!0)),this._maybeParseAndSendUploadError(e,t,n,i),!!n.success},_onDelete:function(e){this._uploadData.setStatus(e,qq.status.DELETING)},_onDeleteComplete:function(e,t,n){this.getName(e);n?this._handleDeleteFailed(e,t):this._handleDeleteSuccess(e)},_onInputChange:function(e){var t;if(qq.supportedFeatures.ajaxUploading){for(t=0;t0&&this.addFiles(e);qq.each(this._buttons,function(e,t){t.reset()})},_onProgress:function(e,t,n,i){this._totalProgress&&this._totalProgress.onIndividualProgress(e,n,i)},_onSubmit:function(e,t){},_onSubmitCallbackSuccess:function(e,t){this._onSubmit.apply(this,arguments),this._uploadData.setStatus(e,qq.status.SUBMITTED),this._onSubmitted.apply(this,arguments),this._options.autoUpload?(this._options.callbacks.onSubmitted.apply(this,arguments),this._uploadFile(e)):(this._storeForLater(e),this._options.callbacks.onSubmitted.apply(this,arguments))},_onSubmitDelete:function(e,t,n){var i,o=this.getUuid(e);return t&&(i=qq.bind(t,this,e,o,n)),this._isDeletePossible()?(this._handleCheckedCallback({name:"onSubmitDelete",callback:qq.bind(this._options.callbacks.onSubmitDelete,this,e),onSuccess:i||qq.bind(this._deleteHandler.sendDelete,this,e,o,n),identifier:e}),!0):(this.log("Delete request ignored for ID "+e+", delete feature is disabled or request not possible due to CORS on a user agent that does not support pre-flighting.","warn"),!1)},_onSubmitted:function(e){},_onTotalProgress:function(e,t){this._options.callbacks.onTotalProgress(e,t)},_onUploadPrep:function(e){},_onUpload:function(e,t){this._uploadData.setStatus(e,qq.status.UPLOADING)},_onUploadChunk:function(e,t){},_onUploadChunkSuccess:function(e,t){!this._preventRetries[e]&&this._options.retry.enableAuto&&(this._autoRetries[e]=0)},_onUploadStatusChange:function(e,t,n){n===qq.status.PAUSED&&clearTimeout(this._retryTimeouts[e])},_onValidateBatchCallbackFailure:function(e){var t=this;qq.each(e,function(e,n){t._fileOrBlobRejected(n.id)})},_onValidateBatchCallbackSuccess:function(e,t,n,i,o){var r,a=this._currentItemLimit,s=this._netUploadedOrQueued;0===a||s<=a?t.length>0?this._handleCheckedCallback({name:"onValidate",callback:qq.bind(this._options.callbacks.onValidate,this,e[0],o),onSuccess:qq.bind(this._onValidateCallbackSuccess,this,t,0,n,i),onFailure:qq.bind(this._onValidateCallbackFailure,this,t,0,n,i),identifier:"Item '"+t[0].file.name+"', size: "+t[0].file.size}):this._itemError("noFilesError"):(this._onValidateBatchCallbackFailure(t),r=this._options.messages.tooManyItemsError.replace(/\{netItems\}/g,s).replace(/\{itemLimit\}/g,a),this._batchError(r))},_onValidateCallbackFailure:function(e,t,n,i){var o=t+1;this._fileOrBlobRejected(e[t].id,e[t].file.name),this._maybeProcessNextItemAfterOnValidateCallback(!1,e,o,n,i)},_onValidateCallbackSuccess:function(e,t,n,i){var o=this,r=t+1,a=this._getValidationDescriptor(e[t]);this._validateFileOrBlobData(e[t],a).then(function(){o._upload(e[t].id,n,i),o._maybeProcessNextItemAfterOnValidateCallback(!0,e,r,n,i)},function(){o._maybeProcessNextItemAfterOnValidateCallback(!1,e,r,n,i)})},_prepareItemsForUpload:function(e,t,n){if(0===e.length)return void this._itemError("noFilesError");var i=this._getValidationDescriptors(e),o=this._getButtonId(e[0].file),r=this._getButton(o);this._handleCheckedCallback({name:"onValidateBatch",callback:qq.bind(this._options.callbacks.onValidateBatch,this,i,r),onSuccess:qq.bind(this._onValidateBatchCallbackSuccess,this,i,e,t,n,r),onFailure:qq.bind(this._onValidateBatchCallbackFailure,this,e),identifier:"batch validation"})},_preventLeaveInProgress:function(){var e=this;this._disposeSupport.attach(window,"beforeunload",function(t){if(e.getInProgress())return t=t||window.event,t.returnValue=e._options.messages.onLeave,e._options.messages.onLeave})},_refreshSessionData:function(){var e=this,t=this._options.session;qq.Session&&null!=this._options.session.endpoint&&(this._session||(qq.extend(t,{cors:this._options.cors}),t.log=qq.bind(this.log,this),t.addFileRecord=qq.bind(this._addCannedFile,this),this._session=new qq.Session(t)),setTimeout(function(){e._session.refresh().then(function(t,n){e._sessionRequestComplete(),e._options.callbacks.onSessionRequestComplete(t,!0,n)},function(t,n){e._options.callbacks.onSessionRequestComplete(t,!1,n)})},0))},_sessionRequestComplete:function(){},_setSize:function(e,t){this._uploadData.updateSize(e,t),this._totalProgress&&this._totalProgress.onNewSize(e)},_shouldAutoRetry:function(e){var t=this._uploadData.retrieve({id:e});return!!(!this._preventRetries[e]&&this._options.retry.enableAuto&&t.status!==qq.status.PAUSED&&(void 0===this._autoRetries[e]&&(this._autoRetries[e]=0),this._autoRetries[e]0&&s.sizeLimit&&r>s.sizeLimit?(this._itemError("sizeError",o,i),u.failure()):r>0&&r=0}function n(e){var t=!1;return qq.each(t,function(e,n){if(qq.indexOf(["Accept","Accept-Language","Content-Language","Content-Type"],n)<0)return t=!0,!1}),t}function i(e){return w.cors.expected&&void 0===e.withCredentials}function o(){var e;return(window.XMLHttpRequest||window.ActiveXObject)&&(e=qq.createXhrInstance(),void 0===e.withCredentials&&(e=new XDomainRequest,e.onload=function(){},e.onerror=function(){},e.ontimeout=function(){},e.onprogress=function(){})),e}function r(e,t){var n=S[e]&&S[e].xhr;return n||(n=t?t:w.cors.expected?o():qq.createXhrInstance(),S[e].xhr=n),n}function a(e){var t,n=qq.indexOf(v,e),i=w.maxConnections;delete S[e],v.splice(n,1),v.length>=i&&n=0?o.send(qq.obj2url(s,"")):s&&w.contentType&&w.contentType.toLowerCase().indexOf("application/json")>=0?o.send(JSON.stringify(s)):o.send(s),o}function c(e,t,n){var i=w.endpointStore.get(e),o=S[e].addToPath;return void 0!=o&&(i+="/"+o),b&&t&&(i=qq.obj2url(t,i)),n&&(i=qq.obj2url(n,i)),i}function d(e){return function(){4===r(e).readyState&&s(e)}}function f(e){var t=w.onProgress;t&&(r(e).upload.onprogress=function(n){n.lengthComputable&&t(e,n.loaded,n.total)})}function p(e){return function(){s(e)}}function h(e){return function(){s(e,!0)}}function q(e){var o=r(e),a=w.customHeaders,s=S[e].additionalHeaders||{},u=w.method,l={};i(o)||(w.acceptHeader&&o.setRequestHeader("Accept",w.acceptHeader),w.allowXRequestedWithAndCacheControl&&(w.cors.expected&&t()&&!n(a)||(o.setRequestHeader("X-Requested-With","XMLHttpRequest"),o.setRequestHeader("Cache-Control","no-cache"))),!w.contentType||"POST"!==u&&"PUT"!==u||o.setRequestHeader("Content-Type",w.contentType),qq.extend(l,qq.isFunction(a)?a(e):a),qq.extend(l,s),qq.each(l,function(e,t){o.setRequestHeader(e,t)}))}function m(e){return qq.indexOf(w.successfulResponseCodes[w.method],e)>=0}function g(e,t,n,i,o,r,a){if(S[e]={addToPath:n,additionalParams:i,additionalQueryParams:o,additionalHeaders:r,payload:a},v.push(e)<=w.maxConnections)return l(e,t)}var _,b,v=[],S={},w={acceptHeader:null,validMethods:["PATCH","POST","PUT"],method:"POST",contentType:"application/x-www-form-urlencoded",maxConnections:3,customHeaders:{},endpointStore:{},paramsStore:{},mandatedParams:{},allowXRequestedWithAndCacheControl:!0,successfulResponseCodes:{DELETE:[200,202,204],PATCH:[200,201,202,203,204],POST:[200,201,202,203,204],PUT:[200,201,202,203,204],GET:[200]},cors:{expected:!1,sendCredentials:!1},log:function(e,t){},onSend:function(e){},onComplete:function(e,t,n){},onProgress:null};if(qq.extend(w,e),_=w.log,qq.indexOf(w.validMethods,w.method)<0)throw new Error("'"+w.method+"' is not a supported method for this type of request!");b="GET"===w.method||"DELETE"===w.method,qq.extend(this,{initTransport:function(e){var t,n,i,o,r,a;return{withPath:function(e){return t=e,this},withParams:function(e){return n=e,this},withQueryParams:function(e){return a=e,this},withHeaders:function(e){return i=e,this},withPayload:function(e){return o=e,this},withCacheBuster:function(){return r=!0,this},send:function(s){return r&&qq.indexOf(["GET","DELETE"],w.method)>=0&&(n.qqtimestamp=(new Date).getTime()),g(e,s,t,n,a,i,o)}}},canceled:function(e){a(e)}})},qq.UploadHandler=function(e){"use strict";var t=e.proxy,n={},i=t.onCancel,o=t.getName;qq.extend(this,{add:function(e,t){n[e]=t,n[e].temp={}},cancel:function(e){var t=this,r=new qq.Promise;i(e,o(e),r).then(function(){t.isValid(e)&&(n[e].canceled=!0,t.expunge(e)),r.success()})},expunge:function(e){delete n[e]},getThirdPartyFileId:function(e){return n[e].key},isValid:function(e){return void 0!==n[e]},reset:function(){n={}},_getFileState:function(e){return n[e]},_setThirdPartyFileId:function(e,t){n[e].key=t},_wasCanceled:function(e){return!!n[e].canceled}})},qq.UploadHandlerController=function(e,t){"use strict";var n,i,o,r=this,a=!1,s=!1,u={paramsStore:{},maxConnections:3,chunking:{enabled:!1,multiple:{enabled:!1}},log:function(e,t){},onProgress:function(e,t,n,i){},onComplete:function(e,t,n,i){},onCancel:function(e,t){},onUploadPrep:function(e){},onUpload:function(e,t){},onUploadChunk:function(e,t,n){},onUploadChunkSuccess:function(e,t,n,i){},onAutoRetry:function(e,t,n,i){},onResume:function(e,t,n,i){},onUuidChanged:function(e,t){},getName:function(e){},setSize:function(e,t){},isQueued:function(e){},getIdsInProxyGroup:function(e){},getIdsInBatch:function(e){},isInProgress:function(e){}},l={done:function(e,t,n,i){var r=o._getChunkData(e,t);o._getFileState(e).attemptingResume=!1,delete o._getFileState(e).temp.chunkProgress[t],o._getFileState(e).loaded+=r.size,u.onUploadChunkSuccess(e,o._getChunkDataForCallback(r),n,i)},finalize:function(e){var t=u.getSize(e),n=u.getName(e);i("All chunks have been uploaded for "+e+" - finalizing...."),o.finalizeChunks(e).then(function(r,a){i("Finalize successful for "+e);var s=f.normalizeResponse(r,!0);u.onProgress(e,n,t,t),o._maybeDeletePersistedChunkData(e),f.cleanup(e,s,a)},function(t,o){var r=f.normalizeResponse(t,!1);i("Problem finalizing chunks for file ID "+e+" - "+r.error,"error"),(r.reset||o&&u.chunking.success.resetOnStatus.indexOf(o.status)>=0)&&l.reset(e),u.onAutoRetry(e,n,r,o)||f.cleanup(e,r,o)})},handleFailure:function(e,t,n,r){var a=u.getName(t);i("Chunked upload request failed for "+t+", chunk "+e),o.clearCachedChunk(t,e);var d,p=f.normalizeResponse(n,!1);if(p.reset)l.reset(t);else{var h=o._getFileState(t).chunking.inProgress;d=h?qq.indexOf(h,e):-1,d>=0&&(o._getFileState(t).chunking.inProgress.splice(d,1),o._getFileState(t).chunking.remaining.unshift(e))}o._getFileState(t).temp.ignoreFailure||(s&&(o._getFileState(t).temp.ignoreFailure=!0,i(qq.format("Going to attempt to abort these chunks: {}. These are currently in-progress: {}.",JSON.stringify(Object.keys(o._getXhrs(t))),JSON.stringify(o._getFileState(t).chunking.inProgress))),qq.each(o._getXhrs(t),function(e,n){i(qq.format("Attempting to abort file {}.{}. XHR readyState {}. ",t,e,n.readyState)),n.abort(),n._cancelled=!0}),o.moveInProgressToRemaining(t),c.free(t,!0)),u.onAutoRetry(t,a,p,r)||f.cleanup(t,p,r))},hasMoreParts:function(e){return!!o._getFileState(e).chunking.remaining.length},nextPart:function(e){var t=o._getFileState(e).chunking.remaining.shift();return t>=o._getTotalChunks(e)&&(t=null),t},reset:function(e){i("Server or callback has ordered chunking effort to be restarted on next attempt for item ID "+e,"error"),o._maybeDeletePersistedChunkData(e),o.reevaluateChunking(e),o._getFileState(e).loaded=0,o._getFileState(e).attemptingResume=!1},sendNext:function(e){var t=u.getSize(e),n=u.getName(e),r=l.nextPart(e),a=o._getChunkData(e,r),d=o._getFileState(e),p=d.attemptingResume,h=d.chunking.inProgress||[];if(null==d.loaded&&(d.loaded=0),p&&u.onResume(e,n,a,d.customResumeData)===!1&&(l.reset(e),r=l.nextPart(e),a=o._getChunkData(e,r),p=!1),null==r&&0===h.length)l.finalize(e);else{h.push(r),o._getFileState(e).chunking.inProgress=h,s&&c.open(e,r),s&&c.available()&&o._getFileState(e).chunking.remaining.length&&l.sendNext(e),0===a.blob.size&&(i(qq.format("Chunk {} for file {} will not be uploaded, zero sized chunk.",r,e),"error"),l.handleFailure(r,e,"File is no longer available",null));u.onUploadChunk(e,n,o._getChunkDataForCallback(a)).then(function(n){if(u.isInProgress(e)){i(qq.format("Sending chunked upload request for item {}.{}, bytes {}-{} of {}.",e,r,a.start+1,a.end,t));var s={chunkIdx:r,id:e,overrides:n,resuming:p};o.uploadChunk(s).then(function(t,n){i("Chunked upload request succeeded for "+e+", chunk "+r),o.clearCachedChunk(e,r);var a=o._getFileState(e).chunking.inProgress||[],s=f.normalizeResponse(t,!0),u=qq.indexOf(a,r);i(qq.format("Chunk {} for file {} uploaded successfully.",r,e)),l.done(e,r,s,n),u>=0&&a.splice(u,1),o._maybePersistChunkedState(e),l.hasMoreParts(e)||0!==a.length?l.hasMoreParts(e)?l.sendNext(e):i(qq.format("File ID {} has no more chunks to send and these chunk indexes are still marked as in-progress: {}",e,JSON.stringify(a))):l.finalize(e)},function(t,n){l.handleFailure(r,e,t,n)}).done(function(){o.clearXhr(e,r)})}else i(qq.format("Not sending chunked upload request for item {}.{} - no longer in progress.",e,r))},function(t){l.handleFailure(r,e,t,null)})}}},c={_open:[],_openChunks:{},_waiting:[],available:function(){var e=u.maxConnections,t=0,n=0;return qq.each(c._openChunks,function(e,i){t++,n+=i.length}),e-(c._open.length-t+n)},free:function(e,t){var n,r=!t,a=qq.indexOf(c._waiting,e),s=qq.indexOf(c._open,e);delete c._openChunks[e],f.getProxyOrBlob(e)instanceof qq.BlobProxy&&(i("Generated blob upload has ended for "+e+", disposing generated blob."),delete o._getFileState(e).file),a>=0?c._waiting.splice(a,1):r&&s>=0&&(c._open.splice(s,1),n=c._waiting.shift(),n>=0&&(c._open.push(n),f.start(n)))},getWaitingOrConnected:function(){var e=[];return qq.each(c._openChunks,function(t,n){n&&n.length&&e.push(parseInt(t))}),qq.each(c._open,function(t,n){c._openChunks[n]||e.push(parseInt(n))}),e=e.concat(c._waiting)},isUsingConnection:function(e){return qq.indexOf(c._open,e)>=0},open:function(e,t){return null==t&&c._waiting.push(e),!!c.available()&&(null==t?(c._waiting.pop(),c._open.push(e)):function(){var n=c._openChunks[e]||[];n.push(t),c._openChunks[e]=n}(),!0)},reset:function(){c._waiting=[],c._open=[]}},d={send:function(e,t){var n=o._getFileState(e);if(!n)return void i("Ignoring send request as this upload may have been cancelled, File ID "+e,"warn");n.loaded=0,i("Sending simple upload request for "+e),o.uploadFile(e).then(function(n,o){i("Simple upload request succeeded for "+e)
+;var r=f.normalizeResponse(n,!0),a=u.getSize(e);u.onProgress(e,t,a,a),f.maybeNewUuid(e,r),f.cleanup(e,r,o)},function(n,o){i("Simple upload request failed for "+e);var r=f.normalizeResponse(n,!1);u.onAutoRetry(e,t,r,o)||f.cleanup(e,r,o)})}},f={cancel:function(e){i("Cancelling "+e),u.paramsStore.remove(e),c.free(e)},cleanup:function(e,t,n){var i=u.getName(e);u.onComplete(e,i,t,n),o._getFileState(e)&&o._clearXhrs&&o._clearXhrs(e),c.free(e)},getProxyOrBlob:function(e){return o.getProxy&&o.getProxy(e)||o.getFile&&o.getFile(e)},initHandler:function(){o=new(t?qq[t]:qq.traditional)[(qq.supportedFeatures.ajaxUploading?"Xhr":"Form")+"UploadHandler"](u,{getCustomResumeData:u.getCustomResumeData,getDataByUuid:u.getDataByUuid,getName:u.getName,getSize:u.getSize,getUuid:u.getUuid,log:i,onCancel:u.onCancel,onProgress:u.onProgress,onUuidChanged:u.onUuidChanged,onFinalizing:function(e){u.setStatus(e,qq.status.UPLOAD_FINALIZING)}}),o._removeExpiredChunkingRecords&&o._removeExpiredChunkingRecords()},isDeferredEligibleForUpload:function(e){return u.isQueued(e)},maybeDefer:function(e,t){return t&&!o.getFile(e)&&t instanceof qq.BlobProxy?(u.onUploadPrep(e),i("Attempting to generate a blob on-demand for "+e),t.create().then(function(t){i("Generated an on-demand blob for "+e),o.updateBlob(e,t),u.setSize(e,t.size),o.reevaluateChunking(e),f.maybeSendDeferredFiles(e)},function(t){var o={};t&&(o.error=t),i(qq.format("Failed to generate blob for ID {}. Error message: {}.",e,t),"error"),u.onComplete(e,u.getName(e),qq.extend(o,n),null),f.maybeSendDeferredFiles(e),c.free(e)}),!1):f.maybeSendDeferredFiles(e)},maybeSendDeferredFiles:function(e){var t=u.getIdsInProxyGroup(e),n=!1;return t&&t.length?(i("Maybe ready to upload proxy group file "+e),qq.each(t,function(t,i){if(f.isDeferredEligibleForUpload(i)&&o.getFile(i))n=i===e,f.now(i);else if(f.isDeferredEligibleForUpload(i))return!1})):(n=!0,f.now(e)),n},maybeNewUuid:function(e,t){void 0!==t.newUuid&&u.onUuidChanged(e,t.newUuid)},normalizeResponse:function(e,t){var n=e;return qq.isObject(e)||(n={},qq.isString(e)&&!t&&(n.error=e)),n.success=t,n},now:function(e){var t=u.getName(e);if(!r.isValid(e))throw new qq.Error(e+" is not a valid file ID to upload!");u.onUpload(e,t).then(function(n){n&&n.pause?(u.setStatus(e,qq.status.PAUSED),o.pause(e),c.free(e)):a&&o._shouldChunkThisFile(e)?l.sendNext(e):d.send(e,t)},function(n){if(n=n||{},i(e+" upload start aborted due to rejected onUpload Promise - details: "+n,"error"),!u.onAutoRetry(e,t,n.responseJSON||{})){var o=f.normalizeResponse(n.responseJSON,!1);f.cleanup(e,o)}})},start:function(e){var t=f.getProxyOrBlob(e);return t?f.maybeDefer(e,t):(f.now(e),!0)}};qq.extend(this,{add:function(e,t){o.add.apply(this,arguments)},upload:function(e){return!!c.open(e)&&f.start(e)},retry:function(e){return s&&(o._getFileState(e).temp.ignoreFailure=!1),c.isUsingConnection(e)?f.start(e):r.upload(e)},cancel:function(e){var t=o.cancel(e);qq.isGenericPromise(t)?t.then(function(){f.cancel(e)}):t!==!1&&f.cancel(e)},cancelAll:function(){var e,t=c.getWaitingOrConnected();if(t.length)for(e=t.length-1;e>=0;e--)r.cancel(t[e]);c.reset()},getFile:function(e){return o.getProxy&&o.getProxy(e)?o.getProxy(e).referenceBlob:o.getFile&&o.getFile(e)},isProxied:function(e){return!(!o.getProxy||!o.getProxy(e))},getInput:function(e){if(o.getInput)return o.getInput(e)},reset:function(){i("Resetting upload handler"),r.cancelAll(),c.reset(),o.reset()},expunge:function(e){if(r.isValid(e))return o.expunge(e)},isValid:function(e){return o.isValid(e)},hasResumeRecord:function(e){var t=o.isValid(e)&&o._getLocalStorageId&&o._getLocalStorageId(e);return!!t&&!!localStorage.getItem(t)},getResumableFilesData:function(){return o.getResumableFilesData?o.getResumableFilesData():[]},getThirdPartyFileId:function(e){if(r.isValid(e))return o.getThirdPartyFileId(e)},pause:function(e){return!!(r.isResumable(e)&&o.pause&&r.isValid(e)&&o.pause(e))&&(c.free(e),o.moveInProgressToRemaining(e),!0)},isAttemptingResume:function(e){return!!o.isAttemptingResume&&o.isAttemptingResume(e)},isResumable:function(e){return!!o.isResumable&&o.isResumable(e)}}),qq.extend(u,e),i=u.log,a=u.chunking.enabled&&qq.supportedFeatures.chunking,s=a&&u.chunking.concurrent.enabled,n=function(){var e={};return e[u.preventRetryParam]=!0,e}(),f.initHandler()},qq.WindowReceiveMessage=function(e){"use strict";var t={log:function(e,t){}},n={};qq.extend(t,e),qq.extend(this,{receiveMessage:function(e,t){var i=function(e){t(e.data)};window.postMessage?n[e]=qq(window).attach("message",i):log("iframe message passing not supported in this browser!","error")},stopReceivingMessages:function(e){if(window.postMessage){var t=n[e];t&&t()}}})},qq.FormUploadHandler=function(e){"use strict";function t(e){delete c[e],f&&(clearTimeout(d[e]),delete d[e],m.stopReceivingMessages(e));var t=document.getElementById(a._getIframeName(e));t&&(t.setAttribute("src","javascript:false;"),qq(t).remove())}function n(e){return e.split("_")[0]}function i(e){var t=qq.toElement("");return t.setAttribute("id",e),t.style.display="none",document.body.appendChild(t),t}function o(e,t){var i=e.id,o=n(i);l[h(o)]=t,c[o]=qq(e).attach("load",function(){a.getInput(o)&&(q("Received iframe load event for CORS upload request (iframe name "+i+")"),d[i]=setTimeout(function(){var e="No valid message received from loaded iframe for iframe name "+i;q(e,"error"),t({error:e})},1e3))}),m.receiveMessage(i,function(e){q("Received the following window message: '"+e+"'");var t,o=(n(i),a._parseJsonResponse(e)),r=o.uuid;r&&l[r]?(q("Handling response for iframe name "+i),clearTimeout(d[i]),delete d[i],a._detachLoadEvent(i),t=l[r],delete l[r],m.stopReceivingMessages(i),t(o)):r||q("'"+e+"' does not contain a UUID - ignoring.")})}var r=e.options,a=this,s=e.proxy,u=qq.getUniqueId(),l={},c={},d={},f=r.isCors,p=r.inputName,h=s.getUuid,q=s.log,m=new qq.WindowReceiveMessage({log:q});qq.extend(this,new qq.UploadHandler(e)),qq.override(this,function(e){return{add:function(t,n){e.add(t,{input:n}),n.setAttribute("name",p),n.parentNode&&qq(n).remove()},expunge:function(n){t(n),e.expunge(n)},isValid:function(t){return e.isValid(t)&&void 0!==a._getFileState(t).input}}}),qq.extend(this,{getInput:function(e){return a._getFileState(e).input},_attachLoadEvent:function(e,t){var n;f?o(e,t):c[e.id]=qq(e).attach("load",function(){if(q("Received response for "+e.id),e.parentNode){try{if(e.contentDocument&&e.contentDocument.body&&"false"==e.contentDocument.body.innerHTML)return}catch(e){q("Error when attempting to access iframe during handling of upload response ("+e.message+")","error"),n={success:!1}}t(n)}})},_createIframe:function(e){return i(a._getIframeName(e))},_detachLoadEvent:function(e){void 0!==c[e]&&(c[e](),delete c[e])},_getIframeName:function(e){return e+"_"+u},_initFormForUpload:function(e){var t=e.method,n=e.endpoint,i=e.params,o=e.paramsInBody,r=e.targetName,a=qq.toElement(""),s=n;return o?qq.obj2Inputs(i,a):s=qq.obj2url(i,n),a.setAttribute("action",s),a.setAttribute("target",r),a.style.display="none",document.body.appendChild(a),a},_parseJsonResponse:function(e){var t={};try{t=qq.parseJson(e)}catch(e){q("Error when attempting to parse iframe upload response ("+e.message+")","error")}return t}})},qq.XhrUploadHandler=function(e){"use strict";function t(e){qq.each(n._getXhrs(e),function(t,i){var o=n._getAjaxRequester(e,t);i.onreadystatechange=null,i.upload.onprogress=null,i.abort(),o&&o.canceled&&o.canceled(e)})}var n=this,i=e.options.namespace,o=e.proxy,r=e.options.chunking,a=function(e){var t=n._getFileState(e);if(t.chunkSize)return t.chunkSize;var i=r.partSize;return qq.isFunction(i)&&(i=i(e,d(e))),t.chunkSize=i,i},s=e.options.resume,u=r&&e.options.chunking.enabled&&qq.supportedFeatures.chunking,l=s&&e.options.resume.enabled&&u&&qq.supportedFeatures.resume,c=o.getName,d=o.getSize,f=o.getUuid,p=o.getEndpoint,h=o.getDataByUuid,q=o.onUuidChanged,m=o.onProgress,g=o.log,_=o.getCustomResumeData;qq.extend(this,new qq.UploadHandler(e)),qq.override(this,function(e){return{add:function(t,i){if(qq.isFile(i)||qq.isBlob(i))e.add(t,{file:i});else{if(!(i instanceof qq.BlobProxy))throw new Error("Passed obj is not a File, Blob, or proxy");e.add(t,{proxy:i})}n._initTempState(t),l&&n._maybePrepareForResume(t)},expunge:function(i){t(i),n._maybeDeletePersistedChunkData(i),n._clearXhrs(i),e.expunge(i)}}}),qq.extend(this,{clearCachedChunk:function(e,t){var i=n._getFileState(e);i&&delete i.temp.cachedChunks[t]},clearXhr:function(e,t){var i=n._getFileState(e).temp;i.xhrs&&delete i.xhrs[t],i.ajaxRequesters&&delete i.ajaxRequesters[t]},finalizeChunks:function(e,t){var i=n._getTotalChunks(e)-1,o=n._getXhr(e,i);return t?(new qq.Promise).success(t(o),o):(new qq.Promise).success({},o)},getFile:function(e){return n.isValid(e)&&n._getFileState(e).file},getProxy:function(e){return n.isValid(e)&&n._getFileState(e).proxy},getResumableFilesData:function(){var e=[];return n._iterateResumeRecords(function(t,i){n.moveInProgressToRemaining(null,i.chunking.inProgress,i.chunking.remaining);var o={name:i.name,remaining:i.chunking.remaining,size:i.size,uuid:i.uuid};i.key&&(o.key=i.key),i.customResumeData&&(o.customResumeData=i.customResumeData),e.push(o)}),e},isAttemptingResume:function(e){return n._getFileState(e).attemptingResume},isResumable:function(e){return!!r&&n.isValid(e)&&!n._getFileState(e).notResumable},moveInProgressToRemaining:function(e,t,i){var o=n._getFileState(e)||{},r=o.chunking||{},a=t||r.inProgress,s=i||r.remaining;a&&(g(qq.format("Moving these chunks from in-progress {}, to remaining.",JSON.stringify(a))),a.reverse(),qq.each(a,function(e,t){s.unshift(t)}),a.length=0)},pause:function(e){if(n.isValid(e))return g(qq.format("Aborting XHR upload for {} '{}' due to pause instruction.",e,c(e))),n._getFileState(e).paused=!0,t(e),!0},reevaluateChunking:function(e){if(r&&n.isValid(e)){var t,i,o=n._getFileState(e);if(delete o.chunking,o.chunking={},t=n._getTotalChunks(e),t>1||r.mandatory){for(o.chunking.enabled=!0,o.chunking.parts=t,o.chunking.remaining=[],i=0;i=o?o:s+i,l=n._getTotalChunks(e),c=this._getFileState(e).temp.cachedChunks,f=c[t]||qq.sliceBlob(r,s,u);return c[t]=f,{part:t,start:s,end:u,count:l,blob:f,size:u-s}},_getChunkDataForCallback:function(e){return{partIndex:e.part,startByte:e.start+1,endByte:e.end,totalParts:e.count}},_getLocalStorageId:function(e){var t=c(e),n=d(e),o=a(e),r=p(e),u=s.customKeys(e),l=qq.format("qq{}resume{}-{}-{}-{}-{}",i,"5.0",t,n,o,r);return u.forEach(function(e){l+="-"+e}),l},_getMimeType:function(e){return n.getFile(e).type},_getPersistableData:function(e){return n._getFileState(e).chunking},_getTotalChunks:function(e){if(r){var t=d(e),n=a(e);return Math.ceil(t/n)}},_getXhr:function(e,t){var i=null==t?-1:t;return n._getFileState(e).temp.xhrs[i]},_getXhrs:function(e){return n._getFileState(e).temp.xhrs},_iterateResumeRecords:function(e){l&&qq.each(localStorage,function(t,n){if(0===t.indexOf(qq.format("qq{}resume",i))){e(t,JSON.parse(n))}})},_initTempState:function(e){n._getFileState(e).temp={ajaxRequesters:{},chunkProgress:{},xhrs:{},cachedChunks:{}}},_markNotResumable:function(e){n._getFileState(e).notResumable=!0},_maybeDeletePersistedChunkData:function(e){var t;return!!(l&&n.isResumable(e)&&(t=n._getLocalStorageId(e),t&&localStorage.getItem(t)))&&(localStorage.removeItem(t),!0)},_maybePrepareForResume:function(e){var t,i,o=n._getFileState(e);l&&void 0===o.key&&(t=n._getLocalStorageId(e),i=localStorage.getItem(t),i&&(i=JSON.parse(i),h(i.uuid)?n._markNotResumable(e):(g(qq.format("Identified file with ID {} and name of {} as resumable.",e,c(e))),q(e,i.uuid),o.key=i.key,o.chunking=i.chunking,o.loaded=i.loaded,o.customResumeData=i.customResumeData,o.attemptingResume=!0,n.moveInProgressToRemaining(e))))},_maybePersistChunkedState:function(e){var t,i,o=n._getFileState(e);if(l&&n.isResumable(e)){var r=_(e);t=n._getLocalStorageId(e),i={name:c(e),size:d(e),uuid:f(e),key:o.key,chunking:o.chunking,loaded:o.loaded,lastUpdated:Date.now()},r&&(i.customResumeData=r);try{localStorage.setItem(t,JSON.stringify(i))}catch(t){g(qq.format("Unable to save resume data for '{}' due to error: '{}'.",e,t.toString()),"warn")}}},_registerProgressHandler:function(e,t,i){var o=n._getXhr(e,t),r=c(e),a={simple:function(t,n){var i=d(e);t===n?m(e,r,i,i):m(e,r,t>=i?i-1:t,i)},chunked:function(o,a){var s=n._getFileState(e).temp.chunkProgress,u=n._getFileState(e).loaded,l=o,c=a,f=d(e),p=l-(c-i),h=u;s[t]=p,qq.each(s,function(e,t){h+=t}),m(e,r,h,f)}};o.upload.onprogress=function(e){if(e.lengthComputable){a[null==i?"simple":"chunked"](e.loaded,e.total)}}},_registerXhr:function(e,t,i,o){var r=null==t?-1:t,a=n._getFileState(e).temp;return a.xhrs=a.xhrs||{},a.ajaxRequesters=a.ajaxRequesters||{},a.xhrs[r]=i,o&&(a.ajaxRequesters[r]=o),i},_removeExpiredChunkingRecords:function(){var e=s.recordsExpireIn;n._iterateResumeRecords(function(t,n){var i=new Date(n.lastUpdated);i.setDate(i.getDate()+e),i.getTime()<=Date.now()&&(g("Removing expired resume record with key "+t),localStorage.removeItem(t))})},_shouldChunkThisFile:function(e){var t=n._getFileState(e);if(t)return t.chunking||n.reevaluateChunking(e),t.chunking.enabled}})},qq.DeleteFileAjaxRequester=function(e){"use strict";function t(){return"POST"===i.method.toUpperCase()?{_method:"DELETE"}:{}}var n,i={method:"DELETE",uuidParamName:"qquuid",endpointStore:{},maxConnections:3,customHeaders:function(e){return{}},paramsStore:{},cors:{expected:!1,sendCredentials:!1},log:function(e,t){},onDelete:function(e){},onDeleteComplete:function(e,t,n){}};qq.extend(i,e),n=qq.extend(this,new qq.AjaxRequester({acceptHeader:"application/json",validMethods:["POST","DELETE"],method:i.method,endpointStore:i.endpointStore,paramsStore:i.paramsStore,mandatedParams:t(),maxConnections:i.maxConnections,customHeaders:function(e){return i.customHeaders.get(e)},log:i.log,onSend:i.onDelete,onComplete:i.onDeleteComplete,cors:i.cors})),qq.extend(this,{sendDelete:function(e,t,o){var r=o||{};i.log("Submitting delete file request for "+e),"DELETE"===i.method?n.initTransport(e).withPath(t).withParams(r).send():(r[i.uuidParamName]=t,n.initTransport(e).withParams(r).send())}})},function(){function e(e){var t,n=e.naturalWidth,i=e.naturalHeight,o=document.createElement("canvas");return n*i>1048576&&(o.width=o.height=1,t=o.getContext("2d"),t.drawImage(e,-n+1,0),0===t.getImageData(0,0,1,1).data[3])}function t(e,t,n){var i,o,r,a,s=document.createElement("canvas"),u=0,l=n,c=n;for(s.width=1,s.height=n,i=s.getContext("2d"),i.drawImage(e,0,0),o=i.getImageData(0,0,1,n).data;c>u;)r=o[4*(c-1)+3],0===r?l=c:u=c,c=l+u>>1;return a=c/n,0===a?1:a}function n(e,t,n,i){var r=document.createElement("canvas"),a=n.mime||"image/jpeg",s=new qq.Promise;return o(e,t,r,n,i).then(function(){s.success(r.toDataURL(a,n.quality||.8))}),s}function i(e){if(!qq.ios())throw new qq.Error("Downsampled dimensions can only be reliably calculated for iOS!");if(e.origHeight*e.origWidth>5241e3)return{newHeight:Math.round(Math.sqrt(5241e3*(e.origHeight/e.origWidth))),newWidth:Math.round(Math.sqrt(5241e3*(e.origWidth/e.origHeight)))}}function o(n,o,s,u,l){var c,d=n.naturalWidth,f=n.naturalHeight,p=u.width,h=u.height,q=s.getContext("2d"),m=new qq.Promise;return q.save(),u.resize?r({blob:o,canvas:s,image:n,imageHeight:f,imageWidth:d,orientation:u.orientation,resize:u.resize,targetHeight:h,targetWidth:p}):(qq.supportedFeatures.unlimitedScaledImageSize||(c=i({origWidth:p,origHeight:h}),c&&(qq.log(qq.format("Had to reduce dimensions due to device limitations from {}w / {}h to {}w / {}h",p,h,c.newWidth,c.newHeight),"warn"),p=c.newWidth,h=c.newHeight)),a(s,p,h,u.orientation),qq.ios()?function(){e(n)&&(d/=2,f/=2);var i,o,r,a=1024,s=document.createElement("canvas"),u=l?t(n,d,f):1,c=Math.ceil(a*p/d),m=Math.ceil(a*h/f/u),g=0,_=0;for(s.width=s.height=a,i=s.getContext("2d");gc&&(u=c,l=s*u/a<<0),d&&l>d&&(l=d,u=a*l/s<<0),i={width:u,height:l},qq.each(t,function(e,t){i[e]=t}),"img"===p?function(){var t=e.src;n(r.srcImage,r.blob,i,f).then(function(n){e.src=n,t===e.src&&e.onload()})}():"canvas"===p&&o(this.srcImage,this.blob,e,i,f),"function"==typeof this.onrender&&this.onrender(e)},qq.MegaPixImage=s}(),qq.ImageGenerator=function(e){"use strict";function t(e){return"img"===e.tagName.toLowerCase()}function n(e){return"canvas"===e.tagName.toLowerCase()}function i(){return void 0!==(new Image).crossOrigin}function o(){var e=document.createElement("canvas");return e.getContext&&e.getContext("2d")}function r(e){var t=e.split("/"),n=t[t.length-1].split("?")[0],i=qq.getExtension(n);switch(i=i&&i.toLowerCase()){case"jpeg":case"jpg":return"image/jpeg";case"png":return"image/png";case"bmp":return"image/bmp";case"gif":return"image/gif";case"tiff":case"tif":return"image/tiff"}}function a(e){var t,n,i,o=document.createElement("a");return o.href=e,t=o.protocol,i=o.port,n=o.hostname,t.toLowerCase()!==window.location.protocol.toLowerCase()||(n.toLowerCase()!==window.location.hostname.toLowerCase()||i!==window.location.port&&!qq.ie())}function s(t,n){t.onload=function(){t.onload=null,t.onerror=null,n.success(t)},t.onerror=function(){t.onload=null,t.onerror=null,e("Problem drawing thumbnail!","error"),n.failure(t,"Problem drawing thumbnail!")}}function u(e,t){e.qqImageRendered=function(){t.success(e)}}function l(i,o){var r=t(i)||n(i);return t(i)?s(i,o):n(i)?u(i,o):(o.failure(i),e(qq.format("Element container of type {} is not supported!",i.tagName),"error")),r}function c(t,n,i){var o=new qq.Promise,r=new qq.Identify(t,e),a=i.maxSize,s=null==i.orient||i.orient,u=function(){n.onerror=null,n.onload=null,e("Could not render preview, file may be too large!","error"),o.failure(n,"Browser cannot render image!")};return r.isPreviewable().then(function(r){var c={parse:function(){return(new qq.Promise).success()}},d=s?new qq.Exif(t,e):c,f=new qq.MegaPixImage(t,u);l(n,o)&&d.parse().then(function(e){var t=e&&e.Orientation;f.render(n,{maxWidth:a,maxHeight:a,orientation:t,mime:r,resize:i.customResizeFunction})},function(t){e(qq.format("EXIF data could not be parsed ({}). Assuming orientation = 1.",t)),f.render(n,{maxWidth:a,maxHeight:a,mime:r,resize:i.customResizeFunction})})},function(){e("Not previewable"),o.failure(n,"Not previewable")}),o}function d(e,t,n,i,o){var s=new Image,u=new qq.Promise;l(s,u),a(e)&&(s.crossOrigin="anonymous"),s.src=e,u.then(function(){l(t,n),new qq.MegaPixImage(s).render(t,{maxWidth:i,maxHeight:i,mime:r(e),resize:o})},n.failure)}function f(e,t,n,i){l(t,n),qq(t).css({maxWidth:i+"px",maxHeight:i+"px"}),t.src=e}function p(e,r,s){var u=new qq.Promise,c=s.scale,p=c?s.maxSize:null;return c&&t(r)?o()?a(e)&&!i()?f(e,r,u,p):d(e,r,u,p):f(e,r,u,p):n(r)?d(e,r,u,p):l(r,u)&&(r.src=e),u}qq.extend(this,{generate:function(t,n,i){return qq.isString(t)?(e("Attempting to update thumbnail based on server response."),p(t,n,i||{})):(e("Attempting to draw client-side image preview."),c(t,n,i||{}))}}),this._testing={},this._testing.isImg=t,this._testing.isCanvas=n,this._testing.isCrossOrigin=a,this._testing.determineMimeOfFileName=r},qq.Exif=function(e,t){"use strict";function n(e){for(var t=0,n=0;e.length>0;)t+=parseInt(e.substring(0,2),16)*Math.pow(2,n),e=e.substring(2,e.length),n+=8;return t}function i(t,n){var o=t,r=n;return void 0===o&&(o=2,r=new qq.Promise),qq.readBlobToHex(e,o,4).then(function(e){var t,n=/^ffe([0-9])/.exec(e);n?"1"!==n[1]?(t=parseInt(e.slice(4,8),16),i(o+t+2,r)):r.success(o):r.failure("No EXIF header to be found!")}),r}function o(){var t=new qq.Promise;return qq.readBlobToHex(e,0,6).then(function(e){0!==e.indexOf("ffd8")?t.failure("Not a valid JPEG!"):i().then(function(e){t.success(e)},function(e){t.failure(e)})}),t}function r(t){var n=new qq.Promise;return qq.readBlobToHex(e,t+10,2).then(function(e){n.success("4949"===e)}),n}function a(t,i){var o=new qq.Promise;return qq.readBlobToHex(e,t+18,2).then(function(e){if(i)return o.success(n(e));o.success(parseInt(e,16))}),o}function s(t,n){var i=t+20,o=12*n;return qq.readBlobToHex(e,i,o)}function u(e){for(var t=[],n=0;n+24<=e.length;)t.push(e.slice(n,n+24)),n+=24;return t}function l(e,t){var i=qq.extend([],c),o={};return qq.each(t,function(t,r){var a,s,u,l=r.slice(0,4),c=e?n(l):parseInt(l,16),f=i.indexOf(c);if(f>=0&&(s=d[c].name,u=d[c].bytes,a=r.slice(16,16+2*u),o[s]=e?n(a):parseInt(a,16),i.splice(f,1)),0===i.length)return!1}),o}var c=[274],d={274:{name:"Orientation",bytes:2}};qq.extend(this,{parse:function(){var n=new qq.Promise,i=function(e){t(qq.format("EXIF header parse failed: '{}' ",e)),n.failure(e)};return o().then(function(o){t(qq.format("Moving forward with EXIF header parsing for '{}'",void 0===e.name?"blob":e.name)),r(o).then(function(e){t(qq.format("EXIF Byte order is {} endian",e?"little":"big")),a(o,e).then(function(r){t(qq.format("Found {} APP1 directory entries",r)),s(o,r).then(function(i){var o=u(i),r=l(e,o);t("Successfully parsed some EXIF tags"),n.success(r)},i)},i)},i)},i),n}}),this._testing={},this._testing.parseLittleEndian=n},qq.Identify=function(e,t){"use strict";function n(e,t){var n=!1,i=[].concat(e);return qq.each(i,function(e,i){if(0===t.indexOf(i))return n=!0,!1}),n}qq.extend(this,{isPreviewable:function(){var i=this,o=new qq.Promise,r=!1,a=void 0===e.name?"blob":e.name;return t(qq.format("Attempting to determine if {} can be rendered in this browser",a)),t("First pass: check type attribute of blob object."),this.isPreviewableSync()?(t("Second pass: check for magic bytes in file header."),qq.readBlobToHex(e,0,4).then(function(e){qq.each(i.PREVIEWABLE_MIME_TYPES,function(t,i){if(n(i,e))return("image/tiff"!==t||qq.supportedFeatures.tiffPreviews)&&(r=!0,o.success(t)),!1}),t(qq.format("'{}' is {} able to be rendered in this browser",a,r?"":"NOT")),r||o.failure()},function(){t("Error reading file w/ name '"+a+"'. Not able to be rendered in this browser."),o.failure()})):o.failure(),o},isPreviewableSync:function(){var n=e.type,i=qq.indexOf(Object.keys(this.PREVIEWABLE_MIME_TYPES),n)>=0,o=!1,r=void 0===e.name?"blob":e.name;return i&&(o="image/tiff"!==n||qq.supportedFeatures.tiffPreviews),!o&&t(r+" is not previewable in this browser per the blob's type attr"),o}})},qq.Identify.prototype.PREVIEWABLE_MIME_TYPES={"image/jpeg":"ffd8ff","image/gif":"474946","image/png":"89504e","image/bmp":"424d","image/tiff":["49492a00","4d4d002a"]},qq.ImageValidation=function(e,t){"use strict";function n(e){var t=!1;return qq.each(e,function(e,n){if(n>0)return t=!0,!1}),t}function i(){var n=new qq.Promise;return new qq.Identify(e,t).isPreviewable().then(function(){var i=new Image,o=window.URL&&window.URL.createObjectURL?window.URL:window.webkitURL&&window.webkitURL.createObjectURL?window.webkitURL:null;o?(i.onerror=function(){t("Cannot determine dimensions for image. May be too large.","error"),n.failure()},i.onload=function(){n.success({width:this.width,height:this.height})},i.src=o.createObjectURL(e)):(t("No createObjectURL function available to generate image URL!","error"),n.failure())},n.failure),n}function o(e,t){var n;return qq.each(e,function(e,i){if(i>0){var o=/(max|min)(Width|Height)/.exec(e),r=o[2].charAt(0).toLowerCase()+o[2].slice(1),a=t[r];switch(o[1]){case"min":if(ai)return n=e,!1}}}),n}this.validate=function(e){var r=new qq.Promise;return t("Attempting to validate image."),n(e)?i().then(function(t){var n=o(e,t);n?r.failure(n):r.success()},r.success):r.success(),r}},qq.Session=function(e){"use strict";function t(e){if(qq.isArray(e))return!0;i.log("Session response is not an array.","error")}function n(e,n,o,r){var a=!1;n=n&&t(e),n&&qq.each(e,function(e,t){if(null==t.uuid)a=!0,i.log(qq.format("Session response item {} did not include a valid UUID - ignoring.",e),"error");else if(null==t.name)a=!0,i.log(qq.format("Session response item {} did not include a valid name - ignoring.",e),"error");else try{return i.addFileRecord(t),!0}catch(e){a=!0,i.log(e.message,"error")}return!1}),r[n&&!a?"success":"failure"](e,o)}var i={endpoint:null,params:{},customHeaders:{},cors:{},addFileRecord:function(e){},log:function(e,t){}};qq.extend(i,e,!0),this.refresh=function(){var e=new qq.Promise,t=function(t,i,o){n(t,i,o,e)},o=qq.extend({},i);return new qq.SessionAjaxRequester(qq.extend(o,{onComplete:t})).queryServer(),e}},qq.SessionAjaxRequester=function(e){"use strict";function t(e,t,n){var o=null;if(null!=t.responseText)try{o=qq.parseJson(t.responseText)}catch(e){i.log("Problem parsing session response: "+e.message,"error"),n=!0}i.onComplete(o,!n,t)}var n,i={endpoint:null,customHeaders:{},params:{},cors:{expected:!1,sendCredentials:!1},onComplete:function(e,t,n){},log:function(e,t){}};qq.extend(i,e),n=qq.extend(this,new qq.AjaxRequester({acceptHeader:"application/json",validMethods:["GET"],method:"GET",endpointStore:{get:function(){return i.endpoint}},customHeaders:i.customHeaders,log:i.log,onComplete:t,cors:i.cors})),qq.extend(this,{queryServer:function(){var e=qq.extend({},i.params);i.log("Session query request."),n.initTransport("sessionRefresh").withParams(e).withCacheBuster().send()}})},qq.Scaler=function(e,t){"use strict";var n=e.customResizer,i=e.sendOriginal,o=e.orient,r=e.defaultType,a=e.defaultQuality/100,s=e.failureText,u=e.includeExif,l=this._getSortedSizes(e.sizes);qq.extend(this,{enabled:qq.supportedFeatures.scaling&&l.length>0,getFileRecords:function(e,c,d){var f=this,p=[],h=d.blob?d.blob:d;return new qq.Identify(h,t).isPreviewableSync()?(qq.each(l,function(e,i){var l=f._determineOutputType({defaultType:r,requestedType:i.type,refType:h.type});p.push({uuid:qq.getUniqueId(),name:f._getName(c,{name:i.name,type:l,refType:h.type}),blob:new qq.BlobProxy(h,qq.bind(f._generateScaledImage,f,{customResizeFunction:n,maxSize:i.maxSize,orient:o,type:l,quality:a,failedText:s,includeExif:u,log:t}))})}),p.push({uuid:e,name:c,size:h.size,blob:i?h:null})):p.push({uuid:e,name:c,size:h.size,blob:h}),p},handleNewFile:function(e,t,n,i,o,r,a,s){var u=this,l=(e.qqButtonId||e.blob&&e.blob.qqButtonId,[]),c=null,d=s.addFileToHandler,f=s.uploadData,p=s.paramsStore,h=qq.getUniqueId();qq.each(u.getFileRecords(n,t,e),function(e,t){var n,i=t.size;t.blob instanceof qq.BlobProxy&&(i=-1),n=f.addFile({uuid:t.uuid,name:t.name,size:i,batchId:r,proxyGroupId:h}),t.blob instanceof qq.BlobProxy?l.push(n):c=n,t.blob?(d(n,t.blob),o.push({id:n,file:t.blob})):f.setStatus(n,qq.status.REJECTED)}),null!==c&&(qq.each(l,function(e,t){var n={qqparentuuid:f.retrieve({id:c}).uuid,qqparentsize:f.retrieve({id:c}).size};n[a]=f.retrieve({id:t}).uuid,f.setParentId(t,c),p.addReadOnly(t,n)}),l.length&&function(){var e={};e[a]=f.retrieve({id:c}).uuid,p.addReadOnly(c,e)}())}})},qq.extend(qq.Scaler.prototype,{scaleImage:function(e,t,n){"use strict";if(!qq.supportedFeatures.scaling)throw new qq.Error("Scaling is not supported in this browser!");var i=new qq.Promise,o=n.log,r=n.getFile(e),a=n.uploadData.retrieve({id:e}),s=a&&a.name,u=a&&a.uuid,l={customResizer:t.customResizer,sendOriginal:!1,orient:t.orient,defaultType:t.type||null,defaultQuality:t.quality,failedToScaleText:"Unable to scale",sizes:[{name:"",maxSize:t.maxSize}]},c=new qq.Scaler(l,o);return qq.Scaler&&qq.supportedFeatures.imagePreviews&&r?qq.bind(function(){var t=c.getFileRecords(u,s,r)[0];t&&t.blob instanceof qq.BlobProxy?t.blob.create().then(i.success,i.failure):(o(e+" is not a scalable image!","error"),i.failure())},this)():(i.failure(),o("Could not generate requested scaled image for "+e+". Scaling is either not possible in this browser, or the file could not be located.","error")),i},_determineOutputType:function(e){"use strict";var t=e.requestedType,n=e.defaultType,i=e.refType;return n||t?t&&qq.indexOf(Object.keys(qq.Identify.prototype.PREVIEWABLE_MIME_TYPES),t)>=0?"image/tiff"===t?qq.supportedFeatures.tiffPreviews?t:n:t:n:"image/jpeg"!==i?"image/png":i},_getName:function(e,t){"use strict";var n=e.lastIndexOf("."),i=t.type||"image/png",o=t.refType,r="",a=qq.getExtension(e),s="";return t.name&&t.name.trim().length&&(s=" ("+t.name+")"),n>=0?(r=e.substr(0,n),o!==i&&(a=i.split("/")[1]),r+=s+"."+a):r=e+s,r},_getSortedSizes:function(e){"use strict";return e=qq.extend([],e),e.sort(function(e,t){return e.maxSize>t.maxSize?1:e.maxSize=0?atob(e.split(",")[1]):decodeURI(e.split(",")[1]),n=e.split(",")[0].split(":")[1].split(";")[0],i=new ArrayBuffer(t.length),o=new Uint8Array(i),qq.each(t,function(e,t){o[e]=t.charCodeAt(0)}),this._createBlob(i,n)},_createBlob:function(e,t){"use strict";var n=window.BlobBuilder||window.WebKitBlobBuilder||window.MozBlobBuilder||window.MSBlobBuilder,i=n&&new n;return i?(i.append(e),i.getBlob(t)):new Blob([e],{type:t})}}),qq.ExifRestorer=function(){var e={};return e.KEY_STR="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",e.encode64=function(e){var t,n,i,o,r,a="",s="",u="",l=0;do t=e[l++],n=e[l++],s=e[l++],i=t>>2,o=(3&t)<<4|n>>4,r=(15&n)<<2|s>>6,u=63&s,isNaN(n)?r=u=64:isNaN(s)&&(u=64),a=a+this.KEY_STR.charAt(i)+this.KEY_STR.charAt(o)+this.KEY_STR.charAt(r)+this.KEY_STR.charAt(u),t=n=s="",i=o=r=u="";while(le.length)break}return n},e.decode64=function(e){var t,n,i,o,r,a="",s="",u=0,l=[];if(/[^A-Za-z0-9\+\/\=]/g.exec(e))throw new Error("There were invalid base64 characters in the input text. Valid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='");e=e.replace(/[^A-Za-z0-9\+\/\=]/g,"");do i=this.KEY_STR.indexOf(e.charAt(u++)),o=this.KEY_STR.indexOf(e.charAt(u++)),r=this.KEY_STR.indexOf(e.charAt(u++)),s=this.KEY_STR.indexOf(e.charAt(u++)),t=i<<2|o>>4,n=(15&o)<<4|r>>2,a=(3&r)<<6|s,l.push(t),64!=r&&l.push(n),64!=s&&l.push(a),t=n=a="",i=o=r=s="";while(u=0)return n=!1,!1}),n},l=function(e){f(e,-1,-1),delete n[e]},c=function(e,t,n){(0===t.length||u(t,n))&&(s(o,o),this.reset())},d=function(e){var i=t(e);i>0&&(f(e,0,i),n[e]={loaded:0,total:i})},f=function(e,t,r){var a=n[e]?n[e].loaded:0,u=n[e]?n[e].total:0;t===-1&&r===-1?(i-=a,o-=u):(t&&(i+=t-a),r&&(o+=r-u)),s(i,o)};qq.extend(this,{onAllComplete:c,onStatusChange:function(e,t,n){n===qq.status.CANCELED||n===qq.status.REJECTED?l(e):n===qq.status.SUBMITTING&&d(e)},onIndividualProgress:function(e,t,i){f(e,t,i),n[e]={loaded:t,total:i}},onNewSize:function(e){d(e)},reset:function(){n={},i=0,o=0}})},qq.PasteSupport=function(e){"use strict";function t(e){return e.type&&0===e.type.indexOf("image/")}function n(){r=qq(o.targetElement).attach("paste",function(e){var n=e.clipboardData;n&&qq.each(n.items,function(e,n){if(t(n)){var i=n.getAsFile();o.callbacks.pasteReceived(i)}})})}function i(){r&&r()}var o,r;o={targetElement:null,callbacks:{log:function(e,t){},pasteReceived:function(e){}}},qq.extend(o,e),n(),qq.extend(this,{reset:function(){i()}})},qq.FormSupport=function(e,t,n){"use strict";function i(e){e.getAttribute("action")&&(s.newEndpoint=e.getAttribute("action"))}function o(e,t){if(!e.checkValidity||e.checkValidity())return!0;n("Form did not pass validation checks - will not upload.","error"),t()}function r(e){var n=e.submit;qq(e).attach("submit",function(i){i=i||window.event,i.preventDefault?i.preventDefault():i.returnValue=!1,o(e,n)&&t()}),e.submit=function(){o(e,n)&&t()}}function a(e){return e&&(qq.isString(e)&&(e=document.getElementById(e)),e&&(n("Attaching to form element."),i(e),u&&r(e))),e}var s=this,u=e.interceptSubmit,l=e.element,c=e.autoUpload;qq.extend(this,{newEndpoint:null,newAutoUpload:c,attachedToForm:!1,getFormInputsAsObject:function(){return null==l?null:s._form2Obj(l)}}),l=a(l),this.attachedToForm=!!l},qq.extend(qq.FormSupport.prototype,{_form2Obj:function(e){"use strict";var t={},n=function(e){var t=["button","image","reset","submit"];return qq.indexOf(t,e.toLowerCase())<0},i=function(e){return qq.indexOf(["checkbox","radio"],e.toLowerCase())>=0},o=function(e){return!(!i(e.type)||e.checked)||e.disabled&&"hidden"!==e.type.toLowerCase()},r=function(e){var t=null;return qq.each(qq(e).children(),function(e,n){if("option"===n.tagName.toLowerCase()&&n.selected)return t=n.value,!1}),t};return qq.each(e.elements,function(e,i){if(!qq.isInput(i,!0)&&"textarea"!==i.tagName.toLowerCase()||!n(i.type)||o(i)){if("select"===i.tagName.toLowerCase()&&!o(i)){var a=r(i);null!==a&&(t[i.name]=a)}}else t[i.name]=i.value}),t}}),qq.traditional=qq.traditional||{},qq.traditional.FormUploadHandler=function(e,t){"use strict";function n(e,t){var n,i,r;try{i=t.contentDocument||t.contentWindow.document,r=i.body.innerHTML,s("converting iframe's innerHTML to JSON"),s("innerHTML = "+r),r&&r.match(/^= 0) {\n byteString = atob(dataUri.split(\",\")[1]);\n }\n else {\n byteString = decodeURI(dataUri.split(\",\")[1]);\n }\n\n // extract the MIME\n mimeString = dataUri.split(\",\")[0]\n .split(\":\")[1]\n .split(\";\")[0];\n\n // write the bytes of the binary string to an ArrayBuffer\n arrayBuffer = new ArrayBuffer(byteString.length);\n intArray = new Uint8Array(arrayBuffer);\n qq.each(byteString, function(idx, character) {\n intArray[idx] = character.charCodeAt(0);\n });\n\n return createBlob(arrayBuffer, mimeString);\n };\n\n qq.log = function(message, level) {\n if (window.console) {\n if (!level || level === \"info\") {\n window.console.log(message);\n }\n else\n {\n if (window.console[level]) {\n window.console[level](message);\n }\n else {\n window.console.log(\"<\" + level + \"> \" + message);\n }\n }\n }\n };\n\n qq.isObject = function(variable) {\n return variable && !variable.nodeType && Object.prototype.toString.call(variable) === \"[object Object]\";\n };\n\n qq.isFunction = function(variable) {\n return typeof (variable) === \"function\";\n };\n\n /**\n * Check the type of a value. Is it an \"array\"?\n *\n * @param value value to test.\n * @returns true if the value is an array or associated with an `ArrayBuffer`\n */\n qq.isArray = function(value) {\n return Object.prototype.toString.call(value) === \"[object Array]\" ||\n (value && window.ArrayBuffer && value.buffer && value.buffer.constructor === ArrayBuffer);\n };\n\n // Looks for an object on a `DataTransfer` object that is associated with drop events when utilizing the Filesystem API.\n qq.isItemList = function(maybeItemList) {\n return Object.prototype.toString.call(maybeItemList) === \"[object DataTransferItemList]\";\n };\n\n // Looks for an object on a `NodeList` or an `HTMLCollection`|`HTMLFormElement`|`HTMLSelectElement`\n // object that is associated with collections of Nodes.\n qq.isNodeList = function(maybeNodeList) {\n return Object.prototype.toString.call(maybeNodeList) === \"[object NodeList]\" ||\n // If `HTMLCollection` is the actual type of the object, we must determine this\n // by checking for expected properties/methods on the object\n (maybeNodeList.item && maybeNodeList.namedItem);\n };\n\n qq.isString = function(maybeString) {\n return Object.prototype.toString.call(maybeString) === \"[object String]\";\n };\n\n qq.trimStr = function(string) {\n if (String.prototype.trim) {\n return string.trim();\n }\n\n return string.replace(/^\\s+|\\s+$/g, \"\");\n };\n\n /**\n * @param str String to format.\n * @returns {string} A string, swapping argument values with the associated occurrence of {} in the passed string.\n */\n qq.format = function(str) {\n\n var args = Array.prototype.slice.call(arguments, 1),\n newStr = str,\n nextIdxToReplace = newStr.indexOf(\"{}\");\n\n qq.each(args, function(idx, val) {\n var strBefore = newStr.substring(0, nextIdxToReplace),\n strAfter = newStr.substring(nextIdxToReplace + 2);\n\n newStr = strBefore + val + strAfter;\n nextIdxToReplace = newStr.indexOf(\"{}\", nextIdxToReplace + val.length);\n\n // End the loop if we have run out of tokens (when the arguments exceed the # of tokens)\n if (nextIdxToReplace < 0) {\n return false;\n }\n });\n\n return newStr;\n };\n\n qq.isFile = function(maybeFile) {\n return window.File && Object.prototype.toString.call(maybeFile) === \"[object File]\";\n };\n\n qq.isFileList = function(maybeFileList) {\n return window.FileList && Object.prototype.toString.call(maybeFileList) === \"[object FileList]\";\n };\n\n qq.isFileOrInput = function(maybeFileOrInput) {\n return qq.isFile(maybeFileOrInput) || qq.isInput(maybeFileOrInput);\n };\n\n qq.isInput = function(maybeInput, notFile) {\n var evaluateType = function(type) {\n var normalizedType = type.toLowerCase();\n\n if (notFile) {\n return normalizedType !== \"file\";\n }\n\n return normalizedType === \"file\";\n };\n\n if (window.HTMLInputElement) {\n if (Object.prototype.toString.call(maybeInput) === \"[object HTMLInputElement]\") {\n if (maybeInput.type && evaluateType(maybeInput.type)) {\n return true;\n }\n }\n }\n if (maybeInput.tagName) {\n if (maybeInput.tagName.toLowerCase() === \"input\") {\n if (maybeInput.type && evaluateType(maybeInput.type)) {\n return true;\n }\n }\n }\n\n return false;\n };\n\n qq.isBlob = function(maybeBlob) {\n if (window.Blob && Object.prototype.toString.call(maybeBlob) === \"[object Blob]\") {\n return true;\n }\n };\n\n qq.isXhrUploadSupported = function() {\n var input = document.createElement(\"input\");\n input.type = \"file\";\n\n return (\n input.multiple !== undefined &&\n typeof File !== \"undefined\" &&\n typeof FormData !== \"undefined\" &&\n typeof (qq.createXhrInstance()).upload !== \"undefined\");\n };\n\n // Fall back to ActiveX is native XHR is disabled (possible in any version of IE).\n qq.createXhrInstance = function() {\n if (window.XMLHttpRequest) {\n return new XMLHttpRequest();\n }\n\n try {\n return new ActiveXObject(\"MSXML2.XMLHTTP.3.0\");\n }\n catch (error) {\n qq.log(\"Neither XHR or ActiveX are supported!\", \"error\");\n return null;\n }\n };\n\n qq.isFolderDropSupported = function(dataTransfer) {\n return dataTransfer.items &&\n dataTransfer.items.length > 0 &&\n dataTransfer.items[0].webkitGetAsEntry;\n };\n\n qq.isFileChunkingSupported = function() {\n return !qq.androidStock() && //Android's stock browser cannot upload Blobs correctly\n qq.isXhrUploadSupported() &&\n (File.prototype.slice !== undefined || File.prototype.webkitSlice !== undefined || File.prototype.mozSlice !== undefined);\n };\n\n qq.sliceBlob = function(fileOrBlob, start, end) {\n var slicer = fileOrBlob.slice || fileOrBlob.mozSlice || fileOrBlob.webkitSlice;\n\n return slicer.call(fileOrBlob, start, end);\n };\n\n qq.arrayBufferToHex = function(buffer) {\n var bytesAsHex = \"\",\n bytes = new Uint8Array(buffer);\n\n qq.each(bytes, function(idx, byt) {\n var byteAsHexStr = byt.toString(16);\n\n if (byteAsHexStr.length < 2) {\n byteAsHexStr = \"0\" + byteAsHexStr;\n }\n\n bytesAsHex += byteAsHexStr;\n });\n\n return bytesAsHex;\n };\n\n qq.readBlobToHex = function(blob, startOffset, length) {\n var initialBlob = qq.sliceBlob(blob, startOffset, startOffset + length),\n fileReader = new FileReader(),\n promise = new qq.Promise();\n\n fileReader.onload = function() {\n promise.success(qq.arrayBufferToHex(fileReader.result));\n };\n\n fileReader.onerror = promise.failure;\n\n fileReader.readAsArrayBuffer(initialBlob);\n\n return promise;\n };\n\n qq.extend = function(first, second, extendNested) {\n qq.each(second, function(prop, val) {\n if (extendNested && qq.isObject(val)) {\n if (first[prop] === undefined) {\n first[prop] = {};\n }\n qq.extend(first[prop], val, true);\n }\n else {\n first[prop] = val;\n }\n });\n\n return first;\n };\n\n /**\n * Allow properties in one object to override properties in another,\n * keeping track of the original values from the target object.\n *\n * Note that the pre-overriden properties to be overriden by the source will be passed into the `sourceFn` when it is invoked.\n *\n * @param target Update properties in this object from some source\n * @param sourceFn A function that, when invoked, will return properties that will replace properties with the same name in the target.\n * @returns {object} The target object\n */\n qq.override = function(target, sourceFn) {\n var super_ = {},\n source = sourceFn(super_);\n\n qq.each(source, function(srcPropName, srcPropVal) {\n if (target[srcPropName] !== undefined) {\n super_[srcPropName] = target[srcPropName];\n }\n\n target[srcPropName] = srcPropVal;\n });\n\n return target;\n };\n\n /**\n * Searches for a given element (elt) in the array, returns -1 if it is not present.\n */\n qq.indexOf = function(arr, elt, from) {\n if (arr.indexOf) {\n return arr.indexOf(elt, from);\n }\n\n from = from || 0;\n var len = arr.length;\n\n if (from < 0) {\n from += len;\n }\n\n for (; from < len; from += 1) {\n if (arr.hasOwnProperty(from) && arr[from] === elt) {\n return from;\n }\n }\n return -1;\n };\n\n //this is a version 4 UUID\n qq.getUniqueId = function() {\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, function(c) {\n /*jslint eqeq: true, bitwise: true*/\n var r = Math.random() * 16 | 0, v = c == \"x\" ? r : (r & 0x3 | 0x8);\n return v.toString(16);\n });\n };\n\n //\n // Browsers and platforms detection\n qq.ie = function() {\n return navigator.userAgent.indexOf(\"MSIE\") !== -1 ||\n navigator.userAgent.indexOf(\"Trident\") !== -1;\n };\n\n qq.ie7 = function() {\n return navigator.userAgent.indexOf(\"MSIE 7\") !== -1;\n };\n\n qq.ie8 = function() {\n return navigator.userAgent.indexOf(\"MSIE 8\") !== -1;\n };\n\n qq.ie10 = function() {\n return navigator.userAgent.indexOf(\"MSIE 10\") !== -1;\n };\n\n qq.ie11 = function() {\n return qq.ie() && navigator.userAgent.indexOf(\"rv:11\") !== -1;\n };\n\n qq.edge = function() {\n return navigator.userAgent.indexOf(\"Edge\") >= 0;\n };\n\n qq.safari = function() {\n return navigator.vendor !== undefined && navigator.vendor.indexOf(\"Apple\") !== -1;\n };\n\n qq.chrome = function() {\n return navigator.vendor !== undefined && navigator.vendor.indexOf(\"Google\") !== -1;\n };\n\n qq.opera = function() {\n return navigator.vendor !== undefined && navigator.vendor.indexOf(\"Opera\") !== -1;\n };\n\n qq.firefox = function() {\n return (!qq.edge() && !qq.ie11() && navigator.userAgent.indexOf(\"Mozilla\") !== -1 && navigator.vendor !== undefined && navigator.vendor === \"\");\n };\n\n qq.windows = function() {\n return navigator.platform === \"Win32\";\n };\n\n qq.android = function() {\n return navigator.userAgent.toLowerCase().indexOf(\"android\") !== -1;\n };\n\n // We need to identify the Android stock browser via the UA string to work around various bugs in this browser,\n // such as the one that prevents a `Blob` from being uploaded.\n qq.androidStock = function() {\n return qq.android() && navigator.userAgent.toLowerCase().indexOf(\"chrome\") < 0;\n };\n\n qq.ios6 = function() {\n return qq.ios() && navigator.userAgent.indexOf(\" OS 6_\") !== -1;\n };\n\n qq.ios7 = function() {\n return qq.ios() && navigator.userAgent.indexOf(\" OS 7_\") !== -1;\n };\n\n qq.ios8 = function() {\n return qq.ios() && navigator.userAgent.indexOf(\" OS 8_\") !== -1;\n };\n\n // iOS 8.0.0\n qq.ios800 = function() {\n return qq.ios() && navigator.userAgent.indexOf(\" OS 8_0 \") !== -1;\n };\n\n qq.ios = function() {\n /*jshint -W014 */\n return navigator.userAgent.indexOf(\"iPad\") !== -1\n || navigator.userAgent.indexOf(\"iPod\") !== -1\n || navigator.userAgent.indexOf(\"iPhone\") !== -1;\n };\n\n qq.iosChrome = function() {\n return qq.ios() && navigator.userAgent.indexOf(\"CriOS\") !== -1;\n };\n\n qq.iosSafari = function() {\n return qq.ios() && !qq.iosChrome() && navigator.userAgent.indexOf(\"Safari\") !== -1;\n };\n\n qq.iosSafariWebView = function() {\n return qq.ios() && !qq.iosChrome() && !qq.iosSafari();\n };\n\n //\n // Events\n\n qq.preventDefault = function(e) {\n if (e.preventDefault) {\n e.preventDefault();\n } else {\n e.returnValue = false;\n }\n };\n\n /**\n * Creates and returns element from html string\n * Uses innerHTML to create an element\n */\n qq.toElement = (function() {\n var div = document.createElement(\"div\");\n return function(html) {\n div.innerHTML = html;\n var element = div.firstChild;\n div.removeChild(element);\n return element;\n };\n }());\n\n //key and value are passed to callback for each entry in the iterable item\n qq.each = function(iterableItem, callback) {\n var keyOrIndex, retVal;\n\n if (iterableItem) {\n // Iterate through [`Storage`](http://www.w3.org/TR/webstorage/#the-storage-interface) items\n if (window.Storage && iterableItem.constructor === window.Storage) {\n for (keyOrIndex = 0; keyOrIndex < iterableItem.length; keyOrIndex++) {\n retVal = callback(iterableItem.key(keyOrIndex), iterableItem.getItem(iterableItem.key(keyOrIndex)));\n if (retVal === false) {\n break;\n }\n }\n }\n // `DataTransferItemList` & `NodeList` objects are array-like and should be treated as arrays\n // when iterating over items inside the object.\n else if (qq.isArray(iterableItem) || qq.isItemList(iterableItem) || qq.isNodeList(iterableItem)) {\n for (keyOrIndex = 0; keyOrIndex < iterableItem.length; keyOrIndex++) {\n retVal = callback(keyOrIndex, iterableItem[keyOrIndex]);\n if (retVal === false) {\n break;\n }\n }\n }\n else if (qq.isString(iterableItem)) {\n for (keyOrIndex = 0; keyOrIndex < iterableItem.length; keyOrIndex++) {\n retVal = callback(keyOrIndex, iterableItem.charAt(keyOrIndex));\n if (retVal === false) {\n break;\n }\n }\n }\n else {\n for (keyOrIndex in iterableItem) {\n if (Object.prototype.hasOwnProperty.call(iterableItem, keyOrIndex)) {\n retVal = callback(keyOrIndex, iterableItem[keyOrIndex]);\n if (retVal === false) {\n break;\n }\n }\n }\n }\n }\n };\n\n //include any args that should be passed to the new function after the context arg\n qq.bind = function(oldFunc, context) {\n if (qq.isFunction(oldFunc)) {\n var args = Array.prototype.slice.call(arguments, 2);\n\n return function() {\n var newArgs = qq.extend([], args);\n if (arguments.length) {\n newArgs = newArgs.concat(Array.prototype.slice.call(arguments));\n }\n return oldFunc.apply(context, newArgs);\n };\n }\n\n throw new Error(\"first parameter must be a function!\");\n };\n\n /**\n * obj2url() takes a json-object as argument and generates\n * a querystring. pretty much like jQuery.param()\n *\n * how to use:\n *\n * `qq.obj2url({a:'b',c:'d'},'http://any.url/upload?otherParam=value');`\n *\n * will result in:\n *\n * `http://any.url/upload?otherParam=value&a=b&c=d`\n *\n * @param Object JSON-Object\n * @param String current querystring-part\n * @return String encoded querystring\n */\n qq.obj2url = function(obj, temp, prefixDone) {\n /*jshint laxbreak: true*/\n var uristrings = [],\n prefix = \"&\",\n add = function(nextObj, i) {\n var nextTemp = temp\n ? (/\\[\\]$/.test(temp)) // prevent double-encoding\n ? temp\n : temp + \"[\" + i + \"]\"\n : i;\n if ((nextTemp !== \"undefined\") && (i !== \"undefined\")) {\n uristrings.push(\n (typeof nextObj === \"object\")\n ? qq.obj2url(nextObj, nextTemp, true)\n : (Object.prototype.toString.call(nextObj) === \"[object Function]\")\n ? encodeURIComponent(nextTemp) + \"=\" + encodeURIComponent(nextObj())\n : encodeURIComponent(nextTemp) + \"=\" + encodeURIComponent(nextObj)\n );\n }\n };\n\n if (!prefixDone && temp) {\n prefix = (/\\?/.test(temp)) ? (/\\?$/.test(temp)) ? \"\" : \"&\" : \"?\";\n uristrings.push(temp);\n uristrings.push(qq.obj2url(obj));\n } else if ((Object.prototype.toString.call(obj) === \"[object Array]\") && (typeof obj !== \"undefined\")) {\n qq.each(obj, function(idx, val) {\n add(val, idx);\n });\n } else if ((typeof obj !== \"undefined\") && (obj !== null) && (typeof obj === \"object\")) {\n qq.each(obj, function(prop, val) {\n add(val, prop);\n });\n } else {\n uristrings.push(encodeURIComponent(temp) + \"=\" + encodeURIComponent(obj));\n }\n\n if (temp) {\n return uristrings.join(prefix);\n } else {\n return uristrings.join(prefix)\n .replace(/^&/, \"\")\n .replace(/%20/g, \"+\");\n }\n };\n\n qq.obj2FormData = function(obj, formData, arrayKeyName) {\n if (!formData) {\n formData = new FormData();\n }\n\n qq.each(obj, function(key, val) {\n key = arrayKeyName ? arrayKeyName + \"[\" + key + \"]\" : key;\n\n if (qq.isObject(val)) {\n qq.obj2FormData(val, formData, key);\n }\n else if (qq.isFunction(val)) {\n formData.append(key, val());\n }\n else {\n formData.append(key, val);\n }\n });\n\n return formData;\n };\n\n qq.obj2Inputs = function(obj, form) {\n var input;\n\n if (!form) {\n form = document.createElement(\"form\");\n }\n\n qq.obj2FormData(obj, {\n append: function(key, val) {\n input = document.createElement(\"input\");\n input.setAttribute(\"name\", key);\n input.setAttribute(\"value\", val);\n form.appendChild(input);\n }\n });\n\n return form;\n };\n\n /**\n * Not recommended for use outside of Fine Uploader since this falls back to an unchecked eval if JSON.parse is not\n * implemented. For a more secure JSON.parse polyfill, use Douglas Crockford's json2.js.\n */\n qq.parseJson = function(json) {\n /*jshint evil: true*/\n if (window.JSON && qq.isFunction(JSON.parse)) {\n return JSON.parse(json);\n } else {\n return eval(\"(\" + json + \")\");\n }\n };\n\n /**\n * Retrieve the extension of a file, if it exists.\n *\n * @param filename\n * @returns {string || undefined}\n */\n qq.getExtension = function(filename) {\n var extIdx = filename.lastIndexOf(\".\") + 1;\n\n if (extIdx > 0) {\n return filename.substr(extIdx, filename.length - extIdx);\n }\n };\n\n qq.getFilename = function(blobOrFileInput) {\n /*jslint regexp: true*/\n\n if (qq.isInput(blobOrFileInput)) {\n // get input value and remove path to normalize\n return blobOrFileInput.value.replace(/.*(\\/|\\\\)/, \"\");\n }\n else if (qq.isFile(blobOrFileInput)) {\n if (blobOrFileInput.fileName !== null && blobOrFileInput.fileName !== undefined) {\n return blobOrFileInput.fileName;\n }\n }\n\n return blobOrFileInput.name;\n };\n\n /**\n * A generic module which supports object disposing in dispose() method.\n * */\n qq.DisposeSupport = function() {\n var disposers = [];\n\n return {\n /** Run all registered disposers */\n dispose: function() {\n var disposer;\n do {\n disposer = disposers.shift();\n if (disposer) {\n disposer();\n }\n }\n while (disposer);\n },\n\n /** Attach event handler and register de-attacher as a disposer */\n attach: function() {\n var args = arguments;\n /*jslint undef:true*/\n this.addDisposer(qq(args[0]).attach.apply(this, Array.prototype.slice.call(arguments, 1)));\n },\n\n /** Add disposer to the collection */\n addDisposer: function(disposeFunction) {\n disposers.push(disposeFunction);\n }\n };\n };\n}());\n","/* globals define, module, global, qq */\n(function() {\n \"use strict\";\n if (typeof define === \"function\" && define.amd) {\n define(function() {\n return qq;\n });\n }\n else if (typeof module !== \"undefined\" && module.exports) {\n module.exports = qq;\n }\n else {\n global.qq = qq;\n }\n}());\n","/* globals qq */\n/**\n * Fine Uploader top-level Error container. Inherits from `Error`.\n */\n(function() {\n \"use strict\";\n\n qq.Error = function(message) {\n this.message = \"[Fine Uploader \" + qq.version + \"] \" + message;\n };\n\n qq.Error.prototype = new Error();\n}());\n","/*global qq */\nqq.version = \"5.12.0\";\n","/* globals qq */\nqq.supportedFeatures = (function() {\n \"use strict\";\n\n var supportsUploading,\n supportsUploadingBlobs,\n supportsFileDrop,\n supportsAjaxFileUploading,\n supportsFolderDrop,\n supportsChunking,\n supportsResume,\n supportsUploadViaPaste,\n supportsUploadCors,\n supportsDeleteFileXdr,\n supportsDeleteFileCorsXhr,\n supportsDeleteFileCors,\n supportsFolderSelection,\n supportsImagePreviews,\n supportsUploadProgress;\n\n function testSupportsFileInputElement() {\n var supported = true,\n tempInput;\n\n try {\n tempInput = document.createElement(\"input\");\n tempInput.type = \"file\";\n qq(tempInput).hide();\n\n if (tempInput.disabled) {\n supported = false;\n }\n }\n catch (ex) {\n supported = false;\n }\n\n return supported;\n }\n\n //only way to test for Filesystem API support since webkit does not expose the DataTransfer interface\n function isChrome21OrHigher() {\n return (qq.chrome() || qq.opera()) &&\n navigator.userAgent.match(/Chrome\\/[2][1-9]|Chrome\\/[3-9][0-9]/) !== undefined;\n }\n\n //only way to test for complete Clipboard API support at this time\n function isChrome14OrHigher() {\n return (qq.chrome() || qq.opera()) &&\n navigator.userAgent.match(/Chrome\\/[1][4-9]|Chrome\\/[2-9][0-9]/) !== undefined;\n }\n\n //Ensure we can send cross-origin `XMLHttpRequest`s\n function isCrossOriginXhrSupported() {\n if (window.XMLHttpRequest) {\n var xhr = qq.createXhrInstance();\n\n //Commonly accepted test for XHR CORS support.\n return xhr.withCredentials !== undefined;\n }\n\n return false;\n }\n\n //Test for (terrible) cross-origin ajax transport fallback for IE9 and IE8\n function isXdrSupported() {\n return window.XDomainRequest !== undefined;\n }\n\n // CORS Ajax requests are supported if it is either possible to send credentialed `XMLHttpRequest`s,\n // or if `XDomainRequest` is an available alternative.\n function isCrossOriginAjaxSupported() {\n if (isCrossOriginXhrSupported()) {\n return true;\n }\n\n return isXdrSupported();\n }\n\n function isFolderSelectionSupported() {\n // We know that folder selection is only supported in Chrome via this proprietary attribute for now\n return document.createElement(\"input\").webkitdirectory !== undefined;\n }\n\n function isLocalStorageSupported() {\n try {\n return !!window.localStorage &&\n // unpatched versions of IE10/11 have buggy impls of localStorage where setItem is a string\n qq.isFunction(window.localStorage.setItem);\n }\n catch (error) {\n // probably caught a security exception, so no localStorage for you\n return false;\n }\n }\n\n function isDragAndDropSupported() {\n var span = document.createElement(\"span\");\n\n return (\"draggable\" in span || (\"ondragstart\" in span && \"ondrop\" in span)) &&\n !qq.android() && !qq.ios();\n }\n\n supportsUploading = testSupportsFileInputElement();\n\n supportsAjaxFileUploading = supportsUploading && qq.isXhrUploadSupported();\n\n supportsUploadingBlobs = supportsAjaxFileUploading && !qq.androidStock();\n\n supportsFileDrop = supportsAjaxFileUploading && isDragAndDropSupported();\n\n supportsFolderDrop = supportsFileDrop && isChrome21OrHigher();\n\n supportsChunking = supportsAjaxFileUploading && qq.isFileChunkingSupported();\n\n supportsResume = supportsAjaxFileUploading && supportsChunking && isLocalStorageSupported();\n\n supportsUploadViaPaste = supportsAjaxFileUploading && isChrome14OrHigher();\n\n supportsUploadCors = supportsUploading && (window.postMessage !== undefined || supportsAjaxFileUploading);\n\n supportsDeleteFileCorsXhr = isCrossOriginXhrSupported();\n\n supportsDeleteFileXdr = isXdrSupported();\n\n supportsDeleteFileCors = isCrossOriginAjaxSupported();\n\n supportsFolderSelection = isFolderSelectionSupported();\n\n supportsImagePreviews = supportsAjaxFileUploading && window.FileReader !== undefined;\n\n supportsUploadProgress = (function() {\n if (supportsAjaxFileUploading) {\n return !qq.androidStock() && !qq.iosChrome();\n }\n return false;\n }());\n\n return {\n ajaxUploading: supportsAjaxFileUploading,\n blobUploading: supportsUploadingBlobs,\n canDetermineSize: supportsAjaxFileUploading,\n chunking: supportsChunking,\n deleteFileCors: supportsDeleteFileCors,\n deleteFileCorsXdr: supportsDeleteFileXdr, //NOTE: will also return true in IE10, where XDR is also supported\n deleteFileCorsXhr: supportsDeleteFileCorsXhr,\n dialogElement: !!window.HTMLDialogElement,\n fileDrop: supportsFileDrop,\n folderDrop: supportsFolderDrop,\n folderSelection: supportsFolderSelection,\n imagePreviews: supportsImagePreviews,\n imageValidation: supportsImagePreviews,\n itemSizeValidation: supportsAjaxFileUploading,\n pause: supportsChunking,\n progressBar: supportsUploadProgress,\n resume: supportsResume,\n scaling: supportsImagePreviews && supportsUploadingBlobs,\n tiffPreviews: qq.safari(), // Not the best solution, but simple and probably accurate enough (for now)\n unlimitedScaledImageSize: !qq.ios(), // false simply indicates that there is some known limit\n uploading: supportsUploading,\n uploadCors: supportsUploadCors,\n uploadCustomHeaders: supportsAjaxFileUploading,\n uploadNonMultipart: supportsAjaxFileUploading,\n uploadViaPaste: supportsUploadViaPaste\n };\n\n}());\n","/*globals qq*/\n\n// Is the passed object a promise instance?\nqq.isGenericPromise = function(maybePromise) {\n \"use strict\";\n return !!(maybePromise && maybePromise.then && qq.isFunction(maybePromise.then));\n};\n\nqq.Promise = function() {\n \"use strict\";\n\n var successArgs, failureArgs,\n successCallbacks = [],\n failureCallbacks = [],\n doneCallbacks = [],\n state = 0;\n\n qq.extend(this, {\n then: function(onSuccess, onFailure) {\n if (state === 0) {\n if (onSuccess) {\n successCallbacks.push(onSuccess);\n }\n if (onFailure) {\n failureCallbacks.push(onFailure);\n }\n }\n else if (state === -1) {\n onFailure && onFailure.apply(null, failureArgs);\n }\n else if (onSuccess) {\n onSuccess.apply(null, successArgs);\n }\n\n return this;\n },\n\n done: function(callback) {\n if (state === 0) {\n doneCallbacks.push(callback);\n }\n else {\n callback.apply(null, failureArgs === undefined ? successArgs : failureArgs);\n }\n\n return this;\n },\n\n success: function() {\n state = 1;\n successArgs = arguments;\n\n if (successCallbacks.length) {\n qq.each(successCallbacks, function(idx, callback) {\n callback.apply(null, successArgs);\n });\n }\n\n if (doneCallbacks.length) {\n qq.each(doneCallbacks, function(idx, callback) {\n callback.apply(null, successArgs);\n });\n }\n\n return this;\n },\n\n failure: function() {\n state = -1;\n failureArgs = arguments;\n\n if (failureCallbacks.length) {\n qq.each(failureCallbacks, function(idx, callback) {\n callback.apply(null, failureArgs);\n });\n }\n\n if (doneCallbacks.length) {\n qq.each(doneCallbacks, function(idx, callback) {\n callback.apply(null, failureArgs);\n });\n }\n\n return this;\n }\n });\n};\n","/* globals qq */\n/**\n * Placeholder for a Blob that will be generated on-demand.\n *\n * @param referenceBlob Parent of the generated blob\n * @param onCreate Function to invoke when the blob must be created. Must be promissory.\n * @constructor\n */\nqq.BlobProxy = function(referenceBlob, onCreate) {\n \"use strict\";\n\n qq.extend(this, {\n referenceBlob: referenceBlob,\n\n create: function() {\n return onCreate(referenceBlob);\n }\n });\n};\n","/*globals qq*/\n\n/**\n * This module represents an upload or \"Select File(s)\" button. It's job is to embed an opaque ` `\n * element as a child of a provided \"container\" element. This \"container\" element (`options.element`) is used to provide\n * a custom style for the ` ` element. The ability to change the style of the container element is also\n * provided here by adding CSS classes to the container on hover/focus.\n *\n * TODO Eliminate the mouseover and mouseout event handlers since the :hover CSS pseudo-class should now be\n * available on all supported browsers.\n *\n * @param o Options to override the default values\n */\nqq.UploadButton = function(o) {\n \"use strict\";\n\n var self = this,\n\n disposeSupport = new qq.DisposeSupport(),\n\n options = {\n // Corresponds to the `accept` attribute on the associated ` `\n acceptFiles: null,\n\n // \"Container\" element\n element: null,\n\n focusClass: \"qq-upload-button-focus\",\n\n // A true value allows folders to be selected, if supported by the UA\n folders: false,\n\n // **This option will be removed** in the future as the :hover CSS pseudo-class is available on all supported browsers\n hoverClass: \"qq-upload-button-hover\",\n\n ios8BrowserCrashWorkaround: false,\n\n // If true adds `multiple` attribute to ` `\n multiple: false,\n\n // `name` attribute of ` `\n name: \"qqfile\",\n\n // Called when the browser invokes the onchange handler on the ` `\n onChange: function(input) {},\n\n title: null\n },\n input, buttonId;\n\n // Overrides any of the default option values with any option values passed in during construction.\n qq.extend(options, o);\n\n buttonId = qq.getUniqueId();\n\n // Embed an opaque ` ` element as a child of `options.element`.\n function createInput() {\n var input = document.createElement(\"input\");\n\n input.setAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME, buttonId);\n input.setAttribute(\"title\", options.title);\n\n self.setMultiple(options.multiple, input);\n\n if (options.folders && qq.supportedFeatures.folderSelection) {\n // selecting directories is only possible in Chrome now, via a vendor-specific prefixed attribute\n input.setAttribute(\"webkitdirectory\", \"\");\n }\n\n if (options.acceptFiles) {\n input.setAttribute(\"accept\", options.acceptFiles);\n }\n\n input.setAttribute(\"type\", \"file\");\n input.setAttribute(\"name\", options.name);\n\n qq(input).css({\n position: \"absolute\",\n // in Opera only 'browse' button\n // is clickable and it is located at\n // the right side of the input\n right: 0,\n top: 0,\n fontFamily: \"Arial\",\n // It's especially important to make this an arbitrarily large value\n // to ensure the rendered input button in IE takes up the entire\n // space of the container element. Otherwise, the left side of the\n // button will require a double-click to invoke the file chooser.\n // In other browsers, this might cause other issues, so a large font-size\n // is only used in IE. There is a bug in IE8 where the opacity style is ignored\n // in some cases when the font-size is large. So, this workaround is not applied\n // to IE8.\n fontSize: qq.ie() && !qq.ie8() ? \"3500px\" : \"118px\",\n margin: 0,\n padding: 0,\n cursor: \"pointer\",\n opacity: 0\n });\n\n // Setting the file input's height to 100% in IE7 causes\n // most of the visible button to be unclickable.\n !qq.ie7() && qq(input).css({height: \"100%\"});\n\n options.element.appendChild(input);\n\n disposeSupport.attach(input, \"change\", function() {\n options.onChange(input);\n });\n\n // **These event handlers will be removed** in the future as the :hover CSS pseudo-class is available on all supported browsers\n disposeSupport.attach(input, \"mouseover\", function() {\n qq(options.element).addClass(options.hoverClass);\n });\n disposeSupport.attach(input, \"mouseout\", function() {\n qq(options.element).removeClass(options.hoverClass);\n });\n\n disposeSupport.attach(input, \"focus\", function() {\n qq(options.element).addClass(options.focusClass);\n });\n disposeSupport.attach(input, \"blur\", function() {\n qq(options.element).removeClass(options.focusClass);\n });\n\n return input;\n }\n\n // Make button suitable container for input\n qq(options.element).css({\n position: \"relative\",\n overflow: \"hidden\",\n // Make sure browse button is in the right side in Internet Explorer\n direction: \"ltr\"\n });\n\n // Exposed API\n qq.extend(this, {\n getInput: function() {\n return input;\n },\n\n getButtonId: function() {\n return buttonId;\n },\n\n setMultiple: function(isMultiple, optInput) {\n var input = optInput || this.getInput();\n\n // Temporary workaround for bug in in iOS8 UIWebView that causes the browser to crash\n // before the file chooser appears if the file input doesn't contain a multiple attribute.\n // See #1283.\n if (options.ios8BrowserCrashWorkaround && qq.ios8() && (qq.iosChrome() || qq.iosSafariWebView())) {\n input.setAttribute(\"multiple\", \"\");\n }\n\n else {\n if (isMultiple) {\n input.setAttribute(\"multiple\", \"\");\n }\n else {\n input.removeAttribute(\"multiple\");\n }\n }\n },\n\n setAcceptFiles: function(acceptFiles) {\n if (acceptFiles !== options.acceptFiles) {\n input.setAttribute(\"accept\", acceptFiles);\n }\n },\n\n reset: function() {\n if (input.parentNode) {\n qq(input).remove();\n }\n\n qq(options.element).removeClass(options.focusClass);\n input = null;\n input = createInput();\n }\n });\n\n input = createInput();\n};\n\nqq.UploadButton.BUTTON_ID_ATTR_NAME = \"qq-button-id\";\n","/*globals qq */\nqq.UploadData = function(uploaderProxy) {\n \"use strict\";\n\n var data = [],\n byUuid = {},\n byStatus = {},\n byProxyGroupId = {},\n byBatchId = {};\n\n function getDataByIds(idOrIds) {\n if (qq.isArray(idOrIds)) {\n var entries = [];\n\n qq.each(idOrIds, function(idx, id) {\n entries.push(data[id]);\n });\n\n return entries;\n }\n\n return data[idOrIds];\n }\n\n function getDataByUuids(uuids) {\n if (qq.isArray(uuids)) {\n var entries = [];\n\n qq.each(uuids, function(idx, uuid) {\n entries.push(data[byUuid[uuid]]);\n });\n\n return entries;\n }\n\n return data[byUuid[uuids]];\n }\n\n function getDataByStatus(status) {\n var statusResults = [],\n statuses = [].concat(status);\n\n qq.each(statuses, function(index, statusEnum) {\n var statusResultIndexes = byStatus[statusEnum];\n\n if (statusResultIndexes !== undefined) {\n qq.each(statusResultIndexes, function(i, dataIndex) {\n statusResults.push(data[dataIndex]);\n });\n }\n });\n\n return statusResults;\n }\n\n qq.extend(this, {\n /**\n * Adds a new file to the data cache for tracking purposes.\n *\n * @param spec Data that describes this file. Possible properties are:\n *\n * - uuid: Initial UUID for this file.\n * - name: Initial name of this file.\n * - size: Size of this file, omit if this cannot be determined\n * - status: Initial `qq.status` for this file. Omit for `qq.status.SUBMITTING`.\n * - batchId: ID of the batch this file belongs to\n * - proxyGroupId: ID of the proxy group associated with this file\n *\n * @returns {number} Internal ID for this file.\n */\n addFile: function(spec) {\n var status = spec.status || qq.status.SUBMITTING,\n id = data.push({\n name: spec.name,\n originalName: spec.name,\n uuid: spec.uuid,\n size: spec.size == null ? -1 : spec.size,\n status: status\n }) - 1;\n\n if (spec.batchId) {\n data[id].batchId = spec.batchId;\n\n if (byBatchId[spec.batchId] === undefined) {\n byBatchId[spec.batchId] = [];\n }\n byBatchId[spec.batchId].push(id);\n }\n\n if (spec.proxyGroupId) {\n data[id].proxyGroupId = spec.proxyGroupId;\n\n if (byProxyGroupId[spec.proxyGroupId] === undefined) {\n byProxyGroupId[spec.proxyGroupId] = [];\n }\n byProxyGroupId[spec.proxyGroupId].push(id);\n }\n\n data[id].id = id;\n byUuid[spec.uuid] = id;\n\n if (byStatus[status] === undefined) {\n byStatus[status] = [];\n }\n byStatus[status].push(id);\n\n uploaderProxy.onStatusChange(id, null, status);\n\n return id;\n },\n\n retrieve: function(optionalFilter) {\n if (qq.isObject(optionalFilter) && data.length) {\n if (optionalFilter.id !== undefined) {\n return getDataByIds(optionalFilter.id);\n }\n\n else if (optionalFilter.uuid !== undefined) {\n return getDataByUuids(optionalFilter.uuid);\n }\n\n else if (optionalFilter.status) {\n return getDataByStatus(optionalFilter.status);\n }\n }\n else {\n return qq.extend([], data, true);\n }\n },\n\n reset: function() {\n data = [];\n byUuid = {};\n byStatus = {};\n byBatchId = {};\n },\n\n setStatus: function(id, newStatus) {\n var oldStatus = data[id].status,\n byStatusOldStatusIndex = qq.indexOf(byStatus[oldStatus], id);\n\n byStatus[oldStatus].splice(byStatusOldStatusIndex, 1);\n\n data[id].status = newStatus;\n\n if (byStatus[newStatus] === undefined) {\n byStatus[newStatus] = [];\n }\n byStatus[newStatus].push(id);\n\n uploaderProxy.onStatusChange(id, oldStatus, newStatus);\n },\n\n uuidChanged: function(id, newUuid) {\n var oldUuid = data[id].uuid;\n\n data[id].uuid = newUuid;\n byUuid[newUuid] = id;\n delete byUuid[oldUuid];\n },\n\n updateName: function(id, newName) {\n data[id].name = newName;\n },\n\n updateSize: function(id, newSize) {\n data[id].size = newSize;\n },\n\n // Only applicable if this file has a parent that we may want to reference later.\n setParentId: function(targetId, parentId) {\n data[targetId].parentId = parentId;\n },\n\n getIdsInProxyGroup: function(id) {\n var proxyGroupId = data[id].proxyGroupId;\n\n if (proxyGroupId) {\n return byProxyGroupId[proxyGroupId];\n }\n return [];\n },\n\n getIdsInBatch: function(id) {\n var batchId = data[id].batchId;\n\n return byBatchId[batchId];\n }\n });\n};\n\nqq.status = {\n SUBMITTING: \"submitting\",\n SUBMITTED: \"submitted\",\n REJECTED: \"rejected\",\n QUEUED: \"queued\",\n CANCELED: \"canceled\",\n PAUSED: \"paused\",\n UPLOADING: \"uploading\",\n UPLOAD_RETRYING: \"retrying upload\",\n UPLOAD_SUCCESSFUL: \"upload successful\",\n UPLOAD_FAILED: \"upload failed\",\n DELETE_FAILED: \"delete failed\",\n DELETING: \"deleting\",\n DELETED: \"deleted\"\n};\n","/*globals qq*/\n/**\n * Defines the public API for FineUploaderBasic mode.\n */\n(function() {\n \"use strict\";\n\n qq.basePublicApi = {\n // DEPRECATED - TODO REMOVE IN NEXT MAJOR RELEASE (replaced by addFiles)\n addBlobs: function(blobDataOrArray, params, endpoint) {\n this.addFiles(blobDataOrArray, params, endpoint);\n },\n\n addInitialFiles: function(cannedFileList) {\n var self = this;\n\n qq.each(cannedFileList, function(index, cannedFile) {\n self._addCannedFile(cannedFile);\n });\n },\n\n addFiles: function(data, params, endpoint) {\n this._maybeHandleIos8SafariWorkaround();\n\n var batchId = this._storedIds.length === 0 ? qq.getUniqueId() : this._currentBatchId,\n\n processBlob = qq.bind(function(blob) {\n this._handleNewFile({\n blob: blob,\n name: this._options.blobs.defaultName\n }, batchId, verifiedFiles);\n }, this),\n\n processBlobData = qq.bind(function(blobData) {\n this._handleNewFile(blobData, batchId, verifiedFiles);\n }, this),\n\n processCanvas = qq.bind(function(canvas) {\n var blob = qq.canvasToBlob(canvas);\n\n this._handleNewFile({\n blob: blob,\n name: this._options.blobs.defaultName + \".png\"\n }, batchId, verifiedFiles);\n }, this),\n\n processCanvasData = qq.bind(function(canvasData) {\n var normalizedQuality = canvasData.quality && canvasData.quality / 100,\n blob = qq.canvasToBlob(canvasData.canvas, canvasData.type, normalizedQuality);\n\n this._handleNewFile({\n blob: blob,\n name: canvasData.name\n }, batchId, verifiedFiles);\n }, this),\n\n processFileOrInput = qq.bind(function(fileOrInput) {\n if (qq.isInput(fileOrInput) && qq.supportedFeatures.ajaxUploading) {\n var files = Array.prototype.slice.call(fileOrInput.files),\n self = this;\n\n qq.each(files, function(idx, file) {\n self._handleNewFile(file, batchId, verifiedFiles);\n });\n }\n else {\n this._handleNewFile(fileOrInput, batchId, verifiedFiles);\n }\n }, this),\n\n normalizeData = function() {\n if (qq.isFileList(data)) {\n data = Array.prototype.slice.call(data);\n }\n data = [].concat(data);\n },\n\n self = this,\n verifiedFiles = [];\n\n this._currentBatchId = batchId;\n\n if (data) {\n normalizeData();\n\n qq.each(data, function(idx, fileContainer) {\n if (qq.isFileOrInput(fileContainer)) {\n processFileOrInput(fileContainer);\n }\n else if (qq.isBlob(fileContainer)) {\n processBlob(fileContainer);\n }\n else if (qq.isObject(fileContainer)) {\n if (fileContainer.blob && fileContainer.name) {\n processBlobData(fileContainer);\n }\n else if (fileContainer.canvas && fileContainer.name) {\n processCanvasData(fileContainer);\n }\n }\n else if (fileContainer.tagName && fileContainer.tagName.toLowerCase() === \"canvas\") {\n processCanvas(fileContainer);\n }\n else {\n self.log(fileContainer + \" is not a valid file container! Ignoring!\", \"warn\");\n }\n });\n\n this.log(\"Received \" + verifiedFiles.length + \" files.\");\n this._prepareItemsForUpload(verifiedFiles, params, endpoint);\n }\n },\n\n cancel: function(id) {\n this._handler.cancel(id);\n },\n\n cancelAll: function() {\n var storedIdsCopy = [],\n self = this;\n\n qq.extend(storedIdsCopy, this._storedIds);\n qq.each(storedIdsCopy, function(idx, storedFileId) {\n self.cancel(storedFileId);\n });\n\n this._handler.cancelAll();\n },\n\n clearStoredFiles: function() {\n this._storedIds = [];\n },\n\n continueUpload: function(id) {\n var uploadData = this._uploadData.retrieve({id: id});\n\n if (!qq.supportedFeatures.pause || !this._options.chunking.enabled) {\n return false;\n }\n\n if (uploadData.status === qq.status.PAUSED) {\n this.log(qq.format(\"Paused file ID {} ({}) will be continued. Not paused.\", id, this.getName(id)));\n this._uploadFile(id);\n return true;\n }\n else {\n this.log(qq.format(\"Ignoring continue for file ID {} ({}). Not paused.\", id, this.getName(id)), \"error\");\n }\n\n return false;\n },\n\n deleteFile: function(id) {\n return this._onSubmitDelete(id);\n },\n\n // TODO document?\n doesExist: function(fileOrBlobId) {\n return this._handler.isValid(fileOrBlobId);\n },\n\n // Generate a variable size thumbnail on an img or canvas,\n // returning a promise that is fulfilled when the attempt completes.\n // Thumbnail can either be based off of a URL for an image returned\n // by the server in the upload response, or the associated `Blob`.\n drawThumbnail: function(fileId, imgOrCanvas, maxSize, fromServer, customResizeFunction) {\n var promiseToReturn = new qq.Promise(),\n fileOrUrl, options;\n\n if (this._imageGenerator) {\n fileOrUrl = this._thumbnailUrls[fileId];\n options = {\n customResizeFunction: customResizeFunction,\n maxSize: maxSize > 0 ? maxSize : null,\n scale: maxSize > 0\n };\n\n // If client-side preview generation is possible\n // and we are not specifically looking for the image URl returned by the server...\n if (!fromServer && qq.supportedFeatures.imagePreviews) {\n fileOrUrl = this.getFile(fileId);\n }\n\n /* jshint eqeqeq:false,eqnull:true */\n if (fileOrUrl == null) {\n promiseToReturn.failure({container: imgOrCanvas, error: \"File or URL not found.\"});\n }\n else {\n this._imageGenerator.generate(fileOrUrl, imgOrCanvas, options).then(\n function success(modifiedContainer) {\n promiseToReturn.success(modifiedContainer);\n },\n\n function failure(container, reason) {\n promiseToReturn.failure({container: container, error: reason || \"Problem generating thumbnail\"});\n }\n );\n }\n }\n else {\n promiseToReturn.failure({container: imgOrCanvas, error: \"Missing image generator module\"});\n }\n\n return promiseToReturn;\n },\n\n getButton: function(fileId) {\n return this._getButton(this._buttonIdsForFileIds[fileId]);\n },\n\n getEndpoint: function(fileId) {\n return this._endpointStore.get(fileId);\n },\n\n getFile: function(fileOrBlobId) {\n return this._handler.getFile(fileOrBlobId) || null;\n },\n\n getInProgress: function() {\n return this._uploadData.retrieve({\n status: [\n qq.status.UPLOADING,\n qq.status.UPLOAD_RETRYING,\n qq.status.QUEUED\n ]\n }).length;\n },\n\n getName: function(id) {\n return this._uploadData.retrieve({id: id}).name;\n },\n\n // Parent ID for a specific file, or null if this is the parent, or if it has no parent.\n getParentId: function(id) {\n var uploadDataEntry = this.getUploads({id: id}),\n parentId = null;\n\n if (uploadDataEntry) {\n if (uploadDataEntry.parentId !== undefined) {\n parentId = uploadDataEntry.parentId;\n }\n }\n\n return parentId;\n },\n\n getResumableFilesData: function() {\n return this._handler.getResumableFilesData();\n },\n\n getSize: function(id) {\n return this._uploadData.retrieve({id: id}).size;\n },\n\n getNetUploads: function() {\n return this._netUploaded;\n },\n\n getRemainingAllowedItems: function() {\n var allowedItems = this._currentItemLimit;\n\n if (allowedItems > 0) {\n return allowedItems - this._netUploadedOrQueued;\n }\n\n return null;\n },\n\n getUploads: function(optionalFilter) {\n return this._uploadData.retrieve(optionalFilter);\n },\n\n getUuid: function(id) {\n return this._uploadData.retrieve({id: id}).uuid;\n },\n\n log: function(str, level) {\n if (this._options.debug && (!level || level === \"info\")) {\n qq.log(\"[Fine Uploader \" + qq.version + \"] \" + str);\n }\n else if (level && level !== \"info\") {\n qq.log(\"[Fine Uploader \" + qq.version + \"] \" + str, level);\n\n }\n },\n\n pauseUpload: function(id) {\n var uploadData = this._uploadData.retrieve({id: id});\n\n if (!qq.supportedFeatures.pause || !this._options.chunking.enabled) {\n return false;\n }\n\n // Pause only really makes sense if the file is uploading or retrying\n if (qq.indexOf([qq.status.UPLOADING, qq.status.UPLOAD_RETRYING], uploadData.status) >= 0) {\n if (this._handler.pause(id)) {\n this._uploadData.setStatus(id, qq.status.PAUSED);\n return true;\n }\n else {\n this.log(qq.format(\"Unable to pause file ID {} ({}).\", id, this.getName(id)), \"error\");\n }\n }\n else {\n this.log(qq.format(\"Ignoring pause for file ID {} ({}). Not in progress.\", id, this.getName(id)), \"error\");\n }\n\n return false;\n },\n\n reset: function() {\n this.log(\"Resetting uploader...\");\n\n this._handler.reset();\n this._storedIds = [];\n this._autoRetries = [];\n this._retryTimeouts = [];\n this._preventRetries = [];\n this._thumbnailUrls = [];\n\n qq.each(this._buttons, function(idx, button) {\n button.reset();\n });\n\n this._paramsStore.reset();\n this._endpointStore.reset();\n this._netUploadedOrQueued = 0;\n this._netUploaded = 0;\n this._uploadData.reset();\n this._buttonIdsForFileIds = [];\n\n this._pasteHandler && this._pasteHandler.reset();\n this._options.session.refreshOnReset && this._refreshSessionData();\n\n this._succeededSinceLastAllComplete = [];\n this._failedSinceLastAllComplete = [];\n\n this._totalProgress && this._totalProgress.reset();\n },\n\n retry: function(id) {\n return this._manualRetry(id);\n },\n\n scaleImage: function(id, specs) {\n var self = this;\n\n return qq.Scaler.prototype.scaleImage(id, specs, {\n log: qq.bind(self.log, self),\n getFile: qq.bind(self.getFile, self),\n uploadData: self._uploadData\n });\n },\n\n setCustomHeaders: function(headers, id) {\n this._customHeadersStore.set(headers, id);\n },\n\n setDeleteFileCustomHeaders: function(headers, id) {\n this._deleteFileCustomHeadersStore.set(headers, id);\n },\n\n setDeleteFileEndpoint: function(endpoint, id) {\n this._deleteFileEndpointStore.set(endpoint, id);\n },\n\n setDeleteFileParams: function(params, id) {\n this._deleteFileParamsStore.set(params, id);\n },\n\n // Re-sets the default endpoint, an endpoint for a specific file, or an endpoint for a specific button\n setEndpoint: function(endpoint, id) {\n this._endpointStore.set(endpoint, id);\n },\n\n setForm: function(elementOrId) {\n this._updateFormSupportAndParams(elementOrId);\n },\n\n setItemLimit: function(newItemLimit) {\n this._currentItemLimit = newItemLimit;\n },\n\n setName: function(id, newName) {\n this._uploadData.updateName(id, newName);\n },\n\n setParams: function(params, id) {\n this._paramsStore.set(params, id);\n },\n\n setUuid: function(id, newUuid) {\n return this._uploadData.uuidChanged(id, newUuid);\n },\n\n uploadStoredFiles: function() {\n if (this._storedIds.length === 0) {\n this._itemError(\"noFilesError\");\n }\n else {\n this._uploadStoredFiles();\n }\n }\n };\n\n /**\n * Defines the private (internal) API for FineUploaderBasic mode.\n */\n qq.basePrivateApi = {\n // Updates internal state with a file record (not backed by a live file). Returns the assigned ID.\n _addCannedFile: function(sessionData) {\n var id = this._uploadData.addFile({\n uuid: sessionData.uuid,\n name: sessionData.name,\n size: sessionData.size,\n status: qq.status.UPLOAD_SUCCESSFUL\n });\n\n sessionData.deleteFileEndpoint && this.setDeleteFileEndpoint(sessionData.deleteFileEndpoint, id);\n sessionData.deleteFileParams && this.setDeleteFileParams(sessionData.deleteFileParams, id);\n\n if (sessionData.thumbnailUrl) {\n this._thumbnailUrls[id] = sessionData.thumbnailUrl;\n }\n\n this._netUploaded++;\n this._netUploadedOrQueued++;\n\n return id;\n },\n\n _annotateWithButtonId: function(file, associatedInput) {\n if (qq.isFile(file)) {\n file.qqButtonId = this._getButtonId(associatedInput);\n }\n },\n\n _batchError: function(message) {\n this._options.callbacks.onError(null, null, message, undefined);\n },\n\n _createDeleteHandler: function() {\n var self = this;\n\n return new qq.DeleteFileAjaxRequester({\n method: this._options.deleteFile.method.toUpperCase(),\n maxConnections: this._options.maxConnections,\n uuidParamName: this._options.request.uuidName,\n customHeaders: this._deleteFileCustomHeadersStore,\n paramsStore: this._deleteFileParamsStore,\n endpointStore: this._deleteFileEndpointStore,\n cors: this._options.cors,\n log: qq.bind(self.log, self),\n onDelete: function(id) {\n self._onDelete(id);\n self._options.callbacks.onDelete(id);\n },\n onDeleteComplete: function(id, xhrOrXdr, isError) {\n self._onDeleteComplete(id, xhrOrXdr, isError);\n self._options.callbacks.onDeleteComplete(id, xhrOrXdr, isError);\n }\n\n });\n },\n\n _createPasteHandler: function() {\n var self = this;\n\n return new qq.PasteSupport({\n targetElement: this._options.paste.targetElement,\n callbacks: {\n log: qq.bind(self.log, self),\n pasteReceived: function(blob) {\n self._handleCheckedCallback({\n name: \"onPasteReceived\",\n callback: qq.bind(self._options.callbacks.onPasteReceived, self, blob),\n onSuccess: qq.bind(self._handlePasteSuccess, self, blob),\n identifier: \"pasted image\"\n });\n }\n }\n });\n },\n\n _createStore: function(initialValue, _readOnlyValues_) {\n var store = {},\n catchall = initialValue,\n perIdReadOnlyValues = {},\n readOnlyValues = _readOnlyValues_,\n copy = function(orig) {\n if (qq.isObject(orig)) {\n return qq.extend({}, orig);\n }\n return orig;\n },\n getReadOnlyValues = function() {\n if (qq.isFunction(readOnlyValues)) {\n return readOnlyValues();\n }\n return readOnlyValues;\n },\n includeReadOnlyValues = function(id, existing) {\n if (readOnlyValues && qq.isObject(existing)) {\n qq.extend(existing, getReadOnlyValues());\n }\n\n if (perIdReadOnlyValues[id]) {\n qq.extend(existing, perIdReadOnlyValues[id]);\n }\n };\n\n return {\n set: function(val, id) {\n /*jshint eqeqeq: true, eqnull: true*/\n if (id == null) {\n store = {};\n catchall = copy(val);\n }\n else {\n store[id] = copy(val);\n }\n },\n\n get: function(id) {\n var values;\n\n /*jshint eqeqeq: true, eqnull: true*/\n if (id != null && store[id]) {\n values = store[id];\n }\n else {\n values = copy(catchall);\n }\n\n includeReadOnlyValues(id, values);\n\n return copy(values);\n },\n\n addReadOnly: function(id, values) {\n // Only applicable to Object stores\n if (qq.isObject(store)) {\n // If null ID, apply readonly values to all files\n if (id === null) {\n if (qq.isFunction(values)) {\n readOnlyValues = values;\n }\n else {\n readOnlyValues = readOnlyValues || {};\n qq.extend(readOnlyValues, values);\n }\n }\n else {\n perIdReadOnlyValues[id] = perIdReadOnlyValues[id] || {};\n qq.extend(perIdReadOnlyValues[id], values);\n }\n }\n },\n\n remove: function(fileId) {\n return delete store[fileId];\n },\n\n reset: function() {\n store = {};\n perIdReadOnlyValues = {};\n catchall = initialValue;\n }\n };\n },\n\n _createUploadDataTracker: function() {\n var self = this;\n\n return new qq.UploadData({\n getName: function(id) {\n return self.getName(id);\n },\n getUuid: function(id) {\n return self.getUuid(id);\n },\n getSize: function(id) {\n return self.getSize(id);\n },\n onStatusChange: function(id, oldStatus, newStatus) {\n self._onUploadStatusChange(id, oldStatus, newStatus);\n self._options.callbacks.onStatusChange(id, oldStatus, newStatus);\n self._maybeAllComplete(id, newStatus);\n\n if (self._totalProgress) {\n setTimeout(function() {\n self._totalProgress.onStatusChange(id, oldStatus, newStatus);\n }, 0);\n }\n }\n });\n },\n\n /**\n * Generate a tracked upload button.\n *\n * @param spec Object containing a required `element` property\n * along with optional `multiple`, `accept`, and `folders`.\n * @returns {qq.UploadButton}\n * @private\n */\n _createUploadButton: function(spec) {\n var self = this,\n acceptFiles = spec.accept || this._options.validation.acceptFiles,\n allowedExtensions = spec.allowedExtensions || this._options.validation.allowedExtensions,\n button;\n\n function allowMultiple() {\n if (qq.supportedFeatures.ajaxUploading) {\n // Workaround for bug in iOS7+ (see #1039)\n if (self._options.workarounds.iosEmptyVideos &&\n qq.ios() &&\n !qq.ios6() &&\n self._isAllowedExtension(allowedExtensions, \".mov\")) {\n\n return false;\n }\n\n if (spec.multiple === undefined) {\n return self._options.multiple;\n }\n\n return spec.multiple;\n }\n\n return false;\n }\n\n button = new qq.UploadButton({\n acceptFiles: acceptFiles,\n element: spec.element,\n focusClass: this._options.classes.buttonFocus,\n folders: spec.folders,\n hoverClass: this._options.classes.buttonHover,\n ios8BrowserCrashWorkaround: this._options.workarounds.ios8BrowserCrash,\n multiple: allowMultiple(),\n name: this._options.request.inputName,\n onChange: function(input) {\n self._onInputChange(input);\n },\n title: spec.title == null ? this._options.text.fileInputTitle : spec.title\n });\n\n this._disposeSupport.addDisposer(function() {\n button.dispose();\n });\n\n self._buttons.push(button);\n\n return button;\n },\n\n _createUploadHandler: function(additionalOptions, namespace) {\n var self = this,\n lastOnProgress = {},\n options = {\n debug: this._options.debug,\n maxConnections: this._options.maxConnections,\n cors: this._options.cors,\n paramsStore: this._paramsStore,\n endpointStore: this._endpointStore,\n chunking: this._options.chunking,\n resume: this._options.resume,\n blobs: this._options.blobs,\n log: qq.bind(self.log, self),\n preventRetryParam: this._options.retry.preventRetryResponseProperty,\n onProgress: function(id, name, loaded, total) {\n if (loaded < 0 || total < 0) {\n return;\n }\n\n if (lastOnProgress[id]) {\n if (lastOnProgress[id].loaded !== loaded || lastOnProgress[id].total !== total) {\n self._onProgress(id, name, loaded, total);\n self._options.callbacks.onProgress(id, name, loaded, total);\n }\n }\n else {\n self._onProgress(id, name, loaded, total);\n self._options.callbacks.onProgress(id, name, loaded, total);\n }\n\n lastOnProgress[id] = {loaded: loaded, total: total};\n\n },\n onComplete: function(id, name, result, xhr) {\n delete lastOnProgress[id];\n\n var status = self.getUploads({id: id}).status,\n retVal;\n\n // This is to deal with some observed cases where the XHR readyStateChange handler is\n // invoked by the browser multiple times for the same XHR instance with the same state\n // readyState value. Higher level: don't invoke complete-related code if we've already\n // done this.\n if (status === qq.status.UPLOAD_SUCCESSFUL || status === qq.status.UPLOAD_FAILED) {\n return;\n }\n\n retVal = self._onComplete(id, name, result, xhr);\n\n // If the internal `_onComplete` handler returns a promise, don't invoke the `onComplete` callback\n // until the promise has been fulfilled.\n if (retVal instanceof qq.Promise) {\n retVal.done(function() {\n self._options.callbacks.onComplete(id, name, result, xhr);\n });\n }\n else {\n self._options.callbacks.onComplete(id, name, result, xhr);\n }\n },\n onCancel: function(id, name, cancelFinalizationEffort) {\n var promise = new qq.Promise();\n\n self._handleCheckedCallback({\n name: \"onCancel\",\n callback: qq.bind(self._options.callbacks.onCancel, self, id, name),\n onFailure: promise.failure,\n onSuccess: function() {\n cancelFinalizationEffort.then(function() {\n self._onCancel(id, name);\n });\n\n promise.success();\n },\n identifier: id\n });\n\n return promise;\n },\n onUploadPrep: qq.bind(this._onUploadPrep, this),\n onUpload: function(id, name) {\n self._onUpload(id, name);\n self._options.callbacks.onUpload(id, name);\n },\n onUploadChunk: function(id, name, chunkData) {\n self._onUploadChunk(id, chunkData);\n self._options.callbacks.onUploadChunk(id, name, chunkData);\n },\n onUploadChunkSuccess: function(id, chunkData, result, xhr) {\n self._options.callbacks.onUploadChunkSuccess.apply(self, arguments);\n },\n onResume: function(id, name, chunkData) {\n return self._options.callbacks.onResume(id, name, chunkData);\n },\n onAutoRetry: function(id, name, responseJSON, xhr) {\n return self._onAutoRetry.apply(self, arguments);\n },\n onUuidChanged: function(id, newUuid) {\n self.log(\"Server requested UUID change from '\" + self.getUuid(id) + \"' to '\" + newUuid + \"'\");\n self.setUuid(id, newUuid);\n },\n getName: qq.bind(self.getName, self),\n getUuid: qq.bind(self.getUuid, self),\n getSize: qq.bind(self.getSize, self),\n setSize: qq.bind(self._setSize, self),\n getDataByUuid: function(uuid) {\n return self.getUploads({uuid: uuid});\n },\n isQueued: function(id) {\n var status = self.getUploads({id: id}).status;\n return status === qq.status.QUEUED ||\n status === qq.status.SUBMITTED ||\n status === qq.status.UPLOAD_RETRYING ||\n status === qq.status.PAUSED;\n },\n getIdsInProxyGroup: self._uploadData.getIdsInProxyGroup,\n getIdsInBatch: self._uploadData.getIdsInBatch\n };\n\n qq.each(this._options.request, function(prop, val) {\n options[prop] = val;\n });\n\n options.customHeaders = this._customHeadersStore;\n\n if (additionalOptions) {\n qq.each(additionalOptions, function(key, val) {\n options[key] = val;\n });\n }\n\n return new qq.UploadHandlerController(options, namespace);\n },\n\n _fileOrBlobRejected: function(id) {\n this._netUploadedOrQueued--;\n this._uploadData.setStatus(id, qq.status.REJECTED);\n },\n\n _formatSize: function(bytes) {\n if (bytes === 0) {\n return bytes + this._options.text.sizeSymbols[0];\n }\n var i = -1;\n do {\n bytes = bytes / 1000;\n i++;\n } while (bytes > 999);\n\n return Math.max(bytes, 0.1).toFixed(1) + this._options.text.sizeSymbols[i];\n },\n\n // Creates an internal object that tracks various properties of each extra button,\n // and then actually creates the extra button.\n _generateExtraButtonSpecs: function() {\n var self = this;\n\n this._extraButtonSpecs = {};\n\n qq.each(this._options.extraButtons, function(idx, extraButtonOptionEntry) {\n var multiple = extraButtonOptionEntry.multiple,\n validation = qq.extend({}, self._options.validation, true),\n extraButtonSpec = qq.extend({}, extraButtonOptionEntry);\n\n if (multiple === undefined) {\n multiple = self._options.multiple;\n }\n\n if (extraButtonSpec.validation) {\n qq.extend(validation, extraButtonOptionEntry.validation, true);\n }\n\n qq.extend(extraButtonSpec, {\n multiple: multiple,\n validation: validation\n }, true);\n\n self._initExtraButton(extraButtonSpec);\n });\n },\n\n _getButton: function(buttonId) {\n var extraButtonsSpec = this._extraButtonSpecs[buttonId];\n\n if (extraButtonsSpec) {\n return extraButtonsSpec.element;\n }\n else if (buttonId === this._defaultButtonId) {\n return this._options.button;\n }\n },\n\n /**\n * Gets the internally used tracking ID for a button.\n *\n * @param buttonOrFileInputOrFile `File`, ` `, or a button container element\n * @returns {*} The button's ID, or undefined if no ID is recoverable\n * @private\n */\n _getButtonId: function(buttonOrFileInputOrFile) {\n var inputs, fileInput,\n fileBlobOrInput = buttonOrFileInputOrFile;\n\n // We want the reference file/blob here if this is a proxy (a file that will be generated on-demand later)\n if (fileBlobOrInput instanceof qq.BlobProxy) {\n fileBlobOrInput = fileBlobOrInput.referenceBlob;\n }\n\n // If the item is a `Blob` it will never be associated with a button or drop zone.\n if (fileBlobOrInput && !qq.isBlob(fileBlobOrInput)) {\n if (qq.isFile(fileBlobOrInput)) {\n return fileBlobOrInput.qqButtonId;\n }\n else if (fileBlobOrInput.tagName.toLowerCase() === \"input\" &&\n fileBlobOrInput.type.toLowerCase() === \"file\") {\n\n return fileBlobOrInput.getAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME);\n }\n\n inputs = fileBlobOrInput.getElementsByTagName(\"input\");\n\n qq.each(inputs, function(idx, input) {\n if (input.getAttribute(\"type\") === \"file\") {\n fileInput = input;\n return false;\n }\n });\n\n if (fileInput) {\n return fileInput.getAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME);\n }\n }\n },\n\n _getNotFinished: function() {\n return this._uploadData.retrieve({\n status: [\n qq.status.UPLOADING,\n qq.status.UPLOAD_RETRYING,\n qq.status.QUEUED,\n qq.status.SUBMITTING,\n qq.status.SUBMITTED,\n qq.status.PAUSED\n ]\n }).length;\n },\n\n // Get the validation options for this button. Could be the default validation option\n // or a specific one assigned to this particular button.\n _getValidationBase: function(buttonId) {\n var extraButtonSpec = this._extraButtonSpecs[buttonId];\n\n return extraButtonSpec ? extraButtonSpec.validation : this._options.validation;\n },\n\n _getValidationDescriptor: function(fileWrapper) {\n if (fileWrapper.file instanceof qq.BlobProxy) {\n return {\n name: qq.getFilename(fileWrapper.file.referenceBlob),\n size: fileWrapper.file.referenceBlob.size\n };\n }\n\n return {\n name: this.getUploads({id: fileWrapper.id}).name,\n size: this.getUploads({id: fileWrapper.id}).size\n };\n },\n\n _getValidationDescriptors: function(fileWrappers) {\n var self = this,\n fileDescriptors = [];\n\n qq.each(fileWrappers, function(idx, fileWrapper) {\n fileDescriptors.push(self._getValidationDescriptor(fileWrapper));\n });\n\n return fileDescriptors;\n },\n\n // Allows camera access on either the default or an extra button for iOS devices.\n _handleCameraAccess: function() {\n if (this._options.camera.ios && qq.ios()) {\n var acceptIosCamera = \"image/*;capture=camera\",\n button = this._options.camera.button,\n buttonId = button ? this._getButtonId(button) : this._defaultButtonId,\n optionRoot = this._options;\n\n // If we are not targeting the default button, it is an \"extra\" button\n if (buttonId && buttonId !== this._defaultButtonId) {\n optionRoot = this._extraButtonSpecs[buttonId];\n }\n\n // Camera access won't work in iOS if the `multiple` attribute is present on the file input\n optionRoot.multiple = false;\n\n // update the options\n if (optionRoot.validation.acceptFiles === null) {\n optionRoot.validation.acceptFiles = acceptIosCamera;\n }\n else {\n optionRoot.validation.acceptFiles += \",\" + acceptIosCamera;\n }\n\n // update the already-created button\n qq.each(this._buttons, function(idx, button) {\n if (button.getButtonId() === buttonId) {\n button.setMultiple(optionRoot.multiple);\n button.setAcceptFiles(optionRoot.acceptFiles);\n\n return false;\n }\n });\n }\n },\n\n _handleCheckedCallback: function(details) {\n var self = this,\n callbackRetVal = details.callback();\n\n if (qq.isGenericPromise(callbackRetVal)) {\n this.log(details.name + \" - waiting for \" + details.name + \" promise to be fulfilled for \" + details.identifier);\n return callbackRetVal.then(\n function(successParam) {\n self.log(details.name + \" promise success for \" + details.identifier);\n details.onSuccess(successParam);\n },\n function() {\n if (details.onFailure) {\n self.log(details.name + \" promise failure for \" + details.identifier);\n details.onFailure();\n }\n else {\n self.log(details.name + \" promise failure for \" + details.identifier);\n }\n });\n }\n\n if (callbackRetVal !== false) {\n details.onSuccess(callbackRetVal);\n }\n else {\n if (details.onFailure) {\n this.log(details.name + \" - return value was 'false' for \" + details.identifier + \". Invoking failure callback.\");\n details.onFailure();\n }\n else {\n this.log(details.name + \" - return value was 'false' for \" + details.identifier + \". Will not proceed.\");\n }\n }\n\n return callbackRetVal;\n },\n\n // Updates internal state when a new file has been received, and adds it along with its ID to a passed array.\n _handleNewFile: function(file, batchId, newFileWrapperList) {\n var self = this,\n uuid = qq.getUniqueId(),\n size = -1,\n name = qq.getFilename(file),\n actualFile = file.blob || file,\n handler = this._customNewFileHandler ?\n this._customNewFileHandler :\n qq.bind(self._handleNewFileGeneric, self);\n\n if (!qq.isInput(actualFile) && actualFile.size >= 0) {\n size = actualFile.size;\n }\n\n handler(actualFile, name, uuid, size, newFileWrapperList, batchId, this._options.request.uuidName, {\n uploadData: self._uploadData,\n paramsStore: self._paramsStore,\n addFileToHandler: function(id, file) {\n self._handler.add(id, file);\n self._netUploadedOrQueued++;\n self._trackButton(id);\n }\n });\n },\n\n _handleNewFileGeneric: function(file, name, uuid, size, fileList, batchId) {\n var id = this._uploadData.addFile({uuid: uuid, name: name, size: size, batchId: batchId});\n\n this._handler.add(id, file);\n this._trackButton(id);\n\n this._netUploadedOrQueued++;\n\n fileList.push({id: id, file: file});\n },\n\n _handlePasteSuccess: function(blob, extSuppliedName) {\n var extension = blob.type.split(\"/\")[1],\n name = extSuppliedName;\n\n /*jshint eqeqeq: true, eqnull: true*/\n if (name == null) {\n name = this._options.paste.defaultName;\n }\n\n name += \".\" + extension;\n\n this.addFiles({\n name: name,\n blob: blob\n });\n },\n\n // Creates an extra button element\n _initExtraButton: function(spec) {\n var button = this._createUploadButton({\n accept: spec.validation.acceptFiles,\n allowedExtensions: spec.validation.allowedExtensions,\n element: spec.element,\n folders: spec.folders,\n multiple: spec.multiple,\n title: spec.fileInputTitle\n });\n\n this._extraButtonSpecs[button.getButtonId()] = spec;\n },\n\n _initFormSupportAndParams: function() {\n this._formSupport = qq.FormSupport && new qq.FormSupport(\n this._options.form, qq.bind(this.uploadStoredFiles, this), qq.bind(this.log, this)\n );\n\n if (this._formSupport && this._formSupport.attachedToForm) {\n this._paramsStore = this._createStore(\n this._options.request.params, this._formSupport.getFormInputsAsObject\n );\n\n this._options.autoUpload = this._formSupport.newAutoUpload;\n if (this._formSupport.newEndpoint) {\n this._options.request.endpoint = this._formSupport.newEndpoint;\n }\n }\n else {\n this._paramsStore = this._createStore(this._options.request.params);\n }\n },\n\n _isDeletePossible: function() {\n if (!qq.DeleteFileAjaxRequester || !this._options.deleteFile.enabled) {\n return false;\n }\n\n if (this._options.cors.expected) {\n if (qq.supportedFeatures.deleteFileCorsXhr) {\n return true;\n }\n\n if (qq.supportedFeatures.deleteFileCorsXdr && this._options.cors.allowXdr) {\n return true;\n }\n\n return false;\n }\n\n return true;\n },\n\n _isAllowedExtension: function(allowed, fileName) {\n var valid = false;\n\n if (!allowed.length) {\n return true;\n }\n\n qq.each(allowed, function(idx, allowedExt) {\n /**\n * If an argument is not a string, ignore it. Added when a possible issue with MooTools hijacking the\n * `allowedExtensions` array was discovered. See case #735 in the issue tracker for more details.\n */\n if (qq.isString(allowedExt)) {\n /*jshint eqeqeq: true, eqnull: true*/\n var extRegex = new RegExp(\"\\\\.\" + allowedExt + \"$\", \"i\");\n\n if (fileName.match(extRegex) != null) {\n valid = true;\n return false;\n }\n }\n });\n\n return valid;\n },\n\n /**\n * Constructs and returns a message that describes an item/file error. Also calls `onError` callback.\n *\n * @param code REQUIRED - a code that corresponds to a stock message describing this type of error\n * @param maybeNameOrNames names of the items that have failed, if applicable\n * @param item `File`, `Blob`, or ` `\n * @private\n */\n _itemError: function(code, maybeNameOrNames, item) {\n var message = this._options.messages[code],\n allowedExtensions = [],\n names = [].concat(maybeNameOrNames),\n name = names[0],\n buttonId = this._getButtonId(item),\n validationBase = this._getValidationBase(buttonId),\n extensionsForMessage, placeholderMatch;\n\n function r(name, replacement) { message = message.replace(name, replacement); }\n\n qq.each(validationBase.allowedExtensions, function(idx, allowedExtension) {\n /**\n * If an argument is not a string, ignore it. Added when a possible issue with MooTools hijacking the\n * `allowedExtensions` array was discovered. See case #735 in the issue tracker for more details.\n */\n if (qq.isString(allowedExtension)) {\n allowedExtensions.push(allowedExtension);\n }\n });\n\n extensionsForMessage = allowedExtensions.join(\", \").toLowerCase();\n\n r(\"{file}\", this._options.formatFileName(name));\n r(\"{extensions}\", extensionsForMessage);\n r(\"{sizeLimit}\", this._formatSize(validationBase.sizeLimit));\n r(\"{minSizeLimit}\", this._formatSize(validationBase.minSizeLimit));\n\n placeholderMatch = message.match(/(\\{\\w+\\})/g);\n if (placeholderMatch !== null) {\n qq.each(placeholderMatch, function(idx, placeholder) {\n r(placeholder, names[idx]);\n });\n }\n\n this._options.callbacks.onError(null, name, message, undefined);\n\n return message;\n },\n\n /**\n * Conditionally orders a manual retry of a failed upload.\n *\n * @param id File ID of the failed upload\n * @param callback Optional callback to invoke if a retry is prudent.\n * In lieu of asking the upload handler to retry.\n * @returns {boolean} true if a manual retry will occur\n * @private\n */\n _manualRetry: function(id, callback) {\n if (this._onBeforeManualRetry(id)) {\n this._netUploadedOrQueued++;\n this._uploadData.setStatus(id, qq.status.UPLOAD_RETRYING);\n\n if (callback) {\n callback(id);\n }\n else {\n this._handler.retry(id);\n }\n\n return true;\n }\n },\n\n _maybeAllComplete: function(id, status) {\n var self = this,\n notFinished = this._getNotFinished();\n\n if (status === qq.status.UPLOAD_SUCCESSFUL) {\n this._succeededSinceLastAllComplete.push(id);\n }\n else if (status === qq.status.UPLOAD_FAILED) {\n this._failedSinceLastAllComplete.push(id);\n }\n\n if (notFinished === 0 &&\n (this._succeededSinceLastAllComplete.length || this._failedSinceLastAllComplete.length)) {\n // Attempt to ensure onAllComplete is not invoked before other callbacks, such as onCancel & onComplete\n setTimeout(function() {\n self._onAllComplete(self._succeededSinceLastAllComplete, self._failedSinceLastAllComplete);\n }, 0);\n }\n },\n\n _maybeHandleIos8SafariWorkaround: function() {\n var self = this;\n\n if (this._options.workarounds.ios8SafariUploads && qq.ios800() && qq.iosSafari()) {\n setTimeout(function() {\n window.alert(self._options.messages.unsupportedBrowserIos8Safari);\n }, 0);\n throw new qq.Error(this._options.messages.unsupportedBrowserIos8Safari);\n }\n },\n\n _maybeParseAndSendUploadError: function(id, name, response, xhr) {\n // Assuming no one will actually set the response code to something other than 200\n // and still set 'success' to true...\n if (!response.success) {\n if (xhr && xhr.status !== 200 && !response.error) {\n this._options.callbacks.onError(id, name, \"XHR returned response code \" + xhr.status, xhr);\n }\n else {\n var errorReason = response.error ? response.error : this._options.text.defaultResponseError;\n this._options.callbacks.onError(id, name, errorReason, xhr);\n }\n }\n },\n\n _maybeProcessNextItemAfterOnValidateCallback: function(validItem, items, index, params, endpoint) {\n var self = this;\n\n if (items.length > index) {\n if (validItem || !this._options.validation.stopOnFirstInvalidFile) {\n //use setTimeout to prevent a stack overflow with a large number of files in the batch & non-promissory callbacks\n setTimeout(function() {\n var validationDescriptor = self._getValidationDescriptor(items[index]),\n buttonId = self._getButtonId(items[index].file),\n button = self._getButton(buttonId);\n\n self._handleCheckedCallback({\n name: \"onValidate\",\n callback: qq.bind(self._options.callbacks.onValidate, self, validationDescriptor, button),\n onSuccess: qq.bind(self._onValidateCallbackSuccess, self, items, index, params, endpoint),\n onFailure: qq.bind(self._onValidateCallbackFailure, self, items, index, params, endpoint),\n identifier: \"Item '\" + validationDescriptor.name + \"', size: \" + validationDescriptor.size\n });\n }, 0);\n }\n else if (!validItem) {\n for (; index < items.length; index++) {\n self._fileOrBlobRejected(items[index].id);\n }\n }\n }\n },\n\n _onAllComplete: function(successful, failed) {\n this._totalProgress && this._totalProgress.onAllComplete(successful, failed, this._preventRetries);\n\n this._options.callbacks.onAllComplete(qq.extend([], successful), qq.extend([], failed));\n\n this._succeededSinceLastAllComplete = [];\n this._failedSinceLastAllComplete = [];\n },\n\n /**\n * Attempt to automatically retry a failed upload.\n *\n * @param id The file ID of the failed upload\n * @param name The name of the file associated with the failed upload\n * @param responseJSON Response from the server, parsed into a javascript object\n * @param xhr Ajax transport used to send the failed request\n * @param callback Optional callback to be invoked if a retry is prudent.\n * Invoked in lieu of asking the upload handler to retry.\n * @returns {boolean} true if an auto-retry will occur\n * @private\n */\n _onAutoRetry: function(id, name, responseJSON, xhr, callback) {\n var self = this;\n\n self._preventRetries[id] = responseJSON[self._options.retry.preventRetryResponseProperty];\n\n if (self._shouldAutoRetry(id, name, responseJSON)) {\n var retryWaitPeriod = self._options.retry.autoAttemptDelay * 1000;\n\n self._maybeParseAndSendUploadError.apply(self, arguments);\n self._options.callbacks.onAutoRetry(id, name, self._autoRetries[id]);\n self._onBeforeAutoRetry(id, name);\n\n self._uploadData.setStatus(id, qq.status.UPLOAD_RETRYING);\n self._retryTimeouts[id] = setTimeout(function() {\n self.log(\"Starting retry for \" + name + \"...\");\n\n if (callback) {\n callback(id);\n }\n else {\n self._handler.retry(id);\n }\n }, retryWaitPeriod);\n\n return true;\n }\n },\n\n _onBeforeAutoRetry: function(id, name) {\n this.log(\"Waiting \" + this._options.retry.autoAttemptDelay + \" seconds before retrying \" + name + \"...\");\n },\n\n //return false if we should not attempt the requested retry\n _onBeforeManualRetry: function(id) {\n var itemLimit = this._currentItemLimit,\n fileName;\n\n if (this._preventRetries[id]) {\n this.log(\"Retries are forbidden for id \" + id, \"warn\");\n return false;\n }\n else if (this._handler.isValid(id)) {\n fileName = this.getName(id);\n\n if (this._options.callbacks.onManualRetry(id, fileName) === false) {\n return false;\n }\n\n if (itemLimit > 0 && this._netUploadedOrQueued + 1 > itemLimit) {\n this._itemError(\"retryFailTooManyItems\");\n return false;\n }\n\n this.log(\"Retrying upload for '\" + fileName + \"' (id: \" + id + \")...\");\n return true;\n }\n else {\n this.log(\"'\" + id + \"' is not a valid file ID\", \"error\");\n return false;\n }\n },\n\n _onCancel: function(id, name) {\n this._netUploadedOrQueued--;\n\n clearTimeout(this._retryTimeouts[id]);\n\n var storedItemIndex = qq.indexOf(this._storedIds, id);\n if (!this._options.autoUpload && storedItemIndex >= 0) {\n this._storedIds.splice(storedItemIndex, 1);\n }\n\n this._uploadData.setStatus(id, qq.status.CANCELED);\n },\n\n _onComplete: function(id, name, result, xhr) {\n if (!result.success) {\n this._netUploadedOrQueued--;\n this._uploadData.setStatus(id, qq.status.UPLOAD_FAILED);\n\n if (result[this._options.retry.preventRetryResponseProperty] === true) {\n this._preventRetries[id] = true;\n }\n }\n else {\n if (result.thumbnailUrl) {\n this._thumbnailUrls[id] = result.thumbnailUrl;\n }\n\n this._netUploaded++;\n this._uploadData.setStatus(id, qq.status.UPLOAD_SUCCESSFUL);\n }\n\n this._maybeParseAndSendUploadError(id, name, result, xhr);\n\n return result.success ? true : false;\n },\n\n _onDelete: function(id) {\n this._uploadData.setStatus(id, qq.status.DELETING);\n },\n\n _onDeleteComplete: function(id, xhrOrXdr, isError) {\n var name = this.getName(id);\n\n if (isError) {\n this._uploadData.setStatus(id, qq.status.DELETE_FAILED);\n this.log(\"Delete request for '\" + name + \"' has failed.\", \"error\");\n\n // For error reporting, we only have access to the response status if this is not\n // an `XDomainRequest`.\n if (xhrOrXdr.withCredentials === undefined) {\n this._options.callbacks.onError(id, name, \"Delete request failed\", xhrOrXdr);\n }\n else {\n this._options.callbacks.onError(id, name, \"Delete request failed with response code \" + xhrOrXdr.status, xhrOrXdr);\n }\n }\n else {\n this._netUploadedOrQueued--;\n this._netUploaded--;\n this._handler.expunge(id);\n this._uploadData.setStatus(id, qq.status.DELETED);\n this.log(\"Delete request for '\" + name + \"' has succeeded.\");\n }\n },\n\n _onInputChange: function(input) {\n var fileIndex;\n\n if (qq.supportedFeatures.ajaxUploading) {\n for (fileIndex = 0; fileIndex < input.files.length; fileIndex++) {\n this._annotateWithButtonId(input.files[fileIndex], input);\n }\n\n this.addFiles(input.files);\n }\n // Android 2.3.x will fire `onchange` even if no file has been selected\n else if (input.value.length > 0) {\n this.addFiles(input);\n }\n\n qq.each(this._buttons, function(idx, button) {\n button.reset();\n });\n },\n\n _onProgress: function(id, name, loaded, total) {\n this._totalProgress && this._totalProgress.onIndividualProgress(id, loaded, total);\n },\n\n _onSubmit: function(id, name) {\n //nothing to do yet in core uploader\n },\n\n _onSubmitCallbackSuccess: function(id, name) {\n this._onSubmit.apply(this, arguments);\n this._uploadData.setStatus(id, qq.status.SUBMITTED);\n this._onSubmitted.apply(this, arguments);\n\n if (this._options.autoUpload) {\n this._options.callbacks.onSubmitted.apply(this, arguments);\n this._uploadFile(id);\n }\n else {\n this._storeForLater(id);\n this._options.callbacks.onSubmitted.apply(this, arguments);\n }\n },\n\n _onSubmitDelete: function(id, onSuccessCallback, additionalMandatedParams) {\n var uuid = this.getUuid(id),\n adjustedOnSuccessCallback;\n\n if (onSuccessCallback) {\n adjustedOnSuccessCallback = qq.bind(onSuccessCallback, this, id, uuid, additionalMandatedParams);\n }\n\n if (this._isDeletePossible()) {\n this._handleCheckedCallback({\n name: \"onSubmitDelete\",\n callback: qq.bind(this._options.callbacks.onSubmitDelete, this, id),\n onSuccess: adjustedOnSuccessCallback ||\n qq.bind(this._deleteHandler.sendDelete, this, id, uuid, additionalMandatedParams),\n identifier: id\n });\n return true;\n }\n else {\n this.log(\"Delete request ignored for ID \" + id + \", delete feature is disabled or request not possible \" +\n \"due to CORS on a user agent that does not support pre-flighting.\", \"warn\");\n return false;\n }\n },\n\n _onSubmitted: function(id) {\n //nothing to do in the base uploader\n },\n\n _onTotalProgress: function(loaded, total) {\n this._options.callbacks.onTotalProgress(loaded, total);\n },\n\n _onUploadPrep: function(id) {\n // nothing to do in the core uploader for now\n },\n\n _onUpload: function(id, name) {\n this._uploadData.setStatus(id, qq.status.UPLOADING);\n },\n\n _onUploadChunk: function(id, chunkData) {\n //nothing to do in the base uploader\n },\n\n _onUploadStatusChange: function(id, oldStatus, newStatus) {\n // Make sure a \"queued\" retry attempt is canceled if the upload has been paused\n if (newStatus === qq.status.PAUSED) {\n clearTimeout(this._retryTimeouts[id]);\n }\n },\n\n _onValidateBatchCallbackFailure: function(fileWrappers) {\n var self = this;\n\n qq.each(fileWrappers, function(idx, fileWrapper) {\n self._fileOrBlobRejected(fileWrapper.id);\n });\n },\n\n _onValidateBatchCallbackSuccess: function(validationDescriptors, items, params, endpoint, button) {\n var errorMessage,\n itemLimit = this._currentItemLimit,\n proposedNetFilesUploadedOrQueued = this._netUploadedOrQueued;\n\n if (itemLimit === 0 || proposedNetFilesUploadedOrQueued <= itemLimit) {\n if (items.length > 0) {\n this._handleCheckedCallback({\n name: \"onValidate\",\n callback: qq.bind(this._options.callbacks.onValidate, this, validationDescriptors[0], button),\n onSuccess: qq.bind(this._onValidateCallbackSuccess, this, items, 0, params, endpoint),\n onFailure: qq.bind(this._onValidateCallbackFailure, this, items, 0, params, endpoint),\n identifier: \"Item '\" + items[0].file.name + \"', size: \" + items[0].file.size\n });\n }\n else {\n this._itemError(\"noFilesError\");\n }\n }\n else {\n this._onValidateBatchCallbackFailure(items);\n errorMessage = this._options.messages.tooManyItemsError\n .replace(/\\{netItems\\}/g, proposedNetFilesUploadedOrQueued)\n .replace(/\\{itemLimit\\}/g, itemLimit);\n this._batchError(errorMessage);\n }\n },\n\n _onValidateCallbackFailure: function(items, index, params, endpoint) {\n var nextIndex = index + 1;\n\n this._fileOrBlobRejected(items[index].id, items[index].file.name);\n\n this._maybeProcessNextItemAfterOnValidateCallback(false, items, nextIndex, params, endpoint);\n },\n\n _onValidateCallbackSuccess: function(items, index, params, endpoint) {\n var self = this,\n nextIndex = index + 1,\n validationDescriptor = this._getValidationDescriptor(items[index]);\n\n this._validateFileOrBlobData(items[index], validationDescriptor)\n .then(\n function() {\n self._upload(items[index].id, params, endpoint);\n self._maybeProcessNextItemAfterOnValidateCallback(true, items, nextIndex, params, endpoint);\n },\n function() {\n self._maybeProcessNextItemAfterOnValidateCallback(false, items, nextIndex, params, endpoint);\n }\n );\n },\n\n _prepareItemsForUpload: function(items, params, endpoint) {\n if (items.length === 0) {\n this._itemError(\"noFilesError\");\n return;\n }\n\n var validationDescriptors = this._getValidationDescriptors(items),\n buttonId = this._getButtonId(items[0].file),\n button = this._getButton(buttonId);\n\n this._handleCheckedCallback({\n name: \"onValidateBatch\",\n callback: qq.bind(this._options.callbacks.onValidateBatch, this, validationDescriptors, button),\n onSuccess: qq.bind(this._onValidateBatchCallbackSuccess, this, validationDescriptors, items, params, endpoint, button),\n onFailure: qq.bind(this._onValidateBatchCallbackFailure, this, items),\n identifier: \"batch validation\"\n });\n },\n\n _preventLeaveInProgress: function() {\n var self = this;\n\n this._disposeSupport.attach(window, \"beforeunload\", function(e) {\n if (self.getInProgress()) {\n e = e || window.event;\n // for ie, ff\n e.returnValue = self._options.messages.onLeave;\n // for webkit\n return self._options.messages.onLeave;\n }\n });\n },\n\n // Attempts to refresh session data only if the `qq.Session` module exists\n // and a session endpoint has been specified. The `onSessionRequestComplete`\n // callback will be invoked once the refresh is complete.\n _refreshSessionData: function() {\n var self = this,\n options = this._options.session;\n\n /* jshint eqnull:true */\n if (qq.Session && this._options.session.endpoint != null) {\n if (!this._session) {\n qq.extend(options, {cors: this._options.cors});\n\n options.log = qq.bind(this.log, this);\n options.addFileRecord = qq.bind(this._addCannedFile, this);\n\n this._session = new qq.Session(options);\n }\n\n setTimeout(function() {\n self._session.refresh().then(function(response, xhrOrXdr) {\n self._sessionRequestComplete();\n self._options.callbacks.onSessionRequestComplete(response, true, xhrOrXdr);\n\n }, function(response, xhrOrXdr) {\n\n self._options.callbacks.onSessionRequestComplete(response, false, xhrOrXdr);\n });\n }, 0);\n }\n },\n\n _sessionRequestComplete: function() {},\n\n _setSize: function(id, newSize) {\n this._uploadData.updateSize(id, newSize);\n this._totalProgress && this._totalProgress.onNewSize(id);\n },\n\n _shouldAutoRetry: function(id, name, responseJSON) {\n var uploadData = this._uploadData.retrieve({id: id});\n\n /*jshint laxbreak: true */\n if (!this._preventRetries[id]\n && this._options.retry.enableAuto\n && uploadData.status !== qq.status.PAUSED) {\n\n if (this._autoRetries[id] === undefined) {\n this._autoRetries[id] = 0;\n }\n\n if (this._autoRetries[id] < this._options.retry.maxAutoAttempts) {\n this._autoRetries[id] += 1;\n return true;\n }\n }\n\n return false;\n },\n\n _storeForLater: function(id) {\n this._storedIds.push(id);\n },\n\n // Maps a file with the button that was used to select it.\n _trackButton: function(id) {\n var buttonId;\n\n if (qq.supportedFeatures.ajaxUploading) {\n buttonId = this._handler.getFile(id).qqButtonId;\n }\n else {\n buttonId = this._getButtonId(this._handler.getInput(id));\n }\n\n if (buttonId) {\n this._buttonIdsForFileIds[id] = buttonId;\n }\n },\n\n _updateFormSupportAndParams: function(formElementOrId) {\n this._options.form.element = formElementOrId;\n\n this._formSupport = qq.FormSupport && new qq.FormSupport(\n this._options.form, qq.bind(this.uploadStoredFiles, this), qq.bind(this.log, this)\n );\n\n if (this._formSupport && this._formSupport.attachedToForm) {\n this._paramsStore.addReadOnly(null, this._formSupport.getFormInputsAsObject);\n\n this._options.autoUpload = this._formSupport.newAutoUpload;\n if (this._formSupport.newEndpoint) {\n this.setEndpoint(this._formSupport.newEndpoint);\n }\n }\n },\n\n _upload: function(id, params, endpoint) {\n var name = this.getName(id);\n\n if (params) {\n this.setParams(params, id);\n }\n\n if (endpoint) {\n this.setEndpoint(endpoint, id);\n }\n\n this._handleCheckedCallback({\n name: \"onSubmit\",\n callback: qq.bind(this._options.callbacks.onSubmit, this, id, name),\n onSuccess: qq.bind(this._onSubmitCallbackSuccess, this, id, name),\n onFailure: qq.bind(this._fileOrBlobRejected, this, id, name),\n identifier: id\n });\n },\n\n _uploadFile: function(id) {\n if (!this._handler.upload(id)) {\n this._uploadData.setStatus(id, qq.status.QUEUED);\n }\n },\n\n _uploadStoredFiles: function() {\n var idToUpload, stillSubmitting,\n self = this;\n\n while (this._storedIds.length) {\n idToUpload = this._storedIds.shift();\n this._uploadFile(idToUpload);\n }\n\n // If we are still waiting for some files to clear validation, attempt to upload these again in a bit\n stillSubmitting = this.getUploads({status: qq.status.SUBMITTING}).length;\n if (stillSubmitting) {\n qq.log(\"Still waiting for \" + stillSubmitting + \" files to clear submit queue. Will re-parse stored IDs array shortly.\");\n setTimeout(function() {\n self._uploadStoredFiles();\n }, 1000);\n }\n },\n\n /**\n * Performs some internal validation checks on an item, defined in the `validation` option.\n *\n * @param fileWrapper Wrapper containing a `file` along with an `id`\n * @param validationDescriptor Normalized information about the item (`size`, `name`).\n * @returns qq.Promise with appropriate callbacks invoked depending on the validity of the file\n * @private\n */\n _validateFileOrBlobData: function(fileWrapper, validationDescriptor) {\n var self = this,\n file = (function() {\n if (fileWrapper.file instanceof qq.BlobProxy) {\n return fileWrapper.file.referenceBlob;\n }\n return fileWrapper.file;\n }()),\n name = validationDescriptor.name,\n size = validationDescriptor.size,\n buttonId = this._getButtonId(fileWrapper.file),\n validationBase = this._getValidationBase(buttonId),\n validityChecker = new qq.Promise();\n\n validityChecker.then(\n function() {},\n function() {\n self._fileOrBlobRejected(fileWrapper.id, name);\n });\n\n if (qq.isFileOrInput(file) && !this._isAllowedExtension(validationBase.allowedExtensions, name)) {\n this._itemError(\"typeError\", name, file);\n return validityChecker.failure();\n }\n\n if (!this._options.validation.allowEmpty && size === 0) {\n this._itemError(\"emptyError\", name, file);\n return validityChecker.failure();\n }\n\n if (size > 0 && validationBase.sizeLimit && size > validationBase.sizeLimit) {\n this._itemError(\"sizeError\", name, file);\n return validityChecker.failure();\n }\n\n if (size > 0 && size < validationBase.minSizeLimit) {\n this._itemError(\"minSizeError\", name, file);\n return validityChecker.failure();\n }\n\n if (qq.ImageValidation && qq.supportedFeatures.imagePreviews && qq.isFile(file)) {\n new qq.ImageValidation(file, qq.bind(self.log, self)).validate(validationBase.image).then(\n validityChecker.success,\n function(errorCode) {\n self._itemError(errorCode + \"ImageError\", name, file);\n validityChecker.failure();\n }\n );\n }\n else {\n validityChecker.success();\n }\n\n return validityChecker;\n },\n\n _wrapCallbacks: function() {\n var self, safeCallback, prop;\n\n self = this;\n\n safeCallback = function(name, callback, args) {\n var errorMsg;\n\n try {\n return callback.apply(self, args);\n }\n catch (exception) {\n errorMsg = exception.message || exception.toString();\n self.log(\"Caught exception in '\" + name + \"' callback - \" + errorMsg, \"error\");\n }\n };\n\n /* jshint forin: false, loopfunc: true */\n for (prop in this._options.callbacks) {\n (function() {\n var callbackName, callbackFunc;\n callbackName = prop;\n callbackFunc = self._options.callbacks[callbackName];\n self._options.callbacks[callbackName] = function() {\n return safeCallback(callbackName, callbackFunc, arguments);\n };\n }());\n }\n }\n };\n}());\n","/*globals qq*/\n(function() {\n \"use strict\";\n\n qq.FineUploaderBasic = function(o) {\n var self = this;\n\n // These options define FineUploaderBasic mode.\n this._options = {\n debug: false,\n button: null,\n multiple: true,\n maxConnections: 3,\n disableCancelForFormUploads: false,\n autoUpload: true,\n\n request: {\n customHeaders: {},\n endpoint: \"/server/upload\",\n filenameParam: \"qqfilename\",\n forceMultipart: true,\n inputName: \"qqfile\",\n method: \"POST\",\n params: {},\n paramsInBody: true,\n totalFileSizeName: \"qqtotalfilesize\",\n uuidName: \"qquuid\"\n },\n\n validation: {\n allowedExtensions: [],\n sizeLimit: 0,\n minSizeLimit: 0,\n itemLimit: 0,\n stopOnFirstInvalidFile: true,\n acceptFiles: null,\n image: {\n maxHeight: 0,\n maxWidth: 0,\n minHeight: 0,\n minWidth: 0\n },\n allowEmpty: false\n },\n\n callbacks: {\n onSubmit: function(id, name) {},\n onSubmitted: function(id, name) {},\n onComplete: function(id, name, responseJSON, maybeXhr) {},\n onAllComplete: function(successful, failed) {},\n onCancel: function(id, name) {},\n onUpload: function(id, name) {},\n onUploadChunk: function(id, name, chunkData) {},\n onUploadChunkSuccess: function(id, chunkData, responseJSON, xhr) {},\n onResume: function(id, fileName, chunkData) {},\n onProgress: function(id, name, loaded, total) {},\n onTotalProgress: function(loaded, total) {},\n onError: function(id, name, reason, maybeXhrOrXdr) {},\n onAutoRetry: function(id, name, attemptNumber) {},\n onManualRetry: function(id, name) {},\n onValidateBatch: function(fileOrBlobData) {},\n onValidate: function(fileOrBlobData) {},\n onSubmitDelete: function(id) {},\n onDelete: function(id) {},\n onDeleteComplete: function(id, xhrOrXdr, isError) {},\n onPasteReceived: function(blob) {},\n onStatusChange: function(id, oldStatus, newStatus) {},\n onSessionRequestComplete: function(response, success, xhrOrXdr) {}\n },\n\n messages: {\n typeError: \"{file} has an invalid extension. Valid extension(s): {extensions}.\",\n sizeError: \"{file} is too large, maximum file size is {sizeLimit}.\",\n minSizeError: \"{file} is too small, minimum file size is {minSizeLimit}.\",\n emptyError: \"{file} is empty, please select files again without it.\",\n noFilesError: \"No files to upload.\",\n tooManyItemsError: \"Too many items ({netItems}) would be uploaded. Item limit is {itemLimit}.\",\n maxHeightImageError: \"Image is too tall.\",\n maxWidthImageError: \"Image is too wide.\",\n minHeightImageError: \"Image is not tall enough.\",\n minWidthImageError: \"Image is not wide enough.\",\n retryFailTooManyItems: \"Retry failed - you have reached your file limit.\",\n onLeave: \"The files are being uploaded, if you leave now the upload will be canceled.\",\n unsupportedBrowserIos8Safari: \"Unrecoverable error - this browser does not permit file uploading of any kind due to serious bugs in iOS8 Safari. Please use iOS8 Chrome until Apple fixes these issues.\"\n },\n\n retry: {\n enableAuto: false,\n maxAutoAttempts: 3,\n autoAttemptDelay: 5,\n preventRetryResponseProperty: \"preventRetry\"\n },\n\n classes: {\n buttonHover: \"qq-upload-button-hover\",\n buttonFocus: \"qq-upload-button-focus\"\n },\n\n chunking: {\n enabled: false,\n concurrent: {\n enabled: false\n },\n mandatory: false,\n paramNames: {\n partIndex: \"qqpartindex\",\n partByteOffset: \"qqpartbyteoffset\",\n chunkSize: \"qqchunksize\",\n totalFileSize: \"qqtotalfilesize\",\n totalParts: \"qqtotalparts\"\n },\n partSize: 2000000,\n // only relevant for traditional endpoints, only required when concurrent.enabled === true\n success: {\n endpoint: null\n }\n },\n\n resume: {\n enabled: false,\n recordsExpireIn: 7, //days\n paramNames: {\n resuming: \"qqresume\"\n }\n },\n\n formatFileName: function(fileOrBlobName) {\n return fileOrBlobName;\n },\n\n text: {\n defaultResponseError: \"Upload failure reason unknown\",\n fileInputTitle: \"file input\",\n sizeSymbols: [\"kB\", \"MB\", \"GB\", \"TB\", \"PB\", \"EB\"]\n },\n\n deleteFile: {\n enabled: false,\n method: \"DELETE\",\n endpoint: \"/server/upload\",\n customHeaders: {},\n params: {}\n },\n\n cors: {\n expected: false,\n sendCredentials: false,\n allowXdr: false\n },\n\n blobs: {\n defaultName: \"misc_data\"\n },\n\n paste: {\n targetElement: null,\n defaultName: \"pasted_image\"\n },\n\n camera: {\n ios: false,\n\n // if ios is true: button is null means target the default button, otherwise target the button specified\n button: null\n },\n\n // This refers to additional upload buttons to be handled by Fine Uploader.\n // Each element is an object, containing `element` as the only required\n // property. The `element` must be a container that will ultimately\n // contain an invisible ` ` created by Fine Uploader.\n // Optional properties of each object include `multiple`, `validation`,\n // and `folders`.\n extraButtons: [],\n\n // Depends on the session module. Used to query the server for an initial file list\n // during initialization and optionally after a `reset`.\n session: {\n endpoint: null,\n params: {},\n customHeaders: {},\n refreshOnReset: true\n },\n\n // Send parameters associated with an existing form along with the files\n form: {\n // Element ID, HTMLElement, or null\n element: \"qq-form\",\n\n // Overrides the base `autoUpload`, unless `element` is null.\n autoUpload: false,\n\n // true = upload files on form submission (and squelch submit event)\n interceptSubmit: true\n },\n\n // scale images client side, upload a new file for each scaled version\n scaling: {\n customResizer: null,\n\n // send the original file as well\n sendOriginal: true,\n\n // fox orientation for scaled images\n orient: true,\n\n // If null, scaled image type will match reference image type. This value will be referred to\n // for any size record that does not specific a type.\n defaultType: null,\n\n defaultQuality: 80,\n\n failureText: \"Failed to scale\",\n\n includeExif: false,\n\n // metadata about each requested scaled version\n sizes: []\n },\n\n workarounds: {\n iosEmptyVideos: true,\n ios8SafariUploads: true,\n ios8BrowserCrash: false\n }\n };\n\n // Replace any default options with user defined ones\n qq.extend(this._options, o, true);\n\n this._buttons = [];\n this._extraButtonSpecs = {};\n this._buttonIdsForFileIds = [];\n\n this._wrapCallbacks();\n this._disposeSupport = new qq.DisposeSupport();\n\n this._storedIds = [];\n this._autoRetries = [];\n this._retryTimeouts = [];\n this._preventRetries = [];\n this._thumbnailUrls = [];\n\n this._netUploadedOrQueued = 0;\n this._netUploaded = 0;\n this._uploadData = this._createUploadDataTracker();\n\n this._initFormSupportAndParams();\n\n this._customHeadersStore = this._createStore(this._options.request.customHeaders);\n this._deleteFileCustomHeadersStore = this._createStore(this._options.deleteFile.customHeaders);\n\n this._deleteFileParamsStore = this._createStore(this._options.deleteFile.params);\n\n this._endpointStore = this._createStore(this._options.request.endpoint);\n this._deleteFileEndpointStore = this._createStore(this._options.deleteFile.endpoint);\n\n this._handler = this._createUploadHandler();\n\n this._deleteHandler = qq.DeleteFileAjaxRequester && this._createDeleteHandler();\n\n if (this._options.button) {\n this._defaultButtonId = this._createUploadButton({\n element: this._options.button,\n title: this._options.text.fileInputTitle\n }).getButtonId();\n }\n\n this._generateExtraButtonSpecs();\n\n this._handleCameraAccess();\n\n if (this._options.paste.targetElement) {\n if (qq.PasteSupport) {\n this._pasteHandler = this._createPasteHandler();\n }\n else {\n this.log(\"Paste support module not found\", \"error\");\n }\n }\n\n this._preventLeaveInProgress();\n\n this._imageGenerator = qq.ImageGenerator && new qq.ImageGenerator(qq.bind(this.log, this));\n this._refreshSessionData();\n\n this._succeededSinceLastAllComplete = [];\n this._failedSinceLastAllComplete = [];\n\n this._scaler = (qq.Scaler && new qq.Scaler(this._options.scaling, qq.bind(this.log, this))) || {};\n if (this._scaler.enabled) {\n this._customNewFileHandler = qq.bind(this._scaler.handleNewFile, this._scaler);\n }\n\n if (qq.TotalProgress && qq.supportedFeatures.progressBar) {\n this._totalProgress = new qq.TotalProgress(\n qq.bind(this._onTotalProgress, this),\n\n function(id) {\n var entry = self._uploadData.retrieve({id: id});\n return (entry && entry.size) || 0;\n }\n );\n }\n\n this._currentItemLimit = this._options.validation.itemLimit;\n };\n\n // Define the private & public API methods.\n qq.FineUploaderBasic.prototype = qq.basePublicApi;\n qq.extend(qq.FineUploaderBasic.prototype, qq.basePrivateApi);\n}());\n","/*globals qq, XDomainRequest*/\n/** Generic class for sending non-upload ajax requests and handling the associated responses **/\nqq.AjaxRequester = function(o) {\n \"use strict\";\n\n var log, shouldParamsBeInQueryString,\n queue = [],\n requestData = {},\n options = {\n acceptHeader: null,\n validMethods: [\"PATCH\", \"POST\", \"PUT\"],\n method: \"POST\",\n contentType: \"application/x-www-form-urlencoded\",\n maxConnections: 3,\n customHeaders: {},\n endpointStore: {},\n paramsStore: {},\n mandatedParams: {},\n allowXRequestedWithAndCacheControl: true,\n successfulResponseCodes: {\n DELETE: [200, 202, 204],\n PATCH: [200, 201, 202, 203, 204],\n POST: [200, 201, 202, 203, 204],\n PUT: [200, 201, 202, 203, 204],\n GET: [200]\n },\n cors: {\n expected: false,\n sendCredentials: false\n },\n log: function(str, level) {},\n onSend: function(id) {},\n onComplete: function(id, xhrOrXdr, isError) {},\n onProgress: null\n };\n\n qq.extend(options, o);\n log = options.log;\n\n if (qq.indexOf(options.validMethods, options.method) < 0) {\n throw new Error(\"'\" + options.method + \"' is not a supported method for this type of request!\");\n }\n\n // [Simple methods](http://www.w3.org/TR/cors/#simple-method)\n // are defined by the W3C in the CORS spec as a list of methods that, in part,\n // make a CORS request eligible to be exempt from preflighting.\n function isSimpleMethod() {\n return qq.indexOf([\"GET\", \"POST\", \"HEAD\"], options.method) >= 0;\n }\n\n // [Simple headers](http://www.w3.org/TR/cors/#simple-header)\n // are defined by the W3C in the CORS spec as a list of headers that, in part,\n // make a CORS request eligible to be exempt from preflighting.\n function containsNonSimpleHeaders(headers) {\n var containsNonSimple = false;\n\n qq.each(containsNonSimple, function(idx, header) {\n if (qq.indexOf([\"Accept\", \"Accept-Language\", \"Content-Language\", \"Content-Type\"], header) < 0) {\n containsNonSimple = true;\n return false;\n }\n });\n\n return containsNonSimple;\n }\n\n function isXdr(xhr) {\n //The `withCredentials` test is a commonly accepted way to determine if XHR supports CORS.\n return options.cors.expected && xhr.withCredentials === undefined;\n }\n\n // Returns either a new `XMLHttpRequest` or `XDomainRequest` instance.\n function getCorsAjaxTransport() {\n var xhrOrXdr;\n\n if (window.XMLHttpRequest || window.ActiveXObject) {\n xhrOrXdr = qq.createXhrInstance();\n\n if (xhrOrXdr.withCredentials === undefined) {\n xhrOrXdr = new XDomainRequest();\n // Workaround for XDR bug in IE9 - https://social.msdn.microsoft.com/Forums/ie/en-US/30ef3add-767c-4436-b8a9-f1ca19b4812e/ie9-rtm-xdomainrequest-issued-requests-may-abort-if-all-event-handlers-not-specified?forum=iewebdevelopment\n xhrOrXdr.onload = function() {};\n xhrOrXdr.onerror = function() {};\n xhrOrXdr.ontimeout = function() {};\n xhrOrXdr.onprogress = function() {};\n }\n }\n\n return xhrOrXdr;\n }\n\n // Returns either a new XHR/XDR instance, or an existing one for the associated `File` or `Blob`.\n function getXhrOrXdr(id, suppliedXhr) {\n var xhrOrXdr = requestData[id].xhr;\n\n if (!xhrOrXdr) {\n if (suppliedXhr) {\n xhrOrXdr = suppliedXhr;\n }\n else {\n if (options.cors.expected) {\n xhrOrXdr = getCorsAjaxTransport();\n }\n else {\n xhrOrXdr = qq.createXhrInstance();\n }\n }\n\n requestData[id].xhr = xhrOrXdr;\n }\n\n return xhrOrXdr;\n }\n\n // Removes element from queue, sends next request\n function dequeue(id) {\n var i = qq.indexOf(queue, id),\n max = options.maxConnections,\n nextId;\n\n delete requestData[id];\n queue.splice(i, 1);\n\n if (queue.length >= max && i < max) {\n nextId = queue[max - 1];\n sendRequest(nextId);\n }\n }\n\n function onComplete(id, xdrError) {\n var xhr = getXhrOrXdr(id),\n method = options.method,\n isError = xdrError === true;\n\n dequeue(id);\n\n if (isError) {\n log(method + \" request for \" + id + \" has failed\", \"error\");\n }\n else if (!isXdr(xhr) && !isResponseSuccessful(xhr.status)) {\n isError = true;\n log(method + \" request for \" + id + \" has failed - response code \" + xhr.status, \"error\");\n }\n\n options.onComplete(id, xhr, isError);\n }\n\n function getParams(id) {\n var onDemandParams = requestData[id].additionalParams,\n mandatedParams = options.mandatedParams,\n params;\n\n if (options.paramsStore.get) {\n params = options.paramsStore.get(id);\n }\n\n if (onDemandParams) {\n qq.each(onDemandParams, function(name, val) {\n params = params || {};\n params[name] = val;\n });\n }\n\n if (mandatedParams) {\n qq.each(mandatedParams, function(name, val) {\n params = params || {};\n params[name] = val;\n });\n }\n\n return params;\n }\n\n function sendRequest(id, optXhr) {\n var xhr = getXhrOrXdr(id, optXhr),\n method = options.method,\n params = getParams(id),\n payload = requestData[id].payload,\n url;\n\n options.onSend(id);\n\n url = createUrl(id, params, requestData[id].additionalQueryParams);\n\n // XDR and XHR status detection APIs differ a bit.\n if (isXdr(xhr)) {\n xhr.onload = getXdrLoadHandler(id);\n xhr.onerror = getXdrErrorHandler(id);\n }\n else {\n xhr.onreadystatechange = getXhrReadyStateChangeHandler(id);\n }\n\n registerForUploadProgress(id);\n\n // The last parameter is assumed to be ignored if we are actually using `XDomainRequest`.\n xhr.open(method, url, true);\n\n // Instruct the transport to send cookies along with the CORS request,\n // unless we are using `XDomainRequest`, which is not capable of this.\n if (options.cors.expected && options.cors.sendCredentials && !isXdr(xhr)) {\n xhr.withCredentials = true;\n }\n\n setHeaders(id);\n\n log(\"Sending \" + method + \" request for \" + id);\n\n if (payload) {\n xhr.send(payload);\n }\n else if (shouldParamsBeInQueryString || !params) {\n xhr.send();\n }\n else if (params && options.contentType && options.contentType.toLowerCase().indexOf(\"application/x-www-form-urlencoded\") >= 0) {\n xhr.send(qq.obj2url(params, \"\"));\n }\n else if (params && options.contentType && options.contentType.toLowerCase().indexOf(\"application/json\") >= 0) {\n xhr.send(JSON.stringify(params));\n }\n else {\n xhr.send(params);\n }\n\n return xhr;\n }\n\n function createUrl(id, params, additionalQueryParams) {\n var endpoint = options.endpointStore.get(id),\n addToPath = requestData[id].addToPath;\n\n /*jshint -W116,-W041 */\n if (addToPath != undefined) {\n endpoint += \"/\" + addToPath;\n }\n\n if (shouldParamsBeInQueryString && params) {\n endpoint = qq.obj2url(params, endpoint);\n }\n\n if (additionalQueryParams) {\n endpoint = qq.obj2url(additionalQueryParams, endpoint);\n }\n\n return endpoint;\n }\n\n // Invoked by the UA to indicate a number of possible states that describe\n // a live `XMLHttpRequest` transport.\n function getXhrReadyStateChangeHandler(id) {\n return function() {\n if (getXhrOrXdr(id).readyState === 4) {\n onComplete(id);\n }\n };\n }\n\n function registerForUploadProgress(id) {\n var onProgress = options.onProgress;\n\n if (onProgress) {\n getXhrOrXdr(id).upload.onprogress = function(e) {\n if (e.lengthComputable) {\n onProgress(id, e.loaded, e.total);\n }\n };\n }\n }\n\n // This will be called by IE to indicate **success** for an associated\n // `XDomainRequest` transported request.\n function getXdrLoadHandler(id) {\n return function() {\n onComplete(id);\n };\n }\n\n // This will be called by IE to indicate **failure** for an associated\n // `XDomainRequest` transported request.\n function getXdrErrorHandler(id) {\n return function() {\n onComplete(id, true);\n };\n }\n\n function setHeaders(id) {\n var xhr = getXhrOrXdr(id),\n customHeaders = options.customHeaders,\n onDemandHeaders = requestData[id].additionalHeaders || {},\n method = options.method,\n allHeaders = {};\n\n // If XDomainRequest is being used, we can't set headers, so just ignore this block.\n if (!isXdr(xhr)) {\n options.acceptHeader && xhr.setRequestHeader(\"Accept\", options.acceptHeader);\n\n // Only attempt to add X-Requested-With & Cache-Control if permitted\n if (options.allowXRequestedWithAndCacheControl) {\n // Do not add X-Requested-With & Cache-Control if this is a cross-origin request\n // OR the cross-origin request contains a non-simple method or header.\n // This is done to ensure a preflight is not triggered exclusively based on the\n // addition of these 2 non-simple headers.\n if (!options.cors.expected || (!isSimpleMethod() || containsNonSimpleHeaders(customHeaders))) {\n xhr.setRequestHeader(\"X-Requested-With\", \"XMLHttpRequest\");\n xhr.setRequestHeader(\"Cache-Control\", \"no-cache\");\n }\n }\n\n if (options.contentType && (method === \"POST\" || method === \"PUT\")) {\n xhr.setRequestHeader(\"Content-Type\", options.contentType);\n }\n\n qq.extend(allHeaders, qq.isFunction(customHeaders) ? customHeaders(id) : customHeaders);\n qq.extend(allHeaders, onDemandHeaders);\n\n qq.each(allHeaders, function(name, val) {\n xhr.setRequestHeader(name, val);\n });\n }\n }\n\n function isResponseSuccessful(responseCode) {\n return qq.indexOf(options.successfulResponseCodes[options.method], responseCode) >= 0;\n }\n\n function prepareToSend(id, optXhr, addToPath, additionalParams, additionalQueryParams, additionalHeaders, payload) {\n requestData[id] = {\n addToPath: addToPath,\n additionalParams: additionalParams,\n additionalQueryParams: additionalQueryParams,\n additionalHeaders: additionalHeaders,\n payload: payload\n };\n\n var len = queue.push(id);\n\n // if too many active connections, wait...\n if (len <= options.maxConnections) {\n return sendRequest(id, optXhr);\n }\n }\n\n shouldParamsBeInQueryString = options.method === \"GET\" || options.method === \"DELETE\";\n\n qq.extend(this, {\n // Start the process of sending the request. The ID refers to the file associated with the request.\n initTransport: function(id) {\n var path, params, headers, payload, cacheBuster, additionalQueryParams;\n\n return {\n // Optionally specify the end of the endpoint path for the request.\n withPath: function(appendToPath) {\n path = appendToPath;\n return this;\n },\n\n // Optionally specify additional parameters to send along with the request.\n // These will be added to the query string for GET/DELETE requests or the payload\n // for POST/PUT requests. The Content-Type of the request will be used to determine\n // how these parameters should be formatted as well.\n withParams: function(additionalParams) {\n params = additionalParams;\n return this;\n },\n\n withQueryParams: function(_additionalQueryParams_) {\n additionalQueryParams = _additionalQueryParams_;\n return this;\n },\n\n // Optionally specify additional headers to send along with the request.\n withHeaders: function(additionalHeaders) {\n headers = additionalHeaders;\n return this;\n },\n\n // Optionally specify a payload/body for the request.\n withPayload: function(thePayload) {\n payload = thePayload;\n return this;\n },\n\n // Appends a cache buster (timestamp) to the request URL as a query parameter (only if GET or DELETE)\n withCacheBuster: function() {\n cacheBuster = true;\n return this;\n },\n\n // Send the constructed request.\n send: function(optXhr) {\n if (cacheBuster && qq.indexOf([\"GET\", \"DELETE\"], options.method) >= 0) {\n params.qqtimestamp = new Date().getTime();\n }\n\n return prepareToSend(id, optXhr, path, params, additionalQueryParams, headers, payload);\n }\n };\n },\n\n canceled: function(id) {\n dequeue(id);\n }\n });\n};\n","/* globals qq */\n/**\n * Common upload handler functions.\n *\n * @constructor\n */\nqq.UploadHandler = function(spec) {\n \"use strict\";\n\n var proxy = spec.proxy,\n fileState = {},\n onCancel = proxy.onCancel,\n getName = proxy.getName;\n\n qq.extend(this, {\n add: function(id, fileItem) {\n fileState[id] = fileItem;\n fileState[id].temp = {};\n },\n\n cancel: function(id) {\n var self = this,\n cancelFinalizationEffort = new qq.Promise(),\n onCancelRetVal = onCancel(id, getName(id), cancelFinalizationEffort);\n\n onCancelRetVal.then(function() {\n if (self.isValid(id)) {\n fileState[id].canceled = true;\n self.expunge(id);\n }\n cancelFinalizationEffort.success();\n });\n },\n\n expunge: function(id) {\n delete fileState[id];\n },\n\n getThirdPartyFileId: function(id) {\n return fileState[id].key;\n },\n\n isValid: function(id) {\n return fileState[id] !== undefined;\n },\n\n reset: function() {\n fileState = {};\n },\n\n _getFileState: function(id) {\n return fileState[id];\n },\n\n _setThirdPartyFileId: function(id, thirdPartyFileId) {\n fileState[id].key = thirdPartyFileId;\n },\n\n _wasCanceled: function(id) {\n return !!fileState[id].canceled;\n }\n });\n};\n","/*globals qq*/\n/**\n * Base upload handler module. Controls more specific handlers.\n *\n * @param o Options. Passed along to the specific handler submodule as well.\n * @param namespace [optional] Namespace for the specific handler.\n */\nqq.UploadHandlerController = function(o, namespace) {\n \"use strict\";\n\n var controller = this,\n chunkingPossible = false,\n concurrentChunkingPossible = false,\n chunking, preventRetryResponse, log, handler,\n\n options = {\n paramsStore: {},\n maxConnections: 3, // maximum number of concurrent uploads\n chunking: {\n enabled: false,\n multiple: {\n enabled: false\n }\n },\n log: function(str, level) {},\n onProgress: function(id, fileName, loaded, total) {},\n onComplete: function(id, fileName, response, xhr) {},\n onCancel: function(id, fileName) {},\n onUploadPrep: function(id) {}, // Called if non-trivial operations will be performed before onUpload\n onUpload: function(id, fileName) {},\n onUploadChunk: function(id, fileName, chunkData) {},\n onUploadChunkSuccess: function(id, chunkData, response, xhr) {},\n onAutoRetry: function(id, fileName, response, xhr) {},\n onResume: function(id, fileName, chunkData) {},\n onUuidChanged: function(id, newUuid) {},\n getName: function(id) {},\n setSize: function(id, newSize) {},\n isQueued: function(id) {},\n getIdsInProxyGroup: function(id) {},\n getIdsInBatch: function(id) {}\n },\n\n chunked = {\n // Called when each chunk has uploaded successfully\n done: function(id, chunkIdx, response, xhr) {\n var chunkData = handler._getChunkData(id, chunkIdx);\n\n handler._getFileState(id).attemptingResume = false;\n\n delete handler._getFileState(id).temp.chunkProgress[chunkIdx];\n handler._getFileState(id).loaded += chunkData.size;\n\n options.onUploadChunkSuccess(id, handler._getChunkDataForCallback(chunkData), response, xhr);\n },\n\n // Called when all chunks have been successfully uploaded and we want to ask the handler to perform any\n // logic associated with closing out the file, such as combining the chunks.\n finalize: function(id) {\n var size = options.getSize(id),\n name = options.getName(id);\n\n log(\"All chunks have been uploaded for \" + id + \" - finalizing....\");\n handler.finalizeChunks(id).then(\n function(response, xhr) {\n log(\"Finalize successful for \" + id);\n\n var normaizedResponse = upload.normalizeResponse(response, true);\n\n options.onProgress(id, name, size, size);\n handler._maybeDeletePersistedChunkData(id);\n upload.cleanup(id, normaizedResponse, xhr);\n },\n function(response, xhr) {\n var normaizedResponse = upload.normalizeResponse(response, false);\n\n log(\"Problem finalizing chunks for file ID \" + id + \" - \" + normaizedResponse.error, \"error\");\n\n if (normaizedResponse.reset) {\n chunked.reset(id);\n }\n\n if (!options.onAutoRetry(id, name, normaizedResponse, xhr)) {\n upload.cleanup(id, normaizedResponse, xhr);\n }\n }\n );\n },\n\n handleFailure: function(chunkIdx, id, response, xhr) {\n var name = options.getName(id);\n\n log(\"Chunked upload request failed for \" + id + \", chunk \" + chunkIdx);\n\n handler.clearCachedChunk(id, chunkIdx);\n\n var responseToReport = upload.normalizeResponse(response, false),\n inProgressIdx;\n\n if (responseToReport.reset) {\n chunked.reset(id);\n }\n else {\n inProgressIdx = qq.indexOf(handler._getFileState(id).chunking.inProgress, chunkIdx);\n if (inProgressIdx >= 0) {\n handler._getFileState(id).chunking.inProgress.splice(inProgressIdx, 1);\n handler._getFileState(id).chunking.remaining.unshift(chunkIdx);\n }\n }\n\n // We may have aborted all other in-progress chunks for this file due to a failure.\n // If so, ignore the failures associated with those aborts.\n if (!handler._getFileState(id).temp.ignoreFailure) {\n // If this chunk has failed, we want to ignore all other failures of currently in-progress\n // chunks since they will be explicitly aborted\n if (concurrentChunkingPossible) {\n handler._getFileState(id).temp.ignoreFailure = true;\n\n log(qq.format(\"Going to attempt to abort these chunks: {}. These are currently in-progress: {}.\", JSON.stringify(Object.keys(handler._getXhrs(id))), JSON.stringify(handler._getFileState(id).chunking.inProgress)));\n qq.each(handler._getXhrs(id), function(ckid, ckXhr) {\n log(qq.format(\"Attempting to abort file {}.{}. XHR readyState {}. \", id, ckid, ckXhr.readyState));\n ckXhr.abort();\n // Flag the transport, in case we are waiting for some other async operation\n // to complete before attempting to upload the chunk\n ckXhr._cancelled = true;\n });\n\n // We must indicate that all aborted chunks are no longer in progress\n handler.moveInProgressToRemaining(id);\n\n // Free up any connections used by these chunks, but don't allow any\n // other files to take up the connections (until we have exhausted all auto-retries)\n connectionManager.free(id, true);\n }\n\n if (!options.onAutoRetry(id, name, responseToReport, xhr)) {\n // If one chunk fails, abort all of the others to avoid odd race conditions that occur\n // if a chunk succeeds immediately after one fails before we have determined if the upload\n // is a failure or not.\n upload.cleanup(id, responseToReport, xhr);\n }\n }\n },\n\n hasMoreParts: function(id) {\n return !!handler._getFileState(id).chunking.remaining.length;\n },\n\n nextPart: function(id) {\n var nextIdx = handler._getFileState(id).chunking.remaining.shift();\n\n if (nextIdx >= handler._getTotalChunks(id)) {\n nextIdx = null;\n }\n\n return nextIdx;\n },\n\n reset: function(id) {\n log(\"Server or callback has ordered chunking effort to be restarted on next attempt for item ID \" + id, \"error\");\n\n handler._maybeDeletePersistedChunkData(id);\n handler.reevaluateChunking(id);\n handler._getFileState(id).loaded = 0;\n },\n\n sendNext: function(id) {\n var size = options.getSize(id),\n name = options.getName(id),\n chunkIdx = chunked.nextPart(id),\n chunkData = handler._getChunkData(id, chunkIdx),\n resuming = handler._getFileState(id).attemptingResume,\n inProgressChunks = handler._getFileState(id).chunking.inProgress || [];\n\n if (handler._getFileState(id).loaded == null) {\n handler._getFileState(id).loaded = 0;\n }\n\n // Don't follow-through with the resume attempt if the integrator returns false from onResume\n if (resuming && options.onResume(id, name, chunkData) === false) {\n chunked.reset(id);\n chunkIdx = chunked.nextPart(id);\n chunkData = handler._getChunkData(id, chunkIdx);\n resuming = false;\n }\n\n // If all chunks have already uploaded successfully, we must be re-attempting the finalize step.\n if (chunkIdx == null && inProgressChunks.length === 0) {\n chunked.finalize(id);\n }\n\n // Send the next chunk\n else {\n log(qq.format(\"Sending chunked upload request for item {}.{}, bytes {}-{} of {}.\", id, chunkIdx, chunkData.start + 1, chunkData.end, size));\n options.onUploadChunk(id, name, handler._getChunkDataForCallback(chunkData));\n inProgressChunks.push(chunkIdx);\n handler._getFileState(id).chunking.inProgress = inProgressChunks;\n\n if (concurrentChunkingPossible) {\n connectionManager.open(id, chunkIdx);\n }\n\n if (concurrentChunkingPossible && connectionManager.available() && handler._getFileState(id).chunking.remaining.length) {\n chunked.sendNext(id);\n }\n\n if (chunkData.blob.size === 0) {\n log(qq.format(\"Chunk {} for file {} will not be uploaded, zero sized chunk.\", chunkIdx, id), \"error\");\n chunked.handleFailure(chunkIdx, id, \"File is no longer available\", null);\n }\n else {\n handler.uploadChunk(id, chunkIdx, resuming).then(\n // upload chunk success\n function success(response, xhr) {\n log(\"Chunked upload request succeeded for \" + id + \", chunk \" + chunkIdx);\n\n handler.clearCachedChunk(id, chunkIdx);\n\n var inProgressChunks = handler._getFileState(id).chunking.inProgress || [],\n responseToReport = upload.normalizeResponse(response, true),\n inProgressChunkIdx = qq.indexOf(inProgressChunks, chunkIdx);\n\n log(qq.format(\"Chunk {} for file {} uploaded successfully.\", chunkIdx, id));\n\n chunked.done(id, chunkIdx, responseToReport, xhr);\n\n if (inProgressChunkIdx >= 0) {\n inProgressChunks.splice(inProgressChunkIdx, 1);\n }\n\n handler._maybePersistChunkedState(id);\n\n if (!chunked.hasMoreParts(id) && inProgressChunks.length === 0) {\n chunked.finalize(id);\n }\n else if (chunked.hasMoreParts(id)) {\n chunked.sendNext(id);\n }\n else {\n log(qq.format(\"File ID {} has no more chunks to send and these chunk indexes are still marked as in-progress: {}\", id, JSON.stringify(inProgressChunks)));\n }\n },\n\n // upload chunk failure\n function failure(response, xhr) {\n chunked.handleFailure(chunkIdx, id, response, xhr);\n }\n )\n .done(function() {\n handler.clearXhr(id, chunkIdx);\n });\n }\n }\n }\n },\n\n connectionManager = {\n _open: [],\n _openChunks: {},\n _waiting: [],\n\n available: function() {\n var max = options.maxConnections,\n openChunkEntriesCount = 0,\n openChunksCount = 0;\n\n qq.each(connectionManager._openChunks, function(fileId, openChunkIndexes) {\n openChunkEntriesCount++;\n openChunksCount += openChunkIndexes.length;\n });\n\n return max - (connectionManager._open.length - openChunkEntriesCount + openChunksCount);\n },\n\n /**\n * Removes element from queue, starts upload of next\n */\n free: function(id, dontAllowNext) {\n var allowNext = !dontAllowNext,\n waitingIndex = qq.indexOf(connectionManager._waiting, id),\n connectionsIndex = qq.indexOf(connectionManager._open, id),\n nextId;\n\n delete connectionManager._openChunks[id];\n\n if (upload.getProxyOrBlob(id) instanceof qq.BlobProxy) {\n log(\"Generated blob upload has ended for \" + id + \", disposing generated blob.\");\n delete handler._getFileState(id).file;\n }\n\n // If this file was not consuming a connection, it was just waiting, so remove it from the waiting array\n if (waitingIndex >= 0) {\n connectionManager._waiting.splice(waitingIndex, 1);\n }\n // If this file was consuming a connection, allow the next file to be uploaded\n else if (allowNext && connectionsIndex >= 0) {\n connectionManager._open.splice(connectionsIndex, 1);\n\n nextId = connectionManager._waiting.shift();\n if (nextId >= 0) {\n connectionManager._open.push(nextId);\n upload.start(nextId);\n }\n }\n },\n\n getWaitingOrConnected: function() {\n var waitingOrConnected = [];\n\n // Chunked files may have multiple connections open per chunk (if concurrent chunking is enabled)\n // We need to grab the file ID of any file that has at least one chunk consuming a connection.\n qq.each(connectionManager._openChunks, function(fileId, chunks) {\n if (chunks && chunks.length) {\n waitingOrConnected.push(parseInt(fileId));\n }\n });\n\n // For non-chunked files, only one connection will be consumed per file.\n // This is where we aggregate those file IDs.\n qq.each(connectionManager._open, function(idx, fileId) {\n if (!connectionManager._openChunks[fileId]) {\n waitingOrConnected.push(parseInt(fileId));\n }\n });\n\n // There may be files waiting for a connection.\n waitingOrConnected = waitingOrConnected.concat(connectionManager._waiting);\n\n return waitingOrConnected;\n },\n\n isUsingConnection: function(id) {\n return qq.indexOf(connectionManager._open, id) >= 0;\n },\n\n open: function(id, chunkIdx) {\n if (chunkIdx == null) {\n connectionManager._waiting.push(id);\n }\n\n if (connectionManager.available()) {\n if (chunkIdx == null) {\n connectionManager._waiting.pop();\n connectionManager._open.push(id);\n }\n else {\n (function() {\n var openChunksEntry = connectionManager._openChunks[id] || [];\n openChunksEntry.push(chunkIdx);\n connectionManager._openChunks[id] = openChunksEntry;\n }());\n }\n\n return true;\n }\n\n return false;\n },\n\n reset: function() {\n connectionManager._waiting = [];\n connectionManager._open = [];\n }\n },\n\n simple = {\n send: function(id, name) {\n handler._getFileState(id).loaded = 0;\n\n log(\"Sending simple upload request for \" + id);\n handler.uploadFile(id).then(\n function(response, optXhr) {\n log(\"Simple upload request succeeded for \" + id);\n\n var responseToReport = upload.normalizeResponse(response, true),\n size = options.getSize(id);\n\n options.onProgress(id, name, size, size);\n upload.maybeNewUuid(id, responseToReport);\n upload.cleanup(id, responseToReport, optXhr);\n },\n\n function(response, optXhr) {\n log(\"Simple upload request failed for \" + id);\n\n var responseToReport = upload.normalizeResponse(response, false);\n\n if (!options.onAutoRetry(id, name, responseToReport, optXhr)) {\n upload.cleanup(id, responseToReport, optXhr);\n }\n }\n );\n }\n },\n\n upload = {\n cancel: function(id) {\n log(\"Cancelling \" + id);\n options.paramsStore.remove(id);\n connectionManager.free(id);\n },\n\n cleanup: function(id, response, optXhr) {\n var name = options.getName(id);\n\n options.onComplete(id, name, response, optXhr);\n\n if (handler._getFileState(id)) {\n handler._clearXhrs && handler._clearXhrs(id);\n }\n\n connectionManager.free(id);\n },\n\n // Returns a qq.BlobProxy, or an actual File/Blob if no proxy is involved, or undefined\n // if none of these are available for the ID\n getProxyOrBlob: function(id) {\n return (handler.getProxy && handler.getProxy(id)) ||\n (handler.getFile && handler.getFile(id));\n },\n\n initHandler: function() {\n var handlerType = namespace ? qq[namespace] : qq.traditional,\n handlerModuleSubtype = qq.supportedFeatures.ajaxUploading ? \"Xhr\" : \"Form\";\n\n handler = new handlerType[handlerModuleSubtype + \"UploadHandler\"](\n options,\n {\n getDataByUuid: options.getDataByUuid,\n getName: options.getName,\n getSize: options.getSize,\n getUuid: options.getUuid,\n log: log,\n onCancel: options.onCancel,\n onProgress: options.onProgress,\n onUuidChanged: options.onUuidChanged\n }\n );\n\n if (handler._removeExpiredChunkingRecords) {\n handler._removeExpiredChunkingRecords();\n }\n },\n\n isDeferredEligibleForUpload: function(id) {\n return options.isQueued(id);\n },\n\n // For Blobs that are part of a group of generated images, along with a reference image,\n // this will ensure the blobs in the group are uploaded in the order they were triggered,\n // even if some async processing must be completed on one or more Blobs first.\n maybeDefer: function(id, blob) {\n // If we don't have a file/blob yet & no file/blob exists for this item, request it,\n // and then submit the upload to the specific handler once the blob is available.\n // ASSUMPTION: This condition will only ever be true if XHR uploading is supported.\n if (blob && !handler.getFile(id) && blob instanceof qq.BlobProxy) {\n\n // Blob creation may take some time, so the caller may want to update the\n // UI to indicate that an operation is in progress, even before the actual\n // upload begins and an onUpload callback is invoked.\n options.onUploadPrep(id);\n\n log(\"Attempting to generate a blob on-demand for \" + id);\n blob.create().then(function(generatedBlob) {\n log(\"Generated an on-demand blob for \" + id);\n\n // Update record associated with this file by providing the generated Blob\n handler.updateBlob(id, generatedBlob);\n\n // Propagate the size for this generated Blob\n options.setSize(id, generatedBlob.size);\n\n // Order handler to recalculate chunking possibility, if applicable\n handler.reevaluateChunking(id);\n\n upload.maybeSendDeferredFiles(id);\n },\n\n // Blob could not be generated. Fail the upload & attempt to prevent retries. Also bubble error message.\n function(errorMessage) {\n var errorResponse = {};\n\n if (errorMessage) {\n errorResponse.error = errorMessage;\n }\n\n log(qq.format(\"Failed to generate blob for ID {}. Error message: {}.\", id, errorMessage), \"error\");\n\n options.onComplete(id, options.getName(id), qq.extend(errorResponse, preventRetryResponse), null);\n upload.maybeSendDeferredFiles(id);\n connectionManager.free(id);\n });\n }\n else {\n return upload.maybeSendDeferredFiles(id);\n }\n\n return false;\n },\n\n // Upload any grouped blobs, in the proper order, that are ready to be uploaded\n maybeSendDeferredFiles: function(id) {\n var idsInGroup = options.getIdsInProxyGroup(id),\n uploadedThisId = false;\n\n if (idsInGroup && idsInGroup.length) {\n log(\"Maybe ready to upload proxy group file \" + id);\n\n qq.each(idsInGroup, function(idx, idInGroup) {\n if (upload.isDeferredEligibleForUpload(idInGroup) && !!handler.getFile(idInGroup)) {\n uploadedThisId = idInGroup === id;\n upload.now(idInGroup);\n }\n else if (upload.isDeferredEligibleForUpload(idInGroup)) {\n return false;\n }\n });\n }\n else {\n uploadedThisId = true;\n upload.now(id);\n }\n\n return uploadedThisId;\n },\n\n maybeNewUuid: function(id, response) {\n if (response.newUuid !== undefined) {\n options.onUuidChanged(id, response.newUuid);\n }\n },\n\n // The response coming from handler implementations may be in various formats.\n // Instead of hoping a promise nested 5 levels deep will always return an object\n // as its first param, let's just normalize the response here.\n normalizeResponse: function(originalResponse, successful) {\n var response = originalResponse;\n\n // The passed \"response\" param may not be a response at all.\n // It could be a string, detailing the error, for example.\n if (!qq.isObject(originalResponse)) {\n response = {};\n\n if (qq.isString(originalResponse) && !successful) {\n response.error = originalResponse;\n }\n }\n\n response.success = successful;\n\n return response;\n },\n\n now: function(id) {\n var name = options.getName(id);\n\n if (!controller.isValid(id)) {\n throw new qq.Error(id + \" is not a valid file ID to upload!\");\n }\n\n options.onUpload(id, name);\n\n if (chunkingPossible && handler._shouldChunkThisFile(id)) {\n chunked.sendNext(id);\n }\n else {\n simple.send(id, name);\n }\n },\n\n start: function(id) {\n var blobToUpload = upload.getProxyOrBlob(id);\n\n if (blobToUpload) {\n return upload.maybeDefer(id, blobToUpload);\n }\n else {\n upload.now(id);\n return true;\n }\n }\n };\n\n qq.extend(this, {\n /**\n * Adds file or file input to the queue\n **/\n add: function(id, file) {\n handler.add.apply(this, arguments);\n },\n\n /**\n * Sends the file identified by id\n */\n upload: function(id) {\n if (connectionManager.open(id)) {\n return upload.start(id);\n }\n return false;\n },\n\n retry: function(id) {\n // On retry, if concurrent chunking has been enabled, we may have aborted all other in-progress chunks\n // for a file when encountering a failed chunk upload. We then signaled the controller to ignore\n // all failures associated with these aborts. We are now retrying, so we don't want to ignore\n // any more failures at this point.\n if (concurrentChunkingPossible) {\n handler._getFileState(id).temp.ignoreFailure = false;\n }\n\n // If we are attempting to retry a file that is already consuming a connection, this is likely an auto-retry.\n // Just go ahead and ask the handler to upload again.\n if (connectionManager.isUsingConnection(id)) {\n return upload.start(id);\n }\n\n // If we are attempting to retry a file that is not currently consuming a connection,\n // this is likely a manual retry attempt. We will need to ensure a connection is available\n // before the retry commences.\n else {\n return controller.upload(id);\n }\n },\n\n /**\n * Cancels file upload by id\n */\n cancel: function(id) {\n var cancelRetVal = handler.cancel(id);\n\n if (qq.isGenericPromise(cancelRetVal)) {\n cancelRetVal.then(function() {\n upload.cancel(id);\n });\n }\n else if (cancelRetVal !== false) {\n upload.cancel(id);\n }\n },\n\n /**\n * Cancels all queued or in-progress uploads\n */\n cancelAll: function() {\n var waitingOrConnected = connectionManager.getWaitingOrConnected(),\n i;\n\n // ensure files are cancelled in reverse order which they were added\n // to avoid a flash of time where a queued file begins to upload before it is canceled\n if (waitingOrConnected.length) {\n for (i = waitingOrConnected.length - 1; i >= 0; i--) {\n controller.cancel(waitingOrConnected[i]);\n }\n }\n\n connectionManager.reset();\n },\n\n // Returns a File, Blob, or the Blob/File for the reference/parent file if the targeted blob is a proxy.\n // Undefined if no file record is available.\n getFile: function(id) {\n if (handler.getProxy && handler.getProxy(id)) {\n return handler.getProxy(id).referenceBlob;\n }\n\n return handler.getFile && handler.getFile(id);\n },\n\n // Returns true if the Blob associated with the ID is related to a proxy s\n isProxied: function(id) {\n return !!(handler.getProxy && handler.getProxy(id));\n },\n\n getInput: function(id) {\n if (handler.getInput) {\n return handler.getInput(id);\n }\n },\n\n reset: function() {\n log(\"Resetting upload handler\");\n controller.cancelAll();\n connectionManager.reset();\n handler.reset();\n },\n\n expunge: function(id) {\n if (controller.isValid(id)) {\n return handler.expunge(id);\n }\n },\n\n /**\n * Determine if the file exists.\n */\n isValid: function(id) {\n return handler.isValid(id);\n },\n\n getResumableFilesData: function() {\n if (handler.getResumableFilesData) {\n return handler.getResumableFilesData();\n }\n return [];\n },\n\n /**\n * This may or may not be implemented, depending on the handler. For handlers where a third-party ID is\n * available (such as the \"key\" for Amazon S3), this will return that value. Otherwise, the return value\n * will be undefined.\n *\n * @param id Internal file ID\n * @returns {*} Some identifier used by a 3rd-party service involved in the upload process\n */\n getThirdPartyFileId: function(id) {\n if (controller.isValid(id)) {\n return handler.getThirdPartyFileId(id);\n }\n },\n\n /**\n * Attempts to pause the associated upload if the specific handler supports this and the file is \"valid\".\n * @param id ID of the upload/file to pause\n * @returns {boolean} true if the upload was paused\n */\n pause: function(id) {\n if (controller.isResumable(id) && handler.pause && controller.isValid(id) && handler.pause(id)) {\n connectionManager.free(id);\n handler.moveInProgressToRemaining(id);\n return true;\n }\n return false;\n },\n\n // True if the file is eligible for pause/resume.\n isResumable: function(id) {\n return !!handler.isResumable && handler.isResumable(id);\n }\n });\n\n qq.extend(options, o);\n log = options.log;\n chunkingPossible = options.chunking.enabled && qq.supportedFeatures.chunking;\n concurrentChunkingPossible = chunkingPossible && options.chunking.concurrent.enabled;\n\n preventRetryResponse = (function() {\n var response = {};\n\n response[options.preventRetryParam] = true;\n\n return response;\n }());\n\n upload.initHandler();\n};\n","/*globals qq */\n/*jshint -W117 */\nqq.WindowReceiveMessage = function(o) {\n \"use strict\";\n\n var options = {\n log: function(message, level) {}\n },\n callbackWrapperDetachers = {};\n\n qq.extend(options, o);\n\n qq.extend(this, {\n receiveMessage: function(id, callback) {\n var onMessageCallbackWrapper = function(event) {\n callback(event.data);\n };\n\n if (window.postMessage) {\n callbackWrapperDetachers[id] = qq(window).attach(\"message\", onMessageCallbackWrapper);\n }\n else {\n log(\"iframe message passing not supported in this browser!\", \"error\");\n }\n },\n\n stopReceivingMessages: function(id) {\n if (window.postMessage) {\n var detacher = callbackWrapperDetachers[id];\n if (detacher) {\n detacher();\n }\n }\n }\n });\n};\n","/* globals qq */\n/**\n * Common APIs exposed to creators of upload via form/iframe handlers. This is reused and possibly overridden\n * in some cases by specific form upload handlers.\n *\n * @constructor\n */\nqq.FormUploadHandler = function(spec) {\n \"use strict\";\n\n var options = spec.options,\n handler = this,\n proxy = spec.proxy,\n formHandlerInstanceId = qq.getUniqueId(),\n onloadCallbacks = {},\n detachLoadEvents = {},\n postMessageCallbackTimers = {},\n isCors = options.isCors,\n inputName = options.inputName,\n getUuid = proxy.getUuid,\n log = proxy.log,\n corsMessageReceiver = new qq.WindowReceiveMessage({log: log});\n\n /**\n * Remove any trace of the file from the handler.\n *\n * @param id ID of the associated file\n */\n function expungeFile(id) {\n delete detachLoadEvents[id];\n\n // If we are dealing with CORS, we might still be waiting for a response from a loaded iframe.\n // In that case, terminate the timer waiting for a message from the loaded iframe\n // and stop listening for any more messages coming from this iframe.\n if (isCors) {\n clearTimeout(postMessageCallbackTimers[id]);\n delete postMessageCallbackTimers[id];\n corsMessageReceiver.stopReceivingMessages(id);\n }\n\n var iframe = document.getElementById(handler._getIframeName(id));\n if (iframe) {\n // To cancel request set src to something else. We use src=\"javascript:false;\"\n // because it doesn't trigger ie6 prompt on https\n /* jshint scripturl:true */\n iframe.setAttribute(\"src\", \"javascript:false;\");\n\n qq(iframe).remove();\n }\n }\n\n /**\n * @param iframeName `document`-unique Name of the associated iframe\n * @returns {*} ID of the associated file\n */\n function getFileIdForIframeName(iframeName) {\n return iframeName.split(\"_\")[0];\n }\n\n /**\n * Generates an iframe to be used as a target for upload-related form submits. This also adds the iframe\n * to the current `document`. Note that the iframe is hidden from view.\n *\n * @param name Name of the iframe.\n * @returns {HTMLIFrameElement} The created iframe\n */\n function initIframeForUpload(name) {\n var iframe = qq.toElement(\"\");\n\n iframe.setAttribute(\"id\", name);\n\n iframe.style.display = \"none\";\n document.body.appendChild(iframe);\n\n return iframe;\n }\n\n /**\n * If we are in CORS mode, we must listen for messages (containing the server response) from the associated\n * iframe, since we cannot directly parse the content of the iframe due to cross-origin restrictions.\n *\n * @param iframe Listen for messages on this iframe.\n * @param callback Invoke this callback with the message from the iframe.\n */\n function registerPostMessageCallback(iframe, callback) {\n var iframeName = iframe.id,\n fileId = getFileIdForIframeName(iframeName),\n uuid = getUuid(fileId);\n\n onloadCallbacks[uuid] = callback;\n\n // When the iframe has loaded (after the server responds to an upload request)\n // declare the attempt a failure if we don't receive a valid message shortly after the response comes in.\n detachLoadEvents[fileId] = qq(iframe).attach(\"load\", function() {\n if (handler.getInput(fileId)) {\n log(\"Received iframe load event for CORS upload request (iframe name \" + iframeName + \")\");\n\n postMessageCallbackTimers[iframeName] = setTimeout(function() {\n var errorMessage = \"No valid message received from loaded iframe for iframe name \" + iframeName;\n log(errorMessage, \"error\");\n callback({\n error: errorMessage\n });\n }, 1000);\n }\n });\n\n // Listen for messages coming from this iframe. When a message has been received, cancel the timer\n // that declares the upload a failure if a message is not received within a reasonable amount of time.\n corsMessageReceiver.receiveMessage(iframeName, function(message) {\n log(\"Received the following window message: '\" + message + \"'\");\n var fileId = getFileIdForIframeName(iframeName),\n response = handler._parseJsonResponse(message),\n uuid = response.uuid,\n onloadCallback;\n\n if (uuid && onloadCallbacks[uuid]) {\n log(\"Handling response for iframe name \" + iframeName);\n clearTimeout(postMessageCallbackTimers[iframeName]);\n delete postMessageCallbackTimers[iframeName];\n\n handler._detachLoadEvent(iframeName);\n\n onloadCallback = onloadCallbacks[uuid];\n\n delete onloadCallbacks[uuid];\n corsMessageReceiver.stopReceivingMessages(iframeName);\n onloadCallback(response);\n }\n else if (!uuid) {\n log(\"'\" + message + \"' does not contain a UUID - ignoring.\");\n }\n });\n }\n\n qq.extend(this, new qq.UploadHandler(spec));\n\n qq.override(this, function(super_) {\n return {\n /**\n * Adds File or Blob to the queue\n **/\n add: function(id, fileInput) {\n super_.add(id, {input: fileInput});\n\n fileInput.setAttribute(\"name\", inputName);\n\n // remove file input from DOM\n if (fileInput.parentNode) {\n qq(fileInput).remove();\n }\n },\n\n expunge: function(id) {\n expungeFile(id);\n super_.expunge(id);\n },\n\n isValid: function(id) {\n return super_.isValid(id) &&\n handler._getFileState(id).input !== undefined;\n }\n };\n });\n\n qq.extend(this, {\n getInput: function(id) {\n return handler._getFileState(id).input;\n },\n\n /**\n * This function either delegates to a more specific message handler if CORS is involved,\n * or simply registers a callback when the iframe has been loaded that invokes the passed callback\n * after determining if the content of the iframe is accessible.\n *\n * @param iframe Associated iframe\n * @param callback Callback to invoke after we have determined if the iframe content is accessible.\n */\n _attachLoadEvent: function(iframe, callback) {\n /*jslint eqeq: true*/\n var responseDescriptor;\n\n if (isCors) {\n registerPostMessageCallback(iframe, callback);\n }\n else {\n detachLoadEvents[iframe.id] = qq(iframe).attach(\"load\", function() {\n log(\"Received response for \" + iframe.id);\n\n // when we remove iframe from dom\n // the request stops, but in IE load\n // event fires\n if (!iframe.parentNode) {\n return;\n }\n\n try {\n // fixing Opera 10.53\n if (iframe.contentDocument &&\n iframe.contentDocument.body &&\n iframe.contentDocument.body.innerHTML == \"false\") {\n // In Opera event is fired second time\n // when body.innerHTML changed from false\n // to server response approx. after 1 sec\n // when we upload file with iframe\n return;\n }\n }\n catch (error) {\n //IE may throw an \"access is denied\" error when attempting to access contentDocument on the iframe in some cases\n log(\"Error when attempting to access iframe during handling of upload response (\" + error.message + \")\", \"error\");\n responseDescriptor = {success: false};\n }\n\n callback(responseDescriptor);\n });\n }\n },\n\n /**\n * Creates an iframe with a specific document-unique name.\n *\n * @param id ID of the associated file\n * @returns {HTMLIFrameElement}\n */\n _createIframe: function(id) {\n var iframeName = handler._getIframeName(id);\n\n return initIframeForUpload(iframeName);\n },\n\n /**\n * Called when we are no longer interested in being notified when an iframe has loaded.\n *\n * @param id Associated file ID\n */\n _detachLoadEvent: function(id) {\n if (detachLoadEvents[id] !== undefined) {\n detachLoadEvents[id]();\n delete detachLoadEvents[id];\n }\n },\n\n /**\n * @param fileId ID of the associated file\n * @returns {string} The `document`-unique name of the iframe\n */\n _getIframeName: function(fileId) {\n return fileId + \"_\" + formHandlerInstanceId;\n },\n\n /**\n * Generates a form element and appends it to the `document`. When the form is submitted, a specific iframe is targeted.\n * The name of the iframe is passed in as a property of the spec parameter, and must be unique in the `document`. Note\n * that the form is hidden from view.\n *\n * @param spec An object containing various properties to be used when constructing the form. Required properties are\n * currently: `method`, `endpoint`, `params`, `paramsInBody`, and `targetName`.\n * @returns {HTMLFormElement} The created form\n */\n _initFormForUpload: function(spec) {\n var method = spec.method,\n endpoint = spec.endpoint,\n params = spec.params,\n paramsInBody = spec.paramsInBody,\n targetName = spec.targetName,\n form = qq.toElement(\" \"),\n url = endpoint;\n\n if (paramsInBody) {\n qq.obj2Inputs(params, form);\n }\n else {\n url = qq.obj2url(params, endpoint);\n }\n\n form.setAttribute(\"action\", url);\n form.setAttribute(\"target\", targetName);\n form.style.display = \"none\";\n document.body.appendChild(form);\n\n return form;\n },\n\n /**\n * @param innerHtmlOrMessage JSON message\n * @returns {*} The parsed response, or an empty object if the response could not be parsed\n */\n _parseJsonResponse: function(innerHtmlOrMessage) {\n var response = {};\n\n try {\n response = qq.parseJson(innerHtmlOrMessage);\n }\n catch (error) {\n log(\"Error when attempting to parse iframe upload response (\" + error.message + \")\", \"error\");\n }\n\n return response;\n }\n });\n};\n","/* globals qq */\n/**\n * Common API exposed to creators of XHR handlers. This is reused and possibly overriding in some cases by specific\n * XHR upload handlers.\n *\n * @constructor\n */\nqq.XhrUploadHandler = function(spec) {\n \"use strict\";\n\n var handler = this,\n namespace = spec.options.namespace,\n proxy = spec.proxy,\n chunking = spec.options.chunking,\n resume = spec.options.resume,\n chunkFiles = chunking && spec.options.chunking.enabled && qq.supportedFeatures.chunking,\n resumeEnabled = resume && spec.options.resume.enabled && chunkFiles && qq.supportedFeatures.resume,\n getName = proxy.getName,\n getSize = proxy.getSize,\n getUuid = proxy.getUuid,\n getEndpoint = proxy.getEndpoint,\n getDataByUuid = proxy.getDataByUuid,\n onUuidChanged = proxy.onUuidChanged,\n onProgress = proxy.onProgress,\n log = proxy.log;\n\n function abort(id) {\n qq.each(handler._getXhrs(id), function(xhrId, xhr) {\n var ajaxRequester = handler._getAjaxRequester(id, xhrId);\n\n xhr.onreadystatechange = null;\n xhr.upload.onprogress = null;\n xhr.abort();\n ajaxRequester && ajaxRequester.canceled && ajaxRequester.canceled(id);\n });\n }\n\n qq.extend(this, new qq.UploadHandler(spec));\n\n qq.override(this, function(super_) {\n return {\n /**\n * Adds File or Blob to the queue\n **/\n add: function(id, blobOrProxy) {\n if (qq.isFile(blobOrProxy) || qq.isBlob(blobOrProxy)) {\n super_.add(id, {file: blobOrProxy});\n }\n else if (blobOrProxy instanceof qq.BlobProxy) {\n super_.add(id, {proxy: blobOrProxy});\n }\n else {\n throw new Error(\"Passed obj is not a File, Blob, or proxy\");\n }\n\n handler._initTempState(id);\n resumeEnabled && handler._maybePrepareForResume(id);\n },\n\n expunge: function(id) {\n abort(id);\n handler._maybeDeletePersistedChunkData(id);\n handler._clearXhrs(id);\n super_.expunge(id);\n }\n };\n });\n\n qq.extend(this, {\n // Clear the cached chunk `Blob` after we are done with it, just in case the `Blob` bytes are stored in memory.\n clearCachedChunk: function(id, chunkIdx) {\n delete handler._getFileState(id).temp.cachedChunks[chunkIdx];\n },\n\n clearXhr: function(id, chunkIdx) {\n var tempState = handler._getFileState(id).temp;\n\n if (tempState.xhrs) {\n delete tempState.xhrs[chunkIdx];\n }\n if (tempState.ajaxRequesters) {\n delete tempState.ajaxRequesters[chunkIdx];\n }\n },\n\n // Called when all chunks have been successfully uploaded. Expected promissory return type.\n // This defines the default behavior if nothing further is required when all chunks have been uploaded.\n finalizeChunks: function(id, responseParser) {\n var lastChunkIdx = handler._getTotalChunks(id) - 1,\n xhr = handler._getXhr(id, lastChunkIdx);\n\n if (responseParser) {\n return new qq.Promise().success(responseParser(xhr), xhr);\n }\n\n return new qq.Promise().success({}, xhr);\n },\n\n getFile: function(id) {\n return handler.isValid(id) && handler._getFileState(id).file;\n },\n\n getProxy: function(id) {\n return handler.isValid(id) && handler._getFileState(id).proxy;\n },\n\n /**\n * @returns {Array} Array of objects containing properties useful to integrators\n * when it is important to determine which files are potentially resumable.\n */\n getResumableFilesData: function() {\n var resumableFilesData = [];\n\n handler._iterateResumeRecords(function(key, uploadData) {\n handler.moveInProgressToRemaining(null, uploadData.chunking.inProgress, uploadData.chunking.remaining);\n\n var data = {\n name: uploadData.name,\n remaining: uploadData.chunking.remaining,\n size: uploadData.size,\n uuid: uploadData.uuid\n };\n\n if (uploadData.key) {\n data.key = uploadData.key;\n }\n\n resumableFilesData.push(data);\n });\n\n return resumableFilesData;\n },\n\n isResumable: function(id) {\n return !!chunking && handler.isValid(id) && !handler._getFileState(id).notResumable;\n },\n\n moveInProgressToRemaining: function(id, optInProgress, optRemaining) {\n var inProgress = optInProgress || handler._getFileState(id).chunking.inProgress,\n remaining = optRemaining || handler._getFileState(id).chunking.remaining;\n\n if (inProgress) {\n log(qq.format(\"Moving these chunks from in-progress {}, to remaining.\", JSON.stringify(inProgress)));\n inProgress.reverse();\n qq.each(inProgress, function(idx, chunkIdx) {\n remaining.unshift(chunkIdx);\n });\n inProgress.length = 0;\n }\n },\n\n pause: function(id) {\n if (handler.isValid(id)) {\n log(qq.format(\"Aborting XHR upload for {} '{}' due to pause instruction.\", id, getName(id)));\n handler._getFileState(id).paused = true;\n abort(id);\n return true;\n }\n },\n\n reevaluateChunking: function(id) {\n if (chunking && handler.isValid(id)) {\n var state = handler._getFileState(id),\n totalChunks,\n i;\n\n delete state.chunking;\n\n state.chunking = {};\n totalChunks = handler._getTotalChunks(id);\n if (totalChunks > 1 || chunking.mandatory) {\n state.chunking.enabled = true;\n state.chunking.parts = totalChunks;\n state.chunking.remaining = [];\n\n for (i = 0; i < totalChunks; i++) {\n state.chunking.remaining.push(i);\n }\n\n handler._initTempState(id);\n }\n else {\n state.chunking.enabled = false;\n }\n }\n },\n\n updateBlob: function(id, newBlob) {\n if (handler.isValid(id)) {\n handler._getFileState(id).file = newBlob;\n }\n },\n\n _clearXhrs: function(id) {\n var tempState = handler._getFileState(id).temp;\n\n qq.each(tempState.ajaxRequesters, function(chunkId) {\n delete tempState.ajaxRequesters[chunkId];\n });\n\n qq.each(tempState.xhrs, function(chunkId) {\n delete tempState.xhrs[chunkId];\n });\n },\n\n /**\n * Creates an XHR instance for this file and stores it in the fileState.\n *\n * @param id File ID\n * @param optChunkIdx The chunk index associated with this XHR, if applicable\n * @returns {XMLHttpRequest}\n */\n _createXhr: function(id, optChunkIdx) {\n return handler._registerXhr(id, optChunkIdx, qq.createXhrInstance());\n },\n\n _getAjaxRequester: function(id, optChunkIdx) {\n var chunkIdx = optChunkIdx == null ? -1 : optChunkIdx;\n return handler._getFileState(id).temp.ajaxRequesters[chunkIdx];\n },\n\n _getChunkData: function(id, chunkIndex) {\n var chunkSize = chunking.partSize,\n fileSize = getSize(id),\n fileOrBlob = handler.getFile(id),\n startBytes = chunkSize * chunkIndex,\n endBytes = startBytes + chunkSize >= fileSize ? fileSize : startBytes + chunkSize,\n totalChunks = handler._getTotalChunks(id),\n cachedChunks = this._getFileState(id).temp.cachedChunks,\n\n // To work around a Webkit GC bug, we must keep each chunk `Blob` in scope until we are done with it.\n // See https://github.com/Widen/fine-uploader/issues/937#issuecomment-41418760\n blob = cachedChunks[chunkIndex] || qq.sliceBlob(fileOrBlob, startBytes, endBytes);\n\n cachedChunks[chunkIndex] = blob;\n\n return {\n part: chunkIndex,\n start: startBytes,\n end: endBytes,\n count: totalChunks,\n blob: blob,\n size: endBytes - startBytes\n };\n },\n\n _getChunkDataForCallback: function(chunkData) {\n return {\n partIndex: chunkData.part,\n startByte: chunkData.start + 1,\n endByte: chunkData.end,\n totalParts: chunkData.count\n };\n },\n\n /**\n * @param id File ID\n * @returns {string} Identifier for this item that may appear in the browser's local storage\n */\n _getLocalStorageId: function(id) {\n var formatVersion = \"5.0\",\n name = getName(id),\n size = getSize(id),\n chunkSize = chunking.partSize,\n endpoint = getEndpoint(id);\n\n return qq.format(\"qq{}resume{}-{}-{}-{}-{}\", namespace, formatVersion, name, size, chunkSize, endpoint);\n },\n\n _getMimeType: function(id) {\n return handler.getFile(id).type;\n },\n\n _getPersistableData: function(id) {\n return handler._getFileState(id).chunking;\n },\n\n /**\n * @param id ID of the associated file\n * @returns {number} Number of parts this file can be divided into, or undefined if chunking is not supported in this UA\n */\n _getTotalChunks: function(id) {\n if (chunking) {\n var fileSize = getSize(id),\n chunkSize = chunking.partSize;\n\n return Math.ceil(fileSize / chunkSize);\n }\n },\n\n _getXhr: function(id, optChunkIdx) {\n var chunkIdx = optChunkIdx == null ? -1 : optChunkIdx;\n return handler._getFileState(id).temp.xhrs[chunkIdx];\n },\n\n _getXhrs: function(id) {\n return handler._getFileState(id).temp.xhrs;\n },\n\n // Iterates through all XHR handler-created resume records (in local storage),\n // invoking the passed callback and passing in the key and value of each local storage record.\n _iterateResumeRecords: function(callback) {\n if (resumeEnabled) {\n qq.each(localStorage, function(key, item) {\n if (key.indexOf(qq.format(\"qq{}resume\", namespace)) === 0) {\n var uploadData = JSON.parse(item);\n callback(key, uploadData);\n }\n });\n }\n },\n\n _initTempState: function(id) {\n handler._getFileState(id).temp = {\n ajaxRequesters: {},\n chunkProgress: {},\n xhrs: {},\n cachedChunks: {}\n };\n },\n\n _markNotResumable: function(id) {\n handler._getFileState(id).notResumable = true;\n },\n\n // Removes a chunked upload record from local storage, if possible.\n // Returns true if the item was removed, false otherwise.\n _maybeDeletePersistedChunkData: function(id) {\n var localStorageId;\n\n if (resumeEnabled && handler.isResumable(id)) {\n localStorageId = handler._getLocalStorageId(id);\n\n if (localStorageId && localStorage.getItem(localStorageId)) {\n localStorage.removeItem(localStorageId);\n return true;\n }\n }\n\n return false;\n },\n\n // If this is a resumable upload, grab the relevant data from storage and items in memory that track this upload\n // so we can pick up from where we left off.\n _maybePrepareForResume: function(id) {\n var state = handler._getFileState(id),\n localStorageId, persistedData;\n\n // Resume is enabled and possible and this is the first time we've tried to upload this file in this session,\n // so prepare for a resume attempt.\n if (resumeEnabled && state.key === undefined) {\n localStorageId = handler._getLocalStorageId(id);\n persistedData = localStorage.getItem(localStorageId);\n\n // If we found this item in local storage, maybe we should resume it.\n if (persistedData) {\n persistedData = JSON.parse(persistedData);\n\n // If we found a resume record but we have already handled this file in this session,\n // don't try to resume it & ensure we don't persist future check data\n if (getDataByUuid(persistedData.uuid)) {\n handler._markNotResumable(id);\n }\n else {\n log(qq.format(\"Identified file with ID {} and name of {} as resumable.\", id, getName(id)));\n\n onUuidChanged(id, persistedData.uuid);\n\n state.key = persistedData.key;\n state.chunking = persistedData.chunking;\n state.loaded = persistedData.loaded;\n state.attemptingResume = true;\n\n handler.moveInProgressToRemaining(id);\n }\n }\n }\n },\n\n // Persist any data needed to resume this upload in a new session.\n _maybePersistChunkedState: function(id) {\n var state = handler._getFileState(id),\n localStorageId, persistedData;\n\n // If local storage isn't supported by the browser, or if resume isn't enabled or possible, give up\n if (resumeEnabled && handler.isResumable(id)) {\n localStorageId = handler._getLocalStorageId(id);\n\n persistedData = {\n name: getName(id),\n size: getSize(id),\n uuid: getUuid(id),\n key: state.key,\n chunking: state.chunking,\n loaded: state.loaded,\n lastUpdated: Date.now()\n };\n\n try {\n localStorage.setItem(localStorageId, JSON.stringify(persistedData));\n }\n catch (error) {\n log(qq.format(\"Unable to save resume data for '{}' due to error: '{}'.\", id, error.toString()), \"warn\");\n }\n }\n },\n\n _registerProgressHandler: function(id, chunkIdx, chunkSize) {\n var xhr = handler._getXhr(id, chunkIdx),\n name = getName(id),\n progressCalculator = {\n simple: function(loaded, total) {\n var fileSize = getSize(id);\n\n if (loaded === total) {\n onProgress(id, name, fileSize, fileSize);\n }\n else {\n onProgress(id, name, (loaded >= fileSize ? fileSize - 1 : loaded), fileSize);\n }\n },\n\n chunked: function(loaded, total) {\n var chunkProgress = handler._getFileState(id).temp.chunkProgress,\n totalSuccessfullyLoadedForFile = handler._getFileState(id).loaded,\n loadedForRequest = loaded,\n totalForRequest = total,\n totalFileSize = getSize(id),\n estActualChunkLoaded = loadedForRequest - (totalForRequest - chunkSize),\n totalLoadedForFile = totalSuccessfullyLoadedForFile;\n\n chunkProgress[chunkIdx] = estActualChunkLoaded;\n\n qq.each(chunkProgress, function(chunkIdx, chunkLoaded) {\n totalLoadedForFile += chunkLoaded;\n });\n\n onProgress(id, name, totalLoadedForFile, totalFileSize);\n }\n };\n\n xhr.upload.onprogress = function(e) {\n if (e.lengthComputable) {\n /* jshint eqnull: true */\n var type = chunkSize == null ? \"simple\" : \"chunked\";\n progressCalculator[type](e.loaded, e.total);\n }\n };\n },\n\n /**\n * Registers an XHR transport instance created elsewhere.\n *\n * @param id ID of the associated file\n * @param optChunkIdx The chunk index associated with this XHR, if applicable\n * @param xhr XMLHttpRequest object instance\n * @param optAjaxRequester `qq.AjaxRequester` associated with this request, if applicable.\n * @returns {XMLHttpRequest}\n */\n _registerXhr: function(id, optChunkIdx, xhr, optAjaxRequester) {\n var xhrsId = optChunkIdx == null ? -1 : optChunkIdx,\n tempState = handler._getFileState(id).temp;\n\n tempState.xhrs = tempState.xhrs || {};\n tempState.ajaxRequesters = tempState.ajaxRequesters || {};\n\n tempState.xhrs[xhrsId] = xhr;\n\n if (optAjaxRequester) {\n tempState.ajaxRequesters[xhrsId] = optAjaxRequester;\n }\n\n return xhr;\n },\n\n // Deletes any local storage records that are \"expired\".\n _removeExpiredChunkingRecords: function() {\n var expirationDays = resume.recordsExpireIn;\n\n handler._iterateResumeRecords(function(key, uploadData) {\n var expirationDate = new Date(uploadData.lastUpdated);\n\n // transform updated date into expiration date\n expirationDate.setDate(expirationDate.getDate() + expirationDays);\n\n if (expirationDate.getTime() <= Date.now()) {\n log(\"Removing expired resume record with key \" + key);\n localStorage.removeItem(key);\n }\n });\n },\n\n /**\n * Determine if the associated file should be chunked.\n *\n * @param id ID of the associated file\n * @returns {*} true if chunking is enabled, possible, and the file can be split into more than 1 part\n */\n _shouldChunkThisFile: function(id) {\n var state = handler._getFileState(id);\n\n if (!state.chunking) {\n handler.reevaluateChunking(id);\n }\n\n return state.chunking.enabled;\n }\n });\n};\n","/*globals qq, XMLHttpRequest*/\nqq.DeleteFileAjaxRequester = function(o) {\n \"use strict\";\n\n var requester,\n options = {\n method: \"DELETE\",\n uuidParamName: \"qquuid\",\n endpointStore: {},\n maxConnections: 3,\n customHeaders: function(id) {return {};},\n paramsStore: {},\n cors: {\n expected: false,\n sendCredentials: false\n },\n log: function(str, level) {},\n onDelete: function(id) {},\n onDeleteComplete: function(id, xhrOrXdr, isError) {}\n };\n\n qq.extend(options, o);\n\n function getMandatedParams() {\n if (options.method.toUpperCase() === \"POST\") {\n return {\n _method: \"DELETE\"\n };\n }\n\n return {};\n }\n\n requester = qq.extend(this, new qq.AjaxRequester({\n acceptHeader: \"application/json\",\n validMethods: [\"POST\", \"DELETE\"],\n method: options.method,\n endpointStore: options.endpointStore,\n paramsStore: options.paramsStore,\n mandatedParams: getMandatedParams(),\n maxConnections: options.maxConnections,\n customHeaders: function(id) {\n return options.customHeaders.get(id);\n },\n log: options.log,\n onSend: options.onDelete,\n onComplete: options.onDeleteComplete,\n cors: options.cors\n }));\n\n qq.extend(this, {\n sendDelete: function(id, uuid, additionalMandatedParams) {\n var additionalOptions = additionalMandatedParams || {};\n\n options.log(\"Submitting delete file request for \" + id);\n\n if (options.method === \"DELETE\") {\n requester.initTransport(id)\n .withPath(uuid)\n .withParams(additionalOptions)\n .send();\n }\n else {\n additionalOptions[options.uuidParamName] = uuid;\n requester.initTransport(id)\n .withParams(additionalOptions)\n .send();\n }\n }\n });\n};\n","/*global qq, define */\n/*jshint strict:false,bitwise:false,nonew:false,asi:true,-W064,-W116,-W089 */\n/**\n * Mega pixel image rendering library for iOS6+\n *\n * Fixes iOS6+'s image file rendering issue for large size image (over mega-pixel),\n * which causes unexpected subsampling when drawing it in canvas.\n * By using this library, you can safely render the image with proper stretching.\n *\n * Copyright (c) 2012 Shinichi Tomita \n * Released under the MIT license\n *\n * Heavily modified by Widen for Fine Uploader\n */\n(function() {\n\n /**\n * Detect subsampling in loaded image.\n * In iOS, larger images than 2M pixels may be subsampled in rendering.\n */\n function detectSubsampling(img) {\n var iw = img.naturalWidth,\n ih = img.naturalHeight,\n canvas = document.createElement(\"canvas\"),\n ctx;\n\n if (iw * ih > 1024 * 1024) { // subsampling may happen over megapixel image\n canvas.width = canvas.height = 1;\n ctx = canvas.getContext(\"2d\");\n ctx.drawImage(img, -iw + 1, 0);\n // subsampled image becomes half smaller in rendering size.\n // check alpha channel value to confirm image is covering edge pixel or not.\n // if alpha value is 0 image is not covering, hence subsampled.\n return ctx.getImageData(0, 0, 1, 1).data[3] === 0;\n } else {\n return false;\n }\n }\n\n /**\n * Detecting vertical squash in loaded image.\n * Fixes a bug which squash image vertically while drawing into canvas for some images.\n */\n function detectVerticalSquash(img, iw, ih) {\n var canvas = document.createElement(\"canvas\"),\n sy = 0,\n ey = ih,\n py = ih,\n ctx, data, alpha, ratio;\n\n canvas.width = 1;\n canvas.height = ih;\n ctx = canvas.getContext(\"2d\");\n ctx.drawImage(img, 0, 0);\n data = ctx.getImageData(0, 0, 1, ih).data;\n\n // search image edge pixel position in case it is squashed vertically.\n while (py > sy) {\n alpha = data[(py - 1) * 4 + 3];\n if (alpha === 0) {\n ey = py;\n } else {\n sy = py;\n }\n py = (ey + sy) >> 1;\n }\n\n ratio = (py / ih);\n return (ratio === 0) ? 1 : ratio;\n }\n\n /**\n * Rendering image element (with resizing) and get its data URL\n */\n function renderImageToDataURL(img, blob, options, doSquash) {\n var canvas = document.createElement(\"canvas\"),\n mime = options.mime || \"image/jpeg\",\n promise = new qq.Promise();\n\n renderImageToCanvas(img, blob, canvas, options, doSquash)\n .then(function() {\n promise.success(\n canvas.toDataURL(mime, options.quality || 0.8)\n );\n });\n\n return promise;\n }\n\n function maybeCalculateDownsampledDimensions(spec) {\n var maxPixels = 5241000; //iOS specific value\n\n if (!qq.ios()) {\n throw new qq.Error(\"Downsampled dimensions can only be reliably calculated for iOS!\");\n }\n\n if (spec.origHeight * spec.origWidth > maxPixels) {\n return {\n newHeight: Math.round(Math.sqrt(maxPixels * (spec.origHeight / spec.origWidth))),\n newWidth: Math.round(Math.sqrt(maxPixels * (spec.origWidth / spec.origHeight)))\n };\n }\n }\n\n /**\n * Rendering image element (with resizing) into the canvas element\n */\n function renderImageToCanvas(img, blob, canvas, options, doSquash) {\n var iw = img.naturalWidth,\n ih = img.naturalHeight,\n width = options.width,\n height = options.height,\n ctx = canvas.getContext(\"2d\"),\n promise = new qq.Promise(),\n modifiedDimensions;\n\n ctx.save();\n\n if (options.resize) {\n return renderImageToCanvasWithCustomResizer({\n blob: blob,\n canvas: canvas,\n image: img,\n imageHeight: ih,\n imageWidth: iw,\n orientation: options.orientation,\n resize: options.resize,\n targetHeight: height,\n targetWidth: width\n });\n }\n\n if (!qq.supportedFeatures.unlimitedScaledImageSize) {\n modifiedDimensions = maybeCalculateDownsampledDimensions({\n origWidth: width,\n origHeight: height\n });\n\n if (modifiedDimensions) {\n qq.log(qq.format(\"Had to reduce dimensions due to device limitations from {}w / {}h to {}w / {}h\",\n width, height, modifiedDimensions.newWidth, modifiedDimensions.newHeight),\n \"warn\");\n\n width = modifiedDimensions.newWidth;\n height = modifiedDimensions.newHeight;\n }\n }\n\n transformCoordinate(canvas, width, height, options.orientation);\n\n // Fine Uploader specific: Save some CPU cycles if not using iOS\n // Assumption: This logic is only needed to overcome iOS image sampling issues\n if (qq.ios()) {\n (function() {\n if (detectSubsampling(img)) {\n iw /= 2;\n ih /= 2;\n }\n\n var d = 1024, // size of tiling canvas\n tmpCanvas = document.createElement(\"canvas\"),\n vertSquashRatio = doSquash ? detectVerticalSquash(img, iw, ih) : 1,\n dw = Math.ceil(d * width / iw),\n dh = Math.ceil(d * height / ih / vertSquashRatio),\n sy = 0,\n dy = 0,\n tmpCtx, sx, dx;\n\n tmpCanvas.width = tmpCanvas.height = d;\n tmpCtx = tmpCanvas.getContext(\"2d\");\n\n while (sy < ih) {\n sx = 0;\n dx = 0;\n while (sx < iw) {\n tmpCtx.clearRect(0, 0, d, d);\n tmpCtx.drawImage(img, -sx, -sy);\n ctx.drawImage(tmpCanvas, 0, 0, d, d, dx, dy, dw, dh);\n sx += d;\n dx += dw;\n }\n sy += d;\n dy += dh;\n }\n ctx.restore();\n tmpCanvas = tmpCtx = null;\n }());\n }\n else {\n ctx.drawImage(img, 0, 0, width, height);\n }\n\n canvas.qqImageRendered && canvas.qqImageRendered();\n promise.success();\n\n return promise;\n }\n\n function renderImageToCanvasWithCustomResizer(resizeInfo) {\n var blob = resizeInfo.blob,\n image = resizeInfo.image,\n imageHeight = resizeInfo.imageHeight,\n imageWidth = resizeInfo.imageWidth,\n orientation = resizeInfo.orientation,\n promise = new qq.Promise(),\n resize = resizeInfo.resize,\n sourceCanvas = document.createElement(\"canvas\"),\n sourceCanvasContext = sourceCanvas.getContext(\"2d\"),\n targetCanvas = resizeInfo.canvas,\n targetHeight = resizeInfo.targetHeight,\n targetWidth = resizeInfo.targetWidth;\n\n transformCoordinate(sourceCanvas, imageWidth, imageHeight, orientation);\n\n targetCanvas.height = targetHeight;\n targetCanvas.width = targetWidth;\n\n sourceCanvasContext.drawImage(image, 0, 0);\n\n resize({\n blob: blob,\n height: targetHeight,\n image: image,\n sourceCanvas: sourceCanvas,\n targetCanvas: targetCanvas,\n width: targetWidth\n })\n .then(\n function success() {\n targetCanvas.qqImageRendered && targetCanvas.qqImageRendered();\n promise.success();\n },\n promise.failure\n );\n\n return promise;\n }\n\n /**\n * Transform canvas coordination according to specified frame size and orientation\n * Orientation value is from EXIF tag\n */\n function transformCoordinate(canvas, width, height, orientation) {\n switch (orientation) {\n case 5:\n case 6:\n case 7:\n case 8:\n canvas.width = height;\n canvas.height = width;\n break;\n default:\n canvas.width = width;\n canvas.height = height;\n }\n var ctx = canvas.getContext(\"2d\");\n switch (orientation) {\n case 2:\n // horizontal flip\n ctx.translate(width, 0);\n ctx.scale(-1, 1);\n break;\n case 3:\n // 180 rotate left\n ctx.translate(width, height);\n ctx.rotate(Math.PI);\n break;\n case 4:\n // vertical flip\n ctx.translate(0, height);\n ctx.scale(1, -1);\n break;\n case 5:\n // vertical flip + 90 rotate right\n ctx.rotate(0.5 * Math.PI);\n ctx.scale(1, -1);\n break;\n case 6:\n // 90 rotate right\n ctx.rotate(0.5 * Math.PI);\n ctx.translate(0, -height);\n break;\n case 7:\n // horizontal flip + 90 rotate right\n ctx.rotate(0.5 * Math.PI);\n ctx.translate(width, -height);\n ctx.scale(-1, 1);\n break;\n case 8:\n // 90 rotate left\n ctx.rotate(-0.5 * Math.PI);\n ctx.translate(-width, 0);\n break;\n default:\n break;\n }\n }\n\n /**\n * MegaPixImage class\n */\n function MegaPixImage(srcImage, errorCallback) {\n var self = this;\n\n if (window.Blob && srcImage instanceof Blob) {\n (function() {\n var img = new Image(),\n URL = window.URL && window.URL.createObjectURL ? window.URL :\n window.webkitURL && window.webkitURL.createObjectURL ? window.webkitURL : null;\n if (!URL) { throw Error(\"No createObjectURL function found to create blob url\"); }\n img.src = URL.createObjectURL(srcImage);\n self.blob = srcImage;\n srcImage = img;\n }());\n }\n if (!srcImage.naturalWidth && !srcImage.naturalHeight) {\n srcImage.onload = function() {\n var listeners = self.imageLoadListeners;\n if (listeners) {\n self.imageLoadListeners = null;\n // IE11 doesn't reliably report actual image dimensions immediately after onload for small files,\n // so let's push this to the end of the UI thread queue.\n setTimeout(function() {\n for (var i = 0, len = listeners.length; i < len; i++) {\n listeners[i]();\n }\n }, 0);\n }\n };\n srcImage.onerror = errorCallback;\n this.imageLoadListeners = [];\n }\n this.srcImage = srcImage;\n }\n\n /**\n * Rendering megapix image into specified target element\n */\n MegaPixImage.prototype.render = function(target, options) {\n options = options || {};\n\n var self = this,\n imgWidth = this.srcImage.naturalWidth,\n imgHeight = this.srcImage.naturalHeight,\n width = options.width,\n height = options.height,\n maxWidth = options.maxWidth,\n maxHeight = options.maxHeight,\n doSquash = !this.blob || this.blob.type === \"image/jpeg\",\n tagName = target.tagName.toLowerCase(),\n opt;\n\n if (this.imageLoadListeners) {\n this.imageLoadListeners.push(function() { self.render(target, options); });\n return;\n }\n\n if (width && !height) {\n height = (imgHeight * width / imgWidth) << 0;\n } else if (height && !width) {\n width = (imgWidth * height / imgHeight) << 0;\n } else {\n width = imgWidth;\n height = imgHeight;\n }\n if (maxWidth && width > maxWidth) {\n width = maxWidth;\n height = (imgHeight * width / imgWidth) << 0;\n }\n if (maxHeight && height > maxHeight) {\n height = maxHeight;\n width = (imgWidth * height / imgHeight) << 0;\n }\n\n opt = { width: width, height: height },\n qq.each(options, function(optionsKey, optionsValue) {\n opt[optionsKey] = optionsValue;\n });\n\n if (tagName === \"img\") {\n (function() {\n var oldTargetSrc = target.src;\n renderImageToDataURL(self.srcImage, self.blob, opt, doSquash)\n .then(function(dataUri) {\n target.src = dataUri;\n oldTargetSrc === target.src && target.onload();\n });\n }());\n } else if (tagName === \"canvas\") {\n renderImageToCanvas(this.srcImage, this.blob, target, opt, doSquash);\n }\n if (typeof this.onrender === \"function\") {\n this.onrender(target);\n }\n };\n\n qq.MegaPixImage = MegaPixImage;\n})();\n","/*globals qq */\n/**\n * Draws a thumbnail of a Blob/File/URL onto an or .\n *\n * @constructor\n */\nqq.ImageGenerator = function(log) {\n \"use strict\";\n\n function isImg(el) {\n return el.tagName.toLowerCase() === \"img\";\n }\n\n function isCanvas(el) {\n return el.tagName.toLowerCase() === \"canvas\";\n }\n\n function isImgCorsSupported() {\n return new Image().crossOrigin !== undefined;\n }\n\n function isCanvasSupported() {\n var canvas = document.createElement(\"canvas\");\n\n return canvas.getContext && canvas.getContext(\"2d\");\n }\n\n // This is only meant to determine the MIME type of a renderable image file.\n // It is used to ensure images drawn from a URL that have transparent backgrounds\n // are rendered correctly, among other things.\n function determineMimeOfFileName(nameWithPath) {\n /*jshint -W015 */\n var pathSegments = nameWithPath.split(\"/\"),\n name = pathSegments[pathSegments.length - 1].split(\"?\")[0],\n extension = qq.getExtension(name);\n\n extension = extension && extension.toLowerCase();\n\n switch (extension) {\n case \"jpeg\":\n case \"jpg\":\n return \"image/jpeg\";\n case \"png\":\n return \"image/png\";\n case \"bmp\":\n return \"image/bmp\";\n case \"gif\":\n return \"image/gif\";\n case \"tiff\":\n case \"tif\":\n return \"image/tiff\";\n }\n }\n\n // This will likely not work correctly in IE8 and older.\n // It's only used as part of a formula to determine\n // if a canvas can be used to scale a server-hosted thumbnail.\n // If canvas isn't supported by the UA (IE8 and older)\n // this method should not even be called.\n function isCrossOrigin(url) {\n var targetAnchor = document.createElement(\"a\"),\n targetProtocol, targetHostname, targetPort;\n\n targetAnchor.href = url;\n\n targetProtocol = targetAnchor.protocol;\n targetPort = targetAnchor.port;\n targetHostname = targetAnchor.hostname;\n\n if (targetProtocol.toLowerCase() !== window.location.protocol.toLowerCase()) {\n return true;\n }\n\n if (targetHostname.toLowerCase() !== window.location.hostname.toLowerCase()) {\n return true;\n }\n\n // IE doesn't take ports into consideration when determining if two endpoints are same origin.\n if (targetPort !== window.location.port && !qq.ie()) {\n return true;\n }\n\n return false;\n }\n\n function registerImgLoadListeners(img, promise) {\n img.onload = function() {\n img.onload = null;\n img.onerror = null;\n promise.success(img);\n };\n\n img.onerror = function() {\n img.onload = null;\n img.onerror = null;\n log(\"Problem drawing thumbnail!\", \"error\");\n promise.failure(img, \"Problem drawing thumbnail!\");\n };\n }\n\n function registerCanvasDrawImageListener(canvas, promise) {\n // The image is drawn on the canvas by a third-party library,\n // and we want to know when this is completed. Since the library\n // may invoke drawImage many times in a loop, we need to be called\n // back when the image is fully rendered. So, we are expecting the\n // code that draws this image to follow a convention that involves a\n // function attached to the canvas instance be invoked when it is done.\n canvas.qqImageRendered = function() {\n promise.success(canvas);\n };\n }\n\n // Fulfills a `qq.Promise` when an image has been drawn onto the target,\n // whether that is a or an . The attempt is considered a\n // failure if the target is not an or a , or if the drawing\n // attempt was not successful.\n function registerThumbnailRenderedListener(imgOrCanvas, promise) {\n var registered = isImg(imgOrCanvas) || isCanvas(imgOrCanvas);\n\n if (isImg(imgOrCanvas)) {\n registerImgLoadListeners(imgOrCanvas, promise);\n }\n else if (isCanvas(imgOrCanvas)) {\n registerCanvasDrawImageListener(imgOrCanvas, promise);\n }\n else {\n promise.failure(imgOrCanvas);\n log(qq.format(\"Element container of type {} is not supported!\", imgOrCanvas.tagName), \"error\");\n }\n\n return registered;\n }\n\n // Draw a preview iff the current UA can natively display it.\n // Also rotate the image if necessary.\n function draw(fileOrBlob, container, options) {\n var drawPreview = new qq.Promise(),\n identifier = new qq.Identify(fileOrBlob, log),\n maxSize = options.maxSize,\n // jshint eqnull:true\n orient = options.orient == null ? true : options.orient,\n megapixErrorHandler = function() {\n container.onerror = null;\n container.onload = null;\n log(\"Could not render preview, file may be too large!\", \"error\");\n drawPreview.failure(container, \"Browser cannot render image!\");\n };\n\n identifier.isPreviewable().then(\n function(mime) {\n // If options explicitly specify that Orientation is not desired,\n // replace the orient task with a dummy promise that \"succeeds\" immediately.\n var dummyExif = {\n parse: function() {\n return new qq.Promise().success();\n }\n },\n exif = orient ? new qq.Exif(fileOrBlob, log) : dummyExif,\n mpImg = new qq.MegaPixImage(fileOrBlob, megapixErrorHandler);\n\n if (registerThumbnailRenderedListener(container, drawPreview)) {\n exif.parse().then(\n function(exif) {\n var orientation = exif && exif.Orientation;\n\n mpImg.render(container, {\n maxWidth: maxSize,\n maxHeight: maxSize,\n orientation: orientation,\n mime: mime,\n resize: options.customResizeFunction\n });\n },\n\n function(failureMsg) {\n log(qq.format(\"EXIF data could not be parsed ({}). Assuming orientation = 1.\", failureMsg));\n\n mpImg.render(container, {\n maxWidth: maxSize,\n maxHeight: maxSize,\n mime: mime,\n resize: options.customResizeFunction\n });\n }\n );\n }\n },\n\n function() {\n log(\"Not previewable\");\n drawPreview.failure(container, \"Not previewable\");\n }\n );\n\n return drawPreview;\n }\n\n function drawOnCanvasOrImgFromUrl(url, canvasOrImg, draw, maxSize, customResizeFunction) {\n var tempImg = new Image(),\n tempImgRender = new qq.Promise();\n\n registerThumbnailRenderedListener(tempImg, tempImgRender);\n\n if (isCrossOrigin(url)) {\n tempImg.crossOrigin = \"anonymous\";\n }\n\n tempImg.src = url;\n\n tempImgRender.then(\n function rendered() {\n registerThumbnailRenderedListener(canvasOrImg, draw);\n\n var mpImg = new qq.MegaPixImage(tempImg);\n mpImg.render(canvasOrImg, {\n maxWidth: maxSize,\n maxHeight: maxSize,\n mime: determineMimeOfFileName(url),\n resize: customResizeFunction\n });\n },\n\n draw.failure\n );\n }\n\n function drawOnImgFromUrlWithCssScaling(url, img, draw, maxSize) {\n registerThumbnailRenderedListener(img, draw);\n // NOTE: The fact that maxWidth/height is set on the thumbnail for scaled images\n // that must drop back to CSS is known and exploited by the templating module.\n // In this module, we pre-render \"waiting\" thumbs for all files immediately after they\n // are submitted, and we must be sure to pass any style associated with the \"waiting\" preview.\n qq(img).css({\n maxWidth: maxSize + \"px\",\n maxHeight: maxSize + \"px\"\n });\n\n img.src = url;\n }\n\n // Draw a (server-hosted) thumbnail given a URL.\n // This will optionally scale the thumbnail as well.\n // It attempts to use to scale, but will fall back\n // to max-width and max-height style properties if the UA\n // doesn't support canvas or if the images is cross-domain and\n // the UA doesn't support the crossorigin attribute on img tags,\n // which is required to scale a cross-origin image using &\n // then export it back to an .\n function drawFromUrl(url, container, options) {\n var draw = new qq.Promise(),\n scale = options.scale,\n maxSize = scale ? options.maxSize : null;\n\n // container is an img, scaling needed\n if (scale && isImg(container)) {\n // Iff canvas is available in this UA, try to use it for scaling.\n // Otherwise, fall back to CSS scaling\n if (isCanvasSupported()) {\n // Attempt to use for image scaling,\n // but we must fall back to scaling via CSS/styles\n // if this is a cross-origin image and the UA doesn't support CORS.\n if (isCrossOrigin(url) && !isImgCorsSupported()) {\n drawOnImgFromUrlWithCssScaling(url, container, draw, maxSize);\n }\n else {\n drawOnCanvasOrImgFromUrl(url, container, draw, maxSize);\n }\n }\n else {\n drawOnImgFromUrlWithCssScaling(url, container, draw, maxSize);\n }\n }\n // container is a canvas, scaling optional\n else if (isCanvas(container)) {\n drawOnCanvasOrImgFromUrl(url, container, draw, maxSize);\n }\n // container is an img & no scaling: just set the src attr to the passed url\n else if (registerThumbnailRenderedListener(container, draw)) {\n container.src = url;\n }\n\n return draw;\n }\n\n qq.extend(this, {\n /**\n * Generate a thumbnail. Depending on the arguments, this may either result in\n * a client-side rendering of an image (if a `Blob` is supplied) or a server-generated\n * image that may optionally be scaled client-side using or CSS/styles (as a fallback).\n *\n * @param fileBlobOrUrl a `File`, `Blob`, or a URL pointing to the image\n * @param container or to contain the preview\n * @param options possible properties include `maxSize` (int), `orient` (bool - default true), resize` (bool - default true), and `customResizeFunction`.\n * @returns qq.Promise fulfilled when the preview has been drawn, or the attempt has failed\n */\n generate: function(fileBlobOrUrl, container, options) {\n if (qq.isString(fileBlobOrUrl)) {\n log(\"Attempting to update thumbnail based on server response.\");\n return drawFromUrl(fileBlobOrUrl, container, options || {});\n }\n else {\n log(\"Attempting to draw client-side image preview.\");\n return draw(fileBlobOrUrl, container, options || {});\n }\n }\n });\n\n /**/\n this._testing = {};\n this._testing.isImg = isImg;\n this._testing.isCanvas = isCanvas;\n this._testing.isCrossOrigin = isCrossOrigin;\n this._testing.determineMimeOfFileName = determineMimeOfFileName;\n /* */\n};\n","/*globals qq */\n/**\n * EXIF image data parser. Currently only parses the Orientation tag value,\n * but this may be expanded to other tags in the future.\n *\n * @param fileOrBlob Attempt to parse EXIF data in this `Blob`\n * @constructor\n */\nqq.Exif = function(fileOrBlob, log) {\n \"use strict\";\n\n // Orientation is the only tag parsed here at this time.\n var TAG_IDS = [274],\n TAG_INFO = {\n 274: {\n name: \"Orientation\",\n bytes: 2\n }\n };\n\n // Convert a little endian (hex string) to big endian (decimal).\n function parseLittleEndian(hex) {\n var result = 0,\n pow = 0;\n\n while (hex.length > 0) {\n result += parseInt(hex.substring(0, 2), 16) * Math.pow(2, pow);\n hex = hex.substring(2, hex.length);\n pow += 8;\n }\n\n return result;\n }\n\n // Find the byte offset, of Application Segment 1 (EXIF).\n // External callers need not supply any arguments.\n function seekToApp1(offset, promise) {\n var theOffset = offset,\n thePromise = promise;\n if (theOffset === undefined) {\n theOffset = 2;\n thePromise = new qq.Promise();\n }\n\n qq.readBlobToHex(fileOrBlob, theOffset, 4).then(function(hex) {\n var match = /^ffe([0-9])/.exec(hex),\n segmentLength;\n\n if (match) {\n if (match[1] !== \"1\") {\n segmentLength = parseInt(hex.slice(4, 8), 16);\n seekToApp1(theOffset + segmentLength + 2, thePromise);\n }\n else {\n thePromise.success(theOffset);\n }\n }\n else {\n thePromise.failure(\"No EXIF header to be found!\");\n }\n });\n\n return thePromise;\n }\n\n // Find the byte offset of Application Segment 1 (EXIF) for valid JPEGs only.\n function getApp1Offset() {\n var promise = new qq.Promise();\n\n qq.readBlobToHex(fileOrBlob, 0, 6).then(function(hex) {\n if (hex.indexOf(\"ffd8\") !== 0) {\n promise.failure(\"Not a valid JPEG!\");\n }\n else {\n seekToApp1().then(function(offset) {\n promise.success(offset);\n },\n function(error) {\n promise.failure(error);\n });\n }\n });\n\n return promise;\n }\n\n // Determine the byte ordering of the EXIF header.\n function isLittleEndian(app1Start) {\n var promise = new qq.Promise();\n\n qq.readBlobToHex(fileOrBlob, app1Start + 10, 2).then(function(hex) {\n promise.success(hex === \"4949\");\n });\n\n return promise;\n }\n\n // Determine the number of directory entries in the EXIF header.\n function getDirEntryCount(app1Start, littleEndian) {\n var promise = new qq.Promise();\n\n qq.readBlobToHex(fileOrBlob, app1Start + 18, 2).then(function(hex) {\n if (littleEndian) {\n return promise.success(parseLittleEndian(hex));\n }\n else {\n promise.success(parseInt(hex, 16));\n }\n });\n\n return promise;\n }\n\n // Get the IFD portion of the EXIF header as a hex string.\n function getIfd(app1Start, dirEntries) {\n var offset = app1Start + 20,\n bytes = dirEntries * 12;\n\n return qq.readBlobToHex(fileOrBlob, offset, bytes);\n }\n\n // Obtain an array of all directory entries (as hex strings) in the EXIF header.\n function getDirEntries(ifdHex) {\n var entries = [],\n offset = 0;\n\n while (offset + 24 <= ifdHex.length) {\n entries.push(ifdHex.slice(offset, offset + 24));\n offset += 24;\n }\n\n return entries;\n }\n\n // Obtain values for all relevant tags and return them.\n function getTagValues(littleEndian, dirEntries) {\n var TAG_VAL_OFFSET = 16,\n tagsToFind = qq.extend([], TAG_IDS),\n vals = {};\n\n qq.each(dirEntries, function(idx, entry) {\n var idHex = entry.slice(0, 4),\n id = littleEndian ? parseLittleEndian(idHex) : parseInt(idHex, 16),\n tagsToFindIdx = tagsToFind.indexOf(id),\n tagValHex, tagName, tagValLength;\n\n if (tagsToFindIdx >= 0) {\n tagName = TAG_INFO[id].name;\n tagValLength = TAG_INFO[id].bytes;\n tagValHex = entry.slice(TAG_VAL_OFFSET, TAG_VAL_OFFSET + (tagValLength * 2));\n vals[tagName] = littleEndian ? parseLittleEndian(tagValHex) : parseInt(tagValHex, 16);\n\n tagsToFind.splice(tagsToFindIdx, 1);\n }\n\n if (tagsToFind.length === 0) {\n return false;\n }\n });\n\n return vals;\n }\n\n qq.extend(this, {\n /**\n * Attempt to parse the EXIF header for the `Blob` associated with this instance.\n *\n * @returns {qq.Promise} To be fulfilled when the parsing is complete.\n * If successful, the parsed EXIF header as an object will be included.\n */\n parse: function() {\n var parser = new qq.Promise(),\n onParseFailure = function(message) {\n log(qq.format(\"EXIF header parse failed: '{}' \", message));\n parser.failure(message);\n };\n\n getApp1Offset().then(function(app1Offset) {\n log(qq.format(\"Moving forward with EXIF header parsing for '{}'\", fileOrBlob.name === undefined ? \"blob\" : fileOrBlob.name));\n\n isLittleEndian(app1Offset).then(function(littleEndian) {\n\n log(qq.format(\"EXIF Byte order is {} endian\", littleEndian ? \"little\" : \"big\"));\n\n getDirEntryCount(app1Offset, littleEndian).then(function(dirEntryCount) {\n\n log(qq.format(\"Found {} APP1 directory entries\", dirEntryCount));\n\n getIfd(app1Offset, dirEntryCount).then(function(ifdHex) {\n var dirEntries = getDirEntries(ifdHex),\n tagValues = getTagValues(littleEndian, dirEntries);\n\n log(\"Successfully parsed some EXIF tags\");\n\n parser.success(tagValues);\n }, onParseFailure);\n }, onParseFailure);\n }, onParseFailure);\n }, onParseFailure);\n\n return parser;\n }\n });\n\n /**/\n this._testing = {};\n this._testing.parseLittleEndian = parseLittleEndian;\n /* */\n};\n","/*globals qq */\nqq.Identify = function(fileOrBlob, log) {\n \"use strict\";\n\n function isIdentifiable(magicBytes, questionableBytes) {\n var identifiable = false,\n magicBytesEntries = [].concat(magicBytes);\n\n qq.each(magicBytesEntries, function(idx, magicBytesArrayEntry) {\n if (questionableBytes.indexOf(magicBytesArrayEntry) === 0) {\n identifiable = true;\n return false;\n }\n });\n\n return identifiable;\n }\n\n qq.extend(this, {\n /**\n * Determines if a Blob can be displayed natively in the current browser. This is done by reading magic\n * bytes in the beginning of the file, so this is an asynchronous operation. Before we attempt to read the\n * file, we will examine the blob's type attribute to save CPU cycles.\n *\n * @returns {qq.Promise} Promise that is fulfilled when identification is complete.\n * If successful, the MIME string is passed to the success handler.\n */\n isPreviewable: function() {\n var self = this,\n identifier = new qq.Promise(),\n previewable = false,\n name = fileOrBlob.name === undefined ? \"blob\" : fileOrBlob.name;\n\n log(qq.format(\"Attempting to determine if {} can be rendered in this browser\", name));\n\n log(\"First pass: check type attribute of blob object.\");\n\n if (this.isPreviewableSync()) {\n log(\"Second pass: check for magic bytes in file header.\");\n\n qq.readBlobToHex(fileOrBlob, 0, 4).then(function(hex) {\n qq.each(self.PREVIEWABLE_MIME_TYPES, function(mime, bytes) {\n if (isIdentifiable(bytes, hex)) {\n // Safari is the only supported browser that can deal with TIFFs natively,\n // so, if this is a TIFF and the UA isn't Safari, declare this file \"non-previewable\".\n if (mime !== \"image/tiff\" || qq.supportedFeatures.tiffPreviews) {\n previewable = true;\n identifier.success(mime);\n }\n\n return false;\n }\n });\n\n log(qq.format(\"'{}' is {} able to be rendered in this browser\", name, previewable ? \"\" : \"NOT\"));\n\n if (!previewable) {\n identifier.failure();\n }\n },\n function() {\n log(\"Error reading file w/ name '\" + name + \"'. Not able to be rendered in this browser.\");\n identifier.failure();\n });\n }\n else {\n identifier.failure();\n }\n\n return identifier;\n },\n\n /**\n * Determines if a Blob can be displayed natively in the current browser. This is done by checking the\n * blob's type attribute. This is a synchronous operation, useful for situations where an asynchronous operation\n * would be challenging to support. Note that the blob's type property is not as accurate as reading the\n * file's magic bytes.\n *\n * @returns {Boolean} true if the blob can be rendered in the current browser\n */\n isPreviewableSync: function() {\n var fileMime = fileOrBlob.type,\n // Assumption: This will only ever be executed in browsers that support `Object.keys`.\n isRecognizedImage = qq.indexOf(Object.keys(this.PREVIEWABLE_MIME_TYPES), fileMime) >= 0,\n previewable = false,\n name = fileOrBlob.name === undefined ? \"blob\" : fileOrBlob.name;\n\n if (isRecognizedImage) {\n if (fileMime === \"image/tiff\") {\n previewable = qq.supportedFeatures.tiffPreviews;\n }\n else {\n previewable = true;\n }\n }\n\n !previewable && log(name + \" is not previewable in this browser per the blob's type attr\");\n\n return previewable;\n }\n });\n};\n\nqq.Identify.prototype.PREVIEWABLE_MIME_TYPES = {\n \"image/jpeg\": \"ffd8ff\",\n \"image/gif\": \"474946\",\n \"image/png\": \"89504e\",\n \"image/bmp\": \"424d\",\n \"image/tiff\": [\"49492a00\", \"4d4d002a\"]\n};\n","/*globals qq*/\n/**\n * Attempts to validate an image, wherever possible.\n *\n * @param blob File or Blob representing a user-selecting image.\n * @param log Uses this to post log messages to the console.\n * @constructor\n */\nqq.ImageValidation = function(blob, log) {\n \"use strict\";\n\n /**\n * @param limits Object with possible image-related limits to enforce.\n * @returns {boolean} true if at least one of the limits has a non-zero value\n */\n function hasNonZeroLimits(limits) {\n var atLeastOne = false;\n\n qq.each(limits, function(limit, value) {\n if (value > 0) {\n atLeastOne = true;\n return false;\n }\n });\n\n return atLeastOne;\n }\n\n /**\n * @returns {qq.Promise} The promise is a failure if we can't obtain the width & height.\n * Otherwise, `success` is called on the returned promise with an object containing\n * `width` and `height` properties.\n */\n function getWidthHeight() {\n var sizeDetermination = new qq.Promise();\n\n new qq.Identify(blob, log).isPreviewable().then(function() {\n var image = new Image(),\n url = window.URL && window.URL.createObjectURL ? window.URL :\n window.webkitURL && window.webkitURL.createObjectURL ? window.webkitURL :\n null;\n\n if (url) {\n image.onerror = function() {\n log(\"Cannot determine dimensions for image. May be too large.\", \"error\");\n sizeDetermination.failure();\n };\n\n image.onload = function() {\n sizeDetermination.success({\n width: this.width,\n height: this.height\n });\n };\n\n image.src = url.createObjectURL(blob);\n }\n else {\n log(\"No createObjectURL function available to generate image URL!\", \"error\");\n sizeDetermination.failure();\n }\n }, sizeDetermination.failure);\n\n return sizeDetermination;\n }\n\n /**\n *\n * @param limits Object with possible image-related limits to enforce.\n * @param dimensions Object containing `width` & `height` properties for the image to test.\n * @returns {String || undefined} The name of the failing limit. Undefined if no failing limits.\n */\n function getFailingLimit(limits, dimensions) {\n var failingLimit;\n\n qq.each(limits, function(limitName, limitValue) {\n if (limitValue > 0) {\n var limitMatcher = /(max|min)(Width|Height)/.exec(limitName),\n dimensionPropName = limitMatcher[2].charAt(0).toLowerCase() + limitMatcher[2].slice(1),\n actualValue = dimensions[dimensionPropName];\n\n /*jshint -W015*/\n switch (limitMatcher[1]) {\n case \"min\":\n if (actualValue < limitValue) {\n failingLimit = limitName;\n return false;\n }\n break;\n case \"max\":\n if (actualValue > limitValue) {\n failingLimit = limitName;\n return false;\n }\n break;\n }\n }\n });\n\n return failingLimit;\n }\n\n /**\n * Validate the associated blob.\n *\n * @param limits\n * @returns {qq.Promise} `success` is called on the promise is the image is valid or\n * if the blob is not an image, or if the image is not verifiable.\n * Otherwise, `failure` with the name of the failing limit.\n */\n this.validate = function(limits) {\n var validationEffort = new qq.Promise();\n\n log(\"Attempting to validate image.\");\n\n if (hasNonZeroLimits(limits)) {\n getWidthHeight().then(function(dimensions) {\n var failingLimit = getFailingLimit(limits, dimensions);\n\n if (failingLimit) {\n validationEffort.failure(failingLimit);\n }\n else {\n validationEffort.success();\n }\n }, validationEffort.success);\n }\n else {\n validationEffort.success();\n }\n\n return validationEffort;\n };\n};\n","/* globals qq */\n/**\n * Module used to control populating the initial list of files.\n *\n * @constructor\n */\nqq.Session = function(spec) {\n \"use strict\";\n\n var options = {\n endpoint: null,\n params: {},\n customHeaders: {},\n cors: {},\n addFileRecord: function(sessionData) {},\n log: function(message, level) {}\n };\n\n qq.extend(options, spec, true);\n\n function isJsonResponseValid(response) {\n if (qq.isArray(response)) {\n return true;\n }\n\n options.log(\"Session response is not an array.\", \"error\");\n }\n\n function handleFileItems(fileItems, success, xhrOrXdr, promise) {\n var someItemsIgnored = false;\n\n success = success && isJsonResponseValid(fileItems);\n\n if (success) {\n qq.each(fileItems, function(idx, fileItem) {\n /* jshint eqnull:true */\n if (fileItem.uuid == null) {\n someItemsIgnored = true;\n options.log(qq.format(\"Session response item {} did not include a valid UUID - ignoring.\", idx), \"error\");\n }\n else if (fileItem.name == null) {\n someItemsIgnored = true;\n options.log(qq.format(\"Session response item {} did not include a valid name - ignoring.\", idx), \"error\");\n }\n else {\n try {\n options.addFileRecord(fileItem);\n return true;\n }\n catch (err) {\n someItemsIgnored = true;\n options.log(err.message, \"error\");\n }\n }\n\n return false;\n });\n }\n\n promise[success && !someItemsIgnored ? \"success\" : \"failure\"](fileItems, xhrOrXdr);\n }\n\n // Initiate a call to the server that will be used to populate the initial file list.\n // Returns a `qq.Promise`.\n this.refresh = function() {\n /*jshint indent:false */\n var refreshEffort = new qq.Promise(),\n refreshCompleteCallback = function(response, success, xhrOrXdr) {\n handleFileItems(response, success, xhrOrXdr, refreshEffort);\n },\n requesterOptions = qq.extend({}, options),\n requester = new qq.SessionAjaxRequester(\n qq.extend(requesterOptions, {onComplete: refreshCompleteCallback})\n );\n\n requester.queryServer();\n\n return refreshEffort;\n };\n};\n","/*globals qq, XMLHttpRequest*/\n/**\n * Thin module used to send GET requests to the server, expecting information about session\n * data used to initialize an uploader instance.\n *\n * @param spec Various options used to influence the associated request.\n * @constructor\n */\nqq.SessionAjaxRequester = function(spec) {\n \"use strict\";\n\n var requester,\n options = {\n endpoint: null,\n customHeaders: {},\n params: {},\n cors: {\n expected: false,\n sendCredentials: false\n },\n onComplete: function(response, success, xhrOrXdr) {},\n log: function(str, level) {}\n };\n\n qq.extend(options, spec);\n\n function onComplete(id, xhrOrXdr, isError) {\n var response = null;\n\n /* jshint eqnull:true */\n if (xhrOrXdr.responseText != null) {\n try {\n response = qq.parseJson(xhrOrXdr.responseText);\n }\n catch (err) {\n options.log(\"Problem parsing session response: \" + err.message, \"error\");\n isError = true;\n }\n }\n\n options.onComplete(response, !isError, xhrOrXdr);\n }\n\n requester = qq.extend(this, new qq.AjaxRequester({\n acceptHeader: \"application/json\",\n validMethods: [\"GET\"],\n method: \"GET\",\n endpointStore: {\n get: function() {\n return options.endpoint;\n }\n },\n customHeaders: options.customHeaders,\n log: options.log,\n onComplete: onComplete,\n cors: options.cors\n }));\n\n qq.extend(this, {\n queryServer: function() {\n var params = qq.extend({}, options.params);\n\n options.log(\"Session query request.\");\n\n requester.initTransport(\"sessionRefresh\")\n .withParams(params)\n .withCacheBuster()\n .send();\n }\n });\n};\n","/* globals qq, ExifRestorer */\n/**\n * Controls generation of scaled images based on a reference image encapsulated in a `File` or `Blob`.\n * Scaled images are generated and converted to blobs on-demand.\n * Multiple scaled images per reference image with varying sizes and other properties are supported.\n *\n * @param spec Information about the scaled images to generate.\n * @param log Logger instance\n * @constructor\n */\nqq.Scaler = function(spec, log) {\n \"use strict\";\n\n var self = this,\n customResizeFunction = spec.customResizer,\n includeOriginal = spec.sendOriginal,\n orient = spec.orient,\n defaultType = spec.defaultType,\n defaultQuality = spec.defaultQuality / 100,\n failedToScaleText = spec.failureText,\n includeExif = spec.includeExif,\n sizes = this._getSortedSizes(spec.sizes);\n\n // Revealed API for instances of this module\n qq.extend(this, {\n // If no targeted sizes have been declared or if this browser doesn't support\n // client-side image preview generation, there is no scaling to do.\n enabled: qq.supportedFeatures.scaling && sizes.length > 0,\n\n getFileRecords: function(originalFileUuid, originalFileName, originalBlobOrBlobData) {\n var self = this,\n records = [],\n originalBlob = originalBlobOrBlobData.blob ? originalBlobOrBlobData.blob : originalBlobOrBlobData,\n identifier = new qq.Identify(originalBlob, log);\n\n // If the reference file cannot be rendered natively, we can't create scaled versions.\n if (identifier.isPreviewableSync()) {\n // Create records for each scaled version & add them to the records array, smallest first.\n qq.each(sizes, function(idx, sizeRecord) {\n var outputType = self._determineOutputType({\n defaultType: defaultType,\n requestedType: sizeRecord.type,\n refType: originalBlob.type\n });\n\n records.push({\n uuid: qq.getUniqueId(),\n name: self._getName(originalFileName, {\n name: sizeRecord.name,\n type: outputType,\n refType: originalBlob.type\n }),\n blob: new qq.BlobProxy(originalBlob,\n qq.bind(self._generateScaledImage, self, {\n customResizeFunction: customResizeFunction,\n maxSize: sizeRecord.maxSize,\n orient: orient,\n type: outputType,\n quality: defaultQuality,\n failedText: failedToScaleText,\n includeExif: includeExif,\n log: log\n }))\n });\n });\n\n records.push({\n uuid: originalFileUuid,\n name: originalFileName,\n size: originalBlob.size,\n blob: includeOriginal ? originalBlob : null\n });\n }\n else {\n records.push({\n uuid: originalFileUuid,\n name: originalFileName,\n size: originalBlob.size,\n blob: originalBlob\n });\n }\n\n return records;\n },\n\n handleNewFile: function(file, name, uuid, size, fileList, batchId, uuidParamName, api) {\n var self = this,\n buttonId = file.qqButtonId || (file.blob && file.blob.qqButtonId),\n scaledIds = [],\n originalId = null,\n addFileToHandler = api.addFileToHandler,\n uploadData = api.uploadData,\n paramsStore = api.paramsStore,\n proxyGroupId = qq.getUniqueId();\n\n qq.each(self.getFileRecords(uuid, name, file), function(idx, record) {\n var blobSize = record.size,\n id;\n\n if (record.blob instanceof qq.BlobProxy) {\n blobSize = -1;\n }\n\n id = uploadData.addFile({\n uuid: record.uuid,\n name: record.name,\n size: blobSize,\n batchId: batchId,\n proxyGroupId: proxyGroupId\n });\n\n if (record.blob instanceof qq.BlobProxy) {\n scaledIds.push(id);\n }\n else {\n originalId = id;\n }\n\n if (record.blob) {\n addFileToHandler(id, record.blob);\n fileList.push({id: id, file: record.blob});\n }\n else {\n uploadData.setStatus(id, qq.status.REJECTED);\n }\n });\n\n // If we are potentially uploading an original file and some scaled versions,\n // ensure the scaled versions include reference's to the parent's UUID and size\n // in their associated upload requests.\n if (originalId !== null) {\n qq.each(scaledIds, function(idx, scaledId) {\n var params = {\n qqparentuuid: uploadData.retrieve({id: originalId}).uuid,\n qqparentsize: uploadData.retrieve({id: originalId}).size\n };\n\n // Make sure the UUID for each scaled image is sent with the upload request,\n // to be consistent (since we may need to ensure it is sent for the original file as well).\n params[uuidParamName] = uploadData.retrieve({id: scaledId}).uuid;\n\n uploadData.setParentId(scaledId, originalId);\n paramsStore.addReadOnly(scaledId, params);\n });\n\n // If any scaled images are tied to this parent image, be SURE we send its UUID as an upload request\n // parameter as well.\n if (scaledIds.length) {\n (function() {\n var param = {};\n param[uuidParamName] = uploadData.retrieve({id: originalId}).uuid;\n paramsStore.addReadOnly(originalId, param);\n }());\n }\n }\n }\n });\n};\n\nqq.extend(qq.Scaler.prototype, {\n scaleImage: function(id, specs, api) {\n \"use strict\";\n\n if (!qq.supportedFeatures.scaling) {\n throw new qq.Error(\"Scaling is not supported in this browser!\");\n }\n\n var scalingEffort = new qq.Promise(),\n log = api.log,\n file = api.getFile(id),\n uploadData = api.uploadData.retrieve({id: id}),\n name = uploadData && uploadData.name,\n uuid = uploadData && uploadData.uuid,\n scalingOptions = {\n customResizer: specs.customResizer,\n sendOriginal: false,\n orient: specs.orient,\n defaultType: specs.type || null,\n defaultQuality: specs.quality,\n failedToScaleText: \"Unable to scale\",\n sizes: [{name: \"\", maxSize: specs.maxSize}]\n },\n scaler = new qq.Scaler(scalingOptions, log);\n\n if (!qq.Scaler || !qq.supportedFeatures.imagePreviews || !file) {\n scalingEffort.failure();\n\n log(\"Could not generate requested scaled image for \" + id + \". \" +\n \"Scaling is either not possible in this browser, or the file could not be located.\", \"error\");\n }\n else {\n (qq.bind(function() {\n // Assumption: There will never be more than one record\n var record = scaler.getFileRecords(uuid, name, file)[0];\n\n if (record && record.blob instanceof qq.BlobProxy) {\n record.blob.create().then(scalingEffort.success, scalingEffort.failure);\n }\n else {\n log(id + \" is not a scalable image!\", \"error\");\n scalingEffort.failure();\n }\n }, this)());\n }\n\n return scalingEffort;\n },\n\n // NOTE: We cannot reliably determine at this time if the UA supports a specific MIME type for the target format.\n // image/jpeg and image/png are the only safe choices at this time.\n _determineOutputType: function(spec) {\n \"use strict\";\n\n var requestedType = spec.requestedType,\n defaultType = spec.defaultType,\n referenceType = spec.refType;\n\n // If a default type and requested type have not been specified, this should be a\n // JPEG if the original type is a JPEG, otherwise, a PNG.\n if (!defaultType && !requestedType) {\n if (referenceType !== \"image/jpeg\") {\n return \"image/png\";\n }\n return referenceType;\n }\n\n // A specified default type is used when a requested type is not specified.\n if (!requestedType) {\n return defaultType;\n }\n\n // If requested type is specified, use it, as long as this recognized type is supported by the current UA\n if (qq.indexOf(Object.keys(qq.Identify.prototype.PREVIEWABLE_MIME_TYPES), requestedType) >= 0) {\n if (requestedType === \"image/tiff\") {\n return qq.supportedFeatures.tiffPreviews ? requestedType : defaultType;\n }\n\n return requestedType;\n }\n\n return defaultType;\n },\n\n // Get a file name for a generated scaled file record, based on the provided scaled image description\n _getName: function(originalName, scaledVersionProperties) {\n \"use strict\";\n\n var startOfExt = originalName.lastIndexOf(\".\"),\n versionType = scaledVersionProperties.type || \"image/png\",\n referenceType = scaledVersionProperties.refType,\n scaledName = \"\",\n scaledExt = qq.getExtension(originalName),\n nameAppendage = \"\";\n\n if (scaledVersionProperties.name && scaledVersionProperties.name.trim().length) {\n nameAppendage = \" (\" + scaledVersionProperties.name + \")\";\n }\n\n if (startOfExt >= 0) {\n scaledName = originalName.substr(0, startOfExt);\n\n if (referenceType !== versionType) {\n scaledExt = versionType.split(\"/\")[1];\n }\n\n scaledName += nameAppendage + \".\" + scaledExt;\n }\n else {\n scaledName = originalName + nameAppendage;\n }\n\n return scaledName;\n },\n\n // We want the smallest scaled file to be uploaded first\n _getSortedSizes: function(sizes) {\n \"use strict\";\n\n sizes = qq.extend([], sizes);\n\n return sizes.sort(function(a, b) {\n if (a.maxSize > b.maxSize) {\n return 1;\n }\n if (a.maxSize < b.maxSize) {\n return -1;\n }\n return 0;\n });\n },\n\n _generateScaledImage: function(spec, sourceFile) {\n \"use strict\";\n\n var self = this,\n customResizeFunction = spec.customResizeFunction,\n log = spec.log,\n maxSize = spec.maxSize,\n orient = spec.orient,\n type = spec.type,\n quality = spec.quality,\n failedText = spec.failedText,\n includeExif = spec.includeExif && sourceFile.type === \"image/jpeg\" && type === \"image/jpeg\",\n scalingEffort = new qq.Promise(),\n imageGenerator = new qq.ImageGenerator(log),\n canvas = document.createElement(\"canvas\");\n\n log(\"Attempting to generate scaled version for \" + sourceFile.name);\n\n imageGenerator.generate(sourceFile, canvas, {maxSize: maxSize, orient: orient, customResizeFunction: customResizeFunction}).then(function() {\n var scaledImageDataUri = canvas.toDataURL(type, quality),\n signalSuccess = function() {\n log(\"Success generating scaled version for \" + sourceFile.name);\n var blob = qq.dataUriToBlob(scaledImageDataUri);\n scalingEffort.success(blob);\n };\n\n if (includeExif) {\n self._insertExifHeader(sourceFile, scaledImageDataUri, log).then(function(scaledImageDataUriWithExif) {\n scaledImageDataUri = scaledImageDataUriWithExif;\n signalSuccess();\n },\n function() {\n log(\"Problem inserting EXIF header into scaled image. Using scaled image w/out EXIF data.\", \"error\");\n signalSuccess();\n });\n }\n else {\n signalSuccess();\n }\n }, function() {\n log(\"Failed attempt to generate scaled version for \" + sourceFile.name, \"error\");\n scalingEffort.failure(failedText);\n });\n\n return scalingEffort;\n },\n\n // Attempt to insert the original image's EXIF header into a scaled version.\n _insertExifHeader: function(originalImage, scaledImageDataUri, log) {\n \"use strict\";\n\n var reader = new FileReader(),\n insertionEffort = new qq.Promise(),\n originalImageDataUri = \"\";\n\n reader.onload = function() {\n originalImageDataUri = reader.result;\n insertionEffort.success(qq.ExifRestorer.restore(originalImageDataUri, scaledImageDataUri));\n };\n\n reader.onerror = function() {\n log(\"Problem reading \" + originalImage.name + \" during attempt to transfer EXIF data to scaled version.\", \"error\");\n insertionEffort.failure();\n };\n\n reader.readAsDataURL(originalImage);\n\n return insertionEffort;\n },\n\n _dataUriToBlob: function(dataUri) {\n \"use strict\";\n\n var byteString, mimeString, arrayBuffer, intArray;\n\n // convert base64 to raw binary data held in a string\n if (dataUri.split(\",\")[0].indexOf(\"base64\") >= 0) {\n byteString = atob(dataUri.split(\",\")[1]);\n }\n else {\n byteString = decodeURI(dataUri.split(\",\")[1]);\n }\n\n // extract the MIME\n mimeString = dataUri.split(\",\")[0]\n .split(\":\")[1]\n .split(\";\")[0];\n\n // write the bytes of the binary string to an ArrayBuffer\n arrayBuffer = new ArrayBuffer(byteString.length);\n intArray = new Uint8Array(arrayBuffer);\n qq.each(byteString, function(idx, character) {\n intArray[idx] = character.charCodeAt(0);\n });\n\n return this._createBlob(arrayBuffer, mimeString);\n },\n\n _createBlob: function(data, mime) {\n \"use strict\";\n\n var BlobBuilder = window.BlobBuilder ||\n window.WebKitBlobBuilder ||\n window.MozBlobBuilder ||\n window.MSBlobBuilder,\n blobBuilder = BlobBuilder && new BlobBuilder();\n\n if (blobBuilder) {\n blobBuilder.append(data);\n return blobBuilder.getBlob(mime);\n }\n else {\n return new Blob([data], {type: mime});\n }\n }\n});\n","//Based on MinifyJpeg\n//http://elicon.blog57.fc2.com/blog-entry-206.html\n\nqq.ExifRestorer = (function()\n{\n \n\tvar ExifRestorer = {};\n\t \n ExifRestorer.KEY_STR = \"ABCDEFGHIJKLMNOP\" +\n \"QRSTUVWXYZabcdef\" +\n \"ghijklmnopqrstuv\" +\n \"wxyz0123456789+/\" +\n \"=\";\n\n ExifRestorer.encode64 = function(input)\n {\n var output = \"\",\n chr1, chr2, chr3 = \"\",\n enc1, enc2, enc3, enc4 = \"\",\n i = 0;\n\n do {\n chr1 = input[i++];\n chr2 = input[i++];\n chr3 = input[i++];\n\n enc1 = chr1 >> 2;\n enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);\n enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);\n enc4 = chr3 & 63;\n\n if (isNaN(chr2)) {\n enc3 = enc4 = 64;\n } else if (isNaN(chr3)) {\n enc4 = 64;\n }\n\n output = output +\n this.KEY_STR.charAt(enc1) +\n this.KEY_STR.charAt(enc2) +\n this.KEY_STR.charAt(enc3) +\n this.KEY_STR.charAt(enc4);\n chr1 = chr2 = chr3 = \"\";\n enc1 = enc2 = enc3 = enc4 = \"\";\n } while (i < input.length);\n\n return output;\n };\n \n ExifRestorer.restore = function(origFileBase64, resizedFileBase64)\n {\n var expectedBase64Header = \"data:image/jpeg;base64,\";\n\n if (!origFileBase64.match(expectedBase64Header))\n {\n \treturn resizedFileBase64;\n } \n \n var rawImage = this.decode64(origFileBase64.replace(expectedBase64Header, \"\"));\n var segments = this.slice2Segments(rawImage);\n \n var image = this.exifManipulation(resizedFileBase64, segments);\n \n return expectedBase64Header + this.encode64(image);\n \n };\n\n\n ExifRestorer.exifManipulation = function(resizedFileBase64, segments)\n {\n var exifArray = this.getExifArray(segments),\n newImageArray = this.insertExif(resizedFileBase64, exifArray),\n aBuffer = new Uint8Array(newImageArray);\n\n return aBuffer;\n };\n\n\n ExifRestorer.getExifArray = function(segments)\n {\n var seg;\n for (var x = 0; x < segments.length; x++)\n {\n seg = segments[x];\n if (seg[0] == 255 & seg[1] == 225) //(ff e1)\n {\n return seg;\n }\n }\n return [];\n };\n\n\n ExifRestorer.insertExif = function(resizedFileBase64, exifArray)\n {\n var imageData = resizedFileBase64.replace(\"data:image/jpeg;base64,\", \"\"),\n buf = this.decode64(imageData),\n separatePoint = buf.indexOf(255,3),\n mae = buf.slice(0, separatePoint),\n ato = buf.slice(separatePoint),\n array = mae;\n\n array = array.concat(exifArray);\n array = array.concat(ato);\n return array;\n };\n\n\n \n ExifRestorer.slice2Segments = function(rawImageArray)\n {\n var head = 0,\n segments = [];\n\n while (1)\n {\n if (rawImageArray[head] == 255 & rawImageArray[head + 1] == 218){break;}\n if (rawImageArray[head] == 255 & rawImageArray[head + 1] == 216)\n {\n head += 2;\n }\n else\n {\n var length = rawImageArray[head + 2] * 256 + rawImageArray[head + 3],\n endPoint = head + length + 2,\n seg = rawImageArray.slice(head, endPoint);\n segments.push(seg);\n head = endPoint;\n }\n if (head > rawImageArray.length){break;}\n }\n\n return segments;\n };\n\n\n \n ExifRestorer.decode64 = function(input) \n {\n var output = \"\",\n chr1, chr2, chr3 = \"\",\n enc1, enc2, enc3, enc4 = \"\",\n i = 0,\n buf = [];\n\n // remove all characters that are not A-Z, a-z, 0-9, +, /, or =\n var base64test = /[^A-Za-z0-9\\+\\/\\=]/g;\n if (base64test.exec(input)) {\n throw new Error(\"There were invalid base64 characters in the input text. \" +\n \"Valid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='\");\n }\n input = input.replace(/[^A-Za-z0-9\\+\\/\\=]/g, \"\");\n\n do {\n enc1 = this.KEY_STR.indexOf(input.charAt(i++));\n enc2 = this.KEY_STR.indexOf(input.charAt(i++));\n enc3 = this.KEY_STR.indexOf(input.charAt(i++));\n enc4 = this.KEY_STR.indexOf(input.charAt(i++));\n\n chr1 = (enc1 << 2) | (enc2 >> 4);\n chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);\n chr3 = ((enc3 & 3) << 6) | enc4;\n\n buf.push(chr1);\n\n if (enc3 != 64) {\n buf.push(chr2);\n }\n if (enc4 != 64) {\n buf.push(chr3);\n }\n\n chr1 = chr2 = chr3 = \"\";\n enc1 = enc2 = enc3 = enc4 = \"\";\n\n } while (i < input.length);\n\n return buf;\n };\n\n \n return ExifRestorer;\n})();\n","/* globals qq */\n/**\n * Keeps a running tally of total upload progress for a batch of files.\n *\n * @param callback Invoked when total progress changes, passing calculated total loaded & total size values.\n * @param getSize Function that returns the size of a file given its ID\n * @constructor\n */\nqq.TotalProgress = function(callback, getSize) {\n \"use strict\";\n\n var perFileProgress = {},\n totalLoaded = 0,\n totalSize = 0,\n\n lastLoadedSent = -1,\n lastTotalSent = -1,\n callbackProxy = function(loaded, total) {\n if (loaded !== lastLoadedSent || total !== lastTotalSent) {\n callback(loaded, total);\n }\n\n lastLoadedSent = loaded;\n lastTotalSent = total;\n },\n\n /**\n * @param failed Array of file IDs that have failed\n * @param retryable Array of file IDs that are retryable\n * @returns true if none of the failed files are eligible for retry\n */\n noRetryableFiles = function(failed, retryable) {\n var none = true;\n\n qq.each(failed, function(idx, failedId) {\n if (qq.indexOf(retryable, failedId) >= 0) {\n none = false;\n return false;\n }\n });\n\n return none;\n },\n\n onCancel = function(id) {\n updateTotalProgress(id, -1, -1);\n delete perFileProgress[id];\n },\n\n onAllComplete = function(successful, failed, retryable) {\n if (failed.length === 0 || noRetryableFiles(failed, retryable)) {\n callbackProxy(totalSize, totalSize);\n this.reset();\n }\n },\n\n onNew = function(id) {\n var size = getSize(id);\n\n // We might not know the size yet, such as for blob proxies\n if (size > 0) {\n updateTotalProgress(id, 0, size);\n perFileProgress[id] = {loaded: 0, total: size};\n }\n },\n\n /**\n * Invokes the callback with the current total progress of all files in the batch. Called whenever it may\n * be appropriate to re-calculate and disseminate this data.\n *\n * @param id ID of a file that has changed in some important way\n * @param newLoaded New loaded value for this file. -1 if this value should no longer be part of calculations\n * @param newTotal New total size of the file. -1 if this value should no longer be part of calculations\n */\n updateTotalProgress = function(id, newLoaded, newTotal) {\n var oldLoaded = perFileProgress[id] ? perFileProgress[id].loaded : 0,\n oldTotal = perFileProgress[id] ? perFileProgress[id].total : 0;\n\n if (newLoaded === -1 && newTotal === -1) {\n totalLoaded -= oldLoaded;\n totalSize -= oldTotal;\n }\n else {\n if (newLoaded) {\n totalLoaded += newLoaded - oldLoaded;\n }\n if (newTotal) {\n totalSize += newTotal - oldTotal;\n }\n }\n\n callbackProxy(totalLoaded, totalSize);\n };\n\n qq.extend(this, {\n // Called when a batch of files has completed uploading.\n onAllComplete: onAllComplete,\n\n // Called when the status of a file has changed.\n onStatusChange: function(id, oldStatus, newStatus) {\n if (newStatus === qq.status.CANCELED || newStatus === qq.status.REJECTED) {\n onCancel(id);\n }\n else if (newStatus === qq.status.SUBMITTING) {\n onNew(id);\n }\n },\n\n // Called whenever the upload progress of an individual file has changed.\n onIndividualProgress: function(id, loaded, total) {\n updateTotalProgress(id, loaded, total);\n perFileProgress[id] = {loaded: loaded, total: total};\n },\n\n // Called whenever the total size of a file has changed, such as when the size of a generated blob is known.\n onNewSize: function(id) {\n onNew(id);\n },\n\n reset: function() {\n perFileProgress = {};\n totalLoaded = 0;\n totalSize = 0;\n }\n });\n};\n","/*globals qq*/\nqq.PasteSupport = function(o) {\n \"use strict\";\n\n var options, detachPasteHandler;\n\n options = {\n targetElement: null,\n callbacks: {\n log: function(message, level) {},\n pasteReceived: function(blob) {}\n }\n };\n\n function isImage(item) {\n return item.type &&\n item.type.indexOf(\"image/\") === 0;\n }\n\n function registerPasteHandler() {\n detachPasteHandler = qq(options.targetElement).attach(\"paste\", function(event) {\n var clipboardData = event.clipboardData;\n\n if (clipboardData) {\n qq.each(clipboardData.items, function(idx, item) {\n if (isImage(item)) {\n var blob = item.getAsFile();\n options.callbacks.pasteReceived(blob);\n }\n });\n }\n });\n }\n\n function unregisterPasteHandler() {\n if (detachPasteHandler) {\n detachPasteHandler();\n }\n }\n\n qq.extend(options, o);\n registerPasteHandler();\n\n qq.extend(this, {\n reset: function() {\n unregisterPasteHandler();\n }\n });\n};\n","/* globals qq */\n/**\n * Module that handles support for existing forms.\n *\n * @param options Options passed from the integrator-supplied options related to form support.\n * @param startUpload Callback to invoke when files \"stored\" should be uploaded.\n * @param log Proxy for the logger\n * @constructor\n */\nqq.FormSupport = function(options, startUpload, log) {\n \"use strict\";\n var self = this,\n interceptSubmit = options.interceptSubmit,\n formEl = options.element,\n autoUpload = options.autoUpload;\n\n // Available on the public API associated with this module.\n qq.extend(this, {\n // To be used by the caller to determine if the endpoint will be determined by some processing\n // that occurs in this module, such as if the form has an action attribute.\n // Ignore if `attachToForm === false`.\n newEndpoint: null,\n\n // To be used by the caller to determine if auto uploading should be allowed.\n // Ignore if `attachToForm === false`.\n newAutoUpload: autoUpload,\n\n // true if a form was detected and is being tracked by this module\n attachedToForm: false,\n\n // Returns an object with names and values for all valid form elements associated with the attached form.\n getFormInputsAsObject: function() {\n /* jshint eqnull:true */\n if (formEl == null) {\n return null;\n }\n\n return self._form2Obj(formEl);\n }\n });\n\n // If the form contains an action attribute, this should be the new upload endpoint.\n function determineNewEndpoint(formEl) {\n if (formEl.getAttribute(\"action\")) {\n self.newEndpoint = formEl.getAttribute(\"action\");\n }\n }\n\n // Return true only if the form is valid, or if we cannot make this determination.\n // If the form is invalid, ensure invalid field(s) are highlighted in the UI.\n function validateForm(formEl, nativeSubmit) {\n if (formEl.checkValidity && !formEl.checkValidity()) {\n log(\"Form did not pass validation checks - will not upload.\", \"error\");\n nativeSubmit();\n }\n else {\n return true;\n }\n }\n\n // Intercept form submit attempts, unless the integrator has told us not to do this.\n function maybeUploadOnSubmit(formEl) {\n var nativeSubmit = formEl.submit;\n\n // Intercept and squelch submit events.\n qq(formEl).attach(\"submit\", function(event) {\n event = event || window.event;\n\n if (event.preventDefault) {\n event.preventDefault();\n }\n else {\n event.returnValue = false;\n }\n\n validateForm(formEl, nativeSubmit) && startUpload();\n });\n\n // The form's `submit()` function may be called instead (i.e. via jQuery.submit()).\n // Intercept that too.\n formEl.submit = function() {\n validateForm(formEl, nativeSubmit) && startUpload();\n };\n }\n\n // If the element value passed from the uploader is a string, assume it is an element ID - select it.\n // The rest of the code in this module depends on this being an HTMLElement.\n function determineFormEl(formEl) {\n if (formEl) {\n if (qq.isString(formEl)) {\n formEl = document.getElementById(formEl);\n }\n\n if (formEl) {\n log(\"Attaching to form element.\");\n determineNewEndpoint(formEl);\n interceptSubmit && maybeUploadOnSubmit(formEl);\n }\n }\n\n return formEl;\n }\n\n formEl = determineFormEl(formEl);\n this.attachedToForm = !!formEl;\n};\n\nqq.extend(qq.FormSupport.prototype, {\n // Converts all relevant form fields to key/value pairs. This is meant to mimic the data a browser will\n // construct from a given form when the form is submitted.\n _form2Obj: function(form) {\n \"use strict\";\n var obj = {},\n notIrrelevantType = function(type) {\n var irrelevantTypes = [\n \"button\",\n \"image\",\n \"reset\",\n \"submit\"\n ];\n\n return qq.indexOf(irrelevantTypes, type.toLowerCase()) < 0;\n },\n radioOrCheckbox = function(type) {\n return qq.indexOf([\"checkbox\", \"radio\"], type.toLowerCase()) >= 0;\n },\n ignoreValue = function(el) {\n if (radioOrCheckbox(el.type) && !el.checked) {\n return true;\n }\n\n return el.disabled && el.type.toLowerCase() !== \"hidden\";\n },\n selectValue = function(select) {\n var value = null;\n\n qq.each(qq(select).children(), function(idx, child) {\n if (child.tagName.toLowerCase() === \"option\" && child.selected) {\n value = child.value;\n return false;\n }\n });\n\n return value;\n };\n\n qq.each(form.elements, function(idx, el) {\n if ((qq.isInput(el, true) || el.tagName.toLowerCase() === \"textarea\") &&\n notIrrelevantType(el.type) &&\n !ignoreValue(el)) {\n\n obj[el.name] = el.value;\n }\n else if (el.tagName.toLowerCase() === \"select\" && !ignoreValue(el)) {\n var value = selectValue(el);\n\n if (value !== null) {\n obj[el.name] = value;\n }\n }\n });\n\n return obj;\n }\n});\n","/*globals qq*/\n/**\n * Upload handler used that assumes the current user agent does not have any support for the\n * File API, and, therefore, makes use of iframes and forms to submit the files directly to\n * a generic server.\n *\n * @param options Options passed from the base handler\n * @param proxy Callbacks & methods used to query for or push out data/changes\n */\nqq.traditional = qq.traditional || {};\nqq.traditional.FormUploadHandler = function(options, proxy) {\n \"use strict\";\n\n var handler = this,\n getName = proxy.getName,\n getUuid = proxy.getUuid,\n log = proxy.log;\n\n /**\n * Returns json object received by iframe from server.\n */\n function getIframeContentJson(id, iframe) {\n /*jshint evil: true*/\n\n var response, doc, innerHtml;\n\n //IE may throw an \"access is denied\" error when attempting to access contentDocument on the iframe in some cases\n try {\n // iframe.contentWindow.document - for IE<7\n doc = iframe.contentDocument || iframe.contentWindow.document;\n innerHtml = doc.body.innerHTML;\n\n log(\"converting iframe's innerHTML to JSON\");\n log(\"innerHTML = \" + innerHtml);\n //plain text response may be wrapped in tag\n if (innerHtml && innerHtml.match(/^= 0) {\n byteString = atob(dataUri.split(\",\")[1]);\n }\n else {\n byteString = decodeURI(dataUri.split(\",\")[1]);\n }\n\n // extract the MIME\n mimeString = dataUri.split(\",\")[0]\n .split(\":\")[1]\n .split(\";\")[0];\n\n // write the bytes of the binary string to an ArrayBuffer\n arrayBuffer = new ArrayBuffer(byteString.length);\n intArray = new Uint8Array(arrayBuffer);\n qq.each(byteString, function(idx, character) {\n intArray[idx] = character.charCodeAt(0);\n });\n\n return createBlob(arrayBuffer, mimeString);\n };\n\n qq.log = function(message, level) {\n if (window.console) {\n if (!level || level === \"info\") {\n window.console.log(message);\n }\n else\n {\n if (window.console[level]) {\n window.console[level](message);\n }\n else {\n window.console.log(\"<\" + level + \"> \" + message);\n }\n }\n }\n };\n\n qq.isObject = function(variable) {\n return variable && !variable.nodeType && Object.prototype.toString.call(variable) === \"[object Object]\";\n };\n\n qq.isFunction = function(variable) {\n return typeof (variable) === \"function\";\n };\n\n /**\n * Check the type of a value. Is it an \"array\"?\n *\n * @param value value to test.\n * @returns true if the value is an array or associated with an `ArrayBuffer`\n */\n qq.isArray = function(value) {\n return Object.prototype.toString.call(value) === \"[object Array]\" ||\n (value && window.ArrayBuffer && value.buffer && value.buffer.constructor === ArrayBuffer);\n };\n\n // Looks for an object on a `DataTransfer` object that is associated with drop events when utilizing the Filesystem API.\n qq.isItemList = function(maybeItemList) {\n return Object.prototype.toString.call(maybeItemList) === \"[object DataTransferItemList]\";\n };\n\n // Looks for an object on a `NodeList` or an `HTMLCollection`|`HTMLFormElement`|`HTMLSelectElement`\n // object that is associated with collections of Nodes.\n qq.isNodeList = function(maybeNodeList) {\n return Object.prototype.toString.call(maybeNodeList) === \"[object NodeList]\" ||\n // If `HTMLCollection` is the actual type of the object, we must determine this\n // by checking for expected properties/methods on the object\n (maybeNodeList.item && maybeNodeList.namedItem);\n };\n\n qq.isString = function(maybeString) {\n return Object.prototype.toString.call(maybeString) === \"[object String]\";\n };\n\n qq.trimStr = function(string) {\n if (String.prototype.trim) {\n return string.trim();\n }\n\n return string.replace(/^\\s+|\\s+$/g, \"\");\n };\n\n /**\n * @param str String to format.\n * @returns {string} A string, swapping argument values with the associated occurrence of {} in the passed string.\n */\n qq.format = function(str) {\n\n var args = Array.prototype.slice.call(arguments, 1),\n newStr = str,\n nextIdxToReplace = newStr.indexOf(\"{}\");\n\n qq.each(args, function(idx, val) {\n var strBefore = newStr.substring(0, nextIdxToReplace),\n strAfter = newStr.substring(nextIdxToReplace + 2);\n\n newStr = strBefore + val + strAfter;\n nextIdxToReplace = newStr.indexOf(\"{}\", nextIdxToReplace + val.length);\n\n // End the loop if we have run out of tokens (when the arguments exceed the # of tokens)\n if (nextIdxToReplace < 0) {\n return false;\n }\n });\n\n return newStr;\n };\n\n qq.isFile = function(maybeFile) {\n return window.File && Object.prototype.toString.call(maybeFile) === \"[object File]\";\n };\n\n qq.isFileList = function(maybeFileList) {\n return window.FileList && Object.prototype.toString.call(maybeFileList) === \"[object FileList]\";\n };\n\n qq.isFileOrInput = function(maybeFileOrInput) {\n return qq.isFile(maybeFileOrInput) || qq.isInput(maybeFileOrInput);\n };\n\n qq.isInput = function(maybeInput, notFile) {\n var evaluateType = function(type) {\n var normalizedType = type.toLowerCase();\n\n if (notFile) {\n return normalizedType !== \"file\";\n }\n\n return normalizedType === \"file\";\n };\n\n if (window.HTMLInputElement) {\n if (Object.prototype.toString.call(maybeInput) === \"[object HTMLInputElement]\") {\n if (maybeInput.type && evaluateType(maybeInput.type)) {\n return true;\n }\n }\n }\n if (maybeInput.tagName) {\n if (maybeInput.tagName.toLowerCase() === \"input\") {\n if (maybeInput.type && evaluateType(maybeInput.type)) {\n return true;\n }\n }\n }\n\n return false;\n };\n\n qq.isBlob = function(maybeBlob) {\n if (window.Blob && Object.prototype.toString.call(maybeBlob) === \"[object Blob]\") {\n return true;\n }\n };\n\n qq.isXhrUploadSupported = function() {\n var input = document.createElement(\"input\");\n input.type = \"file\";\n\n return (\n input.multiple !== undefined &&\n typeof File !== \"undefined\" &&\n typeof FormData !== \"undefined\" &&\n typeof (qq.createXhrInstance()).upload !== \"undefined\");\n };\n\n // Fall back to ActiveX is native XHR is disabled (possible in any version of IE).\n qq.createXhrInstance = function() {\n if (window.XMLHttpRequest) {\n return new XMLHttpRequest();\n }\n\n try {\n return new ActiveXObject(\"MSXML2.XMLHTTP.3.0\");\n }\n catch (error) {\n qq.log(\"Neither XHR or ActiveX are supported!\", \"error\");\n return null;\n }\n };\n\n qq.isFolderDropSupported = function(dataTransfer) {\n return dataTransfer.items &&\n dataTransfer.items.length > 0 &&\n dataTransfer.items[0].webkitGetAsEntry;\n };\n\n qq.isFileChunkingSupported = function() {\n return !qq.androidStock() && //Android's stock browser cannot upload Blobs correctly\n qq.isXhrUploadSupported() &&\n (File.prototype.slice !== undefined || File.prototype.webkitSlice !== undefined || File.prototype.mozSlice !== undefined);\n };\n\n qq.sliceBlob = function(fileOrBlob, start, end) {\n var slicer = fileOrBlob.slice || fileOrBlob.mozSlice || fileOrBlob.webkitSlice;\n\n return slicer.call(fileOrBlob, start, end);\n };\n\n qq.arrayBufferToHex = function(buffer) {\n var bytesAsHex = \"\",\n bytes = new Uint8Array(buffer);\n\n qq.each(bytes, function(idx, byt) {\n var byteAsHexStr = byt.toString(16);\n\n if (byteAsHexStr.length < 2) {\n byteAsHexStr = \"0\" + byteAsHexStr;\n }\n\n bytesAsHex += byteAsHexStr;\n });\n\n return bytesAsHex;\n };\n\n qq.readBlobToHex = function(blob, startOffset, length) {\n var initialBlob = qq.sliceBlob(blob, startOffset, startOffset + length),\n fileReader = new FileReader(),\n promise = new qq.Promise();\n\n fileReader.onload = function() {\n promise.success(qq.arrayBufferToHex(fileReader.result));\n };\n\n fileReader.onerror = promise.failure;\n\n fileReader.readAsArrayBuffer(initialBlob);\n\n return promise;\n };\n\n qq.extend = function(first, second, extendNested) {\n qq.each(second, function(prop, val) {\n if (extendNested && qq.isObject(val)) {\n if (first[prop] === undefined) {\n first[prop] = {};\n }\n qq.extend(first[prop], val, true);\n }\n else {\n first[prop] = val;\n }\n });\n\n return first;\n };\n\n /**\n * Allow properties in one object to override properties in another,\n * keeping track of the original values from the target object.\n *\n * Note that the pre-overriden properties to be overriden by the source will be passed into the `sourceFn` when it is invoked.\n *\n * @param target Update properties in this object from some source\n * @param sourceFn A function that, when invoked, will return properties that will replace properties with the same name in the target.\n * @returns {object} The target object\n */\n qq.override = function(target, sourceFn) {\n var super_ = {},\n source = sourceFn(super_);\n\n qq.each(source, function(srcPropName, srcPropVal) {\n if (target[srcPropName] !== undefined) {\n super_[srcPropName] = target[srcPropName];\n }\n\n target[srcPropName] = srcPropVal;\n });\n\n return target;\n };\n\n /**\n * Searches for a given element (elt) in the array, returns -1 if it is not present.\n */\n qq.indexOf = function(arr, elt, from) {\n if (arr.indexOf) {\n return arr.indexOf(elt, from);\n }\n\n from = from || 0;\n var len = arr.length;\n\n if (from < 0) {\n from += len;\n }\n\n for (; from < len; from += 1) {\n if (arr.hasOwnProperty(from) && arr[from] === elt) {\n return from;\n }\n }\n return -1;\n };\n\n //this is a version 4 UUID\n qq.getUniqueId = function() {\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, function(c) {\n /*jslint eqeq: true, bitwise: true*/\n var r = Math.random() * 16 | 0, v = c == \"x\" ? r : (r & 0x3 | 0x8);\n return v.toString(16);\n });\n };\n\n //\n // Browsers and platforms detection\n qq.ie = function() {\n return navigator.userAgent.indexOf(\"MSIE\") !== -1 ||\n navigator.userAgent.indexOf(\"Trident\") !== -1;\n };\n\n qq.ie7 = function() {\n return navigator.userAgent.indexOf(\"MSIE 7\") !== -1;\n };\n\n qq.ie8 = function() {\n return navigator.userAgent.indexOf(\"MSIE 8\") !== -1;\n };\n\n qq.ie10 = function() {\n return navigator.userAgent.indexOf(\"MSIE 10\") !== -1;\n };\n\n qq.ie11 = function() {\n return qq.ie() && navigator.userAgent.indexOf(\"rv:11\") !== -1;\n };\n\n qq.edge = function() {\n return navigator.userAgent.indexOf(\"Edge\") >= 0;\n };\n\n qq.safari = function() {\n return navigator.vendor !== undefined && navigator.vendor.indexOf(\"Apple\") !== -1;\n };\n\n qq.chrome = function() {\n return navigator.vendor !== undefined && navigator.vendor.indexOf(\"Google\") !== -1;\n };\n\n qq.opera = function() {\n return navigator.vendor !== undefined && navigator.vendor.indexOf(\"Opera\") !== -1;\n };\n\n qq.firefox = function() {\n return (!qq.edge() && !qq.ie11() && navigator.userAgent.indexOf(\"Mozilla\") !== -1 && navigator.vendor !== undefined && navigator.vendor === \"\");\n };\n\n qq.windows = function() {\n return navigator.platform === \"Win32\";\n };\n\n qq.android = function() {\n return navigator.userAgent.toLowerCase().indexOf(\"android\") !== -1;\n };\n\n // We need to identify the Android stock browser via the UA string to work around various bugs in this browser,\n // such as the one that prevents a `Blob` from being uploaded.\n qq.androidStock = function() {\n return qq.android() && navigator.userAgent.toLowerCase().indexOf(\"chrome\") < 0;\n };\n\n qq.ios6 = function() {\n return qq.ios() && navigator.userAgent.indexOf(\" OS 6_\") !== -1;\n };\n\n qq.ios7 = function() {\n return qq.ios() && navigator.userAgent.indexOf(\" OS 7_\") !== -1;\n };\n\n qq.ios8 = function() {\n return qq.ios() && navigator.userAgent.indexOf(\" OS 8_\") !== -1;\n };\n\n // iOS 8.0.0\n qq.ios800 = function() {\n return qq.ios() && navigator.userAgent.indexOf(\" OS 8_0 \") !== -1;\n };\n\n qq.ios = function() {\n /*jshint -W014 */\n return navigator.userAgent.indexOf(\"iPad\") !== -1\n || navigator.userAgent.indexOf(\"iPod\") !== -1\n || navigator.userAgent.indexOf(\"iPhone\") !== -1;\n };\n\n qq.iosChrome = function() {\n return qq.ios() && navigator.userAgent.indexOf(\"CriOS\") !== -1;\n };\n\n qq.iosSafari = function() {\n return qq.ios() && !qq.iosChrome() && navigator.userAgent.indexOf(\"Safari\") !== -1;\n };\n\n qq.iosSafariWebView = function() {\n return qq.ios() && !qq.iosChrome() && !qq.iosSafari();\n };\n\n //\n // Events\n\n qq.preventDefault = function(e) {\n if (e.preventDefault) {\n e.preventDefault();\n } else {\n e.returnValue = false;\n }\n };\n\n /**\n * Creates and returns element from html string\n * Uses innerHTML to create an element\n */\n qq.toElement = (function() {\n var div = document.createElement(\"div\");\n return function(html) {\n div.innerHTML = html;\n var element = div.firstChild;\n div.removeChild(element);\n return element;\n };\n }());\n\n //key and value are passed to callback for each entry in the iterable item\n qq.each = function(iterableItem, callback) {\n var keyOrIndex, retVal;\n\n if (iterableItem) {\n // Iterate through [`Storage`](http://www.w3.org/TR/webstorage/#the-storage-interface) items\n if (window.Storage && iterableItem.constructor === window.Storage) {\n for (keyOrIndex = 0; keyOrIndex < iterableItem.length; keyOrIndex++) {\n retVal = callback(iterableItem.key(keyOrIndex), iterableItem.getItem(iterableItem.key(keyOrIndex)));\n if (retVal === false) {\n break;\n }\n }\n }\n // `DataTransferItemList` & `NodeList` objects are array-like and should be treated as arrays\n // when iterating over items inside the object.\n else if (qq.isArray(iterableItem) || qq.isItemList(iterableItem) || qq.isNodeList(iterableItem)) {\n for (keyOrIndex = 0; keyOrIndex < iterableItem.length; keyOrIndex++) {\n retVal = callback(keyOrIndex, iterableItem[keyOrIndex]);\n if (retVal === false) {\n break;\n }\n }\n }\n else if (qq.isString(iterableItem)) {\n for (keyOrIndex = 0; keyOrIndex < iterableItem.length; keyOrIndex++) {\n retVal = callback(keyOrIndex, iterableItem.charAt(keyOrIndex));\n if (retVal === false) {\n break;\n }\n }\n }\n else {\n for (keyOrIndex in iterableItem) {\n if (Object.prototype.hasOwnProperty.call(iterableItem, keyOrIndex)) {\n retVal = callback(keyOrIndex, iterableItem[keyOrIndex]);\n if (retVal === false) {\n break;\n }\n }\n }\n }\n }\n };\n\n //include any args that should be passed to the new function after the context arg\n qq.bind = function(oldFunc, context) {\n if (qq.isFunction(oldFunc)) {\n var args = Array.prototype.slice.call(arguments, 2);\n\n return function() {\n var newArgs = qq.extend([], args);\n if (arguments.length) {\n newArgs = newArgs.concat(Array.prototype.slice.call(arguments));\n }\n return oldFunc.apply(context, newArgs);\n };\n }\n\n throw new Error(\"first parameter must be a function!\");\n };\n\n /**\n * obj2url() takes a json-object as argument and generates\n * a querystring. pretty much like jQuery.param()\n *\n * how to use:\n *\n * `qq.obj2url({a:'b',c:'d'},'http://any.url/upload?otherParam=value');`\n *\n * will result in:\n *\n * `http://any.url/upload?otherParam=value&a=b&c=d`\n *\n * @param Object JSON-Object\n * @param String current querystring-part\n * @return String encoded querystring\n */\n qq.obj2url = function(obj, temp, prefixDone) {\n /*jshint laxbreak: true*/\n var uristrings = [],\n prefix = \"&\",\n add = function(nextObj, i) {\n var nextTemp = temp\n ? (/\\[\\]$/.test(temp)) // prevent double-encoding\n ? temp\n : temp + \"[\" + i + \"]\"\n : i;\n if ((nextTemp !== \"undefined\") && (i !== \"undefined\")) {\n uristrings.push(\n (typeof nextObj === \"object\")\n ? qq.obj2url(nextObj, nextTemp, true)\n : (Object.prototype.toString.call(nextObj) === \"[object Function]\")\n ? encodeURIComponent(nextTemp) + \"=\" + encodeURIComponent(nextObj())\n : encodeURIComponent(nextTemp) + \"=\" + encodeURIComponent(nextObj)\n );\n }\n };\n\n if (!prefixDone && temp) {\n prefix = (/\\?/.test(temp)) ? (/\\?$/.test(temp)) ? \"\" : \"&\" : \"?\";\n uristrings.push(temp);\n uristrings.push(qq.obj2url(obj));\n } else if ((Object.prototype.toString.call(obj) === \"[object Array]\") && (typeof obj !== \"undefined\")) {\n qq.each(obj, function(idx, val) {\n add(val, idx);\n });\n } else if ((typeof obj !== \"undefined\") && (obj !== null) && (typeof obj === \"object\")) {\n qq.each(obj, function(prop, val) {\n add(val, prop);\n });\n } else {\n uristrings.push(encodeURIComponent(temp) + \"=\" + encodeURIComponent(obj));\n }\n\n if (temp) {\n return uristrings.join(prefix);\n } else {\n return uristrings.join(prefix)\n .replace(/^&/, \"\")\n .replace(/%20/g, \"+\");\n }\n };\n\n qq.obj2FormData = function(obj, formData, arrayKeyName) {\n if (!formData) {\n formData = new FormData();\n }\n\n qq.each(obj, function(key, val) {\n key = arrayKeyName ? arrayKeyName + \"[\" + key + \"]\" : key;\n\n if (qq.isObject(val)) {\n qq.obj2FormData(val, formData, key);\n }\n else if (qq.isFunction(val)) {\n formData.append(key, val());\n }\n else {\n formData.append(key, val);\n }\n });\n\n return formData;\n };\n\n qq.obj2Inputs = function(obj, form) {\n var input;\n\n if (!form) {\n form = document.createElement(\"form\");\n }\n\n qq.obj2FormData(obj, {\n append: function(key, val) {\n input = document.createElement(\"input\");\n input.setAttribute(\"name\", key);\n input.setAttribute(\"value\", val);\n form.appendChild(input);\n }\n });\n\n return form;\n };\n\n /**\n * Not recommended for use outside of Fine Uploader since this falls back to an unchecked eval if JSON.parse is not\n * implemented. For a more secure JSON.parse polyfill, use Douglas Crockford's json2.js.\n */\n qq.parseJson = function(json) {\n /*jshint evil: true*/\n if (window.JSON && qq.isFunction(JSON.parse)) {\n return JSON.parse(json);\n } else {\n return eval(\"(\" + json + \")\");\n }\n };\n\n /**\n * Retrieve the extension of a file, if it exists.\n *\n * @param filename\n * @returns {string || undefined}\n */\n qq.getExtension = function(filename) {\n var extIdx = filename.lastIndexOf(\".\") + 1;\n\n if (extIdx > 0) {\n return filename.substr(extIdx, filename.length - extIdx);\n }\n };\n\n qq.getFilename = function(blobOrFileInput) {\n /*jslint regexp: true*/\n\n if (qq.isInput(blobOrFileInput)) {\n // get input value and remove path to normalize\n return blobOrFileInput.value.replace(/.*(\\/|\\\\)/, \"\");\n }\n else if (qq.isFile(blobOrFileInput)) {\n if (blobOrFileInput.fileName !== null && blobOrFileInput.fileName !== undefined) {\n return blobOrFileInput.fileName;\n }\n }\n\n return blobOrFileInput.name;\n };\n\n /**\n * A generic module which supports object disposing in dispose() method.\n * */\n qq.DisposeSupport = function() {\n var disposers = [];\n\n return {\n /** Run all registered disposers */\n dispose: function() {\n var disposer;\n do {\n disposer = disposers.shift();\n if (disposer) {\n disposer();\n }\n }\n while (disposer);\n },\n\n /** Attach event handler and register de-attacher as a disposer */\n attach: function() {\n var args = arguments;\n /*jslint undef:true*/\n this.addDisposer(qq(args[0]).attach.apply(this, Array.prototype.slice.call(arguments, 1)));\n },\n\n /** Add disposer to the collection */\n addDisposer: function(disposeFunction) {\n disposers.push(disposeFunction);\n }\n };\n };\n}());\n","/* globals define, module, global, qq */\n(function() {\n \"use strict\";\n if (typeof define === \"function\" && define.amd) {\n define(function() {\n return qq;\n });\n }\n else if (typeof module !== \"undefined\" && module.exports) {\n module.exports = qq;\n }\n else {\n global.qq = qq;\n }\n}());\n","/* globals qq */\n/**\n * Fine Uploader top-level Error container. Inherits from `Error`.\n */\n(function() {\n \"use strict\";\n\n qq.Error = function(message) {\n this.message = \"[Fine Uploader \" + qq.version + \"] \" + message;\n };\n\n qq.Error.prototype = new Error();\n}());\n","/*global qq */\nqq.version = \"5.16.2\";\n","/* globals qq */\nqq.supportedFeatures = (function() {\n \"use strict\";\n\n var supportsUploading,\n supportsUploadingBlobs,\n supportsFileDrop,\n supportsAjaxFileUploading,\n supportsFolderDrop,\n supportsChunking,\n supportsResume,\n supportsUploadViaPaste,\n supportsUploadCors,\n supportsDeleteFileXdr,\n supportsDeleteFileCorsXhr,\n supportsDeleteFileCors,\n supportsFolderSelection,\n supportsImagePreviews,\n supportsUploadProgress;\n\n function testSupportsFileInputElement() {\n var supported = true,\n tempInput;\n\n try {\n tempInput = document.createElement(\"input\");\n tempInput.type = \"file\";\n qq(tempInput).hide();\n\n if (tempInput.disabled) {\n supported = false;\n }\n }\n catch (ex) {\n supported = false;\n }\n\n return supported;\n }\n\n //only way to test for complete Clipboard API support at this time\n function isChrome14OrHigher() {\n return (qq.chrome() || qq.opera()) &&\n navigator.userAgent.match(/Chrome\\/[1][4-9]|Chrome\\/[2-9][0-9]/) !== undefined;\n }\n\n //Ensure we can send cross-origin `XMLHttpRequest`s\n function isCrossOriginXhrSupported() {\n if (window.XMLHttpRequest) {\n var xhr = qq.createXhrInstance();\n\n //Commonly accepted test for XHR CORS support.\n return xhr.withCredentials !== undefined;\n }\n\n return false;\n }\n\n //Test for (terrible) cross-origin ajax transport fallback for IE9 and IE8\n function isXdrSupported() {\n return window.XDomainRequest !== undefined;\n }\n\n // CORS Ajax requests are supported if it is either possible to send credentialed `XMLHttpRequest`s,\n // or if `XDomainRequest` is an available alternative.\n function isCrossOriginAjaxSupported() {\n if (isCrossOriginXhrSupported()) {\n return true;\n }\n\n return isXdrSupported();\n }\n\n function isFolderSelectionSupported() {\n // We know that folder selection is only supported in Chrome via this proprietary attribute for now\n return document.createElement(\"input\").webkitdirectory !== undefined;\n }\n\n function isLocalStorageSupported() {\n try {\n return !!window.localStorage &&\n // unpatched versions of IE10/11 have buggy impls of localStorage where setItem is a string\n qq.isFunction(window.localStorage.setItem);\n }\n catch (error) {\n // probably caught a security exception, so no localStorage for you\n return false;\n }\n }\n\n function isDragAndDropSupported() {\n var span = document.createElement(\"span\");\n\n return (\"draggable\" in span || (\"ondragstart\" in span && \"ondrop\" in span)) &&\n !qq.android() && !qq.ios();\n }\n\n supportsUploading = testSupportsFileInputElement();\n\n supportsAjaxFileUploading = supportsUploading && qq.isXhrUploadSupported();\n\n supportsUploadingBlobs = supportsAjaxFileUploading && !qq.androidStock();\n\n supportsFileDrop = supportsAjaxFileUploading && isDragAndDropSupported();\n\n // adapted from https://stackoverflow.com/a/23278460/486979\n supportsFolderDrop = supportsFileDrop && (function() {\n var input = document.createElement(\"input\");\n\n input.type = \"file\";\n return !!(\"webkitdirectory\" in (input || document.querySelectorAll(\"input[type=file]\")[0]));\n }());\n\n supportsChunking = supportsAjaxFileUploading && qq.isFileChunkingSupported();\n\n supportsResume = supportsAjaxFileUploading && supportsChunking && isLocalStorageSupported();\n\n supportsUploadViaPaste = supportsAjaxFileUploading && isChrome14OrHigher();\n\n supportsUploadCors = supportsUploading && (window.postMessage !== undefined || supportsAjaxFileUploading);\n\n supportsDeleteFileCorsXhr = isCrossOriginXhrSupported();\n\n supportsDeleteFileXdr = isXdrSupported();\n\n supportsDeleteFileCors = isCrossOriginAjaxSupported();\n\n supportsFolderSelection = isFolderSelectionSupported();\n\n supportsImagePreviews = supportsAjaxFileUploading && window.FileReader !== undefined;\n\n supportsUploadProgress = (function() {\n if (supportsAjaxFileUploading) {\n return !qq.androidStock() && !qq.iosChrome();\n }\n return false;\n }());\n\n return {\n ajaxUploading: supportsAjaxFileUploading,\n blobUploading: supportsUploadingBlobs,\n canDetermineSize: supportsAjaxFileUploading,\n chunking: supportsChunking,\n deleteFileCors: supportsDeleteFileCors,\n deleteFileCorsXdr: supportsDeleteFileXdr, //NOTE: will also return true in IE10, where XDR is also supported\n deleteFileCorsXhr: supportsDeleteFileCorsXhr,\n dialogElement: !!window.HTMLDialogElement,\n fileDrop: supportsFileDrop,\n folderDrop: supportsFolderDrop,\n folderSelection: supportsFolderSelection,\n imagePreviews: supportsImagePreviews,\n imageValidation: supportsImagePreviews,\n itemSizeValidation: supportsAjaxFileUploading,\n pause: supportsChunking,\n progressBar: supportsUploadProgress,\n resume: supportsResume,\n scaling: supportsImagePreviews && supportsUploadingBlobs,\n tiffPreviews: qq.safari(), // Not the best solution, but simple and probably accurate enough (for now)\n unlimitedScaledImageSize: !qq.ios(), // false simply indicates that there is some known limit\n uploading: supportsUploading,\n uploadCors: supportsUploadCors,\n uploadCustomHeaders: supportsAjaxFileUploading,\n uploadNonMultipart: supportsAjaxFileUploading,\n uploadViaPaste: supportsUploadViaPaste\n };\n\n}());\n","/*globals qq*/\n\n// Is the passed object a promise instance?\nqq.isGenericPromise = function(maybePromise) {\n \"use strict\";\n return !!(maybePromise && maybePromise.then && qq.isFunction(maybePromise.then));\n};\n\nqq.Promise = function() {\n \"use strict\";\n\n var successArgs, failureArgs,\n successCallbacks = [],\n failureCallbacks = [],\n doneCallbacks = [],\n state = 0;\n\n qq.extend(this, {\n then: function(onSuccess, onFailure) {\n if (state === 0) {\n if (onSuccess) {\n successCallbacks.push(onSuccess);\n }\n if (onFailure) {\n failureCallbacks.push(onFailure);\n }\n }\n else if (state === -1) {\n onFailure && onFailure.apply(null, failureArgs);\n }\n else if (onSuccess) {\n onSuccess.apply(null, successArgs);\n }\n\n return this;\n },\n\n done: function(callback) {\n if (state === 0) {\n doneCallbacks.push(callback);\n }\n else {\n callback.apply(null, failureArgs === undefined ? successArgs : failureArgs);\n }\n\n return this;\n },\n\n success: function() {\n state = 1;\n successArgs = arguments;\n\n if (successCallbacks.length) {\n qq.each(successCallbacks, function(idx, callback) {\n callback.apply(null, successArgs);\n });\n }\n\n if (doneCallbacks.length) {\n qq.each(doneCallbacks, function(idx, callback) {\n callback.apply(null, successArgs);\n });\n }\n\n return this;\n },\n\n failure: function() {\n state = -1;\n failureArgs = arguments;\n\n if (failureCallbacks.length) {\n qq.each(failureCallbacks, function(idx, callback) {\n callback.apply(null, failureArgs);\n });\n }\n\n if (doneCallbacks.length) {\n qq.each(doneCallbacks, function(idx, callback) {\n callback.apply(null, failureArgs);\n });\n }\n\n return this;\n }\n });\n};\n","/* globals qq */\n/**\n * Placeholder for a Blob that will be generated on-demand.\n *\n * @param referenceBlob Parent of the generated blob\n * @param onCreate Function to invoke when the blob must be created. Must be promissory.\n * @constructor\n */\nqq.BlobProxy = function(referenceBlob, onCreate) {\n \"use strict\";\n\n qq.extend(this, {\n referenceBlob: referenceBlob,\n\n create: function() {\n return onCreate(referenceBlob);\n }\n });\n};\n","/*globals qq*/\n\n/**\n * This module represents an upload or \"Select File(s)\" button. It's job is to embed an opaque ` `\n * element as a child of a provided \"container\" element. This \"container\" element (`options.element`) is used to provide\n * a custom style for the ` ` element. The ability to change the style of the container element is also\n * provided here by adding CSS classes to the container on hover/focus.\n *\n * TODO Eliminate the mouseover and mouseout event handlers since the :hover CSS pseudo-class should now be\n * available on all supported browsers.\n *\n * @param o Options to override the default values\n */\nqq.UploadButton = function(o) {\n \"use strict\";\n\n var self = this,\n\n disposeSupport = new qq.DisposeSupport(),\n\n options = {\n // Corresponds to the `accept` attribute on the associated ` `\n acceptFiles: null,\n\n // \"Container\" element\n element: null,\n\n focusClass: \"qq-upload-button-focus\",\n\n // A true value allows folders to be selected, if supported by the UA\n folders: false,\n\n // **This option will be removed** in the future as the :hover CSS pseudo-class is available on all supported browsers\n hoverClass: \"qq-upload-button-hover\",\n\n ios8BrowserCrashWorkaround: false,\n\n // If true adds `multiple` attribute to ` `\n multiple: false,\n\n // `name` attribute of ` `\n name: \"qqfile\",\n\n // Called when the browser invokes the onchange handler on the ` `\n onChange: function(input) {},\n\n title: null\n },\n input, buttonId;\n\n // Overrides any of the default option values with any option values passed in during construction.\n qq.extend(options, o);\n\n buttonId = qq.getUniqueId();\n\n // Embed an opaque ` ` element as a child of `options.element`.\n function createInput() {\n var input = document.createElement(\"input\");\n\n input.setAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME, buttonId);\n input.setAttribute(\"title\", options.title);\n\n self.setMultiple(options.multiple, input);\n\n if (options.folders && qq.supportedFeatures.folderSelection) {\n // selecting directories is only possible in Chrome now, via a vendor-specific prefixed attribute\n input.setAttribute(\"webkitdirectory\", \"\");\n }\n\n if (options.acceptFiles) {\n input.setAttribute(\"accept\", options.acceptFiles);\n }\n\n input.setAttribute(\"type\", \"file\");\n input.setAttribute(\"name\", options.name);\n\n qq(input).css({\n position: \"absolute\",\n // in Opera only 'browse' button\n // is clickable and it is located at\n // the right side of the input\n right: 0,\n top: 0,\n fontFamily: \"Arial\",\n // It's especially important to make this an arbitrarily large value\n // to ensure the rendered input button in IE takes up the entire\n // space of the container element. Otherwise, the left side of the\n // button will require a double-click to invoke the file chooser.\n // In other browsers, this might cause other issues, so a large font-size\n // is only used in IE. There is a bug in IE8 where the opacity style is ignored\n // in some cases when the font-size is large. So, this workaround is not applied\n // to IE8.\n fontSize: qq.ie() && !qq.ie8() ? \"3500px\" : \"118px\",\n margin: 0,\n padding: 0,\n cursor: \"pointer\",\n opacity: 0\n });\n\n // Setting the file input's height to 100% in IE7 causes\n // most of the visible button to be unclickable.\n !qq.ie7() && qq(input).css({height: \"100%\"});\n\n options.element.appendChild(input);\n\n disposeSupport.attach(input, \"change\", function() {\n options.onChange(input);\n });\n\n // **These event handlers will be removed** in the future as the :hover CSS pseudo-class is available on all supported browsers\n disposeSupport.attach(input, \"mouseover\", function() {\n qq(options.element).addClass(options.hoverClass);\n });\n disposeSupport.attach(input, \"mouseout\", function() {\n qq(options.element).removeClass(options.hoverClass);\n });\n\n disposeSupport.attach(input, \"focus\", function() {\n qq(options.element).addClass(options.focusClass);\n });\n disposeSupport.attach(input, \"blur\", function() {\n qq(options.element).removeClass(options.focusClass);\n });\n\n return input;\n }\n\n // Make button suitable container for input\n qq(options.element).css({\n position: \"relative\",\n overflow: \"hidden\",\n // Make sure browse button is in the right side in Internet Explorer\n direction: \"ltr\"\n });\n\n // Exposed API\n qq.extend(this, {\n getInput: function() {\n return input;\n },\n\n getButtonId: function() {\n return buttonId;\n },\n\n setMultiple: function(isMultiple, optInput) {\n var input = optInput || this.getInput();\n\n // Temporary workaround for bug in in iOS8 UIWebView that causes the browser to crash\n // before the file chooser appears if the file input doesn't contain a multiple attribute.\n // See #1283.\n if (options.ios8BrowserCrashWorkaround && qq.ios8() && (qq.iosChrome() || qq.iosSafariWebView())) {\n input.setAttribute(\"multiple\", \"\");\n }\n\n else {\n if (isMultiple) {\n input.setAttribute(\"multiple\", \"\");\n }\n else {\n input.removeAttribute(\"multiple\");\n }\n }\n },\n\n setAcceptFiles: function(acceptFiles) {\n if (acceptFiles !== options.acceptFiles) {\n input.setAttribute(\"accept\", acceptFiles);\n }\n },\n\n reset: function() {\n if (input.parentNode) {\n qq(input).remove();\n }\n\n qq(options.element).removeClass(options.focusClass);\n input = null;\n input = createInput();\n }\n });\n\n input = createInput();\n};\n\nqq.UploadButton.BUTTON_ID_ATTR_NAME = \"qq-button-id\";\n","/*globals qq */\nqq.UploadData = function(uploaderProxy) {\n \"use strict\";\n\n var data = [],\n byUuid = {},\n byStatus = {},\n byProxyGroupId = {},\n byBatchId = {};\n\n function getDataByIds(idOrIds) {\n if (qq.isArray(idOrIds)) {\n var entries = [];\n\n qq.each(idOrIds, function(idx, id) {\n entries.push(data[id]);\n });\n\n return entries;\n }\n\n return data[idOrIds];\n }\n\n function getDataByUuids(uuids) {\n if (qq.isArray(uuids)) {\n var entries = [];\n\n qq.each(uuids, function(idx, uuid) {\n entries.push(data[byUuid[uuid]]);\n });\n\n return entries;\n }\n\n return data[byUuid[uuids]];\n }\n\n function getDataByStatus(status) {\n var statusResults = [],\n statuses = [].concat(status);\n\n qq.each(statuses, function(index, statusEnum) {\n var statusResultIndexes = byStatus[statusEnum];\n\n if (statusResultIndexes !== undefined) {\n qq.each(statusResultIndexes, function(i, dataIndex) {\n statusResults.push(data[dataIndex]);\n });\n }\n });\n\n return statusResults;\n }\n\n qq.extend(this, {\n /**\n * Adds a new file to the data cache for tracking purposes.\n *\n * @param spec Data that describes this file. Possible properties are:\n *\n * - uuid: Initial UUID for this file.\n * - name: Initial name of this file.\n * - size: Size of this file, omit if this cannot be determined\n * - status: Initial `qq.status` for this file. Omit for `qq.status.SUBMITTING`.\n * - batchId: ID of the batch this file belongs to\n * - proxyGroupId: ID of the proxy group associated with this file\n * - onBeforeStatusChange(fileId): callback that is executed before the status change is broadcast\n *\n * @returns {number} Internal ID for this file.\n */\n addFile: function(spec) {\n var status = spec.status || qq.status.SUBMITTING,\n id = data.push({\n name: spec.name,\n originalName: spec.name,\n uuid: spec.uuid,\n size: spec.size == null ? -1 : spec.size,\n status: status,\n file: spec.file\n }) - 1;\n\n if (spec.batchId) {\n data[id].batchId = spec.batchId;\n\n if (byBatchId[spec.batchId] === undefined) {\n byBatchId[spec.batchId] = [];\n }\n byBatchId[spec.batchId].push(id);\n }\n\n if (spec.proxyGroupId) {\n data[id].proxyGroupId = spec.proxyGroupId;\n\n if (byProxyGroupId[spec.proxyGroupId] === undefined) {\n byProxyGroupId[spec.proxyGroupId] = [];\n }\n byProxyGroupId[spec.proxyGroupId].push(id);\n }\n\n data[id].id = id;\n byUuid[spec.uuid] = id;\n\n if (byStatus[status] === undefined) {\n byStatus[status] = [];\n }\n byStatus[status].push(id);\n\n spec.onBeforeStatusChange && spec.onBeforeStatusChange(id);\n uploaderProxy.onStatusChange(id, null, status);\n\n return id;\n },\n\n retrieve: function(optionalFilter) {\n if (qq.isObject(optionalFilter) && data.length) {\n if (optionalFilter.id !== undefined) {\n return getDataByIds(optionalFilter.id);\n }\n\n else if (optionalFilter.uuid !== undefined) {\n return getDataByUuids(optionalFilter.uuid);\n }\n\n else if (optionalFilter.status) {\n return getDataByStatus(optionalFilter.status);\n }\n }\n else {\n return qq.extend([], data, true);\n }\n },\n\n removeFileRef: function(id) {\n var record = getDataByIds(id);\n\n if (record) {\n delete record.file;\n }\n },\n\n reset: function() {\n data = [];\n byUuid = {};\n byStatus = {};\n byBatchId = {};\n },\n\n setStatus: function(id, newStatus) {\n var oldStatus = data[id].status,\n byStatusOldStatusIndex = qq.indexOf(byStatus[oldStatus], id);\n\n byStatus[oldStatus].splice(byStatusOldStatusIndex, 1);\n\n data[id].status = newStatus;\n\n if (byStatus[newStatus] === undefined) {\n byStatus[newStatus] = [];\n }\n byStatus[newStatus].push(id);\n\n uploaderProxy.onStatusChange(id, oldStatus, newStatus);\n },\n\n uuidChanged: function(id, newUuid) {\n var oldUuid = data[id].uuid;\n\n data[id].uuid = newUuid;\n byUuid[newUuid] = id;\n delete byUuid[oldUuid];\n },\n\n updateName: function(id, newName) {\n data[id].name = newName;\n },\n\n updateSize: function(id, newSize) {\n data[id].size = newSize;\n },\n\n // Only applicable if this file has a parent that we may want to reference later.\n setParentId: function(targetId, parentId) {\n data[targetId].parentId = parentId;\n },\n\n getIdsInProxyGroup: function(id) {\n var proxyGroupId = data[id].proxyGroupId;\n\n if (proxyGroupId) {\n return byProxyGroupId[proxyGroupId];\n }\n return [];\n },\n\n getIdsInBatch: function(id) {\n var batchId = data[id].batchId;\n\n return byBatchId[batchId];\n }\n });\n};\n\nqq.status = {\n SUBMITTING: \"submitting\",\n SUBMITTED: \"submitted\",\n REJECTED: \"rejected\",\n QUEUED: \"queued\",\n CANCELED: \"canceled\",\n PAUSED: \"paused\",\n UPLOADING: \"uploading\",\n UPLOAD_FINALIZING: \"upload finalizing\",\n UPLOAD_RETRYING: \"retrying upload\",\n UPLOAD_SUCCESSFUL: \"upload successful\",\n UPLOAD_FAILED: \"upload failed\",\n DELETE_FAILED: \"delete failed\",\n DELETING: \"deleting\",\n DELETED: \"deleted\"\n};\n","/*globals qq*/\n/**\n * Defines the public API for FineUploaderBasic mode.\n */\n(function() {\n \"use strict\";\n\n qq.basePublicApi = {\n // DEPRECATED - TODO REMOVE IN NEXT MAJOR RELEASE (replaced by addFiles)\n addBlobs: function(blobDataOrArray, params, endpoint) {\n this.addFiles(blobDataOrArray, params, endpoint);\n },\n\n addInitialFiles: function(cannedFileList) {\n var self = this;\n\n qq.each(cannedFileList, function(index, cannedFile) {\n self._addCannedFile(cannedFile);\n });\n },\n\n addFiles: function(data, params, endpoint) {\n this._maybeHandleIos8SafariWorkaround();\n\n var batchId = this._storedIds.length === 0 ? qq.getUniqueId() : this._currentBatchId,\n\n processBlob = qq.bind(function(blob) {\n this._handleNewFile({\n blob: blob,\n name: this._options.blobs.defaultName\n }, batchId, verifiedFiles);\n }, this),\n\n processBlobData = qq.bind(function(blobData) {\n this._handleNewFile(blobData, batchId, verifiedFiles);\n }, this),\n\n processCanvas = qq.bind(function(canvas) {\n var blob = qq.canvasToBlob(canvas);\n\n this._handleNewFile({\n blob: blob,\n name: this._options.blobs.defaultName + \".png\"\n }, batchId, verifiedFiles);\n }, this),\n\n processCanvasData = qq.bind(function(canvasData) {\n var normalizedQuality = canvasData.quality && canvasData.quality / 100,\n blob = qq.canvasToBlob(canvasData.canvas, canvasData.type, normalizedQuality);\n\n this._handleNewFile({\n blob: blob,\n name: canvasData.name\n }, batchId, verifiedFiles);\n }, this),\n\n processFileOrInput = qq.bind(function(fileOrInput) {\n if (qq.isInput(fileOrInput) && qq.supportedFeatures.ajaxUploading) {\n var files = Array.prototype.slice.call(fileOrInput.files),\n self = this;\n\n qq.each(files, function(idx, file) {\n self._handleNewFile(file, batchId, verifiedFiles);\n });\n }\n else {\n this._handleNewFile(fileOrInput, batchId, verifiedFiles);\n }\n }, this),\n\n normalizeData = function() {\n if (qq.isFileList(data)) {\n data = Array.prototype.slice.call(data);\n }\n data = [].concat(data);\n },\n\n self = this,\n verifiedFiles = [];\n\n this._currentBatchId = batchId;\n\n if (data) {\n normalizeData();\n\n qq.each(data, function(idx, fileContainer) {\n if (qq.isFileOrInput(fileContainer)) {\n processFileOrInput(fileContainer);\n }\n else if (qq.isBlob(fileContainer)) {\n processBlob(fileContainer);\n }\n else if (qq.isObject(fileContainer)) {\n if (fileContainer.blob && fileContainer.name) {\n processBlobData(fileContainer);\n }\n else if (fileContainer.canvas && fileContainer.name) {\n processCanvasData(fileContainer);\n }\n }\n else if (fileContainer.tagName && fileContainer.tagName.toLowerCase() === \"canvas\") {\n processCanvas(fileContainer);\n }\n else {\n self.log(fileContainer + \" is not a valid file container! Ignoring!\", \"warn\");\n }\n });\n\n this.log(\"Received \" + verifiedFiles.length + \" files.\");\n this._prepareItemsForUpload(verifiedFiles, params, endpoint);\n }\n },\n\n cancel: function(id) {\n var uploadData = this._uploadData.retrieve({id: id});\n\n if (uploadData && uploadData.status === qq.status.UPLOAD_FINALIZING) {\n this.log(qq.format(\"Ignoring cancel for file ID {} ({}). Finalizing upload.\", id, this.getName(id)), \"error\");\n }\n else {\n this._handler.cancel(id);\n }\n },\n\n cancelAll: function() {\n var storedIdsCopy = [],\n self = this;\n\n qq.extend(storedIdsCopy, this._storedIds);\n qq.each(storedIdsCopy, function(idx, storedFileId) {\n self.cancel(storedFileId);\n });\n\n this._handler.cancelAll();\n },\n\n clearStoredFiles: function() {\n this._storedIds = [];\n },\n\n continueUpload: function(id) {\n var uploadData = this._uploadData.retrieve({id: id});\n\n if (!qq.supportedFeatures.pause || !this._options.chunking.enabled) {\n return false;\n }\n\n if (uploadData.status === qq.status.PAUSED) {\n this.log(qq.format(\"Paused file ID {} ({}) will be continued. Not paused.\", id, this.getName(id)));\n this._uploadFile(id);\n return true;\n }\n else {\n this.log(qq.format(\"Ignoring continue for file ID {} ({}). Not paused.\", id, this.getName(id)), \"error\");\n }\n\n return false;\n },\n\n deleteFile: function(id) {\n return this._onSubmitDelete(id);\n },\n\n // TODO document?\n doesExist: function(fileOrBlobId) {\n return this._handler.isValid(fileOrBlobId);\n },\n\n // Generate a variable size thumbnail on an img or canvas,\n // returning a promise that is fulfilled when the attempt completes.\n // Thumbnail can either be based off of a URL for an image returned\n // by the server in the upload response, or the associated `Blob`.\n drawThumbnail: function(fileId, imgOrCanvas, maxSize, fromServer, customResizeFunction) {\n var promiseToReturn = new qq.Promise(),\n fileOrUrl, options;\n\n if (this._imageGenerator) {\n fileOrUrl = this._thumbnailUrls[fileId];\n options = {\n customResizeFunction: customResizeFunction,\n maxSize: maxSize > 0 ? maxSize : null,\n scale: maxSize > 0\n };\n\n // If client-side preview generation is possible\n // and we are not specifically looking for the image URl returned by the server...\n if (!fromServer && qq.supportedFeatures.imagePreviews) {\n fileOrUrl = this.getFile(fileId);\n }\n\n /* jshint eqeqeq:false,eqnull:true */\n if (fileOrUrl == null) {\n promiseToReturn.failure({container: imgOrCanvas, error: \"File or URL not found.\"});\n }\n else {\n this._imageGenerator.generate(fileOrUrl, imgOrCanvas, options).then(\n function success(modifiedContainer) {\n promiseToReturn.success(modifiedContainer);\n },\n\n function failure(container, reason) {\n promiseToReturn.failure({container: container, error: reason || \"Problem generating thumbnail\"});\n }\n );\n }\n }\n else {\n promiseToReturn.failure({container: imgOrCanvas, error: \"Missing image generator module\"});\n }\n\n return promiseToReturn;\n },\n\n getButton: function(fileId) {\n return this._getButton(this._buttonIdsForFileIds[fileId]);\n },\n\n getEndpoint: function(fileId) {\n return this._endpointStore.get(fileId);\n },\n\n getFile: function(fileOrBlobId) {\n var file = this._handler.getFile(fileOrBlobId);\n var uploadDataRecord;\n\n if (!file) {\n uploadDataRecord = this._uploadData.retrieve({id: fileOrBlobId});\n\n if (uploadDataRecord) {\n file = uploadDataRecord.file;\n }\n }\n\n return file || null;\n },\n\n getInProgress: function() {\n return this._uploadData.retrieve({\n status: [\n qq.status.UPLOADING,\n qq.status.UPLOAD_RETRYING,\n qq.status.QUEUED\n ]\n }).length;\n },\n\n getName: function(id) {\n return this._uploadData.retrieve({id: id}).name;\n },\n\n // Parent ID for a specific file, or null if this is the parent, or if it has no parent.\n getParentId: function(id) {\n var uploadDataEntry = this.getUploads({id: id}),\n parentId = null;\n\n if (uploadDataEntry) {\n if (uploadDataEntry.parentId !== undefined) {\n parentId = uploadDataEntry.parentId;\n }\n }\n\n return parentId;\n },\n\n getResumableFilesData: function() {\n return this._handler.getResumableFilesData();\n },\n\n getSize: function(id) {\n return this._uploadData.retrieve({id: id}).size;\n },\n\n getNetUploads: function() {\n return this._netUploaded;\n },\n\n getRemainingAllowedItems: function() {\n var allowedItems = this._currentItemLimit;\n\n if (allowedItems > 0) {\n return allowedItems - this._netUploadedOrQueued;\n }\n\n return null;\n },\n\n getUploads: function(optionalFilter) {\n return this._uploadData.retrieve(optionalFilter);\n },\n\n getUuid: function(id) {\n return this._uploadData.retrieve({id: id}).uuid;\n },\n\n isResumable: function(id) {\n return this._handler.hasResumeRecord(id);\n },\n\n log: function(str, level) {\n if (this._options.debug && (!level || level === \"info\")) {\n qq.log(\"[Fine Uploader \" + qq.version + \"] \" + str);\n }\n else if (level && level !== \"info\") {\n qq.log(\"[Fine Uploader \" + qq.version + \"] \" + str, level);\n\n }\n },\n\n pauseUpload: function(id) {\n var uploadData = this._uploadData.retrieve({id: id});\n\n if (!qq.supportedFeatures.pause || !this._options.chunking.enabled) {\n return false;\n }\n\n // Pause only really makes sense if the file is uploading or retrying\n if (qq.indexOf([qq.status.UPLOADING, qq.status.UPLOAD_RETRYING], uploadData.status) >= 0) {\n if (this._handler.pause(id)) {\n this._uploadData.setStatus(id, qq.status.PAUSED);\n return true;\n }\n else {\n this.log(qq.format(\"Unable to pause file ID {} ({}).\", id, this.getName(id)), \"error\");\n }\n }\n else {\n this.log(qq.format(\"Ignoring pause for file ID {} ({}). Not in progress.\", id, this.getName(id)), \"error\");\n }\n\n return false;\n },\n\n removeFileRef: function(id) {\n this._handler.expunge(id);\n this._uploadData.removeFileRef(id);\n },\n\n reset: function() {\n this.log(\"Resetting uploader...\");\n\n this._handler.reset();\n this._storedIds = [];\n this._autoRetries = [];\n this._retryTimeouts = [];\n this._preventRetries = [];\n this._thumbnailUrls = [];\n\n qq.each(this._buttons, function(idx, button) {\n button.reset();\n });\n\n this._paramsStore.reset();\n this._endpointStore.reset();\n this._netUploadedOrQueued = 0;\n this._netUploaded = 0;\n this._uploadData.reset();\n this._buttonIdsForFileIds = [];\n\n this._pasteHandler && this._pasteHandler.reset();\n this._options.session.refreshOnReset && this._refreshSessionData();\n\n this._succeededSinceLastAllComplete = [];\n this._failedSinceLastAllComplete = [];\n\n this._totalProgress && this._totalProgress.reset();\n\n this._customResumeDataStore.reset();\n },\n\n retry: function(id) {\n return this._manualRetry(id);\n },\n\n scaleImage: function(id, specs) {\n var self = this;\n\n return qq.Scaler.prototype.scaleImage(id, specs, {\n log: qq.bind(self.log, self),\n getFile: qq.bind(self.getFile, self),\n uploadData: self._uploadData\n });\n },\n\n setCustomHeaders: function(headers, id) {\n this._customHeadersStore.set(headers, id);\n },\n\n setCustomResumeData: function(id, data) {\n this._customResumeDataStore.set(data, id);\n },\n\n setDeleteFileCustomHeaders: function(headers, id) {\n this._deleteFileCustomHeadersStore.set(headers, id);\n },\n\n setDeleteFileEndpoint: function(endpoint, id) {\n this._deleteFileEndpointStore.set(endpoint, id);\n },\n\n setDeleteFileParams: function(params, id) {\n this._deleteFileParamsStore.set(params, id);\n },\n\n // Re-sets the default endpoint, an endpoint for a specific file, or an endpoint for a specific button\n setEndpoint: function(endpoint, id) {\n this._endpointStore.set(endpoint, id);\n },\n\n setForm: function(elementOrId) {\n this._updateFormSupportAndParams(elementOrId);\n },\n\n setItemLimit: function(newItemLimit) {\n this._currentItemLimit = newItemLimit;\n },\n\n setName: function(id, newName) {\n this._uploadData.updateName(id, newName);\n },\n\n setParams: function(params, id) {\n this._paramsStore.set(params, id);\n },\n\n setUuid: function(id, newUuid) {\n return this._uploadData.uuidChanged(id, newUuid);\n },\n\n /**\n * Expose the internal status of a file id to the public api for manual state changes\n * @public\n *\n * @param {Number} id,\n * @param {String} newStatus\n *\n * @todo Implement the remaining methods\n */\n setStatus: function(id, newStatus) {\n var fileRecord = this.getUploads({id: id});\n if (!fileRecord) {\n throw new qq.Error(id + \" is not a valid file ID.\");\n }\n\n switch (newStatus) {\n case qq.status.DELETED:\n this._onDeleteComplete(id, null, false);\n break;\n case qq.status.DELETE_FAILED:\n this._onDeleteComplete(id, null, true);\n break;\n default:\n var errorMessage = \"Method setStatus called on '\" + name + \"' not implemented yet for \" + newStatus;\n this.log(errorMessage);\n throw new qq.Error(errorMessage);\n }\n },\n\n uploadStoredFiles: function() {\n if (this._storedIds.length === 0) {\n this._itemError(\"noFilesError\");\n }\n else {\n this._uploadStoredFiles();\n }\n }\n };\n\n /**\n * Defines the private (internal) API for FineUploaderBasic mode.\n */\n qq.basePrivateApi = {\n // Updates internal state with a file record (not backed by a live file). Returns the assigned ID.\n _addCannedFile: function(sessionData) {\n var self = this;\n\n return this._uploadData.addFile({\n uuid: sessionData.uuid,\n name: sessionData.name,\n size: sessionData.size,\n status: qq.status.UPLOAD_SUCCESSFUL,\n onBeforeStatusChange: function(id) {\n sessionData.deleteFileEndpoint && self.setDeleteFileEndpoint(sessionData.deleteFileEndpoint, id);\n sessionData.deleteFileParams && self.setDeleteFileParams(sessionData.deleteFileParams, id);\n\n if (sessionData.thumbnailUrl) {\n self._thumbnailUrls[id] = sessionData.thumbnailUrl;\n }\n\n self._netUploaded++;\n self._netUploadedOrQueued++;\n }\n });\n },\n\n _annotateWithButtonId: function(file, associatedInput) {\n if (qq.isFile(file)) {\n file.qqButtonId = this._getButtonId(associatedInput);\n }\n },\n\n _batchError: function(message) {\n this._options.callbacks.onError(null, null, message, undefined);\n },\n\n _createDeleteHandler: function() {\n var self = this;\n\n return new qq.DeleteFileAjaxRequester({\n method: this._options.deleteFile.method.toUpperCase(),\n maxConnections: this._options.maxConnections,\n uuidParamName: this._options.request.uuidName,\n customHeaders: this._deleteFileCustomHeadersStore,\n paramsStore: this._deleteFileParamsStore,\n endpointStore: this._deleteFileEndpointStore,\n cors: this._options.cors,\n log: qq.bind(self.log, self),\n onDelete: function(id) {\n self._onDelete(id);\n self._options.callbacks.onDelete(id);\n },\n onDeleteComplete: function(id, xhrOrXdr, isError) {\n self._onDeleteComplete(id, xhrOrXdr, isError);\n self._options.callbacks.onDeleteComplete(id, xhrOrXdr, isError);\n }\n\n });\n },\n\n _createPasteHandler: function() {\n var self = this;\n\n return new qq.PasteSupport({\n targetElement: this._options.paste.targetElement,\n callbacks: {\n log: qq.bind(self.log, self),\n pasteReceived: function(blob) {\n self._handleCheckedCallback({\n name: \"onPasteReceived\",\n callback: qq.bind(self._options.callbacks.onPasteReceived, self, blob),\n onSuccess: qq.bind(self._handlePasteSuccess, self, blob),\n identifier: \"pasted image\"\n });\n }\n }\n });\n },\n\n _createStore: function(initialValue, _readOnlyValues_) {\n var store = {},\n catchall = initialValue,\n perIdReadOnlyValues = {},\n readOnlyValues = _readOnlyValues_,\n copy = function(orig) {\n if (qq.isObject(orig)) {\n return qq.extend({}, orig);\n }\n return orig;\n },\n getReadOnlyValues = function() {\n if (qq.isFunction(readOnlyValues)) {\n return readOnlyValues();\n }\n return readOnlyValues;\n },\n includeReadOnlyValues = function(id, existing) {\n if (readOnlyValues && qq.isObject(existing)) {\n qq.extend(existing, getReadOnlyValues());\n }\n\n if (perIdReadOnlyValues[id]) {\n qq.extend(existing, perIdReadOnlyValues[id]);\n }\n };\n\n return {\n set: function(val, id) {\n /*jshint eqeqeq: true, eqnull: true*/\n if (id == null) {\n store = {};\n catchall = copy(val);\n }\n else {\n store[id] = copy(val);\n }\n },\n\n get: function(id) {\n var values;\n\n /*jshint eqeqeq: true, eqnull: true*/\n if (id != null && store[id]) {\n values = store[id];\n }\n else {\n values = copy(catchall);\n }\n\n includeReadOnlyValues(id, values);\n\n return copy(values);\n },\n\n addReadOnly: function(id, values) {\n // Only applicable to Object stores\n if (qq.isObject(store)) {\n // If null ID, apply readonly values to all files\n if (id === null) {\n if (qq.isFunction(values)) {\n readOnlyValues = values;\n }\n else {\n readOnlyValues = readOnlyValues || {};\n qq.extend(readOnlyValues, values);\n }\n }\n else {\n perIdReadOnlyValues[id] = perIdReadOnlyValues[id] || {};\n qq.extend(perIdReadOnlyValues[id], values);\n }\n }\n },\n\n remove: function(fileId) {\n return delete store[fileId];\n },\n\n reset: function() {\n store = {};\n perIdReadOnlyValues = {};\n catchall = initialValue;\n }\n };\n },\n\n _createUploadDataTracker: function() {\n var self = this;\n\n return new qq.UploadData({\n getName: function(id) {\n return self.getName(id);\n },\n getUuid: function(id) {\n return self.getUuid(id);\n },\n getSize: function(id) {\n return self.getSize(id);\n },\n onStatusChange: function(id, oldStatus, newStatus) {\n self._onUploadStatusChange(id, oldStatus, newStatus);\n self._options.callbacks.onStatusChange(id, oldStatus, newStatus);\n self._maybeAllComplete(id, newStatus);\n\n if (self._totalProgress) {\n setTimeout(function() {\n self._totalProgress.onStatusChange(id, oldStatus, newStatus);\n }, 0);\n }\n }\n });\n },\n\n /**\n * Generate a tracked upload button.\n *\n * @param spec Object containing a required `element` property\n * along with optional `multiple`, `accept`, and `folders`.\n * @returns {qq.UploadButton}\n * @private\n */\n _createUploadButton: function(spec) {\n var self = this,\n acceptFiles = spec.accept || this._options.validation.acceptFiles,\n allowedExtensions = spec.allowedExtensions || this._options.validation.allowedExtensions,\n button;\n\n function allowMultiple() {\n if (qq.supportedFeatures.ajaxUploading) {\n // Workaround for bug in iOS7+ (see #1039)\n if (self._options.workarounds.iosEmptyVideos &&\n qq.ios() &&\n !qq.ios6() &&\n self._isAllowedExtension(allowedExtensions, \".mov\")) {\n\n return false;\n }\n\n if (spec.multiple === undefined) {\n return self._options.multiple;\n }\n\n return spec.multiple;\n }\n\n return false;\n }\n\n button = new qq.UploadButton({\n acceptFiles: acceptFiles,\n element: spec.element,\n focusClass: this._options.classes.buttonFocus,\n folders: spec.folders,\n hoverClass: this._options.classes.buttonHover,\n ios8BrowserCrashWorkaround: this._options.workarounds.ios8BrowserCrash,\n multiple: allowMultiple(),\n name: this._options.request.inputName,\n onChange: function(input) {\n self._onInputChange(input);\n },\n title: spec.title == null ? this._options.text.fileInputTitle : spec.title\n });\n\n this._disposeSupport.addDisposer(function() {\n button.dispose();\n });\n\n self._buttons.push(button);\n\n return button;\n },\n\n _createUploadHandler: function(additionalOptions, namespace) {\n var self = this,\n lastOnProgress = {},\n options = {\n debug: this._options.debug,\n maxConnections: this._options.maxConnections,\n cors: this._options.cors,\n paramsStore: this._paramsStore,\n endpointStore: this._endpointStore,\n chunking: this._options.chunking,\n resume: this._options.resume,\n blobs: this._options.blobs,\n log: qq.bind(self.log, self),\n preventRetryParam: this._options.retry.preventRetryResponseProperty,\n onProgress: function(id, name, loaded, total) {\n if (loaded < 0 || total < 0) {\n return;\n }\n\n if (lastOnProgress[id]) {\n if (lastOnProgress[id].loaded !== loaded || lastOnProgress[id].total !== total) {\n self._onProgress(id, name, loaded, total);\n self._options.callbacks.onProgress(id, name, loaded, total);\n }\n }\n else {\n self._onProgress(id, name, loaded, total);\n self._options.callbacks.onProgress(id, name, loaded, total);\n }\n\n lastOnProgress[id] = {loaded: loaded, total: total};\n\n },\n onComplete: function(id, name, result, xhr) {\n delete lastOnProgress[id];\n\n var status = self.getUploads({id: id}).status,\n retVal;\n\n // This is to deal with some observed cases where the XHR readyStateChange handler is\n // invoked by the browser multiple times for the same XHR instance with the same state\n // readyState value. Higher level: don't invoke complete-related code if we've already\n // done this.\n if (status === qq.status.UPLOAD_SUCCESSFUL || status === qq.status.UPLOAD_FAILED) {\n return;\n }\n\n retVal = self._onComplete(id, name, result, xhr);\n\n // If the internal `_onComplete` handler returns a promise, don't invoke the `onComplete` callback\n // until the promise has been fulfilled.\n if (retVal instanceof qq.Promise) {\n retVal.done(function() {\n self._options.callbacks.onComplete(id, name, result, xhr);\n });\n }\n else {\n self._options.callbacks.onComplete(id, name, result, xhr);\n }\n },\n onCancel: function(id, name, cancelFinalizationEffort) {\n var promise = new qq.Promise();\n\n self._handleCheckedCallback({\n name: \"onCancel\",\n callback: qq.bind(self._options.callbacks.onCancel, self, id, name),\n onFailure: promise.failure,\n onSuccess: function() {\n cancelFinalizationEffort.then(function() {\n self._onCancel(id, name);\n });\n\n promise.success();\n },\n identifier: id\n });\n\n return promise;\n },\n onUploadPrep: qq.bind(this._onUploadPrep, this),\n onUpload: function(id, name) {\n self._onUpload(id, name);\n var onUploadResult = self._options.callbacks.onUpload(id, name);\n\n if (qq.isGenericPromise(onUploadResult)) {\n self.log(qq.format(\"onUpload for {} returned a Promise - waiting for resolution.\", id));\n return onUploadResult;\n }\n\n return new qq.Promise().success();\n },\n onUploadChunk: function(id, name, chunkData) {\n self._onUploadChunk(id, chunkData);\n var onUploadChunkResult = self._options.callbacks.onUploadChunk(id, name, chunkData);\n\n if (qq.isGenericPromise(onUploadChunkResult)) {\n self.log(qq.format(\"onUploadChunk for {}.{} returned a Promise - waiting for resolution.\", id, chunkData.partIndex));\n return onUploadChunkResult;\n }\n\n return new qq.Promise().success();\n },\n onUploadChunkSuccess: function(id, chunkData, result, xhr) {\n self._onUploadChunkSuccess(id, chunkData);\n self._options.callbacks.onUploadChunkSuccess.apply(self, arguments);\n },\n onResume: function(id, name, chunkData, customResumeData) {\n return self._options.callbacks.onResume(id, name, chunkData, customResumeData);\n },\n onAutoRetry: function(id, name, responseJSON, xhr) {\n return self._onAutoRetry.apply(self, arguments);\n },\n onUuidChanged: function(id, newUuid) {\n self.log(\"Server requested UUID change from '\" + self.getUuid(id) + \"' to '\" + newUuid + \"'\");\n self.setUuid(id, newUuid);\n },\n getName: qq.bind(self.getName, self),\n getUuid: qq.bind(self.getUuid, self),\n getSize: qq.bind(self.getSize, self),\n setSize: qq.bind(self._setSize, self),\n getDataByUuid: function(uuid) {\n return self.getUploads({uuid: uuid});\n },\n isQueued: function(id) {\n var status = self.getUploads({id: id}).status;\n return status === qq.status.QUEUED ||\n status === qq.status.SUBMITTED ||\n status === qq.status.UPLOAD_RETRYING ||\n status === qq.status.PAUSED;\n },\n getIdsInProxyGroup: self._uploadData.getIdsInProxyGroup,\n getIdsInBatch: self._uploadData.getIdsInBatch,\n isInProgress: function(id) {\n return self.getUploads({id: id}).status === qq.status.UPLOADING;\n },\n getCustomResumeData: qq.bind(self._getCustomResumeData, self),\n setStatus: function(id, status) {\n self._uploadData.setStatus(id, status);\n }\n };\n\n qq.each(this._options.request, function(prop, val) {\n options[prop] = val;\n });\n\n options.customHeaders = this._customHeadersStore;\n\n if (additionalOptions) {\n qq.each(additionalOptions, function(key, val) {\n options[key] = val;\n });\n }\n\n return new qq.UploadHandlerController(options, namespace);\n },\n\n _fileOrBlobRejected: function(id) {\n this._netUploadedOrQueued--;\n this._uploadData.setStatus(id, qq.status.REJECTED);\n },\n\n _formatSize: function(bytes) {\n if (bytes === 0) {\n return bytes + this._options.text.sizeSymbols[0];\n }\n var i = -1;\n do {\n bytes = bytes / 1000;\n i++;\n } while (bytes > 999);\n\n return Math.max(bytes, 0.1).toFixed(1) + this._options.text.sizeSymbols[i];\n },\n\n // Creates an internal object that tracks various properties of each extra button,\n // and then actually creates the extra button.\n _generateExtraButtonSpecs: function() {\n var self = this;\n\n this._extraButtonSpecs = {};\n\n qq.each(this._options.extraButtons, function(idx, extraButtonOptionEntry) {\n var multiple = extraButtonOptionEntry.multiple,\n validation = qq.extend({}, self._options.validation, true),\n extraButtonSpec = qq.extend({}, extraButtonOptionEntry);\n\n if (multiple === undefined) {\n multiple = self._options.multiple;\n }\n\n if (extraButtonSpec.validation) {\n qq.extend(validation, extraButtonOptionEntry.validation, true);\n }\n\n qq.extend(extraButtonSpec, {\n multiple: multiple,\n validation: validation\n }, true);\n\n self._initExtraButton(extraButtonSpec);\n });\n },\n\n _getButton: function(buttonId) {\n var extraButtonsSpec = this._extraButtonSpecs[buttonId];\n\n if (extraButtonsSpec) {\n return extraButtonsSpec.element;\n }\n else if (buttonId === this._defaultButtonId) {\n return this._options.button;\n }\n },\n\n /**\n * Gets the internally used tracking ID for a button.\n *\n * @param buttonOrFileInputOrFile `File`, ` `, or a button container element\n * @returns {*} The button's ID, or undefined if no ID is recoverable\n * @private\n */\n _getButtonId: function(buttonOrFileInputOrFile) {\n var inputs, fileInput,\n fileBlobOrInput = buttonOrFileInputOrFile;\n\n // We want the reference file/blob here if this is a proxy (a file that will be generated on-demand later)\n if (fileBlobOrInput instanceof qq.BlobProxy) {\n fileBlobOrInput = fileBlobOrInput.referenceBlob;\n }\n\n // If the item is a `Blob` it will never be associated with a button or drop zone.\n if (fileBlobOrInput && !qq.isBlob(fileBlobOrInput)) {\n if (qq.isFile(fileBlobOrInput)) {\n return fileBlobOrInput.qqButtonId;\n }\n else if (fileBlobOrInput.tagName.toLowerCase() === \"input\" &&\n fileBlobOrInput.type.toLowerCase() === \"file\") {\n\n return fileBlobOrInput.getAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME);\n }\n\n inputs = fileBlobOrInput.getElementsByTagName(\"input\");\n\n qq.each(inputs, function(idx, input) {\n if (input.getAttribute(\"type\") === \"file\") {\n fileInput = input;\n return false;\n }\n });\n\n if (fileInput) {\n return fileInput.getAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME);\n }\n }\n },\n\n _getCustomResumeData: function(fileId) {\n return this._customResumeDataStore.get(fileId);\n },\n\n _getNotFinished: function() {\n return this._uploadData.retrieve({\n status: [\n qq.status.UPLOADING,\n qq.status.UPLOAD_RETRYING,\n qq.status.QUEUED,\n qq.status.SUBMITTING,\n qq.status.SUBMITTED,\n qq.status.PAUSED\n ]\n }).length;\n },\n\n // Get the validation options for this button. Could be the default validation option\n // or a specific one assigned to this particular button.\n _getValidationBase: function(buttonId) {\n var extraButtonSpec = this._extraButtonSpecs[buttonId];\n\n return extraButtonSpec ? extraButtonSpec.validation : this._options.validation;\n },\n\n _getValidationDescriptor: function(fileWrapper) {\n if (fileWrapper.file instanceof qq.BlobProxy) {\n return {\n name: qq.getFilename(fileWrapper.file.referenceBlob),\n size: fileWrapper.file.referenceBlob.size\n };\n }\n\n return {\n name: this.getUploads({id: fileWrapper.id}).name,\n size: this.getUploads({id: fileWrapper.id}).size\n };\n },\n\n _getValidationDescriptors: function(fileWrappers) {\n var self = this,\n fileDescriptors = [];\n\n qq.each(fileWrappers, function(idx, fileWrapper) {\n fileDescriptors.push(self._getValidationDescriptor(fileWrapper));\n });\n\n return fileDescriptors;\n },\n\n // Allows camera access on either the default or an extra button for iOS devices.\n _handleCameraAccess: function() {\n if (this._options.camera.ios && qq.ios()) {\n var acceptIosCamera = \"image/*;capture=camera\",\n button = this._options.camera.button,\n buttonId = button ? this._getButtonId(button) : this._defaultButtonId,\n optionRoot = this._options;\n\n // If we are not targeting the default button, it is an \"extra\" button\n if (buttonId && buttonId !== this._defaultButtonId) {\n optionRoot = this._extraButtonSpecs[buttonId];\n }\n\n // Camera access won't work in iOS if the `multiple` attribute is present on the file input\n optionRoot.multiple = false;\n\n // update the options\n if (optionRoot.validation.acceptFiles === null) {\n optionRoot.validation.acceptFiles = acceptIosCamera;\n }\n else {\n optionRoot.validation.acceptFiles += \",\" + acceptIosCamera;\n }\n\n // update the already-created button\n qq.each(this._buttons, function(idx, button) {\n if (button.getButtonId() === buttonId) {\n button.setMultiple(optionRoot.multiple);\n button.setAcceptFiles(optionRoot.acceptFiles);\n\n return false;\n }\n });\n }\n },\n\n _handleCheckedCallback: function(details) {\n var self = this,\n callbackRetVal = details.callback();\n\n if (qq.isGenericPromise(callbackRetVal)) {\n this.log(details.name + \" - waiting for \" + details.name + \" promise to be fulfilled for \" + details.identifier);\n return callbackRetVal.then(\n function(successParam) {\n self.log(details.name + \" promise success for \" + details.identifier);\n details.onSuccess(successParam);\n },\n function() {\n if (details.onFailure) {\n self.log(details.name + \" promise failure for \" + details.identifier);\n details.onFailure();\n }\n else {\n self.log(details.name + \" promise failure for \" + details.identifier);\n }\n });\n }\n\n if (callbackRetVal !== false) {\n details.onSuccess(callbackRetVal);\n }\n else {\n if (details.onFailure) {\n this.log(details.name + \" - return value was 'false' for \" + details.identifier + \". Invoking failure callback.\");\n details.onFailure();\n }\n else {\n this.log(details.name + \" - return value was 'false' for \" + details.identifier + \". Will not proceed.\");\n }\n }\n\n return callbackRetVal;\n },\n\n // Updates internal state when a new file has been received, and adds it along with its ID to a passed array.\n _handleNewFile: function(file, batchId, newFileWrapperList) {\n var self = this,\n uuid = qq.getUniqueId(),\n size = -1,\n name = qq.getFilename(file),\n actualFile = file.blob || file,\n handler = this._customNewFileHandler ?\n this._customNewFileHandler :\n qq.bind(self._handleNewFileGeneric, self);\n\n if (!qq.isInput(actualFile) && actualFile.size >= 0) {\n size = actualFile.size;\n }\n\n handler(actualFile, name, uuid, size, newFileWrapperList, batchId, this._options.request.uuidName, {\n uploadData: self._uploadData,\n paramsStore: self._paramsStore,\n addFileToHandler: function(id, file) {\n self._handler.add(id, file);\n self._netUploadedOrQueued++;\n self._trackButton(id);\n }\n });\n },\n\n _handleNewFileGeneric: function(file, name, uuid, size, fileList, batchId) {\n var id = this._uploadData.addFile({\n uuid: uuid,\n name: name,\n size: size,\n batchId: batchId,\n file: file\n });\n\n this._handler.add(id, file);\n\n this._trackButton(id);\n\n this._netUploadedOrQueued++;\n\n fileList.push({id: id, file: file});\n },\n\n _handlePasteSuccess: function(blob, extSuppliedName) {\n var extension = blob.type.split(\"/\")[1],\n name = extSuppliedName;\n\n /*jshint eqeqeq: true, eqnull: true*/\n if (name == null) {\n name = this._options.paste.defaultName;\n }\n\n name += \".\" + extension;\n\n this.addFiles({\n name: name,\n blob: blob\n });\n },\n\n _handleDeleteSuccess: function(id) {\n if (this.getUploads({id: id}).status !== qq.status.DELETED) {\n var name = this.getName(id);\n\n this._netUploadedOrQueued--;\n this._netUploaded--;\n this._handler.expunge(id);\n this._uploadData.setStatus(id, qq.status.DELETED);\n this.log(\"Delete request for '\" + name + \"' has succeeded.\");\n }\n },\n\n _handleDeleteFailed: function(id, xhrOrXdr) {\n var name = this.getName(id);\n\n this._uploadData.setStatus(id, qq.status.DELETE_FAILED);\n this.log(\"Delete request for '\" + name + \"' has failed.\", \"error\");\n\n // Check first if xhrOrXdr is actually passed or valid\n // For error reporting, we only have access to the response status if this is not\n // an `XDomainRequest`.\n if (!xhrOrXdr || xhrOrXdr.withCredentials === undefined) {\n this._options.callbacks.onError(id, name, \"Delete request failed\", xhrOrXdr);\n }\n else {\n this._options.callbacks.onError(id, name, \"Delete request failed with response code \" + xhrOrXdr.status, xhrOrXdr);\n }\n },\n\n // Creates an extra button element\n _initExtraButton: function(spec) {\n var button = this._createUploadButton({\n accept: spec.validation.acceptFiles,\n allowedExtensions: spec.validation.allowedExtensions,\n element: spec.element,\n folders: spec.folders,\n multiple: spec.multiple,\n title: spec.fileInputTitle\n });\n\n this._extraButtonSpecs[button.getButtonId()] = spec;\n },\n\n _initFormSupportAndParams: function() {\n this._formSupport = qq.FormSupport && new qq.FormSupport(\n this._options.form, qq.bind(this.uploadStoredFiles, this), qq.bind(this.log, this)\n );\n\n if (this._formSupport && this._formSupport.attachedToForm) {\n this._paramsStore = this._createStore(\n this._options.request.params, this._formSupport.getFormInputsAsObject\n );\n\n this._options.autoUpload = this._formSupport.newAutoUpload;\n if (this._formSupport.newEndpoint) {\n this._options.request.endpoint = this._formSupport.newEndpoint;\n }\n }\n else {\n this._paramsStore = this._createStore(this._options.request.params);\n }\n },\n\n _isDeletePossible: function() {\n if (!qq.DeleteFileAjaxRequester || !this._options.deleteFile.enabled) {\n return false;\n }\n\n if (this._options.cors.expected) {\n if (qq.supportedFeatures.deleteFileCorsXhr) {\n return true;\n }\n\n if (qq.supportedFeatures.deleteFileCorsXdr && this._options.cors.allowXdr) {\n return true;\n }\n\n return false;\n }\n\n return true;\n },\n\n _isAllowedExtension: function(allowed, fileName) {\n var valid = false;\n\n if (!allowed.length) {\n return true;\n }\n\n qq.each(allowed, function(idx, allowedExt) {\n /**\n * If an argument is not a string, ignore it. Added when a possible issue with MooTools hijacking the\n * `allowedExtensions` array was discovered. See case #735 in the issue tracker for more details.\n */\n if (qq.isString(allowedExt)) {\n /*jshint eqeqeq: true, eqnull: true*/\n var extRegex = new RegExp(\"\\\\.\" + allowedExt + \"$\", \"i\");\n\n if (fileName.match(extRegex) != null) {\n valid = true;\n return false;\n }\n }\n });\n\n return valid;\n },\n\n /**\n * Constructs and returns a message that describes an item/file error. Also calls `onError` callback.\n *\n * @param code REQUIRED - a code that corresponds to a stock message describing this type of error\n * @param maybeNameOrNames names of the items that have failed, if applicable\n * @param item `File`, `Blob`, or ` `\n * @private\n */\n _itemError: function(code, maybeNameOrNames, item) {\n var message = this._options.messages[code],\n allowedExtensions = [],\n names = [].concat(maybeNameOrNames),\n name = names[0],\n buttonId = this._getButtonId(item),\n validationBase = this._getValidationBase(buttonId),\n extensionsForMessage, placeholderMatch;\n\n function r(name, replacement) { message = message.replace(name, replacement); }\n\n qq.each(validationBase.allowedExtensions, function(idx, allowedExtension) {\n /**\n * If an argument is not a string, ignore it. Added when a possible issue with MooTools hijacking the\n * `allowedExtensions` array was discovered. See case #735 in the issue tracker for more details.\n */\n if (qq.isString(allowedExtension)) {\n allowedExtensions.push(allowedExtension);\n }\n });\n\n extensionsForMessage = allowedExtensions.join(\", \").toLowerCase();\n\n r(\"{file}\", this._options.formatFileName(name));\n r(\"{extensions}\", extensionsForMessage);\n r(\"{sizeLimit}\", this._formatSize(validationBase.sizeLimit));\n r(\"{minSizeLimit}\", this._formatSize(validationBase.minSizeLimit));\n\n placeholderMatch = message.match(/(\\{\\w+\\})/g);\n if (placeholderMatch !== null) {\n qq.each(placeholderMatch, function(idx, placeholder) {\n r(placeholder, names[idx]);\n });\n }\n\n this._options.callbacks.onError(null, name, message, undefined);\n\n return message;\n },\n\n /**\n * Conditionally orders a manual retry of a failed upload.\n *\n * @param id File ID of the failed upload\n * @param callback Optional callback to invoke if a retry is prudent.\n * In lieu of asking the upload handler to retry.\n * @returns {boolean} true if a manual retry will occur\n * @private\n */\n _manualRetry: function(id, callback) {\n if (this._onBeforeManualRetry(id)) {\n this._netUploadedOrQueued++;\n this._uploadData.setStatus(id, qq.status.UPLOAD_RETRYING);\n\n if (callback) {\n callback(id);\n }\n else {\n this._handler.retry(id);\n }\n\n return true;\n }\n },\n\n _maybeAllComplete: function(id, status) {\n var self = this,\n notFinished = this._getNotFinished();\n\n if (status === qq.status.UPLOAD_SUCCESSFUL) {\n this._succeededSinceLastAllComplete.push(id);\n }\n else if (status === qq.status.UPLOAD_FAILED) {\n this._failedSinceLastAllComplete.push(id);\n }\n\n if (notFinished === 0 &&\n (this._succeededSinceLastAllComplete.length || this._failedSinceLastAllComplete.length)) {\n // Attempt to ensure onAllComplete is not invoked before other callbacks, such as onCancel & onComplete\n setTimeout(function() {\n self._onAllComplete(self._succeededSinceLastAllComplete, self._failedSinceLastAllComplete);\n }, 0);\n }\n },\n\n _maybeHandleIos8SafariWorkaround: function() {\n var self = this;\n\n if (this._options.workarounds.ios8SafariUploads && qq.ios800() && qq.iosSafari()) {\n setTimeout(function() {\n window.alert(self._options.messages.unsupportedBrowserIos8Safari);\n }, 0);\n throw new qq.Error(this._options.messages.unsupportedBrowserIos8Safari);\n }\n },\n\n _maybeParseAndSendUploadError: function(id, name, response, xhr) {\n // Assuming no one will actually set the response code to something other than 200\n // and still set 'success' to true...\n if (!response.success) {\n if (xhr && xhr.status !== 200 && !response.error) {\n this._options.callbacks.onError(id, name, \"XHR returned response code \" + xhr.status, xhr);\n }\n else {\n var errorReason = response.error ? response.error : this._options.text.defaultResponseError;\n this._options.callbacks.onError(id, name, errorReason, xhr);\n }\n }\n },\n\n _maybeProcessNextItemAfterOnValidateCallback: function(validItem, items, index, params, endpoint) {\n var self = this;\n\n if (items.length > index) {\n if (validItem || !this._options.validation.stopOnFirstInvalidFile) {\n //use setTimeout to prevent a stack overflow with a large number of files in the batch & non-promissory callbacks\n setTimeout(function() {\n var validationDescriptor = self._getValidationDescriptor(items[index]),\n buttonId = self._getButtonId(items[index].file),\n button = self._getButton(buttonId);\n\n self._handleCheckedCallback({\n name: \"onValidate\",\n callback: qq.bind(self._options.callbacks.onValidate, self, validationDescriptor, button),\n onSuccess: qq.bind(self._onValidateCallbackSuccess, self, items, index, params, endpoint),\n onFailure: qq.bind(self._onValidateCallbackFailure, self, items, index, params, endpoint),\n identifier: \"Item '\" + validationDescriptor.name + \"', size: \" + validationDescriptor.size\n });\n }, 0);\n }\n else if (!validItem) {\n for (; index < items.length; index++) {\n self._fileOrBlobRejected(items[index].id);\n }\n }\n }\n },\n\n _onAllComplete: function(successful, failed) {\n this._totalProgress && this._totalProgress.onAllComplete(successful, failed, this._preventRetries);\n\n this._options.callbacks.onAllComplete(qq.extend([], successful), qq.extend([], failed));\n\n this._succeededSinceLastAllComplete = [];\n this._failedSinceLastAllComplete = [];\n },\n\n /**\n * Attempt to automatically retry a failed upload.\n *\n * @param id The file ID of the failed upload\n * @param name The name of the file associated with the failed upload\n * @param responseJSON Response from the server, parsed into a javascript object\n * @param xhr Ajax transport used to send the failed request\n * @param callback Optional callback to be invoked if a retry is prudent.\n * Invoked in lieu of asking the upload handler to retry.\n * @returns {boolean} true if an auto-retry will occur\n * @private\n */\n _onAutoRetry: function(id, name, responseJSON, xhr, callback) {\n var self = this;\n\n self._preventRetries[id] = responseJSON[self._options.retry.preventRetryResponseProperty];\n\n if (self._shouldAutoRetry(id)) {\n var retryWaitPeriod = self._options.retry.autoAttemptDelay * 1000;\n\n self._maybeParseAndSendUploadError.apply(self, arguments);\n self._options.callbacks.onAutoRetry(id, name, self._autoRetries[id]);\n self._onBeforeAutoRetry(id, name);\n\n self._uploadData.setStatus(id, qq.status.UPLOAD_RETRYING);\n self._retryTimeouts[id] = setTimeout(function() {\n self.log(\"Starting retry for \" + name + \"...\");\n\n if (callback) {\n callback(id);\n }\n else {\n self._handler.retry(id);\n }\n }, retryWaitPeriod);\n\n return true;\n }\n },\n\n _onBeforeAutoRetry: function(id, name) {\n this.log(\"Waiting \" + this._options.retry.autoAttemptDelay + \" seconds before retrying \" + name + \"...\");\n },\n\n //return false if we should not attempt the requested retry\n _onBeforeManualRetry: function(id) {\n var itemLimit = this._currentItemLimit,\n fileName;\n\n if (this._preventRetries[id]) {\n this.log(\"Retries are forbidden for id \" + id, \"warn\");\n return false;\n }\n else if (this._handler.isValid(id)) {\n fileName = this.getName(id);\n\n if (this._options.callbacks.onManualRetry(id, fileName) === false) {\n return false;\n }\n\n if (itemLimit > 0 && this._netUploadedOrQueued + 1 > itemLimit) {\n this._itemError(\"retryFailTooManyItems\");\n return false;\n }\n\n this.log(\"Retrying upload for '\" + fileName + \"' (id: \" + id + \")...\");\n return true;\n }\n else {\n this.log(\"'\" + id + \"' is not a valid file ID\", \"error\");\n return false;\n }\n },\n\n _onCancel: function(id, name) {\n this._netUploadedOrQueued--;\n\n clearTimeout(this._retryTimeouts[id]);\n\n var storedItemIndex = qq.indexOf(this._storedIds, id);\n if (!this._options.autoUpload && storedItemIndex >= 0) {\n this._storedIds.splice(storedItemIndex, 1);\n }\n\n this._uploadData.setStatus(id, qq.status.CANCELED);\n },\n\n _onComplete: function(id, name, result, xhr) {\n if (!result.success) {\n this._netUploadedOrQueued--;\n this._uploadData.setStatus(id, qq.status.UPLOAD_FAILED);\n\n if (result[this._options.retry.preventRetryResponseProperty] === true) {\n this._preventRetries[id] = true;\n }\n }\n else {\n if (result.thumbnailUrl) {\n this._thumbnailUrls[id] = result.thumbnailUrl;\n }\n\n this._netUploaded++;\n this._uploadData.setStatus(id, qq.status.UPLOAD_SUCCESSFUL);\n }\n\n this._maybeParseAndSendUploadError(id, name, result, xhr);\n\n return result.success ? true : false;\n },\n\n _onDelete: function(id) {\n this._uploadData.setStatus(id, qq.status.DELETING);\n },\n\n _onDeleteComplete: function(id, xhrOrXdr, isError) {\n var name = this.getName(id);\n\n if (isError) {\n this._handleDeleteFailed(id, xhrOrXdr);\n }\n else {\n this._handleDeleteSuccess(id);\n }\n },\n\n _onInputChange: function(input) {\n var fileIndex;\n\n if (qq.supportedFeatures.ajaxUploading) {\n for (fileIndex = 0; fileIndex < input.files.length; fileIndex++) {\n this._annotateWithButtonId(input.files[fileIndex], input);\n }\n\n this.addFiles(input.files);\n }\n // Android 2.3.x will fire `onchange` even if no file has been selected\n else if (input.value.length > 0) {\n this.addFiles(input);\n }\n\n qq.each(this._buttons, function(idx, button) {\n button.reset();\n });\n },\n\n _onProgress: function(id, name, loaded, total) {\n this._totalProgress && this._totalProgress.onIndividualProgress(id, loaded, total);\n },\n\n _onSubmit: function(id, name) {\n //nothing to do yet in core uploader\n },\n\n _onSubmitCallbackSuccess: function(id, name) {\n this._onSubmit.apply(this, arguments);\n this._uploadData.setStatus(id, qq.status.SUBMITTED);\n this._onSubmitted.apply(this, arguments);\n\n if (this._options.autoUpload) {\n this._options.callbacks.onSubmitted.apply(this, arguments);\n this._uploadFile(id);\n }\n else {\n this._storeForLater(id);\n this._options.callbacks.onSubmitted.apply(this, arguments);\n }\n },\n\n _onSubmitDelete: function(id, onSuccessCallback, additionalMandatedParams) {\n var uuid = this.getUuid(id),\n adjustedOnSuccessCallback;\n\n if (onSuccessCallback) {\n adjustedOnSuccessCallback = qq.bind(onSuccessCallback, this, id, uuid, additionalMandatedParams);\n }\n\n if (this._isDeletePossible()) {\n this._handleCheckedCallback({\n name: \"onSubmitDelete\",\n callback: qq.bind(this._options.callbacks.onSubmitDelete, this, id),\n onSuccess: adjustedOnSuccessCallback ||\n qq.bind(this._deleteHandler.sendDelete, this, id, uuid, additionalMandatedParams),\n identifier: id\n });\n return true;\n }\n else {\n this.log(\"Delete request ignored for ID \" + id + \", delete feature is disabled or request not possible \" +\n \"due to CORS on a user agent that does not support pre-flighting.\", \"warn\");\n return false;\n }\n },\n\n _onSubmitted: function(id) {\n //nothing to do in the base uploader\n },\n\n _onTotalProgress: function(loaded, total) {\n this._options.callbacks.onTotalProgress(loaded, total);\n },\n\n _onUploadPrep: function(id) {\n // nothing to do in the core uploader for now\n },\n\n _onUpload: function(id, name) {\n this._uploadData.setStatus(id, qq.status.UPLOADING);\n },\n\n _onUploadChunk: function(id, chunkData) {\n //nothing to do in the base uploader\n },\n\n _onUploadChunkSuccess: function(id, chunkData) {\n if (!this._preventRetries[id] && this._options.retry.enableAuto) {\n this._autoRetries[id] = 0;\n }\n },\n\n _onUploadStatusChange: function(id, oldStatus, newStatus) {\n // Make sure a \"queued\" retry attempt is canceled if the upload has been paused\n if (newStatus === qq.status.PAUSED) {\n clearTimeout(this._retryTimeouts[id]);\n }\n },\n\n _onValidateBatchCallbackFailure: function(fileWrappers) {\n var self = this;\n\n qq.each(fileWrappers, function(idx, fileWrapper) {\n self._fileOrBlobRejected(fileWrapper.id);\n });\n },\n\n _onValidateBatchCallbackSuccess: function(validationDescriptors, items, params, endpoint, button) {\n var errorMessage,\n itemLimit = this._currentItemLimit,\n proposedNetFilesUploadedOrQueued = this._netUploadedOrQueued;\n\n if (itemLimit === 0 || proposedNetFilesUploadedOrQueued <= itemLimit) {\n if (items.length > 0) {\n this._handleCheckedCallback({\n name: \"onValidate\",\n callback: qq.bind(this._options.callbacks.onValidate, this, validationDescriptors[0], button),\n onSuccess: qq.bind(this._onValidateCallbackSuccess, this, items, 0, params, endpoint),\n onFailure: qq.bind(this._onValidateCallbackFailure, this, items, 0, params, endpoint),\n identifier: \"Item '\" + items[0].file.name + \"', size: \" + items[0].file.size\n });\n }\n else {\n this._itemError(\"noFilesError\");\n }\n }\n else {\n this._onValidateBatchCallbackFailure(items);\n errorMessage = this._options.messages.tooManyItemsError\n .replace(/\\{netItems\\}/g, proposedNetFilesUploadedOrQueued)\n .replace(/\\{itemLimit\\}/g, itemLimit);\n this._batchError(errorMessage);\n }\n },\n\n _onValidateCallbackFailure: function(items, index, params, endpoint) {\n var nextIndex = index + 1;\n\n this._fileOrBlobRejected(items[index].id, items[index].file.name);\n\n this._maybeProcessNextItemAfterOnValidateCallback(false, items, nextIndex, params, endpoint);\n },\n\n _onValidateCallbackSuccess: function(items, index, params, endpoint) {\n var self = this,\n nextIndex = index + 1,\n validationDescriptor = this._getValidationDescriptor(items[index]);\n\n this._validateFileOrBlobData(items[index], validationDescriptor)\n .then(\n function() {\n self._upload(items[index].id, params, endpoint);\n self._maybeProcessNextItemAfterOnValidateCallback(true, items, nextIndex, params, endpoint);\n },\n function() {\n self._maybeProcessNextItemAfterOnValidateCallback(false, items, nextIndex, params, endpoint);\n }\n );\n },\n\n _prepareItemsForUpload: function(items, params, endpoint) {\n if (items.length === 0) {\n this._itemError(\"noFilesError\");\n return;\n }\n\n var validationDescriptors = this._getValidationDescriptors(items),\n buttonId = this._getButtonId(items[0].file),\n button = this._getButton(buttonId);\n\n this._handleCheckedCallback({\n name: \"onValidateBatch\",\n callback: qq.bind(this._options.callbacks.onValidateBatch, this, validationDescriptors, button),\n onSuccess: qq.bind(this._onValidateBatchCallbackSuccess, this, validationDescriptors, items, params, endpoint, button),\n onFailure: qq.bind(this._onValidateBatchCallbackFailure, this, items),\n identifier: \"batch validation\"\n });\n },\n\n _preventLeaveInProgress: function() {\n var self = this;\n\n this._disposeSupport.attach(window, \"beforeunload\", function(e) {\n if (self.getInProgress()) {\n e = e || window.event;\n // for ie, ff\n e.returnValue = self._options.messages.onLeave;\n // for webkit\n return self._options.messages.onLeave;\n }\n });\n },\n\n // Attempts to refresh session data only if the `qq.Session` module exists\n // and a session endpoint has been specified. The `onSessionRequestComplete`\n // callback will be invoked once the refresh is complete.\n _refreshSessionData: function() {\n var self = this,\n options = this._options.session;\n\n /* jshint eqnull:true */\n if (qq.Session && this._options.session.endpoint != null) {\n if (!this._session) {\n qq.extend(options, {cors: this._options.cors});\n\n options.log = qq.bind(this.log, this);\n options.addFileRecord = qq.bind(this._addCannedFile, this);\n\n this._session = new qq.Session(options);\n }\n\n setTimeout(function() {\n self._session.refresh().then(function(response, xhrOrXdr) {\n self._sessionRequestComplete();\n self._options.callbacks.onSessionRequestComplete(response, true, xhrOrXdr);\n\n }, function(response, xhrOrXdr) {\n\n self._options.callbacks.onSessionRequestComplete(response, false, xhrOrXdr);\n });\n }, 0);\n }\n },\n\n _sessionRequestComplete: function() {},\n\n _setSize: function(id, newSize) {\n this._uploadData.updateSize(id, newSize);\n this._totalProgress && this._totalProgress.onNewSize(id);\n },\n\n _shouldAutoRetry: function(id) {\n var uploadData = this._uploadData.retrieve({id: id});\n\n /*jshint laxbreak: true */\n if (!this._preventRetries[id]\n && this._options.retry.enableAuto\n && uploadData.status !== qq.status.PAUSED) {\n\n if (this._autoRetries[id] === undefined) {\n this._autoRetries[id] = 0;\n }\n\n if (this._autoRetries[id] < this._options.retry.maxAutoAttempts) {\n this._autoRetries[id] += 1;\n return true;\n }\n }\n\n return false;\n },\n\n _storeForLater: function(id) {\n this._storedIds.push(id);\n },\n\n // Maps a file with the button that was used to select it.\n _trackButton: function(id) {\n var buttonId;\n\n if (qq.supportedFeatures.ajaxUploading) {\n buttonId = this._handler.getFile(id).qqButtonId;\n }\n else {\n buttonId = this._getButtonId(this._handler.getInput(id));\n }\n\n if (buttonId) {\n this._buttonIdsForFileIds[id] = buttonId;\n }\n },\n\n _updateFormSupportAndParams: function(formElementOrId) {\n this._options.form.element = formElementOrId;\n\n this._formSupport = qq.FormSupport && new qq.FormSupport(\n this._options.form, qq.bind(this.uploadStoredFiles, this), qq.bind(this.log, this)\n );\n\n if (this._formSupport && this._formSupport.attachedToForm) {\n this._paramsStore.addReadOnly(null, this._formSupport.getFormInputsAsObject);\n\n this._options.autoUpload = this._formSupport.newAutoUpload;\n if (this._formSupport.newEndpoint) {\n this.setEndpoint(this._formSupport.newEndpoint);\n }\n }\n },\n\n _upload: function(id, params, endpoint) {\n var name = this.getName(id);\n\n if (params) {\n this.setParams(params, id);\n }\n\n if (endpoint) {\n this.setEndpoint(endpoint, id);\n }\n\n this._handleCheckedCallback({\n name: \"onSubmit\",\n callback: qq.bind(this._options.callbacks.onSubmit, this, id, name),\n onSuccess: qq.bind(this._onSubmitCallbackSuccess, this, id, name),\n onFailure: qq.bind(this._fileOrBlobRejected, this, id, name),\n identifier: id\n });\n },\n\n _uploadFile: function(id) {\n if (!this._handler.upload(id)) {\n this._uploadData.setStatus(id, qq.status.QUEUED);\n }\n },\n\n _uploadStoredFiles: function() {\n var idToUpload, stillSubmitting,\n self = this;\n\n while (this._storedIds.length) {\n idToUpload = this._storedIds.shift();\n this._uploadFile(idToUpload);\n }\n\n // If we are still waiting for some files to clear validation, attempt to upload these again in a bit\n stillSubmitting = this.getUploads({status: qq.status.SUBMITTING}).length;\n if (stillSubmitting) {\n qq.log(\"Still waiting for \" + stillSubmitting + \" files to clear submit queue. Will re-parse stored IDs array shortly.\");\n setTimeout(function() {\n self._uploadStoredFiles();\n }, 1000);\n }\n },\n\n /**\n * Performs some internal validation checks on an item, defined in the `validation` option.\n *\n * @param fileWrapper Wrapper containing a `file` along with an `id`\n * @param validationDescriptor Normalized information about the item (`size`, `name`).\n * @returns qq.Promise with appropriate callbacks invoked depending on the validity of the file\n * @private\n */\n _validateFileOrBlobData: function(fileWrapper, validationDescriptor) {\n var self = this,\n file = (function() {\n if (fileWrapper.file instanceof qq.BlobProxy) {\n return fileWrapper.file.referenceBlob;\n }\n return fileWrapper.file;\n }()),\n name = validationDescriptor.name,\n size = validationDescriptor.size,\n buttonId = this._getButtonId(fileWrapper.file),\n validationBase = this._getValidationBase(buttonId),\n validityChecker = new qq.Promise();\n\n validityChecker.then(\n function() {},\n function() {\n self._fileOrBlobRejected(fileWrapper.id, name);\n });\n\n if (qq.isFileOrInput(file) && !this._isAllowedExtension(validationBase.allowedExtensions, name)) {\n this._itemError(\"typeError\", name, file);\n return validityChecker.failure();\n }\n\n if (!this._options.validation.allowEmpty && size === 0) {\n this._itemError(\"emptyError\", name, file);\n return validityChecker.failure();\n }\n\n if (size > 0 && validationBase.sizeLimit && size > validationBase.sizeLimit) {\n this._itemError(\"sizeError\", name, file);\n return validityChecker.failure();\n }\n\n if (size > 0 && size < validationBase.minSizeLimit) {\n this._itemError(\"minSizeError\", name, file);\n return validityChecker.failure();\n }\n\n if (qq.ImageValidation && qq.supportedFeatures.imagePreviews && qq.isFile(file)) {\n new qq.ImageValidation(file, qq.bind(self.log, self)).validate(validationBase.image).then(\n validityChecker.success,\n function(errorCode) {\n self._itemError(errorCode + \"ImageError\", name, file);\n validityChecker.failure();\n }\n );\n }\n else {\n validityChecker.success();\n }\n\n return validityChecker;\n },\n\n _wrapCallbacks: function() {\n var self, safeCallback, prop;\n\n self = this;\n\n safeCallback = function(name, callback, args) {\n var errorMsg;\n\n try {\n return callback.apply(self, args);\n }\n catch (exception) {\n errorMsg = exception.message || exception.toString();\n self.log(\"Caught exception in '\" + name + \"' callback - \" + errorMsg, \"error\");\n }\n };\n\n /* jshint forin: false, loopfunc: true */\n for (prop in this._options.callbacks) {\n (function() {\n var callbackName, callbackFunc;\n callbackName = prop;\n callbackFunc = self._options.callbacks[callbackName];\n self._options.callbacks[callbackName] = function() {\n return safeCallback(callbackName, callbackFunc, arguments);\n };\n }());\n }\n }\n };\n}());\n","/*globals qq*/\n(function() {\n \"use strict\";\n\n qq.FineUploaderBasic = function(o) {\n var self = this;\n\n // These options define FineUploaderBasic mode.\n this._options = {\n debug: false,\n button: null,\n multiple: true,\n maxConnections: 3,\n disableCancelForFormUploads: false,\n autoUpload: true,\n warnBeforeUnload: true,\n\n request: {\n customHeaders: {},\n endpoint: \"/server/upload\",\n filenameParam: \"qqfilename\",\n forceMultipart: true,\n inputName: \"qqfile\",\n method: \"POST\",\n omitDefaultParams: false,\n params: {},\n paramsInBody: true,\n requireSuccessJson: true,\n totalFileSizeName: \"qqtotalfilesize\",\n uuidName: \"qquuid\"\n },\n\n validation: {\n allowedExtensions: [],\n sizeLimit: 0,\n minSizeLimit: 0,\n itemLimit: 0,\n stopOnFirstInvalidFile: true,\n acceptFiles: null,\n image: {\n maxHeight: 0,\n maxWidth: 0,\n minHeight: 0,\n minWidth: 0\n },\n allowEmpty: false\n },\n\n callbacks: {\n onSubmit: function(id, name) {},\n onSubmitted: function(id, name) {},\n onComplete: function(id, name, responseJSON, maybeXhr) {},\n onAllComplete: function(successful, failed) {},\n onCancel: function(id, name) {},\n onUpload: function(id, name) {},\n onUploadChunk: function(id, name, chunkData) {},\n onUploadChunkSuccess: function(id, chunkData, responseJSON, xhr) {},\n onResume: function(id, fileName, chunkData, customResumeData) {},\n onProgress: function(id, name, loaded, total) {},\n onTotalProgress: function(loaded, total) {},\n onError: function(id, name, reason, maybeXhrOrXdr) {},\n onAutoRetry: function(id, name, attemptNumber) {},\n onManualRetry: function(id, name) {},\n onValidateBatch: function(fileOrBlobData) {},\n onValidate: function(fileOrBlobData) {},\n onSubmitDelete: function(id) {},\n onDelete: function(id) {},\n onDeleteComplete: function(id, xhrOrXdr, isError) {},\n onPasteReceived: function(blob) {},\n onStatusChange: function(id, oldStatus, newStatus) {},\n onSessionRequestComplete: function(response, success, xhrOrXdr) {}\n },\n\n messages: {\n typeError: \"{file} has an invalid extension. Valid extension(s): {extensions}.\",\n sizeError: \"{file} is too large, maximum file size is {sizeLimit}.\",\n minSizeError: \"{file} is too small, minimum file size is {minSizeLimit}.\",\n emptyError: \"{file} is empty, please select files again without it.\",\n noFilesError: \"No files to upload.\",\n tooManyItemsError: \"Too many items ({netItems}) would be uploaded. Item limit is {itemLimit}.\",\n maxHeightImageError: \"Image is too tall.\",\n maxWidthImageError: \"Image is too wide.\",\n minHeightImageError: \"Image is not tall enough.\",\n minWidthImageError: \"Image is not wide enough.\",\n retryFailTooManyItems: \"Retry failed - you have reached your file limit.\",\n onLeave: \"The files are being uploaded, if you leave now the upload will be canceled.\",\n unsupportedBrowserIos8Safari: \"Unrecoverable error - this browser does not permit file uploading of any kind due to serious bugs in iOS8 Safari. Please use iOS8 Chrome until Apple fixes these issues.\"\n },\n\n retry: {\n enableAuto: false,\n maxAutoAttempts: 3,\n autoAttemptDelay: 5,\n preventRetryResponseProperty: \"preventRetry\"\n },\n\n classes: {\n buttonHover: \"qq-upload-button-hover\",\n buttonFocus: \"qq-upload-button-focus\"\n },\n\n chunking: {\n enabled: false,\n concurrent: {\n enabled: false\n },\n mandatory: false,\n paramNames: {\n partIndex: \"qqpartindex\",\n partByteOffset: \"qqpartbyteoffset\",\n chunkSize: \"qqchunksize\",\n totalFileSize: \"qqtotalfilesize\",\n totalParts: \"qqtotalparts\"\n },\n partSize: function(id) {\n return 2000000;\n },\n // only relevant for traditional endpoints, only required when concurrent.enabled === true\n success: {\n endpoint: null,\n\n headers: function(id) {\n return null;\n },\n\n jsonPayload: false,\n\n method: \"POST\",\n\n params: function(id) {\n return null;\n },\n\n resetOnStatus: []\n }\n },\n\n resume: {\n enabled: false,\n recordsExpireIn: 7, //days\n paramNames: {\n resuming: \"qqresume\"\n },\n customKeys: function(fileId) {\n return [];\n }\n },\n\n formatFileName: function(fileOrBlobName) {\n return fileOrBlobName;\n },\n\n text: {\n defaultResponseError: \"Upload failure reason unknown\",\n fileInputTitle: \"file input\",\n sizeSymbols: [\"kB\", \"MB\", \"GB\", \"TB\", \"PB\", \"EB\"]\n },\n\n deleteFile: {\n enabled: false,\n method: \"DELETE\",\n endpoint: \"/server/upload\",\n customHeaders: {},\n params: {}\n },\n\n cors: {\n expected: false,\n sendCredentials: false,\n allowXdr: false\n },\n\n blobs: {\n defaultName: \"misc_data\"\n },\n\n paste: {\n targetElement: null,\n defaultName: \"pasted_image\"\n },\n\n camera: {\n ios: false,\n\n // if ios is true: button is null means target the default button, otherwise target the button specified\n button: null\n },\n\n // This refers to additional upload buttons to be handled by Fine Uploader.\n // Each element is an object, containing `element` as the only required\n // property. The `element` must be a container that will ultimately\n // contain an invisible ` ` created by Fine Uploader.\n // Optional properties of each object include `multiple`, `validation`,\n // and `folders`.\n extraButtons: [],\n\n // Depends on the session module. Used to query the server for an initial file list\n // during initialization and optionally after a `reset`.\n session: {\n endpoint: null,\n params: {},\n customHeaders: {},\n refreshOnReset: true\n },\n\n // Send parameters associated with an existing form along with the files\n form: {\n // Element ID, HTMLElement, or null\n element: \"qq-form\",\n\n // Overrides the base `autoUpload`, unless `element` is null.\n autoUpload: false,\n\n // true = upload files on form submission (and squelch submit event)\n interceptSubmit: true\n },\n\n // scale images client side, upload a new file for each scaled version\n scaling: {\n customResizer: null,\n\n // send the original file as well\n sendOriginal: true,\n\n // fox orientation for scaled images\n orient: true,\n\n // If null, scaled image type will match reference image type. This value will be referred to\n // for any size record that does not specific a type.\n defaultType: null,\n\n defaultQuality: 80,\n\n failureText: \"Failed to scale\",\n\n includeExif: false,\n\n // metadata about each requested scaled version\n sizes: []\n },\n\n workarounds: {\n iosEmptyVideos: true,\n ios8SafariUploads: true,\n ios8BrowserCrash: false\n }\n };\n\n // Replace any default options with user defined ones\n qq.extend(this._options, o, true);\n\n this._buttons = [];\n this._extraButtonSpecs = {};\n this._buttonIdsForFileIds = [];\n\n this._wrapCallbacks();\n this._disposeSupport = new qq.DisposeSupport();\n\n this._storedIds = [];\n this._autoRetries = [];\n this._retryTimeouts = [];\n this._preventRetries = [];\n this._thumbnailUrls = [];\n\n this._netUploadedOrQueued = 0;\n this._netUploaded = 0;\n this._uploadData = this._createUploadDataTracker();\n\n this._initFormSupportAndParams();\n\n this._customHeadersStore = this._createStore(this._options.request.customHeaders);\n this._deleteFileCustomHeadersStore = this._createStore(this._options.deleteFile.customHeaders);\n\n this._deleteFileParamsStore = this._createStore(this._options.deleteFile.params);\n\n this._endpointStore = this._createStore(this._options.request.endpoint);\n this._deleteFileEndpointStore = this._createStore(this._options.deleteFile.endpoint);\n\n this._handler = this._createUploadHandler();\n\n this._deleteHandler = qq.DeleteFileAjaxRequester && this._createDeleteHandler();\n\n if (this._options.button) {\n this._defaultButtonId = this._createUploadButton({\n element: this._options.button,\n title: this._options.text.fileInputTitle\n }).getButtonId();\n }\n\n this._generateExtraButtonSpecs();\n\n this._handleCameraAccess();\n\n if (this._options.paste.targetElement) {\n if (qq.PasteSupport) {\n this._pasteHandler = this._createPasteHandler();\n }\n else {\n this.log(\"Paste support module not found\", \"error\");\n }\n }\n\n this._options.warnBeforeUnload && this._preventLeaveInProgress();\n\n this._imageGenerator = qq.ImageGenerator && new qq.ImageGenerator(qq.bind(this.log, this));\n this._refreshSessionData();\n\n this._succeededSinceLastAllComplete = [];\n this._failedSinceLastAllComplete = [];\n\n this._scaler = (qq.Scaler && new qq.Scaler(this._options.scaling, qq.bind(this.log, this))) || {};\n if (this._scaler.enabled) {\n this._customNewFileHandler = qq.bind(this._scaler.handleNewFile, this._scaler);\n }\n\n if (qq.TotalProgress && qq.supportedFeatures.progressBar) {\n this._totalProgress = new qq.TotalProgress(\n qq.bind(this._onTotalProgress, this),\n\n function(id) {\n var entry = self._uploadData.retrieve({id: id});\n return (entry && entry.size) || 0;\n }\n );\n }\n\n this._currentItemLimit = this._options.validation.itemLimit;\n\n this._customResumeDataStore = this._createStore();\n };\n\n // Define the private & public API methods.\n qq.FineUploaderBasic.prototype = qq.basePublicApi;\n qq.extend(qq.FineUploaderBasic.prototype, qq.basePrivateApi);\n}());\n","/*globals qq, XDomainRequest*/\n/** Generic class for sending non-upload ajax requests and handling the associated responses **/\nqq.AjaxRequester = function(o) {\n \"use strict\";\n\n var log, shouldParamsBeInQueryString,\n queue = [],\n requestData = {},\n options = {\n acceptHeader: null,\n validMethods: [\"PATCH\", \"POST\", \"PUT\"],\n method: \"POST\",\n contentType: \"application/x-www-form-urlencoded\",\n maxConnections: 3,\n customHeaders: {},\n endpointStore: {},\n paramsStore: {},\n mandatedParams: {},\n allowXRequestedWithAndCacheControl: true,\n successfulResponseCodes: {\n DELETE: [200, 202, 204],\n PATCH: [200, 201, 202, 203, 204],\n POST: [200, 201, 202, 203, 204],\n PUT: [200, 201, 202, 203, 204],\n GET: [200]\n },\n cors: {\n expected: false,\n sendCredentials: false\n },\n log: function(str, level) {},\n onSend: function(id) {},\n onComplete: function(id, xhrOrXdr, isError) {},\n onProgress: null\n };\n\n qq.extend(options, o);\n log = options.log;\n\n if (qq.indexOf(options.validMethods, options.method) < 0) {\n throw new Error(\"'\" + options.method + \"' is not a supported method for this type of request!\");\n }\n\n // [Simple methods](http://www.w3.org/TR/cors/#simple-method)\n // are defined by the W3C in the CORS spec as a list of methods that, in part,\n // make a CORS request eligible to be exempt from preflighting.\n function isSimpleMethod() {\n return qq.indexOf([\"GET\", \"POST\", \"HEAD\"], options.method) >= 0;\n }\n\n // [Simple headers](http://www.w3.org/TR/cors/#simple-header)\n // are defined by the W3C in the CORS spec as a list of headers that, in part,\n // make a CORS request eligible to be exempt from preflighting.\n function containsNonSimpleHeaders(headers) {\n var containsNonSimple = false;\n\n qq.each(containsNonSimple, function(idx, header) {\n if (qq.indexOf([\"Accept\", \"Accept-Language\", \"Content-Language\", \"Content-Type\"], header) < 0) {\n containsNonSimple = true;\n return false;\n }\n });\n\n return containsNonSimple;\n }\n\n function isXdr(xhr) {\n //The `withCredentials` test is a commonly accepted way to determine if XHR supports CORS.\n return options.cors.expected && xhr.withCredentials === undefined;\n }\n\n // Returns either a new `XMLHttpRequest` or `XDomainRequest` instance.\n function getCorsAjaxTransport() {\n var xhrOrXdr;\n\n if (window.XMLHttpRequest || window.ActiveXObject) {\n xhrOrXdr = qq.createXhrInstance();\n\n if (xhrOrXdr.withCredentials === undefined) {\n xhrOrXdr = new XDomainRequest();\n // Workaround for XDR bug in IE9 - https://social.msdn.microsoft.com/Forums/ie/en-US/30ef3add-767c-4436-b8a9-f1ca19b4812e/ie9-rtm-xdomainrequest-issued-requests-may-abort-if-all-event-handlers-not-specified?forum=iewebdevelopment\n xhrOrXdr.onload = function() {};\n xhrOrXdr.onerror = function() {};\n xhrOrXdr.ontimeout = function() {};\n xhrOrXdr.onprogress = function() {};\n }\n }\n\n return xhrOrXdr;\n }\n\n // Returns either a new XHR/XDR instance, or an existing one for the associated `File` or `Blob`.\n function getXhrOrXdr(id, suppliedXhr) {\n var xhrOrXdr = requestData[id] && requestData[id].xhr;\n\n if (!xhrOrXdr) {\n if (suppliedXhr) {\n xhrOrXdr = suppliedXhr;\n }\n else {\n if (options.cors.expected) {\n xhrOrXdr = getCorsAjaxTransport();\n }\n else {\n xhrOrXdr = qq.createXhrInstance();\n }\n }\n\n requestData[id].xhr = xhrOrXdr;\n }\n\n return xhrOrXdr;\n }\n\n // Removes element from queue, sends next request\n function dequeue(id) {\n var i = qq.indexOf(queue, id),\n max = options.maxConnections,\n nextId;\n\n delete requestData[id];\n queue.splice(i, 1);\n\n if (queue.length >= max && i < max) {\n nextId = queue[max - 1];\n sendRequest(nextId);\n }\n }\n\n function onComplete(id, xdrError) {\n var xhr = getXhrOrXdr(id),\n method = options.method,\n isError = xdrError === true;\n\n dequeue(id);\n\n if (isError) {\n log(method + \" request for \" + id + \" has failed\", \"error\");\n }\n else if (!isXdr(xhr) && !isResponseSuccessful(xhr.status)) {\n isError = true;\n log(method + \" request for \" + id + \" has failed - response code \" + xhr.status, \"error\");\n }\n\n options.onComplete(id, xhr, isError);\n }\n\n function getParams(id) {\n var onDemandParams = requestData[id].additionalParams,\n mandatedParams = options.mandatedParams,\n params;\n\n if (options.paramsStore.get) {\n params = options.paramsStore.get(id);\n }\n\n if (onDemandParams) {\n qq.each(onDemandParams, function(name, val) {\n params = params || {};\n params[name] = val;\n });\n }\n\n if (mandatedParams) {\n qq.each(mandatedParams, function(name, val) {\n params = params || {};\n params[name] = val;\n });\n }\n\n return params;\n }\n\n function sendRequest(id, optXhr) {\n var xhr = getXhrOrXdr(id, optXhr),\n method = options.method,\n params = getParams(id),\n payload = requestData[id].payload,\n url;\n\n options.onSend(id);\n\n url = createUrl(id, params, requestData[id].additionalQueryParams);\n\n // XDR and XHR status detection APIs differ a bit.\n if (isXdr(xhr)) {\n xhr.onload = getXdrLoadHandler(id);\n xhr.onerror = getXdrErrorHandler(id);\n }\n else {\n xhr.onreadystatechange = getXhrReadyStateChangeHandler(id);\n }\n\n registerForUploadProgress(id);\n\n // The last parameter is assumed to be ignored if we are actually using `XDomainRequest`.\n xhr.open(method, url, true);\n\n // Instruct the transport to send cookies along with the CORS request,\n // unless we are using `XDomainRequest`, which is not capable of this.\n if (options.cors.expected && options.cors.sendCredentials && !isXdr(xhr)) {\n xhr.withCredentials = true;\n }\n\n setHeaders(id);\n\n log(\"Sending \" + method + \" request for \" + id);\n\n if (payload) {\n xhr.send(payload);\n }\n else if (shouldParamsBeInQueryString || !params) {\n xhr.send();\n }\n else if (params && options.contentType && options.contentType.toLowerCase().indexOf(\"application/x-www-form-urlencoded\") >= 0) {\n xhr.send(qq.obj2url(params, \"\"));\n }\n else if (params && options.contentType && options.contentType.toLowerCase().indexOf(\"application/json\") >= 0) {\n xhr.send(JSON.stringify(params));\n }\n else {\n xhr.send(params);\n }\n\n return xhr;\n }\n\n function createUrl(id, params, additionalQueryParams) {\n var endpoint = options.endpointStore.get(id),\n addToPath = requestData[id].addToPath;\n\n /*jshint -W116,-W041 */\n if (addToPath != undefined) {\n endpoint += \"/\" + addToPath;\n }\n\n if (shouldParamsBeInQueryString && params) {\n endpoint = qq.obj2url(params, endpoint);\n }\n\n if (additionalQueryParams) {\n endpoint = qq.obj2url(additionalQueryParams, endpoint);\n }\n\n return endpoint;\n }\n\n // Invoked by the UA to indicate a number of possible states that describe\n // a live `XMLHttpRequest` transport.\n function getXhrReadyStateChangeHandler(id) {\n return function() {\n if (getXhrOrXdr(id).readyState === 4) {\n onComplete(id);\n }\n };\n }\n\n function registerForUploadProgress(id) {\n var onProgress = options.onProgress;\n\n if (onProgress) {\n getXhrOrXdr(id).upload.onprogress = function(e) {\n if (e.lengthComputable) {\n onProgress(id, e.loaded, e.total);\n }\n };\n }\n }\n\n // This will be called by IE to indicate **success** for an associated\n // `XDomainRequest` transported request.\n function getXdrLoadHandler(id) {\n return function() {\n onComplete(id);\n };\n }\n\n // This will be called by IE to indicate **failure** for an associated\n // `XDomainRequest` transported request.\n function getXdrErrorHandler(id) {\n return function() {\n onComplete(id, true);\n };\n }\n\n function setHeaders(id) {\n var xhr = getXhrOrXdr(id),\n customHeaders = options.customHeaders,\n onDemandHeaders = requestData[id].additionalHeaders || {},\n method = options.method,\n allHeaders = {};\n\n // If XDomainRequest is being used, we can't set headers, so just ignore this block.\n if (!isXdr(xhr)) {\n options.acceptHeader && xhr.setRequestHeader(\"Accept\", options.acceptHeader);\n\n // Only attempt to add X-Requested-With & Cache-Control if permitted\n if (options.allowXRequestedWithAndCacheControl) {\n // Do not add X-Requested-With & Cache-Control if this is a cross-origin request\n // OR the cross-origin request contains a non-simple method or header.\n // This is done to ensure a preflight is not triggered exclusively based on the\n // addition of these 2 non-simple headers.\n if (!options.cors.expected || (!isSimpleMethod() || containsNonSimpleHeaders(customHeaders))) {\n xhr.setRequestHeader(\"X-Requested-With\", \"XMLHttpRequest\");\n xhr.setRequestHeader(\"Cache-Control\", \"no-cache\");\n }\n }\n\n if (options.contentType && (method === \"POST\" || method === \"PUT\")) {\n xhr.setRequestHeader(\"Content-Type\", options.contentType);\n }\n\n qq.extend(allHeaders, qq.isFunction(customHeaders) ? customHeaders(id) : customHeaders);\n qq.extend(allHeaders, onDemandHeaders);\n\n qq.each(allHeaders, function(name, val) {\n xhr.setRequestHeader(name, val);\n });\n }\n }\n\n function isResponseSuccessful(responseCode) {\n return qq.indexOf(options.successfulResponseCodes[options.method], responseCode) >= 0;\n }\n\n function prepareToSend(id, optXhr, addToPath, additionalParams, additionalQueryParams, additionalHeaders, payload) {\n requestData[id] = {\n addToPath: addToPath,\n additionalParams: additionalParams,\n additionalQueryParams: additionalQueryParams,\n additionalHeaders: additionalHeaders,\n payload: payload\n };\n\n var len = queue.push(id);\n\n // if too many active connections, wait...\n if (len <= options.maxConnections) {\n return sendRequest(id, optXhr);\n }\n }\n\n shouldParamsBeInQueryString = options.method === \"GET\" || options.method === \"DELETE\";\n\n qq.extend(this, {\n // Start the process of sending the request. The ID refers to the file associated with the request.\n initTransport: function(id) {\n var path, params, headers, payload, cacheBuster, additionalQueryParams;\n\n return {\n // Optionally specify the end of the endpoint path for the request.\n withPath: function(appendToPath) {\n path = appendToPath;\n return this;\n },\n\n // Optionally specify additional parameters to send along with the request.\n // These will be added to the query string for GET/DELETE requests or the payload\n // for POST/PUT requests. The Content-Type of the request will be used to determine\n // how these parameters should be formatted as well.\n withParams: function(additionalParams) {\n params = additionalParams;\n return this;\n },\n\n withQueryParams: function(_additionalQueryParams_) {\n additionalQueryParams = _additionalQueryParams_;\n return this;\n },\n\n // Optionally specify additional headers to send along with the request.\n withHeaders: function(additionalHeaders) {\n headers = additionalHeaders;\n return this;\n },\n\n // Optionally specify a payload/body for the request.\n withPayload: function(thePayload) {\n payload = thePayload;\n return this;\n },\n\n // Appends a cache buster (timestamp) to the request URL as a query parameter (only if GET or DELETE)\n withCacheBuster: function() {\n cacheBuster = true;\n return this;\n },\n\n // Send the constructed request.\n send: function(optXhr) {\n if (cacheBuster && qq.indexOf([\"GET\", \"DELETE\"], options.method) >= 0) {\n params.qqtimestamp = new Date().getTime();\n }\n\n return prepareToSend(id, optXhr, path, params, additionalQueryParams, headers, payload);\n }\n };\n },\n\n canceled: function(id) {\n dequeue(id);\n }\n });\n};\n","/* globals qq */\n/**\n * Common upload handler functions.\n *\n * @constructor\n */\nqq.UploadHandler = function(spec) {\n \"use strict\";\n\n var proxy = spec.proxy,\n fileState = {},\n onCancel = proxy.onCancel,\n getName = proxy.getName;\n\n qq.extend(this, {\n add: function(id, fileItem) {\n fileState[id] = fileItem;\n fileState[id].temp = {};\n },\n\n cancel: function(id) {\n var self = this,\n cancelFinalizationEffort = new qq.Promise(),\n onCancelRetVal = onCancel(id, getName(id), cancelFinalizationEffort);\n\n onCancelRetVal.then(function() {\n if (self.isValid(id)) {\n fileState[id].canceled = true;\n self.expunge(id);\n }\n cancelFinalizationEffort.success();\n });\n },\n\n expunge: function(id) {\n delete fileState[id];\n },\n\n getThirdPartyFileId: function(id) {\n return fileState[id].key;\n },\n\n isValid: function(id) {\n return fileState[id] !== undefined;\n },\n\n reset: function() {\n fileState = {};\n },\n\n _getFileState: function(id) {\n return fileState[id];\n },\n\n _setThirdPartyFileId: function(id, thirdPartyFileId) {\n fileState[id].key = thirdPartyFileId;\n },\n\n _wasCanceled: function(id) {\n return !!fileState[id].canceled;\n }\n });\n};\n","/*globals qq*/\n/**\n * Base upload handler module. Controls more specific handlers.\n *\n * @param o Options. Passed along to the specific handler submodule as well.\n * @param namespace [optional] Namespace for the specific handler.\n */\nqq.UploadHandlerController = function(o, namespace) {\n \"use strict\";\n\n var controller = this,\n chunkingPossible = false,\n concurrentChunkingPossible = false,\n chunking, preventRetryResponse, log, handler,\n\n options = {\n paramsStore: {},\n maxConnections: 3, // maximum number of concurrent uploads\n chunking: {\n enabled: false,\n multiple: {\n enabled: false\n }\n },\n log: function(str, level) {},\n onProgress: function(id, fileName, loaded, total) {},\n onComplete: function(id, fileName, response, xhr) {},\n onCancel: function(id, fileName) {},\n onUploadPrep: function(id) {}, // Called if non-trivial operations will be performed before onUpload\n onUpload: function(id, fileName) {},\n onUploadChunk: function(id, fileName, chunkData) {},\n onUploadChunkSuccess: function(id, chunkData, response, xhr) {},\n onAutoRetry: function(id, fileName, response, xhr) {},\n onResume: function(id, fileName, chunkData, customResumeData) {},\n onUuidChanged: function(id, newUuid) {},\n getName: function(id) {},\n setSize: function(id, newSize) {},\n isQueued: function(id) {},\n getIdsInProxyGroup: function(id) {},\n getIdsInBatch: function(id) {},\n isInProgress: function(id) {}\n },\n\n chunked = {\n // Called when each chunk has uploaded successfully\n done: function(id, chunkIdx, response, xhr) {\n var chunkData = handler._getChunkData(id, chunkIdx);\n\n handler._getFileState(id).attemptingResume = false;\n\n delete handler._getFileState(id).temp.chunkProgress[chunkIdx];\n handler._getFileState(id).loaded += chunkData.size;\n\n options.onUploadChunkSuccess(id, handler._getChunkDataForCallback(chunkData), response, xhr);\n },\n\n // Called when all chunks have been successfully uploaded and we want to ask the handler to perform any\n // logic associated with closing out the file, such as combining the chunks.\n finalize: function(id) {\n var size = options.getSize(id),\n name = options.getName(id);\n\n log(\"All chunks have been uploaded for \" + id + \" - finalizing....\");\n handler.finalizeChunks(id).then(\n function(response, xhr) {\n log(\"Finalize successful for \" + id);\n\n var normaizedResponse = upload.normalizeResponse(response, true);\n\n options.onProgress(id, name, size, size);\n handler._maybeDeletePersistedChunkData(id);\n upload.cleanup(id, normaizedResponse, xhr);\n },\n function(response, xhr) {\n var normalizedResponse = upload.normalizeResponse(response, false);\n\n log(\"Problem finalizing chunks for file ID \" + id + \" - \" + normalizedResponse.error, \"error\");\n\n if (\n normalizedResponse.reset ||\n (xhr && options.chunking.success.resetOnStatus.indexOf(xhr.status) >= 0)\n ) {\n chunked.reset(id);\n }\n\n if (!options.onAutoRetry(id, name, normalizedResponse, xhr)) {\n upload.cleanup(id, normalizedResponse, xhr);\n }\n }\n );\n },\n\n handleFailure: function(chunkIdx, id, response, xhr) {\n var name = options.getName(id);\n\n log(\"Chunked upload request failed for \" + id + \", chunk \" + chunkIdx);\n\n handler.clearCachedChunk(id, chunkIdx);\n\n var responseToReport = upload.normalizeResponse(response, false),\n inProgressIdx;\n\n if (responseToReport.reset) {\n chunked.reset(id);\n }\n else {\n var inProgressChunksArray = handler._getFileState(id).chunking.inProgress;\n\n inProgressIdx = inProgressChunksArray ? qq.indexOf(inProgressChunksArray, chunkIdx) : -1;\n if (inProgressIdx >= 0) {\n handler._getFileState(id).chunking.inProgress.splice(inProgressIdx, 1);\n handler._getFileState(id).chunking.remaining.unshift(chunkIdx);\n }\n }\n\n // We may have aborted all other in-progress chunks for this file due to a failure.\n // If so, ignore the failures associated with those aborts.\n if (!handler._getFileState(id).temp.ignoreFailure) {\n // If this chunk has failed, we want to ignore all other failures of currently in-progress\n // chunks since they will be explicitly aborted\n if (concurrentChunkingPossible) {\n handler._getFileState(id).temp.ignoreFailure = true;\n\n log(qq.format(\"Going to attempt to abort these chunks: {}. These are currently in-progress: {}.\", JSON.stringify(Object.keys(handler._getXhrs(id))), JSON.stringify(handler._getFileState(id).chunking.inProgress)));\n qq.each(handler._getXhrs(id), function(ckid, ckXhr) {\n log(qq.format(\"Attempting to abort file {}.{}. XHR readyState {}. \", id, ckid, ckXhr.readyState));\n ckXhr.abort();\n // Flag the transport, in case we are waiting for some other async operation\n // to complete before attempting to upload the chunk\n ckXhr._cancelled = true;\n });\n\n // We must indicate that all aborted chunks are no longer in progress\n handler.moveInProgressToRemaining(id);\n\n // Free up any connections used by these chunks, but don't allow any\n // other files to take up the connections (until we have exhausted all auto-retries)\n connectionManager.free(id, true);\n }\n\n if (!options.onAutoRetry(id, name, responseToReport, xhr)) {\n // If one chunk fails, abort all of the others to avoid odd race conditions that occur\n // if a chunk succeeds immediately after one fails before we have determined if the upload\n // is a failure or not.\n upload.cleanup(id, responseToReport, xhr);\n }\n }\n },\n\n hasMoreParts: function(id) {\n return !!handler._getFileState(id).chunking.remaining.length;\n },\n\n nextPart: function(id) {\n var nextIdx = handler._getFileState(id).chunking.remaining.shift();\n\n if (nextIdx >= handler._getTotalChunks(id)) {\n nextIdx = null;\n }\n\n return nextIdx;\n },\n\n reset: function(id) {\n log(\"Server or callback has ordered chunking effort to be restarted on next attempt for item ID \" + id, \"error\");\n\n handler._maybeDeletePersistedChunkData(id);\n handler.reevaluateChunking(id);\n handler._getFileState(id).loaded = 0;\n handler._getFileState(id).attemptingResume = false;\n },\n\n sendNext: function(id) {\n var size = options.getSize(id),\n name = options.getName(id),\n chunkIdx = chunked.nextPart(id),\n chunkData = handler._getChunkData(id, chunkIdx),\n fileState = handler._getFileState(id),\n resuming = fileState.attemptingResume,\n inProgressChunks = fileState.chunking.inProgress || [];\n\n if (fileState.loaded == null) {\n fileState.loaded = 0;\n }\n\n // Don't follow-through with the resume attempt if the integrator returns false from onResume\n if (resuming && options.onResume(id, name, chunkData, fileState.customResumeData) === false) {\n chunked.reset(id);\n chunkIdx = chunked.nextPart(id);\n chunkData = handler._getChunkData(id, chunkIdx);\n resuming = false;\n }\n\n // If all chunks have already uploaded successfully, we must be re-attempting the finalize step.\n if (chunkIdx == null && inProgressChunks.length === 0) {\n chunked.finalize(id);\n }\n\n // Send the next chunk\n else {\n inProgressChunks.push(chunkIdx);\n handler._getFileState(id).chunking.inProgress = inProgressChunks;\n\n if (concurrentChunkingPossible) {\n connectionManager.open(id, chunkIdx);\n }\n\n if (concurrentChunkingPossible && connectionManager.available() && handler._getFileState(id).chunking.remaining.length) {\n chunked.sendNext(id);\n }\n\n if (chunkData.blob.size === 0) {\n log(qq.format(\"Chunk {} for file {} will not be uploaded, zero sized chunk.\", chunkIdx, id), \"error\");\n chunked.handleFailure(chunkIdx, id, \"File is no longer available\", null);\n }\n\n var onUploadChunkPromise = options.onUploadChunk(id, name, handler._getChunkDataForCallback(chunkData));\n\n onUploadChunkPromise.then(\n function(requestOverrides) {\n if (!options.isInProgress(id)) {\n log(qq.format(\"Not sending chunked upload request for item {}.{} - no longer in progress.\", id, chunkIdx));\n }\n else {\n log(qq.format(\"Sending chunked upload request for item {}.{}, bytes {}-{} of {}.\", id, chunkIdx, chunkData.start + 1, chunkData.end, size));\n\n var uploadChunkData = {\n chunkIdx: chunkIdx,\n id: id,\n overrides: requestOverrides,\n resuming: resuming\n };\n\n handler.uploadChunk(uploadChunkData).then(\n // upload chunk success\n function success(response, xhr) {\n log(\"Chunked upload request succeeded for \" + id + \", chunk \" + chunkIdx);\n\n handler.clearCachedChunk(id, chunkIdx);\n\n var inProgressChunks = handler._getFileState(id).chunking.inProgress || [],\n responseToReport = upload.normalizeResponse(response, true),\n inProgressChunkIdx = qq.indexOf(inProgressChunks, chunkIdx);\n\n log(qq.format(\"Chunk {} for file {} uploaded successfully.\", chunkIdx, id));\n\n chunked.done(id, chunkIdx, responseToReport, xhr);\n\n if (inProgressChunkIdx >= 0) {\n inProgressChunks.splice(inProgressChunkIdx, 1);\n }\n\n handler._maybePersistChunkedState(id);\n\n if (!chunked.hasMoreParts(id) && inProgressChunks.length === 0) {\n chunked.finalize(id);\n }\n else if (chunked.hasMoreParts(id)) {\n chunked.sendNext(id);\n }\n else {\n log(qq.format(\"File ID {} has no more chunks to send and these chunk indexes are still marked as in-progress: {}\", id, JSON.stringify(inProgressChunks)));\n }\n },\n\n // upload chunk failure\n function failure(response, xhr) {\n chunked.handleFailure(chunkIdx, id, response, xhr);\n }\n )\n .done(function () {\n handler.clearXhr(id, chunkIdx);\n });\n }\n },\n\n function(error) {\n chunked.handleFailure(chunkIdx, id, error, null);\n }\n );\n }\n }\n },\n\n connectionManager = {\n _open: [],\n _openChunks: {},\n _waiting: [],\n\n available: function() {\n var max = options.maxConnections,\n openChunkEntriesCount = 0,\n openChunksCount = 0;\n\n qq.each(connectionManager._openChunks, function(fileId, openChunkIndexes) {\n openChunkEntriesCount++;\n openChunksCount += openChunkIndexes.length;\n });\n\n return max - (connectionManager._open.length - openChunkEntriesCount + openChunksCount);\n },\n\n /**\n * Removes element from queue, starts upload of next\n */\n free: function(id, dontAllowNext) {\n var allowNext = !dontAllowNext,\n waitingIndex = qq.indexOf(connectionManager._waiting, id),\n connectionsIndex = qq.indexOf(connectionManager._open, id),\n nextId;\n\n delete connectionManager._openChunks[id];\n\n if (upload.getProxyOrBlob(id) instanceof qq.BlobProxy) {\n log(\"Generated blob upload has ended for \" + id + \", disposing generated blob.\");\n delete handler._getFileState(id).file;\n }\n\n // If this file was not consuming a connection, it was just waiting, so remove it from the waiting array\n if (waitingIndex >= 0) {\n connectionManager._waiting.splice(waitingIndex, 1);\n }\n // If this file was consuming a connection, allow the next file to be uploaded\n else if (allowNext && connectionsIndex >= 0) {\n connectionManager._open.splice(connectionsIndex, 1);\n\n nextId = connectionManager._waiting.shift();\n if (nextId >= 0) {\n connectionManager._open.push(nextId);\n upload.start(nextId);\n }\n }\n },\n\n getWaitingOrConnected: function() {\n var waitingOrConnected = [];\n\n // Chunked files may have multiple connections open per chunk (if concurrent chunking is enabled)\n // We need to grab the file ID of any file that has at least one chunk consuming a connection.\n qq.each(connectionManager._openChunks, function(fileId, chunks) {\n if (chunks && chunks.length) {\n waitingOrConnected.push(parseInt(fileId));\n }\n });\n\n // For non-chunked files, only one connection will be consumed per file.\n // This is where we aggregate those file IDs.\n qq.each(connectionManager._open, function(idx, fileId) {\n if (!connectionManager._openChunks[fileId]) {\n waitingOrConnected.push(parseInt(fileId));\n }\n });\n\n // There may be files waiting for a connection.\n waitingOrConnected = waitingOrConnected.concat(connectionManager._waiting);\n\n return waitingOrConnected;\n },\n\n isUsingConnection: function(id) {\n return qq.indexOf(connectionManager._open, id) >= 0;\n },\n\n open: function(id, chunkIdx) {\n if (chunkIdx == null) {\n connectionManager._waiting.push(id);\n }\n\n if (connectionManager.available()) {\n if (chunkIdx == null) {\n connectionManager._waiting.pop();\n connectionManager._open.push(id);\n }\n else {\n (function() {\n var openChunksEntry = connectionManager._openChunks[id] || [];\n openChunksEntry.push(chunkIdx);\n connectionManager._openChunks[id] = openChunksEntry;\n }());\n }\n\n return true;\n }\n\n return false;\n },\n\n reset: function() {\n connectionManager._waiting = [];\n connectionManager._open = [];\n }\n },\n\n simple = {\n send: function(id, name) {\n var fileState = handler._getFileState(id);\n\n if (!fileState) {\n log(\"Ignoring send request as this upload may have been cancelled, File ID \" + id, \"warn\");\n return;\n }\n\n fileState.loaded = 0;\n\n log(\"Sending simple upload request for \" + id);\n handler.uploadFile(id).then(\n function(response, optXhr) {\n log(\"Simple upload request succeeded for \" + id);\n\n var responseToReport = upload.normalizeResponse(response, true),\n size = options.getSize(id);\n\n options.onProgress(id, name, size, size);\n upload.maybeNewUuid(id, responseToReport);\n upload.cleanup(id, responseToReport, optXhr);\n },\n\n function(response, optXhr) {\n log(\"Simple upload request failed for \" + id);\n\n var responseToReport = upload.normalizeResponse(response, false);\n\n if (!options.onAutoRetry(id, name, responseToReport, optXhr)) {\n upload.cleanup(id, responseToReport, optXhr);\n }\n }\n );\n }\n },\n\n upload = {\n cancel: function(id) {\n log(\"Cancelling \" + id);\n options.paramsStore.remove(id);\n connectionManager.free(id);\n },\n\n cleanup: function(id, response, optXhr) {\n var name = options.getName(id);\n\n options.onComplete(id, name, response, optXhr);\n\n if (handler._getFileState(id)) {\n handler._clearXhrs && handler._clearXhrs(id);\n }\n\n connectionManager.free(id);\n },\n\n // Returns a qq.BlobProxy, or an actual File/Blob if no proxy is involved, or undefined\n // if none of these are available for the ID\n getProxyOrBlob: function(id) {\n return (handler.getProxy && handler.getProxy(id)) ||\n (handler.getFile && handler.getFile(id));\n },\n\n initHandler: function() {\n var handlerType = namespace ? qq[namespace] : qq.traditional,\n handlerModuleSubtype = qq.supportedFeatures.ajaxUploading ? \"Xhr\" : \"Form\";\n\n handler = new handlerType[handlerModuleSubtype + \"UploadHandler\"](\n options,\n {\n getCustomResumeData: options.getCustomResumeData,\n getDataByUuid: options.getDataByUuid,\n getName: options.getName,\n getSize: options.getSize,\n getUuid: options.getUuid,\n log: log,\n onCancel: options.onCancel,\n onProgress: options.onProgress,\n onUuidChanged: options.onUuidChanged,\n onFinalizing: function(id) {\n options.setStatus(id, qq.status.UPLOAD_FINALIZING);\n }\n }\n );\n\n if (handler._removeExpiredChunkingRecords) {\n handler._removeExpiredChunkingRecords();\n }\n },\n\n isDeferredEligibleForUpload: function(id) {\n return options.isQueued(id);\n },\n\n // For Blobs that are part of a group of generated images, along with a reference image,\n // this will ensure the blobs in the group are uploaded in the order they were triggered,\n // even if some async processing must be completed on one or more Blobs first.\n maybeDefer: function(id, blob) {\n // If we don't have a file/blob yet & no file/blob exists for this item, request it,\n // and then submit the upload to the specific handler once the blob is available.\n // ASSUMPTION: This condition will only ever be true if XHR uploading is supported.\n if (blob && !handler.getFile(id) && blob instanceof qq.BlobProxy) {\n\n // Blob creation may take some time, so the caller may want to update the\n // UI to indicate that an operation is in progress, even before the actual\n // upload begins and an onUpload callback is invoked.\n options.onUploadPrep(id);\n\n log(\"Attempting to generate a blob on-demand for \" + id);\n blob.create().then(function(generatedBlob) {\n log(\"Generated an on-demand blob for \" + id);\n\n // Update record associated with this file by providing the generated Blob\n handler.updateBlob(id, generatedBlob);\n\n // Propagate the size for this generated Blob\n options.setSize(id, generatedBlob.size);\n\n // Order handler to recalculate chunking possibility, if applicable\n handler.reevaluateChunking(id);\n\n upload.maybeSendDeferredFiles(id);\n },\n\n // Blob could not be generated. Fail the upload & attempt to prevent retries. Also bubble error message.\n function(errorMessage) {\n var errorResponse = {};\n\n if (errorMessage) {\n errorResponse.error = errorMessage;\n }\n\n log(qq.format(\"Failed to generate blob for ID {}. Error message: {}.\", id, errorMessage), \"error\");\n\n options.onComplete(id, options.getName(id), qq.extend(errorResponse, preventRetryResponse), null);\n upload.maybeSendDeferredFiles(id);\n connectionManager.free(id);\n });\n }\n else {\n return upload.maybeSendDeferredFiles(id);\n }\n\n return false;\n },\n\n // Upload any grouped blobs, in the proper order, that are ready to be uploaded\n maybeSendDeferredFiles: function(id) {\n var idsInGroup = options.getIdsInProxyGroup(id),\n uploadedThisId = false;\n\n if (idsInGroup && idsInGroup.length) {\n log(\"Maybe ready to upload proxy group file \" + id);\n\n qq.each(idsInGroup, function(idx, idInGroup) {\n if (upload.isDeferredEligibleForUpload(idInGroup) && !!handler.getFile(idInGroup)) {\n uploadedThisId = idInGroup === id;\n upload.now(idInGroup);\n }\n else if (upload.isDeferredEligibleForUpload(idInGroup)) {\n return false;\n }\n });\n }\n else {\n uploadedThisId = true;\n upload.now(id);\n }\n\n return uploadedThisId;\n },\n\n maybeNewUuid: function(id, response) {\n if (response.newUuid !== undefined) {\n options.onUuidChanged(id, response.newUuid);\n }\n },\n\n // The response coming from handler implementations may be in various formats.\n // Instead of hoping a promise nested 5 levels deep will always return an object\n // as its first param, let's just normalize the response here.\n normalizeResponse: function(originalResponse, successful) {\n var response = originalResponse;\n\n // The passed \"response\" param may not be a response at all.\n // It could be a string, detailing the error, for example.\n if (!qq.isObject(originalResponse)) {\n response = {};\n\n if (qq.isString(originalResponse) && !successful) {\n response.error = originalResponse;\n }\n }\n\n response.success = successful;\n\n return response;\n },\n\n now: function(id) {\n var name = options.getName(id);\n\n if (!controller.isValid(id)) {\n throw new qq.Error(id + \" is not a valid file ID to upload!\");\n }\n\n options.onUpload(id, name).then(\n function(response) {\n if (response && response.pause) {\n options.setStatus(id, qq.status.PAUSED);\n handler.pause(id);\n connectionManager.free(id);\n }\n else {\n if (chunkingPossible && handler._shouldChunkThisFile(id)) {\n chunked.sendNext(id);\n }\n else {\n simple.send(id, name);\n }\n }\n },\n\n function(error) {\n error = error || {};\n\n log(id + \" upload start aborted due to rejected onUpload Promise - details: \" + error, \"error\");\n\n if (!options.onAutoRetry(id, name, error.responseJSON || {})) {\n var response = upload.normalizeResponse(error.responseJSON, false);\n upload.cleanup(id, response);\n }\n }\n );\n },\n\n start: function(id) {\n var blobToUpload = upload.getProxyOrBlob(id);\n\n if (blobToUpload) {\n return upload.maybeDefer(id, blobToUpload);\n }\n else {\n upload.now(id);\n return true;\n }\n }\n };\n\n qq.extend(this, {\n /**\n * Adds file or file input to the queue\n **/\n add: function(id, file) {\n handler.add.apply(this, arguments);\n },\n\n /**\n * Sends the file identified by id\n */\n upload: function(id) {\n if (connectionManager.open(id)) {\n return upload.start(id);\n }\n return false;\n },\n\n retry: function(id) {\n // On retry, if concurrent chunking has been enabled, we may have aborted all other in-progress chunks\n // for a file when encountering a failed chunk upload. We then signaled the controller to ignore\n // all failures associated with these aborts. We are now retrying, so we don't want to ignore\n // any more failures at this point.\n if (concurrentChunkingPossible) {\n handler._getFileState(id).temp.ignoreFailure = false;\n }\n\n // If we are attempting to retry a file that is already consuming a connection, this is likely an auto-retry.\n // Just go ahead and ask the handler to upload again.\n if (connectionManager.isUsingConnection(id)) {\n return upload.start(id);\n }\n\n // If we are attempting to retry a file that is not currently consuming a connection,\n // this is likely a manual retry attempt. We will need to ensure a connection is available\n // before the retry commences.\n else {\n return controller.upload(id);\n }\n },\n\n /**\n * Cancels file upload by id\n */\n cancel: function(id) {\n var cancelRetVal = handler.cancel(id);\n\n if (qq.isGenericPromise(cancelRetVal)) {\n cancelRetVal.then(function() {\n upload.cancel(id);\n });\n }\n else if (cancelRetVal !== false) {\n upload.cancel(id);\n }\n },\n\n /**\n * Cancels all queued or in-progress uploads\n */\n cancelAll: function() {\n var waitingOrConnected = connectionManager.getWaitingOrConnected(),\n i;\n\n // ensure files are cancelled in reverse order which they were added\n // to avoid a flash of time where a queued file begins to upload before it is canceled\n if (waitingOrConnected.length) {\n for (i = waitingOrConnected.length - 1; i >= 0; i--) {\n controller.cancel(waitingOrConnected[i]);\n }\n }\n\n connectionManager.reset();\n },\n\n // Returns a File, Blob, or the Blob/File for the reference/parent file if the targeted blob is a proxy.\n // Undefined if no file record is available.\n getFile: function(id) {\n if (handler.getProxy && handler.getProxy(id)) {\n return handler.getProxy(id).referenceBlob;\n }\n\n return handler.getFile && handler.getFile(id);\n },\n\n // Returns true if the Blob associated with the ID is related to a proxy s\n isProxied: function(id) {\n return !!(handler.getProxy && handler.getProxy(id));\n },\n\n getInput: function(id) {\n if (handler.getInput) {\n return handler.getInput(id);\n }\n },\n\n reset: function() {\n log(\"Resetting upload handler\");\n controller.cancelAll();\n connectionManager.reset();\n handler.reset();\n },\n\n expunge: function(id) {\n if (controller.isValid(id)) {\n return handler.expunge(id);\n }\n },\n\n /**\n * Determine if the file exists.\n */\n isValid: function(id) {\n return handler.isValid(id);\n },\n\n hasResumeRecord: function(id) {\n var key = handler.isValid(id) &&\n handler._getLocalStorageId &&\n handler._getLocalStorageId(id);\n\n if (key) {\n return !!localStorage.getItem(key);\n }\n\n return false;\n },\n\n getResumableFilesData: function() {\n if (handler.getResumableFilesData) {\n return handler.getResumableFilesData();\n }\n return [];\n },\n\n /**\n * This may or may not be implemented, depending on the handler. For handlers where a third-party ID is\n * available (such as the \"key\" for Amazon S3), this will return that value. Otherwise, the return value\n * will be undefined.\n *\n * @param id Internal file ID\n * @returns {*} Some identifier used by a 3rd-party service involved in the upload process\n */\n getThirdPartyFileId: function(id) {\n if (controller.isValid(id)) {\n return handler.getThirdPartyFileId(id);\n }\n },\n\n /**\n * Attempts to pause the associated upload if the specific handler supports this and the file is \"valid\".\n * @param id ID of the upload/file to pause\n * @returns {boolean} true if the upload was paused\n */\n pause: function(id) {\n if (controller.isResumable(id) && handler.pause && controller.isValid(id) && handler.pause(id)) {\n connectionManager.free(id);\n handler.moveInProgressToRemaining(id);\n return true;\n }\n return false;\n },\n\n isAttemptingResume: function(id) {\n return !!handler.isAttemptingResume && handler.isAttemptingResume(id);\n },\n\n // True if the file is eligible for pause/resume.\n isResumable: function(id) {\n return !!handler.isResumable && handler.isResumable(id);\n }\n });\n\n qq.extend(options, o);\n log = options.log;\n chunkingPossible = options.chunking.enabled && qq.supportedFeatures.chunking;\n concurrentChunkingPossible = chunkingPossible && options.chunking.concurrent.enabled;\n\n preventRetryResponse = (function() {\n var response = {};\n\n response[options.preventRetryParam] = true;\n\n return response;\n }());\n\n upload.initHandler();\n};\n","/*globals qq */\n/*jshint -W117 */\nqq.WindowReceiveMessage = function(o) {\n \"use strict\";\n\n var options = {\n log: function(message, level) {}\n },\n callbackWrapperDetachers = {};\n\n qq.extend(options, o);\n\n qq.extend(this, {\n receiveMessage: function(id, callback) {\n var onMessageCallbackWrapper = function(event) {\n callback(event.data);\n };\n\n if (window.postMessage) {\n callbackWrapperDetachers[id] = qq(window).attach(\"message\", onMessageCallbackWrapper);\n }\n else {\n log(\"iframe message passing not supported in this browser!\", \"error\");\n }\n },\n\n stopReceivingMessages: function(id) {\n if (window.postMessage) {\n var detacher = callbackWrapperDetachers[id];\n if (detacher) {\n detacher();\n }\n }\n }\n });\n};\n","/* globals qq */\n/**\n * Common APIs exposed to creators of upload via form/iframe handlers. This is reused and possibly overridden\n * in some cases by specific form upload handlers.\n *\n * @constructor\n */\nqq.FormUploadHandler = function(spec) {\n \"use strict\";\n\n var options = spec.options,\n handler = this,\n proxy = spec.proxy,\n formHandlerInstanceId = qq.getUniqueId(),\n onloadCallbacks = {},\n detachLoadEvents = {},\n postMessageCallbackTimers = {},\n isCors = options.isCors,\n inputName = options.inputName,\n getUuid = proxy.getUuid,\n log = proxy.log,\n corsMessageReceiver = new qq.WindowReceiveMessage({log: log});\n\n /**\n * Remove any trace of the file from the handler.\n *\n * @param id ID of the associated file\n */\n function expungeFile(id) {\n delete detachLoadEvents[id];\n\n // If we are dealing with CORS, we might still be waiting for a response from a loaded iframe.\n // In that case, terminate the timer waiting for a message from the loaded iframe\n // and stop listening for any more messages coming from this iframe.\n if (isCors) {\n clearTimeout(postMessageCallbackTimers[id]);\n delete postMessageCallbackTimers[id];\n corsMessageReceiver.stopReceivingMessages(id);\n }\n\n var iframe = document.getElementById(handler._getIframeName(id));\n if (iframe) {\n // To cancel request set src to something else. We use src=\"javascript:false;\"\n // because it doesn't trigger ie6 prompt on https\n /* jshint scripturl:true */\n iframe.setAttribute(\"src\", \"javascript:false;\");\n\n qq(iframe).remove();\n }\n }\n\n /**\n * @param iframeName `document`-unique Name of the associated iframe\n * @returns {*} ID of the associated file\n */\n function getFileIdForIframeName(iframeName) {\n return iframeName.split(\"_\")[0];\n }\n\n /**\n * Generates an iframe to be used as a target for upload-related form submits. This also adds the iframe\n * to the current `document`. Note that the iframe is hidden from view.\n *\n * @param name Name of the iframe.\n * @returns {HTMLIFrameElement} The created iframe\n */\n function initIframeForUpload(name) {\n var iframe = qq.toElement(\"\");\n\n iframe.setAttribute(\"id\", name);\n\n iframe.style.display = \"none\";\n document.body.appendChild(iframe);\n\n return iframe;\n }\n\n /**\n * If we are in CORS mode, we must listen for messages (containing the server response) from the associated\n * iframe, since we cannot directly parse the content of the iframe due to cross-origin restrictions.\n *\n * @param iframe Listen for messages on this iframe.\n * @param callback Invoke this callback with the message from the iframe.\n */\n function registerPostMessageCallback(iframe, callback) {\n var iframeName = iframe.id,\n fileId = getFileIdForIframeName(iframeName),\n uuid = getUuid(fileId);\n\n onloadCallbacks[uuid] = callback;\n\n // When the iframe has loaded (after the server responds to an upload request)\n // declare the attempt a failure if we don't receive a valid message shortly after the response comes in.\n detachLoadEvents[fileId] = qq(iframe).attach(\"load\", function() {\n if (handler.getInput(fileId)) {\n log(\"Received iframe load event for CORS upload request (iframe name \" + iframeName + \")\");\n\n postMessageCallbackTimers[iframeName] = setTimeout(function() {\n var errorMessage = \"No valid message received from loaded iframe for iframe name \" + iframeName;\n log(errorMessage, \"error\");\n callback({\n error: errorMessage\n });\n }, 1000);\n }\n });\n\n // Listen for messages coming from this iframe. When a message has been received, cancel the timer\n // that declares the upload a failure if a message is not received within a reasonable amount of time.\n corsMessageReceiver.receiveMessage(iframeName, function(message) {\n log(\"Received the following window message: '\" + message + \"'\");\n var fileId = getFileIdForIframeName(iframeName),\n response = handler._parseJsonResponse(message),\n uuid = response.uuid,\n onloadCallback;\n\n if (uuid && onloadCallbacks[uuid]) {\n log(\"Handling response for iframe name \" + iframeName);\n clearTimeout(postMessageCallbackTimers[iframeName]);\n delete postMessageCallbackTimers[iframeName];\n\n handler._detachLoadEvent(iframeName);\n\n onloadCallback = onloadCallbacks[uuid];\n\n delete onloadCallbacks[uuid];\n corsMessageReceiver.stopReceivingMessages(iframeName);\n onloadCallback(response);\n }\n else if (!uuid) {\n log(\"'\" + message + \"' does not contain a UUID - ignoring.\");\n }\n });\n }\n\n qq.extend(this, new qq.UploadHandler(spec));\n\n qq.override(this, function(super_) {\n return {\n /**\n * Adds File or Blob to the queue\n **/\n add: function(id, fileInput) {\n super_.add(id, {input: fileInput});\n\n fileInput.setAttribute(\"name\", inputName);\n\n // remove file input from DOM\n if (fileInput.parentNode) {\n qq(fileInput).remove();\n }\n },\n\n expunge: function(id) {\n expungeFile(id);\n super_.expunge(id);\n },\n\n isValid: function(id) {\n return super_.isValid(id) &&\n handler._getFileState(id).input !== undefined;\n }\n };\n });\n\n qq.extend(this, {\n getInput: function(id) {\n return handler._getFileState(id).input;\n },\n\n /**\n * This function either delegates to a more specific message handler if CORS is involved,\n * or simply registers a callback when the iframe has been loaded that invokes the passed callback\n * after determining if the content of the iframe is accessible.\n *\n * @param iframe Associated iframe\n * @param callback Callback to invoke after we have determined if the iframe content is accessible.\n */\n _attachLoadEvent: function(iframe, callback) {\n /*jslint eqeq: true*/\n var responseDescriptor;\n\n if (isCors) {\n registerPostMessageCallback(iframe, callback);\n }\n else {\n detachLoadEvents[iframe.id] = qq(iframe).attach(\"load\", function() {\n log(\"Received response for \" + iframe.id);\n\n // when we remove iframe from dom\n // the request stops, but in IE load\n // event fires\n if (!iframe.parentNode) {\n return;\n }\n\n try {\n // fixing Opera 10.53\n if (iframe.contentDocument &&\n iframe.contentDocument.body &&\n iframe.contentDocument.body.innerHTML == \"false\") {\n // In Opera event is fired second time\n // when body.innerHTML changed from false\n // to server response approx. after 1 sec\n // when we upload file with iframe\n return;\n }\n }\n catch (error) {\n //IE may throw an \"access is denied\" error when attempting to access contentDocument on the iframe in some cases\n log(\"Error when attempting to access iframe during handling of upload response (\" + error.message + \")\", \"error\");\n responseDescriptor = {success: false};\n }\n\n callback(responseDescriptor);\n });\n }\n },\n\n /**\n * Creates an iframe with a specific document-unique name.\n *\n * @param id ID of the associated file\n * @returns {HTMLIFrameElement}\n */\n _createIframe: function(id) {\n var iframeName = handler._getIframeName(id);\n\n return initIframeForUpload(iframeName);\n },\n\n /**\n * Called when we are no longer interested in being notified when an iframe has loaded.\n *\n * @param id Associated file ID\n */\n _detachLoadEvent: function(id) {\n if (detachLoadEvents[id] !== undefined) {\n detachLoadEvents[id]();\n delete detachLoadEvents[id];\n }\n },\n\n /**\n * @param fileId ID of the associated file\n * @returns {string} The `document`-unique name of the iframe\n */\n _getIframeName: function(fileId) {\n return fileId + \"_\" + formHandlerInstanceId;\n },\n\n /**\n * Generates a form element and appends it to the `document`. When the form is submitted, a specific iframe is targeted.\n * The name of the iframe is passed in as a property of the spec parameter, and must be unique in the `document`. Note\n * that the form is hidden from view.\n *\n * @param spec An object containing various properties to be used when constructing the form. Required properties are\n * currently: `method`, `endpoint`, `params`, `paramsInBody`, and `targetName`.\n * @returns {HTMLFormElement} The created form\n */\n _initFormForUpload: function(spec) {\n var method = spec.method,\n endpoint = spec.endpoint,\n params = spec.params,\n paramsInBody = spec.paramsInBody,\n targetName = spec.targetName,\n form = qq.toElement(\" \"),\n url = endpoint;\n\n if (paramsInBody) {\n qq.obj2Inputs(params, form);\n }\n else {\n url = qq.obj2url(params, endpoint);\n }\n\n form.setAttribute(\"action\", url);\n form.setAttribute(\"target\", targetName);\n form.style.display = \"none\";\n document.body.appendChild(form);\n\n return form;\n },\n\n /**\n * @param innerHtmlOrMessage JSON message\n * @returns {*} The parsed response, or an empty object if the response could not be parsed\n */\n _parseJsonResponse: function(innerHtmlOrMessage) {\n var response = {};\n\n try {\n response = qq.parseJson(innerHtmlOrMessage);\n }\n catch (error) {\n log(\"Error when attempting to parse iframe upload response (\" + error.message + \")\", \"error\");\n }\n\n return response;\n }\n });\n};\n","/* globals qq */\n/**\n * Common API exposed to creators of XHR handlers. This is reused and possibly overriding in some cases by specific\n * XHR upload handlers.\n *\n * @constructor\n */\nqq.XhrUploadHandler = function(spec) {\n \"use strict\";\n\n var handler = this,\n namespace = spec.options.namespace,\n proxy = spec.proxy,\n chunking = spec.options.chunking,\n getChunkSize = function(id) {\n var fileState = handler._getFileState(id);\n\n if (fileState.chunkSize) {\n return fileState.chunkSize;\n }\n\n else {\n var chunkSize = chunking.partSize;\n\n if (qq.isFunction(chunkSize)) {\n chunkSize = chunkSize(id, getSize(id));\n }\n\n fileState.chunkSize = chunkSize;\n return chunkSize;\n }\n },\n resume = spec.options.resume,\n chunkFiles = chunking && spec.options.chunking.enabled && qq.supportedFeatures.chunking,\n resumeEnabled = resume && spec.options.resume.enabled && chunkFiles && qq.supportedFeatures.resume,\n getName = proxy.getName,\n getSize = proxy.getSize,\n getUuid = proxy.getUuid,\n getEndpoint = proxy.getEndpoint,\n getDataByUuid = proxy.getDataByUuid,\n onUuidChanged = proxy.onUuidChanged,\n onProgress = proxy.onProgress,\n log = proxy.log,\n getCustomResumeData = proxy.getCustomResumeData;\n\n function abort(id) {\n qq.each(handler._getXhrs(id), function(xhrId, xhr) {\n var ajaxRequester = handler._getAjaxRequester(id, xhrId);\n\n xhr.onreadystatechange = null;\n xhr.upload.onprogress = null;\n xhr.abort();\n ajaxRequester && ajaxRequester.canceled && ajaxRequester.canceled(id);\n });\n }\n\n qq.extend(this, new qq.UploadHandler(spec));\n\n qq.override(this, function(super_) {\n return {\n /**\n * Adds File or Blob to the queue\n **/\n add: function(id, blobOrProxy) {\n if (qq.isFile(blobOrProxy) || qq.isBlob(blobOrProxy)) {\n super_.add(id, {file: blobOrProxy});\n }\n else if (blobOrProxy instanceof qq.BlobProxy) {\n super_.add(id, {proxy: blobOrProxy});\n }\n else {\n throw new Error(\"Passed obj is not a File, Blob, or proxy\");\n }\n\n handler._initTempState(id);\n resumeEnabled && handler._maybePrepareForResume(id);\n },\n\n expunge: function(id) {\n abort(id);\n handler._maybeDeletePersistedChunkData(id);\n handler._clearXhrs(id);\n super_.expunge(id);\n }\n };\n });\n\n qq.extend(this, {\n // Clear the cached chunk `Blob` after we are done with it, just in case the `Blob` bytes are stored in memory.\n clearCachedChunk: function(id, chunkIdx) {\n var fileState = handler._getFileState(id);\n\n if (fileState) {\n delete fileState.temp.cachedChunks[chunkIdx];\n }\n },\n\n clearXhr: function(id, chunkIdx) {\n var tempState = handler._getFileState(id).temp;\n\n if (tempState.xhrs) {\n delete tempState.xhrs[chunkIdx];\n }\n if (tempState.ajaxRequesters) {\n delete tempState.ajaxRequesters[chunkIdx];\n }\n },\n\n // Called when all chunks have been successfully uploaded. Expected promissory return type.\n // This defines the default behavior if nothing further is required when all chunks have been uploaded.\n finalizeChunks: function(id, responseParser) {\n var lastChunkIdx = handler._getTotalChunks(id) - 1,\n xhr = handler._getXhr(id, lastChunkIdx);\n\n if (responseParser) {\n return new qq.Promise().success(responseParser(xhr), xhr);\n }\n\n return new qq.Promise().success({}, xhr);\n },\n\n getFile: function(id) {\n return handler.isValid(id) && handler._getFileState(id).file;\n },\n\n getProxy: function(id) {\n return handler.isValid(id) && handler._getFileState(id).proxy;\n },\n\n /**\n * @returns {Array} Array of objects containing properties useful to integrators\n * when it is important to determine which files are potentially resumable.\n */\n getResumableFilesData: function() {\n var resumableFilesData = [];\n\n handler._iterateResumeRecords(function(key, uploadData) {\n handler.moveInProgressToRemaining(null, uploadData.chunking.inProgress, uploadData.chunking.remaining);\n\n var data = {\n name: uploadData.name,\n remaining: uploadData.chunking.remaining,\n size: uploadData.size,\n uuid: uploadData.uuid\n };\n\n if (uploadData.key) {\n data.key = uploadData.key;\n }\n\n if (uploadData.customResumeData) {\n data.customResumeData = uploadData.customResumeData;\n }\n\n resumableFilesData.push(data);\n });\n\n return resumableFilesData;\n },\n\n isAttemptingResume: function(id) {\n return handler._getFileState(id).attemptingResume;\n },\n\n isResumable: function(id) {\n return !!chunking && handler.isValid(id) &&\n !handler._getFileState(id).notResumable;\n },\n\n moveInProgressToRemaining: function(id, optInProgress, optRemaining) {\n var fileState = handler._getFileState(id) || {},\n chunkingState = fileState.chunking || {},\n inProgress = optInProgress || chunkingState.inProgress,\n remaining = optRemaining || chunkingState.remaining;\n\n if (inProgress) {\n log(qq.format(\"Moving these chunks from in-progress {}, to remaining.\", JSON.stringify(inProgress)));\n inProgress.reverse();\n qq.each(inProgress, function(idx, chunkIdx) {\n remaining.unshift(chunkIdx);\n });\n inProgress.length = 0;\n }\n },\n\n pause: function(id) {\n if (handler.isValid(id)) {\n log(qq.format(\"Aborting XHR upload for {} '{}' due to pause instruction.\", id, getName(id)));\n handler._getFileState(id).paused = true;\n abort(id);\n return true;\n }\n },\n\n reevaluateChunking: function(id) {\n if (chunking && handler.isValid(id)) {\n var state = handler._getFileState(id),\n totalChunks,\n i;\n\n delete state.chunking;\n\n state.chunking = {};\n totalChunks = handler._getTotalChunks(id);\n if (totalChunks > 1 || chunking.mandatory) {\n state.chunking.enabled = true;\n state.chunking.parts = totalChunks;\n state.chunking.remaining = [];\n\n for (i = 0; i < totalChunks; i++) {\n state.chunking.remaining.push(i);\n }\n\n handler._initTempState(id);\n }\n else {\n state.chunking.enabled = false;\n }\n }\n },\n\n updateBlob: function(id, newBlob) {\n if (handler.isValid(id)) {\n handler._getFileState(id).file = newBlob;\n }\n },\n\n _clearXhrs: function(id) {\n var tempState = handler._getFileState(id).temp;\n\n qq.each(tempState.ajaxRequesters, function(chunkId) {\n delete tempState.ajaxRequesters[chunkId];\n });\n\n qq.each(tempState.xhrs, function(chunkId) {\n delete tempState.xhrs[chunkId];\n });\n },\n\n /**\n * Creates an XHR instance for this file and stores it in the fileState.\n *\n * @param id File ID\n * @param optChunkIdx The chunk index associated with this XHR, if applicable\n * @returns {XMLHttpRequest}\n */\n _createXhr: function(id, optChunkIdx) {\n return handler._registerXhr(id, optChunkIdx, qq.createXhrInstance());\n },\n\n _getAjaxRequester: function(id, optChunkIdx) {\n var chunkIdx = optChunkIdx == null ? -1 : optChunkIdx;\n return handler._getFileState(id).temp.ajaxRequesters[chunkIdx];\n },\n\n _getChunkData: function(id, chunkIndex) {\n var chunkSize = getChunkSize(id),\n fileSize = getSize(id),\n fileOrBlob = handler.getFile(id),\n startBytes = chunkSize * chunkIndex,\n endBytes = startBytes + chunkSize >= fileSize ? fileSize : startBytes + chunkSize,\n totalChunks = handler._getTotalChunks(id),\n cachedChunks = this._getFileState(id).temp.cachedChunks,\n\n // To work around a Webkit GC bug, we must keep each chunk `Blob` in scope until we are done with it.\n // See https://github.com/FineUploader/fine-uploader/issues/937#issuecomment-41418760\n blob = cachedChunks[chunkIndex] || qq.sliceBlob(fileOrBlob, startBytes, endBytes);\n\n cachedChunks[chunkIndex] = blob;\n\n return {\n part: chunkIndex,\n start: startBytes,\n end: endBytes,\n count: totalChunks,\n blob: blob,\n size: endBytes - startBytes\n };\n },\n\n _getChunkDataForCallback: function(chunkData) {\n return {\n partIndex: chunkData.part,\n startByte: chunkData.start + 1,\n endByte: chunkData.end,\n totalParts: chunkData.count\n };\n },\n\n /**\n * @param id File ID\n * @returns {string} Identifier for this item that may appear in the browser's local storage\n */\n _getLocalStorageId: function(id) {\n var formatVersion = \"5.0\",\n name = getName(id),\n size = getSize(id),\n chunkSize = getChunkSize(id),\n endpoint = getEndpoint(id),\n customKeys = resume.customKeys(id),\n localStorageId = qq.format(\"qq{}resume{}-{}-{}-{}-{}\", namespace, formatVersion, name, size, chunkSize, endpoint);\n\n customKeys.forEach(function(key) {\n localStorageId += \"-\" + key;\n });\n\n return localStorageId;\n },\n\n _getMimeType: function(id) {\n return handler.getFile(id).type;\n },\n\n _getPersistableData: function(id) {\n return handler._getFileState(id).chunking;\n },\n\n /**\n * @param id ID of the associated file\n * @returns {number} Number of parts this file can be divided into, or undefined if chunking is not supported in this UA\n */\n _getTotalChunks: function(id) {\n if (chunking) {\n var fileSize = getSize(id),\n chunkSize = getChunkSize(id);\n\n return Math.ceil(fileSize / chunkSize);\n }\n },\n\n _getXhr: function(id, optChunkIdx) {\n var chunkIdx = optChunkIdx == null ? -1 : optChunkIdx;\n return handler._getFileState(id).temp.xhrs[chunkIdx];\n },\n\n _getXhrs: function(id) {\n return handler._getFileState(id).temp.xhrs;\n },\n\n // Iterates through all XHR handler-created resume records (in local storage),\n // invoking the passed callback and passing in the key and value of each local storage record.\n _iterateResumeRecords: function(callback) {\n if (resumeEnabled) {\n qq.each(localStorage, function(key, item) {\n if (key.indexOf(qq.format(\"qq{}resume\", namespace)) === 0) {\n var uploadData = JSON.parse(item);\n callback(key, uploadData);\n }\n });\n }\n },\n\n _initTempState: function(id) {\n handler._getFileState(id).temp = {\n ajaxRequesters: {},\n chunkProgress: {},\n xhrs: {},\n cachedChunks: {}\n };\n },\n\n _markNotResumable: function(id) {\n handler._getFileState(id).notResumable = true;\n },\n\n // Removes a chunked upload record from local storage, if possible.\n // Returns true if the item was removed, false otherwise.\n _maybeDeletePersistedChunkData: function(id) {\n var localStorageId;\n\n if (resumeEnabled && handler.isResumable(id)) {\n localStorageId = handler._getLocalStorageId(id);\n\n if (localStorageId && localStorage.getItem(localStorageId)) {\n localStorage.removeItem(localStorageId);\n return true;\n }\n }\n\n return false;\n },\n\n // If this is a resumable upload, grab the relevant data from storage and items in memory that track this upload\n // so we can pick up from where we left off.\n _maybePrepareForResume: function(id) {\n var state = handler._getFileState(id),\n localStorageId, persistedData;\n\n // Resume is enabled and possible and this is the first time we've tried to upload this file in this session,\n // so prepare for a resume attempt.\n if (resumeEnabled && state.key === undefined) {\n localStorageId = handler._getLocalStorageId(id);\n persistedData = localStorage.getItem(localStorageId);\n\n // If we found this item in local storage, maybe we should resume it.\n if (persistedData) {\n persistedData = JSON.parse(persistedData);\n\n // If we found a resume record but we have already handled this file in this session,\n // don't try to resume it & ensure we don't persist future check data\n if (getDataByUuid(persistedData.uuid)) {\n handler._markNotResumable(id);\n }\n else {\n log(qq.format(\"Identified file with ID {} and name of {} as resumable.\", id, getName(id)));\n\n onUuidChanged(id, persistedData.uuid);\n\n state.key = persistedData.key;\n state.chunking = persistedData.chunking;\n state.loaded = persistedData.loaded;\n state.customResumeData = persistedData.customResumeData;\n state.attemptingResume = true;\n\n handler.moveInProgressToRemaining(id);\n }\n }\n }\n },\n\n // Persist any data needed to resume this upload in a new session.\n _maybePersistChunkedState: function(id) {\n var state = handler._getFileState(id),\n localStorageId, persistedData;\n\n // If local storage isn't supported by the browser, or if resume isn't enabled or possible, give up\n if (resumeEnabled && handler.isResumable(id)) {\n var customResumeData = getCustomResumeData(id);\n\n localStorageId = handler._getLocalStorageId(id);\n\n persistedData = {\n name: getName(id),\n size: getSize(id),\n uuid: getUuid(id),\n key: state.key,\n chunking: state.chunking,\n loaded: state.loaded,\n lastUpdated: Date.now(),\n };\n\n if (customResumeData) {\n persistedData.customResumeData = customResumeData;\n }\n\n try {\n localStorage.setItem(localStorageId, JSON.stringify(persistedData));\n }\n catch (error) {\n log(qq.format(\"Unable to save resume data for '{}' due to error: '{}'.\", id, error.toString()), \"warn\");\n }\n }\n },\n\n _registerProgressHandler: function(id, chunkIdx, chunkSize) {\n var xhr = handler._getXhr(id, chunkIdx),\n name = getName(id),\n progressCalculator = {\n simple: function(loaded, total) {\n var fileSize = getSize(id);\n\n if (loaded === total) {\n onProgress(id, name, fileSize, fileSize);\n }\n else {\n onProgress(id, name, (loaded >= fileSize ? fileSize - 1 : loaded), fileSize);\n }\n },\n\n chunked: function(loaded, total) {\n var chunkProgress = handler._getFileState(id).temp.chunkProgress,\n totalSuccessfullyLoadedForFile = handler._getFileState(id).loaded,\n loadedForRequest = loaded,\n totalForRequest = total,\n totalFileSize = getSize(id),\n estActualChunkLoaded = loadedForRequest - (totalForRequest - chunkSize),\n totalLoadedForFile = totalSuccessfullyLoadedForFile;\n\n chunkProgress[chunkIdx] = estActualChunkLoaded;\n\n qq.each(chunkProgress, function(chunkIdx, chunkLoaded) {\n totalLoadedForFile += chunkLoaded;\n });\n\n onProgress(id, name, totalLoadedForFile, totalFileSize);\n }\n };\n\n xhr.upload.onprogress = function(e) {\n if (e.lengthComputable) {\n /* jshint eqnull: true */\n var type = chunkSize == null ? \"simple\" : \"chunked\";\n progressCalculator[type](e.loaded, e.total);\n }\n };\n },\n\n /**\n * Registers an XHR transport instance created elsewhere.\n *\n * @param id ID of the associated file\n * @param optChunkIdx The chunk index associated with this XHR, if applicable\n * @param xhr XMLHttpRequest object instance\n * @param optAjaxRequester `qq.AjaxRequester` associated with this request, if applicable.\n * @returns {XMLHttpRequest}\n */\n _registerXhr: function(id, optChunkIdx, xhr, optAjaxRequester) {\n var xhrsId = optChunkIdx == null ? -1 : optChunkIdx,\n tempState = handler._getFileState(id).temp;\n\n tempState.xhrs = tempState.xhrs || {};\n tempState.ajaxRequesters = tempState.ajaxRequesters || {};\n\n tempState.xhrs[xhrsId] = xhr;\n\n if (optAjaxRequester) {\n tempState.ajaxRequesters[xhrsId] = optAjaxRequester;\n }\n\n return xhr;\n },\n\n // Deletes any local storage records that are \"expired\".\n _removeExpiredChunkingRecords: function() {\n var expirationDays = resume.recordsExpireIn;\n\n handler._iterateResumeRecords(function(key, uploadData) {\n var expirationDate = new Date(uploadData.lastUpdated);\n\n // transform updated date into expiration date\n expirationDate.setDate(expirationDate.getDate() + expirationDays);\n\n if (expirationDate.getTime() <= Date.now()) {\n log(\"Removing expired resume record with key \" + key);\n localStorage.removeItem(key);\n }\n });\n },\n\n /**\n * Determine if the associated file should be chunked.\n *\n * @param id ID of the associated file\n * @returns {*} true if chunking is enabled, possible, and the file can be split into more than 1 part\n */\n _shouldChunkThisFile: function(id) {\n var state = handler._getFileState(id);\n\n // file may no longer be available if it was recently cancelled\n if (state) {\n if (!state.chunking) {\n handler.reevaluateChunking(id);\n }\n\n return state.chunking.enabled;\n }\n }\n });\n};\n","/*globals qq, XMLHttpRequest*/\nqq.DeleteFileAjaxRequester = function(o) {\n \"use strict\";\n\n var requester,\n options = {\n method: \"DELETE\",\n uuidParamName: \"qquuid\",\n endpointStore: {},\n maxConnections: 3,\n customHeaders: function(id) {return {};},\n paramsStore: {},\n cors: {\n expected: false,\n sendCredentials: false\n },\n log: function(str, level) {},\n onDelete: function(id) {},\n onDeleteComplete: function(id, xhrOrXdr, isError) {}\n };\n\n qq.extend(options, o);\n\n function getMandatedParams() {\n if (options.method.toUpperCase() === \"POST\") {\n return {\n _method: \"DELETE\"\n };\n }\n\n return {};\n }\n\n requester = qq.extend(this, new qq.AjaxRequester({\n acceptHeader: \"application/json\",\n validMethods: [\"POST\", \"DELETE\"],\n method: options.method,\n endpointStore: options.endpointStore,\n paramsStore: options.paramsStore,\n mandatedParams: getMandatedParams(),\n maxConnections: options.maxConnections,\n customHeaders: function(id) {\n return options.customHeaders.get(id);\n },\n log: options.log,\n onSend: options.onDelete,\n onComplete: options.onDeleteComplete,\n cors: options.cors\n }));\n\n qq.extend(this, {\n sendDelete: function(id, uuid, additionalMandatedParams) {\n var additionalOptions = additionalMandatedParams || {};\n\n options.log(\"Submitting delete file request for \" + id);\n\n if (options.method === \"DELETE\") {\n requester.initTransport(id)\n .withPath(uuid)\n .withParams(additionalOptions)\n .send();\n }\n else {\n additionalOptions[options.uuidParamName] = uuid;\n requester.initTransport(id)\n .withParams(additionalOptions)\n .send();\n }\n }\n });\n};\n","/*global qq, define */\n/*jshint strict:false,bitwise:false,nonew:false,asi:true,-W064,-W116,-W089 */\n/**\n * Mega pixel image rendering library for iOS6+\n *\n * Fixes iOS6+'s image file rendering issue for large size image (over mega-pixel),\n * which causes unexpected subsampling when drawing it in canvas.\n * By using this library, you can safely render the image with proper stretching.\n *\n * Copyright (c) 2012 Shinichi Tomita \n * Released under the MIT license\n *\n * Heavily modified by Widen for Fine Uploader\n */\n(function() {\n\n /**\n * Detect subsampling in loaded image.\n * In iOS, larger images than 2M pixels may be subsampled in rendering.\n */\n function detectSubsampling(img) {\n var iw = img.naturalWidth,\n ih = img.naturalHeight,\n canvas = document.createElement(\"canvas\"),\n ctx;\n\n if (iw * ih > 1024 * 1024) { // subsampling may happen over megapixel image\n canvas.width = canvas.height = 1;\n ctx = canvas.getContext(\"2d\");\n ctx.drawImage(img, -iw + 1, 0);\n // subsampled image becomes half smaller in rendering size.\n // check alpha channel value to confirm image is covering edge pixel or not.\n // if alpha value is 0 image is not covering, hence subsampled.\n return ctx.getImageData(0, 0, 1, 1).data[3] === 0;\n } else {\n return false;\n }\n }\n\n /**\n * Detecting vertical squash in loaded image.\n * Fixes a bug which squash image vertically while drawing into canvas for some images.\n */\n function detectVerticalSquash(img, iw, ih) {\n var canvas = document.createElement(\"canvas\"),\n sy = 0,\n ey = ih,\n py = ih,\n ctx, data, alpha, ratio;\n\n canvas.width = 1;\n canvas.height = ih;\n ctx = canvas.getContext(\"2d\");\n ctx.drawImage(img, 0, 0);\n data = ctx.getImageData(0, 0, 1, ih).data;\n\n // search image edge pixel position in case it is squashed vertically.\n while (py > sy) {\n alpha = data[(py - 1) * 4 + 3];\n if (alpha === 0) {\n ey = py;\n } else {\n sy = py;\n }\n py = (ey + sy) >> 1;\n }\n\n ratio = (py / ih);\n return (ratio === 0) ? 1 : ratio;\n }\n\n /**\n * Rendering image element (with resizing) and get its data URL\n */\n function renderImageToDataURL(img, blob, options, doSquash) {\n var canvas = document.createElement(\"canvas\"),\n mime = options.mime || \"image/jpeg\",\n promise = new qq.Promise();\n\n renderImageToCanvas(img, blob, canvas, options, doSquash)\n .then(function() {\n promise.success(\n canvas.toDataURL(mime, options.quality || 0.8)\n );\n });\n\n return promise;\n }\n\n function maybeCalculateDownsampledDimensions(spec) {\n var maxPixels = 5241000; //iOS specific value\n\n if (!qq.ios()) {\n throw new qq.Error(\"Downsampled dimensions can only be reliably calculated for iOS!\");\n }\n\n if (spec.origHeight * spec.origWidth > maxPixels) {\n return {\n newHeight: Math.round(Math.sqrt(maxPixels * (spec.origHeight / spec.origWidth))),\n newWidth: Math.round(Math.sqrt(maxPixels * (spec.origWidth / spec.origHeight)))\n };\n }\n }\n\n /**\n * Rendering image element (with resizing) into the canvas element\n */\n function renderImageToCanvas(img, blob, canvas, options, doSquash) {\n var iw = img.naturalWidth,\n ih = img.naturalHeight,\n width = options.width,\n height = options.height,\n ctx = canvas.getContext(\"2d\"),\n promise = new qq.Promise(),\n modifiedDimensions;\n\n ctx.save();\n\n if (options.resize) {\n return renderImageToCanvasWithCustomResizer({\n blob: blob,\n canvas: canvas,\n image: img,\n imageHeight: ih,\n imageWidth: iw,\n orientation: options.orientation,\n resize: options.resize,\n targetHeight: height,\n targetWidth: width\n });\n }\n\n if (!qq.supportedFeatures.unlimitedScaledImageSize) {\n modifiedDimensions = maybeCalculateDownsampledDimensions({\n origWidth: width,\n origHeight: height\n });\n\n if (modifiedDimensions) {\n qq.log(qq.format(\"Had to reduce dimensions due to device limitations from {}w / {}h to {}w / {}h\",\n width, height, modifiedDimensions.newWidth, modifiedDimensions.newHeight),\n \"warn\");\n\n width = modifiedDimensions.newWidth;\n height = modifiedDimensions.newHeight;\n }\n }\n\n transformCoordinate(canvas, width, height, options.orientation);\n\n // Fine Uploader specific: Save some CPU cycles if not using iOS\n // Assumption: This logic is only needed to overcome iOS image sampling issues\n if (qq.ios()) {\n (function() {\n if (detectSubsampling(img)) {\n iw /= 2;\n ih /= 2;\n }\n\n var d = 1024, // size of tiling canvas\n tmpCanvas = document.createElement(\"canvas\"),\n vertSquashRatio = doSquash ? detectVerticalSquash(img, iw, ih) : 1,\n dw = Math.ceil(d * width / iw),\n dh = Math.ceil(d * height / ih / vertSquashRatio),\n sy = 0,\n dy = 0,\n tmpCtx, sx, dx;\n\n tmpCanvas.width = tmpCanvas.height = d;\n tmpCtx = tmpCanvas.getContext(\"2d\");\n\n while (sy < ih) {\n sx = 0;\n dx = 0;\n while (sx < iw) {\n tmpCtx.clearRect(0, 0, d, d);\n tmpCtx.drawImage(img, -sx, -sy);\n ctx.drawImage(tmpCanvas, 0, 0, d, d, dx, dy, dw, dh);\n sx += d;\n dx += dw;\n }\n sy += d;\n dy += dh;\n }\n ctx.restore();\n tmpCanvas = tmpCtx = null;\n }());\n }\n else {\n ctx.drawImage(img, 0, 0, width, height);\n }\n\n canvas.qqImageRendered && canvas.qqImageRendered();\n promise.success();\n\n return promise;\n }\n\n function renderImageToCanvasWithCustomResizer(resizeInfo) {\n var blob = resizeInfo.blob,\n image = resizeInfo.image,\n imageHeight = resizeInfo.imageHeight,\n imageWidth = resizeInfo.imageWidth,\n orientation = resizeInfo.orientation,\n promise = new qq.Promise(),\n resize = resizeInfo.resize,\n sourceCanvas = document.createElement(\"canvas\"),\n sourceCanvasContext = sourceCanvas.getContext(\"2d\"),\n targetCanvas = resizeInfo.canvas,\n targetHeight = resizeInfo.targetHeight,\n targetWidth = resizeInfo.targetWidth;\n\n transformCoordinate(sourceCanvas, imageWidth, imageHeight, orientation);\n\n targetCanvas.height = targetHeight;\n targetCanvas.width = targetWidth;\n\n sourceCanvasContext.drawImage(image, 0, 0);\n\n resize({\n blob: blob,\n height: targetHeight,\n image: image,\n sourceCanvas: sourceCanvas,\n targetCanvas: targetCanvas,\n width: targetWidth\n })\n .then(\n function success() {\n targetCanvas.qqImageRendered && targetCanvas.qqImageRendered();\n promise.success();\n },\n promise.failure\n );\n\n return promise;\n }\n\n /**\n * Transform canvas coordination according to specified frame size and orientation\n * Orientation value is from EXIF tag\n */\n function transformCoordinate(canvas, width, height, orientation) {\n switch (orientation) {\n case 5:\n case 6:\n case 7:\n case 8:\n canvas.width = height;\n canvas.height = width;\n break;\n default:\n canvas.width = width;\n canvas.height = height;\n }\n var ctx = canvas.getContext(\"2d\");\n switch (orientation) {\n case 2:\n // horizontal flip\n ctx.translate(width, 0);\n ctx.scale(-1, 1);\n break;\n case 3:\n // 180 rotate left\n ctx.translate(width, height);\n ctx.rotate(Math.PI);\n break;\n case 4:\n // vertical flip\n ctx.translate(0, height);\n ctx.scale(1, -1);\n break;\n case 5:\n // vertical flip + 90 rotate right\n ctx.rotate(0.5 * Math.PI);\n ctx.scale(1, -1);\n break;\n case 6:\n // 90 rotate right\n ctx.rotate(0.5 * Math.PI);\n ctx.translate(0, -height);\n break;\n case 7:\n // horizontal flip + 90 rotate right\n ctx.rotate(0.5 * Math.PI);\n ctx.translate(width, -height);\n ctx.scale(-1, 1);\n break;\n case 8:\n // 90 rotate left\n ctx.rotate(-0.5 * Math.PI);\n ctx.translate(-width, 0);\n break;\n default:\n break;\n }\n }\n\n /**\n * MegaPixImage class\n */\n function MegaPixImage(srcImage, errorCallback) {\n var self = this;\n\n if (window.Blob && srcImage instanceof Blob) {\n (function() {\n var img = new Image(),\n URL = window.URL && window.URL.createObjectURL ? window.URL :\n window.webkitURL && window.webkitURL.createObjectURL ? window.webkitURL : null;\n if (!URL) { throw Error(\"No createObjectURL function found to create blob url\"); }\n img.src = URL.createObjectURL(srcImage);\n self.blob = srcImage;\n srcImage = img;\n }());\n }\n if (!srcImage.naturalWidth && !srcImage.naturalHeight) {\n srcImage.onload = function() {\n var listeners = self.imageLoadListeners;\n if (listeners) {\n self.imageLoadListeners = null;\n // IE11 doesn't reliably report actual image dimensions immediately after onload for small files,\n // so let's push this to the end of the UI thread queue.\n setTimeout(function() {\n for (var i = 0, len = listeners.length; i < len; i++) {\n listeners[i]();\n }\n }, 0);\n }\n };\n srcImage.onerror = errorCallback;\n this.imageLoadListeners = [];\n }\n this.srcImage = srcImage;\n }\n\n /**\n * Rendering megapix image into specified target element\n */\n MegaPixImage.prototype.render = function(target, options) {\n options = options || {};\n\n var self = this,\n imgWidth = this.srcImage.naturalWidth,\n imgHeight = this.srcImage.naturalHeight,\n width = options.width,\n height = options.height,\n maxWidth = options.maxWidth,\n maxHeight = options.maxHeight,\n doSquash = !this.blob || this.blob.type === \"image/jpeg\",\n tagName = target.tagName.toLowerCase(),\n opt;\n\n if (this.imageLoadListeners) {\n this.imageLoadListeners.push(function() { self.render(target, options); });\n return;\n }\n\n if (width && !height) {\n height = (imgHeight * width / imgWidth) << 0;\n } else if (height && !width) {\n width = (imgWidth * height / imgHeight) << 0;\n } else {\n width = imgWidth;\n height = imgHeight;\n }\n if (maxWidth && width > maxWidth) {\n width = maxWidth;\n height = (imgHeight * width / imgWidth) << 0;\n }\n if (maxHeight && height > maxHeight) {\n height = maxHeight;\n width = (imgWidth * height / imgHeight) << 0;\n }\n\n opt = { width: width, height: height },\n qq.each(options, function(optionsKey, optionsValue) {\n opt[optionsKey] = optionsValue;\n });\n\n if (tagName === \"img\") {\n (function() {\n var oldTargetSrc = target.src;\n renderImageToDataURL(self.srcImage, self.blob, opt, doSquash)\n .then(function(dataUri) {\n target.src = dataUri;\n oldTargetSrc === target.src && target.onload();\n });\n }());\n } else if (tagName === \"canvas\") {\n renderImageToCanvas(this.srcImage, this.blob, target, opt, doSquash);\n }\n if (typeof this.onrender === \"function\") {\n this.onrender(target);\n }\n };\n\n qq.MegaPixImage = MegaPixImage;\n})();\n","/*globals qq */\n/**\n * Draws a thumbnail of a Blob/File/URL onto an or .\n *\n * @constructor\n */\nqq.ImageGenerator = function(log) {\n \"use strict\";\n\n function isImg(el) {\n return el.tagName.toLowerCase() === \"img\";\n }\n\n function isCanvas(el) {\n return el.tagName.toLowerCase() === \"canvas\";\n }\n\n function isImgCorsSupported() {\n return new Image().crossOrigin !== undefined;\n }\n\n function isCanvasSupported() {\n var canvas = document.createElement(\"canvas\");\n\n return canvas.getContext && canvas.getContext(\"2d\");\n }\n\n // This is only meant to determine the MIME type of a renderable image file.\n // It is used to ensure images drawn from a URL that have transparent backgrounds\n // are rendered correctly, among other things.\n function determineMimeOfFileName(nameWithPath) {\n /*jshint -W015 */\n var pathSegments = nameWithPath.split(\"/\"),\n name = pathSegments[pathSegments.length - 1].split(\"?\")[0],\n extension = qq.getExtension(name);\n\n extension = extension && extension.toLowerCase();\n\n switch (extension) {\n case \"jpeg\":\n case \"jpg\":\n return \"image/jpeg\";\n case \"png\":\n return \"image/png\";\n case \"bmp\":\n return \"image/bmp\";\n case \"gif\":\n return \"image/gif\";\n case \"tiff\":\n case \"tif\":\n return \"image/tiff\";\n }\n }\n\n // This will likely not work correctly in IE8 and older.\n // It's only used as part of a formula to determine\n // if a canvas can be used to scale a server-hosted thumbnail.\n // If canvas isn't supported by the UA (IE8 and older)\n // this method should not even be called.\n function isCrossOrigin(url) {\n var targetAnchor = document.createElement(\"a\"),\n targetProtocol, targetHostname, targetPort;\n\n targetAnchor.href = url;\n\n targetProtocol = targetAnchor.protocol;\n targetPort = targetAnchor.port;\n targetHostname = targetAnchor.hostname;\n\n if (targetProtocol.toLowerCase() !== window.location.protocol.toLowerCase()) {\n return true;\n }\n\n if (targetHostname.toLowerCase() !== window.location.hostname.toLowerCase()) {\n return true;\n }\n\n // IE doesn't take ports into consideration when determining if two endpoints are same origin.\n if (targetPort !== window.location.port && !qq.ie()) {\n return true;\n }\n\n return false;\n }\n\n function registerImgLoadListeners(img, promise) {\n img.onload = function() {\n img.onload = null;\n img.onerror = null;\n promise.success(img);\n };\n\n img.onerror = function() {\n img.onload = null;\n img.onerror = null;\n log(\"Problem drawing thumbnail!\", \"error\");\n promise.failure(img, \"Problem drawing thumbnail!\");\n };\n }\n\n function registerCanvasDrawImageListener(canvas, promise) {\n // The image is drawn on the canvas by a third-party library,\n // and we want to know when this is completed. Since the library\n // may invoke drawImage many times in a loop, we need to be called\n // back when the image is fully rendered. So, we are expecting the\n // code that draws this image to follow a convention that involves a\n // function attached to the canvas instance be invoked when it is done.\n canvas.qqImageRendered = function() {\n promise.success(canvas);\n };\n }\n\n // Fulfills a `qq.Promise` when an image has been drawn onto the target,\n // whether that is a or an . The attempt is considered a\n // failure if the target is not an or a , or if the drawing\n // attempt was not successful.\n function registerThumbnailRenderedListener(imgOrCanvas, promise) {\n var registered = isImg(imgOrCanvas) || isCanvas(imgOrCanvas);\n\n if (isImg(imgOrCanvas)) {\n registerImgLoadListeners(imgOrCanvas, promise);\n }\n else if (isCanvas(imgOrCanvas)) {\n registerCanvasDrawImageListener(imgOrCanvas, promise);\n }\n else {\n promise.failure(imgOrCanvas);\n log(qq.format(\"Element container of type {} is not supported!\", imgOrCanvas.tagName), \"error\");\n }\n\n return registered;\n }\n\n // Draw a preview iff the current UA can natively display it.\n // Also rotate the image if necessary.\n function draw(fileOrBlob, container, options) {\n var drawPreview = new qq.Promise(),\n identifier = new qq.Identify(fileOrBlob, log),\n maxSize = options.maxSize,\n // jshint eqnull:true\n orient = options.orient == null ? true : options.orient,\n megapixErrorHandler = function() {\n container.onerror = null;\n container.onload = null;\n log(\"Could not render preview, file may be too large!\", \"error\");\n drawPreview.failure(container, \"Browser cannot render image!\");\n };\n\n identifier.isPreviewable().then(\n function(mime) {\n // If options explicitly specify that Orientation is not desired,\n // replace the orient task with a dummy promise that \"succeeds\" immediately.\n var dummyExif = {\n parse: function() {\n return new qq.Promise().success();\n }\n },\n exif = orient ? new qq.Exif(fileOrBlob, log) : dummyExif,\n mpImg = new qq.MegaPixImage(fileOrBlob, megapixErrorHandler);\n\n if (registerThumbnailRenderedListener(container, drawPreview)) {\n exif.parse().then(\n function(exif) {\n var orientation = exif && exif.Orientation;\n\n mpImg.render(container, {\n maxWidth: maxSize,\n maxHeight: maxSize,\n orientation: orientation,\n mime: mime,\n resize: options.customResizeFunction\n });\n },\n\n function(failureMsg) {\n log(qq.format(\"EXIF data could not be parsed ({}). Assuming orientation = 1.\", failureMsg));\n\n mpImg.render(container, {\n maxWidth: maxSize,\n maxHeight: maxSize,\n mime: mime,\n resize: options.customResizeFunction\n });\n }\n );\n }\n },\n\n function() {\n log(\"Not previewable\");\n drawPreview.failure(container, \"Not previewable\");\n }\n );\n\n return drawPreview;\n }\n\n function drawOnCanvasOrImgFromUrl(url, canvasOrImg, draw, maxSize, customResizeFunction) {\n var tempImg = new Image(),\n tempImgRender = new qq.Promise();\n\n registerThumbnailRenderedListener(tempImg, tempImgRender);\n\n if (isCrossOrigin(url)) {\n tempImg.crossOrigin = \"anonymous\";\n }\n\n tempImg.src = url;\n\n tempImgRender.then(\n function rendered() {\n registerThumbnailRenderedListener(canvasOrImg, draw);\n\n var mpImg = new qq.MegaPixImage(tempImg);\n mpImg.render(canvasOrImg, {\n maxWidth: maxSize,\n maxHeight: maxSize,\n mime: determineMimeOfFileName(url),\n resize: customResizeFunction\n });\n },\n\n draw.failure\n );\n }\n\n function drawOnImgFromUrlWithCssScaling(url, img, draw, maxSize) {\n registerThumbnailRenderedListener(img, draw);\n // NOTE: The fact that maxWidth/height is set on the thumbnail for scaled images\n // that must drop back to CSS is known and exploited by the templating module.\n // In this module, we pre-render \"waiting\" thumbs for all files immediately after they\n // are submitted, and we must be sure to pass any style associated with the \"waiting\" preview.\n qq(img).css({\n maxWidth: maxSize + \"px\",\n maxHeight: maxSize + \"px\"\n });\n\n img.src = url;\n }\n\n // Draw a (server-hosted) thumbnail given a URL.\n // This will optionally scale the thumbnail as well.\n // It attempts to use to scale, but will fall back\n // to max-width and max-height style properties if the UA\n // doesn't support canvas or if the images is cross-domain and\n // the UA doesn't support the crossorigin attribute on img tags,\n // which is required to scale a cross-origin image using &\n // then export it back to an .\n function drawFromUrl(url, container, options) {\n var draw = new qq.Promise(),\n scale = options.scale,\n maxSize = scale ? options.maxSize : null;\n\n // container is an img, scaling needed\n if (scale && isImg(container)) {\n // Iff canvas is available in this UA, try to use it for scaling.\n // Otherwise, fall back to CSS scaling\n if (isCanvasSupported()) {\n // Attempt to use for image scaling,\n // but we must fall back to scaling via CSS/styles\n // if this is a cross-origin image and the UA doesn't support CORS.\n if (isCrossOrigin(url) && !isImgCorsSupported()) {\n drawOnImgFromUrlWithCssScaling(url, container, draw, maxSize);\n }\n else {\n drawOnCanvasOrImgFromUrl(url, container, draw, maxSize);\n }\n }\n else {\n drawOnImgFromUrlWithCssScaling(url, container, draw, maxSize);\n }\n }\n // container is a canvas, scaling optional\n else if (isCanvas(container)) {\n drawOnCanvasOrImgFromUrl(url, container, draw, maxSize);\n }\n // container is an img & no scaling: just set the src attr to the passed url\n else if (registerThumbnailRenderedListener(container, draw)) {\n container.src = url;\n }\n\n return draw;\n }\n\n qq.extend(this, {\n /**\n * Generate a thumbnail. Depending on the arguments, this may either result in\n * a client-side rendering of an image (if a `Blob` is supplied) or a server-generated\n * image that may optionally be scaled client-side using or CSS/styles (as a fallback).\n *\n * @param fileBlobOrUrl a `File`, `Blob`, or a URL pointing to the image\n * @param container or to contain the preview\n * @param options possible properties include `maxSize` (int), `orient` (bool - default true), resize` (bool - default true), and `customResizeFunction`.\n * @returns qq.Promise fulfilled when the preview has been drawn, or the attempt has failed\n */\n generate: function(fileBlobOrUrl, container, options) {\n if (qq.isString(fileBlobOrUrl)) {\n log(\"Attempting to update thumbnail based on server response.\");\n return drawFromUrl(fileBlobOrUrl, container, options || {});\n }\n else {\n log(\"Attempting to draw client-side image preview.\");\n return draw(fileBlobOrUrl, container, options || {});\n }\n }\n });\n\n /**/\n this._testing = {};\n this._testing.isImg = isImg;\n this._testing.isCanvas = isCanvas;\n this._testing.isCrossOrigin = isCrossOrigin;\n this._testing.determineMimeOfFileName = determineMimeOfFileName;\n /* */\n};\n","/*globals qq */\n/**\n * EXIF image data parser. Currently only parses the Orientation tag value,\n * but this may be expanded to other tags in the future.\n *\n * @param fileOrBlob Attempt to parse EXIF data in this `Blob`\n * @constructor\n */\nqq.Exif = function(fileOrBlob, log) {\n \"use strict\";\n\n // Orientation is the only tag parsed here at this time.\n var TAG_IDS = [274],\n TAG_INFO = {\n 274: {\n name: \"Orientation\",\n bytes: 2\n }\n };\n\n // Convert a little endian (hex string) to big endian (decimal).\n function parseLittleEndian(hex) {\n var result = 0,\n pow = 0;\n\n while (hex.length > 0) {\n result += parseInt(hex.substring(0, 2), 16) * Math.pow(2, pow);\n hex = hex.substring(2, hex.length);\n pow += 8;\n }\n\n return result;\n }\n\n // Find the byte offset, of Application Segment 1 (EXIF).\n // External callers need not supply any arguments.\n function seekToApp1(offset, promise) {\n var theOffset = offset,\n thePromise = promise;\n if (theOffset === undefined) {\n theOffset = 2;\n thePromise = new qq.Promise();\n }\n\n qq.readBlobToHex(fileOrBlob, theOffset, 4).then(function(hex) {\n var match = /^ffe([0-9])/.exec(hex),\n segmentLength;\n\n if (match) {\n if (match[1] !== \"1\") {\n segmentLength = parseInt(hex.slice(4, 8), 16);\n seekToApp1(theOffset + segmentLength + 2, thePromise);\n }\n else {\n thePromise.success(theOffset);\n }\n }\n else {\n thePromise.failure(\"No EXIF header to be found!\");\n }\n });\n\n return thePromise;\n }\n\n // Find the byte offset of Application Segment 1 (EXIF) for valid JPEGs only.\n function getApp1Offset() {\n var promise = new qq.Promise();\n\n qq.readBlobToHex(fileOrBlob, 0, 6).then(function(hex) {\n if (hex.indexOf(\"ffd8\") !== 0) {\n promise.failure(\"Not a valid JPEG!\");\n }\n else {\n seekToApp1().then(function(offset) {\n promise.success(offset);\n },\n function(error) {\n promise.failure(error);\n });\n }\n });\n\n return promise;\n }\n\n // Determine the byte ordering of the EXIF header.\n function isLittleEndian(app1Start) {\n var promise = new qq.Promise();\n\n qq.readBlobToHex(fileOrBlob, app1Start + 10, 2).then(function(hex) {\n promise.success(hex === \"4949\");\n });\n\n return promise;\n }\n\n // Determine the number of directory entries in the EXIF header.\n function getDirEntryCount(app1Start, littleEndian) {\n var promise = new qq.Promise();\n\n qq.readBlobToHex(fileOrBlob, app1Start + 18, 2).then(function(hex) {\n if (littleEndian) {\n return promise.success(parseLittleEndian(hex));\n }\n else {\n promise.success(parseInt(hex, 16));\n }\n });\n\n return promise;\n }\n\n // Get the IFD portion of the EXIF header as a hex string.\n function getIfd(app1Start, dirEntries) {\n var offset = app1Start + 20,\n bytes = dirEntries * 12;\n\n return qq.readBlobToHex(fileOrBlob, offset, bytes);\n }\n\n // Obtain an array of all directory entries (as hex strings) in the EXIF header.\n function getDirEntries(ifdHex) {\n var entries = [],\n offset = 0;\n\n while (offset + 24 <= ifdHex.length) {\n entries.push(ifdHex.slice(offset, offset + 24));\n offset += 24;\n }\n\n return entries;\n }\n\n // Obtain values for all relevant tags and return them.\n function getTagValues(littleEndian, dirEntries) {\n var TAG_VAL_OFFSET = 16,\n tagsToFind = qq.extend([], TAG_IDS),\n vals = {};\n\n qq.each(dirEntries, function(idx, entry) {\n var idHex = entry.slice(0, 4),\n id = littleEndian ? parseLittleEndian(idHex) : parseInt(idHex, 16),\n tagsToFindIdx = tagsToFind.indexOf(id),\n tagValHex, tagName, tagValLength;\n\n if (tagsToFindIdx >= 0) {\n tagName = TAG_INFO[id].name;\n tagValLength = TAG_INFO[id].bytes;\n tagValHex = entry.slice(TAG_VAL_OFFSET, TAG_VAL_OFFSET + (tagValLength * 2));\n vals[tagName] = littleEndian ? parseLittleEndian(tagValHex) : parseInt(tagValHex, 16);\n\n tagsToFind.splice(tagsToFindIdx, 1);\n }\n\n if (tagsToFind.length === 0) {\n return false;\n }\n });\n\n return vals;\n }\n\n qq.extend(this, {\n /**\n * Attempt to parse the EXIF header for the `Blob` associated with this instance.\n *\n * @returns {qq.Promise} To be fulfilled when the parsing is complete.\n * If successful, the parsed EXIF header as an object will be included.\n */\n parse: function() {\n var parser = new qq.Promise(),\n onParseFailure = function(message) {\n log(qq.format(\"EXIF header parse failed: '{}' \", message));\n parser.failure(message);\n };\n\n getApp1Offset().then(function(app1Offset) {\n log(qq.format(\"Moving forward with EXIF header parsing for '{}'\", fileOrBlob.name === undefined ? \"blob\" : fileOrBlob.name));\n\n isLittleEndian(app1Offset).then(function(littleEndian) {\n\n log(qq.format(\"EXIF Byte order is {} endian\", littleEndian ? \"little\" : \"big\"));\n\n getDirEntryCount(app1Offset, littleEndian).then(function(dirEntryCount) {\n\n log(qq.format(\"Found {} APP1 directory entries\", dirEntryCount));\n\n getIfd(app1Offset, dirEntryCount).then(function(ifdHex) {\n var dirEntries = getDirEntries(ifdHex),\n tagValues = getTagValues(littleEndian, dirEntries);\n\n log(\"Successfully parsed some EXIF tags\");\n\n parser.success(tagValues);\n }, onParseFailure);\n }, onParseFailure);\n }, onParseFailure);\n }, onParseFailure);\n\n return parser;\n }\n });\n\n /**/\n this._testing = {};\n this._testing.parseLittleEndian = parseLittleEndian;\n /* */\n};\n","/*globals qq */\nqq.Identify = function(fileOrBlob, log) {\n \"use strict\";\n\n function isIdentifiable(magicBytes, questionableBytes) {\n var identifiable = false,\n magicBytesEntries = [].concat(magicBytes);\n\n qq.each(magicBytesEntries, function(idx, magicBytesArrayEntry) {\n if (questionableBytes.indexOf(magicBytesArrayEntry) === 0) {\n identifiable = true;\n return false;\n }\n });\n\n return identifiable;\n }\n\n qq.extend(this, {\n /**\n * Determines if a Blob can be displayed natively in the current browser. This is done by reading magic\n * bytes in the beginning of the file, so this is an asynchronous operation. Before we attempt to read the\n * file, we will examine the blob's type attribute to save CPU cycles.\n *\n * @returns {qq.Promise} Promise that is fulfilled when identification is complete.\n * If successful, the MIME string is passed to the success handler.\n */\n isPreviewable: function() {\n var self = this,\n identifier = new qq.Promise(),\n previewable = false,\n name = fileOrBlob.name === undefined ? \"blob\" : fileOrBlob.name;\n\n log(qq.format(\"Attempting to determine if {} can be rendered in this browser\", name));\n\n log(\"First pass: check type attribute of blob object.\");\n\n if (this.isPreviewableSync()) {\n log(\"Second pass: check for magic bytes in file header.\");\n\n qq.readBlobToHex(fileOrBlob, 0, 4).then(function(hex) {\n qq.each(self.PREVIEWABLE_MIME_TYPES, function(mime, bytes) {\n if (isIdentifiable(bytes, hex)) {\n // Safari is the only supported browser that can deal with TIFFs natively,\n // so, if this is a TIFF and the UA isn't Safari, declare this file \"non-previewable\".\n if (mime !== \"image/tiff\" || qq.supportedFeatures.tiffPreviews) {\n previewable = true;\n identifier.success(mime);\n }\n\n return false;\n }\n });\n\n log(qq.format(\"'{}' is {} able to be rendered in this browser\", name, previewable ? \"\" : \"NOT\"));\n\n if (!previewable) {\n identifier.failure();\n }\n },\n function() {\n log(\"Error reading file w/ name '\" + name + \"'. Not able to be rendered in this browser.\");\n identifier.failure();\n });\n }\n else {\n identifier.failure();\n }\n\n return identifier;\n },\n\n /**\n * Determines if a Blob can be displayed natively in the current browser. This is done by checking the\n * blob's type attribute. This is a synchronous operation, useful for situations where an asynchronous operation\n * would be challenging to support. Note that the blob's type property is not as accurate as reading the\n * file's magic bytes.\n *\n * @returns {Boolean} true if the blob can be rendered in the current browser\n */\n isPreviewableSync: function() {\n var fileMime = fileOrBlob.type,\n // Assumption: This will only ever be executed in browsers that support `Object.keys`.\n isRecognizedImage = qq.indexOf(Object.keys(this.PREVIEWABLE_MIME_TYPES), fileMime) >= 0,\n previewable = false,\n name = fileOrBlob.name === undefined ? \"blob\" : fileOrBlob.name;\n\n if (isRecognizedImage) {\n if (fileMime === \"image/tiff\") {\n previewable = qq.supportedFeatures.tiffPreviews;\n }\n else {\n previewable = true;\n }\n }\n\n !previewable && log(name + \" is not previewable in this browser per the blob's type attr\");\n\n return previewable;\n }\n });\n};\n\nqq.Identify.prototype.PREVIEWABLE_MIME_TYPES = {\n \"image/jpeg\": \"ffd8ff\",\n \"image/gif\": \"474946\",\n \"image/png\": \"89504e\",\n \"image/bmp\": \"424d\",\n \"image/tiff\": [\"49492a00\", \"4d4d002a\"]\n};\n","/*globals qq*/\n/**\n * Attempts to validate an image, wherever possible.\n *\n * @param blob File or Blob representing a user-selecting image.\n * @param log Uses this to post log messages to the console.\n * @constructor\n */\nqq.ImageValidation = function(blob, log) {\n \"use strict\";\n\n /**\n * @param limits Object with possible image-related limits to enforce.\n * @returns {boolean} true if at least one of the limits has a non-zero value\n */\n function hasNonZeroLimits(limits) {\n var atLeastOne = false;\n\n qq.each(limits, function(limit, value) {\n if (value > 0) {\n atLeastOne = true;\n return false;\n }\n });\n\n return atLeastOne;\n }\n\n /**\n * @returns {qq.Promise} The promise is a failure if we can't obtain the width & height.\n * Otherwise, `success` is called on the returned promise with an object containing\n * `width` and `height` properties.\n */\n function getWidthHeight() {\n var sizeDetermination = new qq.Promise();\n\n new qq.Identify(blob, log).isPreviewable().then(function() {\n var image = new Image(),\n url = window.URL && window.URL.createObjectURL ? window.URL :\n window.webkitURL && window.webkitURL.createObjectURL ? window.webkitURL :\n null;\n\n if (url) {\n image.onerror = function() {\n log(\"Cannot determine dimensions for image. May be too large.\", \"error\");\n sizeDetermination.failure();\n };\n\n image.onload = function() {\n sizeDetermination.success({\n width: this.width,\n height: this.height\n });\n };\n\n image.src = url.createObjectURL(blob);\n }\n else {\n log(\"No createObjectURL function available to generate image URL!\", \"error\");\n sizeDetermination.failure();\n }\n }, sizeDetermination.failure);\n\n return sizeDetermination;\n }\n\n /**\n *\n * @param limits Object with possible image-related limits to enforce.\n * @param dimensions Object containing `width` & `height` properties for the image to test.\n * @returns {String || undefined} The name of the failing limit. Undefined if no failing limits.\n */\n function getFailingLimit(limits, dimensions) {\n var failingLimit;\n\n qq.each(limits, function(limitName, limitValue) {\n if (limitValue > 0) {\n var limitMatcher = /(max|min)(Width|Height)/.exec(limitName),\n dimensionPropName = limitMatcher[2].charAt(0).toLowerCase() + limitMatcher[2].slice(1),\n actualValue = dimensions[dimensionPropName];\n\n /*jshint -W015*/\n switch (limitMatcher[1]) {\n case \"min\":\n if (actualValue < limitValue) {\n failingLimit = limitName;\n return false;\n }\n break;\n case \"max\":\n if (actualValue > limitValue) {\n failingLimit = limitName;\n return false;\n }\n break;\n }\n }\n });\n\n return failingLimit;\n }\n\n /**\n * Validate the associated blob.\n *\n * @param limits\n * @returns {qq.Promise} `success` is called on the promise is the image is valid or\n * if the blob is not an image, or if the image is not verifiable.\n * Otherwise, `failure` with the name of the failing limit.\n */\n this.validate = function(limits) {\n var validationEffort = new qq.Promise();\n\n log(\"Attempting to validate image.\");\n\n if (hasNonZeroLimits(limits)) {\n getWidthHeight().then(function(dimensions) {\n var failingLimit = getFailingLimit(limits, dimensions);\n\n if (failingLimit) {\n validationEffort.failure(failingLimit);\n }\n else {\n validationEffort.success();\n }\n }, validationEffort.success);\n }\n else {\n validationEffort.success();\n }\n\n return validationEffort;\n };\n};\n","/* globals qq */\n/**\n * Module used to control populating the initial list of files.\n *\n * @constructor\n */\nqq.Session = function(spec) {\n \"use strict\";\n\n var options = {\n endpoint: null,\n params: {},\n customHeaders: {},\n cors: {},\n addFileRecord: function(sessionData) {},\n log: function(message, level) {}\n };\n\n qq.extend(options, spec, true);\n\n function isJsonResponseValid(response) {\n if (qq.isArray(response)) {\n return true;\n }\n\n options.log(\"Session response is not an array.\", \"error\");\n }\n\n function handleFileItems(fileItems, success, xhrOrXdr, promise) {\n var someItemsIgnored = false;\n\n success = success && isJsonResponseValid(fileItems);\n\n if (success) {\n qq.each(fileItems, function(idx, fileItem) {\n /* jshint eqnull:true */\n if (fileItem.uuid == null) {\n someItemsIgnored = true;\n options.log(qq.format(\"Session response item {} did not include a valid UUID - ignoring.\", idx), \"error\");\n }\n else if (fileItem.name == null) {\n someItemsIgnored = true;\n options.log(qq.format(\"Session response item {} did not include a valid name - ignoring.\", idx), \"error\");\n }\n else {\n try {\n options.addFileRecord(fileItem);\n return true;\n }\n catch (err) {\n someItemsIgnored = true;\n options.log(err.message, \"error\");\n }\n }\n\n return false;\n });\n }\n\n promise[success && !someItemsIgnored ? \"success\" : \"failure\"](fileItems, xhrOrXdr);\n }\n\n // Initiate a call to the server that will be used to populate the initial file list.\n // Returns a `qq.Promise`.\n this.refresh = function() {\n /*jshint indent:false */\n var refreshEffort = new qq.Promise(),\n refreshCompleteCallback = function(response, success, xhrOrXdr) {\n handleFileItems(response, success, xhrOrXdr, refreshEffort);\n },\n requesterOptions = qq.extend({}, options),\n requester = new qq.SessionAjaxRequester(\n qq.extend(requesterOptions, {onComplete: refreshCompleteCallback})\n );\n\n requester.queryServer();\n\n return refreshEffort;\n };\n};\n","/*globals qq, XMLHttpRequest*/\n/**\n * Thin module used to send GET requests to the server, expecting information about session\n * data used to initialize an uploader instance.\n *\n * @param spec Various options used to influence the associated request.\n * @constructor\n */\nqq.SessionAjaxRequester = function(spec) {\n \"use strict\";\n\n var requester,\n options = {\n endpoint: null,\n customHeaders: {},\n params: {},\n cors: {\n expected: false,\n sendCredentials: false\n },\n onComplete: function(response, success, xhrOrXdr) {},\n log: function(str, level) {}\n };\n\n qq.extend(options, spec);\n\n function onComplete(id, xhrOrXdr, isError) {\n var response = null;\n\n /* jshint eqnull:true */\n if (xhrOrXdr.responseText != null) {\n try {\n response = qq.parseJson(xhrOrXdr.responseText);\n }\n catch (err) {\n options.log(\"Problem parsing session response: \" + err.message, \"error\");\n isError = true;\n }\n }\n\n options.onComplete(response, !isError, xhrOrXdr);\n }\n\n requester = qq.extend(this, new qq.AjaxRequester({\n acceptHeader: \"application/json\",\n validMethods: [\"GET\"],\n method: \"GET\",\n endpointStore: {\n get: function() {\n return options.endpoint;\n }\n },\n customHeaders: options.customHeaders,\n log: options.log,\n onComplete: onComplete,\n cors: options.cors\n }));\n\n qq.extend(this, {\n queryServer: function() {\n var params = qq.extend({}, options.params);\n\n options.log(\"Session query request.\");\n\n requester.initTransport(\"sessionRefresh\")\n .withParams(params)\n .withCacheBuster()\n .send();\n }\n });\n};\n","/* globals qq, ExifRestorer */\n/**\n * Controls generation of scaled images based on a reference image encapsulated in a `File` or `Blob`.\n * Scaled images are generated and converted to blobs on-demand.\n * Multiple scaled images per reference image with varying sizes and other properties are supported.\n *\n * @param spec Information about the scaled images to generate.\n * @param log Logger instance\n * @constructor\n */\nqq.Scaler = function(spec, log) {\n \"use strict\";\n\n var self = this,\n customResizeFunction = spec.customResizer,\n includeOriginal = spec.sendOriginal,\n orient = spec.orient,\n defaultType = spec.defaultType,\n defaultQuality = spec.defaultQuality / 100,\n failedToScaleText = spec.failureText,\n includeExif = spec.includeExif,\n sizes = this._getSortedSizes(spec.sizes);\n\n // Revealed API for instances of this module\n qq.extend(this, {\n // If no targeted sizes have been declared or if this browser doesn't support\n // client-side image preview generation, there is no scaling to do.\n enabled: qq.supportedFeatures.scaling && sizes.length > 0,\n\n getFileRecords: function(originalFileUuid, originalFileName, originalBlobOrBlobData) {\n var self = this,\n records = [],\n originalBlob = originalBlobOrBlobData.blob ? originalBlobOrBlobData.blob : originalBlobOrBlobData,\n identifier = new qq.Identify(originalBlob, log);\n\n // If the reference file cannot be rendered natively, we can't create scaled versions.\n if (identifier.isPreviewableSync()) {\n // Create records for each scaled version & add them to the records array, smallest first.\n qq.each(sizes, function(idx, sizeRecord) {\n var outputType = self._determineOutputType({\n defaultType: defaultType,\n requestedType: sizeRecord.type,\n refType: originalBlob.type\n });\n\n records.push({\n uuid: qq.getUniqueId(),\n name: self._getName(originalFileName, {\n name: sizeRecord.name,\n type: outputType,\n refType: originalBlob.type\n }),\n blob: new qq.BlobProxy(originalBlob,\n qq.bind(self._generateScaledImage, self, {\n customResizeFunction: customResizeFunction,\n maxSize: sizeRecord.maxSize,\n orient: orient,\n type: outputType,\n quality: defaultQuality,\n failedText: failedToScaleText,\n includeExif: includeExif,\n log: log\n }))\n });\n });\n\n records.push({\n uuid: originalFileUuid,\n name: originalFileName,\n size: originalBlob.size,\n blob: includeOriginal ? originalBlob : null\n });\n }\n else {\n records.push({\n uuid: originalFileUuid,\n name: originalFileName,\n size: originalBlob.size,\n blob: originalBlob\n });\n }\n\n return records;\n },\n\n handleNewFile: function(file, name, uuid, size, fileList, batchId, uuidParamName, api) {\n var self = this,\n buttonId = file.qqButtonId || (file.blob && file.blob.qqButtonId),\n scaledIds = [],\n originalId = null,\n addFileToHandler = api.addFileToHandler,\n uploadData = api.uploadData,\n paramsStore = api.paramsStore,\n proxyGroupId = qq.getUniqueId();\n\n qq.each(self.getFileRecords(uuid, name, file), function(idx, record) {\n var blobSize = record.size,\n id;\n\n if (record.blob instanceof qq.BlobProxy) {\n blobSize = -1;\n }\n\n id = uploadData.addFile({\n uuid: record.uuid,\n name: record.name,\n size: blobSize,\n batchId: batchId,\n proxyGroupId: proxyGroupId\n });\n\n if (record.blob instanceof qq.BlobProxy) {\n scaledIds.push(id);\n }\n else {\n originalId = id;\n }\n\n if (record.blob) {\n addFileToHandler(id, record.blob);\n fileList.push({id: id, file: record.blob});\n }\n else {\n uploadData.setStatus(id, qq.status.REJECTED);\n }\n });\n\n // If we are potentially uploading an original file and some scaled versions,\n // ensure the scaled versions include reference's to the parent's UUID and size\n // in their associated upload requests.\n if (originalId !== null) {\n qq.each(scaledIds, function(idx, scaledId) {\n var params = {\n qqparentuuid: uploadData.retrieve({id: originalId}).uuid,\n qqparentsize: uploadData.retrieve({id: originalId}).size\n };\n\n // Make sure the UUID for each scaled image is sent with the upload request,\n // to be consistent (since we may need to ensure it is sent for the original file as well).\n params[uuidParamName] = uploadData.retrieve({id: scaledId}).uuid;\n\n uploadData.setParentId(scaledId, originalId);\n paramsStore.addReadOnly(scaledId, params);\n });\n\n // If any scaled images are tied to this parent image, be SURE we send its UUID as an upload request\n // parameter as well.\n if (scaledIds.length) {\n (function() {\n var param = {};\n param[uuidParamName] = uploadData.retrieve({id: originalId}).uuid;\n paramsStore.addReadOnly(originalId, param);\n }());\n }\n }\n }\n });\n};\n\nqq.extend(qq.Scaler.prototype, {\n scaleImage: function(id, specs, api) {\n \"use strict\";\n\n if (!qq.supportedFeatures.scaling) {\n throw new qq.Error(\"Scaling is not supported in this browser!\");\n }\n\n var scalingEffort = new qq.Promise(),\n log = api.log,\n file = api.getFile(id),\n uploadData = api.uploadData.retrieve({id: id}),\n name = uploadData && uploadData.name,\n uuid = uploadData && uploadData.uuid,\n scalingOptions = {\n customResizer: specs.customResizer,\n sendOriginal: false,\n orient: specs.orient,\n defaultType: specs.type || null,\n defaultQuality: specs.quality,\n failedToScaleText: \"Unable to scale\",\n sizes: [{name: \"\", maxSize: specs.maxSize}]\n },\n scaler = new qq.Scaler(scalingOptions, log);\n\n if (!qq.Scaler || !qq.supportedFeatures.imagePreviews || !file) {\n scalingEffort.failure();\n\n log(\"Could not generate requested scaled image for \" + id + \". \" +\n \"Scaling is either not possible in this browser, or the file could not be located.\", \"error\");\n }\n else {\n (qq.bind(function() {\n // Assumption: There will never be more than one record\n var record = scaler.getFileRecords(uuid, name, file)[0];\n\n if (record && record.blob instanceof qq.BlobProxy) {\n record.blob.create().then(scalingEffort.success, scalingEffort.failure);\n }\n else {\n log(id + \" is not a scalable image!\", \"error\");\n scalingEffort.failure();\n }\n }, this)());\n }\n\n return scalingEffort;\n },\n\n // NOTE: We cannot reliably determine at this time if the UA supports a specific MIME type for the target format.\n // image/jpeg and image/png are the only safe choices at this time.\n _determineOutputType: function(spec) {\n \"use strict\";\n\n var requestedType = spec.requestedType,\n defaultType = spec.defaultType,\n referenceType = spec.refType;\n\n // If a default type and requested type have not been specified, this should be a\n // JPEG if the original type is a JPEG, otherwise, a PNG.\n if (!defaultType && !requestedType) {\n if (referenceType !== \"image/jpeg\") {\n return \"image/png\";\n }\n return referenceType;\n }\n\n // A specified default type is used when a requested type is not specified.\n if (!requestedType) {\n return defaultType;\n }\n\n // If requested type is specified, use it, as long as this recognized type is supported by the current UA\n if (qq.indexOf(Object.keys(qq.Identify.prototype.PREVIEWABLE_MIME_TYPES), requestedType) >= 0) {\n if (requestedType === \"image/tiff\") {\n return qq.supportedFeatures.tiffPreviews ? requestedType : defaultType;\n }\n\n return requestedType;\n }\n\n return defaultType;\n },\n\n // Get a file name for a generated scaled file record, based on the provided scaled image description\n _getName: function(originalName, scaledVersionProperties) {\n \"use strict\";\n\n var startOfExt = originalName.lastIndexOf(\".\"),\n versionType = scaledVersionProperties.type || \"image/png\",\n referenceType = scaledVersionProperties.refType,\n scaledName = \"\",\n scaledExt = qq.getExtension(originalName),\n nameAppendage = \"\";\n\n if (scaledVersionProperties.name && scaledVersionProperties.name.trim().length) {\n nameAppendage = \" (\" + scaledVersionProperties.name + \")\";\n }\n\n if (startOfExt >= 0) {\n scaledName = originalName.substr(0, startOfExt);\n\n if (referenceType !== versionType) {\n scaledExt = versionType.split(\"/\")[1];\n }\n\n scaledName += nameAppendage + \".\" + scaledExt;\n }\n else {\n scaledName = originalName + nameAppendage;\n }\n\n return scaledName;\n },\n\n // We want the smallest scaled file to be uploaded first\n _getSortedSizes: function(sizes) {\n \"use strict\";\n\n sizes = qq.extend([], sizes);\n\n return sizes.sort(function(a, b) {\n if (a.maxSize > b.maxSize) {\n return 1;\n }\n if (a.maxSize < b.maxSize) {\n return -1;\n }\n return 0;\n });\n },\n\n _generateScaledImage: function(spec, sourceFile) {\n \"use strict\";\n\n var self = this,\n customResizeFunction = spec.customResizeFunction,\n log = spec.log,\n maxSize = spec.maxSize,\n orient = spec.orient,\n type = spec.type,\n quality = spec.quality,\n failedText = spec.failedText,\n includeExif = spec.includeExif && sourceFile.type === \"image/jpeg\" && type === \"image/jpeg\",\n scalingEffort = new qq.Promise(),\n imageGenerator = new qq.ImageGenerator(log),\n canvas = document.createElement(\"canvas\");\n\n log(\"Attempting to generate scaled version for \" + sourceFile.name);\n\n imageGenerator.generate(sourceFile, canvas, {maxSize: maxSize, orient: orient, customResizeFunction: customResizeFunction}).then(function() {\n var scaledImageDataUri = canvas.toDataURL(type, quality),\n signalSuccess = function() {\n log(\"Success generating scaled version for \" + sourceFile.name);\n var blob = qq.dataUriToBlob(scaledImageDataUri);\n scalingEffort.success(blob);\n };\n\n if (includeExif) {\n self._insertExifHeader(sourceFile, scaledImageDataUri, log).then(function(scaledImageDataUriWithExif) {\n scaledImageDataUri = scaledImageDataUriWithExif;\n signalSuccess();\n },\n function() {\n log(\"Problem inserting EXIF header into scaled image. Using scaled image w/out EXIF data.\", \"error\");\n signalSuccess();\n });\n }\n else {\n signalSuccess();\n }\n }, function() {\n log(\"Failed attempt to generate scaled version for \" + sourceFile.name, \"error\");\n scalingEffort.failure(failedText);\n });\n\n return scalingEffort;\n },\n\n // Attempt to insert the original image's EXIF header into a scaled version.\n _insertExifHeader: function(originalImage, scaledImageDataUri, log) {\n \"use strict\";\n\n var reader = new FileReader(),\n insertionEffort = new qq.Promise(),\n originalImageDataUri = \"\";\n\n reader.onload = function() {\n originalImageDataUri = reader.result;\n insertionEffort.success(qq.ExifRestorer.restore(originalImageDataUri, scaledImageDataUri));\n };\n\n reader.onerror = function() {\n log(\"Problem reading \" + originalImage.name + \" during attempt to transfer EXIF data to scaled version.\", \"error\");\n insertionEffort.failure();\n };\n\n reader.readAsDataURL(originalImage);\n\n return insertionEffort;\n },\n\n _dataUriToBlob: function(dataUri) {\n \"use strict\";\n\n var byteString, mimeString, arrayBuffer, intArray;\n\n // convert base64 to raw binary data held in a string\n if (dataUri.split(\",\")[0].indexOf(\"base64\") >= 0) {\n byteString = atob(dataUri.split(\",\")[1]);\n }\n else {\n byteString = decodeURI(dataUri.split(\",\")[1]);\n }\n\n // extract the MIME\n mimeString = dataUri.split(\",\")[0]\n .split(\":\")[1]\n .split(\";\")[0];\n\n // write the bytes of the binary string to an ArrayBuffer\n arrayBuffer = new ArrayBuffer(byteString.length);\n intArray = new Uint8Array(arrayBuffer);\n qq.each(byteString, function(idx, character) {\n intArray[idx] = character.charCodeAt(0);\n });\n\n return this._createBlob(arrayBuffer, mimeString);\n },\n\n _createBlob: function(data, mime) {\n \"use strict\";\n\n var BlobBuilder = window.BlobBuilder ||\n window.WebKitBlobBuilder ||\n window.MozBlobBuilder ||\n window.MSBlobBuilder,\n blobBuilder = BlobBuilder && new BlobBuilder();\n\n if (blobBuilder) {\n blobBuilder.append(data);\n return blobBuilder.getBlob(mime);\n }\n else {\n return new Blob([data], {type: mime});\n }\n }\n});\n","//Based on MinifyJpeg\n//http://elicon.blog57.fc2.com/blog-entry-206.html\n\nqq.ExifRestorer = (function()\n{\n \n\tvar ExifRestorer = {};\n\t \n ExifRestorer.KEY_STR = \"ABCDEFGHIJKLMNOP\" +\n \"QRSTUVWXYZabcdef\" +\n \"ghijklmnopqrstuv\" +\n \"wxyz0123456789+/\" +\n \"=\";\n\n ExifRestorer.encode64 = function(input)\n {\n var output = \"\",\n chr1, chr2, chr3 = \"\",\n enc1, enc2, enc3, enc4 = \"\",\n i = 0;\n\n do {\n chr1 = input[i++];\n chr2 = input[i++];\n chr3 = input[i++];\n\n enc1 = chr1 >> 2;\n enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);\n enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);\n enc4 = chr3 & 63;\n\n if (isNaN(chr2)) {\n enc3 = enc4 = 64;\n } else if (isNaN(chr3)) {\n enc4 = 64;\n }\n\n output = output +\n this.KEY_STR.charAt(enc1) +\n this.KEY_STR.charAt(enc2) +\n this.KEY_STR.charAt(enc3) +\n this.KEY_STR.charAt(enc4);\n chr1 = chr2 = chr3 = \"\";\n enc1 = enc2 = enc3 = enc4 = \"\";\n } while (i < input.length);\n\n return output;\n };\n \n ExifRestorer.restore = function(origFileBase64, resizedFileBase64)\n {\n var expectedBase64Header = \"data:image/jpeg;base64,\";\n\n if (!origFileBase64.match(expectedBase64Header))\n {\n \treturn resizedFileBase64;\n } \n \n var rawImage = this.decode64(origFileBase64.replace(expectedBase64Header, \"\"));\n var segments = this.slice2Segments(rawImage);\n \n var image = this.exifManipulation(resizedFileBase64, segments);\n \n return expectedBase64Header + this.encode64(image);\n \n };\n\n\n ExifRestorer.exifManipulation = function(resizedFileBase64, segments)\n {\n var exifArray = this.getExifArray(segments),\n newImageArray = this.insertExif(resizedFileBase64, exifArray),\n aBuffer = new Uint8Array(newImageArray);\n\n return aBuffer;\n };\n\n\n ExifRestorer.getExifArray = function(segments)\n {\n var seg;\n for (var x = 0; x < segments.length; x++)\n {\n seg = segments[x];\n if (seg[0] == 255 & seg[1] == 225) //(ff e1)\n {\n return seg;\n }\n }\n return [];\n };\n\n\n ExifRestorer.insertExif = function(resizedFileBase64, exifArray)\n {\n var imageData = resizedFileBase64.replace(\"data:image/jpeg;base64,\", \"\"),\n buf = this.decode64(imageData),\n separatePoint = buf.indexOf(255,3),\n mae = buf.slice(0, separatePoint),\n ato = buf.slice(separatePoint),\n array = mae;\n\n array = array.concat(exifArray);\n array = array.concat(ato);\n return array;\n };\n\n\n \n ExifRestorer.slice2Segments = function(rawImageArray)\n {\n var head = 0,\n segments = [];\n\n while (1)\n {\n if (rawImageArray[head] == 255 & rawImageArray[head + 1] == 218){break;}\n if (rawImageArray[head] == 255 & rawImageArray[head + 1] == 216)\n {\n head += 2;\n }\n else\n {\n var length = rawImageArray[head + 2] * 256 + rawImageArray[head + 3],\n endPoint = head + length + 2,\n seg = rawImageArray.slice(head, endPoint);\n segments.push(seg);\n head = endPoint;\n }\n if (head > rawImageArray.length){break;}\n }\n\n return segments;\n };\n\n\n \n ExifRestorer.decode64 = function(input) \n {\n var output = \"\",\n chr1, chr2, chr3 = \"\",\n enc1, enc2, enc3, enc4 = \"\",\n i = 0,\n buf = [];\n\n // remove all characters that are not A-Z, a-z, 0-9, +, /, or =\n var base64test = /[^A-Za-z0-9\\+\\/\\=]/g;\n if (base64test.exec(input)) {\n throw new Error(\"There were invalid base64 characters in the input text. \" +\n \"Valid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='\");\n }\n input = input.replace(/[^A-Za-z0-9\\+\\/\\=]/g, \"\");\n\n do {\n enc1 = this.KEY_STR.indexOf(input.charAt(i++));\n enc2 = this.KEY_STR.indexOf(input.charAt(i++));\n enc3 = this.KEY_STR.indexOf(input.charAt(i++));\n enc4 = this.KEY_STR.indexOf(input.charAt(i++));\n\n chr1 = (enc1 << 2) | (enc2 >> 4);\n chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);\n chr3 = ((enc3 & 3) << 6) | enc4;\n\n buf.push(chr1);\n\n if (enc3 != 64) {\n buf.push(chr2);\n }\n if (enc4 != 64) {\n buf.push(chr3);\n }\n\n chr1 = chr2 = chr3 = \"\";\n enc1 = enc2 = enc3 = enc4 = \"\";\n\n } while (i < input.length);\n\n return buf;\n };\n\n \n return ExifRestorer;\n})();\n","/* globals qq */\n/**\n * Keeps a running tally of total upload progress for a batch of files.\n *\n * @param callback Invoked when total progress changes, passing calculated total loaded & total size values.\n * @param getSize Function that returns the size of a file given its ID\n * @constructor\n */\nqq.TotalProgress = function(callback, getSize) {\n \"use strict\";\n\n var perFileProgress = {},\n totalLoaded = 0,\n totalSize = 0,\n\n lastLoadedSent = -1,\n lastTotalSent = -1,\n callbackProxy = function(loaded, total) {\n if (loaded !== lastLoadedSent || total !== lastTotalSent) {\n callback(loaded, total);\n }\n\n lastLoadedSent = loaded;\n lastTotalSent = total;\n },\n\n /**\n * @param failed Array of file IDs that have failed\n * @param retryable Array of file IDs that are retryable\n * @returns true if none of the failed files are eligible for retry\n */\n noRetryableFiles = function(failed, retryable) {\n var none = true;\n\n qq.each(failed, function(idx, failedId) {\n if (qq.indexOf(retryable, failedId) >= 0) {\n none = false;\n return false;\n }\n });\n\n return none;\n },\n\n onCancel = function(id) {\n updateTotalProgress(id, -1, -1);\n delete perFileProgress[id];\n },\n\n onAllComplete = function(successful, failed, retryable) {\n if (failed.length === 0 || noRetryableFiles(failed, retryable)) {\n callbackProxy(totalSize, totalSize);\n this.reset();\n }\n },\n\n onNew = function(id) {\n var size = getSize(id);\n\n // We might not know the size yet, such as for blob proxies\n if (size > 0) {\n updateTotalProgress(id, 0, size);\n perFileProgress[id] = {loaded: 0, total: size};\n }\n },\n\n /**\n * Invokes the callback with the current total progress of all files in the batch. Called whenever it may\n * be appropriate to re-calculate and disseminate this data.\n *\n * @param id ID of a file that has changed in some important way\n * @param newLoaded New loaded value for this file. -1 if this value should no longer be part of calculations\n * @param newTotal New total size of the file. -1 if this value should no longer be part of calculations\n */\n updateTotalProgress = function(id, newLoaded, newTotal) {\n var oldLoaded = perFileProgress[id] ? perFileProgress[id].loaded : 0,\n oldTotal = perFileProgress[id] ? perFileProgress[id].total : 0;\n\n if (newLoaded === -1 && newTotal === -1) {\n totalLoaded -= oldLoaded;\n totalSize -= oldTotal;\n }\n else {\n if (newLoaded) {\n totalLoaded += newLoaded - oldLoaded;\n }\n if (newTotal) {\n totalSize += newTotal - oldTotal;\n }\n }\n\n callbackProxy(totalLoaded, totalSize);\n };\n\n qq.extend(this, {\n // Called when a batch of files has completed uploading.\n onAllComplete: onAllComplete,\n\n // Called when the status of a file has changed.\n onStatusChange: function(id, oldStatus, newStatus) {\n if (newStatus === qq.status.CANCELED || newStatus === qq.status.REJECTED) {\n onCancel(id);\n }\n else if (newStatus === qq.status.SUBMITTING) {\n onNew(id);\n }\n },\n\n // Called whenever the upload progress of an individual file has changed.\n onIndividualProgress: function(id, loaded, total) {\n updateTotalProgress(id, loaded, total);\n perFileProgress[id] = {loaded: loaded, total: total};\n },\n\n // Called whenever the total size of a file has changed, such as when the size of a generated blob is known.\n onNewSize: function(id) {\n onNew(id);\n },\n\n reset: function() {\n perFileProgress = {};\n totalLoaded = 0;\n totalSize = 0;\n }\n });\n};\n","/*globals qq*/\nqq.PasteSupport = function(o) {\n \"use strict\";\n\n var options, detachPasteHandler;\n\n options = {\n targetElement: null,\n callbacks: {\n log: function(message, level) {},\n pasteReceived: function(blob) {}\n }\n };\n\n function isImage(item) {\n return item.type &&\n item.type.indexOf(\"image/\") === 0;\n }\n\n function registerPasteHandler() {\n detachPasteHandler = qq(options.targetElement).attach(\"paste\", function(event) {\n var clipboardData = event.clipboardData;\n\n if (clipboardData) {\n qq.each(clipboardData.items, function(idx, item) {\n if (isImage(item)) {\n var blob = item.getAsFile();\n options.callbacks.pasteReceived(blob);\n }\n });\n }\n });\n }\n\n function unregisterPasteHandler() {\n if (detachPasteHandler) {\n detachPasteHandler();\n }\n }\n\n qq.extend(options, o);\n registerPasteHandler();\n\n qq.extend(this, {\n reset: function() {\n unregisterPasteHandler();\n }\n });\n};\n","/* globals qq */\n/**\n * Module that handles support for existing forms.\n *\n * @param options Options passed from the integrator-supplied options related to form support.\n * @param startUpload Callback to invoke when files \"stored\" should be uploaded.\n * @param log Proxy for the logger\n * @constructor\n */\nqq.FormSupport = function(options, startUpload, log) {\n \"use strict\";\n var self = this,\n interceptSubmit = options.interceptSubmit,\n formEl = options.element,\n autoUpload = options.autoUpload;\n\n // Available on the public API associated with this module.\n qq.extend(this, {\n // To be used by the caller to determine if the endpoint will be determined by some processing\n // that occurs in this module, such as if the form has an action attribute.\n // Ignore if `attachToForm === false`.\n newEndpoint: null,\n\n // To be used by the caller to determine if auto uploading should be allowed.\n // Ignore if `attachToForm === false`.\n newAutoUpload: autoUpload,\n\n // true if a form was detected and is being tracked by this module\n attachedToForm: false,\n\n // Returns an object with names and values for all valid form elements associated with the attached form.\n getFormInputsAsObject: function() {\n /* jshint eqnull:true */\n if (formEl == null) {\n return null;\n }\n\n return self._form2Obj(formEl);\n }\n });\n\n // If the form contains an action attribute, this should be the new upload endpoint.\n function determineNewEndpoint(formEl) {\n if (formEl.getAttribute(\"action\")) {\n self.newEndpoint = formEl.getAttribute(\"action\");\n }\n }\n\n // Return true only if the form is valid, or if we cannot make this determination.\n // If the form is invalid, ensure invalid field(s) are highlighted in the UI.\n function validateForm(formEl, nativeSubmit) {\n if (formEl.checkValidity && !formEl.checkValidity()) {\n log(\"Form did not pass validation checks - will not upload.\", \"error\");\n nativeSubmit();\n }\n else {\n return true;\n }\n }\n\n // Intercept form submit attempts, unless the integrator has told us not to do this.\n function maybeUploadOnSubmit(formEl) {\n var nativeSubmit = formEl.submit;\n\n // Intercept and squelch submit events.\n qq(formEl).attach(\"submit\", function(event) {\n event = event || window.event;\n\n if (event.preventDefault) {\n event.preventDefault();\n }\n else {\n event.returnValue = false;\n }\n\n validateForm(formEl, nativeSubmit) && startUpload();\n });\n\n // The form's `submit()` function may be called instead (i.e. via jQuery.submit()).\n // Intercept that too.\n formEl.submit = function() {\n validateForm(formEl, nativeSubmit) && startUpload();\n };\n }\n\n // If the element value passed from the uploader is a string, assume it is an element ID - select it.\n // The rest of the code in this module depends on this being an HTMLElement.\n function determineFormEl(formEl) {\n if (formEl) {\n if (qq.isString(formEl)) {\n formEl = document.getElementById(formEl);\n }\n\n if (formEl) {\n log(\"Attaching to form element.\");\n determineNewEndpoint(formEl);\n interceptSubmit && maybeUploadOnSubmit(formEl);\n }\n }\n\n return formEl;\n }\n\n formEl = determineFormEl(formEl);\n this.attachedToForm = !!formEl;\n};\n\nqq.extend(qq.FormSupport.prototype, {\n // Converts all relevant form fields to key/value pairs. This is meant to mimic the data a browser will\n // construct from a given form when the form is submitted.\n _form2Obj: function(form) {\n \"use strict\";\n var obj = {},\n notIrrelevantType = function(type) {\n var irrelevantTypes = [\n \"button\",\n \"image\",\n \"reset\",\n \"submit\"\n ];\n\n return qq.indexOf(irrelevantTypes, type.toLowerCase()) < 0;\n },\n radioOrCheckbox = function(type) {\n return qq.indexOf([\"checkbox\", \"radio\"], type.toLowerCase()) >= 0;\n },\n ignoreValue = function(el) {\n if (radioOrCheckbox(el.type) && !el.checked) {\n return true;\n }\n\n return el.disabled && el.type.toLowerCase() !== \"hidden\";\n },\n selectValue = function(select) {\n var value = null;\n\n qq.each(qq(select).children(), function(idx, child) {\n if (child.tagName.toLowerCase() === \"option\" && child.selected) {\n value = child.value;\n return false;\n }\n });\n\n return value;\n };\n\n qq.each(form.elements, function(idx, el) {\n if ((qq.isInput(el, true) || el.tagName.toLowerCase() === \"textarea\") &&\n notIrrelevantType(el.type) &&\n !ignoreValue(el)) {\n\n obj[el.name] = el.value;\n }\n else if (el.tagName.toLowerCase() === \"select\" && !ignoreValue(el)) {\n var value = selectValue(el);\n\n if (value !== null) {\n obj[el.name] = value;\n }\n }\n });\n\n return obj;\n }\n});\n","/*globals qq*/\n/**\n * Upload handler used that assumes the current user agent does not have any support for the\n * File API, and, therefore, makes use of iframes and forms to submit the files directly to\n * a generic server.\n *\n * @param options Options passed from the base handler\n * @param proxy Callbacks & methods used to query for or push out data/changes\n */\nqq.traditional = qq.traditional || {};\nqq.traditional.FormUploadHandler = function(options, proxy) {\n \"use strict\";\n\n var handler = this,\n getName = proxy.getName,\n getUuid = proxy.getUuid,\n log = proxy.log;\n\n /**\n * Returns json object received by iframe from server.\n */\n function getIframeContentJson(id, iframe) {\n /*jshint evil: true*/\n\n var response, doc, innerHtml;\n\n //IE may throw an \"access is denied\" error when attempting to access contentDocument on the iframe in some cases\n try {\n // iframe.contentWindow.document - for IE<7\n doc = iframe.contentDocument || iframe.contentWindow.document;\n innerHtml = doc.body.innerHTML;\n\n log(\"converting iframe's innerHTML to JSON\");\n log(\"innerHTML = \" + innerHtml);\n //plain text response may be wrapped in tag\n if (innerHtml && innerHtml.match(/^= 0) {
chunked.reset(id);
}
- if (!options.onAutoRetry(id, name, normaizedResponse, xhr)) {
- upload.cleanup(id, normaizedResponse, xhr);
+ if (!options.onAutoRetry(id, name, normalizedResponse, xhr)) {
+ upload.cleanup(id, normalizedResponse, xhr);
}
});
},
@@ -2912,7 +3034,8 @@
if (responseToReport.reset) {
chunked.reset(id);
} else {
- inProgressIdx = qq.indexOf(handler._getFileState(id).chunking.inProgress, chunkIdx);
+ var inProgressChunksArray = handler._getFileState(id).chunking.inProgress;
+ inProgressIdx = inProgressChunksArray ? qq.indexOf(inProgressChunksArray, chunkIdx) : -1;
if (inProgressIdx >= 0) {
handler._getFileState(id).chunking.inProgress.splice(inProgressIdx, 1);
handler._getFileState(id).chunking.remaining.unshift(chunkIdx);
@@ -2950,13 +3073,14 @@
handler._maybeDeletePersistedChunkData(id);
handler.reevaluateChunking(id);
handler._getFileState(id).loaded = 0;
+ handler._getFileState(id).attemptingResume = false;
},
sendNext: function(id) {
- var size = options.getSize(id), name = options.getName(id), chunkIdx = chunked.nextPart(id), chunkData = handler._getChunkData(id, chunkIdx), resuming = handler._getFileState(id).attemptingResume, inProgressChunks = handler._getFileState(id).chunking.inProgress || [];
- if (handler._getFileState(id).loaded == null) {
- handler._getFileState(id).loaded = 0;
+ var size = options.getSize(id), name = options.getName(id), chunkIdx = chunked.nextPart(id), chunkData = handler._getChunkData(id, chunkIdx), fileState = handler._getFileState(id), resuming = fileState.attemptingResume, inProgressChunks = fileState.chunking.inProgress || [];
+ if (fileState.loaded == null) {
+ fileState.loaded = 0;
}
- if (resuming && options.onResume(id, name, chunkData) === false) {
+ if (resuming && options.onResume(id, name, chunkData, fileState.customResumeData) === false) {
chunked.reset(id);
chunkIdx = chunked.nextPart(id);
chunkData = handler._getChunkData(id, chunkIdx);
@@ -2965,8 +3089,6 @@
if (chunkIdx == null && inProgressChunks.length === 0) {
chunked.finalize(id);
} else {
- log(qq.format("Sending chunked upload request for item {}.{}, bytes {}-{} of {}.", id, chunkIdx, chunkData.start + 1, chunkData.end, size));
- options.onUploadChunk(id, name, handler._getChunkDataForCallback(chunkData));
inProgressChunks.push(chunkIdx);
handler._getFileState(id).chunking.inProgress = inProgressChunks;
if (concurrentChunkingPossible) {
@@ -2978,30 +3100,45 @@
if (chunkData.blob.size === 0) {
log(qq.format("Chunk {} for file {} will not be uploaded, zero sized chunk.", chunkIdx, id), "error");
chunked.handleFailure(chunkIdx, id, "File is no longer available", null);
- } else {
- handler.uploadChunk(id, chunkIdx, resuming).then(function success(response, xhr) {
- log("Chunked upload request succeeded for " + id + ", chunk " + chunkIdx);
- handler.clearCachedChunk(id, chunkIdx);
- var inProgressChunks = handler._getFileState(id).chunking.inProgress || [], responseToReport = upload.normalizeResponse(response, true), inProgressChunkIdx = qq.indexOf(inProgressChunks, chunkIdx);
- log(qq.format("Chunk {} for file {} uploaded successfully.", chunkIdx, id));
- chunked.done(id, chunkIdx, responseToReport, xhr);
- if (inProgressChunkIdx >= 0) {
- inProgressChunks.splice(inProgressChunkIdx, 1);
- }
- handler._maybePersistChunkedState(id);
- if (!chunked.hasMoreParts(id) && inProgressChunks.length === 0) {
- chunked.finalize(id);
- } else if (chunked.hasMoreParts(id)) {
- chunked.sendNext(id);
- } else {
- log(qq.format("File ID {} has no more chunks to send and these chunk indexes are still marked as in-progress: {}", id, JSON.stringify(inProgressChunks)));
- }
- }, function failure(response, xhr) {
- chunked.handleFailure(chunkIdx, id, response, xhr);
- }).done(function() {
- handler.clearXhr(id, chunkIdx);
- });
}
+ var onUploadChunkPromise = options.onUploadChunk(id, name, handler._getChunkDataForCallback(chunkData));
+ onUploadChunkPromise.then(function(requestOverrides) {
+ if (!options.isInProgress(id)) {
+ log(qq.format("Not sending chunked upload request for item {}.{} - no longer in progress.", id, chunkIdx));
+ } else {
+ log(qq.format("Sending chunked upload request for item {}.{}, bytes {}-{} of {}.", id, chunkIdx, chunkData.start + 1, chunkData.end, size));
+ var uploadChunkData = {
+ chunkIdx: chunkIdx,
+ id: id,
+ overrides: requestOverrides,
+ resuming: resuming
+ };
+ handler.uploadChunk(uploadChunkData).then(function success(response, xhr) {
+ log("Chunked upload request succeeded for " + id + ", chunk " + chunkIdx);
+ handler.clearCachedChunk(id, chunkIdx);
+ var inProgressChunks = handler._getFileState(id).chunking.inProgress || [], responseToReport = upload.normalizeResponse(response, true), inProgressChunkIdx = qq.indexOf(inProgressChunks, chunkIdx);
+ log(qq.format("Chunk {} for file {} uploaded successfully.", chunkIdx, id));
+ chunked.done(id, chunkIdx, responseToReport, xhr);
+ if (inProgressChunkIdx >= 0) {
+ inProgressChunks.splice(inProgressChunkIdx, 1);
+ }
+ handler._maybePersistChunkedState(id);
+ if (!chunked.hasMoreParts(id) && inProgressChunks.length === 0) {
+ chunked.finalize(id);
+ } else if (chunked.hasMoreParts(id)) {
+ chunked.sendNext(id);
+ } else {
+ log(qq.format("File ID {} has no more chunks to send and these chunk indexes are still marked as in-progress: {}", id, JSON.stringify(inProgressChunks)));
+ }
+ }, function failure(response, xhr) {
+ chunked.handleFailure(chunkIdx, id, response, xhr);
+ }).done(function() {
+ handler.clearXhr(id, chunkIdx);
+ });
+ }
+ }, function(error) {
+ chunked.handleFailure(chunkIdx, id, error, null);
+ });
}
}
}, connectionManager = {
@@ -3077,7 +3214,12 @@
}
}, simple = {
send: function(id, name) {
- handler._getFileState(id).loaded = 0;
+ var fileState = handler._getFileState(id);
+ if (!fileState) {
+ log("Ignoring send request as this upload may have been cancelled, File ID " + id, "warn");
+ return;
+ }
+ fileState.loaded = 0;
log("Sending simple upload request for " + id);
handler.uploadFile(id).then(function(response, optXhr) {
log("Simple upload request succeeded for " + id);
@@ -3113,6 +3255,7 @@
initHandler: function() {
var handlerType = namespace ? qq[namespace] : qq.traditional, handlerModuleSubtype = qq.supportedFeatures.ajaxUploading ? "Xhr" : "Form";
handler = new handlerType[handlerModuleSubtype + "UploadHandler"](options, {
+ getCustomResumeData: options.getCustomResumeData,
getDataByUuid: options.getDataByUuid,
getName: options.getName,
getSize: options.getSize,
@@ -3120,7 +3263,10 @@
log: log,
onCancel: options.onCancel,
onProgress: options.onProgress,
- onUuidChanged: options.onUuidChanged
+ onUuidChanged: options.onUuidChanged,
+ onFinalizing: function(id) {
+ options.setStatus(id, qq.status.UPLOAD_FINALIZING);
+ }
});
if (handler._removeExpiredChunkingRecords) {
handler._removeExpiredChunkingRecords();
@@ -3193,12 +3339,26 @@
if (!controller.isValid(id)) {
throw new qq.Error(id + " is not a valid file ID to upload!");
}
- options.onUpload(id, name);
- if (chunkingPossible && handler._shouldChunkThisFile(id)) {
- chunked.sendNext(id);
- } else {
- simple.send(id, name);
- }
+ options.onUpload(id, name).then(function(response) {
+ if (response && response.pause) {
+ options.setStatus(id, qq.status.PAUSED);
+ handler.pause(id);
+ connectionManager.free(id);
+ } else {
+ if (chunkingPossible && handler._shouldChunkThisFile(id)) {
+ chunked.sendNext(id);
+ } else {
+ simple.send(id, name);
+ }
+ }
+ }, function(error) {
+ error = error || {};
+ log(id + " upload start aborted due to rejected onUpload Promise - details: " + error, "error");
+ if (!options.onAutoRetry(id, name, error.responseJSON || {})) {
+ var response = upload.normalizeResponse(error.responseJSON, false);
+ upload.cleanup(id, response);
+ }
+ });
},
start: function(id) {
var blobToUpload = upload.getProxyOrBlob(id);
@@ -3277,6 +3437,13 @@
isValid: function(id) {
return handler.isValid(id);
},
+ hasResumeRecord: function(id) {
+ var key = handler.isValid(id) && handler._getLocalStorageId && handler._getLocalStorageId(id);
+ if (key) {
+ return !!localStorage.getItem(key);
+ }
+ return false;
+ },
getResumableFilesData: function() {
if (handler.getResumableFilesData) {
return handler.getResumableFilesData();
@@ -3296,6 +3463,9 @@
}
return false;
},
+ isAttemptingResume: function(id) {
+ return !!handler.isAttemptingResume && handler.isAttemptingResume(id);
+ },
isResumable: function(id) {
return !!handler.isResumable && handler.isResumable(id);
}
@@ -3486,7 +3656,19 @@
};
qq.XhrUploadHandler = function(spec) {
"use strict";
- var handler = this, namespace = spec.options.namespace, proxy = spec.proxy, chunking = spec.options.chunking, resume = spec.options.resume, chunkFiles = chunking && spec.options.chunking.enabled && qq.supportedFeatures.chunking, resumeEnabled = resume && spec.options.resume.enabled && chunkFiles && qq.supportedFeatures.resume, getName = proxy.getName, getSize = proxy.getSize, getUuid = proxy.getUuid, getEndpoint = proxy.getEndpoint, getDataByUuid = proxy.getDataByUuid, onUuidChanged = proxy.onUuidChanged, onProgress = proxy.onProgress, log = proxy.log;
+ var handler = this, namespace = spec.options.namespace, proxy = spec.proxy, chunking = spec.options.chunking, getChunkSize = function(id) {
+ var fileState = handler._getFileState(id);
+ if (fileState.chunkSize) {
+ return fileState.chunkSize;
+ } else {
+ var chunkSize = chunking.partSize;
+ if (qq.isFunction(chunkSize)) {
+ chunkSize = chunkSize(id, getSize(id));
+ }
+ fileState.chunkSize = chunkSize;
+ return chunkSize;
+ }
+ }, resume = spec.options.resume, chunkFiles = chunking && spec.options.chunking.enabled && qq.supportedFeatures.chunking, resumeEnabled = resume && spec.options.resume.enabled && chunkFiles && qq.supportedFeatures.resume, getName = proxy.getName, getSize = proxy.getSize, getUuid = proxy.getUuid, getEndpoint = proxy.getEndpoint, getDataByUuid = proxy.getDataByUuid, onUuidChanged = proxy.onUuidChanged, onProgress = proxy.onProgress, log = proxy.log, getCustomResumeData = proxy.getCustomResumeData;
function abort(id) {
qq.each(handler._getXhrs(id), function(xhrId, xhr) {
var ajaxRequester = handler._getAjaxRequester(id, xhrId);
@@ -3524,7 +3706,10 @@
});
qq.extend(this, {
clearCachedChunk: function(id, chunkIdx) {
- delete handler._getFileState(id).temp.cachedChunks[chunkIdx];
+ var fileState = handler._getFileState(id);
+ if (fileState) {
+ delete fileState.temp.cachedChunks[chunkIdx];
+ }
},
clearXhr: function(id, chunkIdx) {
var tempState = handler._getFileState(id).temp;
@@ -3561,15 +3746,21 @@
if (uploadData.key) {
data.key = uploadData.key;
}
+ if (uploadData.customResumeData) {
+ data.customResumeData = uploadData.customResumeData;
+ }
resumableFilesData.push(data);
});
return resumableFilesData;
},
+ isAttemptingResume: function(id) {
+ return handler._getFileState(id).attemptingResume;
+ },
isResumable: function(id) {
return !!chunking && handler.isValid(id) && !handler._getFileState(id).notResumable;
},
moveInProgressToRemaining: function(id, optInProgress, optRemaining) {
- var inProgress = optInProgress || handler._getFileState(id).chunking.inProgress, remaining = optRemaining || handler._getFileState(id).chunking.remaining;
+ var fileState = handler._getFileState(id) || {}, chunkingState = fileState.chunking || {}, inProgress = optInProgress || chunkingState.inProgress, remaining = optRemaining || chunkingState.remaining;
if (inProgress) {
log(qq.format("Moving these chunks from in-progress {}, to remaining.", JSON.stringify(inProgress)));
inProgress.reverse();
@@ -3628,7 +3819,7 @@
return handler._getFileState(id).temp.ajaxRequesters[chunkIdx];
},
_getChunkData: function(id, chunkIndex) {
- var chunkSize = chunking.partSize, fileSize = getSize(id), fileOrBlob = handler.getFile(id), startBytes = chunkSize * chunkIndex, endBytes = startBytes + chunkSize >= fileSize ? fileSize : startBytes + chunkSize, totalChunks = handler._getTotalChunks(id), cachedChunks = this._getFileState(id).temp.cachedChunks, blob = cachedChunks[chunkIndex] || qq.sliceBlob(fileOrBlob, startBytes, endBytes);
+ var chunkSize = getChunkSize(id), fileSize = getSize(id), fileOrBlob = handler.getFile(id), startBytes = chunkSize * chunkIndex, endBytes = startBytes + chunkSize >= fileSize ? fileSize : startBytes + chunkSize, totalChunks = handler._getTotalChunks(id), cachedChunks = this._getFileState(id).temp.cachedChunks, blob = cachedChunks[chunkIndex] || qq.sliceBlob(fileOrBlob, startBytes, endBytes);
cachedChunks[chunkIndex] = blob;
return {
part: chunkIndex,
@@ -3648,8 +3839,11 @@
};
},
_getLocalStorageId: function(id) {
- var formatVersion = "5.0", name = getName(id), size = getSize(id), chunkSize = chunking.partSize, endpoint = getEndpoint(id);
- return qq.format("qq{}resume{}-{}-{}-{}-{}", namespace, formatVersion, name, size, chunkSize, endpoint);
+ var formatVersion = "5.0", name = getName(id), size = getSize(id), chunkSize = getChunkSize(id), endpoint = getEndpoint(id), customKeys = resume.customKeys(id), localStorageId = qq.format("qq{}resume{}-{}-{}-{}-{}", namespace, formatVersion, name, size, chunkSize, endpoint);
+ customKeys.forEach(function(key) {
+ localStorageId += "-" + key;
+ });
+ return localStorageId;
},
_getMimeType: function(id) {
return handler.getFile(id).type;
@@ -3659,7 +3853,7 @@
},
_getTotalChunks: function(id) {
if (chunking) {
- var fileSize = getSize(id), chunkSize = chunking.partSize;
+ var fileSize = getSize(id), chunkSize = getChunkSize(id);
return Math.ceil(fileSize / chunkSize);
}
},
@@ -3717,6 +3911,7 @@
state.key = persistedData.key;
state.chunking = persistedData.chunking;
state.loaded = persistedData.loaded;
+ state.customResumeData = persistedData.customResumeData;
state.attemptingResume = true;
handler.moveInProgressToRemaining(id);
}
@@ -3726,6 +3921,7 @@
_maybePersistChunkedState: function(id) {
var state = handler._getFileState(id), localStorageId, persistedData;
if (resumeEnabled && handler.isResumable(id)) {
+ var customResumeData = getCustomResumeData(id);
localStorageId = handler._getLocalStorageId(id);
persistedData = {
name: getName(id),
@@ -3736,6 +3932,9 @@
loaded: state.loaded,
lastUpdated: Date.now()
};
+ if (customResumeData) {
+ persistedData.customResumeData = customResumeData;
+ }
try {
localStorage.setItem(localStorageId, JSON.stringify(persistedData));
} catch (error) {
@@ -3792,10 +3991,12 @@
},
_shouldChunkThisFile: function(id) {
var state = handler._getFileState(id);
- if (!state.chunking) {
- handler.reevaluateChunking(id);
+ if (state) {
+ if (!state.chunking) {
+ handler.reevaluateChunking(id);
+ }
+ return state.chunking.enabled;
}
- return state.chunking.enabled;
}
});
};
@@ -5322,18 +5523,24 @@
"use strict";
var handler = this, getName = proxy.getName, getSize = proxy.getSize, getUuid = proxy.getUuid, log = proxy.log, multipart = spec.forceMultipart || spec.paramsInBody, addChunkingSpecificParams = function(id, params, chunkData) {
var size = getSize(id), name = getName(id);
- params[spec.chunking.paramNames.partIndex] = chunkData.part;
- params[spec.chunking.paramNames.partByteOffset] = chunkData.start;
- params[spec.chunking.paramNames.chunkSize] = chunkData.size;
- params[spec.chunking.paramNames.totalParts] = chunkData.count;
- params[spec.totalFileSizeName] = size;
- if (multipart) {
+ if (!spec.omitDefaultParams) {
+ params[spec.chunking.paramNames.partIndex] = chunkData.part;
+ params[spec.chunking.paramNames.partByteOffset] = chunkData.start;
+ params[spec.chunking.paramNames.chunkSize] = chunkData.size;
+ params[spec.chunking.paramNames.totalParts] = chunkData.count;
+ params[spec.totalFileSizeName] = size;
+ }
+ if (multipart && !spec.omitDefaultParams) {
params[spec.filenameParam] = name;
}
}, allChunksDoneRequester = new qq.traditional.AllChunksDoneAjaxRequester({
cors: spec.cors,
endpoint: spec.chunking.success.endpoint,
- log: log
+ headers: spec.chunking.success.headers,
+ jsonPayload: spec.chunking.success.jsonPayload,
+ log: log,
+ method: spec.chunking.success.method,
+ params: spec.chunking.success.params
}), createReadyStateChangedHandler = function(id, xhr) {
var promise = new qq.Promise();
xhr.onreadystatechange = function() {
@@ -5355,7 +5562,7 @@
params[spec.chunking.paramNames.totalParts] = handler._getTotalChunks(id);
return params;
}, isErrorUploadResponse = function(xhr, response) {
- return qq.indexOf([ 200, 201, 202, 203, 204 ], xhr.status) < 0 || !response.success || response.reset;
+ return qq.indexOf([ 200, 201, 202, 203, 204 ], xhr.status) < 0 || spec.requireSuccessJson && !response.success || response.reset;
}, onUploadOrChunkComplete = function(id, xhr) {
var response;
log("xhr - server response received for " + id);
@@ -5371,7 +5578,7 @@
log(qq.format("Received response status {} with body: {}", xhr.status, xhr.responseText));
response = qq.parseJson(xhr.responseText);
} catch (error) {
- upload && log("Error when attempting to parse xhr response text (" + error.message + ")", "error");
+ upload && spec.requireSuccessJson && log("Error when attempting to parse xhr response text (" + error.message + ")", "error");
}
return response;
}, sendChunksCompleteRequest = function(id) {
@@ -5382,17 +5589,32 @@
promise.failure(parseResponse(false, xhr), xhr);
});
return promise;
- }, setParamsAndGetEntityToSend = function(params, xhr, fileOrBlob, id) {
- var formData = new FormData(), method = spec.method, endpoint = spec.endpointStore.get(id), name = getName(id), size = getSize(id);
- params[spec.uuidName] = getUuid(id);
- params[spec.filenameParam] = name;
- if (multipart) {
- params[spec.totalFileSizeName] = size;
- }
- if (!spec.paramsInBody) {
- if (!multipart) {
+ }, setParamsAndGetEntityToSend = function(entityToSendParams) {
+ var fileOrBlob = entityToSendParams.fileOrBlob;
+ var id = entityToSendParams.id;
+ var xhr = entityToSendParams.xhr;
+ var xhrOverrides = entityToSendParams.xhrOverrides || {};
+ var customParams = entityToSendParams.customParams || {};
+ var defaultParams = entityToSendParams.params || {};
+ var xhrOverrideParams = xhrOverrides.params || {};
+ var params;
+ var formData = multipart ? new FormData() : null, method = xhrOverrides.method || spec.method, endpoint = xhrOverrides.endpoint || spec.endpointStore.get(id), name = getName(id), size = getSize(id);
+ if (spec.omitDefaultParams) {
+ params = qq.extend({}, customParams);
+ qq.extend(params, xhrOverrideParams);
+ } else {
+ params = qq.extend({}, customParams);
+ qq.extend(params, xhrOverrideParams);
+ qq.extend(params, defaultParams);
+ params[spec.uuidName] = getUuid(id);
+ params[spec.filenameParam] = name;
+ if (multipart) {
+ params[spec.totalFileSizeName] = size;
+ } else if (!spec.paramsInBody) {
params[spec.inputName] = name;
}
+ }
+ if (!spec.paramsInBody) {
endpoint = qq.obj2url(params, endpoint);
}
xhr.open(method, endpoint, true);
@@ -5407,42 +5629,74 @@
return formData;
}
return fileOrBlob;
- }, setUploadHeaders = function(id, xhr) {
- var extraHeaders = spec.customHeaders.get(id), fileOrBlob = handler.getFile(id);
- xhr.setRequestHeader("Accept", "application/json");
- xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
- xhr.setRequestHeader("Cache-Control", "no-cache");
- if (!multipart) {
- xhr.setRequestHeader("Content-Type", "application/octet-stream");
- xhr.setRequestHeader("X-Mime-Type", fileOrBlob.type);
+ }, setUploadHeaders = function(headersOptions) {
+ var headerOverrides = headersOptions.headerOverrides;
+ var id = headersOptions.id;
+ var xhr = headersOptions.xhr;
+ if (headerOverrides) {
+ qq.each(headerOverrides, function(headerName, headerValue) {
+ xhr.setRequestHeader(headerName, headerValue);
+ });
+ } else {
+ var extraHeaders = spec.customHeaders.get(id), fileOrBlob = handler.getFile(id);
+ xhr.setRequestHeader("Accept", "application/json");
+ xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
+ xhr.setRequestHeader("Cache-Control", "no-cache");
+ if (!multipart) {
+ xhr.setRequestHeader("Content-Type", "application/octet-stream");
+ xhr.setRequestHeader("X-Mime-Type", fileOrBlob.type);
+ }
+ qq.each(extraHeaders, function(name, val) {
+ xhr.setRequestHeader(name, val);
+ });
}
- qq.each(extraHeaders, function(name, val) {
- xhr.setRequestHeader(name, val);
- });
};
qq.extend(this, {
- uploadChunk: function(id, chunkIdx, resuming) {
- var chunkData = handler._getChunkData(id, chunkIdx), xhr = handler._createXhr(id, chunkIdx), size = getSize(id), promise, toSend, params;
+ uploadChunk: function(uploadChunkParams) {
+ var id = uploadChunkParams.id;
+ var chunkIdx = uploadChunkParams.chunkIdx;
+ var overrides = uploadChunkParams.overrides || {};
+ var resuming = uploadChunkParams.resuming;
+ var chunkData = handler._getChunkData(id, chunkIdx), xhr = handler._createXhr(id, chunkIdx), promise, toSend, customParams, params = {};
promise = createReadyStateChangedHandler(id, xhr);
handler._registerProgressHandler(id, chunkIdx, chunkData.size);
- params = spec.paramsStore.get(id);
+ customParams = spec.paramsStore.get(id);
addChunkingSpecificParams(id, params, chunkData);
if (resuming) {
params[spec.resume.paramNames.resuming] = true;
}
- toSend = setParamsAndGetEntityToSend(params, xhr, chunkData.blob, id);
- setUploadHeaders(id, xhr);
+ toSend = setParamsAndGetEntityToSend({
+ fileOrBlob: chunkData.blob,
+ id: id,
+ customParams: customParams,
+ params: params,
+ xhr: xhr,
+ xhrOverrides: overrides
+ });
+ setUploadHeaders({
+ headerOverrides: overrides.headers,
+ id: id,
+ xhr: xhr
+ });
xhr.send(toSend);
return promise;
},
uploadFile: function(id) {
- var fileOrBlob = handler.getFile(id), promise, xhr, params, toSend;
+ var fileOrBlob = handler.getFile(id), promise, xhr, customParams, toSend;
xhr = handler._createXhr(id);
handler._registerProgressHandler(id);
promise = createReadyStateChangedHandler(id, xhr);
- params = spec.paramsStore.get(id);
- toSend = setParamsAndGetEntityToSend(params, xhr, fileOrBlob, id);
- setUploadHeaders(id, xhr);
+ customParams = spec.paramsStore.get(id);
+ toSend = setParamsAndGetEntityToSend({
+ fileOrBlob: fileOrBlob,
+ id: id,
+ customParams: customParams,
+ xhr: xhr
+ });
+ setUploadHeaders({
+ id: id,
+ xhr: xhr
+ });
xhr.send(toSend);
return promise;
}
@@ -5458,6 +5712,7 @@
qq.override(this, function(super_) {
return {
finalizeChunks: function(id) {
+ proxy.onFinalizing(id);
if (spec.chunking.success.endpoint) {
return sendChunksCompleteRequest(id);
} else {
@@ -5469,24 +5724,29 @@
};
qq.traditional.AllChunksDoneAjaxRequester = function(o) {
"use strict";
- var requester, method = "POST", options = {
+ var requester, options = {
cors: {
allowXdr: false,
expected: false,
sendCredentials: false
},
endpoint: null,
- log: function(str, level) {}
+ log: function(str, level) {},
+ method: "POST"
}, promises = {}, endpointHandler = {
get: function(id) {
+ if (qq.isFunction(options.endpoint)) {
+ return options.endpoint(id);
+ }
return options.endpoint;
}
};
qq.extend(options, o);
requester = qq.extend(this, new qq.AjaxRequester({
acceptHeader: "application/json",
- validMethods: [ method ],
- method: method,
+ contentType: options.jsonPayload ? "application/json" : "application/x-www-form-urlencoded",
+ validMethods: [ options.method ],
+ method: options.method,
endpointStore: endpointHandler,
allowXRequestedWithAndCacheControl: false,
cors: options.cors,
@@ -5506,7 +5766,7 @@
var promise = new qq.Promise();
options.log("Submitting All Chunks Done request for " + id);
promises[id] = promise;
- requester.initTransport(id).withParams(params).withHeaders(headers).send(xhr);
+ requester.initTransport(id).withParams(options.params(id) || params).withHeaders(options.headers(id) || headers).send(xhr);
return promise;
}
});
@@ -5533,12 +5793,7 @@
var parseEntryPromise = new qq.Promise();
if (entry.isFile) {
entry.file(function(file) {
- var name = entry.name, fullPath = entry.fullPath, indexOfNameInFullPath = fullPath.indexOf(name);
- fullPath = fullPath.substr(0, indexOfNameInFullPath);
- if (fullPath.charAt(0) === "/") {
- fullPath = fullPath.substr(1);
- }
- file.qqPath = fullPath;
+ file.qqPath = extractDirectoryPath(entry);
droppedFiles.push(file);
parseEntryPromise.success();
}, function(fileError) {
@@ -5566,6 +5821,14 @@
}
return parseEntryPromise;
}
+ function extractDirectoryPath(entry) {
+ var name = entry.name, fullPath = entry.fullPath, indexOfNameInFullPath = fullPath.lastIndexOf(name);
+ fullPath = fullPath.substr(0, indexOfNameInFullPath);
+ if (fullPath.charAt(0) === "/") {
+ fullPath = fullPath.substr(1);
+ }
+ return fullPath;
+ }
function getFilesInDirectory(entry, reader, accumEntries, existingPromise) {
var promise = existingPromise || new qq.Promise(), dirReader = reader || entry.createReader();
dirReader.readEntries(function readSuccess(entries) {
@@ -5653,9 +5916,6 @@
return fileDrag;
}
function leavingDocumentOut(e) {
- if (qq.firefox()) {
- return !e.relatedTarget;
- }
if (qq.safari()) {
return e.x < 0 || e.y < 0;
}
@@ -5695,8 +5955,10 @@
maybeHideDropZones();
});
disposeSupport.attach(document, "drop", function(e) {
- e.preventDefault();
- maybeHideDropZones();
+ if (isFileDrag(e)) {
+ e.preventDefault();
+ maybeHideDropZones();
+ }
});
disposeSupport.attach(document, HIDE_ZONES_EVENT_NAME, maybeHideDropZones);
}
@@ -5721,6 +5983,8 @@
});
}
});
+ this._testing = {};
+ this._testing.extractDirectoryPath = extractDirectoryPath;
};
qq.DragAndDrop.callbacks = function() {
"use strict";
@@ -5773,7 +6037,7 @@
}
var effectTest, dt = e.dataTransfer, isSafari = qq.safari();
effectTest = qq.ie() && qq.supportedFeatures.fileDrop ? true : dt.effectAllowed !== "none";
- return dt && effectTest && (dt.files || !isSafari && dt.types.contains && dt.types.contains("Files"));
+ return dt && effectTest && (dt.files && dt.files.length || !isSafari && dt.types.contains && dt.types.contains("Files") || dt.types.includes && dt.types.includes("Files"));
}
function isOrSetDropDisabled(isDisabled) {
if (isDisabled !== undefined) {
@@ -5856,6 +6120,8 @@
return element;
}
});
+ this._testing = {};
+ this._testing.isValidFileDrag = isValidFileDrag;
};
(function() {
"use strict";
@@ -6584,7 +6850,7 @@
dropProcessing: "qq-drop-processing-selector",
dropProcessingSpinner: "qq-drop-processing-spinner-selector",
thumbnail: "qq-thumbnail-selector"
- }, previewGeneration = {}, cachedThumbnailNotAvailableImg = new qq.Promise(), cachedWaitingForThumbnailImg = new qq.Promise(), log, isEditElementsExist, isRetryElementExist, templateHtml, container, fileList, showThumbnails, serverScale, cacheThumbnailPlaceholders = function() {
+ }, previewGeneration = {}, cachedThumbnailNotAvailableImg = new qq.Promise(), cachedWaitingForThumbnailImg = new qq.Promise(), log, isEditElementsExist, isRetryElementExist, templateDom, container, fileList, showThumbnails, serverScale, cacheThumbnailPlaceholders = function() {
var notAvailableUrl = options.placeholders.thumbnailNotAvailable, waitingUrl = options.placeholders.waitingForThumbnail, spec = {
maxSize: thumbnailMaxSize,
scale: serverScale
@@ -6716,7 +6982,7 @@
});
return notAvailableImgPlacement;
}, parseAndGetTemplate = function() {
- var scriptEl, scriptHtml, fileListNode, tempTemplateEl, fileListHtml, defaultButton, dropArea, thumbnail, dropProcessing, dropTextEl, uploaderEl;
+ var scriptEl, scriptHtml, fileListNode, tempTemplateEl, fileListEl, defaultButton, dropArea, thumbnail, dropProcessing, dropTextEl, uploaderEl;
log("Parsing template");
if (options.templateIdOrEl == null) {
throw new Error("You MUST specify either a template element or ID!");
@@ -6780,15 +7046,15 @@
if (fileListNode == null) {
throw new Error("Could not find the file list container in the template!");
}
- fileListHtml = fileListNode.innerHTML;
+ fileListEl = fileListNode.children[0].cloneNode(true);
fileListNode.innerHTML = "";
if (tempTemplateEl.getElementsByTagName("DIALOG").length) {
document.createElement("dialog");
}
log("Template parsing complete");
return {
- template: qq.trimStr(tempTemplateEl.innerHTML),
- fileTemplate: qq.trimStr(fileListHtml)
+ template: tempTemplateEl,
+ fileTemplate: fileListEl
};
}, prependFile = function(el, index, fileList) {
var parentEl = fileList, beforeEl = parentEl.firstChild;
@@ -6894,13 +7160,13 @@
}
container = options.containerEl;
showThumbnails = options.imageGenerator !== undefined;
- templateHtml = parseAndGetTemplate();
+ templateDom = parseAndGetTemplate();
cacheThumbnailPlaceholders();
qq.extend(this, {
render: function() {
log("Rendering template in DOM.");
generatedThumbnails = 0;
- container.innerHTML = templateHtml.template;
+ container.appendChild(templateDom.template.cloneNode(true));
hide(getDropProcessing());
this.hideTotalProgress();
fileList = options.fileContainerEl || getTemplateEl(container, selectorClasses.list);
@@ -6912,6 +7178,7 @@
container.appendChild(cantRenderEl);
},
reset: function() {
+ container.innerHTML = "";
this.render();
},
clearFiles: function() {
@@ -6921,7 +7188,7 @@
isCancelDisabled = true;
},
addFile: function(id, name, prependInfo, hideForever, batch) {
- var fileEl = qq.toElement(templateHtml.fileTemplate), fileNameEl = getTemplateEl(fileEl, selectorClasses.file), uploaderEl = getTemplateEl(container, selectorClasses.uploader), fileContainer = batch ? fileBatch.content : fileList, thumb;
+ var fileEl = templateDom.fileTemplate.cloneNode(true), fileNameEl = getTemplateEl(fileEl, selectorClasses.file), uploaderEl = getTemplateEl(container, selectorClasses.uploader), fileContainer = batch ? fileBatch.content : fileList, thumb;
if (batch) {
fileBatch.map[id] = fileEl;
}
@@ -7411,4 +7678,4 @@
});
};
})(window);
-//# sourceMappingURL=fine-uploader.js.map
+//# sourceMappingURL=fine-uploader.js.map
\ No newline at end of file
diff --git a/styles/bootstrap/fine-uploader/fine-uploader.js.map b/styles/bootstrap/fine-uploader/fine-uploader.js.map
index f04b96e4a..a87518cba 100644
--- a/styles/bootstrap/fine-uploader/fine-uploader.js.map
+++ b/styles/bootstrap/fine-uploader/fine-uploader.js.map
@@ -1 +1 @@
-{"version":3,"sources":["?","../client/js/util.js","../client/js/export.js","../client/js/error/error.js","../client/js/version.js","../client/js/features.js","../client/js/promise.js","../client/js/blob-proxy.js","../client/js/button.js","../client/js/upload-data.js","../client/js/uploader.basic.api.js","../client/js/uploader.basic.js","../client/js/ajax.requester.js","../client/js/upload-handler/upload.handler.js","../client/js/upload-handler/upload.handler.controller.js","../client/js/window.receive.message.js","../client/js/upload-handler/form.upload.handler.js","../client/js/upload-handler/xhr.upload.handler.js","../client/js/deletefile.ajax.requester.js","../client/js/image-support/megapix-image.js","../client/js/image-support/image.js","../client/js/image-support/exif.js","../client/js/identify.js","../client/js/image-support/validation.image.js","../client/js/session.js","../client/js/session.ajax.requester.js","../client/js/image-support/scaler.js","../client/js/third-party/ExifRestorer.js","../client/js/total-progress.js","../client/js/paste.js","../client/js/form-support.js","../client/js/traditional/traditional.form.upload.handler.js","../client/js/traditional/traditional.xhr.upload.handler.js","../client/js/traditional/all-chunks-done.ajax.requester.js","../client/js/dnd.js","../client/js/uploader.api.js","../client/js/uploader.js","../client/js/templating.js","../client/js/ui.handler.events.js","../client/js/ui.handler.click.filebuttons.js","../client/js/ui.handler.click.filename.js","../client/js/ui.handler.focusin.filenameinput.js","../client/js/ui.handler.focus.filenameinput.js","../client/js/ui.handler.edit.filename.js"],"names":["global","qq","element","hide","style","display","this","attach","type","fn","addEventListener","attachEvent","detach","removeEventListener","detachEvent","contains","descendant","compareDocumentPosition","insertBefore","elementB","parentNode","remove","removeChild","css","styles","Error","opacity","filter","Math","round","extend","hasClass","name","considerParent","re","RegExp","test","className","addClass","removeClass","replace","getByClass","first","candidates","result","querySelector","querySelectorAll","getElementsByTagName","each","idx","val","push","getFirstByClass","children","child","firstChild","nodeType","nextSibling","setText","text","innerText","textContent","clearText","hasAttribute","attrName","attrVal","exec","getAttribute","undefined","canvasToBlob","canvas","mime","quality","dataUriToBlob","toDataURL","dataUri","arrayBuffer","byteString","createBlob","data","BlobBuilder","window","WebKitBlobBuilder","MozBlobBuilder","MSBlobBuilder","blobBuilder","append","getBlob","Blob","intArray","mimeString","split","indexOf","atob","decodeURI","ArrayBuffer","length","Uint8Array","character","charCodeAt","log","message","level","console","isObject","variable","Object","prototype","toString","call","isFunction","isArray","value","buffer","constructor","isItemList","maybeItemList","isNodeList","maybeNodeList","item","namedItem","isString","maybeString","trimStr","string","String","trim","format","str","args","Array","slice","arguments","newStr","nextIdxToReplace","strBefore","substring","strAfter","isFile","maybeFile","File","isFileList","maybeFileList","FileList","isFileOrInput","maybeFileOrInput","isInput","maybeInput","notFile","evaluateType","normalizedType","toLowerCase","HTMLInputElement","tagName","isBlob","maybeBlob","isXhrUploadSupported","input","document","createElement","multiple","FormData","createXhrInstance","upload","XMLHttpRequest","ActiveXObject","error","isFolderDropSupported","dataTransfer","items","webkitGetAsEntry","isFileChunkingSupported","androidStock","webkitSlice","mozSlice","sliceBlob","fileOrBlob","start","end","slicer","arrayBufferToHex","bytesAsHex","bytes","byt","byteAsHexStr","readBlobToHex","blob","startOffset","initialBlob","fileReader","FileReader","promise","Promise","onload","success","onerror","failure","readAsArrayBuffer","second","extendNested","prop","override","target","sourceFn","super_","source","srcPropName","srcPropVal","arr","elt","from","len","hasOwnProperty","getUniqueId","c","r","random","v","ie","navigator","userAgent","ie7","ie8","ie10","ie11","edge","safari","vendor","chrome","opera","firefox","windows","platform","android","ios6","ios","ios7","ios8","ios800","iosChrome","iosSafari","iosSafariWebView","preventDefault","e","returnValue","toElement","div","html","innerHTML","iterableItem","callback","keyOrIndex","retVal","Storage","key","getItem","charAt","bind","oldFunc","context","newArgs","concat","apply","obj2url","obj","temp","prefixDone","uristrings","prefix","add","nextObj","i","nextTemp","encodeURIComponent","join","obj2FormData","formData","arrayKeyName","obj2Inputs","form","setAttribute","appendChild","parseJson","json","JSON","parse","eval","getExtension","filename","extIdx","lastIndexOf","substr","getFilename","blobOrFileInput","fileName","DisposeSupport","disposers","dispose","disposer","shift","addDisposer","disposeFunction","define","amd","module","exports","version","supportedFeatures","supportsUploading","supportsUploadingBlobs","supportsFileDrop","supportsAjaxFileUploading","supportsFolderDrop","supportsChunking","supportsResume","supportsUploadViaPaste","supportsUploadCors","supportsDeleteFileXdr","supportsDeleteFileCorsXhr","supportsDeleteFileCors","supportsFolderSelection","supportsImagePreviews","supportsUploadProgress","testSupportsFileInputElement","supported","tempInput","disabled","ex","isChrome21OrHigher","match","isChrome14OrHigher","isCrossOriginXhrSupported","xhr","withCredentials","isXdrSupported","XDomainRequest","isCrossOriginAjaxSupported","isFolderSelectionSupported","webkitdirectory","isLocalStorageSupported","localStorage","setItem","isDragAndDropSupported","span","postMessage","ajaxUploading","blobUploading","canDetermineSize","chunking","deleteFileCors","deleteFileCorsXdr","deleteFileCorsXhr","dialogElement","HTMLDialogElement","fileDrop","folderDrop","folderSelection","imagePreviews","imageValidation","itemSizeValidation","pause","progressBar","resume","scaling","tiffPreviews","unlimitedScaledImageSize","uploading","uploadCors","uploadCustomHeaders","uploadNonMultipart","uploadViaPaste","isGenericPromise","maybePromise","then","successArgs","failureArgs","successCallbacks","failureCallbacks","doneCallbacks","state","onSuccess","onFailure","done","BlobProxy","referenceBlob","onCreate","create","UploadButton","o","self","disposeSupport","options","acceptFiles","focusClass","folders","hoverClass","ios8BrowserCrashWorkaround","onChange","title","buttonId","createInput","BUTTON_ID_ATTR_NAME","setMultiple","position","right","top","fontFamily","fontSize","margin","padding","cursor","height","overflow","direction","getInput","getButtonId","isMultiple","optInput","removeAttribute","setAcceptFiles","reset","UploadData","uploaderProxy","byUuid","byStatus","byProxyGroupId","byBatchId","getDataByIds","idOrIds","entries","id","getDataByUuids","uuids","uuid","getDataByStatus","status","statusResults","statuses","index","statusEnum","statusResultIndexes","dataIndex","addFile","spec","SUBMITTING","originalName","size","batchId","proxyGroupId","onStatusChange","retrieve","optionalFilter","setStatus","newStatus","oldStatus","byStatusOldStatusIndex","splice","uuidChanged","newUuid","oldUuid","updateName","newName","updateSize","newSize","setParentId","targetId","parentId","getIdsInProxyGroup","getIdsInBatch","SUBMITTED","REJECTED","QUEUED","CANCELED","PAUSED","UPLOADING","UPLOAD_RETRYING","UPLOAD_SUCCESSFUL","UPLOAD_FAILED","DELETE_FAILED","DELETING","DELETED","basePublicApi","addBlobs","blobDataOrArray","params","endpoint","addFiles","addInitialFiles","cannedFileList","cannedFile","_addCannedFile","_maybeHandleIos8SafariWorkaround","_storedIds","_currentBatchId","processBlob","_handleNewFile","_options","blobs","defaultName","verifiedFiles","processBlobData","blobData","processCanvas","processCanvasData","canvasData","normalizedQuality","processFileOrInput","fileOrInput","files","file","normalizeData","fileContainer","_prepareItemsForUpload","cancel","_handler","cancelAll","storedIdsCopy","storedFileId","clearStoredFiles","continueUpload","uploadData","_uploadData","enabled","getName","_uploadFile","deleteFile","_onSubmitDelete","doesExist","fileOrBlobId","isValid","drawThumbnail","fileId","imgOrCanvas","maxSize","fromServer","customResizeFunction","promiseToReturn","fileOrUrl","_imageGenerator","_thumbnailUrls","scale","getFile","container","generate","modifiedContainer","reason","getButton","_getButton","_buttonIdsForFileIds","getEndpoint","_endpointStore","get","getInProgress","getParentId","uploadDataEntry","getUploads","getResumableFilesData","getSize","getNetUploads","_netUploaded","getRemainingAllowedItems","allowedItems","_currentItemLimit","_netUploadedOrQueued","getUuid","debug","pauseUpload","_autoRetries","_retryTimeouts","_preventRetries","_buttons","button","_paramsStore","_pasteHandler","session","refreshOnReset","_refreshSessionData","_succeededSinceLastAllComplete","_failedSinceLastAllComplete","_totalProgress","retry","_manualRetry","scaleImage","specs","Scaler","setCustomHeaders","headers","_customHeadersStore","set","setDeleteFileCustomHeaders","_deleteFileCustomHeadersStore","setDeleteFileEndpoint","_deleteFileEndpointStore","setDeleteFileParams","_deleteFileParamsStore","setEndpoint","setForm","elementOrId","_updateFormSupportAndParams","setItemLimit","newItemLimit","setName","setParams","setUuid","uploadStoredFiles","_itemError","_uploadStoredFiles","basePrivateApi","sessionData","deleteFileEndpoint","deleteFileParams","thumbnailUrl","_annotateWithButtonId","associatedInput","qqButtonId","_getButtonId","_batchError","callbacks","onError","_createDeleteHandler","DeleteFileAjaxRequester","method","toUpperCase","maxConnections","uuidParamName","request","uuidName","customHeaders","paramsStore","endpointStore","cors","onDelete","_onDelete","onDeleteComplete","xhrOrXdr","isError","_onDeleteComplete","_createPasteHandler","PasteSupport","targetElement","paste","pasteReceived","_handleCheckedCallback","onPasteReceived","_handlePasteSuccess","identifier","_createStore","initialValue","_readOnlyValues_","store","catchall","perIdReadOnlyValues","readOnlyValues","copy","orig","getReadOnlyValues","includeReadOnlyValues","existing","values","addReadOnly","_createUploadDataTracker","_onUploadStatusChange","_maybeAllComplete","setTimeout","_createUploadButton","accept","validation","allowedExtensions","allowMultiple","workarounds","iosEmptyVideos","_isAllowedExtension","classes","buttonFocus","buttonHover","ios8BrowserCrash","inputName","_onInputChange","fileInputTitle","_disposeSupport","_createUploadHandler","additionalOptions","namespace","lastOnProgress","preventRetryParam","preventRetryResponseProperty","onProgress","loaded","total","_onProgress","onComplete","_onComplete","onCancel","cancelFinalizationEffort","_onCancel","onUploadPrep","_onUploadPrep","onUpload","_onUpload","onUploadChunk","chunkData","_onUploadChunk","onUploadChunkSuccess","onResume","onAutoRetry","responseJSON","_onAutoRetry","onUuidChanged","setSize","_setSize","getDataByUuid","isQueued","UploadHandlerController","_fileOrBlobRejected","_formatSize","sizeSymbols","max","toFixed","_generateExtraButtonSpecs","_extraButtonSpecs","extraButtons","extraButtonOptionEntry","extraButtonSpec","_initExtraButton","extraButtonsSpec","_defaultButtonId","buttonOrFileInputOrFile","inputs","fileInput","fileBlobOrInput","_getNotFinished","_getValidationBase","_getValidationDescriptor","fileWrapper","_getValidationDescriptors","fileWrappers","fileDescriptors","_handleCameraAccess","camera","acceptIosCamera","optionRoot","details","callbackRetVal","successParam","newFileWrapperList","actualFile","handler","_customNewFileHandler","_handleNewFileGeneric","addFileToHandler","_trackButton","fileList","extSuppliedName","extension","_initFormSupportAndParams","_formSupport","FormSupport","attachedToForm","getFormInputsAsObject","autoUpload","newAutoUpload","newEndpoint","_isDeletePossible","expected","allowXdr","allowed","valid","allowedExt","extRegex","code","maybeNameOrNames","messages","names","validationBase","extensionsForMessage","placeholderMatch","replacement","allowedExtension","formatFileName","sizeLimit","minSizeLimit","placeholder","_onBeforeManualRetry","notFinished","_onAllComplete","ios8SafariUploads","alert","unsupportedBrowserIos8Safari","_maybeParseAndSendUploadError","response","errorReason","defaultResponseError","_maybeProcessNextItemAfterOnValidateCallback","validItem","stopOnFirstInvalidFile","validationDescriptor","onValidate","_onValidateCallbackSuccess","_onValidateCallbackFailure","successful","failed","onAllComplete","_shouldAutoRetry","retryWaitPeriod","autoAttemptDelay","_onBeforeAutoRetry","itemLimit","onManualRetry","clearTimeout","storedItemIndex","expunge","fileIndex","onIndividualProgress","_onSubmit","_onSubmitCallbackSuccess","_onSubmitted","onSubmitted","_storeForLater","onSuccessCallback","additionalMandatedParams","adjustedOnSuccessCallback","onSubmitDelete","_deleteHandler","sendDelete","_onTotalProgress","onTotalProgress","_onValidateBatchCallbackFailure","_onValidateBatchCallbackSuccess","validationDescriptors","errorMessage","proposedNetFilesUploadedOrQueued","tooManyItemsError","nextIndex","_validateFileOrBlobData","_upload","onValidateBatch","_preventLeaveInProgress","event","onLeave","Session","_session","addFileRecord","refresh","_sessionRequestComplete","onSessionRequestComplete","onNewSize","enableAuto","maxAutoAttempts","formElementOrId","onSubmit","idToUpload","stillSubmitting","validityChecker","allowEmpty","ImageValidation","validate","image","errorCode","_wrapCallbacks","safeCallback","errorMsg","exception","callbackName","callbackFunc","FineUploaderBasic","disableCancelForFormUploads","filenameParam","forceMultipart","paramsInBody","totalFileSizeName","maxHeight","maxWidth","minHeight","minWidth","maybeXhr","maybeXhrOrXdr","attemptNumber","fileOrBlobData","typeError","sizeError","minSizeError","emptyError","noFilesError","maxHeightImageError","maxWidthImageError","minHeightImageError","minWidthImageError","retryFailTooManyItems","concurrent","mandatory","paramNames","partIndex","partByteOffset","chunkSize","totalFileSize","totalParts","partSize","recordsExpireIn","resuming","fileOrBlobName","sendCredentials","interceptSubmit","customResizer","sendOriginal","orient","defaultType","defaultQuality","failureText","includeExif","sizes","ImageGenerator","_scaler","handleNewFile","TotalProgress","entry","AjaxRequester","shouldParamsBeInQueryString","queue","requestData","acceptHeader","validMethods","contentType","mandatedParams","allowXRequestedWithAndCacheControl","successfulResponseCodes","DELETE","PATCH","POST","PUT","GET","onSend","isSimpleMethod","containsNonSimpleHeaders","containsNonSimple","header","isXdr","getCorsAjaxTransport","ontimeout","onprogress","getXhrOrXdr","suppliedXhr","dequeue","nextId","sendRequest","xdrError","isResponseSuccessful","getParams","onDemandParams","additionalParams","optXhr","payload","url","createUrl","additionalQueryParams","getXdrLoadHandler","getXdrErrorHandler","onreadystatechange","getXhrReadyStateChangeHandler","registerForUploadProgress","open","setHeaders","send","stringify","addToPath","readyState","lengthComputable","onDemandHeaders","additionalHeaders","allHeaders","setRequestHeader","responseCode","prepareToSend","initTransport","path","cacheBuster","withPath","appendToPath","withParams","withQueryParams","_additionalQueryParams_","withHeaders","withPayload","thePayload","withCacheBuster","qqtimestamp","Date","getTime","canceled","UploadHandler","proxy","fileState","fileItem","onCancelRetVal","getThirdPartyFileId","_getFileState","_setThirdPartyFileId","thirdPartyFileId","_wasCanceled","controller","chunkingPossible","concurrentChunkingPossible","preventRetryResponse","chunked","chunkIdx","_getChunkData","attemptingResume","chunkProgress","_getChunkDataForCallback","finalize","finalizeChunks","normaizedResponse","normalizeResponse","_maybeDeletePersistedChunkData","cleanup","handleFailure","clearCachedChunk","responseToReport","inProgressIdx","inProgress","remaining","unshift","ignoreFailure","keys","_getXhrs","ckid","ckXhr","abort","_cancelled","moveInProgressToRemaining","connectionManager","free","hasMoreParts","nextPart","nextIdx","_getTotalChunks","reevaluateChunking","sendNext","inProgressChunks","available","uploadChunk","inProgressChunkIdx","_maybePersistChunkedState","clearXhr","_open","_openChunks","_waiting","openChunkEntriesCount","openChunksCount","openChunkIndexes","dontAllowNext","allowNext","waitingIndex","connectionsIndex","getProxyOrBlob","getWaitingOrConnected","waitingOrConnected","chunks","parseInt","isUsingConnection","pop","openChunksEntry","simple","uploadFile","maybeNewUuid","_clearXhrs","getProxy","initHandler","handlerType","traditional","handlerModuleSubtype","_removeExpiredChunkingRecords","isDeferredEligibleForUpload","maybeDefer","generatedBlob","updateBlob","maybeSendDeferredFiles","errorResponse","idsInGroup","uploadedThisId","idInGroup","now","originalResponse","_shouldChunkThisFile","blobToUpload","cancelRetVal","isProxied","isResumable","WindowReceiveMessage","callbackWrapperDetachers","receiveMessage","onMessageCallbackWrapper","stopReceivingMessages","detacher","FormUploadHandler","formHandlerInstanceId","onloadCallbacks","detachLoadEvents","postMessageCallbackTimers","isCors","corsMessageReceiver","expungeFile","iframe","getElementById","_getIframeName","getFileIdForIframeName","iframeName","initIframeForUpload","body","registerPostMessageCallback","_parseJsonResponse","onloadCallback","_detachLoadEvent","_attachLoadEvent","responseDescriptor","contentDocument","_createIframe","_initFormForUpload","targetName","innerHtmlOrMessage","XhrUploadHandler","chunkFiles","resumeEnabled","xhrId","ajaxRequester","_getAjaxRequester","blobOrProxy","_initTempState","_maybePrepareForResume","cachedChunks","tempState","xhrs","ajaxRequesters","responseParser","lastChunkIdx","_getXhr","resumableFilesData","_iterateResumeRecords","notResumable","optInProgress","optRemaining","reverse","paused","totalChunks","parts","newBlob","chunkId","_createXhr","optChunkIdx","_registerXhr","chunkIndex","fileSize","startBytes","endBytes","part","count","startByte","endByte","_getLocalStorageId","formatVersion","_getMimeType","_getPersistableData","ceil","_markNotResumable","localStorageId","removeItem","persistedData","lastUpdated","_registerProgressHandler","progressCalculator","totalSuccessfullyLoadedForFile","loadedForRequest","totalForRequest","estActualChunkLoaded","totalLoadedForFile","chunkLoaded","optAjaxRequester","xhrsId","expirationDays","expirationDate","setDate","getDate","requester","getMandatedParams","_method","detectSubsampling","img","iw","naturalWidth","ih","naturalHeight","ctx","width","getContext","drawImage","getImageData","detectVerticalSquash","sy","ey","py","alpha","ratio","renderImageToDataURL","doSquash","renderImageToCanvas","maybeCalculateDownsampledDimensions","maxPixels","origHeight","origWidth","newHeight","sqrt","newWidth","modifiedDimensions","save","resize","renderImageToCanvasWithCustomResizer","imageHeight","imageWidth","orientation","targetHeight","targetWidth","transformCoordinate","d","tmpCanvas","vertSquashRatio","dw","dh","dy","tmpCtx","sx","dx","clearRect","restore","qqImageRendered","resizeInfo","sourceCanvas","sourceCanvasContext","targetCanvas","translate","rotate","PI","MegaPixImage","srcImage","errorCallback","Image","URL","createObjectURL","webkitURL","src","listeners","imageLoadListeners","render","imgWidth","imgHeight","opt","optionsKey","optionsValue","oldTargetSrc","onrender","isImg","el","isCanvas","isImgCorsSupported","crossOrigin","isCanvasSupported","determineMimeOfFileName","nameWithPath","pathSegments","isCrossOrigin","targetAnchor","targetProtocol","targetHostname","targetPort","href","protocol","port","hostname","location","registerImgLoadListeners","registerCanvasDrawImageListener","registerThumbnailRenderedListener","registered","draw","drawPreview","Identify","megapixErrorHandler","isPreviewable","dummyExif","exif","Exif","mpImg","Orientation","failureMsg","drawOnCanvasOrImgFromUrl","canvasOrImg","tempImg","tempImgRender","rendered","drawOnImgFromUrlWithCssScaling","drawFromUrl","fileBlobOrUrl","_testing","TAG_IDS","TAG_INFO","274","parseLittleEndian","hex","pow","seekToApp1","offset","theOffset","thePromise","segmentLength","getApp1Offset","isLittleEndian","app1Start","getDirEntryCount","littleEndian","getIfd","dirEntries","getDirEntries","ifdHex","getTagValues","TAG_VAL_OFFSET","tagsToFind","vals","idHex","tagsToFindIdx","tagValHex","tagValLength","parser","onParseFailure","app1Offset","dirEntryCount","tagValues","isIdentifiable","magicBytes","questionableBytes","identifiable","magicBytesEntries","magicBytesArrayEntry","previewable","isPreviewableSync","PREVIEWABLE_MIME_TYPES","fileMime","isRecognizedImage","image/jpeg","image/gif","image/png","image/bmp","image/tiff","hasNonZeroLimits","limits","atLeastOne","limit","getWidthHeight","sizeDetermination","getFailingLimit","dimensions","failingLimit","limitName","limitValue","limitMatcher","dimensionPropName","actualValue","validationEffort","isJsonResponseValid","handleFileItems","fileItems","someItemsIgnored","err","refreshEffort","refreshCompleteCallback","requesterOptions","SessionAjaxRequester","queryServer","responseText","includeOriginal","failedToScaleText","_getSortedSizes","getFileRecords","originalFileUuid","originalFileName","originalBlobOrBlobData","records","originalBlob","sizeRecord","outputType","_determineOutputType","requestedType","refType","_getName","_generateScaledImage","failedText","api","scaledIds","originalId","record","blobSize","scaledId","qqparentuuid","qqparentsize","param","scalingEffort","scalingOptions","scaler","referenceType","scaledVersionProperties","startOfExt","versionType","scaledName","scaledExt","nameAppendage","sort","a","b","sourceFile","imageGenerator","scaledImageDataUri","signalSuccess","_insertExifHeader","scaledImageDataUriWithExif","originalImage","reader","insertionEffort","originalImageDataUri","ExifRestorer","readAsDataURL","_dataUriToBlob","_createBlob","KEY_STR","encode64","output","chr1","chr2","chr3","enc1","enc2","enc3","enc4","isNaN","origFileBase64","resizedFileBase64","expectedBase64Header","rawImage","decode64","segments","slice2Segments","exifManipulation","exifArray","getExifArray","newImageArray","insertExif","aBuffer","seg","x","imageData","buf","separatePoint","mae","ato","array","rawImageArray","head","endPoint","base64test","perFileProgress","totalLoaded","totalSize","lastLoadedSent","lastTotalSent","callbackProxy","noRetryableFiles","retryable","none","failedId","updateTotalProgress","onNew","newLoaded","newTotal","oldLoaded","oldTotal","detachPasteHandler","isImage","registerPasteHandler","clipboardData","getAsFile","unregisterPasteHandler","startUpload","formEl","_form2Obj","determineNewEndpoint","validateForm","nativeSubmit","checkValidity","maybeUploadOnSubmit","submit","determineFormEl","notIrrelevantType","irrelevantTypes","radioOrCheckbox","ignoreValue","checked","selectValue","select","selected","elements","getIframeContentJson","doc","innerHtml","contentWindow","nodeValue","createForm","responseFromMessage","multipart","addChunkingSpecificParams","allChunksDoneRequester","AllChunksDoneAjaxRequester","createReadyStateChangedHandler","onUploadOrChunkComplete","getChunksCompleteParams","isErrorUploadResponse","parseResponse","sendChunksCompleteRequest","complete","setParamsAndGetEntityToSend","setUploadHeaders","extraHeaders","toSend","promises","endpointHandler","DragAndDrop","HIDE_ZONES_EVENT_NAME","HIDE_BEFORE_ENTER_ATTR","uploadDropZones","droppedFiles","dropZoneElements","allowMultipleItems","dropActive","uploadDroppedFiles","uploadDropZone","filesAsArray","dropLog","dropDisabled","processingDroppedFilesComplete","getElement","traverseFileTree","parseEntryPromise","fullPath","indexOfNameInFullPath","qqPath","fileError","isDirectory","getFilesInDirectory","allEntriesRead","entriesLeft","readFailure","accumEntries","existingPromise","dirReader","createReader","readEntries","readSuccess","newEntries","handleDataTransfer","pendingFolderPromises","handleDataTransferPromise","processingDroppedFiles","dropError","setupDropzone","dropArea","dropZone","UploadDropZone","onEnter","stopPropagation","onLeaveNotDescendants","onDrop","isFileDrag","dragEvent","fileDrag","types","leavingDocumentOut","relatedTarget","y","setupDragDrop","dropZones","maybeHideDropZones","HTMLElement","setupExtraDropzone","removeDropzone","dzs","targetEl","errorSpecifics","preventDrop","dropOutsideDisabled","dragoverShouldBeCanceled","disableDropOutside","dropEffect","isValidFileDrag","effectTest","dt","isSafari","effectAllowed","isOrSetDropDisabled","isDisabled","triggerHidezonesEvent","hideZonesEvent","triggerUsingOldApi","createEvent","initEvent","CustomEvent","dispatchEvent","attachEvents","effect","elementFromPoint","clientX","clientY","uiPublicApi","_parent","_templating","addCacheToDom","clearFiles","addExtraDropzone","_dnd","removeExtraDropzone","getItemByFileId","isHiddenForever","getFileContainer","_setupDragAndDrop","_totalFilesInBatch","_filesInBatchAddedToUi","_setupClickAndEditEventHandlers","formattedFilename","updateFilename","uploadPaused","continued","uploadContinued","getId","fileContainerOrChildEl","getFileId","getDropTarget","qqDropTarget","uiPrivateApi","_removeFileItem","removeFile","_fileButtonsClickHandler","FileButtonsClickHandler","_bindFileButtonsClickEvent","_focusinEventSupported","_isEditFilenameEnabled","_filenameClickHandler","_bindFilenameClickEvent","_filenameInputFocusInHandler","_bindFilenameInputFocusInEvent","_filenameInputFocusHandler","_bindFilenameInputFocusEvent","dragAndDrop","extraDropzones","templating","defaultDropZone","getDropZone","showDropProcessing","hideDropProcessing","errorData","lvl","onDeleteFile","onRetry","onPause","onContinue","onGetName","isEditFilenamePossible","FilenameClickHandler","FilenameInputFocusHandler","_filenameEditHandler","onGetUploadStatus","onSetName","onEditingStatusChange","isEditing","qqInput","getEditInput","qqFileContainer","hideFilename","hideEditIcon","showFilename","showEditIcon","markFilenameEditable","hideRetry","setStatusText","_classes","retrying","hidePause","FilenameInputFocusInHandler","hideSpinner","resetTotalProgress","reportDirectoryPaths","qqpath","_addToList","addHandler","updateProgress","hideCancel","hideProgress","waitingForResponse","_displayFileSize","parentRetVal","completeUpload","_markFileAsSuccessful","fail","showCancel","isRetryPossible","showRetry","_controlFailureTextDisplay","newResult","showDeleteButton","_maybeUpdateThumbnail","showSpinner","allowPause","retryNumForDisplay","maxAuto","retryNote","_showCancelLink","showAutoRetryNote","autoRetryNote","resetProgress","_onSubmitDeleteSuccess","forceConfirm","_showDeleteConfirm","_sendDeleteRequest","deletingFailedText","hideDeleteButton","deletingStatusText","confirmMessage","deleteRequestArgs","showConfirm","canned","prependData","prependIndex","dontDisplay","hideScaled","prependFiles","disableCancel","_handledProxyGroup","_clearList","addFileToCache","updateThumbnail","thumbnails","generatePreview","fileSizeOnSubmit","loadedSize","sizeForDisplay","_formatProgress","uploadedSize","formatProgress","mode","responseProperty","failureReason","failedUploadTextDisplay","failUpload","enableTooltip","_showTooltip","showMessage","_setupPastePrompt","namePromptMessage","defaultVal","showPrompt","fileStatus","placeholders","waitUntilResponse","FineUploader","listElement","template","editable","tooManyFilesError","unsupportedBrowser","promptForName","maxCount","notAvailablePath","waitingPath","timeBetweenThumbs","hasDialog","showDialog","confirm","defaultValue","prompt","Templating","templateIdOrEl","containerEl","fileContainerEl","maxThumbs","waitUntilUpdate","thumbnailNotAvailable","waitingForThumbnail","renderFailure","FILE_ID_ATTR","FILE_CLASS_PREFIX","THUMBNAIL_MAX_SIZE_ATTR","THUMBNAIL_SERVER_SCALE_ATTR","HIDE_DROPZONE_ATTR","DROPZPONE_TEXT_ATTR","IN_PROGRESS_CLASS","HIDDEN_FOREVER_CLASS","fileBatch","content","createDocumentFragment","map","isCancelDisabled","generatedThumbnails","thumbnailQueueMonitorRunning","thumbGenerationQueue","thumbnailMaxSize","selectorClasses","alertDialog","dialogCancelButton","confirmDialog","dialogMessage","dialogOkButton","promptDialog","uploader","drop","list","progressBarContainer","totalProgressBarContainer","totalProgressBar","spinner","continueButton","deleteButton","statusText","editFilenameInput","editNameIcon","dropText","dropProcessing","dropProcessingSpinner","thumbnail","previewGeneration","cachedThumbnailNotAvailableImg","cachedWaitingForThumbnailImg","isEditElementsExist","isRetryElementExist","templateHtml","showThumbnails","serverScale","cacheThumbnailPlaceholders","notAvailableUrl","waitingUrl","updatedImg","displayWaitingImg","waitingImgPlacement","maybeScalePlaceholderViaCss","show","generateNewPreview","getThumbnail","qqThumbnailId","maybeSetDisplayNotAvailableImg","generateNextQueuedPreview","queuedThumbRequest","update","processUpdateQueuedPreviewRequest","processNewQueuedPreviewRequest","getCancel","getTemplateEl","getContinue","getDialog","getDelete","getDropProcessing","getEditIcon","getPause","getProgress","getRetry","getSpinner","cssClass","previewing","notAvailableImgPlacement","parseAndGetTemplate","scriptEl","scriptHtml","fileListNode","tempTemplateEl","fileListHtml","defaultButton","dropTextEl","uploaderEl","fileTemplate","prependFile","parentEl","beforeEl","optFileOrBlob","relatedThumbnailId","useCachedPreview","showWaitingImg","setProgressBarWidth","percent","bar","progressBarSelector","targetThumbnailId","cachedThumbnailId","targetThumbnail","cachedThumbnail","hideTotalProgress","cantRenderEl","prependInfo","hideForever","batch","fileEl","fileNameEl","thumb","waitingImg","currentNode","getFileList","filenameEl","isFileName","icon","isEditIcon","isEditInput","isCancel","allowContinueButton","isPause","isContinueButton","isDeleteButton","isRetry","textEl","dialog","messageEl","inputEl","cancelBtn","okBtn","closeHandler","cancelClickHandler","okClickHandler","close","showModal","UiEventHandler","s","protectedApi","eventType","attachTo","onHandled","srcElement","getFileIdFromItem","qqFileId","getDisposeSupport","inheritedInternalApi","buttonHandlers","examineEvent","buttonType","firstLetterCapButtonType","handleFilenameEdit","FilenameEditHandler","handleInputFocus","getFilenameSansExtension","filenameSansExt","getOriginalExtension","origName","handleNameUpdate","newFilenameInputEl","origExtension","registerInputBlurHandler","registerInputEnterKeyHandler","keyCode","which","focusInput","focus"],"mappings":"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","file":"fine-uploader.js","sourcesContent":[null,"/*globals window, navigator, document, FormData, File, HTMLInputElement, XMLHttpRequest, Blob, Storage, ActiveXObject */\n/* jshint -W079 */\nvar qq = function(element) {\n \"use strict\";\n\n return {\n hide: function() {\n element.style.display = \"none\";\n return this;\n },\n\n /** Returns the function which detaches attached event */\n attach: function(type, fn) {\n if (element.addEventListener) {\n element.addEventListener(type, fn, false);\n } else if (element.attachEvent) {\n element.attachEvent(\"on\" + type, fn);\n }\n return function() {\n qq(element).detach(type, fn);\n };\n },\n\n detach: function(type, fn) {\n if (element.removeEventListener) {\n element.removeEventListener(type, fn, false);\n } else if (element.attachEvent) {\n element.detachEvent(\"on\" + type, fn);\n }\n return this;\n },\n\n contains: function(descendant) {\n // The [W3C spec](http://www.w3.org/TR/domcore/#dom-node-contains)\n // says a `null` (or ostensibly `undefined`) parameter\n // passed into `Node.contains` should result in a false return value.\n // IE7 throws an exception if the parameter is `undefined` though.\n if (!descendant) {\n return false;\n }\n\n // compareposition returns false in this case\n if (element === descendant) {\n return true;\n }\n\n if (element.contains) {\n return element.contains(descendant);\n } else {\n /*jslint bitwise: true*/\n return !!(descendant.compareDocumentPosition(element) & 8);\n }\n },\n\n /**\n * Insert this element before elementB.\n */\n insertBefore: function(elementB) {\n elementB.parentNode.insertBefore(element, elementB);\n return this;\n },\n\n remove: function() {\n element.parentNode.removeChild(element);\n return this;\n },\n\n /**\n * Sets styles for an element.\n * Fixes opacity in IE6-8.\n */\n css: function(styles) {\n /*jshint eqnull: true*/\n if (element.style == null) {\n throw new qq.Error(\"Can't apply style to node as it is not on the HTMLElement prototype chain!\");\n }\n\n /*jshint -W116*/\n if (styles.opacity != null) {\n if (typeof element.style.opacity !== \"string\" && typeof (element.filters) !== \"undefined\") {\n styles.filter = \"alpha(opacity=\" + Math.round(100 * styles.opacity) + \")\";\n }\n }\n qq.extend(element.style, styles);\n\n return this;\n },\n\n hasClass: function(name, considerParent) {\n var re = new RegExp(\"(^| )\" + name + \"( |$)\");\n return re.test(element.className) || !!(considerParent && re.test(element.parentNode.className));\n },\n\n addClass: function(name) {\n if (!qq(element).hasClass(name)) {\n element.className += \" \" + name;\n }\n return this;\n },\n\n removeClass: function(name) {\n var re = new RegExp(\"(^| )\" + name + \"( |$)\");\n element.className = element.className.replace(re, \" \").replace(/^\\s+|\\s+$/g, \"\");\n return this;\n },\n\n getByClass: function(className, first) {\n var candidates,\n result = [];\n\n if (first && element.querySelector) {\n return element.querySelector(\".\" + className);\n }\n else if (element.querySelectorAll) {\n return element.querySelectorAll(\".\" + className);\n }\n\n candidates = element.getElementsByTagName(\"*\");\n\n qq.each(candidates, function(idx, val) {\n if (qq(val).hasClass(className)) {\n result.push(val);\n }\n });\n return first ? result[0] : result;\n },\n\n getFirstByClass: function(className) {\n return qq(element).getByClass(className, true);\n },\n\n children: function() {\n var children = [],\n child = element.firstChild;\n\n while (child) {\n if (child.nodeType === 1) {\n children.push(child);\n }\n child = child.nextSibling;\n }\n\n return children;\n },\n\n setText: function(text) {\n element.innerText = text;\n element.textContent = text;\n return this;\n },\n\n clearText: function() {\n return qq(element).setText(\"\");\n },\n\n // Returns true if the attribute exists on the element\n // AND the value of the attribute is NOT \"false\" (case-insensitive)\n hasAttribute: function(attrName) {\n var attrVal;\n\n if (element.hasAttribute) {\n\n if (!element.hasAttribute(attrName)) {\n return false;\n }\n\n /*jshint -W116*/\n return (/^false$/i).exec(element.getAttribute(attrName)) == null;\n }\n else {\n attrVal = element[attrName];\n\n if (attrVal === undefined) {\n return false;\n }\n\n /*jshint -W116*/\n return (/^false$/i).exec(attrVal) == null;\n }\n }\n };\n};\n\n(function() {\n \"use strict\";\n\n qq.canvasToBlob = function(canvas, mime, quality) {\n return qq.dataUriToBlob(canvas.toDataURL(mime, quality));\n };\n\n qq.dataUriToBlob = function(dataUri) {\n var arrayBuffer, byteString,\n createBlob = function(data, mime) {\n var BlobBuilder = window.BlobBuilder ||\n window.WebKitBlobBuilder ||\n window.MozBlobBuilder ||\n window.MSBlobBuilder,\n blobBuilder = BlobBuilder && new BlobBuilder();\n\n if (blobBuilder) {\n blobBuilder.append(data);\n return blobBuilder.getBlob(mime);\n }\n else {\n return new Blob([data], {type: mime});\n }\n },\n intArray, mimeString;\n\n // convert base64 to raw binary data held in a string\n if (dataUri.split(\",\")[0].indexOf(\"base64\") >= 0) {\n byteString = atob(dataUri.split(\",\")[1]);\n }\n else {\n byteString = decodeURI(dataUri.split(\",\")[1]);\n }\n\n // extract the MIME\n mimeString = dataUri.split(\",\")[0]\n .split(\":\")[1]\n .split(\";\")[0];\n\n // write the bytes of the binary string to an ArrayBuffer\n arrayBuffer = new ArrayBuffer(byteString.length);\n intArray = new Uint8Array(arrayBuffer);\n qq.each(byteString, function(idx, character) {\n intArray[idx] = character.charCodeAt(0);\n });\n\n return createBlob(arrayBuffer, mimeString);\n };\n\n qq.log = function(message, level) {\n if (window.console) {\n if (!level || level === \"info\") {\n window.console.log(message);\n }\n else\n {\n if (window.console[level]) {\n window.console[level](message);\n }\n else {\n window.console.log(\"<\" + level + \"> \" + message);\n }\n }\n }\n };\n\n qq.isObject = function(variable) {\n return variable && !variable.nodeType && Object.prototype.toString.call(variable) === \"[object Object]\";\n };\n\n qq.isFunction = function(variable) {\n return typeof (variable) === \"function\";\n };\n\n /**\n * Check the type of a value. Is it an \"array\"?\n *\n * @param value value to test.\n * @returns true if the value is an array or associated with an `ArrayBuffer`\n */\n qq.isArray = function(value) {\n return Object.prototype.toString.call(value) === \"[object Array]\" ||\n (value && window.ArrayBuffer && value.buffer && value.buffer.constructor === ArrayBuffer);\n };\n\n // Looks for an object on a `DataTransfer` object that is associated with drop events when utilizing the Filesystem API.\n qq.isItemList = function(maybeItemList) {\n return Object.prototype.toString.call(maybeItemList) === \"[object DataTransferItemList]\";\n };\n\n // Looks for an object on a `NodeList` or an `HTMLCollection`|`HTMLFormElement`|`HTMLSelectElement`\n // object that is associated with collections of Nodes.\n qq.isNodeList = function(maybeNodeList) {\n return Object.prototype.toString.call(maybeNodeList) === \"[object NodeList]\" ||\n // If `HTMLCollection` is the actual type of the object, we must determine this\n // by checking for expected properties/methods on the object\n (maybeNodeList.item && maybeNodeList.namedItem);\n };\n\n qq.isString = function(maybeString) {\n return Object.prototype.toString.call(maybeString) === \"[object String]\";\n };\n\n qq.trimStr = function(string) {\n if (String.prototype.trim) {\n return string.trim();\n }\n\n return string.replace(/^\\s+|\\s+$/g, \"\");\n };\n\n /**\n * @param str String to format.\n * @returns {string} A string, swapping argument values with the associated occurrence of {} in the passed string.\n */\n qq.format = function(str) {\n\n var args = Array.prototype.slice.call(arguments, 1),\n newStr = str,\n nextIdxToReplace = newStr.indexOf(\"{}\");\n\n qq.each(args, function(idx, val) {\n var strBefore = newStr.substring(0, nextIdxToReplace),\n strAfter = newStr.substring(nextIdxToReplace + 2);\n\n newStr = strBefore + val + strAfter;\n nextIdxToReplace = newStr.indexOf(\"{}\", nextIdxToReplace + val.length);\n\n // End the loop if we have run out of tokens (when the arguments exceed the # of tokens)\n if (nextIdxToReplace < 0) {\n return false;\n }\n });\n\n return newStr;\n };\n\n qq.isFile = function(maybeFile) {\n return window.File && Object.prototype.toString.call(maybeFile) === \"[object File]\";\n };\n\n qq.isFileList = function(maybeFileList) {\n return window.FileList && Object.prototype.toString.call(maybeFileList) === \"[object FileList]\";\n };\n\n qq.isFileOrInput = function(maybeFileOrInput) {\n return qq.isFile(maybeFileOrInput) || qq.isInput(maybeFileOrInput);\n };\n\n qq.isInput = function(maybeInput, notFile) {\n var evaluateType = function(type) {\n var normalizedType = type.toLowerCase();\n\n if (notFile) {\n return normalizedType !== \"file\";\n }\n\n return normalizedType === \"file\";\n };\n\n if (window.HTMLInputElement) {\n if (Object.prototype.toString.call(maybeInput) === \"[object HTMLInputElement]\") {\n if (maybeInput.type && evaluateType(maybeInput.type)) {\n return true;\n }\n }\n }\n if (maybeInput.tagName) {\n if (maybeInput.tagName.toLowerCase() === \"input\") {\n if (maybeInput.type && evaluateType(maybeInput.type)) {\n return true;\n }\n }\n }\n\n return false;\n };\n\n qq.isBlob = function(maybeBlob) {\n if (window.Blob && Object.prototype.toString.call(maybeBlob) === \"[object Blob]\") {\n return true;\n }\n };\n\n qq.isXhrUploadSupported = function() {\n var input = document.createElement(\"input\");\n input.type = \"file\";\n\n return (\n input.multiple !== undefined &&\n typeof File !== \"undefined\" &&\n typeof FormData !== \"undefined\" &&\n typeof (qq.createXhrInstance()).upload !== \"undefined\");\n };\n\n // Fall back to ActiveX is native XHR is disabled (possible in any version of IE).\n qq.createXhrInstance = function() {\n if (window.XMLHttpRequest) {\n return new XMLHttpRequest();\n }\n\n try {\n return new ActiveXObject(\"MSXML2.XMLHTTP.3.0\");\n }\n catch (error) {\n qq.log(\"Neither XHR or ActiveX are supported!\", \"error\");\n return null;\n }\n };\n\n qq.isFolderDropSupported = function(dataTransfer) {\n return dataTransfer.items &&\n dataTransfer.items.length > 0 &&\n dataTransfer.items[0].webkitGetAsEntry;\n };\n\n qq.isFileChunkingSupported = function() {\n return !qq.androidStock() && //Android's stock browser cannot upload Blobs correctly\n qq.isXhrUploadSupported() &&\n (File.prototype.slice !== undefined || File.prototype.webkitSlice !== undefined || File.prototype.mozSlice !== undefined);\n };\n\n qq.sliceBlob = function(fileOrBlob, start, end) {\n var slicer = fileOrBlob.slice || fileOrBlob.mozSlice || fileOrBlob.webkitSlice;\n\n return slicer.call(fileOrBlob, start, end);\n };\n\n qq.arrayBufferToHex = function(buffer) {\n var bytesAsHex = \"\",\n bytes = new Uint8Array(buffer);\n\n qq.each(bytes, function(idx, byt) {\n var byteAsHexStr = byt.toString(16);\n\n if (byteAsHexStr.length < 2) {\n byteAsHexStr = \"0\" + byteAsHexStr;\n }\n\n bytesAsHex += byteAsHexStr;\n });\n\n return bytesAsHex;\n };\n\n qq.readBlobToHex = function(blob, startOffset, length) {\n var initialBlob = qq.sliceBlob(blob, startOffset, startOffset + length),\n fileReader = new FileReader(),\n promise = new qq.Promise();\n\n fileReader.onload = function() {\n promise.success(qq.arrayBufferToHex(fileReader.result));\n };\n\n fileReader.onerror = promise.failure;\n\n fileReader.readAsArrayBuffer(initialBlob);\n\n return promise;\n };\n\n qq.extend = function(first, second, extendNested) {\n qq.each(second, function(prop, val) {\n if (extendNested && qq.isObject(val)) {\n if (first[prop] === undefined) {\n first[prop] = {};\n }\n qq.extend(first[prop], val, true);\n }\n else {\n first[prop] = val;\n }\n });\n\n return first;\n };\n\n /**\n * Allow properties in one object to override properties in another,\n * keeping track of the original values from the target object.\n *\n * Note that the pre-overriden properties to be overriden by the source will be passed into the `sourceFn` when it is invoked.\n *\n * @param target Update properties in this object from some source\n * @param sourceFn A function that, when invoked, will return properties that will replace properties with the same name in the target.\n * @returns {object} The target object\n */\n qq.override = function(target, sourceFn) {\n var super_ = {},\n source = sourceFn(super_);\n\n qq.each(source, function(srcPropName, srcPropVal) {\n if (target[srcPropName] !== undefined) {\n super_[srcPropName] = target[srcPropName];\n }\n\n target[srcPropName] = srcPropVal;\n });\n\n return target;\n };\n\n /**\n * Searches for a given element (elt) in the array, returns -1 if it is not present.\n */\n qq.indexOf = function(arr, elt, from) {\n if (arr.indexOf) {\n return arr.indexOf(elt, from);\n }\n\n from = from || 0;\n var len = arr.length;\n\n if (from < 0) {\n from += len;\n }\n\n for (; from < len; from += 1) {\n if (arr.hasOwnProperty(from) && arr[from] === elt) {\n return from;\n }\n }\n return -1;\n };\n\n //this is a version 4 UUID\n qq.getUniqueId = function() {\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, function(c) {\n /*jslint eqeq: true, bitwise: true*/\n var r = Math.random() * 16 | 0, v = c == \"x\" ? r : (r & 0x3 | 0x8);\n return v.toString(16);\n });\n };\n\n //\n // Browsers and platforms detection\n qq.ie = function() {\n return navigator.userAgent.indexOf(\"MSIE\") !== -1 ||\n navigator.userAgent.indexOf(\"Trident\") !== -1;\n };\n\n qq.ie7 = function() {\n return navigator.userAgent.indexOf(\"MSIE 7\") !== -1;\n };\n\n qq.ie8 = function() {\n return navigator.userAgent.indexOf(\"MSIE 8\") !== -1;\n };\n\n qq.ie10 = function() {\n return navigator.userAgent.indexOf(\"MSIE 10\") !== -1;\n };\n\n qq.ie11 = function() {\n return qq.ie() && navigator.userAgent.indexOf(\"rv:11\") !== -1;\n };\n\n qq.edge = function() {\n return navigator.userAgent.indexOf(\"Edge\") >= 0;\n };\n\n qq.safari = function() {\n return navigator.vendor !== undefined && navigator.vendor.indexOf(\"Apple\") !== -1;\n };\n\n qq.chrome = function() {\n return navigator.vendor !== undefined && navigator.vendor.indexOf(\"Google\") !== -1;\n };\n\n qq.opera = function() {\n return navigator.vendor !== undefined && navigator.vendor.indexOf(\"Opera\") !== -1;\n };\n\n qq.firefox = function() {\n return (!qq.edge() && !qq.ie11() && navigator.userAgent.indexOf(\"Mozilla\") !== -1 && navigator.vendor !== undefined && navigator.vendor === \"\");\n };\n\n qq.windows = function() {\n return navigator.platform === \"Win32\";\n };\n\n qq.android = function() {\n return navigator.userAgent.toLowerCase().indexOf(\"android\") !== -1;\n };\n\n // We need to identify the Android stock browser via the UA string to work around various bugs in this browser,\n // such as the one that prevents a `Blob` from being uploaded.\n qq.androidStock = function() {\n return qq.android() && navigator.userAgent.toLowerCase().indexOf(\"chrome\") < 0;\n };\n\n qq.ios6 = function() {\n return qq.ios() && navigator.userAgent.indexOf(\" OS 6_\") !== -1;\n };\n\n qq.ios7 = function() {\n return qq.ios() && navigator.userAgent.indexOf(\" OS 7_\") !== -1;\n };\n\n qq.ios8 = function() {\n return qq.ios() && navigator.userAgent.indexOf(\" OS 8_\") !== -1;\n };\n\n // iOS 8.0.0\n qq.ios800 = function() {\n return qq.ios() && navigator.userAgent.indexOf(\" OS 8_0 \") !== -1;\n };\n\n qq.ios = function() {\n /*jshint -W014 */\n return navigator.userAgent.indexOf(\"iPad\") !== -1\n || navigator.userAgent.indexOf(\"iPod\") !== -1\n || navigator.userAgent.indexOf(\"iPhone\") !== -1;\n };\n\n qq.iosChrome = function() {\n return qq.ios() && navigator.userAgent.indexOf(\"CriOS\") !== -1;\n };\n\n qq.iosSafari = function() {\n return qq.ios() && !qq.iosChrome() && navigator.userAgent.indexOf(\"Safari\") !== -1;\n };\n\n qq.iosSafariWebView = function() {\n return qq.ios() && !qq.iosChrome() && !qq.iosSafari();\n };\n\n //\n // Events\n\n qq.preventDefault = function(e) {\n if (e.preventDefault) {\n e.preventDefault();\n } else {\n e.returnValue = false;\n }\n };\n\n /**\n * Creates and returns element from html string\n * Uses innerHTML to create an element\n */\n qq.toElement = (function() {\n var div = document.createElement(\"div\");\n return function(html) {\n div.innerHTML = html;\n var element = div.firstChild;\n div.removeChild(element);\n return element;\n };\n }());\n\n //key and value are passed to callback for each entry in the iterable item\n qq.each = function(iterableItem, callback) {\n var keyOrIndex, retVal;\n\n if (iterableItem) {\n // Iterate through [`Storage`](http://www.w3.org/TR/webstorage/#the-storage-interface) items\n if (window.Storage && iterableItem.constructor === window.Storage) {\n for (keyOrIndex = 0; keyOrIndex < iterableItem.length; keyOrIndex++) {\n retVal = callback(iterableItem.key(keyOrIndex), iterableItem.getItem(iterableItem.key(keyOrIndex)));\n if (retVal === false) {\n break;\n }\n }\n }\n // `DataTransferItemList` & `NodeList` objects are array-like and should be treated as arrays\n // when iterating over items inside the object.\n else if (qq.isArray(iterableItem) || qq.isItemList(iterableItem) || qq.isNodeList(iterableItem)) {\n for (keyOrIndex = 0; keyOrIndex < iterableItem.length; keyOrIndex++) {\n retVal = callback(keyOrIndex, iterableItem[keyOrIndex]);\n if (retVal === false) {\n break;\n }\n }\n }\n else if (qq.isString(iterableItem)) {\n for (keyOrIndex = 0; keyOrIndex < iterableItem.length; keyOrIndex++) {\n retVal = callback(keyOrIndex, iterableItem.charAt(keyOrIndex));\n if (retVal === false) {\n break;\n }\n }\n }\n else {\n for (keyOrIndex in iterableItem) {\n if (Object.prototype.hasOwnProperty.call(iterableItem, keyOrIndex)) {\n retVal = callback(keyOrIndex, iterableItem[keyOrIndex]);\n if (retVal === false) {\n break;\n }\n }\n }\n }\n }\n };\n\n //include any args that should be passed to the new function after the context arg\n qq.bind = function(oldFunc, context) {\n if (qq.isFunction(oldFunc)) {\n var args = Array.prototype.slice.call(arguments, 2);\n\n return function() {\n var newArgs = qq.extend([], args);\n if (arguments.length) {\n newArgs = newArgs.concat(Array.prototype.slice.call(arguments));\n }\n return oldFunc.apply(context, newArgs);\n };\n }\n\n throw new Error(\"first parameter must be a function!\");\n };\n\n /**\n * obj2url() takes a json-object as argument and generates\n * a querystring. pretty much like jQuery.param()\n *\n * how to use:\n *\n * `qq.obj2url({a:'b',c:'d'},'http://any.url/upload?otherParam=value');`\n *\n * will result in:\n *\n * `http://any.url/upload?otherParam=value&a=b&c=d`\n *\n * @param Object JSON-Object\n * @param String current querystring-part\n * @return String encoded querystring\n */\n qq.obj2url = function(obj, temp, prefixDone) {\n /*jshint laxbreak: true*/\n var uristrings = [],\n prefix = \"&\",\n add = function(nextObj, i) {\n var nextTemp = temp\n ? (/\\[\\]$/.test(temp)) // prevent double-encoding\n ? temp\n : temp + \"[\" + i + \"]\"\n : i;\n if ((nextTemp !== \"undefined\") && (i !== \"undefined\")) {\n uristrings.push(\n (typeof nextObj === \"object\")\n ? qq.obj2url(nextObj, nextTemp, true)\n : (Object.prototype.toString.call(nextObj) === \"[object Function]\")\n ? encodeURIComponent(nextTemp) + \"=\" + encodeURIComponent(nextObj())\n : encodeURIComponent(nextTemp) + \"=\" + encodeURIComponent(nextObj)\n );\n }\n };\n\n if (!prefixDone && temp) {\n prefix = (/\\?/.test(temp)) ? (/\\?$/.test(temp)) ? \"\" : \"&\" : \"?\";\n uristrings.push(temp);\n uristrings.push(qq.obj2url(obj));\n } else if ((Object.prototype.toString.call(obj) === \"[object Array]\") && (typeof obj !== \"undefined\")) {\n qq.each(obj, function(idx, val) {\n add(val, idx);\n });\n } else if ((typeof obj !== \"undefined\") && (obj !== null) && (typeof obj === \"object\")) {\n qq.each(obj, function(prop, val) {\n add(val, prop);\n });\n } else {\n uristrings.push(encodeURIComponent(temp) + \"=\" + encodeURIComponent(obj));\n }\n\n if (temp) {\n return uristrings.join(prefix);\n } else {\n return uristrings.join(prefix)\n .replace(/^&/, \"\")\n .replace(/%20/g, \"+\");\n }\n };\n\n qq.obj2FormData = function(obj, formData, arrayKeyName) {\n if (!formData) {\n formData = new FormData();\n }\n\n qq.each(obj, function(key, val) {\n key = arrayKeyName ? arrayKeyName + \"[\" + key + \"]\" : key;\n\n if (qq.isObject(val)) {\n qq.obj2FormData(val, formData, key);\n }\n else if (qq.isFunction(val)) {\n formData.append(key, val());\n }\n else {\n formData.append(key, val);\n }\n });\n\n return formData;\n };\n\n qq.obj2Inputs = function(obj, form) {\n var input;\n\n if (!form) {\n form = document.createElement(\"form\");\n }\n\n qq.obj2FormData(obj, {\n append: function(key, val) {\n input = document.createElement(\"input\");\n input.setAttribute(\"name\", key);\n input.setAttribute(\"value\", val);\n form.appendChild(input);\n }\n });\n\n return form;\n };\n\n /**\n * Not recommended for use outside of Fine Uploader since this falls back to an unchecked eval if JSON.parse is not\n * implemented. For a more secure JSON.parse polyfill, use Douglas Crockford's json2.js.\n */\n qq.parseJson = function(json) {\n /*jshint evil: true*/\n if (window.JSON && qq.isFunction(JSON.parse)) {\n return JSON.parse(json);\n } else {\n return eval(\"(\" + json + \")\");\n }\n };\n\n /**\n * Retrieve the extension of a file, if it exists.\n *\n * @param filename\n * @returns {string || undefined}\n */\n qq.getExtension = function(filename) {\n var extIdx = filename.lastIndexOf(\".\") + 1;\n\n if (extIdx > 0) {\n return filename.substr(extIdx, filename.length - extIdx);\n }\n };\n\n qq.getFilename = function(blobOrFileInput) {\n /*jslint regexp: true*/\n\n if (qq.isInput(blobOrFileInput)) {\n // get input value and remove path to normalize\n return blobOrFileInput.value.replace(/.*(\\/|\\\\)/, \"\");\n }\n else if (qq.isFile(blobOrFileInput)) {\n if (blobOrFileInput.fileName !== null && blobOrFileInput.fileName !== undefined) {\n return blobOrFileInput.fileName;\n }\n }\n\n return blobOrFileInput.name;\n };\n\n /**\n * A generic module which supports object disposing in dispose() method.\n * */\n qq.DisposeSupport = function() {\n var disposers = [];\n\n return {\n /** Run all registered disposers */\n dispose: function() {\n var disposer;\n do {\n disposer = disposers.shift();\n if (disposer) {\n disposer();\n }\n }\n while (disposer);\n },\n\n /** Attach event handler and register de-attacher as a disposer */\n attach: function() {\n var args = arguments;\n /*jslint undef:true*/\n this.addDisposer(qq(args[0]).attach.apply(this, Array.prototype.slice.call(arguments, 1)));\n },\n\n /** Add disposer to the collection */\n addDisposer: function(disposeFunction) {\n disposers.push(disposeFunction);\n }\n };\n };\n}());\n","/* globals define, module, global, qq */\n(function() {\n \"use strict\";\n if (typeof define === \"function\" && define.amd) {\n define(function() {\n return qq;\n });\n }\n else if (typeof module !== \"undefined\" && module.exports) {\n module.exports = qq;\n }\n else {\n global.qq = qq;\n }\n}());\n","/* globals qq */\n/**\n * Fine Uploader top-level Error container. Inherits from `Error`.\n */\n(function() {\n \"use strict\";\n\n qq.Error = function(message) {\n this.message = \"[Fine Uploader \" + qq.version + \"] \" + message;\n };\n\n qq.Error.prototype = new Error();\n}());\n","/*global qq */\nqq.version = \"5.12.0\";\n","/* globals qq */\nqq.supportedFeatures = (function() {\n \"use strict\";\n\n var supportsUploading,\n supportsUploadingBlobs,\n supportsFileDrop,\n supportsAjaxFileUploading,\n supportsFolderDrop,\n supportsChunking,\n supportsResume,\n supportsUploadViaPaste,\n supportsUploadCors,\n supportsDeleteFileXdr,\n supportsDeleteFileCorsXhr,\n supportsDeleteFileCors,\n supportsFolderSelection,\n supportsImagePreviews,\n supportsUploadProgress;\n\n function testSupportsFileInputElement() {\n var supported = true,\n tempInput;\n\n try {\n tempInput = document.createElement(\"input\");\n tempInput.type = \"file\";\n qq(tempInput).hide();\n\n if (tempInput.disabled) {\n supported = false;\n }\n }\n catch (ex) {\n supported = false;\n }\n\n return supported;\n }\n\n //only way to test for Filesystem API support since webkit does not expose the DataTransfer interface\n function isChrome21OrHigher() {\n return (qq.chrome() || qq.opera()) &&\n navigator.userAgent.match(/Chrome\\/[2][1-9]|Chrome\\/[3-9][0-9]/) !== undefined;\n }\n\n //only way to test for complete Clipboard API support at this time\n function isChrome14OrHigher() {\n return (qq.chrome() || qq.opera()) &&\n navigator.userAgent.match(/Chrome\\/[1][4-9]|Chrome\\/[2-9][0-9]/) !== undefined;\n }\n\n //Ensure we can send cross-origin `XMLHttpRequest`s\n function isCrossOriginXhrSupported() {\n if (window.XMLHttpRequest) {\n var xhr = qq.createXhrInstance();\n\n //Commonly accepted test for XHR CORS support.\n return xhr.withCredentials !== undefined;\n }\n\n return false;\n }\n\n //Test for (terrible) cross-origin ajax transport fallback for IE9 and IE8\n function isXdrSupported() {\n return window.XDomainRequest !== undefined;\n }\n\n // CORS Ajax requests are supported if it is either possible to send credentialed `XMLHttpRequest`s,\n // or if `XDomainRequest` is an available alternative.\n function isCrossOriginAjaxSupported() {\n if (isCrossOriginXhrSupported()) {\n return true;\n }\n\n return isXdrSupported();\n }\n\n function isFolderSelectionSupported() {\n // We know that folder selection is only supported in Chrome via this proprietary attribute for now\n return document.createElement(\"input\").webkitdirectory !== undefined;\n }\n\n function isLocalStorageSupported() {\n try {\n return !!window.localStorage &&\n // unpatched versions of IE10/11 have buggy impls of localStorage where setItem is a string\n qq.isFunction(window.localStorage.setItem);\n }\n catch (error) {\n // probably caught a security exception, so no localStorage for you\n return false;\n }\n }\n\n function isDragAndDropSupported() {\n var span = document.createElement(\"span\");\n\n return (\"draggable\" in span || (\"ondragstart\" in span && \"ondrop\" in span)) &&\n !qq.android() && !qq.ios();\n }\n\n supportsUploading = testSupportsFileInputElement();\n\n supportsAjaxFileUploading = supportsUploading && qq.isXhrUploadSupported();\n\n supportsUploadingBlobs = supportsAjaxFileUploading && !qq.androidStock();\n\n supportsFileDrop = supportsAjaxFileUploading && isDragAndDropSupported();\n\n supportsFolderDrop = supportsFileDrop && isChrome21OrHigher();\n\n supportsChunking = supportsAjaxFileUploading && qq.isFileChunkingSupported();\n\n supportsResume = supportsAjaxFileUploading && supportsChunking && isLocalStorageSupported();\n\n supportsUploadViaPaste = supportsAjaxFileUploading && isChrome14OrHigher();\n\n supportsUploadCors = supportsUploading && (window.postMessage !== undefined || supportsAjaxFileUploading);\n\n supportsDeleteFileCorsXhr = isCrossOriginXhrSupported();\n\n supportsDeleteFileXdr = isXdrSupported();\n\n supportsDeleteFileCors = isCrossOriginAjaxSupported();\n\n supportsFolderSelection = isFolderSelectionSupported();\n\n supportsImagePreviews = supportsAjaxFileUploading && window.FileReader !== undefined;\n\n supportsUploadProgress = (function() {\n if (supportsAjaxFileUploading) {\n return !qq.androidStock() && !qq.iosChrome();\n }\n return false;\n }());\n\n return {\n ajaxUploading: supportsAjaxFileUploading,\n blobUploading: supportsUploadingBlobs,\n canDetermineSize: supportsAjaxFileUploading,\n chunking: supportsChunking,\n deleteFileCors: supportsDeleteFileCors,\n deleteFileCorsXdr: supportsDeleteFileXdr, //NOTE: will also return true in IE10, where XDR is also supported\n deleteFileCorsXhr: supportsDeleteFileCorsXhr,\n dialogElement: !!window.HTMLDialogElement,\n fileDrop: supportsFileDrop,\n folderDrop: supportsFolderDrop,\n folderSelection: supportsFolderSelection,\n imagePreviews: supportsImagePreviews,\n imageValidation: supportsImagePreviews,\n itemSizeValidation: supportsAjaxFileUploading,\n pause: supportsChunking,\n progressBar: supportsUploadProgress,\n resume: supportsResume,\n scaling: supportsImagePreviews && supportsUploadingBlobs,\n tiffPreviews: qq.safari(), // Not the best solution, but simple and probably accurate enough (for now)\n unlimitedScaledImageSize: !qq.ios(), // false simply indicates that there is some known limit\n uploading: supportsUploading,\n uploadCors: supportsUploadCors,\n uploadCustomHeaders: supportsAjaxFileUploading,\n uploadNonMultipart: supportsAjaxFileUploading,\n uploadViaPaste: supportsUploadViaPaste\n };\n\n}());\n","/*globals qq*/\n\n// Is the passed object a promise instance?\nqq.isGenericPromise = function(maybePromise) {\n \"use strict\";\n return !!(maybePromise && maybePromise.then && qq.isFunction(maybePromise.then));\n};\n\nqq.Promise = function() {\n \"use strict\";\n\n var successArgs, failureArgs,\n successCallbacks = [],\n failureCallbacks = [],\n doneCallbacks = [],\n state = 0;\n\n qq.extend(this, {\n then: function(onSuccess, onFailure) {\n if (state === 0) {\n if (onSuccess) {\n successCallbacks.push(onSuccess);\n }\n if (onFailure) {\n failureCallbacks.push(onFailure);\n }\n }\n else if (state === -1) {\n onFailure && onFailure.apply(null, failureArgs);\n }\n else if (onSuccess) {\n onSuccess.apply(null, successArgs);\n }\n\n return this;\n },\n\n done: function(callback) {\n if (state === 0) {\n doneCallbacks.push(callback);\n }\n else {\n callback.apply(null, failureArgs === undefined ? successArgs : failureArgs);\n }\n\n return this;\n },\n\n success: function() {\n state = 1;\n successArgs = arguments;\n\n if (successCallbacks.length) {\n qq.each(successCallbacks, function(idx, callback) {\n callback.apply(null, successArgs);\n });\n }\n\n if (doneCallbacks.length) {\n qq.each(doneCallbacks, function(idx, callback) {\n callback.apply(null, successArgs);\n });\n }\n\n return this;\n },\n\n failure: function() {\n state = -1;\n failureArgs = arguments;\n\n if (failureCallbacks.length) {\n qq.each(failureCallbacks, function(idx, callback) {\n callback.apply(null, failureArgs);\n });\n }\n\n if (doneCallbacks.length) {\n qq.each(doneCallbacks, function(idx, callback) {\n callback.apply(null, failureArgs);\n });\n }\n\n return this;\n }\n });\n};\n","/* globals qq */\n/**\n * Placeholder for a Blob that will be generated on-demand.\n *\n * @param referenceBlob Parent of the generated blob\n * @param onCreate Function to invoke when the blob must be created. Must be promissory.\n * @constructor\n */\nqq.BlobProxy = function(referenceBlob, onCreate) {\n \"use strict\";\n\n qq.extend(this, {\n referenceBlob: referenceBlob,\n\n create: function() {\n return onCreate(referenceBlob);\n }\n });\n};\n","/*globals qq*/\n\n/**\n * This module represents an upload or \"Select File(s)\" button. It's job is to embed an opaque ` `\n * element as a child of a provided \"container\" element. This \"container\" element (`options.element`) is used to provide\n * a custom style for the ` ` element. The ability to change the style of the container element is also\n * provided here by adding CSS classes to the container on hover/focus.\n *\n * TODO Eliminate the mouseover and mouseout event handlers since the :hover CSS pseudo-class should now be\n * available on all supported browsers.\n *\n * @param o Options to override the default values\n */\nqq.UploadButton = function(o) {\n \"use strict\";\n\n var self = this,\n\n disposeSupport = new qq.DisposeSupport(),\n\n options = {\n // Corresponds to the `accept` attribute on the associated ` `\n acceptFiles: null,\n\n // \"Container\" element\n element: null,\n\n focusClass: \"qq-upload-button-focus\",\n\n // A true value allows folders to be selected, if supported by the UA\n folders: false,\n\n // **This option will be removed** in the future as the :hover CSS pseudo-class is available on all supported browsers\n hoverClass: \"qq-upload-button-hover\",\n\n ios8BrowserCrashWorkaround: false,\n\n // If true adds `multiple` attribute to ` `\n multiple: false,\n\n // `name` attribute of ` `\n name: \"qqfile\",\n\n // Called when the browser invokes the onchange handler on the ` `\n onChange: function(input) {},\n\n title: null\n },\n input, buttonId;\n\n // Overrides any of the default option values with any option values passed in during construction.\n qq.extend(options, o);\n\n buttonId = qq.getUniqueId();\n\n // Embed an opaque ` ` element as a child of `options.element`.\n function createInput() {\n var input = document.createElement(\"input\");\n\n input.setAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME, buttonId);\n input.setAttribute(\"title\", options.title);\n\n self.setMultiple(options.multiple, input);\n\n if (options.folders && qq.supportedFeatures.folderSelection) {\n // selecting directories is only possible in Chrome now, via a vendor-specific prefixed attribute\n input.setAttribute(\"webkitdirectory\", \"\");\n }\n\n if (options.acceptFiles) {\n input.setAttribute(\"accept\", options.acceptFiles);\n }\n\n input.setAttribute(\"type\", \"file\");\n input.setAttribute(\"name\", options.name);\n\n qq(input).css({\n position: \"absolute\",\n // in Opera only 'browse' button\n // is clickable and it is located at\n // the right side of the input\n right: 0,\n top: 0,\n fontFamily: \"Arial\",\n // It's especially important to make this an arbitrarily large value\n // to ensure the rendered input button in IE takes up the entire\n // space of the container element. Otherwise, the left side of the\n // button will require a double-click to invoke the file chooser.\n // In other browsers, this might cause other issues, so a large font-size\n // is only used in IE. There is a bug in IE8 where the opacity style is ignored\n // in some cases when the font-size is large. So, this workaround is not applied\n // to IE8.\n fontSize: qq.ie() && !qq.ie8() ? \"3500px\" : \"118px\",\n margin: 0,\n padding: 0,\n cursor: \"pointer\",\n opacity: 0\n });\n\n // Setting the file input's height to 100% in IE7 causes\n // most of the visible button to be unclickable.\n !qq.ie7() && qq(input).css({height: \"100%\"});\n\n options.element.appendChild(input);\n\n disposeSupport.attach(input, \"change\", function() {\n options.onChange(input);\n });\n\n // **These event handlers will be removed** in the future as the :hover CSS pseudo-class is available on all supported browsers\n disposeSupport.attach(input, \"mouseover\", function() {\n qq(options.element).addClass(options.hoverClass);\n });\n disposeSupport.attach(input, \"mouseout\", function() {\n qq(options.element).removeClass(options.hoverClass);\n });\n\n disposeSupport.attach(input, \"focus\", function() {\n qq(options.element).addClass(options.focusClass);\n });\n disposeSupport.attach(input, \"blur\", function() {\n qq(options.element).removeClass(options.focusClass);\n });\n\n return input;\n }\n\n // Make button suitable container for input\n qq(options.element).css({\n position: \"relative\",\n overflow: \"hidden\",\n // Make sure browse button is in the right side in Internet Explorer\n direction: \"ltr\"\n });\n\n // Exposed API\n qq.extend(this, {\n getInput: function() {\n return input;\n },\n\n getButtonId: function() {\n return buttonId;\n },\n\n setMultiple: function(isMultiple, optInput) {\n var input = optInput || this.getInput();\n\n // Temporary workaround for bug in in iOS8 UIWebView that causes the browser to crash\n // before the file chooser appears if the file input doesn't contain a multiple attribute.\n // See #1283.\n if (options.ios8BrowserCrashWorkaround && qq.ios8() && (qq.iosChrome() || qq.iosSafariWebView())) {\n input.setAttribute(\"multiple\", \"\");\n }\n\n else {\n if (isMultiple) {\n input.setAttribute(\"multiple\", \"\");\n }\n else {\n input.removeAttribute(\"multiple\");\n }\n }\n },\n\n setAcceptFiles: function(acceptFiles) {\n if (acceptFiles !== options.acceptFiles) {\n input.setAttribute(\"accept\", acceptFiles);\n }\n },\n\n reset: function() {\n if (input.parentNode) {\n qq(input).remove();\n }\n\n qq(options.element).removeClass(options.focusClass);\n input = null;\n input = createInput();\n }\n });\n\n input = createInput();\n};\n\nqq.UploadButton.BUTTON_ID_ATTR_NAME = \"qq-button-id\";\n","/*globals qq */\nqq.UploadData = function(uploaderProxy) {\n \"use strict\";\n\n var data = [],\n byUuid = {},\n byStatus = {},\n byProxyGroupId = {},\n byBatchId = {};\n\n function getDataByIds(idOrIds) {\n if (qq.isArray(idOrIds)) {\n var entries = [];\n\n qq.each(idOrIds, function(idx, id) {\n entries.push(data[id]);\n });\n\n return entries;\n }\n\n return data[idOrIds];\n }\n\n function getDataByUuids(uuids) {\n if (qq.isArray(uuids)) {\n var entries = [];\n\n qq.each(uuids, function(idx, uuid) {\n entries.push(data[byUuid[uuid]]);\n });\n\n return entries;\n }\n\n return data[byUuid[uuids]];\n }\n\n function getDataByStatus(status) {\n var statusResults = [],\n statuses = [].concat(status);\n\n qq.each(statuses, function(index, statusEnum) {\n var statusResultIndexes = byStatus[statusEnum];\n\n if (statusResultIndexes !== undefined) {\n qq.each(statusResultIndexes, function(i, dataIndex) {\n statusResults.push(data[dataIndex]);\n });\n }\n });\n\n return statusResults;\n }\n\n qq.extend(this, {\n /**\n * Adds a new file to the data cache for tracking purposes.\n *\n * @param spec Data that describes this file. Possible properties are:\n *\n * - uuid: Initial UUID for this file.\n * - name: Initial name of this file.\n * - size: Size of this file, omit if this cannot be determined\n * - status: Initial `qq.status` for this file. Omit for `qq.status.SUBMITTING`.\n * - batchId: ID of the batch this file belongs to\n * - proxyGroupId: ID of the proxy group associated with this file\n *\n * @returns {number} Internal ID for this file.\n */\n addFile: function(spec) {\n var status = spec.status || qq.status.SUBMITTING,\n id = data.push({\n name: spec.name,\n originalName: spec.name,\n uuid: spec.uuid,\n size: spec.size == null ? -1 : spec.size,\n status: status\n }) - 1;\n\n if (spec.batchId) {\n data[id].batchId = spec.batchId;\n\n if (byBatchId[spec.batchId] === undefined) {\n byBatchId[spec.batchId] = [];\n }\n byBatchId[spec.batchId].push(id);\n }\n\n if (spec.proxyGroupId) {\n data[id].proxyGroupId = spec.proxyGroupId;\n\n if (byProxyGroupId[spec.proxyGroupId] === undefined) {\n byProxyGroupId[spec.proxyGroupId] = [];\n }\n byProxyGroupId[spec.proxyGroupId].push(id);\n }\n\n data[id].id = id;\n byUuid[spec.uuid] = id;\n\n if (byStatus[status] === undefined) {\n byStatus[status] = [];\n }\n byStatus[status].push(id);\n\n uploaderProxy.onStatusChange(id, null, status);\n\n return id;\n },\n\n retrieve: function(optionalFilter) {\n if (qq.isObject(optionalFilter) && data.length) {\n if (optionalFilter.id !== undefined) {\n return getDataByIds(optionalFilter.id);\n }\n\n else if (optionalFilter.uuid !== undefined) {\n return getDataByUuids(optionalFilter.uuid);\n }\n\n else if (optionalFilter.status) {\n return getDataByStatus(optionalFilter.status);\n }\n }\n else {\n return qq.extend([], data, true);\n }\n },\n\n reset: function() {\n data = [];\n byUuid = {};\n byStatus = {};\n byBatchId = {};\n },\n\n setStatus: function(id, newStatus) {\n var oldStatus = data[id].status,\n byStatusOldStatusIndex = qq.indexOf(byStatus[oldStatus], id);\n\n byStatus[oldStatus].splice(byStatusOldStatusIndex, 1);\n\n data[id].status = newStatus;\n\n if (byStatus[newStatus] === undefined) {\n byStatus[newStatus] = [];\n }\n byStatus[newStatus].push(id);\n\n uploaderProxy.onStatusChange(id, oldStatus, newStatus);\n },\n\n uuidChanged: function(id, newUuid) {\n var oldUuid = data[id].uuid;\n\n data[id].uuid = newUuid;\n byUuid[newUuid] = id;\n delete byUuid[oldUuid];\n },\n\n updateName: function(id, newName) {\n data[id].name = newName;\n },\n\n updateSize: function(id, newSize) {\n data[id].size = newSize;\n },\n\n // Only applicable if this file has a parent that we may want to reference later.\n setParentId: function(targetId, parentId) {\n data[targetId].parentId = parentId;\n },\n\n getIdsInProxyGroup: function(id) {\n var proxyGroupId = data[id].proxyGroupId;\n\n if (proxyGroupId) {\n return byProxyGroupId[proxyGroupId];\n }\n return [];\n },\n\n getIdsInBatch: function(id) {\n var batchId = data[id].batchId;\n\n return byBatchId[batchId];\n }\n });\n};\n\nqq.status = {\n SUBMITTING: \"submitting\",\n SUBMITTED: \"submitted\",\n REJECTED: \"rejected\",\n QUEUED: \"queued\",\n CANCELED: \"canceled\",\n PAUSED: \"paused\",\n UPLOADING: \"uploading\",\n UPLOAD_RETRYING: \"retrying upload\",\n UPLOAD_SUCCESSFUL: \"upload successful\",\n UPLOAD_FAILED: \"upload failed\",\n DELETE_FAILED: \"delete failed\",\n DELETING: \"deleting\",\n DELETED: \"deleted\"\n};\n","/*globals qq*/\n/**\n * Defines the public API for FineUploaderBasic mode.\n */\n(function() {\n \"use strict\";\n\n qq.basePublicApi = {\n // DEPRECATED - TODO REMOVE IN NEXT MAJOR RELEASE (replaced by addFiles)\n addBlobs: function(blobDataOrArray, params, endpoint) {\n this.addFiles(blobDataOrArray, params, endpoint);\n },\n\n addInitialFiles: function(cannedFileList) {\n var self = this;\n\n qq.each(cannedFileList, function(index, cannedFile) {\n self._addCannedFile(cannedFile);\n });\n },\n\n addFiles: function(data, params, endpoint) {\n this._maybeHandleIos8SafariWorkaround();\n\n var batchId = this._storedIds.length === 0 ? qq.getUniqueId() : this._currentBatchId,\n\n processBlob = qq.bind(function(blob) {\n this._handleNewFile({\n blob: blob,\n name: this._options.blobs.defaultName\n }, batchId, verifiedFiles);\n }, this),\n\n processBlobData = qq.bind(function(blobData) {\n this._handleNewFile(blobData, batchId, verifiedFiles);\n }, this),\n\n processCanvas = qq.bind(function(canvas) {\n var blob = qq.canvasToBlob(canvas);\n\n this._handleNewFile({\n blob: blob,\n name: this._options.blobs.defaultName + \".png\"\n }, batchId, verifiedFiles);\n }, this),\n\n processCanvasData = qq.bind(function(canvasData) {\n var normalizedQuality = canvasData.quality && canvasData.quality / 100,\n blob = qq.canvasToBlob(canvasData.canvas, canvasData.type, normalizedQuality);\n\n this._handleNewFile({\n blob: blob,\n name: canvasData.name\n }, batchId, verifiedFiles);\n }, this),\n\n processFileOrInput = qq.bind(function(fileOrInput) {\n if (qq.isInput(fileOrInput) && qq.supportedFeatures.ajaxUploading) {\n var files = Array.prototype.slice.call(fileOrInput.files),\n self = this;\n\n qq.each(files, function(idx, file) {\n self._handleNewFile(file, batchId, verifiedFiles);\n });\n }\n else {\n this._handleNewFile(fileOrInput, batchId, verifiedFiles);\n }\n }, this),\n\n normalizeData = function() {\n if (qq.isFileList(data)) {\n data = Array.prototype.slice.call(data);\n }\n data = [].concat(data);\n },\n\n self = this,\n verifiedFiles = [];\n\n this._currentBatchId = batchId;\n\n if (data) {\n normalizeData();\n\n qq.each(data, function(idx, fileContainer) {\n if (qq.isFileOrInput(fileContainer)) {\n processFileOrInput(fileContainer);\n }\n else if (qq.isBlob(fileContainer)) {\n processBlob(fileContainer);\n }\n else if (qq.isObject(fileContainer)) {\n if (fileContainer.blob && fileContainer.name) {\n processBlobData(fileContainer);\n }\n else if (fileContainer.canvas && fileContainer.name) {\n processCanvasData(fileContainer);\n }\n }\n else if (fileContainer.tagName && fileContainer.tagName.toLowerCase() === \"canvas\") {\n processCanvas(fileContainer);\n }\n else {\n self.log(fileContainer + \" is not a valid file container! Ignoring!\", \"warn\");\n }\n });\n\n this.log(\"Received \" + verifiedFiles.length + \" files.\");\n this._prepareItemsForUpload(verifiedFiles, params, endpoint);\n }\n },\n\n cancel: function(id) {\n this._handler.cancel(id);\n },\n\n cancelAll: function() {\n var storedIdsCopy = [],\n self = this;\n\n qq.extend(storedIdsCopy, this._storedIds);\n qq.each(storedIdsCopy, function(idx, storedFileId) {\n self.cancel(storedFileId);\n });\n\n this._handler.cancelAll();\n },\n\n clearStoredFiles: function() {\n this._storedIds = [];\n },\n\n continueUpload: function(id) {\n var uploadData = this._uploadData.retrieve({id: id});\n\n if (!qq.supportedFeatures.pause || !this._options.chunking.enabled) {\n return false;\n }\n\n if (uploadData.status === qq.status.PAUSED) {\n this.log(qq.format(\"Paused file ID {} ({}) will be continued. Not paused.\", id, this.getName(id)));\n this._uploadFile(id);\n return true;\n }\n else {\n this.log(qq.format(\"Ignoring continue for file ID {} ({}). Not paused.\", id, this.getName(id)), \"error\");\n }\n\n return false;\n },\n\n deleteFile: function(id) {\n return this._onSubmitDelete(id);\n },\n\n // TODO document?\n doesExist: function(fileOrBlobId) {\n return this._handler.isValid(fileOrBlobId);\n },\n\n // Generate a variable size thumbnail on an img or canvas,\n // returning a promise that is fulfilled when the attempt completes.\n // Thumbnail can either be based off of a URL for an image returned\n // by the server in the upload response, or the associated `Blob`.\n drawThumbnail: function(fileId, imgOrCanvas, maxSize, fromServer, customResizeFunction) {\n var promiseToReturn = new qq.Promise(),\n fileOrUrl, options;\n\n if (this._imageGenerator) {\n fileOrUrl = this._thumbnailUrls[fileId];\n options = {\n customResizeFunction: customResizeFunction,\n maxSize: maxSize > 0 ? maxSize : null,\n scale: maxSize > 0\n };\n\n // If client-side preview generation is possible\n // and we are not specifically looking for the image URl returned by the server...\n if (!fromServer && qq.supportedFeatures.imagePreviews) {\n fileOrUrl = this.getFile(fileId);\n }\n\n /* jshint eqeqeq:false,eqnull:true */\n if (fileOrUrl == null) {\n promiseToReturn.failure({container: imgOrCanvas, error: \"File or URL not found.\"});\n }\n else {\n this._imageGenerator.generate(fileOrUrl, imgOrCanvas, options).then(\n function success(modifiedContainer) {\n promiseToReturn.success(modifiedContainer);\n },\n\n function failure(container, reason) {\n promiseToReturn.failure({container: container, error: reason || \"Problem generating thumbnail\"});\n }\n );\n }\n }\n else {\n promiseToReturn.failure({container: imgOrCanvas, error: \"Missing image generator module\"});\n }\n\n return promiseToReturn;\n },\n\n getButton: function(fileId) {\n return this._getButton(this._buttonIdsForFileIds[fileId]);\n },\n\n getEndpoint: function(fileId) {\n return this._endpointStore.get(fileId);\n },\n\n getFile: function(fileOrBlobId) {\n return this._handler.getFile(fileOrBlobId) || null;\n },\n\n getInProgress: function() {\n return this._uploadData.retrieve({\n status: [\n qq.status.UPLOADING,\n qq.status.UPLOAD_RETRYING,\n qq.status.QUEUED\n ]\n }).length;\n },\n\n getName: function(id) {\n return this._uploadData.retrieve({id: id}).name;\n },\n\n // Parent ID for a specific file, or null if this is the parent, or if it has no parent.\n getParentId: function(id) {\n var uploadDataEntry = this.getUploads({id: id}),\n parentId = null;\n\n if (uploadDataEntry) {\n if (uploadDataEntry.parentId !== undefined) {\n parentId = uploadDataEntry.parentId;\n }\n }\n\n return parentId;\n },\n\n getResumableFilesData: function() {\n return this._handler.getResumableFilesData();\n },\n\n getSize: function(id) {\n return this._uploadData.retrieve({id: id}).size;\n },\n\n getNetUploads: function() {\n return this._netUploaded;\n },\n\n getRemainingAllowedItems: function() {\n var allowedItems = this._currentItemLimit;\n\n if (allowedItems > 0) {\n return allowedItems - this._netUploadedOrQueued;\n }\n\n return null;\n },\n\n getUploads: function(optionalFilter) {\n return this._uploadData.retrieve(optionalFilter);\n },\n\n getUuid: function(id) {\n return this._uploadData.retrieve({id: id}).uuid;\n },\n\n log: function(str, level) {\n if (this._options.debug && (!level || level === \"info\")) {\n qq.log(\"[Fine Uploader \" + qq.version + \"] \" + str);\n }\n else if (level && level !== \"info\") {\n qq.log(\"[Fine Uploader \" + qq.version + \"] \" + str, level);\n\n }\n },\n\n pauseUpload: function(id) {\n var uploadData = this._uploadData.retrieve({id: id});\n\n if (!qq.supportedFeatures.pause || !this._options.chunking.enabled) {\n return false;\n }\n\n // Pause only really makes sense if the file is uploading or retrying\n if (qq.indexOf([qq.status.UPLOADING, qq.status.UPLOAD_RETRYING], uploadData.status) >= 0) {\n if (this._handler.pause(id)) {\n this._uploadData.setStatus(id, qq.status.PAUSED);\n return true;\n }\n else {\n this.log(qq.format(\"Unable to pause file ID {} ({}).\", id, this.getName(id)), \"error\");\n }\n }\n else {\n this.log(qq.format(\"Ignoring pause for file ID {} ({}). Not in progress.\", id, this.getName(id)), \"error\");\n }\n\n return false;\n },\n\n reset: function() {\n this.log(\"Resetting uploader...\");\n\n this._handler.reset();\n this._storedIds = [];\n this._autoRetries = [];\n this._retryTimeouts = [];\n this._preventRetries = [];\n this._thumbnailUrls = [];\n\n qq.each(this._buttons, function(idx, button) {\n button.reset();\n });\n\n this._paramsStore.reset();\n this._endpointStore.reset();\n this._netUploadedOrQueued = 0;\n this._netUploaded = 0;\n this._uploadData.reset();\n this._buttonIdsForFileIds = [];\n\n this._pasteHandler && this._pasteHandler.reset();\n this._options.session.refreshOnReset && this._refreshSessionData();\n\n this._succeededSinceLastAllComplete = [];\n this._failedSinceLastAllComplete = [];\n\n this._totalProgress && this._totalProgress.reset();\n },\n\n retry: function(id) {\n return this._manualRetry(id);\n },\n\n scaleImage: function(id, specs) {\n var self = this;\n\n return qq.Scaler.prototype.scaleImage(id, specs, {\n log: qq.bind(self.log, self),\n getFile: qq.bind(self.getFile, self),\n uploadData: self._uploadData\n });\n },\n\n setCustomHeaders: function(headers, id) {\n this._customHeadersStore.set(headers, id);\n },\n\n setDeleteFileCustomHeaders: function(headers, id) {\n this._deleteFileCustomHeadersStore.set(headers, id);\n },\n\n setDeleteFileEndpoint: function(endpoint, id) {\n this._deleteFileEndpointStore.set(endpoint, id);\n },\n\n setDeleteFileParams: function(params, id) {\n this._deleteFileParamsStore.set(params, id);\n },\n\n // Re-sets the default endpoint, an endpoint for a specific file, or an endpoint for a specific button\n setEndpoint: function(endpoint, id) {\n this._endpointStore.set(endpoint, id);\n },\n\n setForm: function(elementOrId) {\n this._updateFormSupportAndParams(elementOrId);\n },\n\n setItemLimit: function(newItemLimit) {\n this._currentItemLimit = newItemLimit;\n },\n\n setName: function(id, newName) {\n this._uploadData.updateName(id, newName);\n },\n\n setParams: function(params, id) {\n this._paramsStore.set(params, id);\n },\n\n setUuid: function(id, newUuid) {\n return this._uploadData.uuidChanged(id, newUuid);\n },\n\n uploadStoredFiles: function() {\n if (this._storedIds.length === 0) {\n this._itemError(\"noFilesError\");\n }\n else {\n this._uploadStoredFiles();\n }\n }\n };\n\n /**\n * Defines the private (internal) API for FineUploaderBasic mode.\n */\n qq.basePrivateApi = {\n // Updates internal state with a file record (not backed by a live file). Returns the assigned ID.\n _addCannedFile: function(sessionData) {\n var id = this._uploadData.addFile({\n uuid: sessionData.uuid,\n name: sessionData.name,\n size: sessionData.size,\n status: qq.status.UPLOAD_SUCCESSFUL\n });\n\n sessionData.deleteFileEndpoint && this.setDeleteFileEndpoint(sessionData.deleteFileEndpoint, id);\n sessionData.deleteFileParams && this.setDeleteFileParams(sessionData.deleteFileParams, id);\n\n if (sessionData.thumbnailUrl) {\n this._thumbnailUrls[id] = sessionData.thumbnailUrl;\n }\n\n this._netUploaded++;\n this._netUploadedOrQueued++;\n\n return id;\n },\n\n _annotateWithButtonId: function(file, associatedInput) {\n if (qq.isFile(file)) {\n file.qqButtonId = this._getButtonId(associatedInput);\n }\n },\n\n _batchError: function(message) {\n this._options.callbacks.onError(null, null, message, undefined);\n },\n\n _createDeleteHandler: function() {\n var self = this;\n\n return new qq.DeleteFileAjaxRequester({\n method: this._options.deleteFile.method.toUpperCase(),\n maxConnections: this._options.maxConnections,\n uuidParamName: this._options.request.uuidName,\n customHeaders: this._deleteFileCustomHeadersStore,\n paramsStore: this._deleteFileParamsStore,\n endpointStore: this._deleteFileEndpointStore,\n cors: this._options.cors,\n log: qq.bind(self.log, self),\n onDelete: function(id) {\n self._onDelete(id);\n self._options.callbacks.onDelete(id);\n },\n onDeleteComplete: function(id, xhrOrXdr, isError) {\n self._onDeleteComplete(id, xhrOrXdr, isError);\n self._options.callbacks.onDeleteComplete(id, xhrOrXdr, isError);\n }\n\n });\n },\n\n _createPasteHandler: function() {\n var self = this;\n\n return new qq.PasteSupport({\n targetElement: this._options.paste.targetElement,\n callbacks: {\n log: qq.bind(self.log, self),\n pasteReceived: function(blob) {\n self._handleCheckedCallback({\n name: \"onPasteReceived\",\n callback: qq.bind(self._options.callbacks.onPasteReceived, self, blob),\n onSuccess: qq.bind(self._handlePasteSuccess, self, blob),\n identifier: \"pasted image\"\n });\n }\n }\n });\n },\n\n _createStore: function(initialValue, _readOnlyValues_) {\n var store = {},\n catchall = initialValue,\n perIdReadOnlyValues = {},\n readOnlyValues = _readOnlyValues_,\n copy = function(orig) {\n if (qq.isObject(orig)) {\n return qq.extend({}, orig);\n }\n return orig;\n },\n getReadOnlyValues = function() {\n if (qq.isFunction(readOnlyValues)) {\n return readOnlyValues();\n }\n return readOnlyValues;\n },\n includeReadOnlyValues = function(id, existing) {\n if (readOnlyValues && qq.isObject(existing)) {\n qq.extend(existing, getReadOnlyValues());\n }\n\n if (perIdReadOnlyValues[id]) {\n qq.extend(existing, perIdReadOnlyValues[id]);\n }\n };\n\n return {\n set: function(val, id) {\n /*jshint eqeqeq: true, eqnull: true*/\n if (id == null) {\n store = {};\n catchall = copy(val);\n }\n else {\n store[id] = copy(val);\n }\n },\n\n get: function(id) {\n var values;\n\n /*jshint eqeqeq: true, eqnull: true*/\n if (id != null && store[id]) {\n values = store[id];\n }\n else {\n values = copy(catchall);\n }\n\n includeReadOnlyValues(id, values);\n\n return copy(values);\n },\n\n addReadOnly: function(id, values) {\n // Only applicable to Object stores\n if (qq.isObject(store)) {\n // If null ID, apply readonly values to all files\n if (id === null) {\n if (qq.isFunction(values)) {\n readOnlyValues = values;\n }\n else {\n readOnlyValues = readOnlyValues || {};\n qq.extend(readOnlyValues, values);\n }\n }\n else {\n perIdReadOnlyValues[id] = perIdReadOnlyValues[id] || {};\n qq.extend(perIdReadOnlyValues[id], values);\n }\n }\n },\n\n remove: function(fileId) {\n return delete store[fileId];\n },\n\n reset: function() {\n store = {};\n perIdReadOnlyValues = {};\n catchall = initialValue;\n }\n };\n },\n\n _createUploadDataTracker: function() {\n var self = this;\n\n return new qq.UploadData({\n getName: function(id) {\n return self.getName(id);\n },\n getUuid: function(id) {\n return self.getUuid(id);\n },\n getSize: function(id) {\n return self.getSize(id);\n },\n onStatusChange: function(id, oldStatus, newStatus) {\n self._onUploadStatusChange(id, oldStatus, newStatus);\n self._options.callbacks.onStatusChange(id, oldStatus, newStatus);\n self._maybeAllComplete(id, newStatus);\n\n if (self._totalProgress) {\n setTimeout(function() {\n self._totalProgress.onStatusChange(id, oldStatus, newStatus);\n }, 0);\n }\n }\n });\n },\n\n /**\n * Generate a tracked upload button.\n *\n * @param spec Object containing a required `element` property\n * along with optional `multiple`, `accept`, and `folders`.\n * @returns {qq.UploadButton}\n * @private\n */\n _createUploadButton: function(spec) {\n var self = this,\n acceptFiles = spec.accept || this._options.validation.acceptFiles,\n allowedExtensions = spec.allowedExtensions || this._options.validation.allowedExtensions,\n button;\n\n function allowMultiple() {\n if (qq.supportedFeatures.ajaxUploading) {\n // Workaround for bug in iOS7+ (see #1039)\n if (self._options.workarounds.iosEmptyVideos &&\n qq.ios() &&\n !qq.ios6() &&\n self._isAllowedExtension(allowedExtensions, \".mov\")) {\n\n return false;\n }\n\n if (spec.multiple === undefined) {\n return self._options.multiple;\n }\n\n return spec.multiple;\n }\n\n return false;\n }\n\n button = new qq.UploadButton({\n acceptFiles: acceptFiles,\n element: spec.element,\n focusClass: this._options.classes.buttonFocus,\n folders: spec.folders,\n hoverClass: this._options.classes.buttonHover,\n ios8BrowserCrashWorkaround: this._options.workarounds.ios8BrowserCrash,\n multiple: allowMultiple(),\n name: this._options.request.inputName,\n onChange: function(input) {\n self._onInputChange(input);\n },\n title: spec.title == null ? this._options.text.fileInputTitle : spec.title\n });\n\n this._disposeSupport.addDisposer(function() {\n button.dispose();\n });\n\n self._buttons.push(button);\n\n return button;\n },\n\n _createUploadHandler: function(additionalOptions, namespace) {\n var self = this,\n lastOnProgress = {},\n options = {\n debug: this._options.debug,\n maxConnections: this._options.maxConnections,\n cors: this._options.cors,\n paramsStore: this._paramsStore,\n endpointStore: this._endpointStore,\n chunking: this._options.chunking,\n resume: this._options.resume,\n blobs: this._options.blobs,\n log: qq.bind(self.log, self),\n preventRetryParam: this._options.retry.preventRetryResponseProperty,\n onProgress: function(id, name, loaded, total) {\n if (loaded < 0 || total < 0) {\n return;\n }\n\n if (lastOnProgress[id]) {\n if (lastOnProgress[id].loaded !== loaded || lastOnProgress[id].total !== total) {\n self._onProgress(id, name, loaded, total);\n self._options.callbacks.onProgress(id, name, loaded, total);\n }\n }\n else {\n self._onProgress(id, name, loaded, total);\n self._options.callbacks.onProgress(id, name, loaded, total);\n }\n\n lastOnProgress[id] = {loaded: loaded, total: total};\n\n },\n onComplete: function(id, name, result, xhr) {\n delete lastOnProgress[id];\n\n var status = self.getUploads({id: id}).status,\n retVal;\n\n // This is to deal with some observed cases where the XHR readyStateChange handler is\n // invoked by the browser multiple times for the same XHR instance with the same state\n // readyState value. Higher level: don't invoke complete-related code if we've already\n // done this.\n if (status === qq.status.UPLOAD_SUCCESSFUL || status === qq.status.UPLOAD_FAILED) {\n return;\n }\n\n retVal = self._onComplete(id, name, result, xhr);\n\n // If the internal `_onComplete` handler returns a promise, don't invoke the `onComplete` callback\n // until the promise has been fulfilled.\n if (retVal instanceof qq.Promise) {\n retVal.done(function() {\n self._options.callbacks.onComplete(id, name, result, xhr);\n });\n }\n else {\n self._options.callbacks.onComplete(id, name, result, xhr);\n }\n },\n onCancel: function(id, name, cancelFinalizationEffort) {\n var promise = new qq.Promise();\n\n self._handleCheckedCallback({\n name: \"onCancel\",\n callback: qq.bind(self._options.callbacks.onCancel, self, id, name),\n onFailure: promise.failure,\n onSuccess: function() {\n cancelFinalizationEffort.then(function() {\n self._onCancel(id, name);\n });\n\n promise.success();\n },\n identifier: id\n });\n\n return promise;\n },\n onUploadPrep: qq.bind(this._onUploadPrep, this),\n onUpload: function(id, name) {\n self._onUpload(id, name);\n self._options.callbacks.onUpload(id, name);\n },\n onUploadChunk: function(id, name, chunkData) {\n self._onUploadChunk(id, chunkData);\n self._options.callbacks.onUploadChunk(id, name, chunkData);\n },\n onUploadChunkSuccess: function(id, chunkData, result, xhr) {\n self._options.callbacks.onUploadChunkSuccess.apply(self, arguments);\n },\n onResume: function(id, name, chunkData) {\n return self._options.callbacks.onResume(id, name, chunkData);\n },\n onAutoRetry: function(id, name, responseJSON, xhr) {\n return self._onAutoRetry.apply(self, arguments);\n },\n onUuidChanged: function(id, newUuid) {\n self.log(\"Server requested UUID change from '\" + self.getUuid(id) + \"' to '\" + newUuid + \"'\");\n self.setUuid(id, newUuid);\n },\n getName: qq.bind(self.getName, self),\n getUuid: qq.bind(self.getUuid, self),\n getSize: qq.bind(self.getSize, self),\n setSize: qq.bind(self._setSize, self),\n getDataByUuid: function(uuid) {\n return self.getUploads({uuid: uuid});\n },\n isQueued: function(id) {\n var status = self.getUploads({id: id}).status;\n return status === qq.status.QUEUED ||\n status === qq.status.SUBMITTED ||\n status === qq.status.UPLOAD_RETRYING ||\n status === qq.status.PAUSED;\n },\n getIdsInProxyGroup: self._uploadData.getIdsInProxyGroup,\n getIdsInBatch: self._uploadData.getIdsInBatch\n };\n\n qq.each(this._options.request, function(prop, val) {\n options[prop] = val;\n });\n\n options.customHeaders = this._customHeadersStore;\n\n if (additionalOptions) {\n qq.each(additionalOptions, function(key, val) {\n options[key] = val;\n });\n }\n\n return new qq.UploadHandlerController(options, namespace);\n },\n\n _fileOrBlobRejected: function(id) {\n this._netUploadedOrQueued--;\n this._uploadData.setStatus(id, qq.status.REJECTED);\n },\n\n _formatSize: function(bytes) {\n if (bytes === 0) {\n return bytes + this._options.text.sizeSymbols[0];\n }\n var i = -1;\n do {\n bytes = bytes / 1000;\n i++;\n } while (bytes > 999);\n\n return Math.max(bytes, 0.1).toFixed(1) + this._options.text.sizeSymbols[i];\n },\n\n // Creates an internal object that tracks various properties of each extra button,\n // and then actually creates the extra button.\n _generateExtraButtonSpecs: function() {\n var self = this;\n\n this._extraButtonSpecs = {};\n\n qq.each(this._options.extraButtons, function(idx, extraButtonOptionEntry) {\n var multiple = extraButtonOptionEntry.multiple,\n validation = qq.extend({}, self._options.validation, true),\n extraButtonSpec = qq.extend({}, extraButtonOptionEntry);\n\n if (multiple === undefined) {\n multiple = self._options.multiple;\n }\n\n if (extraButtonSpec.validation) {\n qq.extend(validation, extraButtonOptionEntry.validation, true);\n }\n\n qq.extend(extraButtonSpec, {\n multiple: multiple,\n validation: validation\n }, true);\n\n self._initExtraButton(extraButtonSpec);\n });\n },\n\n _getButton: function(buttonId) {\n var extraButtonsSpec = this._extraButtonSpecs[buttonId];\n\n if (extraButtonsSpec) {\n return extraButtonsSpec.element;\n }\n else if (buttonId === this._defaultButtonId) {\n return this._options.button;\n }\n },\n\n /**\n * Gets the internally used tracking ID for a button.\n *\n * @param buttonOrFileInputOrFile `File`, ` `, or a button container element\n * @returns {*} The button's ID, or undefined if no ID is recoverable\n * @private\n */\n _getButtonId: function(buttonOrFileInputOrFile) {\n var inputs, fileInput,\n fileBlobOrInput = buttonOrFileInputOrFile;\n\n // We want the reference file/blob here if this is a proxy (a file that will be generated on-demand later)\n if (fileBlobOrInput instanceof qq.BlobProxy) {\n fileBlobOrInput = fileBlobOrInput.referenceBlob;\n }\n\n // If the item is a `Blob` it will never be associated with a button or drop zone.\n if (fileBlobOrInput && !qq.isBlob(fileBlobOrInput)) {\n if (qq.isFile(fileBlobOrInput)) {\n return fileBlobOrInput.qqButtonId;\n }\n else if (fileBlobOrInput.tagName.toLowerCase() === \"input\" &&\n fileBlobOrInput.type.toLowerCase() === \"file\") {\n\n return fileBlobOrInput.getAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME);\n }\n\n inputs = fileBlobOrInput.getElementsByTagName(\"input\");\n\n qq.each(inputs, function(idx, input) {\n if (input.getAttribute(\"type\") === \"file\") {\n fileInput = input;\n return false;\n }\n });\n\n if (fileInput) {\n return fileInput.getAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME);\n }\n }\n },\n\n _getNotFinished: function() {\n return this._uploadData.retrieve({\n status: [\n qq.status.UPLOADING,\n qq.status.UPLOAD_RETRYING,\n qq.status.QUEUED,\n qq.status.SUBMITTING,\n qq.status.SUBMITTED,\n qq.status.PAUSED\n ]\n }).length;\n },\n\n // Get the validation options for this button. Could be the default validation option\n // or a specific one assigned to this particular button.\n _getValidationBase: function(buttonId) {\n var extraButtonSpec = this._extraButtonSpecs[buttonId];\n\n return extraButtonSpec ? extraButtonSpec.validation : this._options.validation;\n },\n\n _getValidationDescriptor: function(fileWrapper) {\n if (fileWrapper.file instanceof qq.BlobProxy) {\n return {\n name: qq.getFilename(fileWrapper.file.referenceBlob),\n size: fileWrapper.file.referenceBlob.size\n };\n }\n\n return {\n name: this.getUploads({id: fileWrapper.id}).name,\n size: this.getUploads({id: fileWrapper.id}).size\n };\n },\n\n _getValidationDescriptors: function(fileWrappers) {\n var self = this,\n fileDescriptors = [];\n\n qq.each(fileWrappers, function(idx, fileWrapper) {\n fileDescriptors.push(self._getValidationDescriptor(fileWrapper));\n });\n\n return fileDescriptors;\n },\n\n // Allows camera access on either the default or an extra button for iOS devices.\n _handleCameraAccess: function() {\n if (this._options.camera.ios && qq.ios()) {\n var acceptIosCamera = \"image/*;capture=camera\",\n button = this._options.camera.button,\n buttonId = button ? this._getButtonId(button) : this._defaultButtonId,\n optionRoot = this._options;\n\n // If we are not targeting the default button, it is an \"extra\" button\n if (buttonId && buttonId !== this._defaultButtonId) {\n optionRoot = this._extraButtonSpecs[buttonId];\n }\n\n // Camera access won't work in iOS if the `multiple` attribute is present on the file input\n optionRoot.multiple = false;\n\n // update the options\n if (optionRoot.validation.acceptFiles === null) {\n optionRoot.validation.acceptFiles = acceptIosCamera;\n }\n else {\n optionRoot.validation.acceptFiles += \",\" + acceptIosCamera;\n }\n\n // update the already-created button\n qq.each(this._buttons, function(idx, button) {\n if (button.getButtonId() === buttonId) {\n button.setMultiple(optionRoot.multiple);\n button.setAcceptFiles(optionRoot.acceptFiles);\n\n return false;\n }\n });\n }\n },\n\n _handleCheckedCallback: function(details) {\n var self = this,\n callbackRetVal = details.callback();\n\n if (qq.isGenericPromise(callbackRetVal)) {\n this.log(details.name + \" - waiting for \" + details.name + \" promise to be fulfilled for \" + details.identifier);\n return callbackRetVal.then(\n function(successParam) {\n self.log(details.name + \" promise success for \" + details.identifier);\n details.onSuccess(successParam);\n },\n function() {\n if (details.onFailure) {\n self.log(details.name + \" promise failure for \" + details.identifier);\n details.onFailure();\n }\n else {\n self.log(details.name + \" promise failure for \" + details.identifier);\n }\n });\n }\n\n if (callbackRetVal !== false) {\n details.onSuccess(callbackRetVal);\n }\n else {\n if (details.onFailure) {\n this.log(details.name + \" - return value was 'false' for \" + details.identifier + \". Invoking failure callback.\");\n details.onFailure();\n }\n else {\n this.log(details.name + \" - return value was 'false' for \" + details.identifier + \". Will not proceed.\");\n }\n }\n\n return callbackRetVal;\n },\n\n // Updates internal state when a new file has been received, and adds it along with its ID to a passed array.\n _handleNewFile: function(file, batchId, newFileWrapperList) {\n var self = this,\n uuid = qq.getUniqueId(),\n size = -1,\n name = qq.getFilename(file),\n actualFile = file.blob || file,\n handler = this._customNewFileHandler ?\n this._customNewFileHandler :\n qq.bind(self._handleNewFileGeneric, self);\n\n if (!qq.isInput(actualFile) && actualFile.size >= 0) {\n size = actualFile.size;\n }\n\n handler(actualFile, name, uuid, size, newFileWrapperList, batchId, this._options.request.uuidName, {\n uploadData: self._uploadData,\n paramsStore: self._paramsStore,\n addFileToHandler: function(id, file) {\n self._handler.add(id, file);\n self._netUploadedOrQueued++;\n self._trackButton(id);\n }\n });\n },\n\n _handleNewFileGeneric: function(file, name, uuid, size, fileList, batchId) {\n var id = this._uploadData.addFile({uuid: uuid, name: name, size: size, batchId: batchId});\n\n this._handler.add(id, file);\n this._trackButton(id);\n\n this._netUploadedOrQueued++;\n\n fileList.push({id: id, file: file});\n },\n\n _handlePasteSuccess: function(blob, extSuppliedName) {\n var extension = blob.type.split(\"/\")[1],\n name = extSuppliedName;\n\n /*jshint eqeqeq: true, eqnull: true*/\n if (name == null) {\n name = this._options.paste.defaultName;\n }\n\n name += \".\" + extension;\n\n this.addFiles({\n name: name,\n blob: blob\n });\n },\n\n // Creates an extra button element\n _initExtraButton: function(spec) {\n var button = this._createUploadButton({\n accept: spec.validation.acceptFiles,\n allowedExtensions: spec.validation.allowedExtensions,\n element: spec.element,\n folders: spec.folders,\n multiple: spec.multiple,\n title: spec.fileInputTitle\n });\n\n this._extraButtonSpecs[button.getButtonId()] = spec;\n },\n\n _initFormSupportAndParams: function() {\n this._formSupport = qq.FormSupport && new qq.FormSupport(\n this._options.form, qq.bind(this.uploadStoredFiles, this), qq.bind(this.log, this)\n );\n\n if (this._formSupport && this._formSupport.attachedToForm) {\n this._paramsStore = this._createStore(\n this._options.request.params, this._formSupport.getFormInputsAsObject\n );\n\n this._options.autoUpload = this._formSupport.newAutoUpload;\n if (this._formSupport.newEndpoint) {\n this._options.request.endpoint = this._formSupport.newEndpoint;\n }\n }\n else {\n this._paramsStore = this._createStore(this._options.request.params);\n }\n },\n\n _isDeletePossible: function() {\n if (!qq.DeleteFileAjaxRequester || !this._options.deleteFile.enabled) {\n return false;\n }\n\n if (this._options.cors.expected) {\n if (qq.supportedFeatures.deleteFileCorsXhr) {\n return true;\n }\n\n if (qq.supportedFeatures.deleteFileCorsXdr && this._options.cors.allowXdr) {\n return true;\n }\n\n return false;\n }\n\n return true;\n },\n\n _isAllowedExtension: function(allowed, fileName) {\n var valid = false;\n\n if (!allowed.length) {\n return true;\n }\n\n qq.each(allowed, function(idx, allowedExt) {\n /**\n * If an argument is not a string, ignore it. Added when a possible issue with MooTools hijacking the\n * `allowedExtensions` array was discovered. See case #735 in the issue tracker for more details.\n */\n if (qq.isString(allowedExt)) {\n /*jshint eqeqeq: true, eqnull: true*/\n var extRegex = new RegExp(\"\\\\.\" + allowedExt + \"$\", \"i\");\n\n if (fileName.match(extRegex) != null) {\n valid = true;\n return false;\n }\n }\n });\n\n return valid;\n },\n\n /**\n * Constructs and returns a message that describes an item/file error. Also calls `onError` callback.\n *\n * @param code REQUIRED - a code that corresponds to a stock message describing this type of error\n * @param maybeNameOrNames names of the items that have failed, if applicable\n * @param item `File`, `Blob`, or ` `\n * @private\n */\n _itemError: function(code, maybeNameOrNames, item) {\n var message = this._options.messages[code],\n allowedExtensions = [],\n names = [].concat(maybeNameOrNames),\n name = names[0],\n buttonId = this._getButtonId(item),\n validationBase = this._getValidationBase(buttonId),\n extensionsForMessage, placeholderMatch;\n\n function r(name, replacement) { message = message.replace(name, replacement); }\n\n qq.each(validationBase.allowedExtensions, function(idx, allowedExtension) {\n /**\n * If an argument is not a string, ignore it. Added when a possible issue with MooTools hijacking the\n * `allowedExtensions` array was discovered. See case #735 in the issue tracker for more details.\n */\n if (qq.isString(allowedExtension)) {\n allowedExtensions.push(allowedExtension);\n }\n });\n\n extensionsForMessage = allowedExtensions.join(\", \").toLowerCase();\n\n r(\"{file}\", this._options.formatFileName(name));\n r(\"{extensions}\", extensionsForMessage);\n r(\"{sizeLimit}\", this._formatSize(validationBase.sizeLimit));\n r(\"{minSizeLimit}\", this._formatSize(validationBase.minSizeLimit));\n\n placeholderMatch = message.match(/(\\{\\w+\\})/g);\n if (placeholderMatch !== null) {\n qq.each(placeholderMatch, function(idx, placeholder) {\n r(placeholder, names[idx]);\n });\n }\n\n this._options.callbacks.onError(null, name, message, undefined);\n\n return message;\n },\n\n /**\n * Conditionally orders a manual retry of a failed upload.\n *\n * @param id File ID of the failed upload\n * @param callback Optional callback to invoke if a retry is prudent.\n * In lieu of asking the upload handler to retry.\n * @returns {boolean} true if a manual retry will occur\n * @private\n */\n _manualRetry: function(id, callback) {\n if (this._onBeforeManualRetry(id)) {\n this._netUploadedOrQueued++;\n this._uploadData.setStatus(id, qq.status.UPLOAD_RETRYING);\n\n if (callback) {\n callback(id);\n }\n else {\n this._handler.retry(id);\n }\n\n return true;\n }\n },\n\n _maybeAllComplete: function(id, status) {\n var self = this,\n notFinished = this._getNotFinished();\n\n if (status === qq.status.UPLOAD_SUCCESSFUL) {\n this._succeededSinceLastAllComplete.push(id);\n }\n else if (status === qq.status.UPLOAD_FAILED) {\n this._failedSinceLastAllComplete.push(id);\n }\n\n if (notFinished === 0 &&\n (this._succeededSinceLastAllComplete.length || this._failedSinceLastAllComplete.length)) {\n // Attempt to ensure onAllComplete is not invoked before other callbacks, such as onCancel & onComplete\n setTimeout(function() {\n self._onAllComplete(self._succeededSinceLastAllComplete, self._failedSinceLastAllComplete);\n }, 0);\n }\n },\n\n _maybeHandleIos8SafariWorkaround: function() {\n var self = this;\n\n if (this._options.workarounds.ios8SafariUploads && qq.ios800() && qq.iosSafari()) {\n setTimeout(function() {\n window.alert(self._options.messages.unsupportedBrowserIos8Safari);\n }, 0);\n throw new qq.Error(this._options.messages.unsupportedBrowserIos8Safari);\n }\n },\n\n _maybeParseAndSendUploadError: function(id, name, response, xhr) {\n // Assuming no one will actually set the response code to something other than 200\n // and still set 'success' to true...\n if (!response.success) {\n if (xhr && xhr.status !== 200 && !response.error) {\n this._options.callbacks.onError(id, name, \"XHR returned response code \" + xhr.status, xhr);\n }\n else {\n var errorReason = response.error ? response.error : this._options.text.defaultResponseError;\n this._options.callbacks.onError(id, name, errorReason, xhr);\n }\n }\n },\n\n _maybeProcessNextItemAfterOnValidateCallback: function(validItem, items, index, params, endpoint) {\n var self = this;\n\n if (items.length > index) {\n if (validItem || !this._options.validation.stopOnFirstInvalidFile) {\n //use setTimeout to prevent a stack overflow with a large number of files in the batch & non-promissory callbacks\n setTimeout(function() {\n var validationDescriptor = self._getValidationDescriptor(items[index]),\n buttonId = self._getButtonId(items[index].file),\n button = self._getButton(buttonId);\n\n self._handleCheckedCallback({\n name: \"onValidate\",\n callback: qq.bind(self._options.callbacks.onValidate, self, validationDescriptor, button),\n onSuccess: qq.bind(self._onValidateCallbackSuccess, self, items, index, params, endpoint),\n onFailure: qq.bind(self._onValidateCallbackFailure, self, items, index, params, endpoint),\n identifier: \"Item '\" + validationDescriptor.name + \"', size: \" + validationDescriptor.size\n });\n }, 0);\n }\n else if (!validItem) {\n for (; index < items.length; index++) {\n self._fileOrBlobRejected(items[index].id);\n }\n }\n }\n },\n\n _onAllComplete: function(successful, failed) {\n this._totalProgress && this._totalProgress.onAllComplete(successful, failed, this._preventRetries);\n\n this._options.callbacks.onAllComplete(qq.extend([], successful), qq.extend([], failed));\n\n this._succeededSinceLastAllComplete = [];\n this._failedSinceLastAllComplete = [];\n },\n\n /**\n * Attempt to automatically retry a failed upload.\n *\n * @param id The file ID of the failed upload\n * @param name The name of the file associated with the failed upload\n * @param responseJSON Response from the server, parsed into a javascript object\n * @param xhr Ajax transport used to send the failed request\n * @param callback Optional callback to be invoked if a retry is prudent.\n * Invoked in lieu of asking the upload handler to retry.\n * @returns {boolean} true if an auto-retry will occur\n * @private\n */\n _onAutoRetry: function(id, name, responseJSON, xhr, callback) {\n var self = this;\n\n self._preventRetries[id] = responseJSON[self._options.retry.preventRetryResponseProperty];\n\n if (self._shouldAutoRetry(id, name, responseJSON)) {\n var retryWaitPeriod = self._options.retry.autoAttemptDelay * 1000;\n\n self._maybeParseAndSendUploadError.apply(self, arguments);\n self._options.callbacks.onAutoRetry(id, name, self._autoRetries[id]);\n self._onBeforeAutoRetry(id, name);\n\n self._uploadData.setStatus(id, qq.status.UPLOAD_RETRYING);\n self._retryTimeouts[id] = setTimeout(function() {\n self.log(\"Starting retry for \" + name + \"...\");\n\n if (callback) {\n callback(id);\n }\n else {\n self._handler.retry(id);\n }\n }, retryWaitPeriod);\n\n return true;\n }\n },\n\n _onBeforeAutoRetry: function(id, name) {\n this.log(\"Waiting \" + this._options.retry.autoAttemptDelay + \" seconds before retrying \" + name + \"...\");\n },\n\n //return false if we should not attempt the requested retry\n _onBeforeManualRetry: function(id) {\n var itemLimit = this._currentItemLimit,\n fileName;\n\n if (this._preventRetries[id]) {\n this.log(\"Retries are forbidden for id \" + id, \"warn\");\n return false;\n }\n else if (this._handler.isValid(id)) {\n fileName = this.getName(id);\n\n if (this._options.callbacks.onManualRetry(id, fileName) === false) {\n return false;\n }\n\n if (itemLimit > 0 && this._netUploadedOrQueued + 1 > itemLimit) {\n this._itemError(\"retryFailTooManyItems\");\n return false;\n }\n\n this.log(\"Retrying upload for '\" + fileName + \"' (id: \" + id + \")...\");\n return true;\n }\n else {\n this.log(\"'\" + id + \"' is not a valid file ID\", \"error\");\n return false;\n }\n },\n\n _onCancel: function(id, name) {\n this._netUploadedOrQueued--;\n\n clearTimeout(this._retryTimeouts[id]);\n\n var storedItemIndex = qq.indexOf(this._storedIds, id);\n if (!this._options.autoUpload && storedItemIndex >= 0) {\n this._storedIds.splice(storedItemIndex, 1);\n }\n\n this._uploadData.setStatus(id, qq.status.CANCELED);\n },\n\n _onComplete: function(id, name, result, xhr) {\n if (!result.success) {\n this._netUploadedOrQueued--;\n this._uploadData.setStatus(id, qq.status.UPLOAD_FAILED);\n\n if (result[this._options.retry.preventRetryResponseProperty] === true) {\n this._preventRetries[id] = true;\n }\n }\n else {\n if (result.thumbnailUrl) {\n this._thumbnailUrls[id] = result.thumbnailUrl;\n }\n\n this._netUploaded++;\n this._uploadData.setStatus(id, qq.status.UPLOAD_SUCCESSFUL);\n }\n\n this._maybeParseAndSendUploadError(id, name, result, xhr);\n\n return result.success ? true : false;\n },\n\n _onDelete: function(id) {\n this._uploadData.setStatus(id, qq.status.DELETING);\n },\n\n _onDeleteComplete: function(id, xhrOrXdr, isError) {\n var name = this.getName(id);\n\n if (isError) {\n this._uploadData.setStatus(id, qq.status.DELETE_FAILED);\n this.log(\"Delete request for '\" + name + \"' has failed.\", \"error\");\n\n // For error reporting, we only have access to the response status if this is not\n // an `XDomainRequest`.\n if (xhrOrXdr.withCredentials === undefined) {\n this._options.callbacks.onError(id, name, \"Delete request failed\", xhrOrXdr);\n }\n else {\n this._options.callbacks.onError(id, name, \"Delete request failed with response code \" + xhrOrXdr.status, xhrOrXdr);\n }\n }\n else {\n this._netUploadedOrQueued--;\n this._netUploaded--;\n this._handler.expunge(id);\n this._uploadData.setStatus(id, qq.status.DELETED);\n this.log(\"Delete request for '\" + name + \"' has succeeded.\");\n }\n },\n\n _onInputChange: function(input) {\n var fileIndex;\n\n if (qq.supportedFeatures.ajaxUploading) {\n for (fileIndex = 0; fileIndex < input.files.length; fileIndex++) {\n this._annotateWithButtonId(input.files[fileIndex], input);\n }\n\n this.addFiles(input.files);\n }\n // Android 2.3.x will fire `onchange` even if no file has been selected\n else if (input.value.length > 0) {\n this.addFiles(input);\n }\n\n qq.each(this._buttons, function(idx, button) {\n button.reset();\n });\n },\n\n _onProgress: function(id, name, loaded, total) {\n this._totalProgress && this._totalProgress.onIndividualProgress(id, loaded, total);\n },\n\n _onSubmit: function(id, name) {\n //nothing to do yet in core uploader\n },\n\n _onSubmitCallbackSuccess: function(id, name) {\n this._onSubmit.apply(this, arguments);\n this._uploadData.setStatus(id, qq.status.SUBMITTED);\n this._onSubmitted.apply(this, arguments);\n\n if (this._options.autoUpload) {\n this._options.callbacks.onSubmitted.apply(this, arguments);\n this._uploadFile(id);\n }\n else {\n this._storeForLater(id);\n this._options.callbacks.onSubmitted.apply(this, arguments);\n }\n },\n\n _onSubmitDelete: function(id, onSuccessCallback, additionalMandatedParams) {\n var uuid = this.getUuid(id),\n adjustedOnSuccessCallback;\n\n if (onSuccessCallback) {\n adjustedOnSuccessCallback = qq.bind(onSuccessCallback, this, id, uuid, additionalMandatedParams);\n }\n\n if (this._isDeletePossible()) {\n this._handleCheckedCallback({\n name: \"onSubmitDelete\",\n callback: qq.bind(this._options.callbacks.onSubmitDelete, this, id),\n onSuccess: adjustedOnSuccessCallback ||\n qq.bind(this._deleteHandler.sendDelete, this, id, uuid, additionalMandatedParams),\n identifier: id\n });\n return true;\n }\n else {\n this.log(\"Delete request ignored for ID \" + id + \", delete feature is disabled or request not possible \" +\n \"due to CORS on a user agent that does not support pre-flighting.\", \"warn\");\n return false;\n }\n },\n\n _onSubmitted: function(id) {\n //nothing to do in the base uploader\n },\n\n _onTotalProgress: function(loaded, total) {\n this._options.callbacks.onTotalProgress(loaded, total);\n },\n\n _onUploadPrep: function(id) {\n // nothing to do in the core uploader for now\n },\n\n _onUpload: function(id, name) {\n this._uploadData.setStatus(id, qq.status.UPLOADING);\n },\n\n _onUploadChunk: function(id, chunkData) {\n //nothing to do in the base uploader\n },\n\n _onUploadStatusChange: function(id, oldStatus, newStatus) {\n // Make sure a \"queued\" retry attempt is canceled if the upload has been paused\n if (newStatus === qq.status.PAUSED) {\n clearTimeout(this._retryTimeouts[id]);\n }\n },\n\n _onValidateBatchCallbackFailure: function(fileWrappers) {\n var self = this;\n\n qq.each(fileWrappers, function(idx, fileWrapper) {\n self._fileOrBlobRejected(fileWrapper.id);\n });\n },\n\n _onValidateBatchCallbackSuccess: function(validationDescriptors, items, params, endpoint, button) {\n var errorMessage,\n itemLimit = this._currentItemLimit,\n proposedNetFilesUploadedOrQueued = this._netUploadedOrQueued;\n\n if (itemLimit === 0 || proposedNetFilesUploadedOrQueued <= itemLimit) {\n if (items.length > 0) {\n this._handleCheckedCallback({\n name: \"onValidate\",\n callback: qq.bind(this._options.callbacks.onValidate, this, validationDescriptors[0], button),\n onSuccess: qq.bind(this._onValidateCallbackSuccess, this, items, 0, params, endpoint),\n onFailure: qq.bind(this._onValidateCallbackFailure, this, items, 0, params, endpoint),\n identifier: \"Item '\" + items[0].file.name + \"', size: \" + items[0].file.size\n });\n }\n else {\n this._itemError(\"noFilesError\");\n }\n }\n else {\n this._onValidateBatchCallbackFailure(items);\n errorMessage = this._options.messages.tooManyItemsError\n .replace(/\\{netItems\\}/g, proposedNetFilesUploadedOrQueued)\n .replace(/\\{itemLimit\\}/g, itemLimit);\n this._batchError(errorMessage);\n }\n },\n\n _onValidateCallbackFailure: function(items, index, params, endpoint) {\n var nextIndex = index + 1;\n\n this._fileOrBlobRejected(items[index].id, items[index].file.name);\n\n this._maybeProcessNextItemAfterOnValidateCallback(false, items, nextIndex, params, endpoint);\n },\n\n _onValidateCallbackSuccess: function(items, index, params, endpoint) {\n var self = this,\n nextIndex = index + 1,\n validationDescriptor = this._getValidationDescriptor(items[index]);\n\n this._validateFileOrBlobData(items[index], validationDescriptor)\n .then(\n function() {\n self._upload(items[index].id, params, endpoint);\n self._maybeProcessNextItemAfterOnValidateCallback(true, items, nextIndex, params, endpoint);\n },\n function() {\n self._maybeProcessNextItemAfterOnValidateCallback(false, items, nextIndex, params, endpoint);\n }\n );\n },\n\n _prepareItemsForUpload: function(items, params, endpoint) {\n if (items.length === 0) {\n this._itemError(\"noFilesError\");\n return;\n }\n\n var validationDescriptors = this._getValidationDescriptors(items),\n buttonId = this._getButtonId(items[0].file),\n button = this._getButton(buttonId);\n\n this._handleCheckedCallback({\n name: \"onValidateBatch\",\n callback: qq.bind(this._options.callbacks.onValidateBatch, this, validationDescriptors, button),\n onSuccess: qq.bind(this._onValidateBatchCallbackSuccess, this, validationDescriptors, items, params, endpoint, button),\n onFailure: qq.bind(this._onValidateBatchCallbackFailure, this, items),\n identifier: \"batch validation\"\n });\n },\n\n _preventLeaveInProgress: function() {\n var self = this;\n\n this._disposeSupport.attach(window, \"beforeunload\", function(e) {\n if (self.getInProgress()) {\n e = e || window.event;\n // for ie, ff\n e.returnValue = self._options.messages.onLeave;\n // for webkit\n return self._options.messages.onLeave;\n }\n });\n },\n\n // Attempts to refresh session data only if the `qq.Session` module exists\n // and a session endpoint has been specified. The `onSessionRequestComplete`\n // callback will be invoked once the refresh is complete.\n _refreshSessionData: function() {\n var self = this,\n options = this._options.session;\n\n /* jshint eqnull:true */\n if (qq.Session && this._options.session.endpoint != null) {\n if (!this._session) {\n qq.extend(options, {cors: this._options.cors});\n\n options.log = qq.bind(this.log, this);\n options.addFileRecord = qq.bind(this._addCannedFile, this);\n\n this._session = new qq.Session(options);\n }\n\n setTimeout(function() {\n self._session.refresh().then(function(response, xhrOrXdr) {\n self._sessionRequestComplete();\n self._options.callbacks.onSessionRequestComplete(response, true, xhrOrXdr);\n\n }, function(response, xhrOrXdr) {\n\n self._options.callbacks.onSessionRequestComplete(response, false, xhrOrXdr);\n });\n }, 0);\n }\n },\n\n _sessionRequestComplete: function() {},\n\n _setSize: function(id, newSize) {\n this._uploadData.updateSize(id, newSize);\n this._totalProgress && this._totalProgress.onNewSize(id);\n },\n\n _shouldAutoRetry: function(id, name, responseJSON) {\n var uploadData = this._uploadData.retrieve({id: id});\n\n /*jshint laxbreak: true */\n if (!this._preventRetries[id]\n && this._options.retry.enableAuto\n && uploadData.status !== qq.status.PAUSED) {\n\n if (this._autoRetries[id] === undefined) {\n this._autoRetries[id] = 0;\n }\n\n if (this._autoRetries[id] < this._options.retry.maxAutoAttempts) {\n this._autoRetries[id] += 1;\n return true;\n }\n }\n\n return false;\n },\n\n _storeForLater: function(id) {\n this._storedIds.push(id);\n },\n\n // Maps a file with the button that was used to select it.\n _trackButton: function(id) {\n var buttonId;\n\n if (qq.supportedFeatures.ajaxUploading) {\n buttonId = this._handler.getFile(id).qqButtonId;\n }\n else {\n buttonId = this._getButtonId(this._handler.getInput(id));\n }\n\n if (buttonId) {\n this._buttonIdsForFileIds[id] = buttonId;\n }\n },\n\n _updateFormSupportAndParams: function(formElementOrId) {\n this._options.form.element = formElementOrId;\n\n this._formSupport = qq.FormSupport && new qq.FormSupport(\n this._options.form, qq.bind(this.uploadStoredFiles, this), qq.bind(this.log, this)\n );\n\n if (this._formSupport && this._formSupport.attachedToForm) {\n this._paramsStore.addReadOnly(null, this._formSupport.getFormInputsAsObject);\n\n this._options.autoUpload = this._formSupport.newAutoUpload;\n if (this._formSupport.newEndpoint) {\n this.setEndpoint(this._formSupport.newEndpoint);\n }\n }\n },\n\n _upload: function(id, params, endpoint) {\n var name = this.getName(id);\n\n if (params) {\n this.setParams(params, id);\n }\n\n if (endpoint) {\n this.setEndpoint(endpoint, id);\n }\n\n this._handleCheckedCallback({\n name: \"onSubmit\",\n callback: qq.bind(this._options.callbacks.onSubmit, this, id, name),\n onSuccess: qq.bind(this._onSubmitCallbackSuccess, this, id, name),\n onFailure: qq.bind(this._fileOrBlobRejected, this, id, name),\n identifier: id\n });\n },\n\n _uploadFile: function(id) {\n if (!this._handler.upload(id)) {\n this._uploadData.setStatus(id, qq.status.QUEUED);\n }\n },\n\n _uploadStoredFiles: function() {\n var idToUpload, stillSubmitting,\n self = this;\n\n while (this._storedIds.length) {\n idToUpload = this._storedIds.shift();\n this._uploadFile(idToUpload);\n }\n\n // If we are still waiting for some files to clear validation, attempt to upload these again in a bit\n stillSubmitting = this.getUploads({status: qq.status.SUBMITTING}).length;\n if (stillSubmitting) {\n qq.log(\"Still waiting for \" + stillSubmitting + \" files to clear submit queue. Will re-parse stored IDs array shortly.\");\n setTimeout(function() {\n self._uploadStoredFiles();\n }, 1000);\n }\n },\n\n /**\n * Performs some internal validation checks on an item, defined in the `validation` option.\n *\n * @param fileWrapper Wrapper containing a `file` along with an `id`\n * @param validationDescriptor Normalized information about the item (`size`, `name`).\n * @returns qq.Promise with appropriate callbacks invoked depending on the validity of the file\n * @private\n */\n _validateFileOrBlobData: function(fileWrapper, validationDescriptor) {\n var self = this,\n file = (function() {\n if (fileWrapper.file instanceof qq.BlobProxy) {\n return fileWrapper.file.referenceBlob;\n }\n return fileWrapper.file;\n }()),\n name = validationDescriptor.name,\n size = validationDescriptor.size,\n buttonId = this._getButtonId(fileWrapper.file),\n validationBase = this._getValidationBase(buttonId),\n validityChecker = new qq.Promise();\n\n validityChecker.then(\n function() {},\n function() {\n self._fileOrBlobRejected(fileWrapper.id, name);\n });\n\n if (qq.isFileOrInput(file) && !this._isAllowedExtension(validationBase.allowedExtensions, name)) {\n this._itemError(\"typeError\", name, file);\n return validityChecker.failure();\n }\n\n if (!this._options.validation.allowEmpty && size === 0) {\n this._itemError(\"emptyError\", name, file);\n return validityChecker.failure();\n }\n\n if (size > 0 && validationBase.sizeLimit && size > validationBase.sizeLimit) {\n this._itemError(\"sizeError\", name, file);\n return validityChecker.failure();\n }\n\n if (size > 0 && size < validationBase.minSizeLimit) {\n this._itemError(\"minSizeError\", name, file);\n return validityChecker.failure();\n }\n\n if (qq.ImageValidation && qq.supportedFeatures.imagePreviews && qq.isFile(file)) {\n new qq.ImageValidation(file, qq.bind(self.log, self)).validate(validationBase.image).then(\n validityChecker.success,\n function(errorCode) {\n self._itemError(errorCode + \"ImageError\", name, file);\n validityChecker.failure();\n }\n );\n }\n else {\n validityChecker.success();\n }\n\n return validityChecker;\n },\n\n _wrapCallbacks: function() {\n var self, safeCallback, prop;\n\n self = this;\n\n safeCallback = function(name, callback, args) {\n var errorMsg;\n\n try {\n return callback.apply(self, args);\n }\n catch (exception) {\n errorMsg = exception.message || exception.toString();\n self.log(\"Caught exception in '\" + name + \"' callback - \" + errorMsg, \"error\");\n }\n };\n\n /* jshint forin: false, loopfunc: true */\n for (prop in this._options.callbacks) {\n (function() {\n var callbackName, callbackFunc;\n callbackName = prop;\n callbackFunc = self._options.callbacks[callbackName];\n self._options.callbacks[callbackName] = function() {\n return safeCallback(callbackName, callbackFunc, arguments);\n };\n }());\n }\n }\n };\n}());\n","/*globals qq*/\n(function() {\n \"use strict\";\n\n qq.FineUploaderBasic = function(o) {\n var self = this;\n\n // These options define FineUploaderBasic mode.\n this._options = {\n debug: false,\n button: null,\n multiple: true,\n maxConnections: 3,\n disableCancelForFormUploads: false,\n autoUpload: true,\n\n request: {\n customHeaders: {},\n endpoint: \"/server/upload\",\n filenameParam: \"qqfilename\",\n forceMultipart: true,\n inputName: \"qqfile\",\n method: \"POST\",\n params: {},\n paramsInBody: true,\n totalFileSizeName: \"qqtotalfilesize\",\n uuidName: \"qquuid\"\n },\n\n validation: {\n allowedExtensions: [],\n sizeLimit: 0,\n minSizeLimit: 0,\n itemLimit: 0,\n stopOnFirstInvalidFile: true,\n acceptFiles: null,\n image: {\n maxHeight: 0,\n maxWidth: 0,\n minHeight: 0,\n minWidth: 0\n },\n allowEmpty: false\n },\n\n callbacks: {\n onSubmit: function(id, name) {},\n onSubmitted: function(id, name) {},\n onComplete: function(id, name, responseJSON, maybeXhr) {},\n onAllComplete: function(successful, failed) {},\n onCancel: function(id, name) {},\n onUpload: function(id, name) {},\n onUploadChunk: function(id, name, chunkData) {},\n onUploadChunkSuccess: function(id, chunkData, responseJSON, xhr) {},\n onResume: function(id, fileName, chunkData) {},\n onProgress: function(id, name, loaded, total) {},\n onTotalProgress: function(loaded, total) {},\n onError: function(id, name, reason, maybeXhrOrXdr) {},\n onAutoRetry: function(id, name, attemptNumber) {},\n onManualRetry: function(id, name) {},\n onValidateBatch: function(fileOrBlobData) {},\n onValidate: function(fileOrBlobData) {},\n onSubmitDelete: function(id) {},\n onDelete: function(id) {},\n onDeleteComplete: function(id, xhrOrXdr, isError) {},\n onPasteReceived: function(blob) {},\n onStatusChange: function(id, oldStatus, newStatus) {},\n onSessionRequestComplete: function(response, success, xhrOrXdr) {}\n },\n\n messages: {\n typeError: \"{file} has an invalid extension. Valid extension(s): {extensions}.\",\n sizeError: \"{file} is too large, maximum file size is {sizeLimit}.\",\n minSizeError: \"{file} is too small, minimum file size is {minSizeLimit}.\",\n emptyError: \"{file} is empty, please select files again without it.\",\n noFilesError: \"No files to upload.\",\n tooManyItemsError: \"Too many items ({netItems}) would be uploaded. Item limit is {itemLimit}.\",\n maxHeightImageError: \"Image is too tall.\",\n maxWidthImageError: \"Image is too wide.\",\n minHeightImageError: \"Image is not tall enough.\",\n minWidthImageError: \"Image is not wide enough.\",\n retryFailTooManyItems: \"Retry failed - you have reached your file limit.\",\n onLeave: \"The files are being uploaded, if you leave now the upload will be canceled.\",\n unsupportedBrowserIos8Safari: \"Unrecoverable error - this browser does not permit file uploading of any kind due to serious bugs in iOS8 Safari. Please use iOS8 Chrome until Apple fixes these issues.\"\n },\n\n retry: {\n enableAuto: false,\n maxAutoAttempts: 3,\n autoAttemptDelay: 5,\n preventRetryResponseProperty: \"preventRetry\"\n },\n\n classes: {\n buttonHover: \"qq-upload-button-hover\",\n buttonFocus: \"qq-upload-button-focus\"\n },\n\n chunking: {\n enabled: false,\n concurrent: {\n enabled: false\n },\n mandatory: false,\n paramNames: {\n partIndex: \"qqpartindex\",\n partByteOffset: \"qqpartbyteoffset\",\n chunkSize: \"qqchunksize\",\n totalFileSize: \"qqtotalfilesize\",\n totalParts: \"qqtotalparts\"\n },\n partSize: 2000000,\n // only relevant for traditional endpoints, only required when concurrent.enabled === true\n success: {\n endpoint: null\n }\n },\n\n resume: {\n enabled: false,\n recordsExpireIn: 7, //days\n paramNames: {\n resuming: \"qqresume\"\n }\n },\n\n formatFileName: function(fileOrBlobName) {\n return fileOrBlobName;\n },\n\n text: {\n defaultResponseError: \"Upload failure reason unknown\",\n fileInputTitle: \"file input\",\n sizeSymbols: [\"kB\", \"MB\", \"GB\", \"TB\", \"PB\", \"EB\"]\n },\n\n deleteFile: {\n enabled: false,\n method: \"DELETE\",\n endpoint: \"/server/upload\",\n customHeaders: {},\n params: {}\n },\n\n cors: {\n expected: false,\n sendCredentials: false,\n allowXdr: false\n },\n\n blobs: {\n defaultName: \"misc_data\"\n },\n\n paste: {\n targetElement: null,\n defaultName: \"pasted_image\"\n },\n\n camera: {\n ios: false,\n\n // if ios is true: button is null means target the default button, otherwise target the button specified\n button: null\n },\n\n // This refers to additional upload buttons to be handled by Fine Uploader.\n // Each element is an object, containing `element` as the only required\n // property. The `element` must be a container that will ultimately\n // contain an invisible ` ` created by Fine Uploader.\n // Optional properties of each object include `multiple`, `validation`,\n // and `folders`.\n extraButtons: [],\n\n // Depends on the session module. Used to query the server for an initial file list\n // during initialization and optionally after a `reset`.\n session: {\n endpoint: null,\n params: {},\n customHeaders: {},\n refreshOnReset: true\n },\n\n // Send parameters associated with an existing form along with the files\n form: {\n // Element ID, HTMLElement, or null\n element: \"qq-form\",\n\n // Overrides the base `autoUpload`, unless `element` is null.\n autoUpload: false,\n\n // true = upload files on form submission (and squelch submit event)\n interceptSubmit: true\n },\n\n // scale images client side, upload a new file for each scaled version\n scaling: {\n customResizer: null,\n\n // send the original file as well\n sendOriginal: true,\n\n // fox orientation for scaled images\n orient: true,\n\n // If null, scaled image type will match reference image type. This value will be referred to\n // for any size record that does not specific a type.\n defaultType: null,\n\n defaultQuality: 80,\n\n failureText: \"Failed to scale\",\n\n includeExif: false,\n\n // metadata about each requested scaled version\n sizes: []\n },\n\n workarounds: {\n iosEmptyVideos: true,\n ios8SafariUploads: true,\n ios8BrowserCrash: false\n }\n };\n\n // Replace any default options with user defined ones\n qq.extend(this._options, o, true);\n\n this._buttons = [];\n this._extraButtonSpecs = {};\n this._buttonIdsForFileIds = [];\n\n this._wrapCallbacks();\n this._disposeSupport = new qq.DisposeSupport();\n\n this._storedIds = [];\n this._autoRetries = [];\n this._retryTimeouts = [];\n this._preventRetries = [];\n this._thumbnailUrls = [];\n\n this._netUploadedOrQueued = 0;\n this._netUploaded = 0;\n this._uploadData = this._createUploadDataTracker();\n\n this._initFormSupportAndParams();\n\n this._customHeadersStore = this._createStore(this._options.request.customHeaders);\n this._deleteFileCustomHeadersStore = this._createStore(this._options.deleteFile.customHeaders);\n\n this._deleteFileParamsStore = this._createStore(this._options.deleteFile.params);\n\n this._endpointStore = this._createStore(this._options.request.endpoint);\n this._deleteFileEndpointStore = this._createStore(this._options.deleteFile.endpoint);\n\n this._handler = this._createUploadHandler();\n\n this._deleteHandler = qq.DeleteFileAjaxRequester && this._createDeleteHandler();\n\n if (this._options.button) {\n this._defaultButtonId = this._createUploadButton({\n element: this._options.button,\n title: this._options.text.fileInputTitle\n }).getButtonId();\n }\n\n this._generateExtraButtonSpecs();\n\n this._handleCameraAccess();\n\n if (this._options.paste.targetElement) {\n if (qq.PasteSupport) {\n this._pasteHandler = this._createPasteHandler();\n }\n else {\n this.log(\"Paste support module not found\", \"error\");\n }\n }\n\n this._preventLeaveInProgress();\n\n this._imageGenerator = qq.ImageGenerator && new qq.ImageGenerator(qq.bind(this.log, this));\n this._refreshSessionData();\n\n this._succeededSinceLastAllComplete = [];\n this._failedSinceLastAllComplete = [];\n\n this._scaler = (qq.Scaler && new qq.Scaler(this._options.scaling, qq.bind(this.log, this))) || {};\n if (this._scaler.enabled) {\n this._customNewFileHandler = qq.bind(this._scaler.handleNewFile, this._scaler);\n }\n\n if (qq.TotalProgress && qq.supportedFeatures.progressBar) {\n this._totalProgress = new qq.TotalProgress(\n qq.bind(this._onTotalProgress, this),\n\n function(id) {\n var entry = self._uploadData.retrieve({id: id});\n return (entry && entry.size) || 0;\n }\n );\n }\n\n this._currentItemLimit = this._options.validation.itemLimit;\n };\n\n // Define the private & public API methods.\n qq.FineUploaderBasic.prototype = qq.basePublicApi;\n qq.extend(qq.FineUploaderBasic.prototype, qq.basePrivateApi);\n}());\n","/*globals qq, XDomainRequest*/\n/** Generic class for sending non-upload ajax requests and handling the associated responses **/\nqq.AjaxRequester = function(o) {\n \"use strict\";\n\n var log, shouldParamsBeInQueryString,\n queue = [],\n requestData = {},\n options = {\n acceptHeader: null,\n validMethods: [\"PATCH\", \"POST\", \"PUT\"],\n method: \"POST\",\n contentType: \"application/x-www-form-urlencoded\",\n maxConnections: 3,\n customHeaders: {},\n endpointStore: {},\n paramsStore: {},\n mandatedParams: {},\n allowXRequestedWithAndCacheControl: true,\n successfulResponseCodes: {\n DELETE: [200, 202, 204],\n PATCH: [200, 201, 202, 203, 204],\n POST: [200, 201, 202, 203, 204],\n PUT: [200, 201, 202, 203, 204],\n GET: [200]\n },\n cors: {\n expected: false,\n sendCredentials: false\n },\n log: function(str, level) {},\n onSend: function(id) {},\n onComplete: function(id, xhrOrXdr, isError) {},\n onProgress: null\n };\n\n qq.extend(options, o);\n log = options.log;\n\n if (qq.indexOf(options.validMethods, options.method) < 0) {\n throw new Error(\"'\" + options.method + \"' is not a supported method for this type of request!\");\n }\n\n // [Simple methods](http://www.w3.org/TR/cors/#simple-method)\n // are defined by the W3C in the CORS spec as a list of methods that, in part,\n // make a CORS request eligible to be exempt from preflighting.\n function isSimpleMethod() {\n return qq.indexOf([\"GET\", \"POST\", \"HEAD\"], options.method) >= 0;\n }\n\n // [Simple headers](http://www.w3.org/TR/cors/#simple-header)\n // are defined by the W3C in the CORS spec as a list of headers that, in part,\n // make a CORS request eligible to be exempt from preflighting.\n function containsNonSimpleHeaders(headers) {\n var containsNonSimple = false;\n\n qq.each(containsNonSimple, function(idx, header) {\n if (qq.indexOf([\"Accept\", \"Accept-Language\", \"Content-Language\", \"Content-Type\"], header) < 0) {\n containsNonSimple = true;\n return false;\n }\n });\n\n return containsNonSimple;\n }\n\n function isXdr(xhr) {\n //The `withCredentials` test is a commonly accepted way to determine if XHR supports CORS.\n return options.cors.expected && xhr.withCredentials === undefined;\n }\n\n // Returns either a new `XMLHttpRequest` or `XDomainRequest` instance.\n function getCorsAjaxTransport() {\n var xhrOrXdr;\n\n if (window.XMLHttpRequest || window.ActiveXObject) {\n xhrOrXdr = qq.createXhrInstance();\n\n if (xhrOrXdr.withCredentials === undefined) {\n xhrOrXdr = new XDomainRequest();\n // Workaround for XDR bug in IE9 - https://social.msdn.microsoft.com/Forums/ie/en-US/30ef3add-767c-4436-b8a9-f1ca19b4812e/ie9-rtm-xdomainrequest-issued-requests-may-abort-if-all-event-handlers-not-specified?forum=iewebdevelopment\n xhrOrXdr.onload = function() {};\n xhrOrXdr.onerror = function() {};\n xhrOrXdr.ontimeout = function() {};\n xhrOrXdr.onprogress = function() {};\n }\n }\n\n return xhrOrXdr;\n }\n\n // Returns either a new XHR/XDR instance, or an existing one for the associated `File` or `Blob`.\n function getXhrOrXdr(id, suppliedXhr) {\n var xhrOrXdr = requestData[id].xhr;\n\n if (!xhrOrXdr) {\n if (suppliedXhr) {\n xhrOrXdr = suppliedXhr;\n }\n else {\n if (options.cors.expected) {\n xhrOrXdr = getCorsAjaxTransport();\n }\n else {\n xhrOrXdr = qq.createXhrInstance();\n }\n }\n\n requestData[id].xhr = xhrOrXdr;\n }\n\n return xhrOrXdr;\n }\n\n // Removes element from queue, sends next request\n function dequeue(id) {\n var i = qq.indexOf(queue, id),\n max = options.maxConnections,\n nextId;\n\n delete requestData[id];\n queue.splice(i, 1);\n\n if (queue.length >= max && i < max) {\n nextId = queue[max - 1];\n sendRequest(nextId);\n }\n }\n\n function onComplete(id, xdrError) {\n var xhr = getXhrOrXdr(id),\n method = options.method,\n isError = xdrError === true;\n\n dequeue(id);\n\n if (isError) {\n log(method + \" request for \" + id + \" has failed\", \"error\");\n }\n else if (!isXdr(xhr) && !isResponseSuccessful(xhr.status)) {\n isError = true;\n log(method + \" request for \" + id + \" has failed - response code \" + xhr.status, \"error\");\n }\n\n options.onComplete(id, xhr, isError);\n }\n\n function getParams(id) {\n var onDemandParams = requestData[id].additionalParams,\n mandatedParams = options.mandatedParams,\n params;\n\n if (options.paramsStore.get) {\n params = options.paramsStore.get(id);\n }\n\n if (onDemandParams) {\n qq.each(onDemandParams, function(name, val) {\n params = params || {};\n params[name] = val;\n });\n }\n\n if (mandatedParams) {\n qq.each(mandatedParams, function(name, val) {\n params = params || {};\n params[name] = val;\n });\n }\n\n return params;\n }\n\n function sendRequest(id, optXhr) {\n var xhr = getXhrOrXdr(id, optXhr),\n method = options.method,\n params = getParams(id),\n payload = requestData[id].payload,\n url;\n\n options.onSend(id);\n\n url = createUrl(id, params, requestData[id].additionalQueryParams);\n\n // XDR and XHR status detection APIs differ a bit.\n if (isXdr(xhr)) {\n xhr.onload = getXdrLoadHandler(id);\n xhr.onerror = getXdrErrorHandler(id);\n }\n else {\n xhr.onreadystatechange = getXhrReadyStateChangeHandler(id);\n }\n\n registerForUploadProgress(id);\n\n // The last parameter is assumed to be ignored if we are actually using `XDomainRequest`.\n xhr.open(method, url, true);\n\n // Instruct the transport to send cookies along with the CORS request,\n // unless we are using `XDomainRequest`, which is not capable of this.\n if (options.cors.expected && options.cors.sendCredentials && !isXdr(xhr)) {\n xhr.withCredentials = true;\n }\n\n setHeaders(id);\n\n log(\"Sending \" + method + \" request for \" + id);\n\n if (payload) {\n xhr.send(payload);\n }\n else if (shouldParamsBeInQueryString || !params) {\n xhr.send();\n }\n else if (params && options.contentType && options.contentType.toLowerCase().indexOf(\"application/x-www-form-urlencoded\") >= 0) {\n xhr.send(qq.obj2url(params, \"\"));\n }\n else if (params && options.contentType && options.contentType.toLowerCase().indexOf(\"application/json\") >= 0) {\n xhr.send(JSON.stringify(params));\n }\n else {\n xhr.send(params);\n }\n\n return xhr;\n }\n\n function createUrl(id, params, additionalQueryParams) {\n var endpoint = options.endpointStore.get(id),\n addToPath = requestData[id].addToPath;\n\n /*jshint -W116,-W041 */\n if (addToPath != undefined) {\n endpoint += \"/\" + addToPath;\n }\n\n if (shouldParamsBeInQueryString && params) {\n endpoint = qq.obj2url(params, endpoint);\n }\n\n if (additionalQueryParams) {\n endpoint = qq.obj2url(additionalQueryParams, endpoint);\n }\n\n return endpoint;\n }\n\n // Invoked by the UA to indicate a number of possible states that describe\n // a live `XMLHttpRequest` transport.\n function getXhrReadyStateChangeHandler(id) {\n return function() {\n if (getXhrOrXdr(id).readyState === 4) {\n onComplete(id);\n }\n };\n }\n\n function registerForUploadProgress(id) {\n var onProgress = options.onProgress;\n\n if (onProgress) {\n getXhrOrXdr(id).upload.onprogress = function(e) {\n if (e.lengthComputable) {\n onProgress(id, e.loaded, e.total);\n }\n };\n }\n }\n\n // This will be called by IE to indicate **success** for an associated\n // `XDomainRequest` transported request.\n function getXdrLoadHandler(id) {\n return function() {\n onComplete(id);\n };\n }\n\n // This will be called by IE to indicate **failure** for an associated\n // `XDomainRequest` transported request.\n function getXdrErrorHandler(id) {\n return function() {\n onComplete(id, true);\n };\n }\n\n function setHeaders(id) {\n var xhr = getXhrOrXdr(id),\n customHeaders = options.customHeaders,\n onDemandHeaders = requestData[id].additionalHeaders || {},\n method = options.method,\n allHeaders = {};\n\n // If XDomainRequest is being used, we can't set headers, so just ignore this block.\n if (!isXdr(xhr)) {\n options.acceptHeader && xhr.setRequestHeader(\"Accept\", options.acceptHeader);\n\n // Only attempt to add X-Requested-With & Cache-Control if permitted\n if (options.allowXRequestedWithAndCacheControl) {\n // Do not add X-Requested-With & Cache-Control if this is a cross-origin request\n // OR the cross-origin request contains a non-simple method or header.\n // This is done to ensure a preflight is not triggered exclusively based on the\n // addition of these 2 non-simple headers.\n if (!options.cors.expected || (!isSimpleMethod() || containsNonSimpleHeaders(customHeaders))) {\n xhr.setRequestHeader(\"X-Requested-With\", \"XMLHttpRequest\");\n xhr.setRequestHeader(\"Cache-Control\", \"no-cache\");\n }\n }\n\n if (options.contentType && (method === \"POST\" || method === \"PUT\")) {\n xhr.setRequestHeader(\"Content-Type\", options.contentType);\n }\n\n qq.extend(allHeaders, qq.isFunction(customHeaders) ? customHeaders(id) : customHeaders);\n qq.extend(allHeaders, onDemandHeaders);\n\n qq.each(allHeaders, function(name, val) {\n xhr.setRequestHeader(name, val);\n });\n }\n }\n\n function isResponseSuccessful(responseCode) {\n return qq.indexOf(options.successfulResponseCodes[options.method], responseCode) >= 0;\n }\n\n function prepareToSend(id, optXhr, addToPath, additionalParams, additionalQueryParams, additionalHeaders, payload) {\n requestData[id] = {\n addToPath: addToPath,\n additionalParams: additionalParams,\n additionalQueryParams: additionalQueryParams,\n additionalHeaders: additionalHeaders,\n payload: payload\n };\n\n var len = queue.push(id);\n\n // if too many active connections, wait...\n if (len <= options.maxConnections) {\n return sendRequest(id, optXhr);\n }\n }\n\n shouldParamsBeInQueryString = options.method === \"GET\" || options.method === \"DELETE\";\n\n qq.extend(this, {\n // Start the process of sending the request. The ID refers to the file associated with the request.\n initTransport: function(id) {\n var path, params, headers, payload, cacheBuster, additionalQueryParams;\n\n return {\n // Optionally specify the end of the endpoint path for the request.\n withPath: function(appendToPath) {\n path = appendToPath;\n return this;\n },\n\n // Optionally specify additional parameters to send along with the request.\n // These will be added to the query string for GET/DELETE requests or the payload\n // for POST/PUT requests. The Content-Type of the request will be used to determine\n // how these parameters should be formatted as well.\n withParams: function(additionalParams) {\n params = additionalParams;\n return this;\n },\n\n withQueryParams: function(_additionalQueryParams_) {\n additionalQueryParams = _additionalQueryParams_;\n return this;\n },\n\n // Optionally specify additional headers to send along with the request.\n withHeaders: function(additionalHeaders) {\n headers = additionalHeaders;\n return this;\n },\n\n // Optionally specify a payload/body for the request.\n withPayload: function(thePayload) {\n payload = thePayload;\n return this;\n },\n\n // Appends a cache buster (timestamp) to the request URL as a query parameter (only if GET or DELETE)\n withCacheBuster: function() {\n cacheBuster = true;\n return this;\n },\n\n // Send the constructed request.\n send: function(optXhr) {\n if (cacheBuster && qq.indexOf([\"GET\", \"DELETE\"], options.method) >= 0) {\n params.qqtimestamp = new Date().getTime();\n }\n\n return prepareToSend(id, optXhr, path, params, additionalQueryParams, headers, payload);\n }\n };\n },\n\n canceled: function(id) {\n dequeue(id);\n }\n });\n};\n","/* globals qq */\n/**\n * Common upload handler functions.\n *\n * @constructor\n */\nqq.UploadHandler = function(spec) {\n \"use strict\";\n\n var proxy = spec.proxy,\n fileState = {},\n onCancel = proxy.onCancel,\n getName = proxy.getName;\n\n qq.extend(this, {\n add: function(id, fileItem) {\n fileState[id] = fileItem;\n fileState[id].temp = {};\n },\n\n cancel: function(id) {\n var self = this,\n cancelFinalizationEffort = new qq.Promise(),\n onCancelRetVal = onCancel(id, getName(id), cancelFinalizationEffort);\n\n onCancelRetVal.then(function() {\n if (self.isValid(id)) {\n fileState[id].canceled = true;\n self.expunge(id);\n }\n cancelFinalizationEffort.success();\n });\n },\n\n expunge: function(id) {\n delete fileState[id];\n },\n\n getThirdPartyFileId: function(id) {\n return fileState[id].key;\n },\n\n isValid: function(id) {\n return fileState[id] !== undefined;\n },\n\n reset: function() {\n fileState = {};\n },\n\n _getFileState: function(id) {\n return fileState[id];\n },\n\n _setThirdPartyFileId: function(id, thirdPartyFileId) {\n fileState[id].key = thirdPartyFileId;\n },\n\n _wasCanceled: function(id) {\n return !!fileState[id].canceled;\n }\n });\n};\n","/*globals qq*/\n/**\n * Base upload handler module. Controls more specific handlers.\n *\n * @param o Options. Passed along to the specific handler submodule as well.\n * @param namespace [optional] Namespace for the specific handler.\n */\nqq.UploadHandlerController = function(o, namespace) {\n \"use strict\";\n\n var controller = this,\n chunkingPossible = false,\n concurrentChunkingPossible = false,\n chunking, preventRetryResponse, log, handler,\n\n options = {\n paramsStore: {},\n maxConnections: 3, // maximum number of concurrent uploads\n chunking: {\n enabled: false,\n multiple: {\n enabled: false\n }\n },\n log: function(str, level) {},\n onProgress: function(id, fileName, loaded, total) {},\n onComplete: function(id, fileName, response, xhr) {},\n onCancel: function(id, fileName) {},\n onUploadPrep: function(id) {}, // Called if non-trivial operations will be performed before onUpload\n onUpload: function(id, fileName) {},\n onUploadChunk: function(id, fileName, chunkData) {},\n onUploadChunkSuccess: function(id, chunkData, response, xhr) {},\n onAutoRetry: function(id, fileName, response, xhr) {},\n onResume: function(id, fileName, chunkData) {},\n onUuidChanged: function(id, newUuid) {},\n getName: function(id) {},\n setSize: function(id, newSize) {},\n isQueued: function(id) {},\n getIdsInProxyGroup: function(id) {},\n getIdsInBatch: function(id) {}\n },\n\n chunked = {\n // Called when each chunk has uploaded successfully\n done: function(id, chunkIdx, response, xhr) {\n var chunkData = handler._getChunkData(id, chunkIdx);\n\n handler._getFileState(id).attemptingResume = false;\n\n delete handler._getFileState(id).temp.chunkProgress[chunkIdx];\n handler._getFileState(id).loaded += chunkData.size;\n\n options.onUploadChunkSuccess(id, handler._getChunkDataForCallback(chunkData), response, xhr);\n },\n\n // Called when all chunks have been successfully uploaded and we want to ask the handler to perform any\n // logic associated with closing out the file, such as combining the chunks.\n finalize: function(id) {\n var size = options.getSize(id),\n name = options.getName(id);\n\n log(\"All chunks have been uploaded for \" + id + \" - finalizing....\");\n handler.finalizeChunks(id).then(\n function(response, xhr) {\n log(\"Finalize successful for \" + id);\n\n var normaizedResponse = upload.normalizeResponse(response, true);\n\n options.onProgress(id, name, size, size);\n handler._maybeDeletePersistedChunkData(id);\n upload.cleanup(id, normaizedResponse, xhr);\n },\n function(response, xhr) {\n var normaizedResponse = upload.normalizeResponse(response, false);\n\n log(\"Problem finalizing chunks for file ID \" + id + \" - \" + normaizedResponse.error, \"error\");\n\n if (normaizedResponse.reset) {\n chunked.reset(id);\n }\n\n if (!options.onAutoRetry(id, name, normaizedResponse, xhr)) {\n upload.cleanup(id, normaizedResponse, xhr);\n }\n }\n );\n },\n\n handleFailure: function(chunkIdx, id, response, xhr) {\n var name = options.getName(id);\n\n log(\"Chunked upload request failed for \" + id + \", chunk \" + chunkIdx);\n\n handler.clearCachedChunk(id, chunkIdx);\n\n var responseToReport = upload.normalizeResponse(response, false),\n inProgressIdx;\n\n if (responseToReport.reset) {\n chunked.reset(id);\n }\n else {\n inProgressIdx = qq.indexOf(handler._getFileState(id).chunking.inProgress, chunkIdx);\n if (inProgressIdx >= 0) {\n handler._getFileState(id).chunking.inProgress.splice(inProgressIdx, 1);\n handler._getFileState(id).chunking.remaining.unshift(chunkIdx);\n }\n }\n\n // We may have aborted all other in-progress chunks for this file due to a failure.\n // If so, ignore the failures associated with those aborts.\n if (!handler._getFileState(id).temp.ignoreFailure) {\n // If this chunk has failed, we want to ignore all other failures of currently in-progress\n // chunks since they will be explicitly aborted\n if (concurrentChunkingPossible) {\n handler._getFileState(id).temp.ignoreFailure = true;\n\n log(qq.format(\"Going to attempt to abort these chunks: {}. These are currently in-progress: {}.\", JSON.stringify(Object.keys(handler._getXhrs(id))), JSON.stringify(handler._getFileState(id).chunking.inProgress)));\n qq.each(handler._getXhrs(id), function(ckid, ckXhr) {\n log(qq.format(\"Attempting to abort file {}.{}. XHR readyState {}. \", id, ckid, ckXhr.readyState));\n ckXhr.abort();\n // Flag the transport, in case we are waiting for some other async operation\n // to complete before attempting to upload the chunk\n ckXhr._cancelled = true;\n });\n\n // We must indicate that all aborted chunks are no longer in progress\n handler.moveInProgressToRemaining(id);\n\n // Free up any connections used by these chunks, but don't allow any\n // other files to take up the connections (until we have exhausted all auto-retries)\n connectionManager.free(id, true);\n }\n\n if (!options.onAutoRetry(id, name, responseToReport, xhr)) {\n // If one chunk fails, abort all of the others to avoid odd race conditions that occur\n // if a chunk succeeds immediately after one fails before we have determined if the upload\n // is a failure or not.\n upload.cleanup(id, responseToReport, xhr);\n }\n }\n },\n\n hasMoreParts: function(id) {\n return !!handler._getFileState(id).chunking.remaining.length;\n },\n\n nextPart: function(id) {\n var nextIdx = handler._getFileState(id).chunking.remaining.shift();\n\n if (nextIdx >= handler._getTotalChunks(id)) {\n nextIdx = null;\n }\n\n return nextIdx;\n },\n\n reset: function(id) {\n log(\"Server or callback has ordered chunking effort to be restarted on next attempt for item ID \" + id, \"error\");\n\n handler._maybeDeletePersistedChunkData(id);\n handler.reevaluateChunking(id);\n handler._getFileState(id).loaded = 0;\n },\n\n sendNext: function(id) {\n var size = options.getSize(id),\n name = options.getName(id),\n chunkIdx = chunked.nextPart(id),\n chunkData = handler._getChunkData(id, chunkIdx),\n resuming = handler._getFileState(id).attemptingResume,\n inProgressChunks = handler._getFileState(id).chunking.inProgress || [];\n\n if (handler._getFileState(id).loaded == null) {\n handler._getFileState(id).loaded = 0;\n }\n\n // Don't follow-through with the resume attempt if the integrator returns false from onResume\n if (resuming && options.onResume(id, name, chunkData) === false) {\n chunked.reset(id);\n chunkIdx = chunked.nextPart(id);\n chunkData = handler._getChunkData(id, chunkIdx);\n resuming = false;\n }\n\n // If all chunks have already uploaded successfully, we must be re-attempting the finalize step.\n if (chunkIdx == null && inProgressChunks.length === 0) {\n chunked.finalize(id);\n }\n\n // Send the next chunk\n else {\n log(qq.format(\"Sending chunked upload request for item {}.{}, bytes {}-{} of {}.\", id, chunkIdx, chunkData.start + 1, chunkData.end, size));\n options.onUploadChunk(id, name, handler._getChunkDataForCallback(chunkData));\n inProgressChunks.push(chunkIdx);\n handler._getFileState(id).chunking.inProgress = inProgressChunks;\n\n if (concurrentChunkingPossible) {\n connectionManager.open(id, chunkIdx);\n }\n\n if (concurrentChunkingPossible && connectionManager.available() && handler._getFileState(id).chunking.remaining.length) {\n chunked.sendNext(id);\n }\n\n if (chunkData.blob.size === 0) {\n log(qq.format(\"Chunk {} for file {} will not be uploaded, zero sized chunk.\", chunkIdx, id), \"error\");\n chunked.handleFailure(chunkIdx, id, \"File is no longer available\", null);\n }\n else {\n handler.uploadChunk(id, chunkIdx, resuming).then(\n // upload chunk success\n function success(response, xhr) {\n log(\"Chunked upload request succeeded for \" + id + \", chunk \" + chunkIdx);\n\n handler.clearCachedChunk(id, chunkIdx);\n\n var inProgressChunks = handler._getFileState(id).chunking.inProgress || [],\n responseToReport = upload.normalizeResponse(response, true),\n inProgressChunkIdx = qq.indexOf(inProgressChunks, chunkIdx);\n\n log(qq.format(\"Chunk {} for file {} uploaded successfully.\", chunkIdx, id));\n\n chunked.done(id, chunkIdx, responseToReport, xhr);\n\n if (inProgressChunkIdx >= 0) {\n inProgressChunks.splice(inProgressChunkIdx, 1);\n }\n\n handler._maybePersistChunkedState(id);\n\n if (!chunked.hasMoreParts(id) && inProgressChunks.length === 0) {\n chunked.finalize(id);\n }\n else if (chunked.hasMoreParts(id)) {\n chunked.sendNext(id);\n }\n else {\n log(qq.format(\"File ID {} has no more chunks to send and these chunk indexes are still marked as in-progress: {}\", id, JSON.stringify(inProgressChunks)));\n }\n },\n\n // upload chunk failure\n function failure(response, xhr) {\n chunked.handleFailure(chunkIdx, id, response, xhr);\n }\n )\n .done(function() {\n handler.clearXhr(id, chunkIdx);\n });\n }\n }\n }\n },\n\n connectionManager = {\n _open: [],\n _openChunks: {},\n _waiting: [],\n\n available: function() {\n var max = options.maxConnections,\n openChunkEntriesCount = 0,\n openChunksCount = 0;\n\n qq.each(connectionManager._openChunks, function(fileId, openChunkIndexes) {\n openChunkEntriesCount++;\n openChunksCount += openChunkIndexes.length;\n });\n\n return max - (connectionManager._open.length - openChunkEntriesCount + openChunksCount);\n },\n\n /**\n * Removes element from queue, starts upload of next\n */\n free: function(id, dontAllowNext) {\n var allowNext = !dontAllowNext,\n waitingIndex = qq.indexOf(connectionManager._waiting, id),\n connectionsIndex = qq.indexOf(connectionManager._open, id),\n nextId;\n\n delete connectionManager._openChunks[id];\n\n if (upload.getProxyOrBlob(id) instanceof qq.BlobProxy) {\n log(\"Generated blob upload has ended for \" + id + \", disposing generated blob.\");\n delete handler._getFileState(id).file;\n }\n\n // If this file was not consuming a connection, it was just waiting, so remove it from the waiting array\n if (waitingIndex >= 0) {\n connectionManager._waiting.splice(waitingIndex, 1);\n }\n // If this file was consuming a connection, allow the next file to be uploaded\n else if (allowNext && connectionsIndex >= 0) {\n connectionManager._open.splice(connectionsIndex, 1);\n\n nextId = connectionManager._waiting.shift();\n if (nextId >= 0) {\n connectionManager._open.push(nextId);\n upload.start(nextId);\n }\n }\n },\n\n getWaitingOrConnected: function() {\n var waitingOrConnected = [];\n\n // Chunked files may have multiple connections open per chunk (if concurrent chunking is enabled)\n // We need to grab the file ID of any file that has at least one chunk consuming a connection.\n qq.each(connectionManager._openChunks, function(fileId, chunks) {\n if (chunks && chunks.length) {\n waitingOrConnected.push(parseInt(fileId));\n }\n });\n\n // For non-chunked files, only one connection will be consumed per file.\n // This is where we aggregate those file IDs.\n qq.each(connectionManager._open, function(idx, fileId) {\n if (!connectionManager._openChunks[fileId]) {\n waitingOrConnected.push(parseInt(fileId));\n }\n });\n\n // There may be files waiting for a connection.\n waitingOrConnected = waitingOrConnected.concat(connectionManager._waiting);\n\n return waitingOrConnected;\n },\n\n isUsingConnection: function(id) {\n return qq.indexOf(connectionManager._open, id) >= 0;\n },\n\n open: function(id, chunkIdx) {\n if (chunkIdx == null) {\n connectionManager._waiting.push(id);\n }\n\n if (connectionManager.available()) {\n if (chunkIdx == null) {\n connectionManager._waiting.pop();\n connectionManager._open.push(id);\n }\n else {\n (function() {\n var openChunksEntry = connectionManager._openChunks[id] || [];\n openChunksEntry.push(chunkIdx);\n connectionManager._openChunks[id] = openChunksEntry;\n }());\n }\n\n return true;\n }\n\n return false;\n },\n\n reset: function() {\n connectionManager._waiting = [];\n connectionManager._open = [];\n }\n },\n\n simple = {\n send: function(id, name) {\n handler._getFileState(id).loaded = 0;\n\n log(\"Sending simple upload request for \" + id);\n handler.uploadFile(id).then(\n function(response, optXhr) {\n log(\"Simple upload request succeeded for \" + id);\n\n var responseToReport = upload.normalizeResponse(response, true),\n size = options.getSize(id);\n\n options.onProgress(id, name, size, size);\n upload.maybeNewUuid(id, responseToReport);\n upload.cleanup(id, responseToReport, optXhr);\n },\n\n function(response, optXhr) {\n log(\"Simple upload request failed for \" + id);\n\n var responseToReport = upload.normalizeResponse(response, false);\n\n if (!options.onAutoRetry(id, name, responseToReport, optXhr)) {\n upload.cleanup(id, responseToReport, optXhr);\n }\n }\n );\n }\n },\n\n upload = {\n cancel: function(id) {\n log(\"Cancelling \" + id);\n options.paramsStore.remove(id);\n connectionManager.free(id);\n },\n\n cleanup: function(id, response, optXhr) {\n var name = options.getName(id);\n\n options.onComplete(id, name, response, optXhr);\n\n if (handler._getFileState(id)) {\n handler._clearXhrs && handler._clearXhrs(id);\n }\n\n connectionManager.free(id);\n },\n\n // Returns a qq.BlobProxy, or an actual File/Blob if no proxy is involved, or undefined\n // if none of these are available for the ID\n getProxyOrBlob: function(id) {\n return (handler.getProxy && handler.getProxy(id)) ||\n (handler.getFile && handler.getFile(id));\n },\n\n initHandler: function() {\n var handlerType = namespace ? qq[namespace] : qq.traditional,\n handlerModuleSubtype = qq.supportedFeatures.ajaxUploading ? \"Xhr\" : \"Form\";\n\n handler = new handlerType[handlerModuleSubtype + \"UploadHandler\"](\n options,\n {\n getDataByUuid: options.getDataByUuid,\n getName: options.getName,\n getSize: options.getSize,\n getUuid: options.getUuid,\n log: log,\n onCancel: options.onCancel,\n onProgress: options.onProgress,\n onUuidChanged: options.onUuidChanged\n }\n );\n\n if (handler._removeExpiredChunkingRecords) {\n handler._removeExpiredChunkingRecords();\n }\n },\n\n isDeferredEligibleForUpload: function(id) {\n return options.isQueued(id);\n },\n\n // For Blobs that are part of a group of generated images, along with a reference image,\n // this will ensure the blobs in the group are uploaded in the order they were triggered,\n // even if some async processing must be completed on one or more Blobs first.\n maybeDefer: function(id, blob) {\n // If we don't have a file/blob yet & no file/blob exists for this item, request it,\n // and then submit the upload to the specific handler once the blob is available.\n // ASSUMPTION: This condition will only ever be true if XHR uploading is supported.\n if (blob && !handler.getFile(id) && blob instanceof qq.BlobProxy) {\n\n // Blob creation may take some time, so the caller may want to update the\n // UI to indicate that an operation is in progress, even before the actual\n // upload begins and an onUpload callback is invoked.\n options.onUploadPrep(id);\n\n log(\"Attempting to generate a blob on-demand for \" + id);\n blob.create().then(function(generatedBlob) {\n log(\"Generated an on-demand blob for \" + id);\n\n // Update record associated with this file by providing the generated Blob\n handler.updateBlob(id, generatedBlob);\n\n // Propagate the size for this generated Blob\n options.setSize(id, generatedBlob.size);\n\n // Order handler to recalculate chunking possibility, if applicable\n handler.reevaluateChunking(id);\n\n upload.maybeSendDeferredFiles(id);\n },\n\n // Blob could not be generated. Fail the upload & attempt to prevent retries. Also bubble error message.\n function(errorMessage) {\n var errorResponse = {};\n\n if (errorMessage) {\n errorResponse.error = errorMessage;\n }\n\n log(qq.format(\"Failed to generate blob for ID {}. Error message: {}.\", id, errorMessage), \"error\");\n\n options.onComplete(id, options.getName(id), qq.extend(errorResponse, preventRetryResponse), null);\n upload.maybeSendDeferredFiles(id);\n connectionManager.free(id);\n });\n }\n else {\n return upload.maybeSendDeferredFiles(id);\n }\n\n return false;\n },\n\n // Upload any grouped blobs, in the proper order, that are ready to be uploaded\n maybeSendDeferredFiles: function(id) {\n var idsInGroup = options.getIdsInProxyGroup(id),\n uploadedThisId = false;\n\n if (idsInGroup && idsInGroup.length) {\n log(\"Maybe ready to upload proxy group file \" + id);\n\n qq.each(idsInGroup, function(idx, idInGroup) {\n if (upload.isDeferredEligibleForUpload(idInGroup) && !!handler.getFile(idInGroup)) {\n uploadedThisId = idInGroup === id;\n upload.now(idInGroup);\n }\n else if (upload.isDeferredEligibleForUpload(idInGroup)) {\n return false;\n }\n });\n }\n else {\n uploadedThisId = true;\n upload.now(id);\n }\n\n return uploadedThisId;\n },\n\n maybeNewUuid: function(id, response) {\n if (response.newUuid !== undefined) {\n options.onUuidChanged(id, response.newUuid);\n }\n },\n\n // The response coming from handler implementations may be in various formats.\n // Instead of hoping a promise nested 5 levels deep will always return an object\n // as its first param, let's just normalize the response here.\n normalizeResponse: function(originalResponse, successful) {\n var response = originalResponse;\n\n // The passed \"response\" param may not be a response at all.\n // It could be a string, detailing the error, for example.\n if (!qq.isObject(originalResponse)) {\n response = {};\n\n if (qq.isString(originalResponse) && !successful) {\n response.error = originalResponse;\n }\n }\n\n response.success = successful;\n\n return response;\n },\n\n now: function(id) {\n var name = options.getName(id);\n\n if (!controller.isValid(id)) {\n throw new qq.Error(id + \" is not a valid file ID to upload!\");\n }\n\n options.onUpload(id, name);\n\n if (chunkingPossible && handler._shouldChunkThisFile(id)) {\n chunked.sendNext(id);\n }\n else {\n simple.send(id, name);\n }\n },\n\n start: function(id) {\n var blobToUpload = upload.getProxyOrBlob(id);\n\n if (blobToUpload) {\n return upload.maybeDefer(id, blobToUpload);\n }\n else {\n upload.now(id);\n return true;\n }\n }\n };\n\n qq.extend(this, {\n /**\n * Adds file or file input to the queue\n **/\n add: function(id, file) {\n handler.add.apply(this, arguments);\n },\n\n /**\n * Sends the file identified by id\n */\n upload: function(id) {\n if (connectionManager.open(id)) {\n return upload.start(id);\n }\n return false;\n },\n\n retry: function(id) {\n // On retry, if concurrent chunking has been enabled, we may have aborted all other in-progress chunks\n // for a file when encountering a failed chunk upload. We then signaled the controller to ignore\n // all failures associated with these aborts. We are now retrying, so we don't want to ignore\n // any more failures at this point.\n if (concurrentChunkingPossible) {\n handler._getFileState(id).temp.ignoreFailure = false;\n }\n\n // If we are attempting to retry a file that is already consuming a connection, this is likely an auto-retry.\n // Just go ahead and ask the handler to upload again.\n if (connectionManager.isUsingConnection(id)) {\n return upload.start(id);\n }\n\n // If we are attempting to retry a file that is not currently consuming a connection,\n // this is likely a manual retry attempt. We will need to ensure a connection is available\n // before the retry commences.\n else {\n return controller.upload(id);\n }\n },\n\n /**\n * Cancels file upload by id\n */\n cancel: function(id) {\n var cancelRetVal = handler.cancel(id);\n\n if (qq.isGenericPromise(cancelRetVal)) {\n cancelRetVal.then(function() {\n upload.cancel(id);\n });\n }\n else if (cancelRetVal !== false) {\n upload.cancel(id);\n }\n },\n\n /**\n * Cancels all queued or in-progress uploads\n */\n cancelAll: function() {\n var waitingOrConnected = connectionManager.getWaitingOrConnected(),\n i;\n\n // ensure files are cancelled in reverse order which they were added\n // to avoid a flash of time where a queued file begins to upload before it is canceled\n if (waitingOrConnected.length) {\n for (i = waitingOrConnected.length - 1; i >= 0; i--) {\n controller.cancel(waitingOrConnected[i]);\n }\n }\n\n connectionManager.reset();\n },\n\n // Returns a File, Blob, or the Blob/File for the reference/parent file if the targeted blob is a proxy.\n // Undefined if no file record is available.\n getFile: function(id) {\n if (handler.getProxy && handler.getProxy(id)) {\n return handler.getProxy(id).referenceBlob;\n }\n\n return handler.getFile && handler.getFile(id);\n },\n\n // Returns true if the Blob associated with the ID is related to a proxy s\n isProxied: function(id) {\n return !!(handler.getProxy && handler.getProxy(id));\n },\n\n getInput: function(id) {\n if (handler.getInput) {\n return handler.getInput(id);\n }\n },\n\n reset: function() {\n log(\"Resetting upload handler\");\n controller.cancelAll();\n connectionManager.reset();\n handler.reset();\n },\n\n expunge: function(id) {\n if (controller.isValid(id)) {\n return handler.expunge(id);\n }\n },\n\n /**\n * Determine if the file exists.\n */\n isValid: function(id) {\n return handler.isValid(id);\n },\n\n getResumableFilesData: function() {\n if (handler.getResumableFilesData) {\n return handler.getResumableFilesData();\n }\n return [];\n },\n\n /**\n * This may or may not be implemented, depending on the handler. For handlers where a third-party ID is\n * available (such as the \"key\" for Amazon S3), this will return that value. Otherwise, the return value\n * will be undefined.\n *\n * @param id Internal file ID\n * @returns {*} Some identifier used by a 3rd-party service involved in the upload process\n */\n getThirdPartyFileId: function(id) {\n if (controller.isValid(id)) {\n return handler.getThirdPartyFileId(id);\n }\n },\n\n /**\n * Attempts to pause the associated upload if the specific handler supports this and the file is \"valid\".\n * @param id ID of the upload/file to pause\n * @returns {boolean} true if the upload was paused\n */\n pause: function(id) {\n if (controller.isResumable(id) && handler.pause && controller.isValid(id) && handler.pause(id)) {\n connectionManager.free(id);\n handler.moveInProgressToRemaining(id);\n return true;\n }\n return false;\n },\n\n // True if the file is eligible for pause/resume.\n isResumable: function(id) {\n return !!handler.isResumable && handler.isResumable(id);\n }\n });\n\n qq.extend(options, o);\n log = options.log;\n chunkingPossible = options.chunking.enabled && qq.supportedFeatures.chunking;\n concurrentChunkingPossible = chunkingPossible && options.chunking.concurrent.enabled;\n\n preventRetryResponse = (function() {\n var response = {};\n\n response[options.preventRetryParam] = true;\n\n return response;\n }());\n\n upload.initHandler();\n};\n","/*globals qq */\n/*jshint -W117 */\nqq.WindowReceiveMessage = function(o) {\n \"use strict\";\n\n var options = {\n log: function(message, level) {}\n },\n callbackWrapperDetachers = {};\n\n qq.extend(options, o);\n\n qq.extend(this, {\n receiveMessage: function(id, callback) {\n var onMessageCallbackWrapper = function(event) {\n callback(event.data);\n };\n\n if (window.postMessage) {\n callbackWrapperDetachers[id] = qq(window).attach(\"message\", onMessageCallbackWrapper);\n }\n else {\n log(\"iframe message passing not supported in this browser!\", \"error\");\n }\n },\n\n stopReceivingMessages: function(id) {\n if (window.postMessage) {\n var detacher = callbackWrapperDetachers[id];\n if (detacher) {\n detacher();\n }\n }\n }\n });\n};\n","/* globals qq */\n/**\n * Common APIs exposed to creators of upload via form/iframe handlers. This is reused and possibly overridden\n * in some cases by specific form upload handlers.\n *\n * @constructor\n */\nqq.FormUploadHandler = function(spec) {\n \"use strict\";\n\n var options = spec.options,\n handler = this,\n proxy = spec.proxy,\n formHandlerInstanceId = qq.getUniqueId(),\n onloadCallbacks = {},\n detachLoadEvents = {},\n postMessageCallbackTimers = {},\n isCors = options.isCors,\n inputName = options.inputName,\n getUuid = proxy.getUuid,\n log = proxy.log,\n corsMessageReceiver = new qq.WindowReceiveMessage({log: log});\n\n /**\n * Remove any trace of the file from the handler.\n *\n * @param id ID of the associated file\n */\n function expungeFile(id) {\n delete detachLoadEvents[id];\n\n // If we are dealing with CORS, we might still be waiting for a response from a loaded iframe.\n // In that case, terminate the timer waiting for a message from the loaded iframe\n // and stop listening for any more messages coming from this iframe.\n if (isCors) {\n clearTimeout(postMessageCallbackTimers[id]);\n delete postMessageCallbackTimers[id];\n corsMessageReceiver.stopReceivingMessages(id);\n }\n\n var iframe = document.getElementById(handler._getIframeName(id));\n if (iframe) {\n // To cancel request set src to something else. We use src=\"javascript:false;\"\n // because it doesn't trigger ie6 prompt on https\n /* jshint scripturl:true */\n iframe.setAttribute(\"src\", \"javascript:false;\");\n\n qq(iframe).remove();\n }\n }\n\n /**\n * @param iframeName `document`-unique Name of the associated iframe\n * @returns {*} ID of the associated file\n */\n function getFileIdForIframeName(iframeName) {\n return iframeName.split(\"_\")[0];\n }\n\n /**\n * Generates an iframe to be used as a target for upload-related form submits. This also adds the iframe\n * to the current `document`. Note that the iframe is hidden from view.\n *\n * @param name Name of the iframe.\n * @returns {HTMLIFrameElement} The created iframe\n */\n function initIframeForUpload(name) {\n var iframe = qq.toElement(\"\");\n\n iframe.setAttribute(\"id\", name);\n\n iframe.style.display = \"none\";\n document.body.appendChild(iframe);\n\n return iframe;\n }\n\n /**\n * If we are in CORS mode, we must listen for messages (containing the server response) from the associated\n * iframe, since we cannot directly parse the content of the iframe due to cross-origin restrictions.\n *\n * @param iframe Listen for messages on this iframe.\n * @param callback Invoke this callback with the message from the iframe.\n */\n function registerPostMessageCallback(iframe, callback) {\n var iframeName = iframe.id,\n fileId = getFileIdForIframeName(iframeName),\n uuid = getUuid(fileId);\n\n onloadCallbacks[uuid] = callback;\n\n // When the iframe has loaded (after the server responds to an upload request)\n // declare the attempt a failure if we don't receive a valid message shortly after the response comes in.\n detachLoadEvents[fileId] = qq(iframe).attach(\"load\", function() {\n if (handler.getInput(fileId)) {\n log(\"Received iframe load event for CORS upload request (iframe name \" + iframeName + \")\");\n\n postMessageCallbackTimers[iframeName] = setTimeout(function() {\n var errorMessage = \"No valid message received from loaded iframe for iframe name \" + iframeName;\n log(errorMessage, \"error\");\n callback({\n error: errorMessage\n });\n }, 1000);\n }\n });\n\n // Listen for messages coming from this iframe. When a message has been received, cancel the timer\n // that declares the upload a failure if a message is not received within a reasonable amount of time.\n corsMessageReceiver.receiveMessage(iframeName, function(message) {\n log(\"Received the following window message: '\" + message + \"'\");\n var fileId = getFileIdForIframeName(iframeName),\n response = handler._parseJsonResponse(message),\n uuid = response.uuid,\n onloadCallback;\n\n if (uuid && onloadCallbacks[uuid]) {\n log(\"Handling response for iframe name \" + iframeName);\n clearTimeout(postMessageCallbackTimers[iframeName]);\n delete postMessageCallbackTimers[iframeName];\n\n handler._detachLoadEvent(iframeName);\n\n onloadCallback = onloadCallbacks[uuid];\n\n delete onloadCallbacks[uuid];\n corsMessageReceiver.stopReceivingMessages(iframeName);\n onloadCallback(response);\n }\n else if (!uuid) {\n log(\"'\" + message + \"' does not contain a UUID - ignoring.\");\n }\n });\n }\n\n qq.extend(this, new qq.UploadHandler(spec));\n\n qq.override(this, function(super_) {\n return {\n /**\n * Adds File or Blob to the queue\n **/\n add: function(id, fileInput) {\n super_.add(id, {input: fileInput});\n\n fileInput.setAttribute(\"name\", inputName);\n\n // remove file input from DOM\n if (fileInput.parentNode) {\n qq(fileInput).remove();\n }\n },\n\n expunge: function(id) {\n expungeFile(id);\n super_.expunge(id);\n },\n\n isValid: function(id) {\n return super_.isValid(id) &&\n handler._getFileState(id).input !== undefined;\n }\n };\n });\n\n qq.extend(this, {\n getInput: function(id) {\n return handler._getFileState(id).input;\n },\n\n /**\n * This function either delegates to a more specific message handler if CORS is involved,\n * or simply registers a callback when the iframe has been loaded that invokes the passed callback\n * after determining if the content of the iframe is accessible.\n *\n * @param iframe Associated iframe\n * @param callback Callback to invoke after we have determined if the iframe content is accessible.\n */\n _attachLoadEvent: function(iframe, callback) {\n /*jslint eqeq: true*/\n var responseDescriptor;\n\n if (isCors) {\n registerPostMessageCallback(iframe, callback);\n }\n else {\n detachLoadEvents[iframe.id] = qq(iframe).attach(\"load\", function() {\n log(\"Received response for \" + iframe.id);\n\n // when we remove iframe from dom\n // the request stops, but in IE load\n // event fires\n if (!iframe.parentNode) {\n return;\n }\n\n try {\n // fixing Opera 10.53\n if (iframe.contentDocument &&\n iframe.contentDocument.body &&\n iframe.contentDocument.body.innerHTML == \"false\") {\n // In Opera event is fired second time\n // when body.innerHTML changed from false\n // to server response approx. after 1 sec\n // when we upload file with iframe\n return;\n }\n }\n catch (error) {\n //IE may throw an \"access is denied\" error when attempting to access contentDocument on the iframe in some cases\n log(\"Error when attempting to access iframe during handling of upload response (\" + error.message + \")\", \"error\");\n responseDescriptor = {success: false};\n }\n\n callback(responseDescriptor);\n });\n }\n },\n\n /**\n * Creates an iframe with a specific document-unique name.\n *\n * @param id ID of the associated file\n * @returns {HTMLIFrameElement}\n */\n _createIframe: function(id) {\n var iframeName = handler._getIframeName(id);\n\n return initIframeForUpload(iframeName);\n },\n\n /**\n * Called when we are no longer interested in being notified when an iframe has loaded.\n *\n * @param id Associated file ID\n */\n _detachLoadEvent: function(id) {\n if (detachLoadEvents[id] !== undefined) {\n detachLoadEvents[id]();\n delete detachLoadEvents[id];\n }\n },\n\n /**\n * @param fileId ID of the associated file\n * @returns {string} The `document`-unique name of the iframe\n */\n _getIframeName: function(fileId) {\n return fileId + \"_\" + formHandlerInstanceId;\n },\n\n /**\n * Generates a form element and appends it to the `document`. When the form is submitted, a specific iframe is targeted.\n * The name of the iframe is passed in as a property of the spec parameter, and must be unique in the `document`. Note\n * that the form is hidden from view.\n *\n * @param spec An object containing various properties to be used when constructing the form. Required properties are\n * currently: `method`, `endpoint`, `params`, `paramsInBody`, and `targetName`.\n * @returns {HTMLFormElement} The created form\n */\n _initFormForUpload: function(spec) {\n var method = spec.method,\n endpoint = spec.endpoint,\n params = spec.params,\n paramsInBody = spec.paramsInBody,\n targetName = spec.targetName,\n form = qq.toElement(\" \"),\n url = endpoint;\n\n if (paramsInBody) {\n qq.obj2Inputs(params, form);\n }\n else {\n url = qq.obj2url(params, endpoint);\n }\n\n form.setAttribute(\"action\", url);\n form.setAttribute(\"target\", targetName);\n form.style.display = \"none\";\n document.body.appendChild(form);\n\n return form;\n },\n\n /**\n * @param innerHtmlOrMessage JSON message\n * @returns {*} The parsed response, or an empty object if the response could not be parsed\n */\n _parseJsonResponse: function(innerHtmlOrMessage) {\n var response = {};\n\n try {\n response = qq.parseJson(innerHtmlOrMessage);\n }\n catch (error) {\n log(\"Error when attempting to parse iframe upload response (\" + error.message + \")\", \"error\");\n }\n\n return response;\n }\n });\n};\n","/* globals qq */\n/**\n * Common API exposed to creators of XHR handlers. This is reused and possibly overriding in some cases by specific\n * XHR upload handlers.\n *\n * @constructor\n */\nqq.XhrUploadHandler = function(spec) {\n \"use strict\";\n\n var handler = this,\n namespace = spec.options.namespace,\n proxy = spec.proxy,\n chunking = spec.options.chunking,\n resume = spec.options.resume,\n chunkFiles = chunking && spec.options.chunking.enabled && qq.supportedFeatures.chunking,\n resumeEnabled = resume && spec.options.resume.enabled && chunkFiles && qq.supportedFeatures.resume,\n getName = proxy.getName,\n getSize = proxy.getSize,\n getUuid = proxy.getUuid,\n getEndpoint = proxy.getEndpoint,\n getDataByUuid = proxy.getDataByUuid,\n onUuidChanged = proxy.onUuidChanged,\n onProgress = proxy.onProgress,\n log = proxy.log;\n\n function abort(id) {\n qq.each(handler._getXhrs(id), function(xhrId, xhr) {\n var ajaxRequester = handler._getAjaxRequester(id, xhrId);\n\n xhr.onreadystatechange = null;\n xhr.upload.onprogress = null;\n xhr.abort();\n ajaxRequester && ajaxRequester.canceled && ajaxRequester.canceled(id);\n });\n }\n\n qq.extend(this, new qq.UploadHandler(spec));\n\n qq.override(this, function(super_) {\n return {\n /**\n * Adds File or Blob to the queue\n **/\n add: function(id, blobOrProxy) {\n if (qq.isFile(blobOrProxy) || qq.isBlob(blobOrProxy)) {\n super_.add(id, {file: blobOrProxy});\n }\n else if (blobOrProxy instanceof qq.BlobProxy) {\n super_.add(id, {proxy: blobOrProxy});\n }\n else {\n throw new Error(\"Passed obj is not a File, Blob, or proxy\");\n }\n\n handler._initTempState(id);\n resumeEnabled && handler._maybePrepareForResume(id);\n },\n\n expunge: function(id) {\n abort(id);\n handler._maybeDeletePersistedChunkData(id);\n handler._clearXhrs(id);\n super_.expunge(id);\n }\n };\n });\n\n qq.extend(this, {\n // Clear the cached chunk `Blob` after we are done with it, just in case the `Blob` bytes are stored in memory.\n clearCachedChunk: function(id, chunkIdx) {\n delete handler._getFileState(id).temp.cachedChunks[chunkIdx];\n },\n\n clearXhr: function(id, chunkIdx) {\n var tempState = handler._getFileState(id).temp;\n\n if (tempState.xhrs) {\n delete tempState.xhrs[chunkIdx];\n }\n if (tempState.ajaxRequesters) {\n delete tempState.ajaxRequesters[chunkIdx];\n }\n },\n\n // Called when all chunks have been successfully uploaded. Expected promissory return type.\n // This defines the default behavior if nothing further is required when all chunks have been uploaded.\n finalizeChunks: function(id, responseParser) {\n var lastChunkIdx = handler._getTotalChunks(id) - 1,\n xhr = handler._getXhr(id, lastChunkIdx);\n\n if (responseParser) {\n return new qq.Promise().success(responseParser(xhr), xhr);\n }\n\n return new qq.Promise().success({}, xhr);\n },\n\n getFile: function(id) {\n return handler.isValid(id) && handler._getFileState(id).file;\n },\n\n getProxy: function(id) {\n return handler.isValid(id) && handler._getFileState(id).proxy;\n },\n\n /**\n * @returns {Array} Array of objects containing properties useful to integrators\n * when it is important to determine which files are potentially resumable.\n */\n getResumableFilesData: function() {\n var resumableFilesData = [];\n\n handler._iterateResumeRecords(function(key, uploadData) {\n handler.moveInProgressToRemaining(null, uploadData.chunking.inProgress, uploadData.chunking.remaining);\n\n var data = {\n name: uploadData.name,\n remaining: uploadData.chunking.remaining,\n size: uploadData.size,\n uuid: uploadData.uuid\n };\n\n if (uploadData.key) {\n data.key = uploadData.key;\n }\n\n resumableFilesData.push(data);\n });\n\n return resumableFilesData;\n },\n\n isResumable: function(id) {\n return !!chunking && handler.isValid(id) && !handler._getFileState(id).notResumable;\n },\n\n moveInProgressToRemaining: function(id, optInProgress, optRemaining) {\n var inProgress = optInProgress || handler._getFileState(id).chunking.inProgress,\n remaining = optRemaining || handler._getFileState(id).chunking.remaining;\n\n if (inProgress) {\n log(qq.format(\"Moving these chunks from in-progress {}, to remaining.\", JSON.stringify(inProgress)));\n inProgress.reverse();\n qq.each(inProgress, function(idx, chunkIdx) {\n remaining.unshift(chunkIdx);\n });\n inProgress.length = 0;\n }\n },\n\n pause: function(id) {\n if (handler.isValid(id)) {\n log(qq.format(\"Aborting XHR upload for {} '{}' due to pause instruction.\", id, getName(id)));\n handler._getFileState(id).paused = true;\n abort(id);\n return true;\n }\n },\n\n reevaluateChunking: function(id) {\n if (chunking && handler.isValid(id)) {\n var state = handler._getFileState(id),\n totalChunks,\n i;\n\n delete state.chunking;\n\n state.chunking = {};\n totalChunks = handler._getTotalChunks(id);\n if (totalChunks > 1 || chunking.mandatory) {\n state.chunking.enabled = true;\n state.chunking.parts = totalChunks;\n state.chunking.remaining = [];\n\n for (i = 0; i < totalChunks; i++) {\n state.chunking.remaining.push(i);\n }\n\n handler._initTempState(id);\n }\n else {\n state.chunking.enabled = false;\n }\n }\n },\n\n updateBlob: function(id, newBlob) {\n if (handler.isValid(id)) {\n handler._getFileState(id).file = newBlob;\n }\n },\n\n _clearXhrs: function(id) {\n var tempState = handler._getFileState(id).temp;\n\n qq.each(tempState.ajaxRequesters, function(chunkId) {\n delete tempState.ajaxRequesters[chunkId];\n });\n\n qq.each(tempState.xhrs, function(chunkId) {\n delete tempState.xhrs[chunkId];\n });\n },\n\n /**\n * Creates an XHR instance for this file and stores it in the fileState.\n *\n * @param id File ID\n * @param optChunkIdx The chunk index associated with this XHR, if applicable\n * @returns {XMLHttpRequest}\n */\n _createXhr: function(id, optChunkIdx) {\n return handler._registerXhr(id, optChunkIdx, qq.createXhrInstance());\n },\n\n _getAjaxRequester: function(id, optChunkIdx) {\n var chunkIdx = optChunkIdx == null ? -1 : optChunkIdx;\n return handler._getFileState(id).temp.ajaxRequesters[chunkIdx];\n },\n\n _getChunkData: function(id, chunkIndex) {\n var chunkSize = chunking.partSize,\n fileSize = getSize(id),\n fileOrBlob = handler.getFile(id),\n startBytes = chunkSize * chunkIndex,\n endBytes = startBytes + chunkSize >= fileSize ? fileSize : startBytes + chunkSize,\n totalChunks = handler._getTotalChunks(id),\n cachedChunks = this._getFileState(id).temp.cachedChunks,\n\n // To work around a Webkit GC bug, we must keep each chunk `Blob` in scope until we are done with it.\n // See https://github.com/Widen/fine-uploader/issues/937#issuecomment-41418760\n blob = cachedChunks[chunkIndex] || qq.sliceBlob(fileOrBlob, startBytes, endBytes);\n\n cachedChunks[chunkIndex] = blob;\n\n return {\n part: chunkIndex,\n start: startBytes,\n end: endBytes,\n count: totalChunks,\n blob: blob,\n size: endBytes - startBytes\n };\n },\n\n _getChunkDataForCallback: function(chunkData) {\n return {\n partIndex: chunkData.part,\n startByte: chunkData.start + 1,\n endByte: chunkData.end,\n totalParts: chunkData.count\n };\n },\n\n /**\n * @param id File ID\n * @returns {string} Identifier for this item that may appear in the browser's local storage\n */\n _getLocalStorageId: function(id) {\n var formatVersion = \"5.0\",\n name = getName(id),\n size = getSize(id),\n chunkSize = chunking.partSize,\n endpoint = getEndpoint(id);\n\n return qq.format(\"qq{}resume{}-{}-{}-{}-{}\", namespace, formatVersion, name, size, chunkSize, endpoint);\n },\n\n _getMimeType: function(id) {\n return handler.getFile(id).type;\n },\n\n _getPersistableData: function(id) {\n return handler._getFileState(id).chunking;\n },\n\n /**\n * @param id ID of the associated file\n * @returns {number} Number of parts this file can be divided into, or undefined if chunking is not supported in this UA\n */\n _getTotalChunks: function(id) {\n if (chunking) {\n var fileSize = getSize(id),\n chunkSize = chunking.partSize;\n\n return Math.ceil(fileSize / chunkSize);\n }\n },\n\n _getXhr: function(id, optChunkIdx) {\n var chunkIdx = optChunkIdx == null ? -1 : optChunkIdx;\n return handler._getFileState(id).temp.xhrs[chunkIdx];\n },\n\n _getXhrs: function(id) {\n return handler._getFileState(id).temp.xhrs;\n },\n\n // Iterates through all XHR handler-created resume records (in local storage),\n // invoking the passed callback and passing in the key and value of each local storage record.\n _iterateResumeRecords: function(callback) {\n if (resumeEnabled) {\n qq.each(localStorage, function(key, item) {\n if (key.indexOf(qq.format(\"qq{}resume\", namespace)) === 0) {\n var uploadData = JSON.parse(item);\n callback(key, uploadData);\n }\n });\n }\n },\n\n _initTempState: function(id) {\n handler._getFileState(id).temp = {\n ajaxRequesters: {},\n chunkProgress: {},\n xhrs: {},\n cachedChunks: {}\n };\n },\n\n _markNotResumable: function(id) {\n handler._getFileState(id).notResumable = true;\n },\n\n // Removes a chunked upload record from local storage, if possible.\n // Returns true if the item was removed, false otherwise.\n _maybeDeletePersistedChunkData: function(id) {\n var localStorageId;\n\n if (resumeEnabled && handler.isResumable(id)) {\n localStorageId = handler._getLocalStorageId(id);\n\n if (localStorageId && localStorage.getItem(localStorageId)) {\n localStorage.removeItem(localStorageId);\n return true;\n }\n }\n\n return false;\n },\n\n // If this is a resumable upload, grab the relevant data from storage and items in memory that track this upload\n // so we can pick up from where we left off.\n _maybePrepareForResume: function(id) {\n var state = handler._getFileState(id),\n localStorageId, persistedData;\n\n // Resume is enabled and possible and this is the first time we've tried to upload this file in this session,\n // so prepare for a resume attempt.\n if (resumeEnabled && state.key === undefined) {\n localStorageId = handler._getLocalStorageId(id);\n persistedData = localStorage.getItem(localStorageId);\n\n // If we found this item in local storage, maybe we should resume it.\n if (persistedData) {\n persistedData = JSON.parse(persistedData);\n\n // If we found a resume record but we have already handled this file in this session,\n // don't try to resume it & ensure we don't persist future check data\n if (getDataByUuid(persistedData.uuid)) {\n handler._markNotResumable(id);\n }\n else {\n log(qq.format(\"Identified file with ID {} and name of {} as resumable.\", id, getName(id)));\n\n onUuidChanged(id, persistedData.uuid);\n\n state.key = persistedData.key;\n state.chunking = persistedData.chunking;\n state.loaded = persistedData.loaded;\n state.attemptingResume = true;\n\n handler.moveInProgressToRemaining(id);\n }\n }\n }\n },\n\n // Persist any data needed to resume this upload in a new session.\n _maybePersistChunkedState: function(id) {\n var state = handler._getFileState(id),\n localStorageId, persistedData;\n\n // If local storage isn't supported by the browser, or if resume isn't enabled or possible, give up\n if (resumeEnabled && handler.isResumable(id)) {\n localStorageId = handler._getLocalStorageId(id);\n\n persistedData = {\n name: getName(id),\n size: getSize(id),\n uuid: getUuid(id),\n key: state.key,\n chunking: state.chunking,\n loaded: state.loaded,\n lastUpdated: Date.now()\n };\n\n try {\n localStorage.setItem(localStorageId, JSON.stringify(persistedData));\n }\n catch (error) {\n log(qq.format(\"Unable to save resume data for '{}' due to error: '{}'.\", id, error.toString()), \"warn\");\n }\n }\n },\n\n _registerProgressHandler: function(id, chunkIdx, chunkSize) {\n var xhr = handler._getXhr(id, chunkIdx),\n name = getName(id),\n progressCalculator = {\n simple: function(loaded, total) {\n var fileSize = getSize(id);\n\n if (loaded === total) {\n onProgress(id, name, fileSize, fileSize);\n }\n else {\n onProgress(id, name, (loaded >= fileSize ? fileSize - 1 : loaded), fileSize);\n }\n },\n\n chunked: function(loaded, total) {\n var chunkProgress = handler._getFileState(id).temp.chunkProgress,\n totalSuccessfullyLoadedForFile = handler._getFileState(id).loaded,\n loadedForRequest = loaded,\n totalForRequest = total,\n totalFileSize = getSize(id),\n estActualChunkLoaded = loadedForRequest - (totalForRequest - chunkSize),\n totalLoadedForFile = totalSuccessfullyLoadedForFile;\n\n chunkProgress[chunkIdx] = estActualChunkLoaded;\n\n qq.each(chunkProgress, function(chunkIdx, chunkLoaded) {\n totalLoadedForFile += chunkLoaded;\n });\n\n onProgress(id, name, totalLoadedForFile, totalFileSize);\n }\n };\n\n xhr.upload.onprogress = function(e) {\n if (e.lengthComputable) {\n /* jshint eqnull: true */\n var type = chunkSize == null ? \"simple\" : \"chunked\";\n progressCalculator[type](e.loaded, e.total);\n }\n };\n },\n\n /**\n * Registers an XHR transport instance created elsewhere.\n *\n * @param id ID of the associated file\n * @param optChunkIdx The chunk index associated with this XHR, if applicable\n * @param xhr XMLHttpRequest object instance\n * @param optAjaxRequester `qq.AjaxRequester` associated with this request, if applicable.\n * @returns {XMLHttpRequest}\n */\n _registerXhr: function(id, optChunkIdx, xhr, optAjaxRequester) {\n var xhrsId = optChunkIdx == null ? -1 : optChunkIdx,\n tempState = handler._getFileState(id).temp;\n\n tempState.xhrs = tempState.xhrs || {};\n tempState.ajaxRequesters = tempState.ajaxRequesters || {};\n\n tempState.xhrs[xhrsId] = xhr;\n\n if (optAjaxRequester) {\n tempState.ajaxRequesters[xhrsId] = optAjaxRequester;\n }\n\n return xhr;\n },\n\n // Deletes any local storage records that are \"expired\".\n _removeExpiredChunkingRecords: function() {\n var expirationDays = resume.recordsExpireIn;\n\n handler._iterateResumeRecords(function(key, uploadData) {\n var expirationDate = new Date(uploadData.lastUpdated);\n\n // transform updated date into expiration date\n expirationDate.setDate(expirationDate.getDate() + expirationDays);\n\n if (expirationDate.getTime() <= Date.now()) {\n log(\"Removing expired resume record with key \" + key);\n localStorage.removeItem(key);\n }\n });\n },\n\n /**\n * Determine if the associated file should be chunked.\n *\n * @param id ID of the associated file\n * @returns {*} true if chunking is enabled, possible, and the file can be split into more than 1 part\n */\n _shouldChunkThisFile: function(id) {\n var state = handler._getFileState(id);\n\n if (!state.chunking) {\n handler.reevaluateChunking(id);\n }\n\n return state.chunking.enabled;\n }\n });\n};\n","/*globals qq, XMLHttpRequest*/\nqq.DeleteFileAjaxRequester = function(o) {\n \"use strict\";\n\n var requester,\n options = {\n method: \"DELETE\",\n uuidParamName: \"qquuid\",\n endpointStore: {},\n maxConnections: 3,\n customHeaders: function(id) {return {};},\n paramsStore: {},\n cors: {\n expected: false,\n sendCredentials: false\n },\n log: function(str, level) {},\n onDelete: function(id) {},\n onDeleteComplete: function(id, xhrOrXdr, isError) {}\n };\n\n qq.extend(options, o);\n\n function getMandatedParams() {\n if (options.method.toUpperCase() === \"POST\") {\n return {\n _method: \"DELETE\"\n };\n }\n\n return {};\n }\n\n requester = qq.extend(this, new qq.AjaxRequester({\n acceptHeader: \"application/json\",\n validMethods: [\"POST\", \"DELETE\"],\n method: options.method,\n endpointStore: options.endpointStore,\n paramsStore: options.paramsStore,\n mandatedParams: getMandatedParams(),\n maxConnections: options.maxConnections,\n customHeaders: function(id) {\n return options.customHeaders.get(id);\n },\n log: options.log,\n onSend: options.onDelete,\n onComplete: options.onDeleteComplete,\n cors: options.cors\n }));\n\n qq.extend(this, {\n sendDelete: function(id, uuid, additionalMandatedParams) {\n var additionalOptions = additionalMandatedParams || {};\n\n options.log(\"Submitting delete file request for \" + id);\n\n if (options.method === \"DELETE\") {\n requester.initTransport(id)\n .withPath(uuid)\n .withParams(additionalOptions)\n .send();\n }\n else {\n additionalOptions[options.uuidParamName] = uuid;\n requester.initTransport(id)\n .withParams(additionalOptions)\n .send();\n }\n }\n });\n};\n","/*global qq, define */\n/*jshint strict:false,bitwise:false,nonew:false,asi:true,-W064,-W116,-W089 */\n/**\n * Mega pixel image rendering library for iOS6+\n *\n * Fixes iOS6+'s image file rendering issue for large size image (over mega-pixel),\n * which causes unexpected subsampling when drawing it in canvas.\n * By using this library, you can safely render the image with proper stretching.\n *\n * Copyright (c) 2012 Shinichi Tomita \n * Released under the MIT license\n *\n * Heavily modified by Widen for Fine Uploader\n */\n(function() {\n\n /**\n * Detect subsampling in loaded image.\n * In iOS, larger images than 2M pixels may be subsampled in rendering.\n */\n function detectSubsampling(img) {\n var iw = img.naturalWidth,\n ih = img.naturalHeight,\n canvas = document.createElement(\"canvas\"),\n ctx;\n\n if (iw * ih > 1024 * 1024) { // subsampling may happen over megapixel image\n canvas.width = canvas.height = 1;\n ctx = canvas.getContext(\"2d\");\n ctx.drawImage(img, -iw + 1, 0);\n // subsampled image becomes half smaller in rendering size.\n // check alpha channel value to confirm image is covering edge pixel or not.\n // if alpha value is 0 image is not covering, hence subsampled.\n return ctx.getImageData(0, 0, 1, 1).data[3] === 0;\n } else {\n return false;\n }\n }\n\n /**\n * Detecting vertical squash in loaded image.\n * Fixes a bug which squash image vertically while drawing into canvas for some images.\n */\n function detectVerticalSquash(img, iw, ih) {\n var canvas = document.createElement(\"canvas\"),\n sy = 0,\n ey = ih,\n py = ih,\n ctx, data, alpha, ratio;\n\n canvas.width = 1;\n canvas.height = ih;\n ctx = canvas.getContext(\"2d\");\n ctx.drawImage(img, 0, 0);\n data = ctx.getImageData(0, 0, 1, ih).data;\n\n // search image edge pixel position in case it is squashed vertically.\n while (py > sy) {\n alpha = data[(py - 1) * 4 + 3];\n if (alpha === 0) {\n ey = py;\n } else {\n sy = py;\n }\n py = (ey + sy) >> 1;\n }\n\n ratio = (py / ih);\n return (ratio === 0) ? 1 : ratio;\n }\n\n /**\n * Rendering image element (with resizing) and get its data URL\n */\n function renderImageToDataURL(img, blob, options, doSquash) {\n var canvas = document.createElement(\"canvas\"),\n mime = options.mime || \"image/jpeg\",\n promise = new qq.Promise();\n\n renderImageToCanvas(img, blob, canvas, options, doSquash)\n .then(function() {\n promise.success(\n canvas.toDataURL(mime, options.quality || 0.8)\n );\n });\n\n return promise;\n }\n\n function maybeCalculateDownsampledDimensions(spec) {\n var maxPixels = 5241000; //iOS specific value\n\n if (!qq.ios()) {\n throw new qq.Error(\"Downsampled dimensions can only be reliably calculated for iOS!\");\n }\n\n if (spec.origHeight * spec.origWidth > maxPixels) {\n return {\n newHeight: Math.round(Math.sqrt(maxPixels * (spec.origHeight / spec.origWidth))),\n newWidth: Math.round(Math.sqrt(maxPixels * (spec.origWidth / spec.origHeight)))\n };\n }\n }\n\n /**\n * Rendering image element (with resizing) into the canvas element\n */\n function renderImageToCanvas(img, blob, canvas, options, doSquash) {\n var iw = img.naturalWidth,\n ih = img.naturalHeight,\n width = options.width,\n height = options.height,\n ctx = canvas.getContext(\"2d\"),\n promise = new qq.Promise(),\n modifiedDimensions;\n\n ctx.save();\n\n if (options.resize) {\n return renderImageToCanvasWithCustomResizer({\n blob: blob,\n canvas: canvas,\n image: img,\n imageHeight: ih,\n imageWidth: iw,\n orientation: options.orientation,\n resize: options.resize,\n targetHeight: height,\n targetWidth: width\n });\n }\n\n if (!qq.supportedFeatures.unlimitedScaledImageSize) {\n modifiedDimensions = maybeCalculateDownsampledDimensions({\n origWidth: width,\n origHeight: height\n });\n\n if (modifiedDimensions) {\n qq.log(qq.format(\"Had to reduce dimensions due to device limitations from {}w / {}h to {}w / {}h\",\n width, height, modifiedDimensions.newWidth, modifiedDimensions.newHeight),\n \"warn\");\n\n width = modifiedDimensions.newWidth;\n height = modifiedDimensions.newHeight;\n }\n }\n\n transformCoordinate(canvas, width, height, options.orientation);\n\n // Fine Uploader specific: Save some CPU cycles if not using iOS\n // Assumption: This logic is only needed to overcome iOS image sampling issues\n if (qq.ios()) {\n (function() {\n if (detectSubsampling(img)) {\n iw /= 2;\n ih /= 2;\n }\n\n var d = 1024, // size of tiling canvas\n tmpCanvas = document.createElement(\"canvas\"),\n vertSquashRatio = doSquash ? detectVerticalSquash(img, iw, ih) : 1,\n dw = Math.ceil(d * width / iw),\n dh = Math.ceil(d * height / ih / vertSquashRatio),\n sy = 0,\n dy = 0,\n tmpCtx, sx, dx;\n\n tmpCanvas.width = tmpCanvas.height = d;\n tmpCtx = tmpCanvas.getContext(\"2d\");\n\n while (sy < ih) {\n sx = 0;\n dx = 0;\n while (sx < iw) {\n tmpCtx.clearRect(0, 0, d, d);\n tmpCtx.drawImage(img, -sx, -sy);\n ctx.drawImage(tmpCanvas, 0, 0, d, d, dx, dy, dw, dh);\n sx += d;\n dx += dw;\n }\n sy += d;\n dy += dh;\n }\n ctx.restore();\n tmpCanvas = tmpCtx = null;\n }());\n }\n else {\n ctx.drawImage(img, 0, 0, width, height);\n }\n\n canvas.qqImageRendered && canvas.qqImageRendered();\n promise.success();\n\n return promise;\n }\n\n function renderImageToCanvasWithCustomResizer(resizeInfo) {\n var blob = resizeInfo.blob,\n image = resizeInfo.image,\n imageHeight = resizeInfo.imageHeight,\n imageWidth = resizeInfo.imageWidth,\n orientation = resizeInfo.orientation,\n promise = new qq.Promise(),\n resize = resizeInfo.resize,\n sourceCanvas = document.createElement(\"canvas\"),\n sourceCanvasContext = sourceCanvas.getContext(\"2d\"),\n targetCanvas = resizeInfo.canvas,\n targetHeight = resizeInfo.targetHeight,\n targetWidth = resizeInfo.targetWidth;\n\n transformCoordinate(sourceCanvas, imageWidth, imageHeight, orientation);\n\n targetCanvas.height = targetHeight;\n targetCanvas.width = targetWidth;\n\n sourceCanvasContext.drawImage(image, 0, 0);\n\n resize({\n blob: blob,\n height: targetHeight,\n image: image,\n sourceCanvas: sourceCanvas,\n targetCanvas: targetCanvas,\n width: targetWidth\n })\n .then(\n function success() {\n targetCanvas.qqImageRendered && targetCanvas.qqImageRendered();\n promise.success();\n },\n promise.failure\n );\n\n return promise;\n }\n\n /**\n * Transform canvas coordination according to specified frame size and orientation\n * Orientation value is from EXIF tag\n */\n function transformCoordinate(canvas, width, height, orientation) {\n switch (orientation) {\n case 5:\n case 6:\n case 7:\n case 8:\n canvas.width = height;\n canvas.height = width;\n break;\n default:\n canvas.width = width;\n canvas.height = height;\n }\n var ctx = canvas.getContext(\"2d\");\n switch (orientation) {\n case 2:\n // horizontal flip\n ctx.translate(width, 0);\n ctx.scale(-1, 1);\n break;\n case 3:\n // 180 rotate left\n ctx.translate(width, height);\n ctx.rotate(Math.PI);\n break;\n case 4:\n // vertical flip\n ctx.translate(0, height);\n ctx.scale(1, -1);\n break;\n case 5:\n // vertical flip + 90 rotate right\n ctx.rotate(0.5 * Math.PI);\n ctx.scale(1, -1);\n break;\n case 6:\n // 90 rotate right\n ctx.rotate(0.5 * Math.PI);\n ctx.translate(0, -height);\n break;\n case 7:\n // horizontal flip + 90 rotate right\n ctx.rotate(0.5 * Math.PI);\n ctx.translate(width, -height);\n ctx.scale(-1, 1);\n break;\n case 8:\n // 90 rotate left\n ctx.rotate(-0.5 * Math.PI);\n ctx.translate(-width, 0);\n break;\n default:\n break;\n }\n }\n\n /**\n * MegaPixImage class\n */\n function MegaPixImage(srcImage, errorCallback) {\n var self = this;\n\n if (window.Blob && srcImage instanceof Blob) {\n (function() {\n var img = new Image(),\n URL = window.URL && window.URL.createObjectURL ? window.URL :\n window.webkitURL && window.webkitURL.createObjectURL ? window.webkitURL : null;\n if (!URL) { throw Error(\"No createObjectURL function found to create blob url\"); }\n img.src = URL.createObjectURL(srcImage);\n self.blob = srcImage;\n srcImage = img;\n }());\n }\n if (!srcImage.naturalWidth && !srcImage.naturalHeight) {\n srcImage.onload = function() {\n var listeners = self.imageLoadListeners;\n if (listeners) {\n self.imageLoadListeners = null;\n // IE11 doesn't reliably report actual image dimensions immediately after onload for small files,\n // so let's push this to the end of the UI thread queue.\n setTimeout(function() {\n for (var i = 0, len = listeners.length; i < len; i++) {\n listeners[i]();\n }\n }, 0);\n }\n };\n srcImage.onerror = errorCallback;\n this.imageLoadListeners = [];\n }\n this.srcImage = srcImage;\n }\n\n /**\n * Rendering megapix image into specified target element\n */\n MegaPixImage.prototype.render = function(target, options) {\n options = options || {};\n\n var self = this,\n imgWidth = this.srcImage.naturalWidth,\n imgHeight = this.srcImage.naturalHeight,\n width = options.width,\n height = options.height,\n maxWidth = options.maxWidth,\n maxHeight = options.maxHeight,\n doSquash = !this.blob || this.blob.type === \"image/jpeg\",\n tagName = target.tagName.toLowerCase(),\n opt;\n\n if (this.imageLoadListeners) {\n this.imageLoadListeners.push(function() { self.render(target, options); });\n return;\n }\n\n if (width && !height) {\n height = (imgHeight * width / imgWidth) << 0;\n } else if (height && !width) {\n width = (imgWidth * height / imgHeight) << 0;\n } else {\n width = imgWidth;\n height = imgHeight;\n }\n if (maxWidth && width > maxWidth) {\n width = maxWidth;\n height = (imgHeight * width / imgWidth) << 0;\n }\n if (maxHeight && height > maxHeight) {\n height = maxHeight;\n width = (imgWidth * height / imgHeight) << 0;\n }\n\n opt = { width: width, height: height },\n qq.each(options, function(optionsKey, optionsValue) {\n opt[optionsKey] = optionsValue;\n });\n\n if (tagName === \"img\") {\n (function() {\n var oldTargetSrc = target.src;\n renderImageToDataURL(self.srcImage, self.blob, opt, doSquash)\n .then(function(dataUri) {\n target.src = dataUri;\n oldTargetSrc === target.src && target.onload();\n });\n }());\n } else if (tagName === \"canvas\") {\n renderImageToCanvas(this.srcImage, this.blob, target, opt, doSquash);\n }\n if (typeof this.onrender === \"function\") {\n this.onrender(target);\n }\n };\n\n qq.MegaPixImage = MegaPixImage;\n})();\n","/*globals qq */\n/**\n * Draws a thumbnail of a Blob/File/URL onto an or .\n *\n * @constructor\n */\nqq.ImageGenerator = function(log) {\n \"use strict\";\n\n function isImg(el) {\n return el.tagName.toLowerCase() === \"img\";\n }\n\n function isCanvas(el) {\n return el.tagName.toLowerCase() === \"canvas\";\n }\n\n function isImgCorsSupported() {\n return new Image().crossOrigin !== undefined;\n }\n\n function isCanvasSupported() {\n var canvas = document.createElement(\"canvas\");\n\n return canvas.getContext && canvas.getContext(\"2d\");\n }\n\n // This is only meant to determine the MIME type of a renderable image file.\n // It is used to ensure images drawn from a URL that have transparent backgrounds\n // are rendered correctly, among other things.\n function determineMimeOfFileName(nameWithPath) {\n /*jshint -W015 */\n var pathSegments = nameWithPath.split(\"/\"),\n name = pathSegments[pathSegments.length - 1].split(\"?\")[0],\n extension = qq.getExtension(name);\n\n extension = extension && extension.toLowerCase();\n\n switch (extension) {\n case \"jpeg\":\n case \"jpg\":\n return \"image/jpeg\";\n case \"png\":\n return \"image/png\";\n case \"bmp\":\n return \"image/bmp\";\n case \"gif\":\n return \"image/gif\";\n case \"tiff\":\n case \"tif\":\n return \"image/tiff\";\n }\n }\n\n // This will likely not work correctly in IE8 and older.\n // It's only used as part of a formula to determine\n // if a canvas can be used to scale a server-hosted thumbnail.\n // If canvas isn't supported by the UA (IE8 and older)\n // this method should not even be called.\n function isCrossOrigin(url) {\n var targetAnchor = document.createElement(\"a\"),\n targetProtocol, targetHostname, targetPort;\n\n targetAnchor.href = url;\n\n targetProtocol = targetAnchor.protocol;\n targetPort = targetAnchor.port;\n targetHostname = targetAnchor.hostname;\n\n if (targetProtocol.toLowerCase() !== window.location.protocol.toLowerCase()) {\n return true;\n }\n\n if (targetHostname.toLowerCase() !== window.location.hostname.toLowerCase()) {\n return true;\n }\n\n // IE doesn't take ports into consideration when determining if two endpoints are same origin.\n if (targetPort !== window.location.port && !qq.ie()) {\n return true;\n }\n\n return false;\n }\n\n function registerImgLoadListeners(img, promise) {\n img.onload = function() {\n img.onload = null;\n img.onerror = null;\n promise.success(img);\n };\n\n img.onerror = function() {\n img.onload = null;\n img.onerror = null;\n log(\"Problem drawing thumbnail!\", \"error\");\n promise.failure(img, \"Problem drawing thumbnail!\");\n };\n }\n\n function registerCanvasDrawImageListener(canvas, promise) {\n // The image is drawn on the canvas by a third-party library,\n // and we want to know when this is completed. Since the library\n // may invoke drawImage many times in a loop, we need to be called\n // back when the image is fully rendered. So, we are expecting the\n // code that draws this image to follow a convention that involves a\n // function attached to the canvas instance be invoked when it is done.\n canvas.qqImageRendered = function() {\n promise.success(canvas);\n };\n }\n\n // Fulfills a `qq.Promise` when an image has been drawn onto the target,\n // whether that is a or an . The attempt is considered a\n // failure if the target is not an or a , or if the drawing\n // attempt was not successful.\n function registerThumbnailRenderedListener(imgOrCanvas, promise) {\n var registered = isImg(imgOrCanvas) || isCanvas(imgOrCanvas);\n\n if (isImg(imgOrCanvas)) {\n registerImgLoadListeners(imgOrCanvas, promise);\n }\n else if (isCanvas(imgOrCanvas)) {\n registerCanvasDrawImageListener(imgOrCanvas, promise);\n }\n else {\n promise.failure(imgOrCanvas);\n log(qq.format(\"Element container of type {} is not supported!\", imgOrCanvas.tagName), \"error\");\n }\n\n return registered;\n }\n\n // Draw a preview iff the current UA can natively display it.\n // Also rotate the image if necessary.\n function draw(fileOrBlob, container, options) {\n var drawPreview = new qq.Promise(),\n identifier = new qq.Identify(fileOrBlob, log),\n maxSize = options.maxSize,\n // jshint eqnull:true\n orient = options.orient == null ? true : options.orient,\n megapixErrorHandler = function() {\n container.onerror = null;\n container.onload = null;\n log(\"Could not render preview, file may be too large!\", \"error\");\n drawPreview.failure(container, \"Browser cannot render image!\");\n };\n\n identifier.isPreviewable().then(\n function(mime) {\n // If options explicitly specify that Orientation is not desired,\n // replace the orient task with a dummy promise that \"succeeds\" immediately.\n var dummyExif = {\n parse: function() {\n return new qq.Promise().success();\n }\n },\n exif = orient ? new qq.Exif(fileOrBlob, log) : dummyExif,\n mpImg = new qq.MegaPixImage(fileOrBlob, megapixErrorHandler);\n\n if (registerThumbnailRenderedListener(container, drawPreview)) {\n exif.parse().then(\n function(exif) {\n var orientation = exif && exif.Orientation;\n\n mpImg.render(container, {\n maxWidth: maxSize,\n maxHeight: maxSize,\n orientation: orientation,\n mime: mime,\n resize: options.customResizeFunction\n });\n },\n\n function(failureMsg) {\n log(qq.format(\"EXIF data could not be parsed ({}). Assuming orientation = 1.\", failureMsg));\n\n mpImg.render(container, {\n maxWidth: maxSize,\n maxHeight: maxSize,\n mime: mime,\n resize: options.customResizeFunction\n });\n }\n );\n }\n },\n\n function() {\n log(\"Not previewable\");\n drawPreview.failure(container, \"Not previewable\");\n }\n );\n\n return drawPreview;\n }\n\n function drawOnCanvasOrImgFromUrl(url, canvasOrImg, draw, maxSize, customResizeFunction) {\n var tempImg = new Image(),\n tempImgRender = new qq.Promise();\n\n registerThumbnailRenderedListener(tempImg, tempImgRender);\n\n if (isCrossOrigin(url)) {\n tempImg.crossOrigin = \"anonymous\";\n }\n\n tempImg.src = url;\n\n tempImgRender.then(\n function rendered() {\n registerThumbnailRenderedListener(canvasOrImg, draw);\n\n var mpImg = new qq.MegaPixImage(tempImg);\n mpImg.render(canvasOrImg, {\n maxWidth: maxSize,\n maxHeight: maxSize,\n mime: determineMimeOfFileName(url),\n resize: customResizeFunction\n });\n },\n\n draw.failure\n );\n }\n\n function drawOnImgFromUrlWithCssScaling(url, img, draw, maxSize) {\n registerThumbnailRenderedListener(img, draw);\n // NOTE: The fact that maxWidth/height is set on the thumbnail for scaled images\n // that must drop back to CSS is known and exploited by the templating module.\n // In this module, we pre-render \"waiting\" thumbs for all files immediately after they\n // are submitted, and we must be sure to pass any style associated with the \"waiting\" preview.\n qq(img).css({\n maxWidth: maxSize + \"px\",\n maxHeight: maxSize + \"px\"\n });\n\n img.src = url;\n }\n\n // Draw a (server-hosted) thumbnail given a URL.\n // This will optionally scale the thumbnail as well.\n // It attempts to use to scale, but will fall back\n // to max-width and max-height style properties if the UA\n // doesn't support canvas or if the images is cross-domain and\n // the UA doesn't support the crossorigin attribute on img tags,\n // which is required to scale a cross-origin image using &\n // then export it back to an .\n function drawFromUrl(url, container, options) {\n var draw = new qq.Promise(),\n scale = options.scale,\n maxSize = scale ? options.maxSize : null;\n\n // container is an img, scaling needed\n if (scale && isImg(container)) {\n // Iff canvas is available in this UA, try to use it for scaling.\n // Otherwise, fall back to CSS scaling\n if (isCanvasSupported()) {\n // Attempt to use for image scaling,\n // but we must fall back to scaling via CSS/styles\n // if this is a cross-origin image and the UA doesn't support CORS.\n if (isCrossOrigin(url) && !isImgCorsSupported()) {\n drawOnImgFromUrlWithCssScaling(url, container, draw, maxSize);\n }\n else {\n drawOnCanvasOrImgFromUrl(url, container, draw, maxSize);\n }\n }\n else {\n drawOnImgFromUrlWithCssScaling(url, container, draw, maxSize);\n }\n }\n // container is a canvas, scaling optional\n else if (isCanvas(container)) {\n drawOnCanvasOrImgFromUrl(url, container, draw, maxSize);\n }\n // container is an img & no scaling: just set the src attr to the passed url\n else if (registerThumbnailRenderedListener(container, draw)) {\n container.src = url;\n }\n\n return draw;\n }\n\n qq.extend(this, {\n /**\n * Generate a thumbnail. Depending on the arguments, this may either result in\n * a client-side rendering of an image (if a `Blob` is supplied) or a server-generated\n * image that may optionally be scaled client-side using or CSS/styles (as a fallback).\n *\n * @param fileBlobOrUrl a `File`, `Blob`, or a URL pointing to the image\n * @param container or to contain the preview\n * @param options possible properties include `maxSize` (int), `orient` (bool - default true), resize` (bool - default true), and `customResizeFunction`.\n * @returns qq.Promise fulfilled when the preview has been drawn, or the attempt has failed\n */\n generate: function(fileBlobOrUrl, container, options) {\n if (qq.isString(fileBlobOrUrl)) {\n log(\"Attempting to update thumbnail based on server response.\");\n return drawFromUrl(fileBlobOrUrl, container, options || {});\n }\n else {\n log(\"Attempting to draw client-side image preview.\");\n return draw(fileBlobOrUrl, container, options || {});\n }\n }\n });\n\n /**/\n this._testing = {};\n this._testing.isImg = isImg;\n this._testing.isCanvas = isCanvas;\n this._testing.isCrossOrigin = isCrossOrigin;\n this._testing.determineMimeOfFileName = determineMimeOfFileName;\n /* */\n};\n","/*globals qq */\n/**\n * EXIF image data parser. Currently only parses the Orientation tag value,\n * but this may be expanded to other tags in the future.\n *\n * @param fileOrBlob Attempt to parse EXIF data in this `Blob`\n * @constructor\n */\nqq.Exif = function(fileOrBlob, log) {\n \"use strict\";\n\n // Orientation is the only tag parsed here at this time.\n var TAG_IDS = [274],\n TAG_INFO = {\n 274: {\n name: \"Orientation\",\n bytes: 2\n }\n };\n\n // Convert a little endian (hex string) to big endian (decimal).\n function parseLittleEndian(hex) {\n var result = 0,\n pow = 0;\n\n while (hex.length > 0) {\n result += parseInt(hex.substring(0, 2), 16) * Math.pow(2, pow);\n hex = hex.substring(2, hex.length);\n pow += 8;\n }\n\n return result;\n }\n\n // Find the byte offset, of Application Segment 1 (EXIF).\n // External callers need not supply any arguments.\n function seekToApp1(offset, promise) {\n var theOffset = offset,\n thePromise = promise;\n if (theOffset === undefined) {\n theOffset = 2;\n thePromise = new qq.Promise();\n }\n\n qq.readBlobToHex(fileOrBlob, theOffset, 4).then(function(hex) {\n var match = /^ffe([0-9])/.exec(hex),\n segmentLength;\n\n if (match) {\n if (match[1] !== \"1\") {\n segmentLength = parseInt(hex.slice(4, 8), 16);\n seekToApp1(theOffset + segmentLength + 2, thePromise);\n }\n else {\n thePromise.success(theOffset);\n }\n }\n else {\n thePromise.failure(\"No EXIF header to be found!\");\n }\n });\n\n return thePromise;\n }\n\n // Find the byte offset of Application Segment 1 (EXIF) for valid JPEGs only.\n function getApp1Offset() {\n var promise = new qq.Promise();\n\n qq.readBlobToHex(fileOrBlob, 0, 6).then(function(hex) {\n if (hex.indexOf(\"ffd8\") !== 0) {\n promise.failure(\"Not a valid JPEG!\");\n }\n else {\n seekToApp1().then(function(offset) {\n promise.success(offset);\n },\n function(error) {\n promise.failure(error);\n });\n }\n });\n\n return promise;\n }\n\n // Determine the byte ordering of the EXIF header.\n function isLittleEndian(app1Start) {\n var promise = new qq.Promise();\n\n qq.readBlobToHex(fileOrBlob, app1Start + 10, 2).then(function(hex) {\n promise.success(hex === \"4949\");\n });\n\n return promise;\n }\n\n // Determine the number of directory entries in the EXIF header.\n function getDirEntryCount(app1Start, littleEndian) {\n var promise = new qq.Promise();\n\n qq.readBlobToHex(fileOrBlob, app1Start + 18, 2).then(function(hex) {\n if (littleEndian) {\n return promise.success(parseLittleEndian(hex));\n }\n else {\n promise.success(parseInt(hex, 16));\n }\n });\n\n return promise;\n }\n\n // Get the IFD portion of the EXIF header as a hex string.\n function getIfd(app1Start, dirEntries) {\n var offset = app1Start + 20,\n bytes = dirEntries * 12;\n\n return qq.readBlobToHex(fileOrBlob, offset, bytes);\n }\n\n // Obtain an array of all directory entries (as hex strings) in the EXIF header.\n function getDirEntries(ifdHex) {\n var entries = [],\n offset = 0;\n\n while (offset + 24 <= ifdHex.length) {\n entries.push(ifdHex.slice(offset, offset + 24));\n offset += 24;\n }\n\n return entries;\n }\n\n // Obtain values for all relevant tags and return them.\n function getTagValues(littleEndian, dirEntries) {\n var TAG_VAL_OFFSET = 16,\n tagsToFind = qq.extend([], TAG_IDS),\n vals = {};\n\n qq.each(dirEntries, function(idx, entry) {\n var idHex = entry.slice(0, 4),\n id = littleEndian ? parseLittleEndian(idHex) : parseInt(idHex, 16),\n tagsToFindIdx = tagsToFind.indexOf(id),\n tagValHex, tagName, tagValLength;\n\n if (tagsToFindIdx >= 0) {\n tagName = TAG_INFO[id].name;\n tagValLength = TAG_INFO[id].bytes;\n tagValHex = entry.slice(TAG_VAL_OFFSET, TAG_VAL_OFFSET + (tagValLength * 2));\n vals[tagName] = littleEndian ? parseLittleEndian(tagValHex) : parseInt(tagValHex, 16);\n\n tagsToFind.splice(tagsToFindIdx, 1);\n }\n\n if (tagsToFind.length === 0) {\n return false;\n }\n });\n\n return vals;\n }\n\n qq.extend(this, {\n /**\n * Attempt to parse the EXIF header for the `Blob` associated with this instance.\n *\n * @returns {qq.Promise} To be fulfilled when the parsing is complete.\n * If successful, the parsed EXIF header as an object will be included.\n */\n parse: function() {\n var parser = new qq.Promise(),\n onParseFailure = function(message) {\n log(qq.format(\"EXIF header parse failed: '{}' \", message));\n parser.failure(message);\n };\n\n getApp1Offset().then(function(app1Offset) {\n log(qq.format(\"Moving forward with EXIF header parsing for '{}'\", fileOrBlob.name === undefined ? \"blob\" : fileOrBlob.name));\n\n isLittleEndian(app1Offset).then(function(littleEndian) {\n\n log(qq.format(\"EXIF Byte order is {} endian\", littleEndian ? \"little\" : \"big\"));\n\n getDirEntryCount(app1Offset, littleEndian).then(function(dirEntryCount) {\n\n log(qq.format(\"Found {} APP1 directory entries\", dirEntryCount));\n\n getIfd(app1Offset, dirEntryCount).then(function(ifdHex) {\n var dirEntries = getDirEntries(ifdHex),\n tagValues = getTagValues(littleEndian, dirEntries);\n\n log(\"Successfully parsed some EXIF tags\");\n\n parser.success(tagValues);\n }, onParseFailure);\n }, onParseFailure);\n }, onParseFailure);\n }, onParseFailure);\n\n return parser;\n }\n });\n\n /**/\n this._testing = {};\n this._testing.parseLittleEndian = parseLittleEndian;\n /* */\n};\n","/*globals qq */\nqq.Identify = function(fileOrBlob, log) {\n \"use strict\";\n\n function isIdentifiable(magicBytes, questionableBytes) {\n var identifiable = false,\n magicBytesEntries = [].concat(magicBytes);\n\n qq.each(magicBytesEntries, function(idx, magicBytesArrayEntry) {\n if (questionableBytes.indexOf(magicBytesArrayEntry) === 0) {\n identifiable = true;\n return false;\n }\n });\n\n return identifiable;\n }\n\n qq.extend(this, {\n /**\n * Determines if a Blob can be displayed natively in the current browser. This is done by reading magic\n * bytes in the beginning of the file, so this is an asynchronous operation. Before we attempt to read the\n * file, we will examine the blob's type attribute to save CPU cycles.\n *\n * @returns {qq.Promise} Promise that is fulfilled when identification is complete.\n * If successful, the MIME string is passed to the success handler.\n */\n isPreviewable: function() {\n var self = this,\n identifier = new qq.Promise(),\n previewable = false,\n name = fileOrBlob.name === undefined ? \"blob\" : fileOrBlob.name;\n\n log(qq.format(\"Attempting to determine if {} can be rendered in this browser\", name));\n\n log(\"First pass: check type attribute of blob object.\");\n\n if (this.isPreviewableSync()) {\n log(\"Second pass: check for magic bytes in file header.\");\n\n qq.readBlobToHex(fileOrBlob, 0, 4).then(function(hex) {\n qq.each(self.PREVIEWABLE_MIME_TYPES, function(mime, bytes) {\n if (isIdentifiable(bytes, hex)) {\n // Safari is the only supported browser that can deal with TIFFs natively,\n // so, if this is a TIFF and the UA isn't Safari, declare this file \"non-previewable\".\n if (mime !== \"image/tiff\" || qq.supportedFeatures.tiffPreviews) {\n previewable = true;\n identifier.success(mime);\n }\n\n return false;\n }\n });\n\n log(qq.format(\"'{}' is {} able to be rendered in this browser\", name, previewable ? \"\" : \"NOT\"));\n\n if (!previewable) {\n identifier.failure();\n }\n },\n function() {\n log(\"Error reading file w/ name '\" + name + \"'. Not able to be rendered in this browser.\");\n identifier.failure();\n });\n }\n else {\n identifier.failure();\n }\n\n return identifier;\n },\n\n /**\n * Determines if a Blob can be displayed natively in the current browser. This is done by checking the\n * blob's type attribute. This is a synchronous operation, useful for situations where an asynchronous operation\n * would be challenging to support. Note that the blob's type property is not as accurate as reading the\n * file's magic bytes.\n *\n * @returns {Boolean} true if the blob can be rendered in the current browser\n */\n isPreviewableSync: function() {\n var fileMime = fileOrBlob.type,\n // Assumption: This will only ever be executed in browsers that support `Object.keys`.\n isRecognizedImage = qq.indexOf(Object.keys(this.PREVIEWABLE_MIME_TYPES), fileMime) >= 0,\n previewable = false,\n name = fileOrBlob.name === undefined ? \"blob\" : fileOrBlob.name;\n\n if (isRecognizedImage) {\n if (fileMime === \"image/tiff\") {\n previewable = qq.supportedFeatures.tiffPreviews;\n }\n else {\n previewable = true;\n }\n }\n\n !previewable && log(name + \" is not previewable in this browser per the blob's type attr\");\n\n return previewable;\n }\n });\n};\n\nqq.Identify.prototype.PREVIEWABLE_MIME_TYPES = {\n \"image/jpeg\": \"ffd8ff\",\n \"image/gif\": \"474946\",\n \"image/png\": \"89504e\",\n \"image/bmp\": \"424d\",\n \"image/tiff\": [\"49492a00\", \"4d4d002a\"]\n};\n","/*globals qq*/\n/**\n * Attempts to validate an image, wherever possible.\n *\n * @param blob File or Blob representing a user-selecting image.\n * @param log Uses this to post log messages to the console.\n * @constructor\n */\nqq.ImageValidation = function(blob, log) {\n \"use strict\";\n\n /**\n * @param limits Object with possible image-related limits to enforce.\n * @returns {boolean} true if at least one of the limits has a non-zero value\n */\n function hasNonZeroLimits(limits) {\n var atLeastOne = false;\n\n qq.each(limits, function(limit, value) {\n if (value > 0) {\n atLeastOne = true;\n return false;\n }\n });\n\n return atLeastOne;\n }\n\n /**\n * @returns {qq.Promise} The promise is a failure if we can't obtain the width & height.\n * Otherwise, `success` is called on the returned promise with an object containing\n * `width` and `height` properties.\n */\n function getWidthHeight() {\n var sizeDetermination = new qq.Promise();\n\n new qq.Identify(blob, log).isPreviewable().then(function() {\n var image = new Image(),\n url = window.URL && window.URL.createObjectURL ? window.URL :\n window.webkitURL && window.webkitURL.createObjectURL ? window.webkitURL :\n null;\n\n if (url) {\n image.onerror = function() {\n log(\"Cannot determine dimensions for image. May be too large.\", \"error\");\n sizeDetermination.failure();\n };\n\n image.onload = function() {\n sizeDetermination.success({\n width: this.width,\n height: this.height\n });\n };\n\n image.src = url.createObjectURL(blob);\n }\n else {\n log(\"No createObjectURL function available to generate image URL!\", \"error\");\n sizeDetermination.failure();\n }\n }, sizeDetermination.failure);\n\n return sizeDetermination;\n }\n\n /**\n *\n * @param limits Object with possible image-related limits to enforce.\n * @param dimensions Object containing `width` & `height` properties for the image to test.\n * @returns {String || undefined} The name of the failing limit. Undefined if no failing limits.\n */\n function getFailingLimit(limits, dimensions) {\n var failingLimit;\n\n qq.each(limits, function(limitName, limitValue) {\n if (limitValue > 0) {\n var limitMatcher = /(max|min)(Width|Height)/.exec(limitName),\n dimensionPropName = limitMatcher[2].charAt(0).toLowerCase() + limitMatcher[2].slice(1),\n actualValue = dimensions[dimensionPropName];\n\n /*jshint -W015*/\n switch (limitMatcher[1]) {\n case \"min\":\n if (actualValue < limitValue) {\n failingLimit = limitName;\n return false;\n }\n break;\n case \"max\":\n if (actualValue > limitValue) {\n failingLimit = limitName;\n return false;\n }\n break;\n }\n }\n });\n\n return failingLimit;\n }\n\n /**\n * Validate the associated blob.\n *\n * @param limits\n * @returns {qq.Promise} `success` is called on the promise is the image is valid or\n * if the blob is not an image, or if the image is not verifiable.\n * Otherwise, `failure` with the name of the failing limit.\n */\n this.validate = function(limits) {\n var validationEffort = new qq.Promise();\n\n log(\"Attempting to validate image.\");\n\n if (hasNonZeroLimits(limits)) {\n getWidthHeight().then(function(dimensions) {\n var failingLimit = getFailingLimit(limits, dimensions);\n\n if (failingLimit) {\n validationEffort.failure(failingLimit);\n }\n else {\n validationEffort.success();\n }\n }, validationEffort.success);\n }\n else {\n validationEffort.success();\n }\n\n return validationEffort;\n };\n};\n","/* globals qq */\n/**\n * Module used to control populating the initial list of files.\n *\n * @constructor\n */\nqq.Session = function(spec) {\n \"use strict\";\n\n var options = {\n endpoint: null,\n params: {},\n customHeaders: {},\n cors: {},\n addFileRecord: function(sessionData) {},\n log: function(message, level) {}\n };\n\n qq.extend(options, spec, true);\n\n function isJsonResponseValid(response) {\n if (qq.isArray(response)) {\n return true;\n }\n\n options.log(\"Session response is not an array.\", \"error\");\n }\n\n function handleFileItems(fileItems, success, xhrOrXdr, promise) {\n var someItemsIgnored = false;\n\n success = success && isJsonResponseValid(fileItems);\n\n if (success) {\n qq.each(fileItems, function(idx, fileItem) {\n /* jshint eqnull:true */\n if (fileItem.uuid == null) {\n someItemsIgnored = true;\n options.log(qq.format(\"Session response item {} did not include a valid UUID - ignoring.\", idx), \"error\");\n }\n else if (fileItem.name == null) {\n someItemsIgnored = true;\n options.log(qq.format(\"Session response item {} did not include a valid name - ignoring.\", idx), \"error\");\n }\n else {\n try {\n options.addFileRecord(fileItem);\n return true;\n }\n catch (err) {\n someItemsIgnored = true;\n options.log(err.message, \"error\");\n }\n }\n\n return false;\n });\n }\n\n promise[success && !someItemsIgnored ? \"success\" : \"failure\"](fileItems, xhrOrXdr);\n }\n\n // Initiate a call to the server that will be used to populate the initial file list.\n // Returns a `qq.Promise`.\n this.refresh = function() {\n /*jshint indent:false */\n var refreshEffort = new qq.Promise(),\n refreshCompleteCallback = function(response, success, xhrOrXdr) {\n handleFileItems(response, success, xhrOrXdr, refreshEffort);\n },\n requesterOptions = qq.extend({}, options),\n requester = new qq.SessionAjaxRequester(\n qq.extend(requesterOptions, {onComplete: refreshCompleteCallback})\n );\n\n requester.queryServer();\n\n return refreshEffort;\n };\n};\n","/*globals qq, XMLHttpRequest*/\n/**\n * Thin module used to send GET requests to the server, expecting information about session\n * data used to initialize an uploader instance.\n *\n * @param spec Various options used to influence the associated request.\n * @constructor\n */\nqq.SessionAjaxRequester = function(spec) {\n \"use strict\";\n\n var requester,\n options = {\n endpoint: null,\n customHeaders: {},\n params: {},\n cors: {\n expected: false,\n sendCredentials: false\n },\n onComplete: function(response, success, xhrOrXdr) {},\n log: function(str, level) {}\n };\n\n qq.extend(options, spec);\n\n function onComplete(id, xhrOrXdr, isError) {\n var response = null;\n\n /* jshint eqnull:true */\n if (xhrOrXdr.responseText != null) {\n try {\n response = qq.parseJson(xhrOrXdr.responseText);\n }\n catch (err) {\n options.log(\"Problem parsing session response: \" + err.message, \"error\");\n isError = true;\n }\n }\n\n options.onComplete(response, !isError, xhrOrXdr);\n }\n\n requester = qq.extend(this, new qq.AjaxRequester({\n acceptHeader: \"application/json\",\n validMethods: [\"GET\"],\n method: \"GET\",\n endpointStore: {\n get: function() {\n return options.endpoint;\n }\n },\n customHeaders: options.customHeaders,\n log: options.log,\n onComplete: onComplete,\n cors: options.cors\n }));\n\n qq.extend(this, {\n queryServer: function() {\n var params = qq.extend({}, options.params);\n\n options.log(\"Session query request.\");\n\n requester.initTransport(\"sessionRefresh\")\n .withParams(params)\n .withCacheBuster()\n .send();\n }\n });\n};\n","/* globals qq, ExifRestorer */\n/**\n * Controls generation of scaled images based on a reference image encapsulated in a `File` or `Blob`.\n * Scaled images are generated and converted to blobs on-demand.\n * Multiple scaled images per reference image with varying sizes and other properties are supported.\n *\n * @param spec Information about the scaled images to generate.\n * @param log Logger instance\n * @constructor\n */\nqq.Scaler = function(spec, log) {\n \"use strict\";\n\n var self = this,\n customResizeFunction = spec.customResizer,\n includeOriginal = spec.sendOriginal,\n orient = spec.orient,\n defaultType = spec.defaultType,\n defaultQuality = spec.defaultQuality / 100,\n failedToScaleText = spec.failureText,\n includeExif = spec.includeExif,\n sizes = this._getSortedSizes(spec.sizes);\n\n // Revealed API for instances of this module\n qq.extend(this, {\n // If no targeted sizes have been declared or if this browser doesn't support\n // client-side image preview generation, there is no scaling to do.\n enabled: qq.supportedFeatures.scaling && sizes.length > 0,\n\n getFileRecords: function(originalFileUuid, originalFileName, originalBlobOrBlobData) {\n var self = this,\n records = [],\n originalBlob = originalBlobOrBlobData.blob ? originalBlobOrBlobData.blob : originalBlobOrBlobData,\n identifier = new qq.Identify(originalBlob, log);\n\n // If the reference file cannot be rendered natively, we can't create scaled versions.\n if (identifier.isPreviewableSync()) {\n // Create records for each scaled version & add them to the records array, smallest first.\n qq.each(sizes, function(idx, sizeRecord) {\n var outputType = self._determineOutputType({\n defaultType: defaultType,\n requestedType: sizeRecord.type,\n refType: originalBlob.type\n });\n\n records.push({\n uuid: qq.getUniqueId(),\n name: self._getName(originalFileName, {\n name: sizeRecord.name,\n type: outputType,\n refType: originalBlob.type\n }),\n blob: new qq.BlobProxy(originalBlob,\n qq.bind(self._generateScaledImage, self, {\n customResizeFunction: customResizeFunction,\n maxSize: sizeRecord.maxSize,\n orient: orient,\n type: outputType,\n quality: defaultQuality,\n failedText: failedToScaleText,\n includeExif: includeExif,\n log: log\n }))\n });\n });\n\n records.push({\n uuid: originalFileUuid,\n name: originalFileName,\n size: originalBlob.size,\n blob: includeOriginal ? originalBlob : null\n });\n }\n else {\n records.push({\n uuid: originalFileUuid,\n name: originalFileName,\n size: originalBlob.size,\n blob: originalBlob\n });\n }\n\n return records;\n },\n\n handleNewFile: function(file, name, uuid, size, fileList, batchId, uuidParamName, api) {\n var self = this,\n buttonId = file.qqButtonId || (file.blob && file.blob.qqButtonId),\n scaledIds = [],\n originalId = null,\n addFileToHandler = api.addFileToHandler,\n uploadData = api.uploadData,\n paramsStore = api.paramsStore,\n proxyGroupId = qq.getUniqueId();\n\n qq.each(self.getFileRecords(uuid, name, file), function(idx, record) {\n var blobSize = record.size,\n id;\n\n if (record.blob instanceof qq.BlobProxy) {\n blobSize = -1;\n }\n\n id = uploadData.addFile({\n uuid: record.uuid,\n name: record.name,\n size: blobSize,\n batchId: batchId,\n proxyGroupId: proxyGroupId\n });\n\n if (record.blob instanceof qq.BlobProxy) {\n scaledIds.push(id);\n }\n else {\n originalId = id;\n }\n\n if (record.blob) {\n addFileToHandler(id, record.blob);\n fileList.push({id: id, file: record.blob});\n }\n else {\n uploadData.setStatus(id, qq.status.REJECTED);\n }\n });\n\n // If we are potentially uploading an original file and some scaled versions,\n // ensure the scaled versions include reference's to the parent's UUID and size\n // in their associated upload requests.\n if (originalId !== null) {\n qq.each(scaledIds, function(idx, scaledId) {\n var params = {\n qqparentuuid: uploadData.retrieve({id: originalId}).uuid,\n qqparentsize: uploadData.retrieve({id: originalId}).size\n };\n\n // Make sure the UUID for each scaled image is sent with the upload request,\n // to be consistent (since we may need to ensure it is sent for the original file as well).\n params[uuidParamName] = uploadData.retrieve({id: scaledId}).uuid;\n\n uploadData.setParentId(scaledId, originalId);\n paramsStore.addReadOnly(scaledId, params);\n });\n\n // If any scaled images are tied to this parent image, be SURE we send its UUID as an upload request\n // parameter as well.\n if (scaledIds.length) {\n (function() {\n var param = {};\n param[uuidParamName] = uploadData.retrieve({id: originalId}).uuid;\n paramsStore.addReadOnly(originalId, param);\n }());\n }\n }\n }\n });\n};\n\nqq.extend(qq.Scaler.prototype, {\n scaleImage: function(id, specs, api) {\n \"use strict\";\n\n if (!qq.supportedFeatures.scaling) {\n throw new qq.Error(\"Scaling is not supported in this browser!\");\n }\n\n var scalingEffort = new qq.Promise(),\n log = api.log,\n file = api.getFile(id),\n uploadData = api.uploadData.retrieve({id: id}),\n name = uploadData && uploadData.name,\n uuid = uploadData && uploadData.uuid,\n scalingOptions = {\n customResizer: specs.customResizer,\n sendOriginal: false,\n orient: specs.orient,\n defaultType: specs.type || null,\n defaultQuality: specs.quality,\n failedToScaleText: \"Unable to scale\",\n sizes: [{name: \"\", maxSize: specs.maxSize}]\n },\n scaler = new qq.Scaler(scalingOptions, log);\n\n if (!qq.Scaler || !qq.supportedFeatures.imagePreviews || !file) {\n scalingEffort.failure();\n\n log(\"Could not generate requested scaled image for \" + id + \". \" +\n \"Scaling is either not possible in this browser, or the file could not be located.\", \"error\");\n }\n else {\n (qq.bind(function() {\n // Assumption: There will never be more than one record\n var record = scaler.getFileRecords(uuid, name, file)[0];\n\n if (record && record.blob instanceof qq.BlobProxy) {\n record.blob.create().then(scalingEffort.success, scalingEffort.failure);\n }\n else {\n log(id + \" is not a scalable image!\", \"error\");\n scalingEffort.failure();\n }\n }, this)());\n }\n\n return scalingEffort;\n },\n\n // NOTE: We cannot reliably determine at this time if the UA supports a specific MIME type for the target format.\n // image/jpeg and image/png are the only safe choices at this time.\n _determineOutputType: function(spec) {\n \"use strict\";\n\n var requestedType = spec.requestedType,\n defaultType = spec.defaultType,\n referenceType = spec.refType;\n\n // If a default type and requested type have not been specified, this should be a\n // JPEG if the original type is a JPEG, otherwise, a PNG.\n if (!defaultType && !requestedType) {\n if (referenceType !== \"image/jpeg\") {\n return \"image/png\";\n }\n return referenceType;\n }\n\n // A specified default type is used when a requested type is not specified.\n if (!requestedType) {\n return defaultType;\n }\n\n // If requested type is specified, use it, as long as this recognized type is supported by the current UA\n if (qq.indexOf(Object.keys(qq.Identify.prototype.PREVIEWABLE_MIME_TYPES), requestedType) >= 0) {\n if (requestedType === \"image/tiff\") {\n return qq.supportedFeatures.tiffPreviews ? requestedType : defaultType;\n }\n\n return requestedType;\n }\n\n return defaultType;\n },\n\n // Get a file name for a generated scaled file record, based on the provided scaled image description\n _getName: function(originalName, scaledVersionProperties) {\n \"use strict\";\n\n var startOfExt = originalName.lastIndexOf(\".\"),\n versionType = scaledVersionProperties.type || \"image/png\",\n referenceType = scaledVersionProperties.refType,\n scaledName = \"\",\n scaledExt = qq.getExtension(originalName),\n nameAppendage = \"\";\n\n if (scaledVersionProperties.name && scaledVersionProperties.name.trim().length) {\n nameAppendage = \" (\" + scaledVersionProperties.name + \")\";\n }\n\n if (startOfExt >= 0) {\n scaledName = originalName.substr(0, startOfExt);\n\n if (referenceType !== versionType) {\n scaledExt = versionType.split(\"/\")[1];\n }\n\n scaledName += nameAppendage + \".\" + scaledExt;\n }\n else {\n scaledName = originalName + nameAppendage;\n }\n\n return scaledName;\n },\n\n // We want the smallest scaled file to be uploaded first\n _getSortedSizes: function(sizes) {\n \"use strict\";\n\n sizes = qq.extend([], sizes);\n\n return sizes.sort(function(a, b) {\n if (a.maxSize > b.maxSize) {\n return 1;\n }\n if (a.maxSize < b.maxSize) {\n return -1;\n }\n return 0;\n });\n },\n\n _generateScaledImage: function(spec, sourceFile) {\n \"use strict\";\n\n var self = this,\n customResizeFunction = spec.customResizeFunction,\n log = spec.log,\n maxSize = spec.maxSize,\n orient = spec.orient,\n type = spec.type,\n quality = spec.quality,\n failedText = spec.failedText,\n includeExif = spec.includeExif && sourceFile.type === \"image/jpeg\" && type === \"image/jpeg\",\n scalingEffort = new qq.Promise(),\n imageGenerator = new qq.ImageGenerator(log),\n canvas = document.createElement(\"canvas\");\n\n log(\"Attempting to generate scaled version for \" + sourceFile.name);\n\n imageGenerator.generate(sourceFile, canvas, {maxSize: maxSize, orient: orient, customResizeFunction: customResizeFunction}).then(function() {\n var scaledImageDataUri = canvas.toDataURL(type, quality),\n signalSuccess = function() {\n log(\"Success generating scaled version for \" + sourceFile.name);\n var blob = qq.dataUriToBlob(scaledImageDataUri);\n scalingEffort.success(blob);\n };\n\n if (includeExif) {\n self._insertExifHeader(sourceFile, scaledImageDataUri, log).then(function(scaledImageDataUriWithExif) {\n scaledImageDataUri = scaledImageDataUriWithExif;\n signalSuccess();\n },\n function() {\n log(\"Problem inserting EXIF header into scaled image. Using scaled image w/out EXIF data.\", \"error\");\n signalSuccess();\n });\n }\n else {\n signalSuccess();\n }\n }, function() {\n log(\"Failed attempt to generate scaled version for \" + sourceFile.name, \"error\");\n scalingEffort.failure(failedText);\n });\n\n return scalingEffort;\n },\n\n // Attempt to insert the original image's EXIF header into a scaled version.\n _insertExifHeader: function(originalImage, scaledImageDataUri, log) {\n \"use strict\";\n\n var reader = new FileReader(),\n insertionEffort = new qq.Promise(),\n originalImageDataUri = \"\";\n\n reader.onload = function() {\n originalImageDataUri = reader.result;\n insertionEffort.success(qq.ExifRestorer.restore(originalImageDataUri, scaledImageDataUri));\n };\n\n reader.onerror = function() {\n log(\"Problem reading \" + originalImage.name + \" during attempt to transfer EXIF data to scaled version.\", \"error\");\n insertionEffort.failure();\n };\n\n reader.readAsDataURL(originalImage);\n\n return insertionEffort;\n },\n\n _dataUriToBlob: function(dataUri) {\n \"use strict\";\n\n var byteString, mimeString, arrayBuffer, intArray;\n\n // convert base64 to raw binary data held in a string\n if (dataUri.split(\",\")[0].indexOf(\"base64\") >= 0) {\n byteString = atob(dataUri.split(\",\")[1]);\n }\n else {\n byteString = decodeURI(dataUri.split(\",\")[1]);\n }\n\n // extract the MIME\n mimeString = dataUri.split(\",\")[0]\n .split(\":\")[1]\n .split(\";\")[0];\n\n // write the bytes of the binary string to an ArrayBuffer\n arrayBuffer = new ArrayBuffer(byteString.length);\n intArray = new Uint8Array(arrayBuffer);\n qq.each(byteString, function(idx, character) {\n intArray[idx] = character.charCodeAt(0);\n });\n\n return this._createBlob(arrayBuffer, mimeString);\n },\n\n _createBlob: function(data, mime) {\n \"use strict\";\n\n var BlobBuilder = window.BlobBuilder ||\n window.WebKitBlobBuilder ||\n window.MozBlobBuilder ||\n window.MSBlobBuilder,\n blobBuilder = BlobBuilder && new BlobBuilder();\n\n if (blobBuilder) {\n blobBuilder.append(data);\n return blobBuilder.getBlob(mime);\n }\n else {\n return new Blob([data], {type: mime});\n }\n }\n});\n","//Based on MinifyJpeg\n//http://elicon.blog57.fc2.com/blog-entry-206.html\n\nqq.ExifRestorer = (function()\n{\n \n\tvar ExifRestorer = {};\n\t \n ExifRestorer.KEY_STR = \"ABCDEFGHIJKLMNOP\" +\n \"QRSTUVWXYZabcdef\" +\n \"ghijklmnopqrstuv\" +\n \"wxyz0123456789+/\" +\n \"=\";\n\n ExifRestorer.encode64 = function(input)\n {\n var output = \"\",\n chr1, chr2, chr3 = \"\",\n enc1, enc2, enc3, enc4 = \"\",\n i = 0;\n\n do {\n chr1 = input[i++];\n chr2 = input[i++];\n chr3 = input[i++];\n\n enc1 = chr1 >> 2;\n enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);\n enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);\n enc4 = chr3 & 63;\n\n if (isNaN(chr2)) {\n enc3 = enc4 = 64;\n } else if (isNaN(chr3)) {\n enc4 = 64;\n }\n\n output = output +\n this.KEY_STR.charAt(enc1) +\n this.KEY_STR.charAt(enc2) +\n this.KEY_STR.charAt(enc3) +\n this.KEY_STR.charAt(enc4);\n chr1 = chr2 = chr3 = \"\";\n enc1 = enc2 = enc3 = enc4 = \"\";\n } while (i < input.length);\n\n return output;\n };\n \n ExifRestorer.restore = function(origFileBase64, resizedFileBase64)\n {\n var expectedBase64Header = \"data:image/jpeg;base64,\";\n\n if (!origFileBase64.match(expectedBase64Header))\n {\n \treturn resizedFileBase64;\n } \n \n var rawImage = this.decode64(origFileBase64.replace(expectedBase64Header, \"\"));\n var segments = this.slice2Segments(rawImage);\n \n var image = this.exifManipulation(resizedFileBase64, segments);\n \n return expectedBase64Header + this.encode64(image);\n \n };\n\n\n ExifRestorer.exifManipulation = function(resizedFileBase64, segments)\n {\n var exifArray = this.getExifArray(segments),\n newImageArray = this.insertExif(resizedFileBase64, exifArray),\n aBuffer = new Uint8Array(newImageArray);\n\n return aBuffer;\n };\n\n\n ExifRestorer.getExifArray = function(segments)\n {\n var seg;\n for (var x = 0; x < segments.length; x++)\n {\n seg = segments[x];\n if (seg[0] == 255 & seg[1] == 225) //(ff e1)\n {\n return seg;\n }\n }\n return [];\n };\n\n\n ExifRestorer.insertExif = function(resizedFileBase64, exifArray)\n {\n var imageData = resizedFileBase64.replace(\"data:image/jpeg;base64,\", \"\"),\n buf = this.decode64(imageData),\n separatePoint = buf.indexOf(255,3),\n mae = buf.slice(0, separatePoint),\n ato = buf.slice(separatePoint),\n array = mae;\n\n array = array.concat(exifArray);\n array = array.concat(ato);\n return array;\n };\n\n\n \n ExifRestorer.slice2Segments = function(rawImageArray)\n {\n var head = 0,\n segments = [];\n\n while (1)\n {\n if (rawImageArray[head] == 255 & rawImageArray[head + 1] == 218){break;}\n if (rawImageArray[head] == 255 & rawImageArray[head + 1] == 216)\n {\n head += 2;\n }\n else\n {\n var length = rawImageArray[head + 2] * 256 + rawImageArray[head + 3],\n endPoint = head + length + 2,\n seg = rawImageArray.slice(head, endPoint);\n segments.push(seg);\n head = endPoint;\n }\n if (head > rawImageArray.length){break;}\n }\n\n return segments;\n };\n\n\n \n ExifRestorer.decode64 = function(input) \n {\n var output = \"\",\n chr1, chr2, chr3 = \"\",\n enc1, enc2, enc3, enc4 = \"\",\n i = 0,\n buf = [];\n\n // remove all characters that are not A-Z, a-z, 0-9, +, /, or =\n var base64test = /[^A-Za-z0-9\\+\\/\\=]/g;\n if (base64test.exec(input)) {\n throw new Error(\"There were invalid base64 characters in the input text. \" +\n \"Valid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='\");\n }\n input = input.replace(/[^A-Za-z0-9\\+\\/\\=]/g, \"\");\n\n do {\n enc1 = this.KEY_STR.indexOf(input.charAt(i++));\n enc2 = this.KEY_STR.indexOf(input.charAt(i++));\n enc3 = this.KEY_STR.indexOf(input.charAt(i++));\n enc4 = this.KEY_STR.indexOf(input.charAt(i++));\n\n chr1 = (enc1 << 2) | (enc2 >> 4);\n chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);\n chr3 = ((enc3 & 3) << 6) | enc4;\n\n buf.push(chr1);\n\n if (enc3 != 64) {\n buf.push(chr2);\n }\n if (enc4 != 64) {\n buf.push(chr3);\n }\n\n chr1 = chr2 = chr3 = \"\";\n enc1 = enc2 = enc3 = enc4 = \"\";\n\n } while (i < input.length);\n\n return buf;\n };\n\n \n return ExifRestorer;\n})();\n","/* globals qq */\n/**\n * Keeps a running tally of total upload progress for a batch of files.\n *\n * @param callback Invoked when total progress changes, passing calculated total loaded & total size values.\n * @param getSize Function that returns the size of a file given its ID\n * @constructor\n */\nqq.TotalProgress = function(callback, getSize) {\n \"use strict\";\n\n var perFileProgress = {},\n totalLoaded = 0,\n totalSize = 0,\n\n lastLoadedSent = -1,\n lastTotalSent = -1,\n callbackProxy = function(loaded, total) {\n if (loaded !== lastLoadedSent || total !== lastTotalSent) {\n callback(loaded, total);\n }\n\n lastLoadedSent = loaded;\n lastTotalSent = total;\n },\n\n /**\n * @param failed Array of file IDs that have failed\n * @param retryable Array of file IDs that are retryable\n * @returns true if none of the failed files are eligible for retry\n */\n noRetryableFiles = function(failed, retryable) {\n var none = true;\n\n qq.each(failed, function(idx, failedId) {\n if (qq.indexOf(retryable, failedId) >= 0) {\n none = false;\n return false;\n }\n });\n\n return none;\n },\n\n onCancel = function(id) {\n updateTotalProgress(id, -1, -1);\n delete perFileProgress[id];\n },\n\n onAllComplete = function(successful, failed, retryable) {\n if (failed.length === 0 || noRetryableFiles(failed, retryable)) {\n callbackProxy(totalSize, totalSize);\n this.reset();\n }\n },\n\n onNew = function(id) {\n var size = getSize(id);\n\n // We might not know the size yet, such as for blob proxies\n if (size > 0) {\n updateTotalProgress(id, 0, size);\n perFileProgress[id] = {loaded: 0, total: size};\n }\n },\n\n /**\n * Invokes the callback with the current total progress of all files in the batch. Called whenever it may\n * be appropriate to re-calculate and disseminate this data.\n *\n * @param id ID of a file that has changed in some important way\n * @param newLoaded New loaded value for this file. -1 if this value should no longer be part of calculations\n * @param newTotal New total size of the file. -1 if this value should no longer be part of calculations\n */\n updateTotalProgress = function(id, newLoaded, newTotal) {\n var oldLoaded = perFileProgress[id] ? perFileProgress[id].loaded : 0,\n oldTotal = perFileProgress[id] ? perFileProgress[id].total : 0;\n\n if (newLoaded === -1 && newTotal === -1) {\n totalLoaded -= oldLoaded;\n totalSize -= oldTotal;\n }\n else {\n if (newLoaded) {\n totalLoaded += newLoaded - oldLoaded;\n }\n if (newTotal) {\n totalSize += newTotal - oldTotal;\n }\n }\n\n callbackProxy(totalLoaded, totalSize);\n };\n\n qq.extend(this, {\n // Called when a batch of files has completed uploading.\n onAllComplete: onAllComplete,\n\n // Called when the status of a file has changed.\n onStatusChange: function(id, oldStatus, newStatus) {\n if (newStatus === qq.status.CANCELED || newStatus === qq.status.REJECTED) {\n onCancel(id);\n }\n else if (newStatus === qq.status.SUBMITTING) {\n onNew(id);\n }\n },\n\n // Called whenever the upload progress of an individual file has changed.\n onIndividualProgress: function(id, loaded, total) {\n updateTotalProgress(id, loaded, total);\n perFileProgress[id] = {loaded: loaded, total: total};\n },\n\n // Called whenever the total size of a file has changed, such as when the size of a generated blob is known.\n onNewSize: function(id) {\n onNew(id);\n },\n\n reset: function() {\n perFileProgress = {};\n totalLoaded = 0;\n totalSize = 0;\n }\n });\n};\n","/*globals qq*/\nqq.PasteSupport = function(o) {\n \"use strict\";\n\n var options, detachPasteHandler;\n\n options = {\n targetElement: null,\n callbacks: {\n log: function(message, level) {},\n pasteReceived: function(blob) {}\n }\n };\n\n function isImage(item) {\n return item.type &&\n item.type.indexOf(\"image/\") === 0;\n }\n\n function registerPasteHandler() {\n detachPasteHandler = qq(options.targetElement).attach(\"paste\", function(event) {\n var clipboardData = event.clipboardData;\n\n if (clipboardData) {\n qq.each(clipboardData.items, function(idx, item) {\n if (isImage(item)) {\n var blob = item.getAsFile();\n options.callbacks.pasteReceived(blob);\n }\n });\n }\n });\n }\n\n function unregisterPasteHandler() {\n if (detachPasteHandler) {\n detachPasteHandler();\n }\n }\n\n qq.extend(options, o);\n registerPasteHandler();\n\n qq.extend(this, {\n reset: function() {\n unregisterPasteHandler();\n }\n });\n};\n","/* globals qq */\n/**\n * Module that handles support for existing forms.\n *\n * @param options Options passed from the integrator-supplied options related to form support.\n * @param startUpload Callback to invoke when files \"stored\" should be uploaded.\n * @param log Proxy for the logger\n * @constructor\n */\nqq.FormSupport = function(options, startUpload, log) {\n \"use strict\";\n var self = this,\n interceptSubmit = options.interceptSubmit,\n formEl = options.element,\n autoUpload = options.autoUpload;\n\n // Available on the public API associated with this module.\n qq.extend(this, {\n // To be used by the caller to determine if the endpoint will be determined by some processing\n // that occurs in this module, such as if the form has an action attribute.\n // Ignore if `attachToForm === false`.\n newEndpoint: null,\n\n // To be used by the caller to determine if auto uploading should be allowed.\n // Ignore if `attachToForm === false`.\n newAutoUpload: autoUpload,\n\n // true if a form was detected and is being tracked by this module\n attachedToForm: false,\n\n // Returns an object with names and values for all valid form elements associated with the attached form.\n getFormInputsAsObject: function() {\n /* jshint eqnull:true */\n if (formEl == null) {\n return null;\n }\n\n return self._form2Obj(formEl);\n }\n });\n\n // If the form contains an action attribute, this should be the new upload endpoint.\n function determineNewEndpoint(formEl) {\n if (formEl.getAttribute(\"action\")) {\n self.newEndpoint = formEl.getAttribute(\"action\");\n }\n }\n\n // Return true only if the form is valid, or if we cannot make this determination.\n // If the form is invalid, ensure invalid field(s) are highlighted in the UI.\n function validateForm(formEl, nativeSubmit) {\n if (formEl.checkValidity && !formEl.checkValidity()) {\n log(\"Form did not pass validation checks - will not upload.\", \"error\");\n nativeSubmit();\n }\n else {\n return true;\n }\n }\n\n // Intercept form submit attempts, unless the integrator has told us not to do this.\n function maybeUploadOnSubmit(formEl) {\n var nativeSubmit = formEl.submit;\n\n // Intercept and squelch submit events.\n qq(formEl).attach(\"submit\", function(event) {\n event = event || window.event;\n\n if (event.preventDefault) {\n event.preventDefault();\n }\n else {\n event.returnValue = false;\n }\n\n validateForm(formEl, nativeSubmit) && startUpload();\n });\n\n // The form's `submit()` function may be called instead (i.e. via jQuery.submit()).\n // Intercept that too.\n formEl.submit = function() {\n validateForm(formEl, nativeSubmit) && startUpload();\n };\n }\n\n // If the element value passed from the uploader is a string, assume it is an element ID - select it.\n // The rest of the code in this module depends on this being an HTMLElement.\n function determineFormEl(formEl) {\n if (formEl) {\n if (qq.isString(formEl)) {\n formEl = document.getElementById(formEl);\n }\n\n if (formEl) {\n log(\"Attaching to form element.\");\n determineNewEndpoint(formEl);\n interceptSubmit && maybeUploadOnSubmit(formEl);\n }\n }\n\n return formEl;\n }\n\n formEl = determineFormEl(formEl);\n this.attachedToForm = !!formEl;\n};\n\nqq.extend(qq.FormSupport.prototype, {\n // Converts all relevant form fields to key/value pairs. This is meant to mimic the data a browser will\n // construct from a given form when the form is submitted.\n _form2Obj: function(form) {\n \"use strict\";\n var obj = {},\n notIrrelevantType = function(type) {\n var irrelevantTypes = [\n \"button\",\n \"image\",\n \"reset\",\n \"submit\"\n ];\n\n return qq.indexOf(irrelevantTypes, type.toLowerCase()) < 0;\n },\n radioOrCheckbox = function(type) {\n return qq.indexOf([\"checkbox\", \"radio\"], type.toLowerCase()) >= 0;\n },\n ignoreValue = function(el) {\n if (radioOrCheckbox(el.type) && !el.checked) {\n return true;\n }\n\n return el.disabled && el.type.toLowerCase() !== \"hidden\";\n },\n selectValue = function(select) {\n var value = null;\n\n qq.each(qq(select).children(), function(idx, child) {\n if (child.tagName.toLowerCase() === \"option\" && child.selected) {\n value = child.value;\n return false;\n }\n });\n\n return value;\n };\n\n qq.each(form.elements, function(idx, el) {\n if ((qq.isInput(el, true) || el.tagName.toLowerCase() === \"textarea\") &&\n notIrrelevantType(el.type) &&\n !ignoreValue(el)) {\n\n obj[el.name] = el.value;\n }\n else if (el.tagName.toLowerCase() === \"select\" && !ignoreValue(el)) {\n var value = selectValue(el);\n\n if (value !== null) {\n obj[el.name] = value;\n }\n }\n });\n\n return obj;\n }\n});\n","/*globals qq*/\n/**\n * Upload handler used that assumes the current user agent does not have any support for the\n * File API, and, therefore, makes use of iframes and forms to submit the files directly to\n * a generic server.\n *\n * @param options Options passed from the base handler\n * @param proxy Callbacks & methods used to query for or push out data/changes\n */\nqq.traditional = qq.traditional || {};\nqq.traditional.FormUploadHandler = function(options, proxy) {\n \"use strict\";\n\n var handler = this,\n getName = proxy.getName,\n getUuid = proxy.getUuid,\n log = proxy.log;\n\n /**\n * Returns json object received by iframe from server.\n */\n function getIframeContentJson(id, iframe) {\n /*jshint evil: true*/\n\n var response, doc, innerHtml;\n\n //IE may throw an \"access is denied\" error when attempting to access contentDocument on the iframe in some cases\n try {\n // iframe.contentWindow.document - for IE<7\n doc = iframe.contentDocument || iframe.contentWindow.document;\n innerHtml = doc.body.innerHTML;\n\n log(\"converting iframe's innerHTML to JSON\");\n log(\"innerHTML = \" + innerHtml);\n //plain text response may be wrapped in tag\n if (innerHtml && innerHtml.match(/^ 1 && !options.allowMultipleItems) {\n options.callbacks.processingDroppedFilesComplete([]);\n options.callbacks.dropError(\"tooManyFilesError\", \"\");\n uploadDropZone.dropDisabled(false);\n handleDataTransferPromise.failure();\n }\n else {\n droppedFiles = [];\n\n if (qq.isFolderDropSupported(dataTransfer)) {\n qq.each(dataTransfer.items, function(idx, item) {\n var entry = item.webkitGetAsEntry();\n\n if (entry) {\n //due to a bug in Chrome's File System API impl - #149735\n if (entry.isFile) {\n droppedFiles.push(item.getAsFile());\n }\n\n else {\n pendingFolderPromises.push(traverseFileTree(entry).done(function() {\n pendingFolderPromises.pop();\n if (pendingFolderPromises.length === 0) {\n handleDataTransferPromise.success();\n }\n }));\n }\n }\n });\n }\n else {\n droppedFiles = dataTransfer.files;\n }\n\n if (pendingFolderPromises.length === 0) {\n handleDataTransferPromise.success();\n }\n }\n\n return handleDataTransferPromise;\n }\n\n function setupDropzone(dropArea) {\n var dropZone = new qq.UploadDropZone({\n HIDE_ZONES_EVENT_NAME: HIDE_ZONES_EVENT_NAME,\n element: dropArea,\n onEnter: function(e) {\n qq(dropArea).addClass(options.classes.dropActive);\n e.stopPropagation();\n },\n onLeaveNotDescendants: function(e) {\n qq(dropArea).removeClass(options.classes.dropActive);\n },\n onDrop: function(e) {\n handleDataTransfer(e.dataTransfer, dropZone).then(\n function() {\n uploadDroppedFiles(droppedFiles, dropZone);\n },\n function() {\n options.callbacks.dropLog(\"Drop event DataTransfer parsing failed. No files will be uploaded.\", \"error\");\n }\n );\n }\n });\n\n disposeSupport.addDisposer(function() {\n dropZone.dispose();\n });\n\n qq(dropArea).hasAttribute(HIDE_BEFORE_ENTER_ATTR) && qq(dropArea).hide();\n\n uploadDropZones.push(dropZone);\n\n return dropZone;\n }\n\n function isFileDrag(dragEvent) {\n var fileDrag;\n\n qq.each(dragEvent.dataTransfer.types, function(key, val) {\n if (val === \"Files\") {\n fileDrag = true;\n return false;\n }\n });\n\n return fileDrag;\n }\n\n // Attempt to determine when the file has left the document. It is not always possible to detect this\n // in all cases, but it is generally possible in all browsers, with a few exceptions.\n //\n // Exceptions:\n // * IE10+ & Safari: We can't detect a file leaving the document if the Explorer window housing the file\n // overlays the browser window.\n // * IE10+: If the file is dragged out of the window too quickly, IE does not set the expected values of the\n // event's X & Y properties.\n function leavingDocumentOut(e) {\n if (qq.firefox()) {\n return !e.relatedTarget;\n }\n\n if (qq.safari()) {\n return e.x < 0 || e.y < 0;\n }\n\n return e.x === 0 && e.y === 0;\n }\n\n function setupDragDrop() {\n var dropZones = options.dropZoneElements,\n\n maybeHideDropZones = function() {\n setTimeout(function() {\n qq.each(dropZones, function(idx, dropZone) {\n qq(dropZone).hasAttribute(HIDE_BEFORE_ENTER_ATTR) && qq(dropZone).hide();\n qq(dropZone).removeClass(options.classes.dropActive);\n });\n }, 10);\n };\n\n qq.each(dropZones, function(idx, dropZone) {\n var uploadDropZone = setupDropzone(dropZone);\n\n // IE <= 9 does not support the File API used for drag+drop uploads\n if (dropZones.length && qq.supportedFeatures.fileDrop) {\n disposeSupport.attach(document, \"dragenter\", function(e) {\n if (!uploadDropZone.dropDisabled() && isFileDrag(e)) {\n qq.each(dropZones, function(idx, dropZone) {\n // We can't apply styles to non-HTMLElements, since they lack the `style` property.\n // Also, if the drop zone isn't initially hidden, let's not mess with `style.display`.\n if (dropZone instanceof HTMLElement &&\n qq(dropZone).hasAttribute(HIDE_BEFORE_ENTER_ATTR)) {\n\n qq(dropZone).css({display: \"block\"});\n }\n });\n }\n });\n }\n });\n\n disposeSupport.attach(document, \"dragleave\", function(e) {\n if (leavingDocumentOut(e)) {\n maybeHideDropZones();\n }\n });\n\n // Just in case we were not able to detect when a dragged file has left the document,\n // hide all relevant drop zones the next time the mouse enters the document.\n // Note that mouse events such as this one are not fired during drag operations.\n disposeSupport.attach(qq(document).children()[0], \"mouseenter\", function(e) {\n maybeHideDropZones();\n });\n\n disposeSupport.attach(document, \"drop\", function(e) {\n e.preventDefault();\n maybeHideDropZones();\n });\n\n disposeSupport.attach(document, HIDE_ZONES_EVENT_NAME, maybeHideDropZones);\n }\n\n setupDragDrop();\n\n qq.extend(this, {\n setupExtraDropzone: function(element) {\n options.dropZoneElements.push(element);\n setupDropzone(element);\n },\n\n removeDropzone: function(element) {\n var i,\n dzs = options.dropZoneElements;\n\n for (i in dzs) {\n if (dzs[i] === element) {\n return dzs.splice(i, 1);\n }\n }\n },\n\n dispose: function() {\n disposeSupport.dispose();\n qq.each(uploadDropZones, function(idx, dropZone) {\n dropZone.dispose();\n });\n }\n });\n};\n\nqq.DragAndDrop.callbacks = function() {\n \"use strict\";\n\n return {\n processingDroppedFiles: function() {},\n processingDroppedFilesComplete: function(files, targetEl) {},\n dropError: function(code, errorSpecifics) {\n qq.log(\"Drag & drop error code '\" + code + \" with these specifics: '\" + errorSpecifics + \"'\", \"error\");\n },\n dropLog: function(message, level) {\n qq.log(message, level);\n }\n };\n};\n\nqq.UploadDropZone = function(o) {\n \"use strict\";\n\n var disposeSupport = new qq.DisposeSupport(),\n options, element, preventDrop, dropOutsideDisabled;\n\n options = {\n element: null,\n onEnter: function(e) {},\n onLeave: function(e) {},\n // is not fired when leaving element by hovering descendants\n onLeaveNotDescendants: function(e) {},\n onDrop: function(e) {}\n };\n\n qq.extend(options, o);\n element = options.element;\n\n function dragoverShouldBeCanceled() {\n return qq.safari() || (qq.firefox() && qq.windows());\n }\n\n function disableDropOutside(e) {\n // run only once for all instances\n if (!dropOutsideDisabled) {\n\n // for these cases we need to catch onDrop to reset dropArea\n if (dragoverShouldBeCanceled) {\n disposeSupport.attach(document, \"dragover\", function(e) {\n e.preventDefault();\n });\n } else {\n disposeSupport.attach(document, \"dragover\", function(e) {\n if (e.dataTransfer) {\n e.dataTransfer.dropEffect = \"none\";\n e.preventDefault();\n }\n });\n }\n\n dropOutsideDisabled = true;\n }\n }\n\n function isValidFileDrag(e) {\n // e.dataTransfer currently causing IE errors\n // IE9 does NOT support file API, so drag-and-drop is not possible\n if (!qq.supportedFeatures.fileDrop) {\n return false;\n }\n\n var effectTest, dt = e.dataTransfer,\n // do not check dt.types.contains in webkit, because it crashes safari 4\n isSafari = qq.safari();\n\n // dt.effectAllowed is none in Safari 5\n // dt.types.contains check is for firefox\n\n // dt.effectAllowed crashes IE 11 & 10 when files have been dragged from\n // the filesystem\n effectTest = qq.ie() && qq.supportedFeatures.fileDrop ? true : dt.effectAllowed !== \"none\";\n return dt && effectTest && (dt.files || (!isSafari && dt.types.contains && dt.types.contains(\"Files\")));\n }\n\n function isOrSetDropDisabled(isDisabled) {\n if (isDisabled !== undefined) {\n preventDrop = isDisabled;\n }\n return preventDrop;\n }\n\n function triggerHidezonesEvent() {\n var hideZonesEvent;\n\n function triggerUsingOldApi() {\n hideZonesEvent = document.createEvent(\"Event\");\n hideZonesEvent.initEvent(options.HIDE_ZONES_EVENT_NAME, true, true);\n }\n\n if (window.CustomEvent) {\n try {\n hideZonesEvent = new CustomEvent(options.HIDE_ZONES_EVENT_NAME);\n }\n catch (err) {\n triggerUsingOldApi();\n }\n }\n else {\n triggerUsingOldApi();\n }\n\n document.dispatchEvent(hideZonesEvent);\n }\n\n function attachEvents() {\n disposeSupport.attach(element, \"dragover\", function(e) {\n if (!isValidFileDrag(e)) {\n return;\n }\n\n // dt.effectAllowed crashes IE 11 & 10 when files have been dragged from\n // the filesystem\n var effect = qq.ie() && qq.supportedFeatures.fileDrop ? null : e.dataTransfer.effectAllowed;\n if (effect === \"move\" || effect === \"linkMove\") {\n e.dataTransfer.dropEffect = \"move\"; // for FF (only move allowed)\n } else {\n e.dataTransfer.dropEffect = \"copy\"; // for Chrome\n }\n\n e.stopPropagation();\n e.preventDefault();\n });\n\n disposeSupport.attach(element, \"dragenter\", function(e) {\n if (!isOrSetDropDisabled()) {\n if (!isValidFileDrag(e)) {\n return;\n }\n options.onEnter(e);\n }\n });\n\n disposeSupport.attach(element, \"dragleave\", function(e) {\n if (!isValidFileDrag(e)) {\n return;\n }\n\n options.onLeave(e);\n\n var relatedTarget = document.elementFromPoint(e.clientX, e.clientY);\n // do not fire when moving a mouse over a descendant\n if (qq(this).contains(relatedTarget)) {\n return;\n }\n\n options.onLeaveNotDescendants(e);\n });\n\n disposeSupport.attach(element, \"drop\", function(e) {\n if (!isOrSetDropDisabled()) {\n if (!isValidFileDrag(e)) {\n return;\n }\n\n e.preventDefault();\n e.stopPropagation();\n options.onDrop(e);\n\n triggerHidezonesEvent();\n }\n });\n }\n\n disableDropOutside();\n attachEvents();\n\n qq.extend(this, {\n dropDisabled: function(isDisabled) {\n return isOrSetDropDisabled(isDisabled);\n },\n\n dispose: function() {\n disposeSupport.dispose();\n },\n\n getElement: function() {\n return element;\n }\n });\n};\n","/*globals qq */\n/**\n * Defines the public API for FineUploader mode.\n */\n(function() {\n \"use strict\";\n\n qq.uiPublicApi = {\n addInitialFiles: function(cannedFileList) {\n this._parent.prototype.addInitialFiles.apply(this, arguments);\n this._templating.addCacheToDom();\n },\n\n clearStoredFiles: function() {\n this._parent.prototype.clearStoredFiles.apply(this, arguments);\n this._templating.clearFiles();\n },\n\n addExtraDropzone: function(element) {\n this._dnd && this._dnd.setupExtraDropzone(element);\n },\n\n removeExtraDropzone: function(element) {\n if (this._dnd) {\n return this._dnd.removeDropzone(element);\n }\n },\n\n getItemByFileId: function(id) {\n if (!this._templating.isHiddenForever(id)) {\n return this._templating.getFileContainer(id);\n }\n },\n\n reset: function() {\n this._parent.prototype.reset.apply(this, arguments);\n this._templating.reset();\n\n if (!this._options.button && this._templating.getButton()) {\n this._defaultButtonId = this._createUploadButton({\n element: this._templating.getButton(),\n title: this._options.text.fileInputTitle\n }).getButtonId();\n }\n\n if (this._dnd) {\n this._dnd.dispose();\n this._dnd = this._setupDragAndDrop();\n }\n\n this._totalFilesInBatch = 0;\n this._filesInBatchAddedToUi = 0;\n\n this._setupClickAndEditEventHandlers();\n },\n\n setName: function(id, newName) {\n var formattedFilename = this._options.formatFileName(newName);\n\n this._parent.prototype.setName.apply(this, arguments);\n this._templating.updateFilename(id, formattedFilename);\n },\n\n pauseUpload: function(id) {\n var paused = this._parent.prototype.pauseUpload.apply(this, arguments);\n\n paused && this._templating.uploadPaused(id);\n return paused;\n },\n\n continueUpload: function(id) {\n var continued = this._parent.prototype.continueUpload.apply(this, arguments);\n\n continued && this._templating.uploadContinued(id);\n return continued;\n },\n\n getId: function(fileContainerOrChildEl) {\n return this._templating.getFileId(fileContainerOrChildEl);\n },\n\n getDropTarget: function(fileId) {\n var file = this.getFile(fileId);\n\n return file.qqDropTarget;\n }\n };\n\n /**\n * Defines the private (internal) API for FineUploader mode.\n */\n qq.uiPrivateApi = {\n _getButton: function(buttonId) {\n var button = this._parent.prototype._getButton.apply(this, arguments);\n\n if (!button) {\n if (buttonId === this._defaultButtonId) {\n button = this._templating.getButton();\n }\n }\n\n return button;\n },\n\n _removeFileItem: function(fileId) {\n this._templating.removeFile(fileId);\n },\n\n _setupClickAndEditEventHandlers: function() {\n this._fileButtonsClickHandler = qq.FileButtonsClickHandler && this._bindFileButtonsClickEvent();\n\n // A better approach would be to check specifically for focusin event support by querying the DOM API,\n // but the DOMFocusIn event is not exposed as a property, so we have to resort to UA string sniffing.\n this._focusinEventSupported = !qq.firefox();\n\n if (this._isEditFilenameEnabled())\n {\n this._filenameClickHandler = this._bindFilenameClickEvent();\n this._filenameInputFocusInHandler = this._bindFilenameInputFocusInEvent();\n this._filenameInputFocusHandler = this._bindFilenameInputFocusEvent();\n }\n },\n\n _setupDragAndDrop: function() {\n var self = this,\n dropZoneElements = this._options.dragAndDrop.extraDropzones,\n templating = this._templating,\n defaultDropZone = templating.getDropZone();\n\n defaultDropZone && dropZoneElements.push(defaultDropZone);\n\n return new qq.DragAndDrop({\n dropZoneElements: dropZoneElements,\n allowMultipleItems: this._options.multiple,\n classes: {\n dropActive: this._options.classes.dropActive\n },\n callbacks: {\n processingDroppedFiles: function() {\n templating.showDropProcessing();\n },\n processingDroppedFilesComplete: function(files, targetEl) {\n templating.hideDropProcessing();\n\n qq.each(files, function(idx, file) {\n file.qqDropTarget = targetEl;\n });\n\n if (files.length) {\n self.addFiles(files, null, null);\n }\n },\n dropError: function(code, errorData) {\n self._itemError(code, errorData);\n },\n dropLog: function(message, level) {\n self.log(message, level);\n }\n }\n });\n },\n\n _bindFileButtonsClickEvent: function() {\n var self = this;\n\n return new qq.FileButtonsClickHandler({\n templating: this._templating,\n\n log: function(message, lvl) {\n self.log(message, lvl);\n },\n\n onDeleteFile: function(fileId) {\n self.deleteFile(fileId);\n },\n\n onCancel: function(fileId) {\n self.cancel(fileId);\n },\n\n onRetry: function(fileId) {\n self.retry(fileId);\n },\n\n onPause: function(fileId) {\n self.pauseUpload(fileId);\n },\n\n onContinue: function(fileId) {\n self.continueUpload(fileId);\n },\n\n onGetName: function(fileId) {\n return self.getName(fileId);\n }\n });\n },\n\n _isEditFilenameEnabled: function() {\n /*jshint -W014 */\n return this._templating.isEditFilenamePossible()\n && !this._options.autoUpload\n && qq.FilenameClickHandler\n && qq.FilenameInputFocusHandler\n && qq.FilenameInputFocusHandler;\n },\n\n _filenameEditHandler: function() {\n var self = this,\n templating = this._templating;\n\n return {\n templating: templating,\n log: function(message, lvl) {\n self.log(message, lvl);\n },\n onGetUploadStatus: function(fileId) {\n return self.getUploads({id: fileId}).status;\n },\n onGetName: function(fileId) {\n return self.getName(fileId);\n },\n onSetName: function(id, newName) {\n self.setName(id, newName);\n },\n onEditingStatusChange: function(id, isEditing) {\n var qqInput = qq(templating.getEditInput(id)),\n qqFileContainer = qq(templating.getFileContainer(id));\n\n if (isEditing) {\n qqInput.addClass(\"qq-editing\");\n templating.hideFilename(id);\n templating.hideEditIcon(id);\n }\n else {\n qqInput.removeClass(\"qq-editing\");\n templating.showFilename(id);\n templating.showEditIcon(id);\n }\n\n // Force IE8 and older to repaint\n qqFileContainer.addClass(\"qq-temp\").removeClass(\"qq-temp\");\n }\n };\n },\n\n _onUploadStatusChange: function(id, oldStatus, newStatus) {\n this._parent.prototype._onUploadStatusChange.apply(this, arguments);\n\n if (this._isEditFilenameEnabled()) {\n // Status for a file exists before it has been added to the DOM, so we must be careful here.\n if (this._templating.getFileContainer(id) && newStatus !== qq.status.SUBMITTED) {\n this._templating.markFilenameEditable(id);\n this._templating.hideEditIcon(id);\n }\n }\n\n if (oldStatus === qq.status.UPLOAD_RETRYING && newStatus === qq.status.UPLOADING) {\n this._templating.hideRetry(id);\n this._templating.setStatusText(id);\n qq(this._templating.getFileContainer(id)).removeClass(this._classes.retrying);\n }\n else if (newStatus === qq.status.UPLOAD_FAILED) {\n this._templating.hidePause(id);\n }\n },\n\n _bindFilenameInputFocusInEvent: function() {\n var spec = qq.extend({}, this._filenameEditHandler());\n\n return new qq.FilenameInputFocusInHandler(spec);\n },\n\n _bindFilenameInputFocusEvent: function() {\n var spec = qq.extend({}, this._filenameEditHandler());\n\n return new qq.FilenameInputFocusHandler(spec);\n },\n\n _bindFilenameClickEvent: function() {\n var spec = qq.extend({}, this._filenameEditHandler());\n\n return new qq.FilenameClickHandler(spec);\n },\n\n _storeForLater: function(id) {\n this._parent.prototype._storeForLater.apply(this, arguments);\n this._templating.hideSpinner(id);\n },\n\n _onAllComplete: function(successful, failed) {\n this._parent.prototype._onAllComplete.apply(this, arguments);\n this._templating.resetTotalProgress();\n },\n\n _onSubmit: function(id, name) {\n var file = this.getFile(id);\n\n if (file && file.qqPath && this._options.dragAndDrop.reportDirectoryPaths) {\n this._paramsStore.addReadOnly(id, {\n qqpath: file.qqPath\n });\n }\n\n this._parent.prototype._onSubmit.apply(this, arguments);\n this._addToList(id, name);\n },\n\n // The file item has been added to the DOM.\n _onSubmitted: function(id) {\n // If the edit filename feature is enabled, mark the filename element as \"editable\" and the associated edit icon\n if (this._isEditFilenameEnabled()) {\n this._templating.markFilenameEditable(id);\n this._templating.showEditIcon(id);\n\n // If the focusin event is not supported, we must add a focus handler to the newly create edit filename text input\n if (!this._focusinEventSupported) {\n this._filenameInputFocusHandler.addHandler(this._templating.getEditInput(id));\n }\n }\n },\n\n // Update the progress bar & percentage as the file is uploaded\n _onProgress: function(id, name, loaded, total) {\n this._parent.prototype._onProgress.apply(this, arguments);\n\n this._templating.updateProgress(id, loaded, total);\n\n if (total === 0 || Math.round(loaded / total * 100) === 100) {\n this._templating.hideCancel(id);\n this._templating.hidePause(id);\n this._templating.hideProgress(id);\n this._templating.setStatusText(id, this._options.text.waitingForResponse);\n\n // If ~last byte was sent, display total file size\n this._displayFileSize(id);\n }\n else {\n // If still uploading, display percentage - total size is actually the total request(s) size\n this._displayFileSize(id, loaded, total);\n }\n },\n\n _onTotalProgress: function(loaded, total) {\n this._parent.prototype._onTotalProgress.apply(this, arguments);\n this._templating.updateTotalProgress(loaded, total);\n },\n\n _onComplete: function(id, name, result, xhr) {\n var parentRetVal = this._parent.prototype._onComplete.apply(this, arguments),\n templating = this._templating,\n fileContainer = templating.getFileContainer(id),\n self = this;\n\n function completeUpload(result) {\n // If this file is not represented in the templating module, perhaps it was hidden intentionally.\n // If so, don't perform any UI-related tasks related to this file.\n if (!fileContainer) {\n return;\n }\n\n templating.setStatusText(id);\n\n qq(fileContainer).removeClass(self._classes.retrying);\n templating.hideProgress(id);\n\n if (self.getUploads({id: id}).status !== qq.status.UPLOAD_FAILED) {\n templating.hideCancel(id);\n }\n templating.hideSpinner(id);\n\n if (result.success) {\n self._markFileAsSuccessful(id);\n }\n else {\n qq(fileContainer).addClass(self._classes.fail);\n templating.showCancel(id);\n\n if (templating.isRetryPossible() && !self._preventRetries[id]) {\n qq(fileContainer).addClass(self._classes.retryable);\n templating.showRetry(id);\n }\n self._controlFailureTextDisplay(id, result);\n }\n }\n\n // The parent may need to perform some async operation before we can accurately determine the status of the upload.\n if (parentRetVal instanceof qq.Promise) {\n parentRetVal.done(function(newResult) {\n completeUpload(newResult);\n });\n\n }\n else {\n completeUpload(result);\n }\n\n return parentRetVal;\n },\n\n _markFileAsSuccessful: function(id) {\n var templating = this._templating;\n\n if (this._isDeletePossible()) {\n templating.showDeleteButton(id);\n }\n\n qq(templating.getFileContainer(id)).addClass(this._classes.success);\n\n this._maybeUpdateThumbnail(id);\n },\n\n _onUploadPrep: function(id) {\n this._parent.prototype._onUploadPrep.apply(this, arguments);\n this._templating.showSpinner(id);\n },\n\n _onUpload: function(id, name) {\n var parentRetVal = this._parent.prototype._onUpload.apply(this, arguments);\n\n this._templating.showSpinner(id);\n\n return parentRetVal;\n },\n\n _onUploadChunk: function(id, chunkData) {\n this._parent.prototype._onUploadChunk.apply(this, arguments);\n\n // Only display the pause button if we have finished uploading at least one chunk\n // & this file can be resumed\n if (chunkData.partIndex > 0 && this._handler.isResumable(id)) {\n this._templating.allowPause(id);\n }\n },\n\n _onCancel: function(id, name) {\n this._parent.prototype._onCancel.apply(this, arguments);\n this._removeFileItem(id);\n\n if (this._getNotFinished() === 0) {\n this._templating.resetTotalProgress();\n }\n },\n\n _onBeforeAutoRetry: function(id) {\n var retryNumForDisplay, maxAuto, retryNote;\n\n this._parent.prototype._onBeforeAutoRetry.apply(this, arguments);\n\n this._showCancelLink(id);\n\n if (this._options.retry.showAutoRetryNote) {\n retryNumForDisplay = this._autoRetries[id];\n maxAuto = this._options.retry.maxAutoAttempts;\n\n retryNote = this._options.retry.autoRetryNote.replace(/\\{retryNum\\}/g, retryNumForDisplay);\n retryNote = retryNote.replace(/\\{maxAuto\\}/g, maxAuto);\n\n this._templating.setStatusText(id, retryNote);\n qq(this._templating.getFileContainer(id)).addClass(this._classes.retrying);\n }\n },\n\n //return false if we should not attempt the requested retry\n _onBeforeManualRetry: function(id) {\n if (this._parent.prototype._onBeforeManualRetry.apply(this, arguments)) {\n this._templating.resetProgress(id);\n qq(this._templating.getFileContainer(id)).removeClass(this._classes.fail);\n this._templating.setStatusText(id);\n this._templating.showSpinner(id);\n this._showCancelLink(id);\n return true;\n }\n else {\n qq(this._templating.getFileContainer(id)).addClass(this._classes.retryable);\n this._templating.showRetry(id);\n return false;\n }\n },\n\n _onSubmitDelete: function(id) {\n var onSuccessCallback = qq.bind(this._onSubmitDeleteSuccess, this);\n\n this._parent.prototype._onSubmitDelete.call(this, id, onSuccessCallback);\n },\n\n _onSubmitDeleteSuccess: function(id, uuid, additionalMandatedParams) {\n if (this._options.deleteFile.forceConfirm) {\n this._showDeleteConfirm.apply(this, arguments);\n }\n else {\n this._sendDeleteRequest.apply(this, arguments);\n }\n },\n\n _onDeleteComplete: function(id, xhr, isError) {\n this._parent.prototype._onDeleteComplete.apply(this, arguments);\n\n this._templating.hideSpinner(id);\n\n if (isError) {\n this._templating.setStatusText(id, this._options.deleteFile.deletingFailedText);\n this._templating.showDeleteButton(id);\n }\n else {\n this._removeFileItem(id);\n }\n },\n\n _sendDeleteRequest: function(id, uuid, additionalMandatedParams) {\n this._templating.hideDeleteButton(id);\n this._templating.showSpinner(id);\n this._templating.setStatusText(id, this._options.deleteFile.deletingStatusText);\n this._deleteHandler.sendDelete.apply(this, arguments);\n },\n\n _showDeleteConfirm: function(id, uuid, mandatedParams) {\n /*jshint -W004 */\n var fileName = this.getName(id),\n confirmMessage = this._options.deleteFile.confirmMessage.replace(/\\{filename\\}/g, fileName),\n uuid = this.getUuid(id),\n deleteRequestArgs = arguments,\n self = this,\n retVal;\n\n retVal = this._options.showConfirm(confirmMessage);\n\n if (qq.isGenericPromise(retVal)) {\n retVal.then(function() {\n self._sendDeleteRequest.apply(self, deleteRequestArgs);\n });\n }\n else if (retVal !== false) {\n self._sendDeleteRequest.apply(self, deleteRequestArgs);\n }\n },\n\n _addToList: function(id, name, canned) {\n var prependData,\n prependIndex = 0,\n dontDisplay = this._handler.isProxied(id) && this._options.scaling.hideScaled,\n record;\n\n if (this._options.display.prependFiles) {\n if (this._totalFilesInBatch > 1 && this._filesInBatchAddedToUi > 0) {\n prependIndex = this._filesInBatchAddedToUi - 1;\n }\n\n prependData = {\n index: prependIndex\n };\n }\n\n if (!canned) {\n if (this._options.disableCancelForFormUploads && !qq.supportedFeatures.ajaxUploading) {\n this._templating.disableCancel();\n }\n\n // Cancel all existing (previous) files and clear the list if this file is not part of\n // a scaled file group that has already been accepted, or if this file is not part of\n // a scaled file group at all.\n if (!this._options.multiple) {\n record = this.getUploads({id: id});\n\n this._handledProxyGroup = this._handledProxyGroup || record.proxyGroupId;\n\n if (record.proxyGroupId !== this._handledProxyGroup || !record.proxyGroupId) {\n this._handler.cancelAll();\n this._clearList();\n this._handledProxyGroup = null;\n }\n }\n }\n\n if (canned) {\n this._templating.addFileToCache(id, this._options.formatFileName(name), prependData, dontDisplay);\n this._templating.updateThumbnail(id, this._thumbnailUrls[id], true, this._options.thumbnails.customResizer);\n }\n else {\n this._templating.addFile(id, this._options.formatFileName(name), prependData, dontDisplay);\n this._templating.generatePreview(id, this.getFile(id), this._options.thumbnails.customResizer);\n }\n\n this._filesInBatchAddedToUi += 1;\n\n if (canned ||\n (this._options.display.fileSizeOnSubmit && qq.supportedFeatures.ajaxUploading)) {\n\n this._displayFileSize(id);\n }\n },\n\n _clearList: function() {\n this._templating.clearFiles();\n this.clearStoredFiles();\n },\n\n _displayFileSize: function(id, loadedSize, totalSize) {\n var size = this.getSize(id),\n sizeForDisplay = this._formatSize(size);\n\n if (size >= 0) {\n if (loadedSize !== undefined && totalSize !== undefined) {\n sizeForDisplay = this._formatProgress(loadedSize, totalSize);\n }\n\n this._templating.updateSize(id, sizeForDisplay);\n }\n },\n\n _formatProgress: function(uploadedSize, totalSize) {\n var message = this._options.text.formatProgress;\n function r(name, replacement) { message = message.replace(name, replacement); }\n\n r(\"{percent}\", Math.round(uploadedSize / totalSize * 100));\n r(\"{total_size}\", this._formatSize(totalSize));\n return message;\n },\n\n _controlFailureTextDisplay: function(id, response) {\n var mode, responseProperty, failureReason;\n\n mode = this._options.failedUploadTextDisplay.mode;\n responseProperty = this._options.failedUploadTextDisplay.responseProperty;\n\n if (mode === \"custom\") {\n failureReason = response[responseProperty];\n if (!failureReason) {\n failureReason = this._options.text.failUpload;\n }\n\n this._templating.setStatusText(id, failureReason);\n\n if (this._options.failedUploadTextDisplay.enableTooltip) {\n this._showTooltip(id, failureReason);\n }\n }\n else if (mode === \"default\") {\n this._templating.setStatusText(id, this._options.text.failUpload);\n }\n else if (mode !== \"none\") {\n this.log(\"failedUploadTextDisplay.mode value of '\" + mode + \"' is not valid\", \"warn\");\n }\n },\n\n _showTooltip: function(id, text) {\n this._templating.getFileContainer(id).title = text;\n },\n\n _showCancelLink: function(id) {\n if (!this._options.disableCancelForFormUploads || qq.supportedFeatures.ajaxUploading) {\n this._templating.showCancel(id);\n }\n },\n\n _itemError: function(code, name, item) {\n var message = this._parent.prototype._itemError.apply(this, arguments);\n this._options.showMessage(message);\n },\n\n _batchError: function(message) {\n this._parent.prototype._batchError.apply(this, arguments);\n this._options.showMessage(message);\n },\n\n _setupPastePrompt: function() {\n var self = this;\n\n this._options.callbacks.onPasteReceived = function() {\n var message = self._options.paste.namePromptMessage,\n defaultVal = self._options.paste.defaultName;\n\n return self._options.showPrompt(message, defaultVal);\n };\n },\n\n _fileOrBlobRejected: function(id, name) {\n this._totalFilesInBatch -= 1;\n this._parent.prototype._fileOrBlobRejected.apply(this, arguments);\n },\n\n _prepareItemsForUpload: function(items, params, endpoint) {\n this._totalFilesInBatch = items.length;\n this._filesInBatchAddedToUi = 0;\n this._parent.prototype._prepareItemsForUpload.apply(this, arguments);\n },\n\n _maybeUpdateThumbnail: function(fileId) {\n var thumbnailUrl = this._thumbnailUrls[fileId],\n fileStatus = this.getUploads({id: fileId}).status;\n\n if (fileStatus !== qq.status.DELETED &&\n (thumbnailUrl ||\n this._options.thumbnails.placeholders.waitUntilResponse ||\n !qq.supportedFeatures.imagePreviews)) {\n\n // This will replace the \"waiting\" placeholder with a \"preview not available\" placeholder\n // if called with a null thumbnailUrl.\n this._templating.updateThumbnail(fileId, thumbnailUrl, this._options.thumbnails.customResizer);\n }\n },\n\n _addCannedFile: function(sessionData) {\n var id = this._parent.prototype._addCannedFile.apply(this, arguments);\n\n this._addToList(id, this.getName(id), true);\n this._templating.hideSpinner(id);\n this._templating.hideCancel(id);\n this._markFileAsSuccessful(id);\n\n return id;\n },\n\n _setSize: function(id, newSize) {\n this._parent.prototype._setSize.apply(this, arguments);\n\n this._templating.updateSize(id, this._formatSize(newSize));\n },\n\n _sessionRequestComplete: function() {\n this._templating.addCacheToDom();\n this._parent.prototype._sessionRequestComplete.apply(this, arguments);\n }\n };\n}());\n","/*globals qq */\n/**\n * This defines FineUploader mode, which is a default UI w/ drag & drop uploading.\n */\nqq.FineUploader = function(o, namespace) {\n \"use strict\";\n\n var self = this;\n\n // By default this should inherit instance data from FineUploaderBasic, but this can be overridden\n // if the (internal) caller defines a different parent. The parent is also used by\n // the private and public API functions that need to delegate to a parent function.\n this._parent = namespace ? qq[namespace].FineUploaderBasic : qq.FineUploaderBasic;\n this._parent.apply(this, arguments);\n\n // Options provided by FineUploader mode\n qq.extend(this._options, {\n element: null,\n\n button: null,\n\n listElement: null,\n\n dragAndDrop: {\n extraDropzones: [],\n reportDirectoryPaths: false\n },\n\n text: {\n formatProgress: \"{percent}% of {total_size}\",\n failUpload: \"Upload failed\",\n waitingForResponse: \"Processing...\",\n paused: \"Paused\"\n },\n\n template: \"qq-template\",\n\n classes: {\n retrying: \"qq-upload-retrying\",\n retryable: \"qq-upload-retryable\",\n success: \"qq-upload-success\",\n fail: \"qq-upload-fail\",\n editable: \"qq-editable\",\n hide: \"qq-hide\",\n dropActive: \"qq-upload-drop-area-active\"\n },\n\n failedUploadTextDisplay: {\n mode: \"default\", //default, custom, or none\n responseProperty: \"error\",\n enableTooltip: true\n },\n\n messages: {\n tooManyFilesError: \"You may only drop one file\",\n unsupportedBrowser: \"Unrecoverable error - this browser does not permit file uploading of any kind.\"\n },\n\n retry: {\n showAutoRetryNote: true,\n autoRetryNote: \"Retrying {retryNum}/{maxAuto}...\"\n },\n\n deleteFile: {\n forceConfirm: false,\n confirmMessage: \"Are you sure you want to delete {filename}?\",\n deletingStatusText: \"Deleting...\",\n deletingFailedText: \"Delete failed\"\n\n },\n\n display: {\n fileSizeOnSubmit: false,\n prependFiles: false\n },\n\n paste: {\n promptForName: false,\n namePromptMessage: \"Please name this image\"\n },\n\n thumbnails: {\n customResizer: null,\n maxCount: 0,\n placeholders: {\n waitUntilResponse: false,\n notAvailablePath: null,\n waitingPath: null\n },\n timeBetweenThumbs: 750\n },\n\n scaling: {\n hideScaled: false\n },\n\n showMessage: function(message) {\n if (self._templating.hasDialog(\"alert\")) {\n return self._templating.showDialog(\"alert\", message);\n }\n else {\n setTimeout(function() {\n window.alert(message);\n }, 0);\n }\n },\n\n showConfirm: function(message) {\n if (self._templating.hasDialog(\"confirm\")) {\n return self._templating.showDialog(\"confirm\", message);\n }\n else {\n return window.confirm(message);\n }\n },\n\n showPrompt: function(message, defaultValue) {\n if (self._templating.hasDialog(\"prompt\")) {\n return self._templating.showDialog(\"prompt\", message, defaultValue);\n }\n else {\n return window.prompt(message, defaultValue);\n }\n }\n }, true);\n\n // Replace any default options with user defined ones\n qq.extend(this._options, o, true);\n\n this._templating = new qq.Templating({\n log: qq.bind(this.log, this),\n templateIdOrEl: this._options.template,\n containerEl: this._options.element,\n fileContainerEl: this._options.listElement,\n button: this._options.button,\n imageGenerator: this._imageGenerator,\n classes: {\n hide: this._options.classes.hide,\n editable: this._options.classes.editable\n },\n limits: {\n maxThumbs: this._options.thumbnails.maxCount,\n timeBetweenThumbs: this._options.thumbnails.timeBetweenThumbs\n },\n placeholders: {\n waitUntilUpdate: this._options.thumbnails.placeholders.waitUntilResponse,\n thumbnailNotAvailable: this._options.thumbnails.placeholders.notAvailablePath,\n waitingForThumbnail: this._options.thumbnails.placeholders.waitingPath\n },\n text: this._options.text\n });\n\n if (this._options.workarounds.ios8SafariUploads && qq.ios800() && qq.iosSafari()) {\n this._templating.renderFailure(this._options.messages.unsupportedBrowserIos8Safari);\n }\n else if (!qq.supportedFeatures.uploading || (this._options.cors.expected && !qq.supportedFeatures.uploadCors)) {\n this._templating.renderFailure(this._options.messages.unsupportedBrowser);\n }\n else {\n this._wrapCallbacks();\n\n this._templating.render();\n\n this._classes = this._options.classes;\n\n if (!this._options.button && this._templating.getButton()) {\n this._defaultButtonId = this._createUploadButton({\n element: this._templating.getButton(),\n title: this._options.text.fileInputTitle\n }).getButtonId();\n }\n\n this._setupClickAndEditEventHandlers();\n\n if (qq.DragAndDrop && qq.supportedFeatures.fileDrop) {\n this._dnd = this._setupDragAndDrop();\n }\n\n if (this._options.paste.targetElement && this._options.paste.promptForName) {\n if (qq.PasteSupport) {\n this._setupPastePrompt();\n }\n else {\n this.log(\"Paste support module not found.\", \"error\");\n }\n }\n\n this._totalFilesInBatch = 0;\n this._filesInBatchAddedToUi = 0;\n }\n};\n\n// Inherit the base public & private API methods\nqq.extend(qq.FineUploader.prototype, qq.basePublicApi);\nqq.extend(qq.FineUploader.prototype, qq.basePrivateApi);\n\n// Add the FineUploader/default UI public & private UI methods, which may override some base methods.\nqq.extend(qq.FineUploader.prototype, qq.uiPublicApi);\nqq.extend(qq.FineUploader.prototype, qq.uiPrivateApi);\n","/* globals qq */\n/* jshint -W065 */\n/**\n * Module responsible for rendering all Fine Uploader UI templates. This module also asserts at least\n * a limited amount of control over the template elements after they are added to the DOM.\n * Wherever possible, this module asserts total control over template elements present in the DOM.\n *\n * @param spec Specification object used to control various templating behaviors\n * @constructor\n */\nqq.Templating = function(spec) {\n \"use strict\";\n\n var FILE_ID_ATTR = \"qq-file-id\",\n FILE_CLASS_PREFIX = \"qq-file-id-\",\n THUMBNAIL_MAX_SIZE_ATTR = \"qq-max-size\",\n THUMBNAIL_SERVER_SCALE_ATTR = \"qq-server-scale\",\n // This variable is duplicated in the DnD module since it can function as a standalone as well\n HIDE_DROPZONE_ATTR = \"qq-hide-dropzone\",\n DROPZPONE_TEXT_ATTR = \"qq-drop-area-text\",\n IN_PROGRESS_CLASS = \"qq-in-progress\",\n HIDDEN_FOREVER_CLASS = \"qq-hidden-forever\",\n fileBatch = {\n content: document.createDocumentFragment(),\n map: {}\n },\n isCancelDisabled = false,\n generatedThumbnails = 0,\n thumbnailQueueMonitorRunning = false,\n thumbGenerationQueue = [],\n thumbnailMaxSize = -1,\n options = {\n log: null,\n limits: {\n maxThumbs: 0,\n timeBetweenThumbs: 750\n },\n templateIdOrEl: \"qq-template\",\n containerEl: null,\n fileContainerEl: null,\n button: null,\n imageGenerator: null,\n classes: {\n hide: \"qq-hide\",\n editable: \"qq-editable\"\n },\n placeholders: {\n waitUntilUpdate: false,\n thumbnailNotAvailable: null,\n waitingForThumbnail: null\n },\n text: {\n paused: \"Paused\"\n }\n },\n selectorClasses = {\n button: \"qq-upload-button-selector\",\n alertDialog: \"qq-alert-dialog-selector\",\n dialogCancelButton: \"qq-cancel-button-selector\",\n confirmDialog: \"qq-confirm-dialog-selector\",\n dialogMessage: \"qq-dialog-message-selector\",\n dialogOkButton: \"qq-ok-button-selector\",\n promptDialog: \"qq-prompt-dialog-selector\",\n uploader: \"qq-uploader-selector\",\n drop: \"qq-upload-drop-area-selector\",\n list: \"qq-upload-list-selector\",\n progressBarContainer: \"qq-progress-bar-container-selector\",\n progressBar: \"qq-progress-bar-selector\",\n totalProgressBarContainer: \"qq-total-progress-bar-container-selector\",\n totalProgressBar: \"qq-total-progress-bar-selector\",\n file: \"qq-upload-file-selector\",\n spinner: \"qq-upload-spinner-selector\",\n size: \"qq-upload-size-selector\",\n cancel: \"qq-upload-cancel-selector\",\n pause: \"qq-upload-pause-selector\",\n continueButton: \"qq-upload-continue-selector\",\n deleteButton: \"qq-upload-delete-selector\",\n retry: \"qq-upload-retry-selector\",\n statusText: \"qq-upload-status-text-selector\",\n editFilenameInput: \"qq-edit-filename-selector\",\n editNameIcon: \"qq-edit-filename-icon-selector\",\n dropText: \"qq-upload-drop-area-text-selector\",\n dropProcessing: \"qq-drop-processing-selector\",\n dropProcessingSpinner: \"qq-drop-processing-spinner-selector\",\n thumbnail: \"qq-thumbnail-selector\"\n },\n previewGeneration = {},\n cachedThumbnailNotAvailableImg = new qq.Promise(),\n cachedWaitingForThumbnailImg = new qq.Promise(),\n log,\n isEditElementsExist,\n isRetryElementExist,\n templateHtml,\n container,\n fileList,\n showThumbnails,\n serverScale,\n\n // During initialization of the templating module we should cache any\n // placeholder images so we can quickly swap them into the file list on demand.\n // Any placeholder images that cannot be loaded/found are simply ignored.\n cacheThumbnailPlaceholders = function() {\n var notAvailableUrl = options.placeholders.thumbnailNotAvailable,\n waitingUrl = options.placeholders.waitingForThumbnail,\n spec = {\n maxSize: thumbnailMaxSize,\n scale: serverScale\n };\n\n if (showThumbnails) {\n if (notAvailableUrl) {\n options.imageGenerator.generate(notAvailableUrl, new Image(), spec).then(\n function(updatedImg) {\n cachedThumbnailNotAvailableImg.success(updatedImg);\n },\n function() {\n cachedThumbnailNotAvailableImg.failure();\n log(\"Problem loading 'not available' placeholder image at \" + notAvailableUrl, \"error\");\n }\n );\n }\n else {\n cachedThumbnailNotAvailableImg.failure();\n }\n\n if (waitingUrl) {\n options.imageGenerator.generate(waitingUrl, new Image(), spec).then(\n function(updatedImg) {\n cachedWaitingForThumbnailImg.success(updatedImg);\n },\n function() {\n cachedWaitingForThumbnailImg.failure();\n log(\"Problem loading 'waiting for thumbnail' placeholder image at \" + waitingUrl, \"error\");\n }\n );\n }\n else {\n cachedWaitingForThumbnailImg.failure();\n }\n }\n },\n\n // Displays a \"waiting for thumbnail\" type placeholder image\n // iff we were able to load it during initialization of the templating module.\n displayWaitingImg = function(thumbnail) {\n var waitingImgPlacement = new qq.Promise();\n\n cachedWaitingForThumbnailImg.then(function(img) {\n maybeScalePlaceholderViaCss(img, thumbnail);\n /* jshint eqnull:true */\n if (!thumbnail.src) {\n thumbnail.src = img.src;\n thumbnail.onload = function() {\n thumbnail.onload = null;\n show(thumbnail);\n waitingImgPlacement.success();\n };\n }\n else {\n waitingImgPlacement.success();\n }\n }, function() {\n // In some browsers (such as IE9 and older) an img w/out a src attribute\n // are displayed as \"broken\" images, so we should just hide the img tag\n // if we aren't going to display the \"waiting\" placeholder.\n hide(thumbnail);\n waitingImgPlacement.success();\n });\n\n return waitingImgPlacement;\n },\n\n generateNewPreview = function(id, blob, spec) {\n var thumbnail = getThumbnail(id);\n\n log(\"Generating new thumbnail for \" + id);\n blob.qqThumbnailId = id;\n\n return options.imageGenerator.generate(blob, thumbnail, spec).then(\n function() {\n generatedThumbnails++;\n show(thumbnail);\n previewGeneration[id].success();\n },\n function() {\n previewGeneration[id].failure();\n\n // Display the \"not available\" placeholder img only if we are\n // not expecting a thumbnail at a later point, such as in a server response.\n if (!options.placeholders.waitUntilUpdate) {\n maybeSetDisplayNotAvailableImg(id, thumbnail);\n }\n });\n },\n\n generateNextQueuedPreview = function() {\n if (thumbGenerationQueue.length) {\n thumbnailQueueMonitorRunning = true;\n\n var queuedThumbRequest = thumbGenerationQueue.shift();\n\n if (queuedThumbRequest.update) {\n processUpdateQueuedPreviewRequest(queuedThumbRequest);\n }\n else {\n processNewQueuedPreviewRequest(queuedThumbRequest);\n }\n }\n else {\n thumbnailQueueMonitorRunning = false;\n }\n },\n\n getCancel = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.cancel);\n },\n\n getContinue = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.continueButton);\n },\n\n getDialog = function(type) {\n return getTemplateEl(container, selectorClasses[type + \"Dialog\"]);\n },\n\n getDelete = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.deleteButton);\n },\n\n getDropProcessing = function() {\n return getTemplateEl(container, selectorClasses.dropProcessing);\n },\n\n getEditIcon = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.editNameIcon);\n },\n\n getFile = function(id) {\n return fileBatch.map[id] || qq(fileList).getFirstByClass(FILE_CLASS_PREFIX + id);\n },\n\n getFilename = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.file);\n },\n\n getPause = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.pause);\n },\n\n getProgress = function(id) {\n /* jshint eqnull:true */\n // Total progress bar\n if (id == null) {\n return getTemplateEl(container, selectorClasses.totalProgressBarContainer) ||\n getTemplateEl(container, selectorClasses.totalProgressBar);\n }\n\n // Per-file progress bar\n return getTemplateEl(getFile(id), selectorClasses.progressBarContainer) ||\n getTemplateEl(getFile(id), selectorClasses.progressBar);\n },\n\n getRetry = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.retry);\n },\n\n getSize = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.size);\n },\n\n getSpinner = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.spinner);\n },\n\n getTemplateEl = function(context, cssClass) {\n return context && qq(context).getFirstByClass(cssClass);\n },\n\n getThumbnail = function(id) {\n return showThumbnails && getTemplateEl(getFile(id), selectorClasses.thumbnail);\n },\n\n hide = function(el) {\n el && qq(el).addClass(options.classes.hide);\n },\n\n // Ensures a placeholder image does not exceed any max size specified\n // via `style` attribute properties iff was not used to scale\n // the placeholder AND the target doesn't already have these `style` attribute properties set.\n maybeScalePlaceholderViaCss = function(placeholder, thumbnail) {\n var maxWidth = placeholder.style.maxWidth,\n maxHeight = placeholder.style.maxHeight;\n\n if (maxHeight && maxWidth && !thumbnail.style.maxWidth && !thumbnail.style.maxHeight) {\n qq(thumbnail).css({\n maxWidth: maxWidth,\n maxHeight: maxHeight\n });\n }\n },\n\n // Displays a \"thumbnail not available\" type placeholder image\n // iff we were able to load this placeholder during initialization\n // of the templating module or after preview generation has failed.\n maybeSetDisplayNotAvailableImg = function(id, thumbnail) {\n var previewing = previewGeneration[id] || new qq.Promise().failure(),\n notAvailableImgPlacement = new qq.Promise();\n\n cachedThumbnailNotAvailableImg.then(function(img) {\n previewing.then(\n function() {\n notAvailableImgPlacement.success();\n },\n function() {\n maybeScalePlaceholderViaCss(img, thumbnail);\n\n thumbnail.onload = function() {\n thumbnail.onload = null;\n notAvailableImgPlacement.success();\n };\n\n thumbnail.src = img.src;\n show(thumbnail);\n }\n );\n });\n\n return notAvailableImgPlacement;\n },\n\n /**\n * Grabs the HTML from the script tag holding the template markup. This function will also adjust\n * some internally-tracked state variables based on the contents of the template.\n * The template is filtered so that irrelevant elements (such as the drop zone if DnD is not supported)\n * are omitted from the DOM. Useful errors will be thrown if the template cannot be parsed.\n *\n * @returns {{template: *, fileTemplate: *}} HTML for the top-level file items templates\n */\n parseAndGetTemplate = function() {\n var scriptEl,\n scriptHtml,\n fileListNode,\n tempTemplateEl,\n fileListHtml,\n defaultButton,\n dropArea,\n thumbnail,\n dropProcessing,\n dropTextEl,\n uploaderEl;\n\n log(\"Parsing template\");\n\n /*jshint -W116*/\n if (options.templateIdOrEl == null) {\n throw new Error(\"You MUST specify either a template element or ID!\");\n }\n\n // Grab the contents of the script tag holding the template.\n if (qq.isString(options.templateIdOrEl)) {\n scriptEl = document.getElementById(options.templateIdOrEl);\n\n if (scriptEl === null) {\n throw new Error(qq.format(\"Cannot find template script at ID '{}'!\", options.templateIdOrEl));\n }\n\n scriptHtml = scriptEl.innerHTML;\n }\n else {\n if (options.templateIdOrEl.innerHTML === undefined) {\n throw new Error(\"You have specified an invalid value for the template option! \" +\n \"It must be an ID or an Element.\");\n }\n\n scriptHtml = options.templateIdOrEl.innerHTML;\n }\n\n scriptHtml = qq.trimStr(scriptHtml);\n tempTemplateEl = document.createElement(\"div\");\n tempTemplateEl.appendChild(qq.toElement(scriptHtml));\n uploaderEl = qq(tempTemplateEl).getFirstByClass(selectorClasses.uploader);\n\n // Don't include the default template button in the DOM\n // if an alternate button container has been specified.\n if (options.button) {\n defaultButton = qq(tempTemplateEl).getFirstByClass(selectorClasses.button);\n if (defaultButton) {\n qq(defaultButton).remove();\n }\n }\n\n // Omit the drop processing element from the DOM if DnD is not supported by the UA,\n // or the drag and drop module is not found.\n // NOTE: We are consciously not removing the drop zone if the UA doesn't support DnD\n // to support layouts where the drop zone is also a container for visible elements,\n // such as the file list.\n if (!qq.DragAndDrop || !qq.supportedFeatures.fileDrop) {\n dropProcessing = qq(tempTemplateEl).getFirstByClass(selectorClasses.dropProcessing);\n if (dropProcessing) {\n qq(dropProcessing).remove();\n }\n }\n\n dropArea = qq(tempTemplateEl).getFirstByClass(selectorClasses.drop);\n\n // If DnD is not available then remove\n // it from the DOM as well.\n if (dropArea && !qq.DragAndDrop) {\n log(\"DnD module unavailable.\", \"info\");\n qq(dropArea).remove();\n }\n\n if (!qq.supportedFeatures.fileDrop) {\n // don't display any \"drop files to upload\" background text\n uploaderEl.removeAttribute(DROPZPONE_TEXT_ATTR);\n\n if (dropArea && qq(dropArea).hasAttribute(HIDE_DROPZONE_ATTR)) {\n // If there is a drop area defined in the template, and the current UA doesn't support DnD,\n // and the drop area is marked as \"hide before enter\", ensure it is hidden as the DnD module\n // will not do this (since we will not be loading the DnD module)\n qq(dropArea).css({\n display: \"none\"\n });\n }\n }\n else if (qq(uploaderEl).hasAttribute(DROPZPONE_TEXT_ATTR) && dropArea) {\n dropTextEl = qq(dropArea).getFirstByClass(selectorClasses.dropText);\n dropTextEl && qq(dropTextEl).remove();\n }\n\n // Ensure the `showThumbnails` flag is only set if the thumbnail element\n // is present in the template AND the current UA is capable of generating client-side previews.\n thumbnail = qq(tempTemplateEl).getFirstByClass(selectorClasses.thumbnail);\n if (!showThumbnails) {\n thumbnail && qq(thumbnail).remove();\n }\n else if (thumbnail) {\n thumbnailMaxSize = parseInt(thumbnail.getAttribute(THUMBNAIL_MAX_SIZE_ATTR));\n // Only enforce max size if the attr value is non-zero\n thumbnailMaxSize = thumbnailMaxSize > 0 ? thumbnailMaxSize : null;\n\n serverScale = qq(thumbnail).hasAttribute(THUMBNAIL_SERVER_SCALE_ATTR);\n }\n showThumbnails = showThumbnails && thumbnail;\n\n isEditElementsExist = qq(tempTemplateEl).getByClass(selectorClasses.editFilenameInput).length > 0;\n isRetryElementExist = qq(tempTemplateEl).getByClass(selectorClasses.retry).length > 0;\n\n fileListNode = qq(tempTemplateEl).getFirstByClass(selectorClasses.list);\n /*jshint -W116*/\n if (fileListNode == null) {\n throw new Error(\"Could not find the file list container in the template!\");\n }\n\n fileListHtml = fileListNode.innerHTML;\n fileListNode.innerHTML = \"\";\n\n // We must call `createElement` in IE8 in order to target and hide any via CSS\n if (tempTemplateEl.getElementsByTagName(\"DIALOG\").length) {\n document.createElement(\"dialog\");\n }\n\n log(\"Template parsing complete\");\n\n return {\n template: qq.trimStr(tempTemplateEl.innerHTML),\n fileTemplate: qq.trimStr(fileListHtml)\n };\n },\n\n prependFile = function(el, index, fileList) {\n var parentEl = fileList,\n beforeEl = parentEl.firstChild;\n\n if (index > 0) {\n beforeEl = qq(parentEl).children()[index].nextSibling;\n\n }\n\n parentEl.insertBefore(el, beforeEl);\n },\n\n processNewQueuedPreviewRequest = function(queuedThumbRequest) {\n var id = queuedThumbRequest.id,\n optFileOrBlob = queuedThumbRequest.optFileOrBlob,\n relatedThumbnailId = optFileOrBlob && optFileOrBlob.qqThumbnailId,\n thumbnail = getThumbnail(id),\n spec = {\n customResizeFunction: queuedThumbRequest.customResizeFunction,\n maxSize: thumbnailMaxSize,\n orient: true,\n scale: true\n };\n\n if (qq.supportedFeatures.imagePreviews) {\n if (thumbnail) {\n if (options.limits.maxThumbs && options.limits.maxThumbs <= generatedThumbnails) {\n maybeSetDisplayNotAvailableImg(id, thumbnail);\n generateNextQueuedPreview();\n }\n else {\n displayWaitingImg(thumbnail).done(function() {\n previewGeneration[id] = new qq.Promise();\n\n previewGeneration[id].done(function() {\n setTimeout(generateNextQueuedPreview, options.limits.timeBetweenThumbs);\n });\n\n /* jshint eqnull: true */\n // If we've already generated an for this file, use the one that exists,\n // don't waste resources generating a new one.\n if (relatedThumbnailId != null) {\n useCachedPreview(id, relatedThumbnailId);\n }\n else {\n generateNewPreview(id, optFileOrBlob, spec);\n }\n });\n }\n }\n // File element in template may have been removed, so move on to next item in queue\n else {\n generateNextQueuedPreview();\n }\n }\n else if (thumbnail) {\n displayWaitingImg(thumbnail);\n generateNextQueuedPreview();\n }\n },\n\n processUpdateQueuedPreviewRequest = function(queuedThumbRequest) {\n var id = queuedThumbRequest.id,\n thumbnailUrl = queuedThumbRequest.thumbnailUrl,\n showWaitingImg = queuedThumbRequest.showWaitingImg,\n thumbnail = getThumbnail(id),\n spec = {\n customResizeFunction: queuedThumbRequest.customResizeFunction,\n scale: serverScale,\n maxSize: thumbnailMaxSize\n };\n\n if (thumbnail) {\n if (thumbnailUrl) {\n if (options.limits.maxThumbs && options.limits.maxThumbs <= generatedThumbnails) {\n maybeSetDisplayNotAvailableImg(id, thumbnail);\n generateNextQueuedPreview();\n }\n else {\n if (showWaitingImg) {\n displayWaitingImg(thumbnail);\n }\n\n return options.imageGenerator.generate(thumbnailUrl, thumbnail, spec).then(\n function() {\n show(thumbnail);\n generatedThumbnails++;\n setTimeout(generateNextQueuedPreview, options.limits.timeBetweenThumbs);\n },\n\n function() {\n maybeSetDisplayNotAvailableImg(id, thumbnail);\n setTimeout(generateNextQueuedPreview, options.limits.timeBetweenThumbs);\n }\n );\n }\n }\n else {\n maybeSetDisplayNotAvailableImg(id, thumbnail);\n generateNextQueuedPreview();\n }\n }\n },\n\n setProgressBarWidth = function(id, percent) {\n var bar = getProgress(id),\n /* jshint eqnull:true */\n progressBarSelector = id == null ? selectorClasses.totalProgressBar : selectorClasses.progressBar;\n\n if (bar && !qq(bar).hasClass(progressBarSelector)) {\n bar = qq(bar).getFirstByClass(progressBarSelector);\n }\n\n if (bar) {\n qq(bar).css({width: percent + \"%\"});\n bar.setAttribute(\"aria-valuenow\", percent);\n }\n },\n\n show = function(el) {\n el && qq(el).removeClass(options.classes.hide);\n },\n\n useCachedPreview = function(targetThumbnailId, cachedThumbnailId) {\n var targetThumbnail = getThumbnail(targetThumbnailId),\n cachedThumbnail = getThumbnail(cachedThumbnailId);\n\n log(qq.format(\"ID {} is the same file as ID {}. Will use generated thumbnail from ID {} instead.\", targetThumbnailId, cachedThumbnailId, cachedThumbnailId));\n\n // Generation of the related thumbnail may still be in progress, so, wait until it is done.\n previewGeneration[cachedThumbnailId].then(function() {\n generatedThumbnails++;\n previewGeneration[targetThumbnailId].success();\n log(qq.format(\"Now using previously generated thumbnail created for ID {} on ID {}.\", cachedThumbnailId, targetThumbnailId));\n targetThumbnail.src = cachedThumbnail.src;\n show(targetThumbnail);\n },\n function() {\n previewGeneration[targetThumbnailId].failure();\n if (!options.placeholders.waitUntilUpdate) {\n maybeSetDisplayNotAvailableImg(targetThumbnailId, targetThumbnail);\n }\n });\n };\n\n qq.extend(options, spec);\n log = options.log;\n\n // No need to worry about conserving CPU or memory on older browsers,\n // since there is no ability to preview, and thumbnail display is primitive and quick.\n if (!qq.supportedFeatures.imagePreviews) {\n options.limits.timeBetweenThumbs = 0;\n options.limits.maxThumbs = 0;\n }\n\n container = options.containerEl;\n showThumbnails = options.imageGenerator !== undefined;\n templateHtml = parseAndGetTemplate();\n\n cacheThumbnailPlaceholders();\n\n qq.extend(this, {\n render: function() {\n log(\"Rendering template in DOM.\");\n\n generatedThumbnails = 0;\n\n container.innerHTML = templateHtml.template;\n hide(getDropProcessing());\n this.hideTotalProgress();\n fileList = options.fileContainerEl || getTemplateEl(container, selectorClasses.list);\n\n log(\"Template rendering complete\");\n },\n\n renderFailure: function(message) {\n var cantRenderEl = qq.toElement(message);\n container.innerHTML = \"\";\n container.appendChild(cantRenderEl);\n },\n\n reset: function() {\n this.render();\n },\n\n clearFiles: function() {\n fileList.innerHTML = \"\";\n },\n\n disableCancel: function() {\n isCancelDisabled = true;\n },\n\n addFile: function(id, name, prependInfo, hideForever, batch) {\n var fileEl = qq.toElement(templateHtml.fileTemplate),\n fileNameEl = getTemplateEl(fileEl, selectorClasses.file),\n uploaderEl = getTemplateEl(container, selectorClasses.uploader),\n fileContainer = batch ? fileBatch.content : fileList,\n thumb;\n\n if (batch) {\n fileBatch.map[id] = fileEl;\n }\n\n qq(fileEl).addClass(FILE_CLASS_PREFIX + id);\n uploaderEl.removeAttribute(DROPZPONE_TEXT_ATTR);\n\n if (fileNameEl) {\n qq(fileNameEl).setText(name);\n fileNameEl.setAttribute(\"title\", name);\n }\n\n fileEl.setAttribute(FILE_ID_ATTR, id);\n\n if (prependInfo) {\n prependFile(fileEl, prependInfo.index, fileContainer);\n }\n else {\n fileContainer.appendChild(fileEl);\n }\n\n if (hideForever) {\n fileEl.style.display = \"none\";\n qq(fileEl).addClass(HIDDEN_FOREVER_CLASS);\n }\n else {\n hide(getProgress(id));\n hide(getSize(id));\n hide(getDelete(id));\n hide(getRetry(id));\n hide(getPause(id));\n hide(getContinue(id));\n\n if (isCancelDisabled) {\n this.hideCancel(id);\n }\n\n thumb = getThumbnail(id);\n if (thumb && !thumb.src) {\n cachedWaitingForThumbnailImg.then(function(waitingImg) {\n thumb.src = waitingImg.src;\n if (waitingImg.style.maxHeight && waitingImg.style.maxWidth) {\n qq(thumb).css({\n maxHeight: waitingImg.style.maxHeight,\n maxWidth: waitingImg.style.maxWidth\n });\n }\n\n show(thumb);\n });\n }\n }\n },\n\n addFileToCache: function(id, name, prependInfo, hideForever) {\n this.addFile(id, name, prependInfo, hideForever, true);\n },\n\n addCacheToDom: function() {\n fileList.appendChild(fileBatch.content);\n fileBatch.content = document.createDocumentFragment();\n fileBatch.map = {};\n },\n\n removeFile: function(id) {\n qq(getFile(id)).remove();\n },\n\n getFileId: function(el) {\n var currentNode = el;\n\n if (currentNode) {\n /*jshint -W116*/\n while (currentNode.getAttribute(FILE_ID_ATTR) == null) {\n currentNode = currentNode.parentNode;\n }\n\n return parseInt(currentNode.getAttribute(FILE_ID_ATTR));\n }\n },\n\n getFileList: function() {\n return fileList;\n },\n\n markFilenameEditable: function(id) {\n var filename = getFilename(id);\n\n filename && qq(filename).addClass(options.classes.editable);\n },\n\n updateFilename: function(id, name) {\n var filenameEl = getFilename(id);\n\n if (filenameEl) {\n qq(filenameEl).setText(name);\n filenameEl.setAttribute(\"title\", name);\n }\n },\n\n hideFilename: function(id) {\n hide(getFilename(id));\n },\n\n showFilename: function(id) {\n show(getFilename(id));\n },\n\n isFileName: function(el) {\n return qq(el).hasClass(selectorClasses.file);\n },\n\n getButton: function() {\n return options.button || getTemplateEl(container, selectorClasses.button);\n },\n\n hideDropProcessing: function() {\n hide(getDropProcessing());\n },\n\n showDropProcessing: function() {\n show(getDropProcessing());\n },\n\n getDropZone: function() {\n return getTemplateEl(container, selectorClasses.drop);\n },\n\n isEditFilenamePossible: function() {\n return isEditElementsExist;\n },\n\n hideRetry: function(id) {\n hide(getRetry(id));\n },\n\n isRetryPossible: function() {\n return isRetryElementExist;\n },\n\n showRetry: function(id) {\n show(getRetry(id));\n },\n\n getFileContainer: function(id) {\n return getFile(id);\n },\n\n showEditIcon: function(id) {\n var icon = getEditIcon(id);\n\n icon && qq(icon).addClass(options.classes.editable);\n },\n\n isHiddenForever: function(id) {\n return qq(getFile(id)).hasClass(HIDDEN_FOREVER_CLASS);\n },\n\n hideEditIcon: function(id) {\n var icon = getEditIcon(id);\n\n icon && qq(icon).removeClass(options.classes.editable);\n },\n\n isEditIcon: function(el) {\n return qq(el).hasClass(selectorClasses.editNameIcon, true);\n },\n\n getEditInput: function(id) {\n return getTemplateEl(getFile(id), selectorClasses.editFilenameInput);\n },\n\n isEditInput: function(el) {\n return qq(el).hasClass(selectorClasses.editFilenameInput, true);\n },\n\n updateProgress: function(id, loaded, total) {\n var bar = getProgress(id),\n percent;\n\n if (bar && total > 0) {\n percent = Math.round(loaded / total * 100);\n\n if (percent === 100) {\n hide(bar);\n }\n else {\n show(bar);\n }\n\n setProgressBarWidth(id, percent);\n }\n },\n\n updateTotalProgress: function(loaded, total) {\n this.updateProgress(null, loaded, total);\n },\n\n hideProgress: function(id) {\n var bar = getProgress(id);\n\n bar && hide(bar);\n },\n\n hideTotalProgress: function() {\n this.hideProgress();\n },\n\n resetProgress: function(id) {\n setProgressBarWidth(id, 0);\n this.hideTotalProgress(id);\n },\n\n resetTotalProgress: function() {\n this.resetProgress();\n },\n\n showCancel: function(id) {\n if (!isCancelDisabled) {\n var cancel = getCancel(id);\n\n cancel && qq(cancel).removeClass(options.classes.hide);\n }\n },\n\n hideCancel: function(id) {\n hide(getCancel(id));\n },\n\n isCancel: function(el) {\n return qq(el).hasClass(selectorClasses.cancel, true);\n },\n\n allowPause: function(id) {\n show(getPause(id));\n hide(getContinue(id));\n },\n\n uploadPaused: function(id) {\n this.setStatusText(id, options.text.paused);\n this.allowContinueButton(id);\n hide(getSpinner(id));\n },\n\n hidePause: function(id) {\n hide(getPause(id));\n },\n\n isPause: function(el) {\n return qq(el).hasClass(selectorClasses.pause, true);\n },\n\n isContinueButton: function(el) {\n return qq(el).hasClass(selectorClasses.continueButton, true);\n },\n\n allowContinueButton: function(id) {\n show(getContinue(id));\n hide(getPause(id));\n },\n\n uploadContinued: function(id) {\n this.setStatusText(id, \"\");\n this.allowPause(id);\n show(getSpinner(id));\n },\n\n showDeleteButton: function(id) {\n show(getDelete(id));\n },\n\n hideDeleteButton: function(id) {\n hide(getDelete(id));\n },\n\n isDeleteButton: function(el) {\n return qq(el).hasClass(selectorClasses.deleteButton, true);\n },\n\n isRetry: function(el) {\n return qq(el).hasClass(selectorClasses.retry, true);\n },\n\n updateSize: function(id, text) {\n var size = getSize(id);\n\n if (size) {\n show(size);\n qq(size).setText(text);\n }\n },\n\n setStatusText: function(id, text) {\n var textEl = getTemplateEl(getFile(id), selectorClasses.statusText);\n\n if (textEl) {\n /*jshint -W116*/\n if (text == null) {\n qq(textEl).clearText();\n }\n else {\n qq(textEl).setText(text);\n }\n }\n },\n\n hideSpinner: function(id) {\n qq(getFile(id)).removeClass(IN_PROGRESS_CLASS);\n hide(getSpinner(id));\n },\n\n showSpinner: function(id) {\n qq(getFile(id)).addClass(IN_PROGRESS_CLASS);\n show(getSpinner(id));\n },\n\n generatePreview: function(id, optFileOrBlob, customResizeFunction) {\n if (!this.isHiddenForever(id)) {\n thumbGenerationQueue.push({id: id, customResizeFunction: customResizeFunction, optFileOrBlob: optFileOrBlob});\n !thumbnailQueueMonitorRunning && generateNextQueuedPreview();\n }\n },\n\n updateThumbnail: function(id, thumbnailUrl, showWaitingImg, customResizeFunction) {\n if (!this.isHiddenForever(id)) {\n thumbGenerationQueue.push({customResizeFunction: customResizeFunction, update: true, id: id, thumbnailUrl: thumbnailUrl, showWaitingImg: showWaitingImg});\n !thumbnailQueueMonitorRunning && generateNextQueuedPreview();\n }\n },\n\n hasDialog: function(type) {\n return qq.supportedFeatures.dialogElement && !!getDialog(type);\n },\n\n showDialog: function(type, message, defaultValue) {\n var dialog = getDialog(type),\n messageEl = getTemplateEl(dialog, selectorClasses.dialogMessage),\n inputEl = dialog.getElementsByTagName(\"INPUT\")[0],\n cancelBtn = getTemplateEl(dialog, selectorClasses.dialogCancelButton),\n okBtn = getTemplateEl(dialog, selectorClasses.dialogOkButton),\n promise = new qq.Promise(),\n\n closeHandler = function() {\n cancelBtn.removeEventListener(\"click\", cancelClickHandler);\n okBtn && okBtn.removeEventListener(\"click\", okClickHandler);\n promise.failure();\n },\n\n cancelClickHandler = function() {\n cancelBtn.removeEventListener(\"click\", cancelClickHandler);\n dialog.close();\n },\n\n okClickHandler = function() {\n dialog.removeEventListener(\"close\", closeHandler);\n okBtn.removeEventListener(\"click\", okClickHandler);\n dialog.close();\n\n promise.success(inputEl && inputEl.value);\n };\n\n dialog.addEventListener(\"close\", closeHandler);\n cancelBtn.addEventListener(\"click\", cancelClickHandler);\n okBtn && okBtn.addEventListener(\"click\", okClickHandler);\n\n if (inputEl) {\n inputEl.value = defaultValue;\n }\n messageEl.textContent = message;\n\n dialog.showModal();\n\n return promise;\n }\n });\n};\n","/*globals qq */\n// Base handler for UI (FineUploader mode) events.\n// Some more specific handlers inherit from this one.\nqq.UiEventHandler = function(s, protectedApi) {\n \"use strict\";\n\n var disposer = new qq.DisposeSupport(),\n spec = {\n eventType: \"click\",\n attachTo: null,\n onHandled: function(target, event) {}\n };\n\n // This makes up the \"public\" API methods that will be accessible\n // to instances constructing a base or child handler\n qq.extend(this, {\n addHandler: function(element) {\n addHandler(element);\n },\n\n dispose: function() {\n disposer.dispose();\n }\n });\n\n function addHandler(element) {\n disposer.attach(element, spec.eventType, function(event) {\n // Only in IE: the `event` is a property of the `window`.\n event = event || window.event;\n\n // On older browsers, we must check the `srcElement` instead of the `target`.\n var target = event.target || event.srcElement;\n\n spec.onHandled(target, event);\n });\n }\n\n // These make up the \"protected\" API methods that children of this base handler will utilize.\n qq.extend(protectedApi, {\n getFileIdFromItem: function(item) {\n return item.qqFileId;\n },\n\n getDisposeSupport: function() {\n return disposer;\n }\n });\n\n qq.extend(spec, s);\n\n if (spec.attachTo) {\n addHandler(spec.attachTo);\n }\n};\n","/* global qq */\nqq.FileButtonsClickHandler = function(s) {\n \"use strict\";\n\n var inheritedInternalApi = {},\n spec = {\n templating: null,\n log: function(message, lvl) {},\n onDeleteFile: function(fileId) {},\n onCancel: function(fileId) {},\n onRetry: function(fileId) {},\n onPause: function(fileId) {},\n onContinue: function(fileId) {},\n onGetName: function(fileId) {}\n },\n buttonHandlers = {\n cancel: function(id) { spec.onCancel(id); },\n retry: function(id) { spec.onRetry(id); },\n deleteButton: function(id) { spec.onDeleteFile(id); },\n pause: function(id) { spec.onPause(id); },\n continueButton: function(id) { spec.onContinue(id); }\n };\n\n function examineEvent(target, event) {\n qq.each(buttonHandlers, function(buttonType, handler) {\n var firstLetterCapButtonType = buttonType.charAt(0).toUpperCase() + buttonType.slice(1),\n fileId;\n\n if (spec.templating[\"is\" + firstLetterCapButtonType](target)) {\n fileId = spec.templating.getFileId(target);\n qq.preventDefault(event);\n spec.log(qq.format(\"Detected valid file button click event on file '{}', ID: {}.\", spec.onGetName(fileId), fileId));\n handler(fileId);\n return false;\n }\n });\n }\n\n qq.extend(spec, s);\n\n spec.eventType = \"click\";\n spec.onHandled = examineEvent;\n spec.attachTo = spec.templating.getFileList();\n\n qq.extend(this, new qq.UiEventHandler(spec, inheritedInternalApi));\n};\n","/*globals qq */\n// Child of FilenameEditHandler. Used to detect click events on filename display elements.\nqq.FilenameClickHandler = function(s) {\n \"use strict\";\n\n var inheritedInternalApi = {},\n spec = {\n templating: null,\n log: function(message, lvl) {},\n classes: {\n file: \"qq-upload-file\",\n editNameIcon: \"qq-edit-filename-icon\"\n },\n onGetUploadStatus: function(fileId) {},\n onGetName: function(fileId) {}\n };\n\n qq.extend(spec, s);\n\n // This will be called by the parent handler when a `click` event is received on the list element.\n function examineEvent(target, event) {\n if (spec.templating.isFileName(target) || spec.templating.isEditIcon(target)) {\n var fileId = spec.templating.getFileId(target),\n status = spec.onGetUploadStatus(fileId);\n\n // We only allow users to change filenames of files that have been submitted but not yet uploaded.\n if (status === qq.status.SUBMITTED) {\n spec.log(qq.format(\"Detected valid filename click event on file '{}', ID: {}.\", spec.onGetName(fileId), fileId));\n qq.preventDefault(event);\n\n inheritedInternalApi.handleFilenameEdit(fileId, target, true);\n }\n }\n }\n\n spec.eventType = \"click\";\n spec.onHandled = examineEvent;\n\n qq.extend(this, new qq.FilenameEditHandler(spec, inheritedInternalApi));\n};\n","/*globals qq */\n// Child of FilenameEditHandler. Used to detect focusin events on file edit input elements.\nqq.FilenameInputFocusInHandler = function(s, inheritedInternalApi) {\n \"use strict\";\n\n var spec = {\n templating: null,\n onGetUploadStatus: function(fileId) {},\n log: function(message, lvl) {}\n };\n\n if (!inheritedInternalApi) {\n inheritedInternalApi = {};\n }\n\n // This will be called by the parent handler when a `focusin` event is received on the list element.\n function handleInputFocus(target, event) {\n if (spec.templating.isEditInput(target)) {\n var fileId = spec.templating.getFileId(target),\n status = spec.onGetUploadStatus(fileId);\n\n if (status === qq.status.SUBMITTED) {\n spec.log(qq.format(\"Detected valid filename input focus event on file '{}', ID: {}.\", spec.onGetName(fileId), fileId));\n inheritedInternalApi.handleFilenameEdit(fileId, target);\n }\n }\n }\n\n spec.eventType = \"focusin\";\n spec.onHandled = handleInputFocus;\n\n qq.extend(spec, s);\n qq.extend(this, new qq.FilenameEditHandler(spec, inheritedInternalApi));\n};\n","/*globals qq */\n/**\n * Child of FilenameInputFocusInHandler. Used to detect focus events on file edit input elements. This child module is only\n * needed for UAs that do not support the focusin event. Currently, only Firefox lacks this event.\n *\n * @param spec Overrides for default specifications\n */\nqq.FilenameInputFocusHandler = function(spec) {\n \"use strict\";\n\n spec.eventType = \"focus\";\n spec.attachTo = null;\n\n qq.extend(this, new qq.FilenameInputFocusInHandler(spec, {}));\n};\n","/*globals qq */\n// Handles edit-related events on a file item (FineUploader mode). This is meant to be a parent handler.\n// Children will delegate to this handler when specific edit-related actions are detected.\nqq.FilenameEditHandler = function(s, inheritedInternalApi) {\n \"use strict\";\n\n var spec = {\n templating: null,\n log: function(message, lvl) {},\n onGetUploadStatus: function(fileId) {},\n onGetName: function(fileId) {},\n onSetName: function(fileId, newName) {},\n onEditingStatusChange: function(fileId, isEditing) {}\n };\n\n function getFilenameSansExtension(fileId) {\n var filenameSansExt = spec.onGetName(fileId),\n extIdx = filenameSansExt.lastIndexOf(\".\");\n\n if (extIdx > 0) {\n filenameSansExt = filenameSansExt.substr(0, extIdx);\n }\n\n return filenameSansExt;\n }\n\n function getOriginalExtension(fileId) {\n var origName = spec.onGetName(fileId);\n return qq.getExtension(origName);\n }\n\n // Callback iff the name has been changed\n function handleNameUpdate(newFilenameInputEl, fileId) {\n var newName = newFilenameInputEl.value,\n origExtension;\n\n if (newName !== undefined && qq.trimStr(newName).length > 0) {\n origExtension = getOriginalExtension(fileId);\n\n if (origExtension !== undefined) {\n newName = newName + \".\" + origExtension;\n }\n\n spec.onSetName(fileId, newName);\n }\n\n spec.onEditingStatusChange(fileId, false);\n }\n\n // The name has been updated if the filename edit input loses focus.\n function registerInputBlurHandler(inputEl, fileId) {\n inheritedInternalApi.getDisposeSupport().attach(inputEl, \"blur\", function() {\n handleNameUpdate(inputEl, fileId);\n });\n }\n\n // The name has been updated if the user presses enter.\n function registerInputEnterKeyHandler(inputEl, fileId) {\n inheritedInternalApi.getDisposeSupport().attach(inputEl, \"keyup\", function(event) {\n\n var code = event.keyCode || event.which;\n\n if (code === 13) {\n handleNameUpdate(inputEl, fileId);\n }\n });\n }\n\n qq.extend(spec, s);\n\n spec.attachTo = spec.templating.getFileList();\n\n qq.extend(this, new qq.UiEventHandler(spec, inheritedInternalApi));\n\n qq.extend(inheritedInternalApi, {\n handleFilenameEdit: function(id, target, focusInput) {\n var newFilenameInputEl = spec.templating.getEditInput(id);\n\n spec.onEditingStatusChange(id, true);\n\n newFilenameInputEl.value = getFilenameSansExtension(id);\n\n if (focusInput) {\n newFilenameInputEl.focus();\n }\n\n registerInputBlurHandler(newFilenameInputEl, id);\n registerInputEnterKeyHandler(newFilenameInputEl, id);\n }\n });\n};\n"]}
\ No newline at end of file
+{"version":3,"sources":["?","../client/js/util.js","../client/js/export.js","../client/js/error/error.js","../client/js/version.js","../client/js/features.js","../client/js/promise.js","../client/js/blob-proxy.js","../client/js/button.js","../client/js/upload-data.js","../client/js/uploader.basic.api.js","../client/js/uploader.basic.js","../client/js/ajax.requester.js","../client/js/upload-handler/upload.handler.js","../client/js/upload-handler/upload.handler.controller.js","../client/js/window.receive.message.js","../client/js/upload-handler/form.upload.handler.js","../client/js/upload-handler/xhr.upload.handler.js","../client/js/deletefile.ajax.requester.js","../client/js/image-support/megapix-image.js","../client/js/image-support/image.js","../client/js/image-support/exif.js","../client/js/identify.js","../client/js/image-support/validation.image.js","../client/js/session.js","../client/js/session.ajax.requester.js","../client/js/image-support/scaler.js","../client/js/third-party/ExifRestorer.js","../client/js/total-progress.js","../client/js/paste.js","../client/js/form-support.js","../client/js/traditional/traditional.form.upload.handler.js","../client/js/traditional/traditional.xhr.upload.handler.js","../client/js/traditional/all-chunks-done.ajax.requester.js","../client/js/dnd.js","../client/js/uploader.api.js","../client/js/uploader.js","../client/js/templating.js","../client/js/ui.handler.events.js","../client/js/ui.handler.click.filebuttons.js","../client/js/ui.handler.click.filename.js","../client/js/ui.handler.focusin.filenameinput.js","../client/js/ui.handler.focus.filenameinput.js","../client/js/ui.handler.edit.filename.js"],"names":["global","qq","element","hide","style","display","this","attach","type","fn","addEventListener","attachEvent","detach","removeEventListener","detachEvent","contains","descendant","compareDocumentPosition","insertBefore","elementB","parentNode","remove","removeChild","css","styles","Error","opacity","filter","Math","round","extend","hasClass","name","considerParent","re","RegExp","test","className","addClass","removeClass","replace","getByClass","first","candidates","result","querySelector","querySelectorAll","getElementsByTagName","each","idx","val","push","getFirstByClass","children","child","firstChild","nodeType","nextSibling","setText","text","innerText","textContent","clearText","hasAttribute","attrName","attrVal","exec","getAttribute","undefined","canvasToBlob","canvas","mime","quality","dataUriToBlob","toDataURL","dataUri","arrayBuffer","byteString","createBlob","data","BlobBuilder","window","WebKitBlobBuilder","MozBlobBuilder","MSBlobBuilder","blobBuilder","append","getBlob","Blob","intArray","mimeString","split","indexOf","atob","decodeURI","ArrayBuffer","length","Uint8Array","character","charCodeAt","log","message","level","console","isObject","variable","Object","prototype","toString","call","isFunction","isArray","value","buffer","constructor","isItemList","maybeItemList","isNodeList","maybeNodeList","item","namedItem","isString","maybeString","trimStr","string","String","trim","format","str","args","Array","slice","arguments","newStr","nextIdxToReplace","strBefore","substring","strAfter","isFile","maybeFile","File","isFileList","maybeFileList","FileList","isFileOrInput","maybeFileOrInput","isInput","maybeInput","notFile","evaluateType","normalizedType","toLowerCase","HTMLInputElement","tagName","isBlob","maybeBlob","isXhrUploadSupported","input","document","createElement","multiple","FormData","createXhrInstance","upload","XMLHttpRequest","ActiveXObject","error","isFolderDropSupported","dataTransfer","items","webkitGetAsEntry","isFileChunkingSupported","androidStock","webkitSlice","mozSlice","sliceBlob","fileOrBlob","start","end","slicer","arrayBufferToHex","bytesAsHex","bytes","byt","byteAsHexStr","readBlobToHex","blob","startOffset","initialBlob","fileReader","FileReader","promise","Promise","onload","success","onerror","failure","readAsArrayBuffer","second","extendNested","prop","override","target","sourceFn","super_","source","srcPropName","srcPropVal","arr","elt","from","len","hasOwnProperty","getUniqueId","c","r","random","v","ie","navigator","userAgent","ie7","ie8","ie10","ie11","edge","safari","vendor","chrome","opera","firefox","windows","platform","android","ios6","ios","ios7","ios8","ios800","iosChrome","iosSafari","iosSafariWebView","preventDefault","e","returnValue","toElement","div","html","innerHTML","iterableItem","callback","keyOrIndex","retVal","Storage","key","getItem","charAt","bind","oldFunc","context","newArgs","concat","apply","obj2url","obj","temp","prefixDone","uristrings","prefix","add","nextObj","i","nextTemp","encodeURIComponent","join","obj2FormData","formData","arrayKeyName","obj2Inputs","form","setAttribute","appendChild","parseJson","json","JSON","parse","eval","getExtension","filename","extIdx","lastIndexOf","substr","getFilename","blobOrFileInput","fileName","DisposeSupport","disposers","dispose","disposer","shift","addDisposer","disposeFunction","define","amd","module","exports","version","supportedFeatures","supportsUploading","supportsUploadingBlobs","supportsFileDrop","supportsAjaxFileUploading","supportsFolderDrop","supportsChunking","supportsResume","supportsUploadViaPaste","supportsUploadCors","supportsDeleteFileXdr","supportsDeleteFileCorsXhr","supportsDeleteFileCors","supportsFolderSelection","supportsImagePreviews","supportsUploadProgress","testSupportsFileInputElement","supported","tempInput","disabled","ex","isChrome14OrHigher","match","isCrossOriginXhrSupported","xhr","withCredentials","isXdrSupported","XDomainRequest","isCrossOriginAjaxSupported","isFolderSelectionSupported","webkitdirectory","isLocalStorageSupported","localStorage","setItem","isDragAndDropSupported","span","postMessage","ajaxUploading","blobUploading","canDetermineSize","chunking","deleteFileCors","deleteFileCorsXdr","deleteFileCorsXhr","dialogElement","HTMLDialogElement","fileDrop","folderDrop","folderSelection","imagePreviews","imageValidation","itemSizeValidation","pause","progressBar","resume","scaling","tiffPreviews","unlimitedScaledImageSize","uploading","uploadCors","uploadCustomHeaders","uploadNonMultipart","uploadViaPaste","isGenericPromise","maybePromise","then","successArgs","failureArgs","successCallbacks","failureCallbacks","doneCallbacks","state","onSuccess","onFailure","done","BlobProxy","referenceBlob","onCreate","create","UploadButton","o","self","disposeSupport","options","acceptFiles","focusClass","folders","hoverClass","ios8BrowserCrashWorkaround","onChange","title","buttonId","createInput","BUTTON_ID_ATTR_NAME","setMultiple","position","right","top","fontFamily","fontSize","margin","padding","cursor","height","overflow","direction","getInput","getButtonId","isMultiple","optInput","removeAttribute","setAcceptFiles","reset","UploadData","uploaderProxy","byUuid","byStatus","byProxyGroupId","byBatchId","getDataByIds","idOrIds","entries","id","getDataByUuids","uuids","uuid","getDataByStatus","status","statusResults","statuses","index","statusEnum","statusResultIndexes","dataIndex","addFile","spec","SUBMITTING","originalName","size","file","batchId","proxyGroupId","onBeforeStatusChange","onStatusChange","retrieve","optionalFilter","removeFileRef","record","setStatus","newStatus","oldStatus","byStatusOldStatusIndex","splice","uuidChanged","newUuid","oldUuid","updateName","newName","updateSize","newSize","setParentId","targetId","parentId","getIdsInProxyGroup","getIdsInBatch","SUBMITTED","REJECTED","QUEUED","CANCELED","PAUSED","UPLOADING","UPLOAD_FINALIZING","UPLOAD_RETRYING","UPLOAD_SUCCESSFUL","UPLOAD_FAILED","DELETE_FAILED","DELETING","DELETED","basePublicApi","addBlobs","blobDataOrArray","params","endpoint","addFiles","addInitialFiles","cannedFileList","cannedFile","_addCannedFile","_maybeHandleIos8SafariWorkaround","_storedIds","_currentBatchId","processBlob","_handleNewFile","_options","blobs","defaultName","verifiedFiles","processBlobData","blobData","processCanvas","processCanvasData","canvasData","normalizedQuality","processFileOrInput","fileOrInput","files","normalizeData","fileContainer","_prepareItemsForUpload","cancel","uploadData","_uploadData","getName","_handler","cancelAll","storedIdsCopy","storedFileId","clearStoredFiles","continueUpload","enabled","_uploadFile","deleteFile","_onSubmitDelete","doesExist","fileOrBlobId","isValid","drawThumbnail","fileId","imgOrCanvas","maxSize","fromServer","customResizeFunction","promiseToReturn","fileOrUrl","_imageGenerator","_thumbnailUrls","scale","getFile","container","generate","modifiedContainer","reason","getButton","_getButton","_buttonIdsForFileIds","getEndpoint","_endpointStore","get","uploadDataRecord","getInProgress","getParentId","uploadDataEntry","getUploads","getResumableFilesData","getSize","getNetUploads","_netUploaded","getRemainingAllowedItems","allowedItems","_currentItemLimit","_netUploadedOrQueued","getUuid","isResumable","hasResumeRecord","debug","pauseUpload","expunge","_autoRetries","_retryTimeouts","_preventRetries","_buttons","button","_paramsStore","_pasteHandler","session","refreshOnReset","_refreshSessionData","_succeededSinceLastAllComplete","_failedSinceLastAllComplete","_totalProgress","_customResumeDataStore","retry","_manualRetry","scaleImage","specs","Scaler","setCustomHeaders","headers","_customHeadersStore","set","setCustomResumeData","setDeleteFileCustomHeaders","_deleteFileCustomHeadersStore","setDeleteFileEndpoint","_deleteFileEndpointStore","setDeleteFileParams","_deleteFileParamsStore","setEndpoint","setForm","elementOrId","_updateFormSupportAndParams","setItemLimit","newItemLimit","setName","setParams","setUuid","fileRecord","_onDeleteComplete","errorMessage","uploadStoredFiles","_itemError","_uploadStoredFiles","basePrivateApi","sessionData","deleteFileEndpoint","deleteFileParams","thumbnailUrl","_annotateWithButtonId","associatedInput","qqButtonId","_getButtonId","_batchError","callbacks","onError","_createDeleteHandler","DeleteFileAjaxRequester","method","toUpperCase","maxConnections","uuidParamName","request","uuidName","customHeaders","paramsStore","endpointStore","cors","onDelete","_onDelete","onDeleteComplete","xhrOrXdr","isError","_createPasteHandler","PasteSupport","targetElement","paste","pasteReceived","_handleCheckedCallback","onPasteReceived","_handlePasteSuccess","identifier","_createStore","initialValue","_readOnlyValues_","store","catchall","perIdReadOnlyValues","readOnlyValues","copy","orig","getReadOnlyValues","includeReadOnlyValues","existing","values","addReadOnly","_createUploadDataTracker","_onUploadStatusChange","_maybeAllComplete","setTimeout","_createUploadButton","accept","validation","allowedExtensions","allowMultiple","workarounds","iosEmptyVideos","_isAllowedExtension","classes","buttonFocus","buttonHover","ios8BrowserCrash","inputName","_onInputChange","fileInputTitle","_disposeSupport","_createUploadHandler","additionalOptions","namespace","lastOnProgress","preventRetryParam","preventRetryResponseProperty","onProgress","loaded","total","_onProgress","onComplete","_onComplete","onCancel","cancelFinalizationEffort","_onCancel","onUploadPrep","_onUploadPrep","onUpload","_onUpload","onUploadResult","onUploadChunk","chunkData","_onUploadChunk","onUploadChunkResult","partIndex","onUploadChunkSuccess","_onUploadChunkSuccess","onResume","customResumeData","onAutoRetry","responseJSON","_onAutoRetry","onUuidChanged","setSize","_setSize","getDataByUuid","isQueued","isInProgress","getCustomResumeData","_getCustomResumeData","UploadHandlerController","_fileOrBlobRejected","_formatSize","sizeSymbols","max","toFixed","_generateExtraButtonSpecs","_extraButtonSpecs","extraButtons","extraButtonOptionEntry","extraButtonSpec","_initExtraButton","extraButtonsSpec","_defaultButtonId","buttonOrFileInputOrFile","inputs","fileInput","fileBlobOrInput","_getNotFinished","_getValidationBase","_getValidationDescriptor","fileWrapper","_getValidationDescriptors","fileWrappers","fileDescriptors","_handleCameraAccess","camera","acceptIosCamera","optionRoot","details","callbackRetVal","successParam","newFileWrapperList","actualFile","handler","_customNewFileHandler","_handleNewFileGeneric","addFileToHandler","_trackButton","fileList","extSuppliedName","extension","_handleDeleteSuccess","_handleDeleteFailed","_initFormSupportAndParams","_formSupport","FormSupport","attachedToForm","getFormInputsAsObject","autoUpload","newAutoUpload","newEndpoint","_isDeletePossible","expected","allowXdr","allowed","valid","allowedExt","extRegex","code","maybeNameOrNames","messages","names","validationBase","extensionsForMessage","placeholderMatch","replacement","allowedExtension","formatFileName","sizeLimit","minSizeLimit","placeholder","_onBeforeManualRetry","notFinished","_onAllComplete","ios8SafariUploads","alert","unsupportedBrowserIos8Safari","_maybeParseAndSendUploadError","response","errorReason","defaultResponseError","_maybeProcessNextItemAfterOnValidateCallback","validItem","stopOnFirstInvalidFile","validationDescriptor","onValidate","_onValidateCallbackSuccess","_onValidateCallbackFailure","successful","failed","onAllComplete","_shouldAutoRetry","retryWaitPeriod","autoAttemptDelay","_onBeforeAutoRetry","itemLimit","onManualRetry","clearTimeout","storedItemIndex","fileIndex","onIndividualProgress","_onSubmit","_onSubmitCallbackSuccess","_onSubmitted","onSubmitted","_storeForLater","onSuccessCallback","additionalMandatedParams","adjustedOnSuccessCallback","onSubmitDelete","_deleteHandler","sendDelete","_onTotalProgress","onTotalProgress","enableAuto","_onValidateBatchCallbackFailure","_onValidateBatchCallbackSuccess","validationDescriptors","proposedNetFilesUploadedOrQueued","tooManyItemsError","nextIndex","_validateFileOrBlobData","_upload","onValidateBatch","_preventLeaveInProgress","event","onLeave","Session","_session","addFileRecord","refresh","_sessionRequestComplete","onSessionRequestComplete","onNewSize","maxAutoAttempts","formElementOrId","onSubmit","idToUpload","stillSubmitting","validityChecker","allowEmpty","ImageValidation","validate","image","errorCode","_wrapCallbacks","safeCallback","errorMsg","exception","callbackName","callbackFunc","FineUploaderBasic","disableCancelForFormUploads","warnBeforeUnload","filenameParam","forceMultipart","omitDefaultParams","paramsInBody","requireSuccessJson","totalFileSizeName","maxHeight","maxWidth","minHeight","minWidth","maybeXhr","maybeXhrOrXdr","attemptNumber","fileOrBlobData","typeError","sizeError","minSizeError","emptyError","noFilesError","maxHeightImageError","maxWidthImageError","minHeightImageError","minWidthImageError","retryFailTooManyItems","concurrent","mandatory","paramNames","partByteOffset","chunkSize","totalFileSize","totalParts","partSize","jsonPayload","resetOnStatus","recordsExpireIn","resuming","customKeys","fileOrBlobName","sendCredentials","interceptSubmit","customResizer","sendOriginal","orient","defaultType","defaultQuality","failureText","includeExif","sizes","ImageGenerator","_scaler","handleNewFile","TotalProgress","entry","AjaxRequester","shouldParamsBeInQueryString","queue","requestData","acceptHeader","validMethods","contentType","mandatedParams","allowXRequestedWithAndCacheControl","successfulResponseCodes","DELETE","PATCH","POST","PUT","GET","onSend","isSimpleMethod","containsNonSimpleHeaders","containsNonSimple","header","isXdr","getCorsAjaxTransport","ontimeout","onprogress","getXhrOrXdr","suppliedXhr","dequeue","nextId","sendRequest","xdrError","isResponseSuccessful","getParams","onDemandParams","additionalParams","optXhr","payload","url","createUrl","additionalQueryParams","getXdrLoadHandler","getXdrErrorHandler","onreadystatechange","getXhrReadyStateChangeHandler","registerForUploadProgress","open","setHeaders","send","stringify","addToPath","readyState","lengthComputable","onDemandHeaders","additionalHeaders","allHeaders","setRequestHeader","responseCode","prepareToSend","initTransport","path","cacheBuster","withPath","appendToPath","withParams","withQueryParams","_additionalQueryParams_","withHeaders","withPayload","thePayload","withCacheBuster","qqtimestamp","Date","getTime","canceled","UploadHandler","proxy","fileState","fileItem","onCancelRetVal","getThirdPartyFileId","_getFileState","_setThirdPartyFileId","thirdPartyFileId","_wasCanceled","controller","chunkingPossible","concurrentChunkingPossible","preventRetryResponse","chunked","chunkIdx","_getChunkData","attemptingResume","chunkProgress","_getChunkDataForCallback","finalize","finalizeChunks","normaizedResponse","normalizeResponse","_maybeDeletePersistedChunkData","cleanup","normalizedResponse","handleFailure","clearCachedChunk","responseToReport","inProgressIdx","inProgressChunksArray","inProgress","remaining","unshift","ignoreFailure","keys","_getXhrs","ckid","ckXhr","abort","_cancelled","moveInProgressToRemaining","connectionManager","free","hasMoreParts","nextPart","nextIdx","_getTotalChunks","reevaluateChunking","sendNext","inProgressChunks","available","onUploadChunkPromise","requestOverrides","uploadChunkData","overrides","uploadChunk","inProgressChunkIdx","_maybePersistChunkedState","clearXhr","_open","_openChunks","_waiting","openChunkEntriesCount","openChunksCount","openChunkIndexes","dontAllowNext","allowNext","waitingIndex","connectionsIndex","getProxyOrBlob","getWaitingOrConnected","waitingOrConnected","chunks","parseInt","isUsingConnection","pop","openChunksEntry","simple","uploadFile","maybeNewUuid","_clearXhrs","getProxy","initHandler","handlerType","traditional","handlerModuleSubtype","onFinalizing","_removeExpiredChunkingRecords","isDeferredEligibleForUpload","maybeDefer","generatedBlob","updateBlob","maybeSendDeferredFiles","errorResponse","idsInGroup","uploadedThisId","idInGroup","now","originalResponse","_shouldChunkThisFile","blobToUpload","cancelRetVal","isProxied","_getLocalStorageId","isAttemptingResume","WindowReceiveMessage","callbackWrapperDetachers","receiveMessage","onMessageCallbackWrapper","stopReceivingMessages","detacher","FormUploadHandler","formHandlerInstanceId","onloadCallbacks","detachLoadEvents","postMessageCallbackTimers","isCors","corsMessageReceiver","expungeFile","iframe","getElementById","_getIframeName","getFileIdForIframeName","iframeName","initIframeForUpload","body","registerPostMessageCallback","_parseJsonResponse","onloadCallback","_detachLoadEvent","_attachLoadEvent","responseDescriptor","contentDocument","_createIframe","_initFormForUpload","targetName","innerHtmlOrMessage","XhrUploadHandler","getChunkSize","chunkFiles","resumeEnabled","xhrId","ajaxRequester","_getAjaxRequester","blobOrProxy","_initTempState","_maybePrepareForResume","cachedChunks","tempState","xhrs","ajaxRequesters","responseParser","lastChunkIdx","_getXhr","resumableFilesData","_iterateResumeRecords","notResumable","optInProgress","optRemaining","chunkingState","reverse","paused","totalChunks","parts","newBlob","chunkId","_createXhr","optChunkIdx","_registerXhr","chunkIndex","fileSize","startBytes","endBytes","part","count","startByte","endByte","formatVersion","localStorageId","forEach","_getMimeType","_getPersistableData","ceil","_markNotResumable","removeItem","persistedData","lastUpdated","_registerProgressHandler","progressCalculator","totalSuccessfullyLoadedForFile","loadedForRequest","totalForRequest","estActualChunkLoaded","totalLoadedForFile","chunkLoaded","optAjaxRequester","xhrsId","expirationDays","expirationDate","setDate","getDate","requester","getMandatedParams","_method","detectSubsampling","img","iw","naturalWidth","ih","naturalHeight","ctx","width","getContext","drawImage","getImageData","detectVerticalSquash","sy","ey","py","alpha","ratio","renderImageToDataURL","doSquash","renderImageToCanvas","maybeCalculateDownsampledDimensions","maxPixels","origHeight","origWidth","newHeight","sqrt","newWidth","modifiedDimensions","save","resize","renderImageToCanvasWithCustomResizer","imageHeight","imageWidth","orientation","targetHeight","targetWidth","transformCoordinate","d","tmpCanvas","vertSquashRatio","dw","dh","dy","tmpCtx","sx","dx","clearRect","restore","qqImageRendered","resizeInfo","sourceCanvas","sourceCanvasContext","targetCanvas","translate","rotate","PI","MegaPixImage","srcImage","errorCallback","Image","URL","createObjectURL","webkitURL","src","listeners","imageLoadListeners","render","imgWidth","imgHeight","opt","optionsKey","optionsValue","oldTargetSrc","onrender","isImg","el","isCanvas","isImgCorsSupported","crossOrigin","isCanvasSupported","determineMimeOfFileName","nameWithPath","pathSegments","isCrossOrigin","targetAnchor","targetProtocol","targetHostname","targetPort","href","protocol","port","hostname","location","registerImgLoadListeners","registerCanvasDrawImageListener","registerThumbnailRenderedListener","registered","draw","drawPreview","Identify","megapixErrorHandler","isPreviewable","dummyExif","exif","Exif","mpImg","Orientation","failureMsg","drawOnCanvasOrImgFromUrl","canvasOrImg","tempImg","tempImgRender","rendered","drawOnImgFromUrlWithCssScaling","drawFromUrl","fileBlobOrUrl","_testing","TAG_IDS","TAG_INFO","274","parseLittleEndian","hex","pow","seekToApp1","offset","theOffset","thePromise","segmentLength","getApp1Offset","isLittleEndian","app1Start","getDirEntryCount","littleEndian","getIfd","dirEntries","getDirEntries","ifdHex","getTagValues","TAG_VAL_OFFSET","tagsToFind","vals","idHex","tagsToFindIdx","tagValHex","tagValLength","parser","onParseFailure","app1Offset","dirEntryCount","tagValues","isIdentifiable","magicBytes","questionableBytes","identifiable","magicBytesEntries","magicBytesArrayEntry","previewable","isPreviewableSync","PREVIEWABLE_MIME_TYPES","fileMime","isRecognizedImage","image/jpeg","image/gif","image/png","image/bmp","image/tiff","hasNonZeroLimits","limits","atLeastOne","limit","getWidthHeight","sizeDetermination","getFailingLimit","dimensions","failingLimit","limitName","limitValue","limitMatcher","dimensionPropName","actualValue","validationEffort","isJsonResponseValid","handleFileItems","fileItems","someItemsIgnored","err","refreshEffort","refreshCompleteCallback","requesterOptions","SessionAjaxRequester","queryServer","responseText","includeOriginal","failedToScaleText","_getSortedSizes","getFileRecords","originalFileUuid","originalFileName","originalBlobOrBlobData","records","originalBlob","sizeRecord","outputType","_determineOutputType","requestedType","refType","_getName","_generateScaledImage","failedText","api","scaledIds","originalId","blobSize","scaledId","qqparentuuid","qqparentsize","param","scalingEffort","scalingOptions","scaler","referenceType","scaledVersionProperties","startOfExt","versionType","scaledName","scaledExt","nameAppendage","sort","a","b","sourceFile","imageGenerator","scaledImageDataUri","signalSuccess","_insertExifHeader","scaledImageDataUriWithExif","originalImage","reader","insertionEffort","originalImageDataUri","ExifRestorer","readAsDataURL","_dataUriToBlob","_createBlob","KEY_STR","encode64","output","chr1","chr2","chr3","enc1","enc2","enc3","enc4","isNaN","origFileBase64","resizedFileBase64","expectedBase64Header","rawImage","decode64","segments","slice2Segments","exifManipulation","exifArray","getExifArray","newImageArray","insertExif","aBuffer","seg","x","imageData","buf","separatePoint","mae","ato","array","rawImageArray","head","endPoint","base64test","perFileProgress","totalLoaded","totalSize","lastLoadedSent","lastTotalSent","callbackProxy","noRetryableFiles","retryable","none","failedId","updateTotalProgress","onNew","newLoaded","newTotal","oldLoaded","oldTotal","detachPasteHandler","isImage","registerPasteHandler","clipboardData","getAsFile","unregisterPasteHandler","startUpload","formEl","_form2Obj","determineNewEndpoint","validateForm","nativeSubmit","checkValidity","maybeUploadOnSubmit","submit","determineFormEl","notIrrelevantType","irrelevantTypes","radioOrCheckbox","ignoreValue","checked","selectValue","select","selected","elements","getIframeContentJson","doc","innerHtml","contentWindow","nodeValue","createForm","responseFromMessage","multipart","addChunkingSpecificParams","allChunksDoneRequester","AllChunksDoneAjaxRequester","createReadyStateChangedHandler","onUploadOrChunkComplete","getChunksCompleteParams","isErrorUploadResponse","parseResponse","sendChunksCompleteRequest","complete","setParamsAndGetEntityToSend","entityToSendParams","xhrOverrides","customParams","defaultParams","xhrOverrideParams","setUploadHeaders","headersOptions","headerOverrides","headerName","headerValue","extraHeaders","uploadChunkParams","toSend","promises","endpointHandler","DragAndDrop","HIDE_ZONES_EVENT_NAME","HIDE_BEFORE_ENTER_ATTR","uploadDropZones","droppedFiles","dropZoneElements","allowMultipleItems","dropActive","uploadDroppedFiles","uploadDropZone","filesAsArray","dropLog","dropDisabled","processingDroppedFilesComplete","getElement","traverseFileTree","parseEntryPromise","qqPath","extractDirectoryPath","fileError","fullPath","isDirectory","getFilesInDirectory","allEntriesRead","entriesLeft","readFailure","indexOfNameInFullPath","accumEntries","existingPromise","dirReader","createReader","readEntries","readSuccess","newEntries","handleDataTransfer","pendingFolderPromises","handleDataTransferPromise","processingDroppedFiles","dropError","setupDropzone","dropArea","dropZone","UploadDropZone","onEnter","stopPropagation","onLeaveNotDescendants","onDrop","isFileDrag","dragEvent","fileDrag","types","leavingDocumentOut","y","setupDragDrop","dropZones","maybeHideDropZones","HTMLElement","setupExtraDropzone","removeDropzone","dzs","targetEl","errorSpecifics","preventDrop","dropOutsideDisabled","dragoverShouldBeCanceled","disableDropOutside","dropEffect","isValidFileDrag","effectTest","dt","isSafari","effectAllowed","includes","isOrSetDropDisabled","isDisabled","triggerHidezonesEvent","hideZonesEvent","triggerUsingOldApi","createEvent","initEvent","CustomEvent","dispatchEvent","attachEvents","effect","relatedTarget","elementFromPoint","clientX","clientY","uiPublicApi","_parent","_templating","addCacheToDom","clearFiles","addExtraDropzone","_dnd","removeExtraDropzone","getItemByFileId","isHiddenForever","getFileContainer","_setupDragAndDrop","_totalFilesInBatch","_filesInBatchAddedToUi","_setupClickAndEditEventHandlers","formattedFilename","updateFilename","uploadPaused","continued","uploadContinued","getId","fileContainerOrChildEl","getFileId","getDropTarget","qqDropTarget","uiPrivateApi","_removeFileItem","removeFile","_fileButtonsClickHandler","FileButtonsClickHandler","_bindFileButtonsClickEvent","_focusinEventSupported","_isEditFilenameEnabled","_filenameClickHandler","_bindFilenameClickEvent","_filenameInputFocusInHandler","_bindFilenameInputFocusInEvent","_filenameInputFocusHandler","_bindFilenameInputFocusEvent","dragAndDrop","extraDropzones","templating","defaultDropZone","getDropZone","showDropProcessing","hideDropProcessing","errorData","lvl","onDeleteFile","onRetry","onPause","onContinue","onGetName","isEditFilenamePossible","FilenameClickHandler","FilenameInputFocusHandler","_filenameEditHandler","onGetUploadStatus","onSetName","onEditingStatusChange","isEditing","qqInput","getEditInput","qqFileContainer","hideFilename","hideEditIcon","showFilename","showEditIcon","markFilenameEditable","hideRetry","setStatusText","_classes","retrying","hidePause","FilenameInputFocusInHandler","hideSpinner","resetTotalProgress","reportDirectoryPaths","qqpath","_addToList","addHandler","updateProgress","hideCancel","hideProgress","waitingForResponse","_displayFileSize","parentRetVal","completeUpload","_markFileAsSuccessful","fail","showCancel","isRetryPossible","showRetry","_controlFailureTextDisplay","newResult","showDeleteButton","_maybeUpdateThumbnail","showSpinner","allowPause","retryNumForDisplay","maxAuto","retryNote","_showCancelLink","showAutoRetryNote","autoRetryNote","resetProgress","_onSubmitDeleteSuccess","forceConfirm","_showDeleteConfirm","_sendDeleteRequest","deletingFailedText","hideDeleteButton","deletingStatusText","confirmMessage","deleteRequestArgs","showConfirm","canned","prependData","prependIndex","dontDisplay","hideScaled","prependFiles","disableCancel","_handledProxyGroup","_clearList","addFileToCache","updateThumbnail","thumbnails","generatePreview","fileSizeOnSubmit","loadedSize","sizeForDisplay","_formatProgress","uploadedSize","formatProgress","mode","responseProperty","failureReason","failedUploadTextDisplay","failUpload","enableTooltip","_showTooltip","showMessage","_setupPastePrompt","namePromptMessage","defaultVal","showPrompt","fileStatus","placeholders","waitUntilResponse","FineUploader","listElement","template","editable","tooManyFilesError","unsupportedBrowser","promptForName","maxCount","notAvailablePath","waitingPath","timeBetweenThumbs","hasDialog","showDialog","confirm","defaultValue","prompt","Templating","templateIdOrEl","containerEl","fileContainerEl","maxThumbs","waitUntilUpdate","thumbnailNotAvailable","waitingForThumbnail","renderFailure","FILE_ID_ATTR","FILE_CLASS_PREFIX","THUMBNAIL_MAX_SIZE_ATTR","THUMBNAIL_SERVER_SCALE_ATTR","HIDE_DROPZONE_ATTR","DROPZPONE_TEXT_ATTR","IN_PROGRESS_CLASS","HIDDEN_FOREVER_CLASS","fileBatch","content","createDocumentFragment","map","isCancelDisabled","generatedThumbnails","thumbnailQueueMonitorRunning","thumbGenerationQueue","thumbnailMaxSize","selectorClasses","alertDialog","dialogCancelButton","confirmDialog","dialogMessage","dialogOkButton","promptDialog","uploader","drop","list","progressBarContainer","totalProgressBarContainer","totalProgressBar","spinner","continueButton","deleteButton","statusText","editFilenameInput","editNameIcon","dropText","dropProcessing","dropProcessingSpinner","thumbnail","previewGeneration","cachedThumbnailNotAvailableImg","cachedWaitingForThumbnailImg","isEditElementsExist","isRetryElementExist","templateDom","showThumbnails","serverScale","cacheThumbnailPlaceholders","notAvailableUrl","waitingUrl","updatedImg","displayWaitingImg","waitingImgPlacement","maybeScalePlaceholderViaCss","show","generateNewPreview","getThumbnail","qqThumbnailId","maybeSetDisplayNotAvailableImg","generateNextQueuedPreview","queuedThumbRequest","update","processUpdateQueuedPreviewRequest","processNewQueuedPreviewRequest","getCancel","getTemplateEl","getContinue","getDialog","getDelete","getDropProcessing","getEditIcon","getPause","getProgress","getRetry","getSpinner","cssClass","previewing","notAvailableImgPlacement","parseAndGetTemplate","scriptEl","scriptHtml","fileListNode","tempTemplateEl","fileListEl","defaultButton","dropTextEl","uploaderEl","cloneNode","fileTemplate","prependFile","parentEl","beforeEl","optFileOrBlob","relatedThumbnailId","useCachedPreview","showWaitingImg","setProgressBarWidth","percent","bar","progressBarSelector","targetThumbnailId","cachedThumbnailId","targetThumbnail","cachedThumbnail","hideTotalProgress","cantRenderEl","prependInfo","hideForever","batch","fileEl","fileNameEl","thumb","waitingImg","currentNode","getFileList","filenameEl","isFileName","icon","isEditIcon","isEditInput","isCancel","allowContinueButton","isPause","isContinueButton","isDeleteButton","isRetry","textEl","dialog","messageEl","inputEl","cancelBtn","okBtn","closeHandler","cancelClickHandler","okClickHandler","close","showModal","UiEventHandler","s","protectedApi","eventType","attachTo","onHandled","srcElement","getFileIdFromItem","qqFileId","getDisposeSupport","inheritedInternalApi","buttonHandlers","examineEvent","buttonType","firstLetterCapButtonType","handleFilenameEdit","FilenameEditHandler","handleInputFocus","getFilenameSansExtension","filenameSansExt","getOriginalExtension","origName","handleNameUpdate","newFilenameInputEl","origExtension","registerInputBlurHandler","registerInputEnterKeyHandler","keyCode","which","focusInput","focus"],"mappings":"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","file":"fine-uploader.js","sourcesContent":[null,"/*globals window, navigator, document, FormData, File, HTMLInputElement, XMLHttpRequest, Blob, Storage, ActiveXObject */\n/* jshint -W079 */\nvar qq = function(element) {\n \"use strict\";\n\n return {\n hide: function() {\n element.style.display = \"none\";\n return this;\n },\n\n /** Returns the function which detaches attached event */\n attach: function(type, fn) {\n if (element.addEventListener) {\n element.addEventListener(type, fn, false);\n } else if (element.attachEvent) {\n element.attachEvent(\"on\" + type, fn);\n }\n return function() {\n qq(element).detach(type, fn);\n };\n },\n\n detach: function(type, fn) {\n if (element.removeEventListener) {\n element.removeEventListener(type, fn, false);\n } else if (element.attachEvent) {\n element.detachEvent(\"on\" + type, fn);\n }\n return this;\n },\n\n contains: function(descendant) {\n // The [W3C spec](http://www.w3.org/TR/domcore/#dom-node-contains)\n // says a `null` (or ostensibly `undefined`) parameter\n // passed into `Node.contains` should result in a false return value.\n // IE7 throws an exception if the parameter is `undefined` though.\n if (!descendant) {\n return false;\n }\n\n // compareposition returns false in this case\n if (element === descendant) {\n return true;\n }\n\n if (element.contains) {\n return element.contains(descendant);\n } else {\n /*jslint bitwise: true*/\n return !!(descendant.compareDocumentPosition(element) & 8);\n }\n },\n\n /**\n * Insert this element before elementB.\n */\n insertBefore: function(elementB) {\n elementB.parentNode.insertBefore(element, elementB);\n return this;\n },\n\n remove: function() {\n element.parentNode.removeChild(element);\n return this;\n },\n\n /**\n * Sets styles for an element.\n * Fixes opacity in IE6-8.\n */\n css: function(styles) {\n /*jshint eqnull: true*/\n if (element.style == null) {\n throw new qq.Error(\"Can't apply style to node as it is not on the HTMLElement prototype chain!\");\n }\n\n /*jshint -W116*/\n if (styles.opacity != null) {\n if (typeof element.style.opacity !== \"string\" && typeof (element.filters) !== \"undefined\") {\n styles.filter = \"alpha(opacity=\" + Math.round(100 * styles.opacity) + \")\";\n }\n }\n qq.extend(element.style, styles);\n\n return this;\n },\n\n hasClass: function(name, considerParent) {\n var re = new RegExp(\"(^| )\" + name + \"( |$)\");\n return re.test(element.className) || !!(considerParent && re.test(element.parentNode.className));\n },\n\n addClass: function(name) {\n if (!qq(element).hasClass(name)) {\n element.className += \" \" + name;\n }\n return this;\n },\n\n removeClass: function(name) {\n var re = new RegExp(\"(^| )\" + name + \"( |$)\");\n element.className = element.className.replace(re, \" \").replace(/^\\s+|\\s+$/g, \"\");\n return this;\n },\n\n getByClass: function(className, first) {\n var candidates,\n result = [];\n\n if (first && element.querySelector) {\n return element.querySelector(\".\" + className);\n }\n else if (element.querySelectorAll) {\n return element.querySelectorAll(\".\" + className);\n }\n\n candidates = element.getElementsByTagName(\"*\");\n\n qq.each(candidates, function(idx, val) {\n if (qq(val).hasClass(className)) {\n result.push(val);\n }\n });\n return first ? result[0] : result;\n },\n\n getFirstByClass: function(className) {\n return qq(element).getByClass(className, true);\n },\n\n children: function() {\n var children = [],\n child = element.firstChild;\n\n while (child) {\n if (child.nodeType === 1) {\n children.push(child);\n }\n child = child.nextSibling;\n }\n\n return children;\n },\n\n setText: function(text) {\n element.innerText = text;\n element.textContent = text;\n return this;\n },\n\n clearText: function() {\n return qq(element).setText(\"\");\n },\n\n // Returns true if the attribute exists on the element\n // AND the value of the attribute is NOT \"false\" (case-insensitive)\n hasAttribute: function(attrName) {\n var attrVal;\n\n if (element.hasAttribute) {\n\n if (!element.hasAttribute(attrName)) {\n return false;\n }\n\n /*jshint -W116*/\n return (/^false$/i).exec(element.getAttribute(attrName)) == null;\n }\n else {\n attrVal = element[attrName];\n\n if (attrVal === undefined) {\n return false;\n }\n\n /*jshint -W116*/\n return (/^false$/i).exec(attrVal) == null;\n }\n }\n };\n};\n\n(function() {\n \"use strict\";\n\n qq.canvasToBlob = function(canvas, mime, quality) {\n return qq.dataUriToBlob(canvas.toDataURL(mime, quality));\n };\n\n qq.dataUriToBlob = function(dataUri) {\n var arrayBuffer, byteString,\n createBlob = function(data, mime) {\n var BlobBuilder = window.BlobBuilder ||\n window.WebKitBlobBuilder ||\n window.MozBlobBuilder ||\n window.MSBlobBuilder,\n blobBuilder = BlobBuilder && new BlobBuilder();\n\n if (blobBuilder) {\n blobBuilder.append(data);\n return blobBuilder.getBlob(mime);\n }\n else {\n return new Blob([data], {type: mime});\n }\n },\n intArray, mimeString;\n\n // convert base64 to raw binary data held in a string\n if (dataUri.split(\",\")[0].indexOf(\"base64\") >= 0) {\n byteString = atob(dataUri.split(\",\")[1]);\n }\n else {\n byteString = decodeURI(dataUri.split(\",\")[1]);\n }\n\n // extract the MIME\n mimeString = dataUri.split(\",\")[0]\n .split(\":\")[1]\n .split(\";\")[0];\n\n // write the bytes of the binary string to an ArrayBuffer\n arrayBuffer = new ArrayBuffer(byteString.length);\n intArray = new Uint8Array(arrayBuffer);\n qq.each(byteString, function(idx, character) {\n intArray[idx] = character.charCodeAt(0);\n });\n\n return createBlob(arrayBuffer, mimeString);\n };\n\n qq.log = function(message, level) {\n if (window.console) {\n if (!level || level === \"info\") {\n window.console.log(message);\n }\n else\n {\n if (window.console[level]) {\n window.console[level](message);\n }\n else {\n window.console.log(\"<\" + level + \"> \" + message);\n }\n }\n }\n };\n\n qq.isObject = function(variable) {\n return variable && !variable.nodeType && Object.prototype.toString.call(variable) === \"[object Object]\";\n };\n\n qq.isFunction = function(variable) {\n return typeof (variable) === \"function\";\n };\n\n /**\n * Check the type of a value. Is it an \"array\"?\n *\n * @param value value to test.\n * @returns true if the value is an array or associated with an `ArrayBuffer`\n */\n qq.isArray = function(value) {\n return Object.prototype.toString.call(value) === \"[object Array]\" ||\n (value && window.ArrayBuffer && value.buffer && value.buffer.constructor === ArrayBuffer);\n };\n\n // Looks for an object on a `DataTransfer` object that is associated with drop events when utilizing the Filesystem API.\n qq.isItemList = function(maybeItemList) {\n return Object.prototype.toString.call(maybeItemList) === \"[object DataTransferItemList]\";\n };\n\n // Looks for an object on a `NodeList` or an `HTMLCollection`|`HTMLFormElement`|`HTMLSelectElement`\n // object that is associated with collections of Nodes.\n qq.isNodeList = function(maybeNodeList) {\n return Object.prototype.toString.call(maybeNodeList) === \"[object NodeList]\" ||\n // If `HTMLCollection` is the actual type of the object, we must determine this\n // by checking for expected properties/methods on the object\n (maybeNodeList.item && maybeNodeList.namedItem);\n };\n\n qq.isString = function(maybeString) {\n return Object.prototype.toString.call(maybeString) === \"[object String]\";\n };\n\n qq.trimStr = function(string) {\n if (String.prototype.trim) {\n return string.trim();\n }\n\n return string.replace(/^\\s+|\\s+$/g, \"\");\n };\n\n /**\n * @param str String to format.\n * @returns {string} A string, swapping argument values with the associated occurrence of {} in the passed string.\n */\n qq.format = function(str) {\n\n var args = Array.prototype.slice.call(arguments, 1),\n newStr = str,\n nextIdxToReplace = newStr.indexOf(\"{}\");\n\n qq.each(args, function(idx, val) {\n var strBefore = newStr.substring(0, nextIdxToReplace),\n strAfter = newStr.substring(nextIdxToReplace + 2);\n\n newStr = strBefore + val + strAfter;\n nextIdxToReplace = newStr.indexOf(\"{}\", nextIdxToReplace + val.length);\n\n // End the loop if we have run out of tokens (when the arguments exceed the # of tokens)\n if (nextIdxToReplace < 0) {\n return false;\n }\n });\n\n return newStr;\n };\n\n qq.isFile = function(maybeFile) {\n return window.File && Object.prototype.toString.call(maybeFile) === \"[object File]\";\n };\n\n qq.isFileList = function(maybeFileList) {\n return window.FileList && Object.prototype.toString.call(maybeFileList) === \"[object FileList]\";\n };\n\n qq.isFileOrInput = function(maybeFileOrInput) {\n return qq.isFile(maybeFileOrInput) || qq.isInput(maybeFileOrInput);\n };\n\n qq.isInput = function(maybeInput, notFile) {\n var evaluateType = function(type) {\n var normalizedType = type.toLowerCase();\n\n if (notFile) {\n return normalizedType !== \"file\";\n }\n\n return normalizedType === \"file\";\n };\n\n if (window.HTMLInputElement) {\n if (Object.prototype.toString.call(maybeInput) === \"[object HTMLInputElement]\") {\n if (maybeInput.type && evaluateType(maybeInput.type)) {\n return true;\n }\n }\n }\n if (maybeInput.tagName) {\n if (maybeInput.tagName.toLowerCase() === \"input\") {\n if (maybeInput.type && evaluateType(maybeInput.type)) {\n return true;\n }\n }\n }\n\n return false;\n };\n\n qq.isBlob = function(maybeBlob) {\n if (window.Blob && Object.prototype.toString.call(maybeBlob) === \"[object Blob]\") {\n return true;\n }\n };\n\n qq.isXhrUploadSupported = function() {\n var input = document.createElement(\"input\");\n input.type = \"file\";\n\n return (\n input.multiple !== undefined &&\n typeof File !== \"undefined\" &&\n typeof FormData !== \"undefined\" &&\n typeof (qq.createXhrInstance()).upload !== \"undefined\");\n };\n\n // Fall back to ActiveX is native XHR is disabled (possible in any version of IE).\n qq.createXhrInstance = function() {\n if (window.XMLHttpRequest) {\n return new XMLHttpRequest();\n }\n\n try {\n return new ActiveXObject(\"MSXML2.XMLHTTP.3.0\");\n }\n catch (error) {\n qq.log(\"Neither XHR or ActiveX are supported!\", \"error\");\n return null;\n }\n };\n\n qq.isFolderDropSupported = function(dataTransfer) {\n return dataTransfer.items &&\n dataTransfer.items.length > 0 &&\n dataTransfer.items[0].webkitGetAsEntry;\n };\n\n qq.isFileChunkingSupported = function() {\n return !qq.androidStock() && //Android's stock browser cannot upload Blobs correctly\n qq.isXhrUploadSupported() &&\n (File.prototype.slice !== undefined || File.prototype.webkitSlice !== undefined || File.prototype.mozSlice !== undefined);\n };\n\n qq.sliceBlob = function(fileOrBlob, start, end) {\n var slicer = fileOrBlob.slice || fileOrBlob.mozSlice || fileOrBlob.webkitSlice;\n\n return slicer.call(fileOrBlob, start, end);\n };\n\n qq.arrayBufferToHex = function(buffer) {\n var bytesAsHex = \"\",\n bytes = new Uint8Array(buffer);\n\n qq.each(bytes, function(idx, byt) {\n var byteAsHexStr = byt.toString(16);\n\n if (byteAsHexStr.length < 2) {\n byteAsHexStr = \"0\" + byteAsHexStr;\n }\n\n bytesAsHex += byteAsHexStr;\n });\n\n return bytesAsHex;\n };\n\n qq.readBlobToHex = function(blob, startOffset, length) {\n var initialBlob = qq.sliceBlob(blob, startOffset, startOffset + length),\n fileReader = new FileReader(),\n promise = new qq.Promise();\n\n fileReader.onload = function() {\n promise.success(qq.arrayBufferToHex(fileReader.result));\n };\n\n fileReader.onerror = promise.failure;\n\n fileReader.readAsArrayBuffer(initialBlob);\n\n return promise;\n };\n\n qq.extend = function(first, second, extendNested) {\n qq.each(second, function(prop, val) {\n if (extendNested && qq.isObject(val)) {\n if (first[prop] === undefined) {\n first[prop] = {};\n }\n qq.extend(first[prop], val, true);\n }\n else {\n first[prop] = val;\n }\n });\n\n return first;\n };\n\n /**\n * Allow properties in one object to override properties in another,\n * keeping track of the original values from the target object.\n *\n * Note that the pre-overriden properties to be overriden by the source will be passed into the `sourceFn` when it is invoked.\n *\n * @param target Update properties in this object from some source\n * @param sourceFn A function that, when invoked, will return properties that will replace properties with the same name in the target.\n * @returns {object} The target object\n */\n qq.override = function(target, sourceFn) {\n var super_ = {},\n source = sourceFn(super_);\n\n qq.each(source, function(srcPropName, srcPropVal) {\n if (target[srcPropName] !== undefined) {\n super_[srcPropName] = target[srcPropName];\n }\n\n target[srcPropName] = srcPropVal;\n });\n\n return target;\n };\n\n /**\n * Searches for a given element (elt) in the array, returns -1 if it is not present.\n */\n qq.indexOf = function(arr, elt, from) {\n if (arr.indexOf) {\n return arr.indexOf(elt, from);\n }\n\n from = from || 0;\n var len = arr.length;\n\n if (from < 0) {\n from += len;\n }\n\n for (; from < len; from += 1) {\n if (arr.hasOwnProperty(from) && arr[from] === elt) {\n return from;\n }\n }\n return -1;\n };\n\n //this is a version 4 UUID\n qq.getUniqueId = function() {\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, function(c) {\n /*jslint eqeq: true, bitwise: true*/\n var r = Math.random() * 16 | 0, v = c == \"x\" ? r : (r & 0x3 | 0x8);\n return v.toString(16);\n });\n };\n\n //\n // Browsers and platforms detection\n qq.ie = function() {\n return navigator.userAgent.indexOf(\"MSIE\") !== -1 ||\n navigator.userAgent.indexOf(\"Trident\") !== -1;\n };\n\n qq.ie7 = function() {\n return navigator.userAgent.indexOf(\"MSIE 7\") !== -1;\n };\n\n qq.ie8 = function() {\n return navigator.userAgent.indexOf(\"MSIE 8\") !== -1;\n };\n\n qq.ie10 = function() {\n return navigator.userAgent.indexOf(\"MSIE 10\") !== -1;\n };\n\n qq.ie11 = function() {\n return qq.ie() && navigator.userAgent.indexOf(\"rv:11\") !== -1;\n };\n\n qq.edge = function() {\n return navigator.userAgent.indexOf(\"Edge\") >= 0;\n };\n\n qq.safari = function() {\n return navigator.vendor !== undefined && navigator.vendor.indexOf(\"Apple\") !== -1;\n };\n\n qq.chrome = function() {\n return navigator.vendor !== undefined && navigator.vendor.indexOf(\"Google\") !== -1;\n };\n\n qq.opera = function() {\n return navigator.vendor !== undefined && navigator.vendor.indexOf(\"Opera\") !== -1;\n };\n\n qq.firefox = function() {\n return (!qq.edge() && !qq.ie11() && navigator.userAgent.indexOf(\"Mozilla\") !== -1 && navigator.vendor !== undefined && navigator.vendor === \"\");\n };\n\n qq.windows = function() {\n return navigator.platform === \"Win32\";\n };\n\n qq.android = function() {\n return navigator.userAgent.toLowerCase().indexOf(\"android\") !== -1;\n };\n\n // We need to identify the Android stock browser via the UA string to work around various bugs in this browser,\n // such as the one that prevents a `Blob` from being uploaded.\n qq.androidStock = function() {\n return qq.android() && navigator.userAgent.toLowerCase().indexOf(\"chrome\") < 0;\n };\n\n qq.ios6 = function() {\n return qq.ios() && navigator.userAgent.indexOf(\" OS 6_\") !== -1;\n };\n\n qq.ios7 = function() {\n return qq.ios() && navigator.userAgent.indexOf(\" OS 7_\") !== -1;\n };\n\n qq.ios8 = function() {\n return qq.ios() && navigator.userAgent.indexOf(\" OS 8_\") !== -1;\n };\n\n // iOS 8.0.0\n qq.ios800 = function() {\n return qq.ios() && navigator.userAgent.indexOf(\" OS 8_0 \") !== -1;\n };\n\n qq.ios = function() {\n /*jshint -W014 */\n return navigator.userAgent.indexOf(\"iPad\") !== -1\n || navigator.userAgent.indexOf(\"iPod\") !== -1\n || navigator.userAgent.indexOf(\"iPhone\") !== -1;\n };\n\n qq.iosChrome = function() {\n return qq.ios() && navigator.userAgent.indexOf(\"CriOS\") !== -1;\n };\n\n qq.iosSafari = function() {\n return qq.ios() && !qq.iosChrome() && navigator.userAgent.indexOf(\"Safari\") !== -1;\n };\n\n qq.iosSafariWebView = function() {\n return qq.ios() && !qq.iosChrome() && !qq.iosSafari();\n };\n\n //\n // Events\n\n qq.preventDefault = function(e) {\n if (e.preventDefault) {\n e.preventDefault();\n } else {\n e.returnValue = false;\n }\n };\n\n /**\n * Creates and returns element from html string\n * Uses innerHTML to create an element\n */\n qq.toElement = (function() {\n var div = document.createElement(\"div\");\n return function(html) {\n div.innerHTML = html;\n var element = div.firstChild;\n div.removeChild(element);\n return element;\n };\n }());\n\n //key and value are passed to callback for each entry in the iterable item\n qq.each = function(iterableItem, callback) {\n var keyOrIndex, retVal;\n\n if (iterableItem) {\n // Iterate through [`Storage`](http://www.w3.org/TR/webstorage/#the-storage-interface) items\n if (window.Storage && iterableItem.constructor === window.Storage) {\n for (keyOrIndex = 0; keyOrIndex < iterableItem.length; keyOrIndex++) {\n retVal = callback(iterableItem.key(keyOrIndex), iterableItem.getItem(iterableItem.key(keyOrIndex)));\n if (retVal === false) {\n break;\n }\n }\n }\n // `DataTransferItemList` & `NodeList` objects are array-like and should be treated as arrays\n // when iterating over items inside the object.\n else if (qq.isArray(iterableItem) || qq.isItemList(iterableItem) || qq.isNodeList(iterableItem)) {\n for (keyOrIndex = 0; keyOrIndex < iterableItem.length; keyOrIndex++) {\n retVal = callback(keyOrIndex, iterableItem[keyOrIndex]);\n if (retVal === false) {\n break;\n }\n }\n }\n else if (qq.isString(iterableItem)) {\n for (keyOrIndex = 0; keyOrIndex < iterableItem.length; keyOrIndex++) {\n retVal = callback(keyOrIndex, iterableItem.charAt(keyOrIndex));\n if (retVal === false) {\n break;\n }\n }\n }\n else {\n for (keyOrIndex in iterableItem) {\n if (Object.prototype.hasOwnProperty.call(iterableItem, keyOrIndex)) {\n retVal = callback(keyOrIndex, iterableItem[keyOrIndex]);\n if (retVal === false) {\n break;\n }\n }\n }\n }\n }\n };\n\n //include any args that should be passed to the new function after the context arg\n qq.bind = function(oldFunc, context) {\n if (qq.isFunction(oldFunc)) {\n var args = Array.prototype.slice.call(arguments, 2);\n\n return function() {\n var newArgs = qq.extend([], args);\n if (arguments.length) {\n newArgs = newArgs.concat(Array.prototype.slice.call(arguments));\n }\n return oldFunc.apply(context, newArgs);\n };\n }\n\n throw new Error(\"first parameter must be a function!\");\n };\n\n /**\n * obj2url() takes a json-object as argument and generates\n * a querystring. pretty much like jQuery.param()\n *\n * how to use:\n *\n * `qq.obj2url({a:'b',c:'d'},'http://any.url/upload?otherParam=value');`\n *\n * will result in:\n *\n * `http://any.url/upload?otherParam=value&a=b&c=d`\n *\n * @param Object JSON-Object\n * @param String current querystring-part\n * @return String encoded querystring\n */\n qq.obj2url = function(obj, temp, prefixDone) {\n /*jshint laxbreak: true*/\n var uristrings = [],\n prefix = \"&\",\n add = function(nextObj, i) {\n var nextTemp = temp\n ? (/\\[\\]$/.test(temp)) // prevent double-encoding\n ? temp\n : temp + \"[\" + i + \"]\"\n : i;\n if ((nextTemp !== \"undefined\") && (i !== \"undefined\")) {\n uristrings.push(\n (typeof nextObj === \"object\")\n ? qq.obj2url(nextObj, nextTemp, true)\n : (Object.prototype.toString.call(nextObj) === \"[object Function]\")\n ? encodeURIComponent(nextTemp) + \"=\" + encodeURIComponent(nextObj())\n : encodeURIComponent(nextTemp) + \"=\" + encodeURIComponent(nextObj)\n );\n }\n };\n\n if (!prefixDone && temp) {\n prefix = (/\\?/.test(temp)) ? (/\\?$/.test(temp)) ? \"\" : \"&\" : \"?\";\n uristrings.push(temp);\n uristrings.push(qq.obj2url(obj));\n } else if ((Object.prototype.toString.call(obj) === \"[object Array]\") && (typeof obj !== \"undefined\")) {\n qq.each(obj, function(idx, val) {\n add(val, idx);\n });\n } else if ((typeof obj !== \"undefined\") && (obj !== null) && (typeof obj === \"object\")) {\n qq.each(obj, function(prop, val) {\n add(val, prop);\n });\n } else {\n uristrings.push(encodeURIComponent(temp) + \"=\" + encodeURIComponent(obj));\n }\n\n if (temp) {\n return uristrings.join(prefix);\n } else {\n return uristrings.join(prefix)\n .replace(/^&/, \"\")\n .replace(/%20/g, \"+\");\n }\n };\n\n qq.obj2FormData = function(obj, formData, arrayKeyName) {\n if (!formData) {\n formData = new FormData();\n }\n\n qq.each(obj, function(key, val) {\n key = arrayKeyName ? arrayKeyName + \"[\" + key + \"]\" : key;\n\n if (qq.isObject(val)) {\n qq.obj2FormData(val, formData, key);\n }\n else if (qq.isFunction(val)) {\n formData.append(key, val());\n }\n else {\n formData.append(key, val);\n }\n });\n\n return formData;\n };\n\n qq.obj2Inputs = function(obj, form) {\n var input;\n\n if (!form) {\n form = document.createElement(\"form\");\n }\n\n qq.obj2FormData(obj, {\n append: function(key, val) {\n input = document.createElement(\"input\");\n input.setAttribute(\"name\", key);\n input.setAttribute(\"value\", val);\n form.appendChild(input);\n }\n });\n\n return form;\n };\n\n /**\n * Not recommended for use outside of Fine Uploader since this falls back to an unchecked eval if JSON.parse is not\n * implemented. For a more secure JSON.parse polyfill, use Douglas Crockford's json2.js.\n */\n qq.parseJson = function(json) {\n /*jshint evil: true*/\n if (window.JSON && qq.isFunction(JSON.parse)) {\n return JSON.parse(json);\n } else {\n return eval(\"(\" + json + \")\");\n }\n };\n\n /**\n * Retrieve the extension of a file, if it exists.\n *\n * @param filename\n * @returns {string || undefined}\n */\n qq.getExtension = function(filename) {\n var extIdx = filename.lastIndexOf(\".\") + 1;\n\n if (extIdx > 0) {\n return filename.substr(extIdx, filename.length - extIdx);\n }\n };\n\n qq.getFilename = function(blobOrFileInput) {\n /*jslint regexp: true*/\n\n if (qq.isInput(blobOrFileInput)) {\n // get input value and remove path to normalize\n return blobOrFileInput.value.replace(/.*(\\/|\\\\)/, \"\");\n }\n else if (qq.isFile(blobOrFileInput)) {\n if (blobOrFileInput.fileName !== null && blobOrFileInput.fileName !== undefined) {\n return blobOrFileInput.fileName;\n }\n }\n\n return blobOrFileInput.name;\n };\n\n /**\n * A generic module which supports object disposing in dispose() method.\n * */\n qq.DisposeSupport = function() {\n var disposers = [];\n\n return {\n /** Run all registered disposers */\n dispose: function() {\n var disposer;\n do {\n disposer = disposers.shift();\n if (disposer) {\n disposer();\n }\n }\n while (disposer);\n },\n\n /** Attach event handler and register de-attacher as a disposer */\n attach: function() {\n var args = arguments;\n /*jslint undef:true*/\n this.addDisposer(qq(args[0]).attach.apply(this, Array.prototype.slice.call(arguments, 1)));\n },\n\n /** Add disposer to the collection */\n addDisposer: function(disposeFunction) {\n disposers.push(disposeFunction);\n }\n };\n };\n}());\n","/* globals define, module, global, qq */\n(function() {\n \"use strict\";\n if (typeof define === \"function\" && define.amd) {\n define(function() {\n return qq;\n });\n }\n else if (typeof module !== \"undefined\" && module.exports) {\n module.exports = qq;\n }\n else {\n global.qq = qq;\n }\n}());\n","/* globals qq */\n/**\n * Fine Uploader top-level Error container. Inherits from `Error`.\n */\n(function() {\n \"use strict\";\n\n qq.Error = function(message) {\n this.message = \"[Fine Uploader \" + qq.version + \"] \" + message;\n };\n\n qq.Error.prototype = new Error();\n}());\n","/*global qq */\nqq.version = \"5.16.2\";\n","/* globals qq */\nqq.supportedFeatures = (function() {\n \"use strict\";\n\n var supportsUploading,\n supportsUploadingBlobs,\n supportsFileDrop,\n supportsAjaxFileUploading,\n supportsFolderDrop,\n supportsChunking,\n supportsResume,\n supportsUploadViaPaste,\n supportsUploadCors,\n supportsDeleteFileXdr,\n supportsDeleteFileCorsXhr,\n supportsDeleteFileCors,\n supportsFolderSelection,\n supportsImagePreviews,\n supportsUploadProgress;\n\n function testSupportsFileInputElement() {\n var supported = true,\n tempInput;\n\n try {\n tempInput = document.createElement(\"input\");\n tempInput.type = \"file\";\n qq(tempInput).hide();\n\n if (tempInput.disabled) {\n supported = false;\n }\n }\n catch (ex) {\n supported = false;\n }\n\n return supported;\n }\n\n //only way to test for complete Clipboard API support at this time\n function isChrome14OrHigher() {\n return (qq.chrome() || qq.opera()) &&\n navigator.userAgent.match(/Chrome\\/[1][4-9]|Chrome\\/[2-9][0-9]/) !== undefined;\n }\n\n //Ensure we can send cross-origin `XMLHttpRequest`s\n function isCrossOriginXhrSupported() {\n if (window.XMLHttpRequest) {\n var xhr = qq.createXhrInstance();\n\n //Commonly accepted test for XHR CORS support.\n return xhr.withCredentials !== undefined;\n }\n\n return false;\n }\n\n //Test for (terrible) cross-origin ajax transport fallback for IE9 and IE8\n function isXdrSupported() {\n return window.XDomainRequest !== undefined;\n }\n\n // CORS Ajax requests are supported if it is either possible to send credentialed `XMLHttpRequest`s,\n // or if `XDomainRequest` is an available alternative.\n function isCrossOriginAjaxSupported() {\n if (isCrossOriginXhrSupported()) {\n return true;\n }\n\n return isXdrSupported();\n }\n\n function isFolderSelectionSupported() {\n // We know that folder selection is only supported in Chrome via this proprietary attribute for now\n return document.createElement(\"input\").webkitdirectory !== undefined;\n }\n\n function isLocalStorageSupported() {\n try {\n return !!window.localStorage &&\n // unpatched versions of IE10/11 have buggy impls of localStorage where setItem is a string\n qq.isFunction(window.localStorage.setItem);\n }\n catch (error) {\n // probably caught a security exception, so no localStorage for you\n return false;\n }\n }\n\n function isDragAndDropSupported() {\n var span = document.createElement(\"span\");\n\n return (\"draggable\" in span || (\"ondragstart\" in span && \"ondrop\" in span)) &&\n !qq.android() && !qq.ios();\n }\n\n supportsUploading = testSupportsFileInputElement();\n\n supportsAjaxFileUploading = supportsUploading && qq.isXhrUploadSupported();\n\n supportsUploadingBlobs = supportsAjaxFileUploading && !qq.androidStock();\n\n supportsFileDrop = supportsAjaxFileUploading && isDragAndDropSupported();\n\n // adapted from https://stackoverflow.com/a/23278460/486979\n supportsFolderDrop = supportsFileDrop && (function() {\n var input = document.createElement(\"input\");\n\n input.type = \"file\";\n return !!(\"webkitdirectory\" in (input || document.querySelectorAll(\"input[type=file]\")[0]));\n }());\n\n supportsChunking = supportsAjaxFileUploading && qq.isFileChunkingSupported();\n\n supportsResume = supportsAjaxFileUploading && supportsChunking && isLocalStorageSupported();\n\n supportsUploadViaPaste = supportsAjaxFileUploading && isChrome14OrHigher();\n\n supportsUploadCors = supportsUploading && (window.postMessage !== undefined || supportsAjaxFileUploading);\n\n supportsDeleteFileCorsXhr = isCrossOriginXhrSupported();\n\n supportsDeleteFileXdr = isXdrSupported();\n\n supportsDeleteFileCors = isCrossOriginAjaxSupported();\n\n supportsFolderSelection = isFolderSelectionSupported();\n\n supportsImagePreviews = supportsAjaxFileUploading && window.FileReader !== undefined;\n\n supportsUploadProgress = (function() {\n if (supportsAjaxFileUploading) {\n return !qq.androidStock() && !qq.iosChrome();\n }\n return false;\n }());\n\n return {\n ajaxUploading: supportsAjaxFileUploading,\n blobUploading: supportsUploadingBlobs,\n canDetermineSize: supportsAjaxFileUploading,\n chunking: supportsChunking,\n deleteFileCors: supportsDeleteFileCors,\n deleteFileCorsXdr: supportsDeleteFileXdr, //NOTE: will also return true in IE10, where XDR is also supported\n deleteFileCorsXhr: supportsDeleteFileCorsXhr,\n dialogElement: !!window.HTMLDialogElement,\n fileDrop: supportsFileDrop,\n folderDrop: supportsFolderDrop,\n folderSelection: supportsFolderSelection,\n imagePreviews: supportsImagePreviews,\n imageValidation: supportsImagePreviews,\n itemSizeValidation: supportsAjaxFileUploading,\n pause: supportsChunking,\n progressBar: supportsUploadProgress,\n resume: supportsResume,\n scaling: supportsImagePreviews && supportsUploadingBlobs,\n tiffPreviews: qq.safari(), // Not the best solution, but simple and probably accurate enough (for now)\n unlimitedScaledImageSize: !qq.ios(), // false simply indicates that there is some known limit\n uploading: supportsUploading,\n uploadCors: supportsUploadCors,\n uploadCustomHeaders: supportsAjaxFileUploading,\n uploadNonMultipart: supportsAjaxFileUploading,\n uploadViaPaste: supportsUploadViaPaste\n };\n\n}());\n","/*globals qq*/\n\n// Is the passed object a promise instance?\nqq.isGenericPromise = function(maybePromise) {\n \"use strict\";\n return !!(maybePromise && maybePromise.then && qq.isFunction(maybePromise.then));\n};\n\nqq.Promise = function() {\n \"use strict\";\n\n var successArgs, failureArgs,\n successCallbacks = [],\n failureCallbacks = [],\n doneCallbacks = [],\n state = 0;\n\n qq.extend(this, {\n then: function(onSuccess, onFailure) {\n if (state === 0) {\n if (onSuccess) {\n successCallbacks.push(onSuccess);\n }\n if (onFailure) {\n failureCallbacks.push(onFailure);\n }\n }\n else if (state === -1) {\n onFailure && onFailure.apply(null, failureArgs);\n }\n else if (onSuccess) {\n onSuccess.apply(null, successArgs);\n }\n\n return this;\n },\n\n done: function(callback) {\n if (state === 0) {\n doneCallbacks.push(callback);\n }\n else {\n callback.apply(null, failureArgs === undefined ? successArgs : failureArgs);\n }\n\n return this;\n },\n\n success: function() {\n state = 1;\n successArgs = arguments;\n\n if (successCallbacks.length) {\n qq.each(successCallbacks, function(idx, callback) {\n callback.apply(null, successArgs);\n });\n }\n\n if (doneCallbacks.length) {\n qq.each(doneCallbacks, function(idx, callback) {\n callback.apply(null, successArgs);\n });\n }\n\n return this;\n },\n\n failure: function() {\n state = -1;\n failureArgs = arguments;\n\n if (failureCallbacks.length) {\n qq.each(failureCallbacks, function(idx, callback) {\n callback.apply(null, failureArgs);\n });\n }\n\n if (doneCallbacks.length) {\n qq.each(doneCallbacks, function(idx, callback) {\n callback.apply(null, failureArgs);\n });\n }\n\n return this;\n }\n });\n};\n","/* globals qq */\n/**\n * Placeholder for a Blob that will be generated on-demand.\n *\n * @param referenceBlob Parent of the generated blob\n * @param onCreate Function to invoke when the blob must be created. Must be promissory.\n * @constructor\n */\nqq.BlobProxy = function(referenceBlob, onCreate) {\n \"use strict\";\n\n qq.extend(this, {\n referenceBlob: referenceBlob,\n\n create: function() {\n return onCreate(referenceBlob);\n }\n });\n};\n","/*globals qq*/\n\n/**\n * This module represents an upload or \"Select File(s)\" button. It's job is to embed an opaque ` `\n * element as a child of a provided \"container\" element. This \"container\" element (`options.element`) is used to provide\n * a custom style for the ` ` element. The ability to change the style of the container element is also\n * provided here by adding CSS classes to the container on hover/focus.\n *\n * TODO Eliminate the mouseover and mouseout event handlers since the :hover CSS pseudo-class should now be\n * available on all supported browsers.\n *\n * @param o Options to override the default values\n */\nqq.UploadButton = function(o) {\n \"use strict\";\n\n var self = this,\n\n disposeSupport = new qq.DisposeSupport(),\n\n options = {\n // Corresponds to the `accept` attribute on the associated ` `\n acceptFiles: null,\n\n // \"Container\" element\n element: null,\n\n focusClass: \"qq-upload-button-focus\",\n\n // A true value allows folders to be selected, if supported by the UA\n folders: false,\n\n // **This option will be removed** in the future as the :hover CSS pseudo-class is available on all supported browsers\n hoverClass: \"qq-upload-button-hover\",\n\n ios8BrowserCrashWorkaround: false,\n\n // If true adds `multiple` attribute to ` `\n multiple: false,\n\n // `name` attribute of ` `\n name: \"qqfile\",\n\n // Called when the browser invokes the onchange handler on the ` `\n onChange: function(input) {},\n\n title: null\n },\n input, buttonId;\n\n // Overrides any of the default option values with any option values passed in during construction.\n qq.extend(options, o);\n\n buttonId = qq.getUniqueId();\n\n // Embed an opaque ` ` element as a child of `options.element`.\n function createInput() {\n var input = document.createElement(\"input\");\n\n input.setAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME, buttonId);\n input.setAttribute(\"title\", options.title);\n\n self.setMultiple(options.multiple, input);\n\n if (options.folders && qq.supportedFeatures.folderSelection) {\n // selecting directories is only possible in Chrome now, via a vendor-specific prefixed attribute\n input.setAttribute(\"webkitdirectory\", \"\");\n }\n\n if (options.acceptFiles) {\n input.setAttribute(\"accept\", options.acceptFiles);\n }\n\n input.setAttribute(\"type\", \"file\");\n input.setAttribute(\"name\", options.name);\n\n qq(input).css({\n position: \"absolute\",\n // in Opera only 'browse' button\n // is clickable and it is located at\n // the right side of the input\n right: 0,\n top: 0,\n fontFamily: \"Arial\",\n // It's especially important to make this an arbitrarily large value\n // to ensure the rendered input button in IE takes up the entire\n // space of the container element. Otherwise, the left side of the\n // button will require a double-click to invoke the file chooser.\n // In other browsers, this might cause other issues, so a large font-size\n // is only used in IE. There is a bug in IE8 where the opacity style is ignored\n // in some cases when the font-size is large. So, this workaround is not applied\n // to IE8.\n fontSize: qq.ie() && !qq.ie8() ? \"3500px\" : \"118px\",\n margin: 0,\n padding: 0,\n cursor: \"pointer\",\n opacity: 0\n });\n\n // Setting the file input's height to 100% in IE7 causes\n // most of the visible button to be unclickable.\n !qq.ie7() && qq(input).css({height: \"100%\"});\n\n options.element.appendChild(input);\n\n disposeSupport.attach(input, \"change\", function() {\n options.onChange(input);\n });\n\n // **These event handlers will be removed** in the future as the :hover CSS pseudo-class is available on all supported browsers\n disposeSupport.attach(input, \"mouseover\", function() {\n qq(options.element).addClass(options.hoverClass);\n });\n disposeSupport.attach(input, \"mouseout\", function() {\n qq(options.element).removeClass(options.hoverClass);\n });\n\n disposeSupport.attach(input, \"focus\", function() {\n qq(options.element).addClass(options.focusClass);\n });\n disposeSupport.attach(input, \"blur\", function() {\n qq(options.element).removeClass(options.focusClass);\n });\n\n return input;\n }\n\n // Make button suitable container for input\n qq(options.element).css({\n position: \"relative\",\n overflow: \"hidden\",\n // Make sure browse button is in the right side in Internet Explorer\n direction: \"ltr\"\n });\n\n // Exposed API\n qq.extend(this, {\n getInput: function() {\n return input;\n },\n\n getButtonId: function() {\n return buttonId;\n },\n\n setMultiple: function(isMultiple, optInput) {\n var input = optInput || this.getInput();\n\n // Temporary workaround for bug in in iOS8 UIWebView that causes the browser to crash\n // before the file chooser appears if the file input doesn't contain a multiple attribute.\n // See #1283.\n if (options.ios8BrowserCrashWorkaround && qq.ios8() && (qq.iosChrome() || qq.iosSafariWebView())) {\n input.setAttribute(\"multiple\", \"\");\n }\n\n else {\n if (isMultiple) {\n input.setAttribute(\"multiple\", \"\");\n }\n else {\n input.removeAttribute(\"multiple\");\n }\n }\n },\n\n setAcceptFiles: function(acceptFiles) {\n if (acceptFiles !== options.acceptFiles) {\n input.setAttribute(\"accept\", acceptFiles);\n }\n },\n\n reset: function() {\n if (input.parentNode) {\n qq(input).remove();\n }\n\n qq(options.element).removeClass(options.focusClass);\n input = null;\n input = createInput();\n }\n });\n\n input = createInput();\n};\n\nqq.UploadButton.BUTTON_ID_ATTR_NAME = \"qq-button-id\";\n","/*globals qq */\nqq.UploadData = function(uploaderProxy) {\n \"use strict\";\n\n var data = [],\n byUuid = {},\n byStatus = {},\n byProxyGroupId = {},\n byBatchId = {};\n\n function getDataByIds(idOrIds) {\n if (qq.isArray(idOrIds)) {\n var entries = [];\n\n qq.each(idOrIds, function(idx, id) {\n entries.push(data[id]);\n });\n\n return entries;\n }\n\n return data[idOrIds];\n }\n\n function getDataByUuids(uuids) {\n if (qq.isArray(uuids)) {\n var entries = [];\n\n qq.each(uuids, function(idx, uuid) {\n entries.push(data[byUuid[uuid]]);\n });\n\n return entries;\n }\n\n return data[byUuid[uuids]];\n }\n\n function getDataByStatus(status) {\n var statusResults = [],\n statuses = [].concat(status);\n\n qq.each(statuses, function(index, statusEnum) {\n var statusResultIndexes = byStatus[statusEnum];\n\n if (statusResultIndexes !== undefined) {\n qq.each(statusResultIndexes, function(i, dataIndex) {\n statusResults.push(data[dataIndex]);\n });\n }\n });\n\n return statusResults;\n }\n\n qq.extend(this, {\n /**\n * Adds a new file to the data cache for tracking purposes.\n *\n * @param spec Data that describes this file. Possible properties are:\n *\n * - uuid: Initial UUID for this file.\n * - name: Initial name of this file.\n * - size: Size of this file, omit if this cannot be determined\n * - status: Initial `qq.status` for this file. Omit for `qq.status.SUBMITTING`.\n * - batchId: ID of the batch this file belongs to\n * - proxyGroupId: ID of the proxy group associated with this file\n * - onBeforeStatusChange(fileId): callback that is executed before the status change is broadcast\n *\n * @returns {number} Internal ID for this file.\n */\n addFile: function(spec) {\n var status = spec.status || qq.status.SUBMITTING,\n id = data.push({\n name: spec.name,\n originalName: spec.name,\n uuid: spec.uuid,\n size: spec.size == null ? -1 : spec.size,\n status: status,\n file: spec.file\n }) - 1;\n\n if (spec.batchId) {\n data[id].batchId = spec.batchId;\n\n if (byBatchId[spec.batchId] === undefined) {\n byBatchId[spec.batchId] = [];\n }\n byBatchId[spec.batchId].push(id);\n }\n\n if (spec.proxyGroupId) {\n data[id].proxyGroupId = spec.proxyGroupId;\n\n if (byProxyGroupId[spec.proxyGroupId] === undefined) {\n byProxyGroupId[spec.proxyGroupId] = [];\n }\n byProxyGroupId[spec.proxyGroupId].push(id);\n }\n\n data[id].id = id;\n byUuid[spec.uuid] = id;\n\n if (byStatus[status] === undefined) {\n byStatus[status] = [];\n }\n byStatus[status].push(id);\n\n spec.onBeforeStatusChange && spec.onBeforeStatusChange(id);\n uploaderProxy.onStatusChange(id, null, status);\n\n return id;\n },\n\n retrieve: function(optionalFilter) {\n if (qq.isObject(optionalFilter) && data.length) {\n if (optionalFilter.id !== undefined) {\n return getDataByIds(optionalFilter.id);\n }\n\n else if (optionalFilter.uuid !== undefined) {\n return getDataByUuids(optionalFilter.uuid);\n }\n\n else if (optionalFilter.status) {\n return getDataByStatus(optionalFilter.status);\n }\n }\n else {\n return qq.extend([], data, true);\n }\n },\n\n removeFileRef: function(id) {\n var record = getDataByIds(id);\n\n if (record) {\n delete record.file;\n }\n },\n\n reset: function() {\n data = [];\n byUuid = {};\n byStatus = {};\n byBatchId = {};\n },\n\n setStatus: function(id, newStatus) {\n var oldStatus = data[id].status,\n byStatusOldStatusIndex = qq.indexOf(byStatus[oldStatus], id);\n\n byStatus[oldStatus].splice(byStatusOldStatusIndex, 1);\n\n data[id].status = newStatus;\n\n if (byStatus[newStatus] === undefined) {\n byStatus[newStatus] = [];\n }\n byStatus[newStatus].push(id);\n\n uploaderProxy.onStatusChange(id, oldStatus, newStatus);\n },\n\n uuidChanged: function(id, newUuid) {\n var oldUuid = data[id].uuid;\n\n data[id].uuid = newUuid;\n byUuid[newUuid] = id;\n delete byUuid[oldUuid];\n },\n\n updateName: function(id, newName) {\n data[id].name = newName;\n },\n\n updateSize: function(id, newSize) {\n data[id].size = newSize;\n },\n\n // Only applicable if this file has a parent that we may want to reference later.\n setParentId: function(targetId, parentId) {\n data[targetId].parentId = parentId;\n },\n\n getIdsInProxyGroup: function(id) {\n var proxyGroupId = data[id].proxyGroupId;\n\n if (proxyGroupId) {\n return byProxyGroupId[proxyGroupId];\n }\n return [];\n },\n\n getIdsInBatch: function(id) {\n var batchId = data[id].batchId;\n\n return byBatchId[batchId];\n }\n });\n};\n\nqq.status = {\n SUBMITTING: \"submitting\",\n SUBMITTED: \"submitted\",\n REJECTED: \"rejected\",\n QUEUED: \"queued\",\n CANCELED: \"canceled\",\n PAUSED: \"paused\",\n UPLOADING: \"uploading\",\n UPLOAD_FINALIZING: \"upload finalizing\",\n UPLOAD_RETRYING: \"retrying upload\",\n UPLOAD_SUCCESSFUL: \"upload successful\",\n UPLOAD_FAILED: \"upload failed\",\n DELETE_FAILED: \"delete failed\",\n DELETING: \"deleting\",\n DELETED: \"deleted\"\n};\n","/*globals qq*/\n/**\n * Defines the public API for FineUploaderBasic mode.\n */\n(function() {\n \"use strict\";\n\n qq.basePublicApi = {\n // DEPRECATED - TODO REMOVE IN NEXT MAJOR RELEASE (replaced by addFiles)\n addBlobs: function(blobDataOrArray, params, endpoint) {\n this.addFiles(blobDataOrArray, params, endpoint);\n },\n\n addInitialFiles: function(cannedFileList) {\n var self = this;\n\n qq.each(cannedFileList, function(index, cannedFile) {\n self._addCannedFile(cannedFile);\n });\n },\n\n addFiles: function(data, params, endpoint) {\n this._maybeHandleIos8SafariWorkaround();\n\n var batchId = this._storedIds.length === 0 ? qq.getUniqueId() : this._currentBatchId,\n\n processBlob = qq.bind(function(blob) {\n this._handleNewFile({\n blob: blob,\n name: this._options.blobs.defaultName\n }, batchId, verifiedFiles);\n }, this),\n\n processBlobData = qq.bind(function(blobData) {\n this._handleNewFile(blobData, batchId, verifiedFiles);\n }, this),\n\n processCanvas = qq.bind(function(canvas) {\n var blob = qq.canvasToBlob(canvas);\n\n this._handleNewFile({\n blob: blob,\n name: this._options.blobs.defaultName + \".png\"\n }, batchId, verifiedFiles);\n }, this),\n\n processCanvasData = qq.bind(function(canvasData) {\n var normalizedQuality = canvasData.quality && canvasData.quality / 100,\n blob = qq.canvasToBlob(canvasData.canvas, canvasData.type, normalizedQuality);\n\n this._handleNewFile({\n blob: blob,\n name: canvasData.name\n }, batchId, verifiedFiles);\n }, this),\n\n processFileOrInput = qq.bind(function(fileOrInput) {\n if (qq.isInput(fileOrInput) && qq.supportedFeatures.ajaxUploading) {\n var files = Array.prototype.slice.call(fileOrInput.files),\n self = this;\n\n qq.each(files, function(idx, file) {\n self._handleNewFile(file, batchId, verifiedFiles);\n });\n }\n else {\n this._handleNewFile(fileOrInput, batchId, verifiedFiles);\n }\n }, this),\n\n normalizeData = function() {\n if (qq.isFileList(data)) {\n data = Array.prototype.slice.call(data);\n }\n data = [].concat(data);\n },\n\n self = this,\n verifiedFiles = [];\n\n this._currentBatchId = batchId;\n\n if (data) {\n normalizeData();\n\n qq.each(data, function(idx, fileContainer) {\n if (qq.isFileOrInput(fileContainer)) {\n processFileOrInput(fileContainer);\n }\n else if (qq.isBlob(fileContainer)) {\n processBlob(fileContainer);\n }\n else if (qq.isObject(fileContainer)) {\n if (fileContainer.blob && fileContainer.name) {\n processBlobData(fileContainer);\n }\n else if (fileContainer.canvas && fileContainer.name) {\n processCanvasData(fileContainer);\n }\n }\n else if (fileContainer.tagName && fileContainer.tagName.toLowerCase() === \"canvas\") {\n processCanvas(fileContainer);\n }\n else {\n self.log(fileContainer + \" is not a valid file container! Ignoring!\", \"warn\");\n }\n });\n\n this.log(\"Received \" + verifiedFiles.length + \" files.\");\n this._prepareItemsForUpload(verifiedFiles, params, endpoint);\n }\n },\n\n cancel: function(id) {\n var uploadData = this._uploadData.retrieve({id: id});\n\n if (uploadData && uploadData.status === qq.status.UPLOAD_FINALIZING) {\n this.log(qq.format(\"Ignoring cancel for file ID {} ({}). Finalizing upload.\", id, this.getName(id)), \"error\");\n }\n else {\n this._handler.cancel(id);\n }\n },\n\n cancelAll: function() {\n var storedIdsCopy = [],\n self = this;\n\n qq.extend(storedIdsCopy, this._storedIds);\n qq.each(storedIdsCopy, function(idx, storedFileId) {\n self.cancel(storedFileId);\n });\n\n this._handler.cancelAll();\n },\n\n clearStoredFiles: function() {\n this._storedIds = [];\n },\n\n continueUpload: function(id) {\n var uploadData = this._uploadData.retrieve({id: id});\n\n if (!qq.supportedFeatures.pause || !this._options.chunking.enabled) {\n return false;\n }\n\n if (uploadData.status === qq.status.PAUSED) {\n this.log(qq.format(\"Paused file ID {} ({}) will be continued. Not paused.\", id, this.getName(id)));\n this._uploadFile(id);\n return true;\n }\n else {\n this.log(qq.format(\"Ignoring continue for file ID {} ({}). Not paused.\", id, this.getName(id)), \"error\");\n }\n\n return false;\n },\n\n deleteFile: function(id) {\n return this._onSubmitDelete(id);\n },\n\n // TODO document?\n doesExist: function(fileOrBlobId) {\n return this._handler.isValid(fileOrBlobId);\n },\n\n // Generate a variable size thumbnail on an img or canvas,\n // returning a promise that is fulfilled when the attempt completes.\n // Thumbnail can either be based off of a URL for an image returned\n // by the server in the upload response, or the associated `Blob`.\n drawThumbnail: function(fileId, imgOrCanvas, maxSize, fromServer, customResizeFunction) {\n var promiseToReturn = new qq.Promise(),\n fileOrUrl, options;\n\n if (this._imageGenerator) {\n fileOrUrl = this._thumbnailUrls[fileId];\n options = {\n customResizeFunction: customResizeFunction,\n maxSize: maxSize > 0 ? maxSize : null,\n scale: maxSize > 0\n };\n\n // If client-side preview generation is possible\n // and we are not specifically looking for the image URl returned by the server...\n if (!fromServer && qq.supportedFeatures.imagePreviews) {\n fileOrUrl = this.getFile(fileId);\n }\n\n /* jshint eqeqeq:false,eqnull:true */\n if (fileOrUrl == null) {\n promiseToReturn.failure({container: imgOrCanvas, error: \"File or URL not found.\"});\n }\n else {\n this._imageGenerator.generate(fileOrUrl, imgOrCanvas, options).then(\n function success(modifiedContainer) {\n promiseToReturn.success(modifiedContainer);\n },\n\n function failure(container, reason) {\n promiseToReturn.failure({container: container, error: reason || \"Problem generating thumbnail\"});\n }\n );\n }\n }\n else {\n promiseToReturn.failure({container: imgOrCanvas, error: \"Missing image generator module\"});\n }\n\n return promiseToReturn;\n },\n\n getButton: function(fileId) {\n return this._getButton(this._buttonIdsForFileIds[fileId]);\n },\n\n getEndpoint: function(fileId) {\n return this._endpointStore.get(fileId);\n },\n\n getFile: function(fileOrBlobId) {\n var file = this._handler.getFile(fileOrBlobId);\n var uploadDataRecord;\n\n if (!file) {\n uploadDataRecord = this._uploadData.retrieve({id: fileOrBlobId});\n\n if (uploadDataRecord) {\n file = uploadDataRecord.file;\n }\n }\n\n return file || null;\n },\n\n getInProgress: function() {\n return this._uploadData.retrieve({\n status: [\n qq.status.UPLOADING,\n qq.status.UPLOAD_RETRYING,\n qq.status.QUEUED\n ]\n }).length;\n },\n\n getName: function(id) {\n return this._uploadData.retrieve({id: id}).name;\n },\n\n // Parent ID for a specific file, or null if this is the parent, or if it has no parent.\n getParentId: function(id) {\n var uploadDataEntry = this.getUploads({id: id}),\n parentId = null;\n\n if (uploadDataEntry) {\n if (uploadDataEntry.parentId !== undefined) {\n parentId = uploadDataEntry.parentId;\n }\n }\n\n return parentId;\n },\n\n getResumableFilesData: function() {\n return this._handler.getResumableFilesData();\n },\n\n getSize: function(id) {\n return this._uploadData.retrieve({id: id}).size;\n },\n\n getNetUploads: function() {\n return this._netUploaded;\n },\n\n getRemainingAllowedItems: function() {\n var allowedItems = this._currentItemLimit;\n\n if (allowedItems > 0) {\n return allowedItems - this._netUploadedOrQueued;\n }\n\n return null;\n },\n\n getUploads: function(optionalFilter) {\n return this._uploadData.retrieve(optionalFilter);\n },\n\n getUuid: function(id) {\n return this._uploadData.retrieve({id: id}).uuid;\n },\n\n isResumable: function(id) {\n return this._handler.hasResumeRecord(id);\n },\n\n log: function(str, level) {\n if (this._options.debug && (!level || level === \"info\")) {\n qq.log(\"[Fine Uploader \" + qq.version + \"] \" + str);\n }\n else if (level && level !== \"info\") {\n qq.log(\"[Fine Uploader \" + qq.version + \"] \" + str, level);\n\n }\n },\n\n pauseUpload: function(id) {\n var uploadData = this._uploadData.retrieve({id: id});\n\n if (!qq.supportedFeatures.pause || !this._options.chunking.enabled) {\n return false;\n }\n\n // Pause only really makes sense if the file is uploading or retrying\n if (qq.indexOf([qq.status.UPLOADING, qq.status.UPLOAD_RETRYING], uploadData.status) >= 0) {\n if (this._handler.pause(id)) {\n this._uploadData.setStatus(id, qq.status.PAUSED);\n return true;\n }\n else {\n this.log(qq.format(\"Unable to pause file ID {} ({}).\", id, this.getName(id)), \"error\");\n }\n }\n else {\n this.log(qq.format(\"Ignoring pause for file ID {} ({}). Not in progress.\", id, this.getName(id)), \"error\");\n }\n\n return false;\n },\n\n removeFileRef: function(id) {\n this._handler.expunge(id);\n this._uploadData.removeFileRef(id);\n },\n\n reset: function() {\n this.log(\"Resetting uploader...\");\n\n this._handler.reset();\n this._storedIds = [];\n this._autoRetries = [];\n this._retryTimeouts = [];\n this._preventRetries = [];\n this._thumbnailUrls = [];\n\n qq.each(this._buttons, function(idx, button) {\n button.reset();\n });\n\n this._paramsStore.reset();\n this._endpointStore.reset();\n this._netUploadedOrQueued = 0;\n this._netUploaded = 0;\n this._uploadData.reset();\n this._buttonIdsForFileIds = [];\n\n this._pasteHandler && this._pasteHandler.reset();\n this._options.session.refreshOnReset && this._refreshSessionData();\n\n this._succeededSinceLastAllComplete = [];\n this._failedSinceLastAllComplete = [];\n\n this._totalProgress && this._totalProgress.reset();\n\n this._customResumeDataStore.reset();\n },\n\n retry: function(id) {\n return this._manualRetry(id);\n },\n\n scaleImage: function(id, specs) {\n var self = this;\n\n return qq.Scaler.prototype.scaleImage(id, specs, {\n log: qq.bind(self.log, self),\n getFile: qq.bind(self.getFile, self),\n uploadData: self._uploadData\n });\n },\n\n setCustomHeaders: function(headers, id) {\n this._customHeadersStore.set(headers, id);\n },\n\n setCustomResumeData: function(id, data) {\n this._customResumeDataStore.set(data, id);\n },\n\n setDeleteFileCustomHeaders: function(headers, id) {\n this._deleteFileCustomHeadersStore.set(headers, id);\n },\n\n setDeleteFileEndpoint: function(endpoint, id) {\n this._deleteFileEndpointStore.set(endpoint, id);\n },\n\n setDeleteFileParams: function(params, id) {\n this._deleteFileParamsStore.set(params, id);\n },\n\n // Re-sets the default endpoint, an endpoint for a specific file, or an endpoint for a specific button\n setEndpoint: function(endpoint, id) {\n this._endpointStore.set(endpoint, id);\n },\n\n setForm: function(elementOrId) {\n this._updateFormSupportAndParams(elementOrId);\n },\n\n setItemLimit: function(newItemLimit) {\n this._currentItemLimit = newItemLimit;\n },\n\n setName: function(id, newName) {\n this._uploadData.updateName(id, newName);\n },\n\n setParams: function(params, id) {\n this._paramsStore.set(params, id);\n },\n\n setUuid: function(id, newUuid) {\n return this._uploadData.uuidChanged(id, newUuid);\n },\n\n /**\n * Expose the internal status of a file id to the public api for manual state changes\n * @public\n *\n * @param {Number} id,\n * @param {String} newStatus\n *\n * @todo Implement the remaining methods\n */\n setStatus: function(id, newStatus) {\n var fileRecord = this.getUploads({id: id});\n if (!fileRecord) {\n throw new qq.Error(id + \" is not a valid file ID.\");\n }\n\n switch (newStatus) {\n case qq.status.DELETED:\n this._onDeleteComplete(id, null, false);\n break;\n case qq.status.DELETE_FAILED:\n this._onDeleteComplete(id, null, true);\n break;\n default:\n var errorMessage = \"Method setStatus called on '\" + name + \"' not implemented yet for \" + newStatus;\n this.log(errorMessage);\n throw new qq.Error(errorMessage);\n }\n },\n\n uploadStoredFiles: function() {\n if (this._storedIds.length === 0) {\n this._itemError(\"noFilesError\");\n }\n else {\n this._uploadStoredFiles();\n }\n }\n };\n\n /**\n * Defines the private (internal) API for FineUploaderBasic mode.\n */\n qq.basePrivateApi = {\n // Updates internal state with a file record (not backed by a live file). Returns the assigned ID.\n _addCannedFile: function(sessionData) {\n var self = this;\n\n return this._uploadData.addFile({\n uuid: sessionData.uuid,\n name: sessionData.name,\n size: sessionData.size,\n status: qq.status.UPLOAD_SUCCESSFUL,\n onBeforeStatusChange: function(id) {\n sessionData.deleteFileEndpoint && self.setDeleteFileEndpoint(sessionData.deleteFileEndpoint, id);\n sessionData.deleteFileParams && self.setDeleteFileParams(sessionData.deleteFileParams, id);\n\n if (sessionData.thumbnailUrl) {\n self._thumbnailUrls[id] = sessionData.thumbnailUrl;\n }\n\n self._netUploaded++;\n self._netUploadedOrQueued++;\n }\n });\n },\n\n _annotateWithButtonId: function(file, associatedInput) {\n if (qq.isFile(file)) {\n file.qqButtonId = this._getButtonId(associatedInput);\n }\n },\n\n _batchError: function(message) {\n this._options.callbacks.onError(null, null, message, undefined);\n },\n\n _createDeleteHandler: function() {\n var self = this;\n\n return new qq.DeleteFileAjaxRequester({\n method: this._options.deleteFile.method.toUpperCase(),\n maxConnections: this._options.maxConnections,\n uuidParamName: this._options.request.uuidName,\n customHeaders: this._deleteFileCustomHeadersStore,\n paramsStore: this._deleteFileParamsStore,\n endpointStore: this._deleteFileEndpointStore,\n cors: this._options.cors,\n log: qq.bind(self.log, self),\n onDelete: function(id) {\n self._onDelete(id);\n self._options.callbacks.onDelete(id);\n },\n onDeleteComplete: function(id, xhrOrXdr, isError) {\n self._onDeleteComplete(id, xhrOrXdr, isError);\n self._options.callbacks.onDeleteComplete(id, xhrOrXdr, isError);\n }\n\n });\n },\n\n _createPasteHandler: function() {\n var self = this;\n\n return new qq.PasteSupport({\n targetElement: this._options.paste.targetElement,\n callbacks: {\n log: qq.bind(self.log, self),\n pasteReceived: function(blob) {\n self._handleCheckedCallback({\n name: \"onPasteReceived\",\n callback: qq.bind(self._options.callbacks.onPasteReceived, self, blob),\n onSuccess: qq.bind(self._handlePasteSuccess, self, blob),\n identifier: \"pasted image\"\n });\n }\n }\n });\n },\n\n _createStore: function(initialValue, _readOnlyValues_) {\n var store = {},\n catchall = initialValue,\n perIdReadOnlyValues = {},\n readOnlyValues = _readOnlyValues_,\n copy = function(orig) {\n if (qq.isObject(orig)) {\n return qq.extend({}, orig);\n }\n return orig;\n },\n getReadOnlyValues = function() {\n if (qq.isFunction(readOnlyValues)) {\n return readOnlyValues();\n }\n return readOnlyValues;\n },\n includeReadOnlyValues = function(id, existing) {\n if (readOnlyValues && qq.isObject(existing)) {\n qq.extend(existing, getReadOnlyValues());\n }\n\n if (perIdReadOnlyValues[id]) {\n qq.extend(existing, perIdReadOnlyValues[id]);\n }\n };\n\n return {\n set: function(val, id) {\n /*jshint eqeqeq: true, eqnull: true*/\n if (id == null) {\n store = {};\n catchall = copy(val);\n }\n else {\n store[id] = copy(val);\n }\n },\n\n get: function(id) {\n var values;\n\n /*jshint eqeqeq: true, eqnull: true*/\n if (id != null && store[id]) {\n values = store[id];\n }\n else {\n values = copy(catchall);\n }\n\n includeReadOnlyValues(id, values);\n\n return copy(values);\n },\n\n addReadOnly: function(id, values) {\n // Only applicable to Object stores\n if (qq.isObject(store)) {\n // If null ID, apply readonly values to all files\n if (id === null) {\n if (qq.isFunction(values)) {\n readOnlyValues = values;\n }\n else {\n readOnlyValues = readOnlyValues || {};\n qq.extend(readOnlyValues, values);\n }\n }\n else {\n perIdReadOnlyValues[id] = perIdReadOnlyValues[id] || {};\n qq.extend(perIdReadOnlyValues[id], values);\n }\n }\n },\n\n remove: function(fileId) {\n return delete store[fileId];\n },\n\n reset: function() {\n store = {};\n perIdReadOnlyValues = {};\n catchall = initialValue;\n }\n };\n },\n\n _createUploadDataTracker: function() {\n var self = this;\n\n return new qq.UploadData({\n getName: function(id) {\n return self.getName(id);\n },\n getUuid: function(id) {\n return self.getUuid(id);\n },\n getSize: function(id) {\n return self.getSize(id);\n },\n onStatusChange: function(id, oldStatus, newStatus) {\n self._onUploadStatusChange(id, oldStatus, newStatus);\n self._options.callbacks.onStatusChange(id, oldStatus, newStatus);\n self._maybeAllComplete(id, newStatus);\n\n if (self._totalProgress) {\n setTimeout(function() {\n self._totalProgress.onStatusChange(id, oldStatus, newStatus);\n }, 0);\n }\n }\n });\n },\n\n /**\n * Generate a tracked upload button.\n *\n * @param spec Object containing a required `element` property\n * along with optional `multiple`, `accept`, and `folders`.\n * @returns {qq.UploadButton}\n * @private\n */\n _createUploadButton: function(spec) {\n var self = this,\n acceptFiles = spec.accept || this._options.validation.acceptFiles,\n allowedExtensions = spec.allowedExtensions || this._options.validation.allowedExtensions,\n button;\n\n function allowMultiple() {\n if (qq.supportedFeatures.ajaxUploading) {\n // Workaround for bug in iOS7+ (see #1039)\n if (self._options.workarounds.iosEmptyVideos &&\n qq.ios() &&\n !qq.ios6() &&\n self._isAllowedExtension(allowedExtensions, \".mov\")) {\n\n return false;\n }\n\n if (spec.multiple === undefined) {\n return self._options.multiple;\n }\n\n return spec.multiple;\n }\n\n return false;\n }\n\n button = new qq.UploadButton({\n acceptFiles: acceptFiles,\n element: spec.element,\n focusClass: this._options.classes.buttonFocus,\n folders: spec.folders,\n hoverClass: this._options.classes.buttonHover,\n ios8BrowserCrashWorkaround: this._options.workarounds.ios8BrowserCrash,\n multiple: allowMultiple(),\n name: this._options.request.inputName,\n onChange: function(input) {\n self._onInputChange(input);\n },\n title: spec.title == null ? this._options.text.fileInputTitle : spec.title\n });\n\n this._disposeSupport.addDisposer(function() {\n button.dispose();\n });\n\n self._buttons.push(button);\n\n return button;\n },\n\n _createUploadHandler: function(additionalOptions, namespace) {\n var self = this,\n lastOnProgress = {},\n options = {\n debug: this._options.debug,\n maxConnections: this._options.maxConnections,\n cors: this._options.cors,\n paramsStore: this._paramsStore,\n endpointStore: this._endpointStore,\n chunking: this._options.chunking,\n resume: this._options.resume,\n blobs: this._options.blobs,\n log: qq.bind(self.log, self),\n preventRetryParam: this._options.retry.preventRetryResponseProperty,\n onProgress: function(id, name, loaded, total) {\n if (loaded < 0 || total < 0) {\n return;\n }\n\n if (lastOnProgress[id]) {\n if (lastOnProgress[id].loaded !== loaded || lastOnProgress[id].total !== total) {\n self._onProgress(id, name, loaded, total);\n self._options.callbacks.onProgress(id, name, loaded, total);\n }\n }\n else {\n self._onProgress(id, name, loaded, total);\n self._options.callbacks.onProgress(id, name, loaded, total);\n }\n\n lastOnProgress[id] = {loaded: loaded, total: total};\n\n },\n onComplete: function(id, name, result, xhr) {\n delete lastOnProgress[id];\n\n var status = self.getUploads({id: id}).status,\n retVal;\n\n // This is to deal with some observed cases where the XHR readyStateChange handler is\n // invoked by the browser multiple times for the same XHR instance with the same state\n // readyState value. Higher level: don't invoke complete-related code if we've already\n // done this.\n if (status === qq.status.UPLOAD_SUCCESSFUL || status === qq.status.UPLOAD_FAILED) {\n return;\n }\n\n retVal = self._onComplete(id, name, result, xhr);\n\n // If the internal `_onComplete` handler returns a promise, don't invoke the `onComplete` callback\n // until the promise has been fulfilled.\n if (retVal instanceof qq.Promise) {\n retVal.done(function() {\n self._options.callbacks.onComplete(id, name, result, xhr);\n });\n }\n else {\n self._options.callbacks.onComplete(id, name, result, xhr);\n }\n },\n onCancel: function(id, name, cancelFinalizationEffort) {\n var promise = new qq.Promise();\n\n self._handleCheckedCallback({\n name: \"onCancel\",\n callback: qq.bind(self._options.callbacks.onCancel, self, id, name),\n onFailure: promise.failure,\n onSuccess: function() {\n cancelFinalizationEffort.then(function() {\n self._onCancel(id, name);\n });\n\n promise.success();\n },\n identifier: id\n });\n\n return promise;\n },\n onUploadPrep: qq.bind(this._onUploadPrep, this),\n onUpload: function(id, name) {\n self._onUpload(id, name);\n var onUploadResult = self._options.callbacks.onUpload(id, name);\n\n if (qq.isGenericPromise(onUploadResult)) {\n self.log(qq.format(\"onUpload for {} returned a Promise - waiting for resolution.\", id));\n return onUploadResult;\n }\n\n return new qq.Promise().success();\n },\n onUploadChunk: function(id, name, chunkData) {\n self._onUploadChunk(id, chunkData);\n var onUploadChunkResult = self._options.callbacks.onUploadChunk(id, name, chunkData);\n\n if (qq.isGenericPromise(onUploadChunkResult)) {\n self.log(qq.format(\"onUploadChunk for {}.{} returned a Promise - waiting for resolution.\", id, chunkData.partIndex));\n return onUploadChunkResult;\n }\n\n return new qq.Promise().success();\n },\n onUploadChunkSuccess: function(id, chunkData, result, xhr) {\n self._onUploadChunkSuccess(id, chunkData);\n self._options.callbacks.onUploadChunkSuccess.apply(self, arguments);\n },\n onResume: function(id, name, chunkData, customResumeData) {\n return self._options.callbacks.onResume(id, name, chunkData, customResumeData);\n },\n onAutoRetry: function(id, name, responseJSON, xhr) {\n return self._onAutoRetry.apply(self, arguments);\n },\n onUuidChanged: function(id, newUuid) {\n self.log(\"Server requested UUID change from '\" + self.getUuid(id) + \"' to '\" + newUuid + \"'\");\n self.setUuid(id, newUuid);\n },\n getName: qq.bind(self.getName, self),\n getUuid: qq.bind(self.getUuid, self),\n getSize: qq.bind(self.getSize, self),\n setSize: qq.bind(self._setSize, self),\n getDataByUuid: function(uuid) {\n return self.getUploads({uuid: uuid});\n },\n isQueued: function(id) {\n var status = self.getUploads({id: id}).status;\n return status === qq.status.QUEUED ||\n status === qq.status.SUBMITTED ||\n status === qq.status.UPLOAD_RETRYING ||\n status === qq.status.PAUSED;\n },\n getIdsInProxyGroup: self._uploadData.getIdsInProxyGroup,\n getIdsInBatch: self._uploadData.getIdsInBatch,\n isInProgress: function(id) {\n return self.getUploads({id: id}).status === qq.status.UPLOADING;\n },\n getCustomResumeData: qq.bind(self._getCustomResumeData, self),\n setStatus: function(id, status) {\n self._uploadData.setStatus(id, status);\n }\n };\n\n qq.each(this._options.request, function(prop, val) {\n options[prop] = val;\n });\n\n options.customHeaders = this._customHeadersStore;\n\n if (additionalOptions) {\n qq.each(additionalOptions, function(key, val) {\n options[key] = val;\n });\n }\n\n return new qq.UploadHandlerController(options, namespace);\n },\n\n _fileOrBlobRejected: function(id) {\n this._netUploadedOrQueued--;\n this._uploadData.setStatus(id, qq.status.REJECTED);\n },\n\n _formatSize: function(bytes) {\n if (bytes === 0) {\n return bytes + this._options.text.sizeSymbols[0];\n }\n var i = -1;\n do {\n bytes = bytes / 1000;\n i++;\n } while (bytes > 999);\n\n return Math.max(bytes, 0.1).toFixed(1) + this._options.text.sizeSymbols[i];\n },\n\n // Creates an internal object that tracks various properties of each extra button,\n // and then actually creates the extra button.\n _generateExtraButtonSpecs: function() {\n var self = this;\n\n this._extraButtonSpecs = {};\n\n qq.each(this._options.extraButtons, function(idx, extraButtonOptionEntry) {\n var multiple = extraButtonOptionEntry.multiple,\n validation = qq.extend({}, self._options.validation, true),\n extraButtonSpec = qq.extend({}, extraButtonOptionEntry);\n\n if (multiple === undefined) {\n multiple = self._options.multiple;\n }\n\n if (extraButtonSpec.validation) {\n qq.extend(validation, extraButtonOptionEntry.validation, true);\n }\n\n qq.extend(extraButtonSpec, {\n multiple: multiple,\n validation: validation\n }, true);\n\n self._initExtraButton(extraButtonSpec);\n });\n },\n\n _getButton: function(buttonId) {\n var extraButtonsSpec = this._extraButtonSpecs[buttonId];\n\n if (extraButtonsSpec) {\n return extraButtonsSpec.element;\n }\n else if (buttonId === this._defaultButtonId) {\n return this._options.button;\n }\n },\n\n /**\n * Gets the internally used tracking ID for a button.\n *\n * @param buttonOrFileInputOrFile `File`, ` `, or a button container element\n * @returns {*} The button's ID, or undefined if no ID is recoverable\n * @private\n */\n _getButtonId: function(buttonOrFileInputOrFile) {\n var inputs, fileInput,\n fileBlobOrInput = buttonOrFileInputOrFile;\n\n // We want the reference file/blob here if this is a proxy (a file that will be generated on-demand later)\n if (fileBlobOrInput instanceof qq.BlobProxy) {\n fileBlobOrInput = fileBlobOrInput.referenceBlob;\n }\n\n // If the item is a `Blob` it will never be associated with a button or drop zone.\n if (fileBlobOrInput && !qq.isBlob(fileBlobOrInput)) {\n if (qq.isFile(fileBlobOrInput)) {\n return fileBlobOrInput.qqButtonId;\n }\n else if (fileBlobOrInput.tagName.toLowerCase() === \"input\" &&\n fileBlobOrInput.type.toLowerCase() === \"file\") {\n\n return fileBlobOrInput.getAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME);\n }\n\n inputs = fileBlobOrInput.getElementsByTagName(\"input\");\n\n qq.each(inputs, function(idx, input) {\n if (input.getAttribute(\"type\") === \"file\") {\n fileInput = input;\n return false;\n }\n });\n\n if (fileInput) {\n return fileInput.getAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME);\n }\n }\n },\n\n _getCustomResumeData: function(fileId) {\n return this._customResumeDataStore.get(fileId);\n },\n\n _getNotFinished: function() {\n return this._uploadData.retrieve({\n status: [\n qq.status.UPLOADING,\n qq.status.UPLOAD_RETRYING,\n qq.status.QUEUED,\n qq.status.SUBMITTING,\n qq.status.SUBMITTED,\n qq.status.PAUSED\n ]\n }).length;\n },\n\n // Get the validation options for this button. Could be the default validation option\n // or a specific one assigned to this particular button.\n _getValidationBase: function(buttonId) {\n var extraButtonSpec = this._extraButtonSpecs[buttonId];\n\n return extraButtonSpec ? extraButtonSpec.validation : this._options.validation;\n },\n\n _getValidationDescriptor: function(fileWrapper) {\n if (fileWrapper.file instanceof qq.BlobProxy) {\n return {\n name: qq.getFilename(fileWrapper.file.referenceBlob),\n size: fileWrapper.file.referenceBlob.size\n };\n }\n\n return {\n name: this.getUploads({id: fileWrapper.id}).name,\n size: this.getUploads({id: fileWrapper.id}).size\n };\n },\n\n _getValidationDescriptors: function(fileWrappers) {\n var self = this,\n fileDescriptors = [];\n\n qq.each(fileWrappers, function(idx, fileWrapper) {\n fileDescriptors.push(self._getValidationDescriptor(fileWrapper));\n });\n\n return fileDescriptors;\n },\n\n // Allows camera access on either the default or an extra button for iOS devices.\n _handleCameraAccess: function() {\n if (this._options.camera.ios && qq.ios()) {\n var acceptIosCamera = \"image/*;capture=camera\",\n button = this._options.camera.button,\n buttonId = button ? this._getButtonId(button) : this._defaultButtonId,\n optionRoot = this._options;\n\n // If we are not targeting the default button, it is an \"extra\" button\n if (buttonId && buttonId !== this._defaultButtonId) {\n optionRoot = this._extraButtonSpecs[buttonId];\n }\n\n // Camera access won't work in iOS if the `multiple` attribute is present on the file input\n optionRoot.multiple = false;\n\n // update the options\n if (optionRoot.validation.acceptFiles === null) {\n optionRoot.validation.acceptFiles = acceptIosCamera;\n }\n else {\n optionRoot.validation.acceptFiles += \",\" + acceptIosCamera;\n }\n\n // update the already-created button\n qq.each(this._buttons, function(idx, button) {\n if (button.getButtonId() === buttonId) {\n button.setMultiple(optionRoot.multiple);\n button.setAcceptFiles(optionRoot.acceptFiles);\n\n return false;\n }\n });\n }\n },\n\n _handleCheckedCallback: function(details) {\n var self = this,\n callbackRetVal = details.callback();\n\n if (qq.isGenericPromise(callbackRetVal)) {\n this.log(details.name + \" - waiting for \" + details.name + \" promise to be fulfilled for \" + details.identifier);\n return callbackRetVal.then(\n function(successParam) {\n self.log(details.name + \" promise success for \" + details.identifier);\n details.onSuccess(successParam);\n },\n function() {\n if (details.onFailure) {\n self.log(details.name + \" promise failure for \" + details.identifier);\n details.onFailure();\n }\n else {\n self.log(details.name + \" promise failure for \" + details.identifier);\n }\n });\n }\n\n if (callbackRetVal !== false) {\n details.onSuccess(callbackRetVal);\n }\n else {\n if (details.onFailure) {\n this.log(details.name + \" - return value was 'false' for \" + details.identifier + \". Invoking failure callback.\");\n details.onFailure();\n }\n else {\n this.log(details.name + \" - return value was 'false' for \" + details.identifier + \". Will not proceed.\");\n }\n }\n\n return callbackRetVal;\n },\n\n // Updates internal state when a new file has been received, and adds it along with its ID to a passed array.\n _handleNewFile: function(file, batchId, newFileWrapperList) {\n var self = this,\n uuid = qq.getUniqueId(),\n size = -1,\n name = qq.getFilename(file),\n actualFile = file.blob || file,\n handler = this._customNewFileHandler ?\n this._customNewFileHandler :\n qq.bind(self._handleNewFileGeneric, self);\n\n if (!qq.isInput(actualFile) && actualFile.size >= 0) {\n size = actualFile.size;\n }\n\n handler(actualFile, name, uuid, size, newFileWrapperList, batchId, this._options.request.uuidName, {\n uploadData: self._uploadData,\n paramsStore: self._paramsStore,\n addFileToHandler: function(id, file) {\n self._handler.add(id, file);\n self._netUploadedOrQueued++;\n self._trackButton(id);\n }\n });\n },\n\n _handleNewFileGeneric: function(file, name, uuid, size, fileList, batchId) {\n var id = this._uploadData.addFile({\n uuid: uuid,\n name: name,\n size: size,\n batchId: batchId,\n file: file\n });\n\n this._handler.add(id, file);\n\n this._trackButton(id);\n\n this._netUploadedOrQueued++;\n\n fileList.push({id: id, file: file});\n },\n\n _handlePasteSuccess: function(blob, extSuppliedName) {\n var extension = blob.type.split(\"/\")[1],\n name = extSuppliedName;\n\n /*jshint eqeqeq: true, eqnull: true*/\n if (name == null) {\n name = this._options.paste.defaultName;\n }\n\n name += \".\" + extension;\n\n this.addFiles({\n name: name,\n blob: blob\n });\n },\n\n _handleDeleteSuccess: function(id) {\n if (this.getUploads({id: id}).status !== qq.status.DELETED) {\n var name = this.getName(id);\n\n this._netUploadedOrQueued--;\n this._netUploaded--;\n this._handler.expunge(id);\n this._uploadData.setStatus(id, qq.status.DELETED);\n this.log(\"Delete request for '\" + name + \"' has succeeded.\");\n }\n },\n\n _handleDeleteFailed: function(id, xhrOrXdr) {\n var name = this.getName(id);\n\n this._uploadData.setStatus(id, qq.status.DELETE_FAILED);\n this.log(\"Delete request for '\" + name + \"' has failed.\", \"error\");\n\n // Check first if xhrOrXdr is actually passed or valid\n // For error reporting, we only have access to the response status if this is not\n // an `XDomainRequest`.\n if (!xhrOrXdr || xhrOrXdr.withCredentials === undefined) {\n this._options.callbacks.onError(id, name, \"Delete request failed\", xhrOrXdr);\n }\n else {\n this._options.callbacks.onError(id, name, \"Delete request failed with response code \" + xhrOrXdr.status, xhrOrXdr);\n }\n },\n\n // Creates an extra button element\n _initExtraButton: function(spec) {\n var button = this._createUploadButton({\n accept: spec.validation.acceptFiles,\n allowedExtensions: spec.validation.allowedExtensions,\n element: spec.element,\n folders: spec.folders,\n multiple: spec.multiple,\n title: spec.fileInputTitle\n });\n\n this._extraButtonSpecs[button.getButtonId()] = spec;\n },\n\n _initFormSupportAndParams: function() {\n this._formSupport = qq.FormSupport && new qq.FormSupport(\n this._options.form, qq.bind(this.uploadStoredFiles, this), qq.bind(this.log, this)\n );\n\n if (this._formSupport && this._formSupport.attachedToForm) {\n this._paramsStore = this._createStore(\n this._options.request.params, this._formSupport.getFormInputsAsObject\n );\n\n this._options.autoUpload = this._formSupport.newAutoUpload;\n if (this._formSupport.newEndpoint) {\n this._options.request.endpoint = this._formSupport.newEndpoint;\n }\n }\n else {\n this._paramsStore = this._createStore(this._options.request.params);\n }\n },\n\n _isDeletePossible: function() {\n if (!qq.DeleteFileAjaxRequester || !this._options.deleteFile.enabled) {\n return false;\n }\n\n if (this._options.cors.expected) {\n if (qq.supportedFeatures.deleteFileCorsXhr) {\n return true;\n }\n\n if (qq.supportedFeatures.deleteFileCorsXdr && this._options.cors.allowXdr) {\n return true;\n }\n\n return false;\n }\n\n return true;\n },\n\n _isAllowedExtension: function(allowed, fileName) {\n var valid = false;\n\n if (!allowed.length) {\n return true;\n }\n\n qq.each(allowed, function(idx, allowedExt) {\n /**\n * If an argument is not a string, ignore it. Added when a possible issue with MooTools hijacking the\n * `allowedExtensions` array was discovered. See case #735 in the issue tracker for more details.\n */\n if (qq.isString(allowedExt)) {\n /*jshint eqeqeq: true, eqnull: true*/\n var extRegex = new RegExp(\"\\\\.\" + allowedExt + \"$\", \"i\");\n\n if (fileName.match(extRegex) != null) {\n valid = true;\n return false;\n }\n }\n });\n\n return valid;\n },\n\n /**\n * Constructs and returns a message that describes an item/file error. Also calls `onError` callback.\n *\n * @param code REQUIRED - a code that corresponds to a stock message describing this type of error\n * @param maybeNameOrNames names of the items that have failed, if applicable\n * @param item `File`, `Blob`, or ` `\n * @private\n */\n _itemError: function(code, maybeNameOrNames, item) {\n var message = this._options.messages[code],\n allowedExtensions = [],\n names = [].concat(maybeNameOrNames),\n name = names[0],\n buttonId = this._getButtonId(item),\n validationBase = this._getValidationBase(buttonId),\n extensionsForMessage, placeholderMatch;\n\n function r(name, replacement) { message = message.replace(name, replacement); }\n\n qq.each(validationBase.allowedExtensions, function(idx, allowedExtension) {\n /**\n * If an argument is not a string, ignore it. Added when a possible issue with MooTools hijacking the\n * `allowedExtensions` array was discovered. See case #735 in the issue tracker for more details.\n */\n if (qq.isString(allowedExtension)) {\n allowedExtensions.push(allowedExtension);\n }\n });\n\n extensionsForMessage = allowedExtensions.join(\", \").toLowerCase();\n\n r(\"{file}\", this._options.formatFileName(name));\n r(\"{extensions}\", extensionsForMessage);\n r(\"{sizeLimit}\", this._formatSize(validationBase.sizeLimit));\n r(\"{minSizeLimit}\", this._formatSize(validationBase.minSizeLimit));\n\n placeholderMatch = message.match(/(\\{\\w+\\})/g);\n if (placeholderMatch !== null) {\n qq.each(placeholderMatch, function(idx, placeholder) {\n r(placeholder, names[idx]);\n });\n }\n\n this._options.callbacks.onError(null, name, message, undefined);\n\n return message;\n },\n\n /**\n * Conditionally orders a manual retry of a failed upload.\n *\n * @param id File ID of the failed upload\n * @param callback Optional callback to invoke if a retry is prudent.\n * In lieu of asking the upload handler to retry.\n * @returns {boolean} true if a manual retry will occur\n * @private\n */\n _manualRetry: function(id, callback) {\n if (this._onBeforeManualRetry(id)) {\n this._netUploadedOrQueued++;\n this._uploadData.setStatus(id, qq.status.UPLOAD_RETRYING);\n\n if (callback) {\n callback(id);\n }\n else {\n this._handler.retry(id);\n }\n\n return true;\n }\n },\n\n _maybeAllComplete: function(id, status) {\n var self = this,\n notFinished = this._getNotFinished();\n\n if (status === qq.status.UPLOAD_SUCCESSFUL) {\n this._succeededSinceLastAllComplete.push(id);\n }\n else if (status === qq.status.UPLOAD_FAILED) {\n this._failedSinceLastAllComplete.push(id);\n }\n\n if (notFinished === 0 &&\n (this._succeededSinceLastAllComplete.length || this._failedSinceLastAllComplete.length)) {\n // Attempt to ensure onAllComplete is not invoked before other callbacks, such as onCancel & onComplete\n setTimeout(function() {\n self._onAllComplete(self._succeededSinceLastAllComplete, self._failedSinceLastAllComplete);\n }, 0);\n }\n },\n\n _maybeHandleIos8SafariWorkaround: function() {\n var self = this;\n\n if (this._options.workarounds.ios8SafariUploads && qq.ios800() && qq.iosSafari()) {\n setTimeout(function() {\n window.alert(self._options.messages.unsupportedBrowserIos8Safari);\n }, 0);\n throw new qq.Error(this._options.messages.unsupportedBrowserIos8Safari);\n }\n },\n\n _maybeParseAndSendUploadError: function(id, name, response, xhr) {\n // Assuming no one will actually set the response code to something other than 200\n // and still set 'success' to true...\n if (!response.success) {\n if (xhr && xhr.status !== 200 && !response.error) {\n this._options.callbacks.onError(id, name, \"XHR returned response code \" + xhr.status, xhr);\n }\n else {\n var errorReason = response.error ? response.error : this._options.text.defaultResponseError;\n this._options.callbacks.onError(id, name, errorReason, xhr);\n }\n }\n },\n\n _maybeProcessNextItemAfterOnValidateCallback: function(validItem, items, index, params, endpoint) {\n var self = this;\n\n if (items.length > index) {\n if (validItem || !this._options.validation.stopOnFirstInvalidFile) {\n //use setTimeout to prevent a stack overflow with a large number of files in the batch & non-promissory callbacks\n setTimeout(function() {\n var validationDescriptor = self._getValidationDescriptor(items[index]),\n buttonId = self._getButtonId(items[index].file),\n button = self._getButton(buttonId);\n\n self._handleCheckedCallback({\n name: \"onValidate\",\n callback: qq.bind(self._options.callbacks.onValidate, self, validationDescriptor, button),\n onSuccess: qq.bind(self._onValidateCallbackSuccess, self, items, index, params, endpoint),\n onFailure: qq.bind(self._onValidateCallbackFailure, self, items, index, params, endpoint),\n identifier: \"Item '\" + validationDescriptor.name + \"', size: \" + validationDescriptor.size\n });\n }, 0);\n }\n else if (!validItem) {\n for (; index < items.length; index++) {\n self._fileOrBlobRejected(items[index].id);\n }\n }\n }\n },\n\n _onAllComplete: function(successful, failed) {\n this._totalProgress && this._totalProgress.onAllComplete(successful, failed, this._preventRetries);\n\n this._options.callbacks.onAllComplete(qq.extend([], successful), qq.extend([], failed));\n\n this._succeededSinceLastAllComplete = [];\n this._failedSinceLastAllComplete = [];\n },\n\n /**\n * Attempt to automatically retry a failed upload.\n *\n * @param id The file ID of the failed upload\n * @param name The name of the file associated with the failed upload\n * @param responseJSON Response from the server, parsed into a javascript object\n * @param xhr Ajax transport used to send the failed request\n * @param callback Optional callback to be invoked if a retry is prudent.\n * Invoked in lieu of asking the upload handler to retry.\n * @returns {boolean} true if an auto-retry will occur\n * @private\n */\n _onAutoRetry: function(id, name, responseJSON, xhr, callback) {\n var self = this;\n\n self._preventRetries[id] = responseJSON[self._options.retry.preventRetryResponseProperty];\n\n if (self._shouldAutoRetry(id)) {\n var retryWaitPeriod = self._options.retry.autoAttemptDelay * 1000;\n\n self._maybeParseAndSendUploadError.apply(self, arguments);\n self._options.callbacks.onAutoRetry(id, name, self._autoRetries[id]);\n self._onBeforeAutoRetry(id, name);\n\n self._uploadData.setStatus(id, qq.status.UPLOAD_RETRYING);\n self._retryTimeouts[id] = setTimeout(function() {\n self.log(\"Starting retry for \" + name + \"...\");\n\n if (callback) {\n callback(id);\n }\n else {\n self._handler.retry(id);\n }\n }, retryWaitPeriod);\n\n return true;\n }\n },\n\n _onBeforeAutoRetry: function(id, name) {\n this.log(\"Waiting \" + this._options.retry.autoAttemptDelay + \" seconds before retrying \" + name + \"...\");\n },\n\n //return false if we should not attempt the requested retry\n _onBeforeManualRetry: function(id) {\n var itemLimit = this._currentItemLimit,\n fileName;\n\n if (this._preventRetries[id]) {\n this.log(\"Retries are forbidden for id \" + id, \"warn\");\n return false;\n }\n else if (this._handler.isValid(id)) {\n fileName = this.getName(id);\n\n if (this._options.callbacks.onManualRetry(id, fileName) === false) {\n return false;\n }\n\n if (itemLimit > 0 && this._netUploadedOrQueued + 1 > itemLimit) {\n this._itemError(\"retryFailTooManyItems\");\n return false;\n }\n\n this.log(\"Retrying upload for '\" + fileName + \"' (id: \" + id + \")...\");\n return true;\n }\n else {\n this.log(\"'\" + id + \"' is not a valid file ID\", \"error\");\n return false;\n }\n },\n\n _onCancel: function(id, name) {\n this._netUploadedOrQueued--;\n\n clearTimeout(this._retryTimeouts[id]);\n\n var storedItemIndex = qq.indexOf(this._storedIds, id);\n if (!this._options.autoUpload && storedItemIndex >= 0) {\n this._storedIds.splice(storedItemIndex, 1);\n }\n\n this._uploadData.setStatus(id, qq.status.CANCELED);\n },\n\n _onComplete: function(id, name, result, xhr) {\n if (!result.success) {\n this._netUploadedOrQueued--;\n this._uploadData.setStatus(id, qq.status.UPLOAD_FAILED);\n\n if (result[this._options.retry.preventRetryResponseProperty] === true) {\n this._preventRetries[id] = true;\n }\n }\n else {\n if (result.thumbnailUrl) {\n this._thumbnailUrls[id] = result.thumbnailUrl;\n }\n\n this._netUploaded++;\n this._uploadData.setStatus(id, qq.status.UPLOAD_SUCCESSFUL);\n }\n\n this._maybeParseAndSendUploadError(id, name, result, xhr);\n\n return result.success ? true : false;\n },\n\n _onDelete: function(id) {\n this._uploadData.setStatus(id, qq.status.DELETING);\n },\n\n _onDeleteComplete: function(id, xhrOrXdr, isError) {\n var name = this.getName(id);\n\n if (isError) {\n this._handleDeleteFailed(id, xhrOrXdr);\n }\n else {\n this._handleDeleteSuccess(id);\n }\n },\n\n _onInputChange: function(input) {\n var fileIndex;\n\n if (qq.supportedFeatures.ajaxUploading) {\n for (fileIndex = 0; fileIndex < input.files.length; fileIndex++) {\n this._annotateWithButtonId(input.files[fileIndex], input);\n }\n\n this.addFiles(input.files);\n }\n // Android 2.3.x will fire `onchange` even if no file has been selected\n else if (input.value.length > 0) {\n this.addFiles(input);\n }\n\n qq.each(this._buttons, function(idx, button) {\n button.reset();\n });\n },\n\n _onProgress: function(id, name, loaded, total) {\n this._totalProgress && this._totalProgress.onIndividualProgress(id, loaded, total);\n },\n\n _onSubmit: function(id, name) {\n //nothing to do yet in core uploader\n },\n\n _onSubmitCallbackSuccess: function(id, name) {\n this._onSubmit.apply(this, arguments);\n this._uploadData.setStatus(id, qq.status.SUBMITTED);\n this._onSubmitted.apply(this, arguments);\n\n if (this._options.autoUpload) {\n this._options.callbacks.onSubmitted.apply(this, arguments);\n this._uploadFile(id);\n }\n else {\n this._storeForLater(id);\n this._options.callbacks.onSubmitted.apply(this, arguments);\n }\n },\n\n _onSubmitDelete: function(id, onSuccessCallback, additionalMandatedParams) {\n var uuid = this.getUuid(id),\n adjustedOnSuccessCallback;\n\n if (onSuccessCallback) {\n adjustedOnSuccessCallback = qq.bind(onSuccessCallback, this, id, uuid, additionalMandatedParams);\n }\n\n if (this._isDeletePossible()) {\n this._handleCheckedCallback({\n name: \"onSubmitDelete\",\n callback: qq.bind(this._options.callbacks.onSubmitDelete, this, id),\n onSuccess: adjustedOnSuccessCallback ||\n qq.bind(this._deleteHandler.sendDelete, this, id, uuid, additionalMandatedParams),\n identifier: id\n });\n return true;\n }\n else {\n this.log(\"Delete request ignored for ID \" + id + \", delete feature is disabled or request not possible \" +\n \"due to CORS on a user agent that does not support pre-flighting.\", \"warn\");\n return false;\n }\n },\n\n _onSubmitted: function(id) {\n //nothing to do in the base uploader\n },\n\n _onTotalProgress: function(loaded, total) {\n this._options.callbacks.onTotalProgress(loaded, total);\n },\n\n _onUploadPrep: function(id) {\n // nothing to do in the core uploader for now\n },\n\n _onUpload: function(id, name) {\n this._uploadData.setStatus(id, qq.status.UPLOADING);\n },\n\n _onUploadChunk: function(id, chunkData) {\n //nothing to do in the base uploader\n },\n\n _onUploadChunkSuccess: function(id, chunkData) {\n if (!this._preventRetries[id] && this._options.retry.enableAuto) {\n this._autoRetries[id] = 0;\n }\n },\n\n _onUploadStatusChange: function(id, oldStatus, newStatus) {\n // Make sure a \"queued\" retry attempt is canceled if the upload has been paused\n if (newStatus === qq.status.PAUSED) {\n clearTimeout(this._retryTimeouts[id]);\n }\n },\n\n _onValidateBatchCallbackFailure: function(fileWrappers) {\n var self = this;\n\n qq.each(fileWrappers, function(idx, fileWrapper) {\n self._fileOrBlobRejected(fileWrapper.id);\n });\n },\n\n _onValidateBatchCallbackSuccess: function(validationDescriptors, items, params, endpoint, button) {\n var errorMessage,\n itemLimit = this._currentItemLimit,\n proposedNetFilesUploadedOrQueued = this._netUploadedOrQueued;\n\n if (itemLimit === 0 || proposedNetFilesUploadedOrQueued <= itemLimit) {\n if (items.length > 0) {\n this._handleCheckedCallback({\n name: \"onValidate\",\n callback: qq.bind(this._options.callbacks.onValidate, this, validationDescriptors[0], button),\n onSuccess: qq.bind(this._onValidateCallbackSuccess, this, items, 0, params, endpoint),\n onFailure: qq.bind(this._onValidateCallbackFailure, this, items, 0, params, endpoint),\n identifier: \"Item '\" + items[0].file.name + \"', size: \" + items[0].file.size\n });\n }\n else {\n this._itemError(\"noFilesError\");\n }\n }\n else {\n this._onValidateBatchCallbackFailure(items);\n errorMessage = this._options.messages.tooManyItemsError\n .replace(/\\{netItems\\}/g, proposedNetFilesUploadedOrQueued)\n .replace(/\\{itemLimit\\}/g, itemLimit);\n this._batchError(errorMessage);\n }\n },\n\n _onValidateCallbackFailure: function(items, index, params, endpoint) {\n var nextIndex = index + 1;\n\n this._fileOrBlobRejected(items[index].id, items[index].file.name);\n\n this._maybeProcessNextItemAfterOnValidateCallback(false, items, nextIndex, params, endpoint);\n },\n\n _onValidateCallbackSuccess: function(items, index, params, endpoint) {\n var self = this,\n nextIndex = index + 1,\n validationDescriptor = this._getValidationDescriptor(items[index]);\n\n this._validateFileOrBlobData(items[index], validationDescriptor)\n .then(\n function() {\n self._upload(items[index].id, params, endpoint);\n self._maybeProcessNextItemAfterOnValidateCallback(true, items, nextIndex, params, endpoint);\n },\n function() {\n self._maybeProcessNextItemAfterOnValidateCallback(false, items, nextIndex, params, endpoint);\n }\n );\n },\n\n _prepareItemsForUpload: function(items, params, endpoint) {\n if (items.length === 0) {\n this._itemError(\"noFilesError\");\n return;\n }\n\n var validationDescriptors = this._getValidationDescriptors(items),\n buttonId = this._getButtonId(items[0].file),\n button = this._getButton(buttonId);\n\n this._handleCheckedCallback({\n name: \"onValidateBatch\",\n callback: qq.bind(this._options.callbacks.onValidateBatch, this, validationDescriptors, button),\n onSuccess: qq.bind(this._onValidateBatchCallbackSuccess, this, validationDescriptors, items, params, endpoint, button),\n onFailure: qq.bind(this._onValidateBatchCallbackFailure, this, items),\n identifier: \"batch validation\"\n });\n },\n\n _preventLeaveInProgress: function() {\n var self = this;\n\n this._disposeSupport.attach(window, \"beforeunload\", function(e) {\n if (self.getInProgress()) {\n e = e || window.event;\n // for ie, ff\n e.returnValue = self._options.messages.onLeave;\n // for webkit\n return self._options.messages.onLeave;\n }\n });\n },\n\n // Attempts to refresh session data only if the `qq.Session` module exists\n // and a session endpoint has been specified. The `onSessionRequestComplete`\n // callback will be invoked once the refresh is complete.\n _refreshSessionData: function() {\n var self = this,\n options = this._options.session;\n\n /* jshint eqnull:true */\n if (qq.Session && this._options.session.endpoint != null) {\n if (!this._session) {\n qq.extend(options, {cors: this._options.cors});\n\n options.log = qq.bind(this.log, this);\n options.addFileRecord = qq.bind(this._addCannedFile, this);\n\n this._session = new qq.Session(options);\n }\n\n setTimeout(function() {\n self._session.refresh().then(function(response, xhrOrXdr) {\n self._sessionRequestComplete();\n self._options.callbacks.onSessionRequestComplete(response, true, xhrOrXdr);\n\n }, function(response, xhrOrXdr) {\n\n self._options.callbacks.onSessionRequestComplete(response, false, xhrOrXdr);\n });\n }, 0);\n }\n },\n\n _sessionRequestComplete: function() {},\n\n _setSize: function(id, newSize) {\n this._uploadData.updateSize(id, newSize);\n this._totalProgress && this._totalProgress.onNewSize(id);\n },\n\n _shouldAutoRetry: function(id) {\n var uploadData = this._uploadData.retrieve({id: id});\n\n /*jshint laxbreak: true */\n if (!this._preventRetries[id]\n && this._options.retry.enableAuto\n && uploadData.status !== qq.status.PAUSED) {\n\n if (this._autoRetries[id] === undefined) {\n this._autoRetries[id] = 0;\n }\n\n if (this._autoRetries[id] < this._options.retry.maxAutoAttempts) {\n this._autoRetries[id] += 1;\n return true;\n }\n }\n\n return false;\n },\n\n _storeForLater: function(id) {\n this._storedIds.push(id);\n },\n\n // Maps a file with the button that was used to select it.\n _trackButton: function(id) {\n var buttonId;\n\n if (qq.supportedFeatures.ajaxUploading) {\n buttonId = this._handler.getFile(id).qqButtonId;\n }\n else {\n buttonId = this._getButtonId(this._handler.getInput(id));\n }\n\n if (buttonId) {\n this._buttonIdsForFileIds[id] = buttonId;\n }\n },\n\n _updateFormSupportAndParams: function(formElementOrId) {\n this._options.form.element = formElementOrId;\n\n this._formSupport = qq.FormSupport && new qq.FormSupport(\n this._options.form, qq.bind(this.uploadStoredFiles, this), qq.bind(this.log, this)\n );\n\n if (this._formSupport && this._formSupport.attachedToForm) {\n this._paramsStore.addReadOnly(null, this._formSupport.getFormInputsAsObject);\n\n this._options.autoUpload = this._formSupport.newAutoUpload;\n if (this._formSupport.newEndpoint) {\n this.setEndpoint(this._formSupport.newEndpoint);\n }\n }\n },\n\n _upload: function(id, params, endpoint) {\n var name = this.getName(id);\n\n if (params) {\n this.setParams(params, id);\n }\n\n if (endpoint) {\n this.setEndpoint(endpoint, id);\n }\n\n this._handleCheckedCallback({\n name: \"onSubmit\",\n callback: qq.bind(this._options.callbacks.onSubmit, this, id, name),\n onSuccess: qq.bind(this._onSubmitCallbackSuccess, this, id, name),\n onFailure: qq.bind(this._fileOrBlobRejected, this, id, name),\n identifier: id\n });\n },\n\n _uploadFile: function(id) {\n if (!this._handler.upload(id)) {\n this._uploadData.setStatus(id, qq.status.QUEUED);\n }\n },\n\n _uploadStoredFiles: function() {\n var idToUpload, stillSubmitting,\n self = this;\n\n while (this._storedIds.length) {\n idToUpload = this._storedIds.shift();\n this._uploadFile(idToUpload);\n }\n\n // If we are still waiting for some files to clear validation, attempt to upload these again in a bit\n stillSubmitting = this.getUploads({status: qq.status.SUBMITTING}).length;\n if (stillSubmitting) {\n qq.log(\"Still waiting for \" + stillSubmitting + \" files to clear submit queue. Will re-parse stored IDs array shortly.\");\n setTimeout(function() {\n self._uploadStoredFiles();\n }, 1000);\n }\n },\n\n /**\n * Performs some internal validation checks on an item, defined in the `validation` option.\n *\n * @param fileWrapper Wrapper containing a `file` along with an `id`\n * @param validationDescriptor Normalized information about the item (`size`, `name`).\n * @returns qq.Promise with appropriate callbacks invoked depending on the validity of the file\n * @private\n */\n _validateFileOrBlobData: function(fileWrapper, validationDescriptor) {\n var self = this,\n file = (function() {\n if (fileWrapper.file instanceof qq.BlobProxy) {\n return fileWrapper.file.referenceBlob;\n }\n return fileWrapper.file;\n }()),\n name = validationDescriptor.name,\n size = validationDescriptor.size,\n buttonId = this._getButtonId(fileWrapper.file),\n validationBase = this._getValidationBase(buttonId),\n validityChecker = new qq.Promise();\n\n validityChecker.then(\n function() {},\n function() {\n self._fileOrBlobRejected(fileWrapper.id, name);\n });\n\n if (qq.isFileOrInput(file) && !this._isAllowedExtension(validationBase.allowedExtensions, name)) {\n this._itemError(\"typeError\", name, file);\n return validityChecker.failure();\n }\n\n if (!this._options.validation.allowEmpty && size === 0) {\n this._itemError(\"emptyError\", name, file);\n return validityChecker.failure();\n }\n\n if (size > 0 && validationBase.sizeLimit && size > validationBase.sizeLimit) {\n this._itemError(\"sizeError\", name, file);\n return validityChecker.failure();\n }\n\n if (size > 0 && size < validationBase.minSizeLimit) {\n this._itemError(\"minSizeError\", name, file);\n return validityChecker.failure();\n }\n\n if (qq.ImageValidation && qq.supportedFeatures.imagePreviews && qq.isFile(file)) {\n new qq.ImageValidation(file, qq.bind(self.log, self)).validate(validationBase.image).then(\n validityChecker.success,\n function(errorCode) {\n self._itemError(errorCode + \"ImageError\", name, file);\n validityChecker.failure();\n }\n );\n }\n else {\n validityChecker.success();\n }\n\n return validityChecker;\n },\n\n _wrapCallbacks: function() {\n var self, safeCallback, prop;\n\n self = this;\n\n safeCallback = function(name, callback, args) {\n var errorMsg;\n\n try {\n return callback.apply(self, args);\n }\n catch (exception) {\n errorMsg = exception.message || exception.toString();\n self.log(\"Caught exception in '\" + name + \"' callback - \" + errorMsg, \"error\");\n }\n };\n\n /* jshint forin: false, loopfunc: true */\n for (prop in this._options.callbacks) {\n (function() {\n var callbackName, callbackFunc;\n callbackName = prop;\n callbackFunc = self._options.callbacks[callbackName];\n self._options.callbacks[callbackName] = function() {\n return safeCallback(callbackName, callbackFunc, arguments);\n };\n }());\n }\n }\n };\n}());\n","/*globals qq*/\n(function() {\n \"use strict\";\n\n qq.FineUploaderBasic = function(o) {\n var self = this;\n\n // These options define FineUploaderBasic mode.\n this._options = {\n debug: false,\n button: null,\n multiple: true,\n maxConnections: 3,\n disableCancelForFormUploads: false,\n autoUpload: true,\n warnBeforeUnload: true,\n\n request: {\n customHeaders: {},\n endpoint: \"/server/upload\",\n filenameParam: \"qqfilename\",\n forceMultipart: true,\n inputName: \"qqfile\",\n method: \"POST\",\n omitDefaultParams: false,\n params: {},\n paramsInBody: true,\n requireSuccessJson: true,\n totalFileSizeName: \"qqtotalfilesize\",\n uuidName: \"qquuid\"\n },\n\n validation: {\n allowedExtensions: [],\n sizeLimit: 0,\n minSizeLimit: 0,\n itemLimit: 0,\n stopOnFirstInvalidFile: true,\n acceptFiles: null,\n image: {\n maxHeight: 0,\n maxWidth: 0,\n minHeight: 0,\n minWidth: 0\n },\n allowEmpty: false\n },\n\n callbacks: {\n onSubmit: function(id, name) {},\n onSubmitted: function(id, name) {},\n onComplete: function(id, name, responseJSON, maybeXhr) {},\n onAllComplete: function(successful, failed) {},\n onCancel: function(id, name) {},\n onUpload: function(id, name) {},\n onUploadChunk: function(id, name, chunkData) {},\n onUploadChunkSuccess: function(id, chunkData, responseJSON, xhr) {},\n onResume: function(id, fileName, chunkData, customResumeData) {},\n onProgress: function(id, name, loaded, total) {},\n onTotalProgress: function(loaded, total) {},\n onError: function(id, name, reason, maybeXhrOrXdr) {},\n onAutoRetry: function(id, name, attemptNumber) {},\n onManualRetry: function(id, name) {},\n onValidateBatch: function(fileOrBlobData) {},\n onValidate: function(fileOrBlobData) {},\n onSubmitDelete: function(id) {},\n onDelete: function(id) {},\n onDeleteComplete: function(id, xhrOrXdr, isError) {},\n onPasteReceived: function(blob) {},\n onStatusChange: function(id, oldStatus, newStatus) {},\n onSessionRequestComplete: function(response, success, xhrOrXdr) {}\n },\n\n messages: {\n typeError: \"{file} has an invalid extension. Valid extension(s): {extensions}.\",\n sizeError: \"{file} is too large, maximum file size is {sizeLimit}.\",\n minSizeError: \"{file} is too small, minimum file size is {minSizeLimit}.\",\n emptyError: \"{file} is empty, please select files again without it.\",\n noFilesError: \"No files to upload.\",\n tooManyItemsError: \"Too many items ({netItems}) would be uploaded. Item limit is {itemLimit}.\",\n maxHeightImageError: \"Image is too tall.\",\n maxWidthImageError: \"Image is too wide.\",\n minHeightImageError: \"Image is not tall enough.\",\n minWidthImageError: \"Image is not wide enough.\",\n retryFailTooManyItems: \"Retry failed - you have reached your file limit.\",\n onLeave: \"The files are being uploaded, if you leave now the upload will be canceled.\",\n unsupportedBrowserIos8Safari: \"Unrecoverable error - this browser does not permit file uploading of any kind due to serious bugs in iOS8 Safari. Please use iOS8 Chrome until Apple fixes these issues.\"\n },\n\n retry: {\n enableAuto: false,\n maxAutoAttempts: 3,\n autoAttemptDelay: 5,\n preventRetryResponseProperty: \"preventRetry\"\n },\n\n classes: {\n buttonHover: \"qq-upload-button-hover\",\n buttonFocus: \"qq-upload-button-focus\"\n },\n\n chunking: {\n enabled: false,\n concurrent: {\n enabled: false\n },\n mandatory: false,\n paramNames: {\n partIndex: \"qqpartindex\",\n partByteOffset: \"qqpartbyteoffset\",\n chunkSize: \"qqchunksize\",\n totalFileSize: \"qqtotalfilesize\",\n totalParts: \"qqtotalparts\"\n },\n partSize: function(id) {\n return 2000000;\n },\n // only relevant for traditional endpoints, only required when concurrent.enabled === true\n success: {\n endpoint: null,\n\n headers: function(id) {\n return null;\n },\n\n jsonPayload: false,\n\n method: \"POST\",\n\n params: function(id) {\n return null;\n },\n\n resetOnStatus: []\n }\n },\n\n resume: {\n enabled: false,\n recordsExpireIn: 7, //days\n paramNames: {\n resuming: \"qqresume\"\n },\n customKeys: function(fileId) {\n return [];\n }\n },\n\n formatFileName: function(fileOrBlobName) {\n return fileOrBlobName;\n },\n\n text: {\n defaultResponseError: \"Upload failure reason unknown\",\n fileInputTitle: \"file input\",\n sizeSymbols: [\"kB\", \"MB\", \"GB\", \"TB\", \"PB\", \"EB\"]\n },\n\n deleteFile: {\n enabled: false,\n method: \"DELETE\",\n endpoint: \"/server/upload\",\n customHeaders: {},\n params: {}\n },\n\n cors: {\n expected: false,\n sendCredentials: false,\n allowXdr: false\n },\n\n blobs: {\n defaultName: \"misc_data\"\n },\n\n paste: {\n targetElement: null,\n defaultName: \"pasted_image\"\n },\n\n camera: {\n ios: false,\n\n // if ios is true: button is null means target the default button, otherwise target the button specified\n button: null\n },\n\n // This refers to additional upload buttons to be handled by Fine Uploader.\n // Each element is an object, containing `element` as the only required\n // property. The `element` must be a container that will ultimately\n // contain an invisible ` ` created by Fine Uploader.\n // Optional properties of each object include `multiple`, `validation`,\n // and `folders`.\n extraButtons: [],\n\n // Depends on the session module. Used to query the server for an initial file list\n // during initialization and optionally after a `reset`.\n session: {\n endpoint: null,\n params: {},\n customHeaders: {},\n refreshOnReset: true\n },\n\n // Send parameters associated with an existing form along with the files\n form: {\n // Element ID, HTMLElement, or null\n element: \"qq-form\",\n\n // Overrides the base `autoUpload`, unless `element` is null.\n autoUpload: false,\n\n // true = upload files on form submission (and squelch submit event)\n interceptSubmit: true\n },\n\n // scale images client side, upload a new file for each scaled version\n scaling: {\n customResizer: null,\n\n // send the original file as well\n sendOriginal: true,\n\n // fox orientation for scaled images\n orient: true,\n\n // If null, scaled image type will match reference image type. This value will be referred to\n // for any size record that does not specific a type.\n defaultType: null,\n\n defaultQuality: 80,\n\n failureText: \"Failed to scale\",\n\n includeExif: false,\n\n // metadata about each requested scaled version\n sizes: []\n },\n\n workarounds: {\n iosEmptyVideos: true,\n ios8SafariUploads: true,\n ios8BrowserCrash: false\n }\n };\n\n // Replace any default options with user defined ones\n qq.extend(this._options, o, true);\n\n this._buttons = [];\n this._extraButtonSpecs = {};\n this._buttonIdsForFileIds = [];\n\n this._wrapCallbacks();\n this._disposeSupport = new qq.DisposeSupport();\n\n this._storedIds = [];\n this._autoRetries = [];\n this._retryTimeouts = [];\n this._preventRetries = [];\n this._thumbnailUrls = [];\n\n this._netUploadedOrQueued = 0;\n this._netUploaded = 0;\n this._uploadData = this._createUploadDataTracker();\n\n this._initFormSupportAndParams();\n\n this._customHeadersStore = this._createStore(this._options.request.customHeaders);\n this._deleteFileCustomHeadersStore = this._createStore(this._options.deleteFile.customHeaders);\n\n this._deleteFileParamsStore = this._createStore(this._options.deleteFile.params);\n\n this._endpointStore = this._createStore(this._options.request.endpoint);\n this._deleteFileEndpointStore = this._createStore(this._options.deleteFile.endpoint);\n\n this._handler = this._createUploadHandler();\n\n this._deleteHandler = qq.DeleteFileAjaxRequester && this._createDeleteHandler();\n\n if (this._options.button) {\n this._defaultButtonId = this._createUploadButton({\n element: this._options.button,\n title: this._options.text.fileInputTitle\n }).getButtonId();\n }\n\n this._generateExtraButtonSpecs();\n\n this._handleCameraAccess();\n\n if (this._options.paste.targetElement) {\n if (qq.PasteSupport) {\n this._pasteHandler = this._createPasteHandler();\n }\n else {\n this.log(\"Paste support module not found\", \"error\");\n }\n }\n\n this._options.warnBeforeUnload && this._preventLeaveInProgress();\n\n this._imageGenerator = qq.ImageGenerator && new qq.ImageGenerator(qq.bind(this.log, this));\n this._refreshSessionData();\n\n this._succeededSinceLastAllComplete = [];\n this._failedSinceLastAllComplete = [];\n\n this._scaler = (qq.Scaler && new qq.Scaler(this._options.scaling, qq.bind(this.log, this))) || {};\n if (this._scaler.enabled) {\n this._customNewFileHandler = qq.bind(this._scaler.handleNewFile, this._scaler);\n }\n\n if (qq.TotalProgress && qq.supportedFeatures.progressBar) {\n this._totalProgress = new qq.TotalProgress(\n qq.bind(this._onTotalProgress, this),\n\n function(id) {\n var entry = self._uploadData.retrieve({id: id});\n return (entry && entry.size) || 0;\n }\n );\n }\n\n this._currentItemLimit = this._options.validation.itemLimit;\n\n this._customResumeDataStore = this._createStore();\n };\n\n // Define the private & public API methods.\n qq.FineUploaderBasic.prototype = qq.basePublicApi;\n qq.extend(qq.FineUploaderBasic.prototype, qq.basePrivateApi);\n}());\n","/*globals qq, XDomainRequest*/\n/** Generic class for sending non-upload ajax requests and handling the associated responses **/\nqq.AjaxRequester = function(o) {\n \"use strict\";\n\n var log, shouldParamsBeInQueryString,\n queue = [],\n requestData = {},\n options = {\n acceptHeader: null,\n validMethods: [\"PATCH\", \"POST\", \"PUT\"],\n method: \"POST\",\n contentType: \"application/x-www-form-urlencoded\",\n maxConnections: 3,\n customHeaders: {},\n endpointStore: {},\n paramsStore: {},\n mandatedParams: {},\n allowXRequestedWithAndCacheControl: true,\n successfulResponseCodes: {\n DELETE: [200, 202, 204],\n PATCH: [200, 201, 202, 203, 204],\n POST: [200, 201, 202, 203, 204],\n PUT: [200, 201, 202, 203, 204],\n GET: [200]\n },\n cors: {\n expected: false,\n sendCredentials: false\n },\n log: function(str, level) {},\n onSend: function(id) {},\n onComplete: function(id, xhrOrXdr, isError) {},\n onProgress: null\n };\n\n qq.extend(options, o);\n log = options.log;\n\n if (qq.indexOf(options.validMethods, options.method) < 0) {\n throw new Error(\"'\" + options.method + \"' is not a supported method for this type of request!\");\n }\n\n // [Simple methods](http://www.w3.org/TR/cors/#simple-method)\n // are defined by the W3C in the CORS spec as a list of methods that, in part,\n // make a CORS request eligible to be exempt from preflighting.\n function isSimpleMethod() {\n return qq.indexOf([\"GET\", \"POST\", \"HEAD\"], options.method) >= 0;\n }\n\n // [Simple headers](http://www.w3.org/TR/cors/#simple-header)\n // are defined by the W3C in the CORS spec as a list of headers that, in part,\n // make a CORS request eligible to be exempt from preflighting.\n function containsNonSimpleHeaders(headers) {\n var containsNonSimple = false;\n\n qq.each(containsNonSimple, function(idx, header) {\n if (qq.indexOf([\"Accept\", \"Accept-Language\", \"Content-Language\", \"Content-Type\"], header) < 0) {\n containsNonSimple = true;\n return false;\n }\n });\n\n return containsNonSimple;\n }\n\n function isXdr(xhr) {\n //The `withCredentials` test is a commonly accepted way to determine if XHR supports CORS.\n return options.cors.expected && xhr.withCredentials === undefined;\n }\n\n // Returns either a new `XMLHttpRequest` or `XDomainRequest` instance.\n function getCorsAjaxTransport() {\n var xhrOrXdr;\n\n if (window.XMLHttpRequest || window.ActiveXObject) {\n xhrOrXdr = qq.createXhrInstance();\n\n if (xhrOrXdr.withCredentials === undefined) {\n xhrOrXdr = new XDomainRequest();\n // Workaround for XDR bug in IE9 - https://social.msdn.microsoft.com/Forums/ie/en-US/30ef3add-767c-4436-b8a9-f1ca19b4812e/ie9-rtm-xdomainrequest-issued-requests-may-abort-if-all-event-handlers-not-specified?forum=iewebdevelopment\n xhrOrXdr.onload = function() {};\n xhrOrXdr.onerror = function() {};\n xhrOrXdr.ontimeout = function() {};\n xhrOrXdr.onprogress = function() {};\n }\n }\n\n return xhrOrXdr;\n }\n\n // Returns either a new XHR/XDR instance, or an existing one for the associated `File` or `Blob`.\n function getXhrOrXdr(id, suppliedXhr) {\n var xhrOrXdr = requestData[id] && requestData[id].xhr;\n\n if (!xhrOrXdr) {\n if (suppliedXhr) {\n xhrOrXdr = suppliedXhr;\n }\n else {\n if (options.cors.expected) {\n xhrOrXdr = getCorsAjaxTransport();\n }\n else {\n xhrOrXdr = qq.createXhrInstance();\n }\n }\n\n requestData[id].xhr = xhrOrXdr;\n }\n\n return xhrOrXdr;\n }\n\n // Removes element from queue, sends next request\n function dequeue(id) {\n var i = qq.indexOf(queue, id),\n max = options.maxConnections,\n nextId;\n\n delete requestData[id];\n queue.splice(i, 1);\n\n if (queue.length >= max && i < max) {\n nextId = queue[max - 1];\n sendRequest(nextId);\n }\n }\n\n function onComplete(id, xdrError) {\n var xhr = getXhrOrXdr(id),\n method = options.method,\n isError = xdrError === true;\n\n dequeue(id);\n\n if (isError) {\n log(method + \" request for \" + id + \" has failed\", \"error\");\n }\n else if (!isXdr(xhr) && !isResponseSuccessful(xhr.status)) {\n isError = true;\n log(method + \" request for \" + id + \" has failed - response code \" + xhr.status, \"error\");\n }\n\n options.onComplete(id, xhr, isError);\n }\n\n function getParams(id) {\n var onDemandParams = requestData[id].additionalParams,\n mandatedParams = options.mandatedParams,\n params;\n\n if (options.paramsStore.get) {\n params = options.paramsStore.get(id);\n }\n\n if (onDemandParams) {\n qq.each(onDemandParams, function(name, val) {\n params = params || {};\n params[name] = val;\n });\n }\n\n if (mandatedParams) {\n qq.each(mandatedParams, function(name, val) {\n params = params || {};\n params[name] = val;\n });\n }\n\n return params;\n }\n\n function sendRequest(id, optXhr) {\n var xhr = getXhrOrXdr(id, optXhr),\n method = options.method,\n params = getParams(id),\n payload = requestData[id].payload,\n url;\n\n options.onSend(id);\n\n url = createUrl(id, params, requestData[id].additionalQueryParams);\n\n // XDR and XHR status detection APIs differ a bit.\n if (isXdr(xhr)) {\n xhr.onload = getXdrLoadHandler(id);\n xhr.onerror = getXdrErrorHandler(id);\n }\n else {\n xhr.onreadystatechange = getXhrReadyStateChangeHandler(id);\n }\n\n registerForUploadProgress(id);\n\n // The last parameter is assumed to be ignored if we are actually using `XDomainRequest`.\n xhr.open(method, url, true);\n\n // Instruct the transport to send cookies along with the CORS request,\n // unless we are using `XDomainRequest`, which is not capable of this.\n if (options.cors.expected && options.cors.sendCredentials && !isXdr(xhr)) {\n xhr.withCredentials = true;\n }\n\n setHeaders(id);\n\n log(\"Sending \" + method + \" request for \" + id);\n\n if (payload) {\n xhr.send(payload);\n }\n else if (shouldParamsBeInQueryString || !params) {\n xhr.send();\n }\n else if (params && options.contentType && options.contentType.toLowerCase().indexOf(\"application/x-www-form-urlencoded\") >= 0) {\n xhr.send(qq.obj2url(params, \"\"));\n }\n else if (params && options.contentType && options.contentType.toLowerCase().indexOf(\"application/json\") >= 0) {\n xhr.send(JSON.stringify(params));\n }\n else {\n xhr.send(params);\n }\n\n return xhr;\n }\n\n function createUrl(id, params, additionalQueryParams) {\n var endpoint = options.endpointStore.get(id),\n addToPath = requestData[id].addToPath;\n\n /*jshint -W116,-W041 */\n if (addToPath != undefined) {\n endpoint += \"/\" + addToPath;\n }\n\n if (shouldParamsBeInQueryString && params) {\n endpoint = qq.obj2url(params, endpoint);\n }\n\n if (additionalQueryParams) {\n endpoint = qq.obj2url(additionalQueryParams, endpoint);\n }\n\n return endpoint;\n }\n\n // Invoked by the UA to indicate a number of possible states that describe\n // a live `XMLHttpRequest` transport.\n function getXhrReadyStateChangeHandler(id) {\n return function() {\n if (getXhrOrXdr(id).readyState === 4) {\n onComplete(id);\n }\n };\n }\n\n function registerForUploadProgress(id) {\n var onProgress = options.onProgress;\n\n if (onProgress) {\n getXhrOrXdr(id).upload.onprogress = function(e) {\n if (e.lengthComputable) {\n onProgress(id, e.loaded, e.total);\n }\n };\n }\n }\n\n // This will be called by IE to indicate **success** for an associated\n // `XDomainRequest` transported request.\n function getXdrLoadHandler(id) {\n return function() {\n onComplete(id);\n };\n }\n\n // This will be called by IE to indicate **failure** for an associated\n // `XDomainRequest` transported request.\n function getXdrErrorHandler(id) {\n return function() {\n onComplete(id, true);\n };\n }\n\n function setHeaders(id) {\n var xhr = getXhrOrXdr(id),\n customHeaders = options.customHeaders,\n onDemandHeaders = requestData[id].additionalHeaders || {},\n method = options.method,\n allHeaders = {};\n\n // If XDomainRequest is being used, we can't set headers, so just ignore this block.\n if (!isXdr(xhr)) {\n options.acceptHeader && xhr.setRequestHeader(\"Accept\", options.acceptHeader);\n\n // Only attempt to add X-Requested-With & Cache-Control if permitted\n if (options.allowXRequestedWithAndCacheControl) {\n // Do not add X-Requested-With & Cache-Control if this is a cross-origin request\n // OR the cross-origin request contains a non-simple method or header.\n // This is done to ensure a preflight is not triggered exclusively based on the\n // addition of these 2 non-simple headers.\n if (!options.cors.expected || (!isSimpleMethod() || containsNonSimpleHeaders(customHeaders))) {\n xhr.setRequestHeader(\"X-Requested-With\", \"XMLHttpRequest\");\n xhr.setRequestHeader(\"Cache-Control\", \"no-cache\");\n }\n }\n\n if (options.contentType && (method === \"POST\" || method === \"PUT\")) {\n xhr.setRequestHeader(\"Content-Type\", options.contentType);\n }\n\n qq.extend(allHeaders, qq.isFunction(customHeaders) ? customHeaders(id) : customHeaders);\n qq.extend(allHeaders, onDemandHeaders);\n\n qq.each(allHeaders, function(name, val) {\n xhr.setRequestHeader(name, val);\n });\n }\n }\n\n function isResponseSuccessful(responseCode) {\n return qq.indexOf(options.successfulResponseCodes[options.method], responseCode) >= 0;\n }\n\n function prepareToSend(id, optXhr, addToPath, additionalParams, additionalQueryParams, additionalHeaders, payload) {\n requestData[id] = {\n addToPath: addToPath,\n additionalParams: additionalParams,\n additionalQueryParams: additionalQueryParams,\n additionalHeaders: additionalHeaders,\n payload: payload\n };\n\n var len = queue.push(id);\n\n // if too many active connections, wait...\n if (len <= options.maxConnections) {\n return sendRequest(id, optXhr);\n }\n }\n\n shouldParamsBeInQueryString = options.method === \"GET\" || options.method === \"DELETE\";\n\n qq.extend(this, {\n // Start the process of sending the request. The ID refers to the file associated with the request.\n initTransport: function(id) {\n var path, params, headers, payload, cacheBuster, additionalQueryParams;\n\n return {\n // Optionally specify the end of the endpoint path for the request.\n withPath: function(appendToPath) {\n path = appendToPath;\n return this;\n },\n\n // Optionally specify additional parameters to send along with the request.\n // These will be added to the query string for GET/DELETE requests or the payload\n // for POST/PUT requests. The Content-Type of the request will be used to determine\n // how these parameters should be formatted as well.\n withParams: function(additionalParams) {\n params = additionalParams;\n return this;\n },\n\n withQueryParams: function(_additionalQueryParams_) {\n additionalQueryParams = _additionalQueryParams_;\n return this;\n },\n\n // Optionally specify additional headers to send along with the request.\n withHeaders: function(additionalHeaders) {\n headers = additionalHeaders;\n return this;\n },\n\n // Optionally specify a payload/body for the request.\n withPayload: function(thePayload) {\n payload = thePayload;\n return this;\n },\n\n // Appends a cache buster (timestamp) to the request URL as a query parameter (only if GET or DELETE)\n withCacheBuster: function() {\n cacheBuster = true;\n return this;\n },\n\n // Send the constructed request.\n send: function(optXhr) {\n if (cacheBuster && qq.indexOf([\"GET\", \"DELETE\"], options.method) >= 0) {\n params.qqtimestamp = new Date().getTime();\n }\n\n return prepareToSend(id, optXhr, path, params, additionalQueryParams, headers, payload);\n }\n };\n },\n\n canceled: function(id) {\n dequeue(id);\n }\n });\n};\n","/* globals qq */\n/**\n * Common upload handler functions.\n *\n * @constructor\n */\nqq.UploadHandler = function(spec) {\n \"use strict\";\n\n var proxy = spec.proxy,\n fileState = {},\n onCancel = proxy.onCancel,\n getName = proxy.getName;\n\n qq.extend(this, {\n add: function(id, fileItem) {\n fileState[id] = fileItem;\n fileState[id].temp = {};\n },\n\n cancel: function(id) {\n var self = this,\n cancelFinalizationEffort = new qq.Promise(),\n onCancelRetVal = onCancel(id, getName(id), cancelFinalizationEffort);\n\n onCancelRetVal.then(function() {\n if (self.isValid(id)) {\n fileState[id].canceled = true;\n self.expunge(id);\n }\n cancelFinalizationEffort.success();\n });\n },\n\n expunge: function(id) {\n delete fileState[id];\n },\n\n getThirdPartyFileId: function(id) {\n return fileState[id].key;\n },\n\n isValid: function(id) {\n return fileState[id] !== undefined;\n },\n\n reset: function() {\n fileState = {};\n },\n\n _getFileState: function(id) {\n return fileState[id];\n },\n\n _setThirdPartyFileId: function(id, thirdPartyFileId) {\n fileState[id].key = thirdPartyFileId;\n },\n\n _wasCanceled: function(id) {\n return !!fileState[id].canceled;\n }\n });\n};\n","/*globals qq*/\n/**\n * Base upload handler module. Controls more specific handlers.\n *\n * @param o Options. Passed along to the specific handler submodule as well.\n * @param namespace [optional] Namespace for the specific handler.\n */\nqq.UploadHandlerController = function(o, namespace) {\n \"use strict\";\n\n var controller = this,\n chunkingPossible = false,\n concurrentChunkingPossible = false,\n chunking, preventRetryResponse, log, handler,\n\n options = {\n paramsStore: {},\n maxConnections: 3, // maximum number of concurrent uploads\n chunking: {\n enabled: false,\n multiple: {\n enabled: false\n }\n },\n log: function(str, level) {},\n onProgress: function(id, fileName, loaded, total) {},\n onComplete: function(id, fileName, response, xhr) {},\n onCancel: function(id, fileName) {},\n onUploadPrep: function(id) {}, // Called if non-trivial operations will be performed before onUpload\n onUpload: function(id, fileName) {},\n onUploadChunk: function(id, fileName, chunkData) {},\n onUploadChunkSuccess: function(id, chunkData, response, xhr) {},\n onAutoRetry: function(id, fileName, response, xhr) {},\n onResume: function(id, fileName, chunkData, customResumeData) {},\n onUuidChanged: function(id, newUuid) {},\n getName: function(id) {},\n setSize: function(id, newSize) {},\n isQueued: function(id) {},\n getIdsInProxyGroup: function(id) {},\n getIdsInBatch: function(id) {},\n isInProgress: function(id) {}\n },\n\n chunked = {\n // Called when each chunk has uploaded successfully\n done: function(id, chunkIdx, response, xhr) {\n var chunkData = handler._getChunkData(id, chunkIdx);\n\n handler._getFileState(id).attemptingResume = false;\n\n delete handler._getFileState(id).temp.chunkProgress[chunkIdx];\n handler._getFileState(id).loaded += chunkData.size;\n\n options.onUploadChunkSuccess(id, handler._getChunkDataForCallback(chunkData), response, xhr);\n },\n\n // Called when all chunks have been successfully uploaded and we want to ask the handler to perform any\n // logic associated with closing out the file, such as combining the chunks.\n finalize: function(id) {\n var size = options.getSize(id),\n name = options.getName(id);\n\n log(\"All chunks have been uploaded for \" + id + \" - finalizing....\");\n handler.finalizeChunks(id).then(\n function(response, xhr) {\n log(\"Finalize successful for \" + id);\n\n var normaizedResponse = upload.normalizeResponse(response, true);\n\n options.onProgress(id, name, size, size);\n handler._maybeDeletePersistedChunkData(id);\n upload.cleanup(id, normaizedResponse, xhr);\n },\n function(response, xhr) {\n var normalizedResponse = upload.normalizeResponse(response, false);\n\n log(\"Problem finalizing chunks for file ID \" + id + \" - \" + normalizedResponse.error, \"error\");\n\n if (\n normalizedResponse.reset ||\n (xhr && options.chunking.success.resetOnStatus.indexOf(xhr.status) >= 0)\n ) {\n chunked.reset(id);\n }\n\n if (!options.onAutoRetry(id, name, normalizedResponse, xhr)) {\n upload.cleanup(id, normalizedResponse, xhr);\n }\n }\n );\n },\n\n handleFailure: function(chunkIdx, id, response, xhr) {\n var name = options.getName(id);\n\n log(\"Chunked upload request failed for \" + id + \", chunk \" + chunkIdx);\n\n handler.clearCachedChunk(id, chunkIdx);\n\n var responseToReport = upload.normalizeResponse(response, false),\n inProgressIdx;\n\n if (responseToReport.reset) {\n chunked.reset(id);\n }\n else {\n var inProgressChunksArray = handler._getFileState(id).chunking.inProgress;\n\n inProgressIdx = inProgressChunksArray ? qq.indexOf(inProgressChunksArray, chunkIdx) : -1;\n if (inProgressIdx >= 0) {\n handler._getFileState(id).chunking.inProgress.splice(inProgressIdx, 1);\n handler._getFileState(id).chunking.remaining.unshift(chunkIdx);\n }\n }\n\n // We may have aborted all other in-progress chunks for this file due to a failure.\n // If so, ignore the failures associated with those aborts.\n if (!handler._getFileState(id).temp.ignoreFailure) {\n // If this chunk has failed, we want to ignore all other failures of currently in-progress\n // chunks since they will be explicitly aborted\n if (concurrentChunkingPossible) {\n handler._getFileState(id).temp.ignoreFailure = true;\n\n log(qq.format(\"Going to attempt to abort these chunks: {}. These are currently in-progress: {}.\", JSON.stringify(Object.keys(handler._getXhrs(id))), JSON.stringify(handler._getFileState(id).chunking.inProgress)));\n qq.each(handler._getXhrs(id), function(ckid, ckXhr) {\n log(qq.format(\"Attempting to abort file {}.{}. XHR readyState {}. \", id, ckid, ckXhr.readyState));\n ckXhr.abort();\n // Flag the transport, in case we are waiting for some other async operation\n // to complete before attempting to upload the chunk\n ckXhr._cancelled = true;\n });\n\n // We must indicate that all aborted chunks are no longer in progress\n handler.moveInProgressToRemaining(id);\n\n // Free up any connections used by these chunks, but don't allow any\n // other files to take up the connections (until we have exhausted all auto-retries)\n connectionManager.free(id, true);\n }\n\n if (!options.onAutoRetry(id, name, responseToReport, xhr)) {\n // If one chunk fails, abort all of the others to avoid odd race conditions that occur\n // if a chunk succeeds immediately after one fails before we have determined if the upload\n // is a failure or not.\n upload.cleanup(id, responseToReport, xhr);\n }\n }\n },\n\n hasMoreParts: function(id) {\n return !!handler._getFileState(id).chunking.remaining.length;\n },\n\n nextPart: function(id) {\n var nextIdx = handler._getFileState(id).chunking.remaining.shift();\n\n if (nextIdx >= handler._getTotalChunks(id)) {\n nextIdx = null;\n }\n\n return nextIdx;\n },\n\n reset: function(id) {\n log(\"Server or callback has ordered chunking effort to be restarted on next attempt for item ID \" + id, \"error\");\n\n handler._maybeDeletePersistedChunkData(id);\n handler.reevaluateChunking(id);\n handler._getFileState(id).loaded = 0;\n handler._getFileState(id).attemptingResume = false;\n },\n\n sendNext: function(id) {\n var size = options.getSize(id),\n name = options.getName(id),\n chunkIdx = chunked.nextPart(id),\n chunkData = handler._getChunkData(id, chunkIdx),\n fileState = handler._getFileState(id),\n resuming = fileState.attemptingResume,\n inProgressChunks = fileState.chunking.inProgress || [];\n\n if (fileState.loaded == null) {\n fileState.loaded = 0;\n }\n\n // Don't follow-through with the resume attempt if the integrator returns false from onResume\n if (resuming && options.onResume(id, name, chunkData, fileState.customResumeData) === false) {\n chunked.reset(id);\n chunkIdx = chunked.nextPart(id);\n chunkData = handler._getChunkData(id, chunkIdx);\n resuming = false;\n }\n\n // If all chunks have already uploaded successfully, we must be re-attempting the finalize step.\n if (chunkIdx == null && inProgressChunks.length === 0) {\n chunked.finalize(id);\n }\n\n // Send the next chunk\n else {\n inProgressChunks.push(chunkIdx);\n handler._getFileState(id).chunking.inProgress = inProgressChunks;\n\n if (concurrentChunkingPossible) {\n connectionManager.open(id, chunkIdx);\n }\n\n if (concurrentChunkingPossible && connectionManager.available() && handler._getFileState(id).chunking.remaining.length) {\n chunked.sendNext(id);\n }\n\n if (chunkData.blob.size === 0) {\n log(qq.format(\"Chunk {} for file {} will not be uploaded, zero sized chunk.\", chunkIdx, id), \"error\");\n chunked.handleFailure(chunkIdx, id, \"File is no longer available\", null);\n }\n\n var onUploadChunkPromise = options.onUploadChunk(id, name, handler._getChunkDataForCallback(chunkData));\n\n onUploadChunkPromise.then(\n function(requestOverrides) {\n if (!options.isInProgress(id)) {\n log(qq.format(\"Not sending chunked upload request for item {}.{} - no longer in progress.\", id, chunkIdx));\n }\n else {\n log(qq.format(\"Sending chunked upload request for item {}.{}, bytes {}-{} of {}.\", id, chunkIdx, chunkData.start + 1, chunkData.end, size));\n\n var uploadChunkData = {\n chunkIdx: chunkIdx,\n id: id,\n overrides: requestOverrides,\n resuming: resuming\n };\n\n handler.uploadChunk(uploadChunkData).then(\n // upload chunk success\n function success(response, xhr) {\n log(\"Chunked upload request succeeded for \" + id + \", chunk \" + chunkIdx);\n\n handler.clearCachedChunk(id, chunkIdx);\n\n var inProgressChunks = handler._getFileState(id).chunking.inProgress || [],\n responseToReport = upload.normalizeResponse(response, true),\n inProgressChunkIdx = qq.indexOf(inProgressChunks, chunkIdx);\n\n log(qq.format(\"Chunk {} for file {} uploaded successfully.\", chunkIdx, id));\n\n chunked.done(id, chunkIdx, responseToReport, xhr);\n\n if (inProgressChunkIdx >= 0) {\n inProgressChunks.splice(inProgressChunkIdx, 1);\n }\n\n handler._maybePersistChunkedState(id);\n\n if (!chunked.hasMoreParts(id) && inProgressChunks.length === 0) {\n chunked.finalize(id);\n }\n else if (chunked.hasMoreParts(id)) {\n chunked.sendNext(id);\n }\n else {\n log(qq.format(\"File ID {} has no more chunks to send and these chunk indexes are still marked as in-progress: {}\", id, JSON.stringify(inProgressChunks)));\n }\n },\n\n // upload chunk failure\n function failure(response, xhr) {\n chunked.handleFailure(chunkIdx, id, response, xhr);\n }\n )\n .done(function () {\n handler.clearXhr(id, chunkIdx);\n });\n }\n },\n\n function(error) {\n chunked.handleFailure(chunkIdx, id, error, null);\n }\n );\n }\n }\n },\n\n connectionManager = {\n _open: [],\n _openChunks: {},\n _waiting: [],\n\n available: function() {\n var max = options.maxConnections,\n openChunkEntriesCount = 0,\n openChunksCount = 0;\n\n qq.each(connectionManager._openChunks, function(fileId, openChunkIndexes) {\n openChunkEntriesCount++;\n openChunksCount += openChunkIndexes.length;\n });\n\n return max - (connectionManager._open.length - openChunkEntriesCount + openChunksCount);\n },\n\n /**\n * Removes element from queue, starts upload of next\n */\n free: function(id, dontAllowNext) {\n var allowNext = !dontAllowNext,\n waitingIndex = qq.indexOf(connectionManager._waiting, id),\n connectionsIndex = qq.indexOf(connectionManager._open, id),\n nextId;\n\n delete connectionManager._openChunks[id];\n\n if (upload.getProxyOrBlob(id) instanceof qq.BlobProxy) {\n log(\"Generated blob upload has ended for \" + id + \", disposing generated blob.\");\n delete handler._getFileState(id).file;\n }\n\n // If this file was not consuming a connection, it was just waiting, so remove it from the waiting array\n if (waitingIndex >= 0) {\n connectionManager._waiting.splice(waitingIndex, 1);\n }\n // If this file was consuming a connection, allow the next file to be uploaded\n else if (allowNext && connectionsIndex >= 0) {\n connectionManager._open.splice(connectionsIndex, 1);\n\n nextId = connectionManager._waiting.shift();\n if (nextId >= 0) {\n connectionManager._open.push(nextId);\n upload.start(nextId);\n }\n }\n },\n\n getWaitingOrConnected: function() {\n var waitingOrConnected = [];\n\n // Chunked files may have multiple connections open per chunk (if concurrent chunking is enabled)\n // We need to grab the file ID of any file that has at least one chunk consuming a connection.\n qq.each(connectionManager._openChunks, function(fileId, chunks) {\n if (chunks && chunks.length) {\n waitingOrConnected.push(parseInt(fileId));\n }\n });\n\n // For non-chunked files, only one connection will be consumed per file.\n // This is where we aggregate those file IDs.\n qq.each(connectionManager._open, function(idx, fileId) {\n if (!connectionManager._openChunks[fileId]) {\n waitingOrConnected.push(parseInt(fileId));\n }\n });\n\n // There may be files waiting for a connection.\n waitingOrConnected = waitingOrConnected.concat(connectionManager._waiting);\n\n return waitingOrConnected;\n },\n\n isUsingConnection: function(id) {\n return qq.indexOf(connectionManager._open, id) >= 0;\n },\n\n open: function(id, chunkIdx) {\n if (chunkIdx == null) {\n connectionManager._waiting.push(id);\n }\n\n if (connectionManager.available()) {\n if (chunkIdx == null) {\n connectionManager._waiting.pop();\n connectionManager._open.push(id);\n }\n else {\n (function() {\n var openChunksEntry = connectionManager._openChunks[id] || [];\n openChunksEntry.push(chunkIdx);\n connectionManager._openChunks[id] = openChunksEntry;\n }());\n }\n\n return true;\n }\n\n return false;\n },\n\n reset: function() {\n connectionManager._waiting = [];\n connectionManager._open = [];\n }\n },\n\n simple = {\n send: function(id, name) {\n var fileState = handler._getFileState(id);\n\n if (!fileState) {\n log(\"Ignoring send request as this upload may have been cancelled, File ID \" + id, \"warn\");\n return;\n }\n\n fileState.loaded = 0;\n\n log(\"Sending simple upload request for \" + id);\n handler.uploadFile(id).then(\n function(response, optXhr) {\n log(\"Simple upload request succeeded for \" + id);\n\n var responseToReport = upload.normalizeResponse(response, true),\n size = options.getSize(id);\n\n options.onProgress(id, name, size, size);\n upload.maybeNewUuid(id, responseToReport);\n upload.cleanup(id, responseToReport, optXhr);\n },\n\n function(response, optXhr) {\n log(\"Simple upload request failed for \" + id);\n\n var responseToReport = upload.normalizeResponse(response, false);\n\n if (!options.onAutoRetry(id, name, responseToReport, optXhr)) {\n upload.cleanup(id, responseToReport, optXhr);\n }\n }\n );\n }\n },\n\n upload = {\n cancel: function(id) {\n log(\"Cancelling \" + id);\n options.paramsStore.remove(id);\n connectionManager.free(id);\n },\n\n cleanup: function(id, response, optXhr) {\n var name = options.getName(id);\n\n options.onComplete(id, name, response, optXhr);\n\n if (handler._getFileState(id)) {\n handler._clearXhrs && handler._clearXhrs(id);\n }\n\n connectionManager.free(id);\n },\n\n // Returns a qq.BlobProxy, or an actual File/Blob if no proxy is involved, or undefined\n // if none of these are available for the ID\n getProxyOrBlob: function(id) {\n return (handler.getProxy && handler.getProxy(id)) ||\n (handler.getFile && handler.getFile(id));\n },\n\n initHandler: function() {\n var handlerType = namespace ? qq[namespace] : qq.traditional,\n handlerModuleSubtype = qq.supportedFeatures.ajaxUploading ? \"Xhr\" : \"Form\";\n\n handler = new handlerType[handlerModuleSubtype + \"UploadHandler\"](\n options,\n {\n getCustomResumeData: options.getCustomResumeData,\n getDataByUuid: options.getDataByUuid,\n getName: options.getName,\n getSize: options.getSize,\n getUuid: options.getUuid,\n log: log,\n onCancel: options.onCancel,\n onProgress: options.onProgress,\n onUuidChanged: options.onUuidChanged,\n onFinalizing: function(id) {\n options.setStatus(id, qq.status.UPLOAD_FINALIZING);\n }\n }\n );\n\n if (handler._removeExpiredChunkingRecords) {\n handler._removeExpiredChunkingRecords();\n }\n },\n\n isDeferredEligibleForUpload: function(id) {\n return options.isQueued(id);\n },\n\n // For Blobs that are part of a group of generated images, along with a reference image,\n // this will ensure the blobs in the group are uploaded in the order they were triggered,\n // even if some async processing must be completed on one or more Blobs first.\n maybeDefer: function(id, blob) {\n // If we don't have a file/blob yet & no file/blob exists for this item, request it,\n // and then submit the upload to the specific handler once the blob is available.\n // ASSUMPTION: This condition will only ever be true if XHR uploading is supported.\n if (blob && !handler.getFile(id) && blob instanceof qq.BlobProxy) {\n\n // Blob creation may take some time, so the caller may want to update the\n // UI to indicate that an operation is in progress, even before the actual\n // upload begins and an onUpload callback is invoked.\n options.onUploadPrep(id);\n\n log(\"Attempting to generate a blob on-demand for \" + id);\n blob.create().then(function(generatedBlob) {\n log(\"Generated an on-demand blob for \" + id);\n\n // Update record associated with this file by providing the generated Blob\n handler.updateBlob(id, generatedBlob);\n\n // Propagate the size for this generated Blob\n options.setSize(id, generatedBlob.size);\n\n // Order handler to recalculate chunking possibility, if applicable\n handler.reevaluateChunking(id);\n\n upload.maybeSendDeferredFiles(id);\n },\n\n // Blob could not be generated. Fail the upload & attempt to prevent retries. Also bubble error message.\n function(errorMessage) {\n var errorResponse = {};\n\n if (errorMessage) {\n errorResponse.error = errorMessage;\n }\n\n log(qq.format(\"Failed to generate blob for ID {}. Error message: {}.\", id, errorMessage), \"error\");\n\n options.onComplete(id, options.getName(id), qq.extend(errorResponse, preventRetryResponse), null);\n upload.maybeSendDeferredFiles(id);\n connectionManager.free(id);\n });\n }\n else {\n return upload.maybeSendDeferredFiles(id);\n }\n\n return false;\n },\n\n // Upload any grouped blobs, in the proper order, that are ready to be uploaded\n maybeSendDeferredFiles: function(id) {\n var idsInGroup = options.getIdsInProxyGroup(id),\n uploadedThisId = false;\n\n if (idsInGroup && idsInGroup.length) {\n log(\"Maybe ready to upload proxy group file \" + id);\n\n qq.each(idsInGroup, function(idx, idInGroup) {\n if (upload.isDeferredEligibleForUpload(idInGroup) && !!handler.getFile(idInGroup)) {\n uploadedThisId = idInGroup === id;\n upload.now(idInGroup);\n }\n else if (upload.isDeferredEligibleForUpload(idInGroup)) {\n return false;\n }\n });\n }\n else {\n uploadedThisId = true;\n upload.now(id);\n }\n\n return uploadedThisId;\n },\n\n maybeNewUuid: function(id, response) {\n if (response.newUuid !== undefined) {\n options.onUuidChanged(id, response.newUuid);\n }\n },\n\n // The response coming from handler implementations may be in various formats.\n // Instead of hoping a promise nested 5 levels deep will always return an object\n // as its first param, let's just normalize the response here.\n normalizeResponse: function(originalResponse, successful) {\n var response = originalResponse;\n\n // The passed \"response\" param may not be a response at all.\n // It could be a string, detailing the error, for example.\n if (!qq.isObject(originalResponse)) {\n response = {};\n\n if (qq.isString(originalResponse) && !successful) {\n response.error = originalResponse;\n }\n }\n\n response.success = successful;\n\n return response;\n },\n\n now: function(id) {\n var name = options.getName(id);\n\n if (!controller.isValid(id)) {\n throw new qq.Error(id + \" is not a valid file ID to upload!\");\n }\n\n options.onUpload(id, name).then(\n function(response) {\n if (response && response.pause) {\n options.setStatus(id, qq.status.PAUSED);\n handler.pause(id);\n connectionManager.free(id);\n }\n else {\n if (chunkingPossible && handler._shouldChunkThisFile(id)) {\n chunked.sendNext(id);\n }\n else {\n simple.send(id, name);\n }\n }\n },\n\n function(error) {\n error = error || {};\n\n log(id + \" upload start aborted due to rejected onUpload Promise - details: \" + error, \"error\");\n\n if (!options.onAutoRetry(id, name, error.responseJSON || {})) {\n var response = upload.normalizeResponse(error.responseJSON, false);\n upload.cleanup(id, response);\n }\n }\n );\n },\n\n start: function(id) {\n var blobToUpload = upload.getProxyOrBlob(id);\n\n if (blobToUpload) {\n return upload.maybeDefer(id, blobToUpload);\n }\n else {\n upload.now(id);\n return true;\n }\n }\n };\n\n qq.extend(this, {\n /**\n * Adds file or file input to the queue\n **/\n add: function(id, file) {\n handler.add.apply(this, arguments);\n },\n\n /**\n * Sends the file identified by id\n */\n upload: function(id) {\n if (connectionManager.open(id)) {\n return upload.start(id);\n }\n return false;\n },\n\n retry: function(id) {\n // On retry, if concurrent chunking has been enabled, we may have aborted all other in-progress chunks\n // for a file when encountering a failed chunk upload. We then signaled the controller to ignore\n // all failures associated with these aborts. We are now retrying, so we don't want to ignore\n // any more failures at this point.\n if (concurrentChunkingPossible) {\n handler._getFileState(id).temp.ignoreFailure = false;\n }\n\n // If we are attempting to retry a file that is already consuming a connection, this is likely an auto-retry.\n // Just go ahead and ask the handler to upload again.\n if (connectionManager.isUsingConnection(id)) {\n return upload.start(id);\n }\n\n // If we are attempting to retry a file that is not currently consuming a connection,\n // this is likely a manual retry attempt. We will need to ensure a connection is available\n // before the retry commences.\n else {\n return controller.upload(id);\n }\n },\n\n /**\n * Cancels file upload by id\n */\n cancel: function(id) {\n var cancelRetVal = handler.cancel(id);\n\n if (qq.isGenericPromise(cancelRetVal)) {\n cancelRetVal.then(function() {\n upload.cancel(id);\n });\n }\n else if (cancelRetVal !== false) {\n upload.cancel(id);\n }\n },\n\n /**\n * Cancels all queued or in-progress uploads\n */\n cancelAll: function() {\n var waitingOrConnected = connectionManager.getWaitingOrConnected(),\n i;\n\n // ensure files are cancelled in reverse order which they were added\n // to avoid a flash of time where a queued file begins to upload before it is canceled\n if (waitingOrConnected.length) {\n for (i = waitingOrConnected.length - 1; i >= 0; i--) {\n controller.cancel(waitingOrConnected[i]);\n }\n }\n\n connectionManager.reset();\n },\n\n // Returns a File, Blob, or the Blob/File for the reference/parent file if the targeted blob is a proxy.\n // Undefined if no file record is available.\n getFile: function(id) {\n if (handler.getProxy && handler.getProxy(id)) {\n return handler.getProxy(id).referenceBlob;\n }\n\n return handler.getFile && handler.getFile(id);\n },\n\n // Returns true if the Blob associated with the ID is related to a proxy s\n isProxied: function(id) {\n return !!(handler.getProxy && handler.getProxy(id));\n },\n\n getInput: function(id) {\n if (handler.getInput) {\n return handler.getInput(id);\n }\n },\n\n reset: function() {\n log(\"Resetting upload handler\");\n controller.cancelAll();\n connectionManager.reset();\n handler.reset();\n },\n\n expunge: function(id) {\n if (controller.isValid(id)) {\n return handler.expunge(id);\n }\n },\n\n /**\n * Determine if the file exists.\n */\n isValid: function(id) {\n return handler.isValid(id);\n },\n\n hasResumeRecord: function(id) {\n var key = handler.isValid(id) &&\n handler._getLocalStorageId &&\n handler._getLocalStorageId(id);\n\n if (key) {\n return !!localStorage.getItem(key);\n }\n\n return false;\n },\n\n getResumableFilesData: function() {\n if (handler.getResumableFilesData) {\n return handler.getResumableFilesData();\n }\n return [];\n },\n\n /**\n * This may or may not be implemented, depending on the handler. For handlers where a third-party ID is\n * available (such as the \"key\" for Amazon S3), this will return that value. Otherwise, the return value\n * will be undefined.\n *\n * @param id Internal file ID\n * @returns {*} Some identifier used by a 3rd-party service involved in the upload process\n */\n getThirdPartyFileId: function(id) {\n if (controller.isValid(id)) {\n return handler.getThirdPartyFileId(id);\n }\n },\n\n /**\n * Attempts to pause the associated upload if the specific handler supports this and the file is \"valid\".\n * @param id ID of the upload/file to pause\n * @returns {boolean} true if the upload was paused\n */\n pause: function(id) {\n if (controller.isResumable(id) && handler.pause && controller.isValid(id) && handler.pause(id)) {\n connectionManager.free(id);\n handler.moveInProgressToRemaining(id);\n return true;\n }\n return false;\n },\n\n isAttemptingResume: function(id) {\n return !!handler.isAttemptingResume && handler.isAttemptingResume(id);\n },\n\n // True if the file is eligible for pause/resume.\n isResumable: function(id) {\n return !!handler.isResumable && handler.isResumable(id);\n }\n });\n\n qq.extend(options, o);\n log = options.log;\n chunkingPossible = options.chunking.enabled && qq.supportedFeatures.chunking;\n concurrentChunkingPossible = chunkingPossible && options.chunking.concurrent.enabled;\n\n preventRetryResponse = (function() {\n var response = {};\n\n response[options.preventRetryParam] = true;\n\n return response;\n }());\n\n upload.initHandler();\n};\n","/*globals qq */\n/*jshint -W117 */\nqq.WindowReceiveMessage = function(o) {\n \"use strict\";\n\n var options = {\n log: function(message, level) {}\n },\n callbackWrapperDetachers = {};\n\n qq.extend(options, o);\n\n qq.extend(this, {\n receiveMessage: function(id, callback) {\n var onMessageCallbackWrapper = function(event) {\n callback(event.data);\n };\n\n if (window.postMessage) {\n callbackWrapperDetachers[id] = qq(window).attach(\"message\", onMessageCallbackWrapper);\n }\n else {\n log(\"iframe message passing not supported in this browser!\", \"error\");\n }\n },\n\n stopReceivingMessages: function(id) {\n if (window.postMessage) {\n var detacher = callbackWrapperDetachers[id];\n if (detacher) {\n detacher();\n }\n }\n }\n });\n};\n","/* globals qq */\n/**\n * Common APIs exposed to creators of upload via form/iframe handlers. This is reused and possibly overridden\n * in some cases by specific form upload handlers.\n *\n * @constructor\n */\nqq.FormUploadHandler = function(spec) {\n \"use strict\";\n\n var options = spec.options,\n handler = this,\n proxy = spec.proxy,\n formHandlerInstanceId = qq.getUniqueId(),\n onloadCallbacks = {},\n detachLoadEvents = {},\n postMessageCallbackTimers = {},\n isCors = options.isCors,\n inputName = options.inputName,\n getUuid = proxy.getUuid,\n log = proxy.log,\n corsMessageReceiver = new qq.WindowReceiveMessage({log: log});\n\n /**\n * Remove any trace of the file from the handler.\n *\n * @param id ID of the associated file\n */\n function expungeFile(id) {\n delete detachLoadEvents[id];\n\n // If we are dealing with CORS, we might still be waiting for a response from a loaded iframe.\n // In that case, terminate the timer waiting for a message from the loaded iframe\n // and stop listening for any more messages coming from this iframe.\n if (isCors) {\n clearTimeout(postMessageCallbackTimers[id]);\n delete postMessageCallbackTimers[id];\n corsMessageReceiver.stopReceivingMessages(id);\n }\n\n var iframe = document.getElementById(handler._getIframeName(id));\n if (iframe) {\n // To cancel request set src to something else. We use src=\"javascript:false;\"\n // because it doesn't trigger ie6 prompt on https\n /* jshint scripturl:true */\n iframe.setAttribute(\"src\", \"javascript:false;\");\n\n qq(iframe).remove();\n }\n }\n\n /**\n * @param iframeName `document`-unique Name of the associated iframe\n * @returns {*} ID of the associated file\n */\n function getFileIdForIframeName(iframeName) {\n return iframeName.split(\"_\")[0];\n }\n\n /**\n * Generates an iframe to be used as a target for upload-related form submits. This also adds the iframe\n * to the current `document`. Note that the iframe is hidden from view.\n *\n * @param name Name of the iframe.\n * @returns {HTMLIFrameElement} The created iframe\n */\n function initIframeForUpload(name) {\n var iframe = qq.toElement(\"\");\n\n iframe.setAttribute(\"id\", name);\n\n iframe.style.display = \"none\";\n document.body.appendChild(iframe);\n\n return iframe;\n }\n\n /**\n * If we are in CORS mode, we must listen for messages (containing the server response) from the associated\n * iframe, since we cannot directly parse the content of the iframe due to cross-origin restrictions.\n *\n * @param iframe Listen for messages on this iframe.\n * @param callback Invoke this callback with the message from the iframe.\n */\n function registerPostMessageCallback(iframe, callback) {\n var iframeName = iframe.id,\n fileId = getFileIdForIframeName(iframeName),\n uuid = getUuid(fileId);\n\n onloadCallbacks[uuid] = callback;\n\n // When the iframe has loaded (after the server responds to an upload request)\n // declare the attempt a failure if we don't receive a valid message shortly after the response comes in.\n detachLoadEvents[fileId] = qq(iframe).attach(\"load\", function() {\n if (handler.getInput(fileId)) {\n log(\"Received iframe load event for CORS upload request (iframe name \" + iframeName + \")\");\n\n postMessageCallbackTimers[iframeName] = setTimeout(function() {\n var errorMessage = \"No valid message received from loaded iframe for iframe name \" + iframeName;\n log(errorMessage, \"error\");\n callback({\n error: errorMessage\n });\n }, 1000);\n }\n });\n\n // Listen for messages coming from this iframe. When a message has been received, cancel the timer\n // that declares the upload a failure if a message is not received within a reasonable amount of time.\n corsMessageReceiver.receiveMessage(iframeName, function(message) {\n log(\"Received the following window message: '\" + message + \"'\");\n var fileId = getFileIdForIframeName(iframeName),\n response = handler._parseJsonResponse(message),\n uuid = response.uuid,\n onloadCallback;\n\n if (uuid && onloadCallbacks[uuid]) {\n log(\"Handling response for iframe name \" + iframeName);\n clearTimeout(postMessageCallbackTimers[iframeName]);\n delete postMessageCallbackTimers[iframeName];\n\n handler._detachLoadEvent(iframeName);\n\n onloadCallback = onloadCallbacks[uuid];\n\n delete onloadCallbacks[uuid];\n corsMessageReceiver.stopReceivingMessages(iframeName);\n onloadCallback(response);\n }\n else if (!uuid) {\n log(\"'\" + message + \"' does not contain a UUID - ignoring.\");\n }\n });\n }\n\n qq.extend(this, new qq.UploadHandler(spec));\n\n qq.override(this, function(super_) {\n return {\n /**\n * Adds File or Blob to the queue\n **/\n add: function(id, fileInput) {\n super_.add(id, {input: fileInput});\n\n fileInput.setAttribute(\"name\", inputName);\n\n // remove file input from DOM\n if (fileInput.parentNode) {\n qq(fileInput).remove();\n }\n },\n\n expunge: function(id) {\n expungeFile(id);\n super_.expunge(id);\n },\n\n isValid: function(id) {\n return super_.isValid(id) &&\n handler._getFileState(id).input !== undefined;\n }\n };\n });\n\n qq.extend(this, {\n getInput: function(id) {\n return handler._getFileState(id).input;\n },\n\n /**\n * This function either delegates to a more specific message handler if CORS is involved,\n * or simply registers a callback when the iframe has been loaded that invokes the passed callback\n * after determining if the content of the iframe is accessible.\n *\n * @param iframe Associated iframe\n * @param callback Callback to invoke after we have determined if the iframe content is accessible.\n */\n _attachLoadEvent: function(iframe, callback) {\n /*jslint eqeq: true*/\n var responseDescriptor;\n\n if (isCors) {\n registerPostMessageCallback(iframe, callback);\n }\n else {\n detachLoadEvents[iframe.id] = qq(iframe).attach(\"load\", function() {\n log(\"Received response for \" + iframe.id);\n\n // when we remove iframe from dom\n // the request stops, but in IE load\n // event fires\n if (!iframe.parentNode) {\n return;\n }\n\n try {\n // fixing Opera 10.53\n if (iframe.contentDocument &&\n iframe.contentDocument.body &&\n iframe.contentDocument.body.innerHTML == \"false\") {\n // In Opera event is fired second time\n // when body.innerHTML changed from false\n // to server response approx. after 1 sec\n // when we upload file with iframe\n return;\n }\n }\n catch (error) {\n //IE may throw an \"access is denied\" error when attempting to access contentDocument on the iframe in some cases\n log(\"Error when attempting to access iframe during handling of upload response (\" + error.message + \")\", \"error\");\n responseDescriptor = {success: false};\n }\n\n callback(responseDescriptor);\n });\n }\n },\n\n /**\n * Creates an iframe with a specific document-unique name.\n *\n * @param id ID of the associated file\n * @returns {HTMLIFrameElement}\n */\n _createIframe: function(id) {\n var iframeName = handler._getIframeName(id);\n\n return initIframeForUpload(iframeName);\n },\n\n /**\n * Called when we are no longer interested in being notified when an iframe has loaded.\n *\n * @param id Associated file ID\n */\n _detachLoadEvent: function(id) {\n if (detachLoadEvents[id] !== undefined) {\n detachLoadEvents[id]();\n delete detachLoadEvents[id];\n }\n },\n\n /**\n * @param fileId ID of the associated file\n * @returns {string} The `document`-unique name of the iframe\n */\n _getIframeName: function(fileId) {\n return fileId + \"_\" + formHandlerInstanceId;\n },\n\n /**\n * Generates a form element and appends it to the `document`. When the form is submitted, a specific iframe is targeted.\n * The name of the iframe is passed in as a property of the spec parameter, and must be unique in the `document`. Note\n * that the form is hidden from view.\n *\n * @param spec An object containing various properties to be used when constructing the form. Required properties are\n * currently: `method`, `endpoint`, `params`, `paramsInBody`, and `targetName`.\n * @returns {HTMLFormElement} The created form\n */\n _initFormForUpload: function(spec) {\n var method = spec.method,\n endpoint = spec.endpoint,\n params = spec.params,\n paramsInBody = spec.paramsInBody,\n targetName = spec.targetName,\n form = qq.toElement(\"\"),\n url = endpoint;\n\n if (paramsInBody) {\n qq.obj2Inputs(params, form);\n }\n else {\n url = qq.obj2url(params, endpoint);\n }\n\n form.setAttribute(\"action\", url);\n form.setAttribute(\"target\", targetName);\n form.style.display = \"none\";\n document.body.appendChild(form);\n\n return form;\n },\n\n /**\n * @param innerHtmlOrMessage JSON message\n * @returns {*} The parsed response, or an empty object if the response could not be parsed\n */\n _parseJsonResponse: function(innerHtmlOrMessage) {\n var response = {};\n\n try {\n response = qq.parseJson(innerHtmlOrMessage);\n }\n catch (error) {\n log(\"Error when attempting to parse iframe upload response (\" + error.message + \")\", \"error\");\n }\n\n return response;\n }\n });\n};\n","/* globals qq */\n/**\n * Common API exposed to creators of XHR handlers. This is reused and possibly overriding in some cases by specific\n * XHR upload handlers.\n *\n * @constructor\n */\nqq.XhrUploadHandler = function(spec) {\n \"use strict\";\n\n var handler = this,\n namespace = spec.options.namespace,\n proxy = spec.proxy,\n chunking = spec.options.chunking,\n getChunkSize = function(id) {\n var fileState = handler._getFileState(id);\n\n if (fileState.chunkSize) {\n return fileState.chunkSize;\n }\n\n else {\n var chunkSize = chunking.partSize;\n\n if (qq.isFunction(chunkSize)) {\n chunkSize = chunkSize(id, getSize(id));\n }\n\n fileState.chunkSize = chunkSize;\n return chunkSize;\n }\n },\n resume = spec.options.resume,\n chunkFiles = chunking && spec.options.chunking.enabled && qq.supportedFeatures.chunking,\n resumeEnabled = resume && spec.options.resume.enabled && chunkFiles && qq.supportedFeatures.resume,\n getName = proxy.getName,\n getSize = proxy.getSize,\n getUuid = proxy.getUuid,\n getEndpoint = proxy.getEndpoint,\n getDataByUuid = proxy.getDataByUuid,\n onUuidChanged = proxy.onUuidChanged,\n onProgress = proxy.onProgress,\n log = proxy.log,\n getCustomResumeData = proxy.getCustomResumeData;\n\n function abort(id) {\n qq.each(handler._getXhrs(id), function(xhrId, xhr) {\n var ajaxRequester = handler._getAjaxRequester(id, xhrId);\n\n xhr.onreadystatechange = null;\n xhr.upload.onprogress = null;\n xhr.abort();\n ajaxRequester && ajaxRequester.canceled && ajaxRequester.canceled(id);\n });\n }\n\n qq.extend(this, new qq.UploadHandler(spec));\n\n qq.override(this, function(super_) {\n return {\n /**\n * Adds File or Blob to the queue\n **/\n add: function(id, blobOrProxy) {\n if (qq.isFile(blobOrProxy) || qq.isBlob(blobOrProxy)) {\n super_.add(id, {file: blobOrProxy});\n }\n else if (blobOrProxy instanceof qq.BlobProxy) {\n super_.add(id, {proxy: blobOrProxy});\n }\n else {\n throw new Error(\"Passed obj is not a File, Blob, or proxy\");\n }\n\n handler._initTempState(id);\n resumeEnabled && handler._maybePrepareForResume(id);\n },\n\n expunge: function(id) {\n abort(id);\n handler._maybeDeletePersistedChunkData(id);\n handler._clearXhrs(id);\n super_.expunge(id);\n }\n };\n });\n\n qq.extend(this, {\n // Clear the cached chunk `Blob` after we are done with it, just in case the `Blob` bytes are stored in memory.\n clearCachedChunk: function(id, chunkIdx) {\n var fileState = handler._getFileState(id);\n\n if (fileState) {\n delete fileState.temp.cachedChunks[chunkIdx];\n }\n },\n\n clearXhr: function(id, chunkIdx) {\n var tempState = handler._getFileState(id).temp;\n\n if (tempState.xhrs) {\n delete tempState.xhrs[chunkIdx];\n }\n if (tempState.ajaxRequesters) {\n delete tempState.ajaxRequesters[chunkIdx];\n }\n },\n\n // Called when all chunks have been successfully uploaded. Expected promissory return type.\n // This defines the default behavior if nothing further is required when all chunks have been uploaded.\n finalizeChunks: function(id, responseParser) {\n var lastChunkIdx = handler._getTotalChunks(id) - 1,\n xhr = handler._getXhr(id, lastChunkIdx);\n\n if (responseParser) {\n return new qq.Promise().success(responseParser(xhr), xhr);\n }\n\n return new qq.Promise().success({}, xhr);\n },\n\n getFile: function(id) {\n return handler.isValid(id) && handler._getFileState(id).file;\n },\n\n getProxy: function(id) {\n return handler.isValid(id) && handler._getFileState(id).proxy;\n },\n\n /**\n * @returns {Array} Array of objects containing properties useful to integrators\n * when it is important to determine which files are potentially resumable.\n */\n getResumableFilesData: function() {\n var resumableFilesData = [];\n\n handler._iterateResumeRecords(function(key, uploadData) {\n handler.moveInProgressToRemaining(null, uploadData.chunking.inProgress, uploadData.chunking.remaining);\n\n var data = {\n name: uploadData.name,\n remaining: uploadData.chunking.remaining,\n size: uploadData.size,\n uuid: uploadData.uuid\n };\n\n if (uploadData.key) {\n data.key = uploadData.key;\n }\n\n if (uploadData.customResumeData) {\n data.customResumeData = uploadData.customResumeData;\n }\n\n resumableFilesData.push(data);\n });\n\n return resumableFilesData;\n },\n\n isAttemptingResume: function(id) {\n return handler._getFileState(id).attemptingResume;\n },\n\n isResumable: function(id) {\n return !!chunking && handler.isValid(id) &&\n !handler._getFileState(id).notResumable;\n },\n\n moveInProgressToRemaining: function(id, optInProgress, optRemaining) {\n var fileState = handler._getFileState(id) || {},\n chunkingState = fileState.chunking || {},\n inProgress = optInProgress || chunkingState.inProgress,\n remaining = optRemaining || chunkingState.remaining;\n\n if (inProgress) {\n log(qq.format(\"Moving these chunks from in-progress {}, to remaining.\", JSON.stringify(inProgress)));\n inProgress.reverse();\n qq.each(inProgress, function(idx, chunkIdx) {\n remaining.unshift(chunkIdx);\n });\n inProgress.length = 0;\n }\n },\n\n pause: function(id) {\n if (handler.isValid(id)) {\n log(qq.format(\"Aborting XHR upload for {} '{}' due to pause instruction.\", id, getName(id)));\n handler._getFileState(id).paused = true;\n abort(id);\n return true;\n }\n },\n\n reevaluateChunking: function(id) {\n if (chunking && handler.isValid(id)) {\n var state = handler._getFileState(id),\n totalChunks,\n i;\n\n delete state.chunking;\n\n state.chunking = {};\n totalChunks = handler._getTotalChunks(id);\n if (totalChunks > 1 || chunking.mandatory) {\n state.chunking.enabled = true;\n state.chunking.parts = totalChunks;\n state.chunking.remaining = [];\n\n for (i = 0; i < totalChunks; i++) {\n state.chunking.remaining.push(i);\n }\n\n handler._initTempState(id);\n }\n else {\n state.chunking.enabled = false;\n }\n }\n },\n\n updateBlob: function(id, newBlob) {\n if (handler.isValid(id)) {\n handler._getFileState(id).file = newBlob;\n }\n },\n\n _clearXhrs: function(id) {\n var tempState = handler._getFileState(id).temp;\n\n qq.each(tempState.ajaxRequesters, function(chunkId) {\n delete tempState.ajaxRequesters[chunkId];\n });\n\n qq.each(tempState.xhrs, function(chunkId) {\n delete tempState.xhrs[chunkId];\n });\n },\n\n /**\n * Creates an XHR instance for this file and stores it in the fileState.\n *\n * @param id File ID\n * @param optChunkIdx The chunk index associated with this XHR, if applicable\n * @returns {XMLHttpRequest}\n */\n _createXhr: function(id, optChunkIdx) {\n return handler._registerXhr(id, optChunkIdx, qq.createXhrInstance());\n },\n\n _getAjaxRequester: function(id, optChunkIdx) {\n var chunkIdx = optChunkIdx == null ? -1 : optChunkIdx;\n return handler._getFileState(id).temp.ajaxRequesters[chunkIdx];\n },\n\n _getChunkData: function(id, chunkIndex) {\n var chunkSize = getChunkSize(id),\n fileSize = getSize(id),\n fileOrBlob = handler.getFile(id),\n startBytes = chunkSize * chunkIndex,\n endBytes = startBytes + chunkSize >= fileSize ? fileSize : startBytes + chunkSize,\n totalChunks = handler._getTotalChunks(id),\n cachedChunks = this._getFileState(id).temp.cachedChunks,\n\n // To work around a Webkit GC bug, we must keep each chunk `Blob` in scope until we are done with it.\n // See https://github.com/FineUploader/fine-uploader/issues/937#issuecomment-41418760\n blob = cachedChunks[chunkIndex] || qq.sliceBlob(fileOrBlob, startBytes, endBytes);\n\n cachedChunks[chunkIndex] = blob;\n\n return {\n part: chunkIndex,\n start: startBytes,\n end: endBytes,\n count: totalChunks,\n blob: blob,\n size: endBytes - startBytes\n };\n },\n\n _getChunkDataForCallback: function(chunkData) {\n return {\n partIndex: chunkData.part,\n startByte: chunkData.start + 1,\n endByte: chunkData.end,\n totalParts: chunkData.count\n };\n },\n\n /**\n * @param id File ID\n * @returns {string} Identifier for this item that may appear in the browser's local storage\n */\n _getLocalStorageId: function(id) {\n var formatVersion = \"5.0\",\n name = getName(id),\n size = getSize(id),\n chunkSize = getChunkSize(id),\n endpoint = getEndpoint(id),\n customKeys = resume.customKeys(id),\n localStorageId = qq.format(\"qq{}resume{}-{}-{}-{}-{}\", namespace, formatVersion, name, size, chunkSize, endpoint);\n\n customKeys.forEach(function(key) {\n localStorageId += \"-\" + key;\n });\n\n return localStorageId;\n },\n\n _getMimeType: function(id) {\n return handler.getFile(id).type;\n },\n\n _getPersistableData: function(id) {\n return handler._getFileState(id).chunking;\n },\n\n /**\n * @param id ID of the associated file\n * @returns {number} Number of parts this file can be divided into, or undefined if chunking is not supported in this UA\n */\n _getTotalChunks: function(id) {\n if (chunking) {\n var fileSize = getSize(id),\n chunkSize = getChunkSize(id);\n\n return Math.ceil(fileSize / chunkSize);\n }\n },\n\n _getXhr: function(id, optChunkIdx) {\n var chunkIdx = optChunkIdx == null ? -1 : optChunkIdx;\n return handler._getFileState(id).temp.xhrs[chunkIdx];\n },\n\n _getXhrs: function(id) {\n return handler._getFileState(id).temp.xhrs;\n },\n\n // Iterates through all XHR handler-created resume records (in local storage),\n // invoking the passed callback and passing in the key and value of each local storage record.\n _iterateResumeRecords: function(callback) {\n if (resumeEnabled) {\n qq.each(localStorage, function(key, item) {\n if (key.indexOf(qq.format(\"qq{}resume\", namespace)) === 0) {\n var uploadData = JSON.parse(item);\n callback(key, uploadData);\n }\n });\n }\n },\n\n _initTempState: function(id) {\n handler._getFileState(id).temp = {\n ajaxRequesters: {},\n chunkProgress: {},\n xhrs: {},\n cachedChunks: {}\n };\n },\n\n _markNotResumable: function(id) {\n handler._getFileState(id).notResumable = true;\n },\n\n // Removes a chunked upload record from local storage, if possible.\n // Returns true if the item was removed, false otherwise.\n _maybeDeletePersistedChunkData: function(id) {\n var localStorageId;\n\n if (resumeEnabled && handler.isResumable(id)) {\n localStorageId = handler._getLocalStorageId(id);\n\n if (localStorageId && localStorage.getItem(localStorageId)) {\n localStorage.removeItem(localStorageId);\n return true;\n }\n }\n\n return false;\n },\n\n // If this is a resumable upload, grab the relevant data from storage and items in memory that track this upload\n // so we can pick up from where we left off.\n _maybePrepareForResume: function(id) {\n var state = handler._getFileState(id),\n localStorageId, persistedData;\n\n // Resume is enabled and possible and this is the first time we've tried to upload this file in this session,\n // so prepare for a resume attempt.\n if (resumeEnabled && state.key === undefined) {\n localStorageId = handler._getLocalStorageId(id);\n persistedData = localStorage.getItem(localStorageId);\n\n // If we found this item in local storage, maybe we should resume it.\n if (persistedData) {\n persistedData = JSON.parse(persistedData);\n\n // If we found a resume record but we have already handled this file in this session,\n // don't try to resume it & ensure we don't persist future check data\n if (getDataByUuid(persistedData.uuid)) {\n handler._markNotResumable(id);\n }\n else {\n log(qq.format(\"Identified file with ID {} and name of {} as resumable.\", id, getName(id)));\n\n onUuidChanged(id, persistedData.uuid);\n\n state.key = persistedData.key;\n state.chunking = persistedData.chunking;\n state.loaded = persistedData.loaded;\n state.customResumeData = persistedData.customResumeData;\n state.attemptingResume = true;\n\n handler.moveInProgressToRemaining(id);\n }\n }\n }\n },\n\n // Persist any data needed to resume this upload in a new session.\n _maybePersistChunkedState: function(id) {\n var state = handler._getFileState(id),\n localStorageId, persistedData;\n\n // If local storage isn't supported by the browser, or if resume isn't enabled or possible, give up\n if (resumeEnabled && handler.isResumable(id)) {\n var customResumeData = getCustomResumeData(id);\n\n localStorageId = handler._getLocalStorageId(id);\n\n persistedData = {\n name: getName(id),\n size: getSize(id),\n uuid: getUuid(id),\n key: state.key,\n chunking: state.chunking,\n loaded: state.loaded,\n lastUpdated: Date.now(),\n };\n\n if (customResumeData) {\n persistedData.customResumeData = customResumeData;\n }\n\n try {\n localStorage.setItem(localStorageId, JSON.stringify(persistedData));\n }\n catch (error) {\n log(qq.format(\"Unable to save resume data for '{}' due to error: '{}'.\", id, error.toString()), \"warn\");\n }\n }\n },\n\n _registerProgressHandler: function(id, chunkIdx, chunkSize) {\n var xhr = handler._getXhr(id, chunkIdx),\n name = getName(id),\n progressCalculator = {\n simple: function(loaded, total) {\n var fileSize = getSize(id);\n\n if (loaded === total) {\n onProgress(id, name, fileSize, fileSize);\n }\n else {\n onProgress(id, name, (loaded >= fileSize ? fileSize - 1 : loaded), fileSize);\n }\n },\n\n chunked: function(loaded, total) {\n var chunkProgress = handler._getFileState(id).temp.chunkProgress,\n totalSuccessfullyLoadedForFile = handler._getFileState(id).loaded,\n loadedForRequest = loaded,\n totalForRequest = total,\n totalFileSize = getSize(id),\n estActualChunkLoaded = loadedForRequest - (totalForRequest - chunkSize),\n totalLoadedForFile = totalSuccessfullyLoadedForFile;\n\n chunkProgress[chunkIdx] = estActualChunkLoaded;\n\n qq.each(chunkProgress, function(chunkIdx, chunkLoaded) {\n totalLoadedForFile += chunkLoaded;\n });\n\n onProgress(id, name, totalLoadedForFile, totalFileSize);\n }\n };\n\n xhr.upload.onprogress = function(e) {\n if (e.lengthComputable) {\n /* jshint eqnull: true */\n var type = chunkSize == null ? \"simple\" : \"chunked\";\n progressCalculator[type](e.loaded, e.total);\n }\n };\n },\n\n /**\n * Registers an XHR transport instance created elsewhere.\n *\n * @param id ID of the associated file\n * @param optChunkIdx The chunk index associated with this XHR, if applicable\n * @param xhr XMLHttpRequest object instance\n * @param optAjaxRequester `qq.AjaxRequester` associated with this request, if applicable.\n * @returns {XMLHttpRequest}\n */\n _registerXhr: function(id, optChunkIdx, xhr, optAjaxRequester) {\n var xhrsId = optChunkIdx == null ? -1 : optChunkIdx,\n tempState = handler._getFileState(id).temp;\n\n tempState.xhrs = tempState.xhrs || {};\n tempState.ajaxRequesters = tempState.ajaxRequesters || {};\n\n tempState.xhrs[xhrsId] = xhr;\n\n if (optAjaxRequester) {\n tempState.ajaxRequesters[xhrsId] = optAjaxRequester;\n }\n\n return xhr;\n },\n\n // Deletes any local storage records that are \"expired\".\n _removeExpiredChunkingRecords: function() {\n var expirationDays = resume.recordsExpireIn;\n\n handler._iterateResumeRecords(function(key, uploadData) {\n var expirationDate = new Date(uploadData.lastUpdated);\n\n // transform updated date into expiration date\n expirationDate.setDate(expirationDate.getDate() + expirationDays);\n\n if (expirationDate.getTime() <= Date.now()) {\n log(\"Removing expired resume record with key \" + key);\n localStorage.removeItem(key);\n }\n });\n },\n\n /**\n * Determine if the associated file should be chunked.\n *\n * @param id ID of the associated file\n * @returns {*} true if chunking is enabled, possible, and the file can be split into more than 1 part\n */\n _shouldChunkThisFile: function(id) {\n var state = handler._getFileState(id);\n\n // file may no longer be available if it was recently cancelled\n if (state) {\n if (!state.chunking) {\n handler.reevaluateChunking(id);\n }\n\n return state.chunking.enabled;\n }\n }\n });\n};\n","/*globals qq, XMLHttpRequest*/\nqq.DeleteFileAjaxRequester = function(o) {\n \"use strict\";\n\n var requester,\n options = {\n method: \"DELETE\",\n uuidParamName: \"qquuid\",\n endpointStore: {},\n maxConnections: 3,\n customHeaders: function(id) {return {};},\n paramsStore: {},\n cors: {\n expected: false,\n sendCredentials: false\n },\n log: function(str, level) {},\n onDelete: function(id) {},\n onDeleteComplete: function(id, xhrOrXdr, isError) {}\n };\n\n qq.extend(options, o);\n\n function getMandatedParams() {\n if (options.method.toUpperCase() === \"POST\") {\n return {\n _method: \"DELETE\"\n };\n }\n\n return {};\n }\n\n requester = qq.extend(this, new qq.AjaxRequester({\n acceptHeader: \"application/json\",\n validMethods: [\"POST\", \"DELETE\"],\n method: options.method,\n endpointStore: options.endpointStore,\n paramsStore: options.paramsStore,\n mandatedParams: getMandatedParams(),\n maxConnections: options.maxConnections,\n customHeaders: function(id) {\n return options.customHeaders.get(id);\n },\n log: options.log,\n onSend: options.onDelete,\n onComplete: options.onDeleteComplete,\n cors: options.cors\n }));\n\n qq.extend(this, {\n sendDelete: function(id, uuid, additionalMandatedParams) {\n var additionalOptions = additionalMandatedParams || {};\n\n options.log(\"Submitting delete file request for \" + id);\n\n if (options.method === \"DELETE\") {\n requester.initTransport(id)\n .withPath(uuid)\n .withParams(additionalOptions)\n .send();\n }\n else {\n additionalOptions[options.uuidParamName] = uuid;\n requester.initTransport(id)\n .withParams(additionalOptions)\n .send();\n }\n }\n });\n};\n","/*global qq, define */\n/*jshint strict:false,bitwise:false,nonew:false,asi:true,-W064,-W116,-W089 */\n/**\n * Mega pixel image rendering library for iOS6+\n *\n * Fixes iOS6+'s image file rendering issue for large size image (over mega-pixel),\n * which causes unexpected subsampling when drawing it in canvas.\n * By using this library, you can safely render the image with proper stretching.\n *\n * Copyright (c) 2012 Shinichi Tomita \n * Released under the MIT license\n *\n * Heavily modified by Widen for Fine Uploader\n */\n(function() {\n\n /**\n * Detect subsampling in loaded image.\n * In iOS, larger images than 2M pixels may be subsampled in rendering.\n */\n function detectSubsampling(img) {\n var iw = img.naturalWidth,\n ih = img.naturalHeight,\n canvas = document.createElement(\"canvas\"),\n ctx;\n\n if (iw * ih > 1024 * 1024) { // subsampling may happen over megapixel image\n canvas.width = canvas.height = 1;\n ctx = canvas.getContext(\"2d\");\n ctx.drawImage(img, -iw + 1, 0);\n // subsampled image becomes half smaller in rendering size.\n // check alpha channel value to confirm image is covering edge pixel or not.\n // if alpha value is 0 image is not covering, hence subsampled.\n return ctx.getImageData(0, 0, 1, 1).data[3] === 0;\n } else {\n return false;\n }\n }\n\n /**\n * Detecting vertical squash in loaded image.\n * Fixes a bug which squash image vertically while drawing into canvas for some images.\n */\n function detectVerticalSquash(img, iw, ih) {\n var canvas = document.createElement(\"canvas\"),\n sy = 0,\n ey = ih,\n py = ih,\n ctx, data, alpha, ratio;\n\n canvas.width = 1;\n canvas.height = ih;\n ctx = canvas.getContext(\"2d\");\n ctx.drawImage(img, 0, 0);\n data = ctx.getImageData(0, 0, 1, ih).data;\n\n // search image edge pixel position in case it is squashed vertically.\n while (py > sy) {\n alpha = data[(py - 1) * 4 + 3];\n if (alpha === 0) {\n ey = py;\n } else {\n sy = py;\n }\n py = (ey + sy) >> 1;\n }\n\n ratio = (py / ih);\n return (ratio === 0) ? 1 : ratio;\n }\n\n /**\n * Rendering image element (with resizing) and get its data URL\n */\n function renderImageToDataURL(img, blob, options, doSquash) {\n var canvas = document.createElement(\"canvas\"),\n mime = options.mime || \"image/jpeg\",\n promise = new qq.Promise();\n\n renderImageToCanvas(img, blob, canvas, options, doSquash)\n .then(function() {\n promise.success(\n canvas.toDataURL(mime, options.quality || 0.8)\n );\n });\n\n return promise;\n }\n\n function maybeCalculateDownsampledDimensions(spec) {\n var maxPixels = 5241000; //iOS specific value\n\n if (!qq.ios()) {\n throw new qq.Error(\"Downsampled dimensions can only be reliably calculated for iOS!\");\n }\n\n if (spec.origHeight * spec.origWidth > maxPixels) {\n return {\n newHeight: Math.round(Math.sqrt(maxPixels * (spec.origHeight / spec.origWidth))),\n newWidth: Math.round(Math.sqrt(maxPixels * (spec.origWidth / spec.origHeight)))\n };\n }\n }\n\n /**\n * Rendering image element (with resizing) into the canvas element\n */\n function renderImageToCanvas(img, blob, canvas, options, doSquash) {\n var iw = img.naturalWidth,\n ih = img.naturalHeight,\n width = options.width,\n height = options.height,\n ctx = canvas.getContext(\"2d\"),\n promise = new qq.Promise(),\n modifiedDimensions;\n\n ctx.save();\n\n if (options.resize) {\n return renderImageToCanvasWithCustomResizer({\n blob: blob,\n canvas: canvas,\n image: img,\n imageHeight: ih,\n imageWidth: iw,\n orientation: options.orientation,\n resize: options.resize,\n targetHeight: height,\n targetWidth: width\n });\n }\n\n if (!qq.supportedFeatures.unlimitedScaledImageSize) {\n modifiedDimensions = maybeCalculateDownsampledDimensions({\n origWidth: width,\n origHeight: height\n });\n\n if (modifiedDimensions) {\n qq.log(qq.format(\"Had to reduce dimensions due to device limitations from {}w / {}h to {}w / {}h\",\n width, height, modifiedDimensions.newWidth, modifiedDimensions.newHeight),\n \"warn\");\n\n width = modifiedDimensions.newWidth;\n height = modifiedDimensions.newHeight;\n }\n }\n\n transformCoordinate(canvas, width, height, options.orientation);\n\n // Fine Uploader specific: Save some CPU cycles if not using iOS\n // Assumption: This logic is only needed to overcome iOS image sampling issues\n if (qq.ios()) {\n (function() {\n if (detectSubsampling(img)) {\n iw /= 2;\n ih /= 2;\n }\n\n var d = 1024, // size of tiling canvas\n tmpCanvas = document.createElement(\"canvas\"),\n vertSquashRatio = doSquash ? detectVerticalSquash(img, iw, ih) : 1,\n dw = Math.ceil(d * width / iw),\n dh = Math.ceil(d * height / ih / vertSquashRatio),\n sy = 0,\n dy = 0,\n tmpCtx, sx, dx;\n\n tmpCanvas.width = tmpCanvas.height = d;\n tmpCtx = tmpCanvas.getContext(\"2d\");\n\n while (sy < ih) {\n sx = 0;\n dx = 0;\n while (sx < iw) {\n tmpCtx.clearRect(0, 0, d, d);\n tmpCtx.drawImage(img, -sx, -sy);\n ctx.drawImage(tmpCanvas, 0, 0, d, d, dx, dy, dw, dh);\n sx += d;\n dx += dw;\n }\n sy += d;\n dy += dh;\n }\n ctx.restore();\n tmpCanvas = tmpCtx = null;\n }());\n }\n else {\n ctx.drawImage(img, 0, 0, width, height);\n }\n\n canvas.qqImageRendered && canvas.qqImageRendered();\n promise.success();\n\n return promise;\n }\n\n function renderImageToCanvasWithCustomResizer(resizeInfo) {\n var blob = resizeInfo.blob,\n image = resizeInfo.image,\n imageHeight = resizeInfo.imageHeight,\n imageWidth = resizeInfo.imageWidth,\n orientation = resizeInfo.orientation,\n promise = new qq.Promise(),\n resize = resizeInfo.resize,\n sourceCanvas = document.createElement(\"canvas\"),\n sourceCanvasContext = sourceCanvas.getContext(\"2d\"),\n targetCanvas = resizeInfo.canvas,\n targetHeight = resizeInfo.targetHeight,\n targetWidth = resizeInfo.targetWidth;\n\n transformCoordinate(sourceCanvas, imageWidth, imageHeight, orientation);\n\n targetCanvas.height = targetHeight;\n targetCanvas.width = targetWidth;\n\n sourceCanvasContext.drawImage(image, 0, 0);\n\n resize({\n blob: blob,\n height: targetHeight,\n image: image,\n sourceCanvas: sourceCanvas,\n targetCanvas: targetCanvas,\n width: targetWidth\n })\n .then(\n function success() {\n targetCanvas.qqImageRendered && targetCanvas.qqImageRendered();\n promise.success();\n },\n promise.failure\n );\n\n return promise;\n }\n\n /**\n * Transform canvas coordination according to specified frame size and orientation\n * Orientation value is from EXIF tag\n */\n function transformCoordinate(canvas, width, height, orientation) {\n switch (orientation) {\n case 5:\n case 6:\n case 7:\n case 8:\n canvas.width = height;\n canvas.height = width;\n break;\n default:\n canvas.width = width;\n canvas.height = height;\n }\n var ctx = canvas.getContext(\"2d\");\n switch (orientation) {\n case 2:\n // horizontal flip\n ctx.translate(width, 0);\n ctx.scale(-1, 1);\n break;\n case 3:\n // 180 rotate left\n ctx.translate(width, height);\n ctx.rotate(Math.PI);\n break;\n case 4:\n // vertical flip\n ctx.translate(0, height);\n ctx.scale(1, -1);\n break;\n case 5:\n // vertical flip + 90 rotate right\n ctx.rotate(0.5 * Math.PI);\n ctx.scale(1, -1);\n break;\n case 6:\n // 90 rotate right\n ctx.rotate(0.5 * Math.PI);\n ctx.translate(0, -height);\n break;\n case 7:\n // horizontal flip + 90 rotate right\n ctx.rotate(0.5 * Math.PI);\n ctx.translate(width, -height);\n ctx.scale(-1, 1);\n break;\n case 8:\n // 90 rotate left\n ctx.rotate(-0.5 * Math.PI);\n ctx.translate(-width, 0);\n break;\n default:\n break;\n }\n }\n\n /**\n * MegaPixImage class\n */\n function MegaPixImage(srcImage, errorCallback) {\n var self = this;\n\n if (window.Blob && srcImage instanceof Blob) {\n (function() {\n var img = new Image(),\n URL = window.URL && window.URL.createObjectURL ? window.URL :\n window.webkitURL && window.webkitURL.createObjectURL ? window.webkitURL : null;\n if (!URL) { throw Error(\"No createObjectURL function found to create blob url\"); }\n img.src = URL.createObjectURL(srcImage);\n self.blob = srcImage;\n srcImage = img;\n }());\n }\n if (!srcImage.naturalWidth && !srcImage.naturalHeight) {\n srcImage.onload = function() {\n var listeners = self.imageLoadListeners;\n if (listeners) {\n self.imageLoadListeners = null;\n // IE11 doesn't reliably report actual image dimensions immediately after onload for small files,\n // so let's push this to the end of the UI thread queue.\n setTimeout(function() {\n for (var i = 0, len = listeners.length; i < len; i++) {\n listeners[i]();\n }\n }, 0);\n }\n };\n srcImage.onerror = errorCallback;\n this.imageLoadListeners = [];\n }\n this.srcImage = srcImage;\n }\n\n /**\n * Rendering megapix image into specified target element\n */\n MegaPixImage.prototype.render = function(target, options) {\n options = options || {};\n\n var self = this,\n imgWidth = this.srcImage.naturalWidth,\n imgHeight = this.srcImage.naturalHeight,\n width = options.width,\n height = options.height,\n maxWidth = options.maxWidth,\n maxHeight = options.maxHeight,\n doSquash = !this.blob || this.blob.type === \"image/jpeg\",\n tagName = target.tagName.toLowerCase(),\n opt;\n\n if (this.imageLoadListeners) {\n this.imageLoadListeners.push(function() { self.render(target, options); });\n return;\n }\n\n if (width && !height) {\n height = (imgHeight * width / imgWidth) << 0;\n } else if (height && !width) {\n width = (imgWidth * height / imgHeight) << 0;\n } else {\n width = imgWidth;\n height = imgHeight;\n }\n if (maxWidth && width > maxWidth) {\n width = maxWidth;\n height = (imgHeight * width / imgWidth) << 0;\n }\n if (maxHeight && height > maxHeight) {\n height = maxHeight;\n width = (imgWidth * height / imgHeight) << 0;\n }\n\n opt = { width: width, height: height },\n qq.each(options, function(optionsKey, optionsValue) {\n opt[optionsKey] = optionsValue;\n });\n\n if (tagName === \"img\") {\n (function() {\n var oldTargetSrc = target.src;\n renderImageToDataURL(self.srcImage, self.blob, opt, doSquash)\n .then(function(dataUri) {\n target.src = dataUri;\n oldTargetSrc === target.src && target.onload();\n });\n }());\n } else if (tagName === \"canvas\") {\n renderImageToCanvas(this.srcImage, this.blob, target, opt, doSquash);\n }\n if (typeof this.onrender === \"function\") {\n this.onrender(target);\n }\n };\n\n qq.MegaPixImage = MegaPixImage;\n})();\n","/*globals qq */\n/**\n * Draws a thumbnail of a Blob/File/URL onto an or .\n *\n * @constructor\n */\nqq.ImageGenerator = function(log) {\n \"use strict\";\n\n function isImg(el) {\n return el.tagName.toLowerCase() === \"img\";\n }\n\n function isCanvas(el) {\n return el.tagName.toLowerCase() === \"canvas\";\n }\n\n function isImgCorsSupported() {\n return new Image().crossOrigin !== undefined;\n }\n\n function isCanvasSupported() {\n var canvas = document.createElement(\"canvas\");\n\n return canvas.getContext && canvas.getContext(\"2d\");\n }\n\n // This is only meant to determine the MIME type of a renderable image file.\n // It is used to ensure images drawn from a URL that have transparent backgrounds\n // are rendered correctly, among other things.\n function determineMimeOfFileName(nameWithPath) {\n /*jshint -W015 */\n var pathSegments = nameWithPath.split(\"/\"),\n name = pathSegments[pathSegments.length - 1].split(\"?\")[0],\n extension = qq.getExtension(name);\n\n extension = extension && extension.toLowerCase();\n\n switch (extension) {\n case \"jpeg\":\n case \"jpg\":\n return \"image/jpeg\";\n case \"png\":\n return \"image/png\";\n case \"bmp\":\n return \"image/bmp\";\n case \"gif\":\n return \"image/gif\";\n case \"tiff\":\n case \"tif\":\n return \"image/tiff\";\n }\n }\n\n // This will likely not work correctly in IE8 and older.\n // It's only used as part of a formula to determine\n // if a canvas can be used to scale a server-hosted thumbnail.\n // If canvas isn't supported by the UA (IE8 and older)\n // this method should not even be called.\n function isCrossOrigin(url) {\n var targetAnchor = document.createElement(\"a\"),\n targetProtocol, targetHostname, targetPort;\n\n targetAnchor.href = url;\n\n targetProtocol = targetAnchor.protocol;\n targetPort = targetAnchor.port;\n targetHostname = targetAnchor.hostname;\n\n if (targetProtocol.toLowerCase() !== window.location.protocol.toLowerCase()) {\n return true;\n }\n\n if (targetHostname.toLowerCase() !== window.location.hostname.toLowerCase()) {\n return true;\n }\n\n // IE doesn't take ports into consideration when determining if two endpoints are same origin.\n if (targetPort !== window.location.port && !qq.ie()) {\n return true;\n }\n\n return false;\n }\n\n function registerImgLoadListeners(img, promise) {\n img.onload = function() {\n img.onload = null;\n img.onerror = null;\n promise.success(img);\n };\n\n img.onerror = function() {\n img.onload = null;\n img.onerror = null;\n log(\"Problem drawing thumbnail!\", \"error\");\n promise.failure(img, \"Problem drawing thumbnail!\");\n };\n }\n\n function registerCanvasDrawImageListener(canvas, promise) {\n // The image is drawn on the canvas by a third-party library,\n // and we want to know when this is completed. Since the library\n // may invoke drawImage many times in a loop, we need to be called\n // back when the image is fully rendered. So, we are expecting the\n // code that draws this image to follow a convention that involves a\n // function attached to the canvas instance be invoked when it is done.\n canvas.qqImageRendered = function() {\n promise.success(canvas);\n };\n }\n\n // Fulfills a `qq.Promise` when an image has been drawn onto the target,\n // whether that is a or an . The attempt is considered a\n // failure if the target is not an or a , or if the drawing\n // attempt was not successful.\n function registerThumbnailRenderedListener(imgOrCanvas, promise) {\n var registered = isImg(imgOrCanvas) || isCanvas(imgOrCanvas);\n\n if (isImg(imgOrCanvas)) {\n registerImgLoadListeners(imgOrCanvas, promise);\n }\n else if (isCanvas(imgOrCanvas)) {\n registerCanvasDrawImageListener(imgOrCanvas, promise);\n }\n else {\n promise.failure(imgOrCanvas);\n log(qq.format(\"Element container of type {} is not supported!\", imgOrCanvas.tagName), \"error\");\n }\n\n return registered;\n }\n\n // Draw a preview iff the current UA can natively display it.\n // Also rotate the image if necessary.\n function draw(fileOrBlob, container, options) {\n var drawPreview = new qq.Promise(),\n identifier = new qq.Identify(fileOrBlob, log),\n maxSize = options.maxSize,\n // jshint eqnull:true\n orient = options.orient == null ? true : options.orient,\n megapixErrorHandler = function() {\n container.onerror = null;\n container.onload = null;\n log(\"Could not render preview, file may be too large!\", \"error\");\n drawPreview.failure(container, \"Browser cannot render image!\");\n };\n\n identifier.isPreviewable().then(\n function(mime) {\n // If options explicitly specify that Orientation is not desired,\n // replace the orient task with a dummy promise that \"succeeds\" immediately.\n var dummyExif = {\n parse: function() {\n return new qq.Promise().success();\n }\n },\n exif = orient ? new qq.Exif(fileOrBlob, log) : dummyExif,\n mpImg = new qq.MegaPixImage(fileOrBlob, megapixErrorHandler);\n\n if (registerThumbnailRenderedListener(container, drawPreview)) {\n exif.parse().then(\n function(exif) {\n var orientation = exif && exif.Orientation;\n\n mpImg.render(container, {\n maxWidth: maxSize,\n maxHeight: maxSize,\n orientation: orientation,\n mime: mime,\n resize: options.customResizeFunction\n });\n },\n\n function(failureMsg) {\n log(qq.format(\"EXIF data could not be parsed ({}). Assuming orientation = 1.\", failureMsg));\n\n mpImg.render(container, {\n maxWidth: maxSize,\n maxHeight: maxSize,\n mime: mime,\n resize: options.customResizeFunction\n });\n }\n );\n }\n },\n\n function() {\n log(\"Not previewable\");\n drawPreview.failure(container, \"Not previewable\");\n }\n );\n\n return drawPreview;\n }\n\n function drawOnCanvasOrImgFromUrl(url, canvasOrImg, draw, maxSize, customResizeFunction) {\n var tempImg = new Image(),\n tempImgRender = new qq.Promise();\n\n registerThumbnailRenderedListener(tempImg, tempImgRender);\n\n if (isCrossOrigin(url)) {\n tempImg.crossOrigin = \"anonymous\";\n }\n\n tempImg.src = url;\n\n tempImgRender.then(\n function rendered() {\n registerThumbnailRenderedListener(canvasOrImg, draw);\n\n var mpImg = new qq.MegaPixImage(tempImg);\n mpImg.render(canvasOrImg, {\n maxWidth: maxSize,\n maxHeight: maxSize,\n mime: determineMimeOfFileName(url),\n resize: customResizeFunction\n });\n },\n\n draw.failure\n );\n }\n\n function drawOnImgFromUrlWithCssScaling(url, img, draw, maxSize) {\n registerThumbnailRenderedListener(img, draw);\n // NOTE: The fact that maxWidth/height is set on the thumbnail for scaled images\n // that must drop back to CSS is known and exploited by the templating module.\n // In this module, we pre-render \"waiting\" thumbs for all files immediately after they\n // are submitted, and we must be sure to pass any style associated with the \"waiting\" preview.\n qq(img).css({\n maxWidth: maxSize + \"px\",\n maxHeight: maxSize + \"px\"\n });\n\n img.src = url;\n }\n\n // Draw a (server-hosted) thumbnail given a URL.\n // This will optionally scale the thumbnail as well.\n // It attempts to use to scale, but will fall back\n // to max-width and max-height style properties if the UA\n // doesn't support canvas or if the images is cross-domain and\n // the UA doesn't support the crossorigin attribute on img tags,\n // which is required to scale a cross-origin image using &\n // then export it back to an .\n function drawFromUrl(url, container, options) {\n var draw = new qq.Promise(),\n scale = options.scale,\n maxSize = scale ? options.maxSize : null;\n\n // container is an img, scaling needed\n if (scale && isImg(container)) {\n // Iff canvas is available in this UA, try to use it for scaling.\n // Otherwise, fall back to CSS scaling\n if (isCanvasSupported()) {\n // Attempt to use for image scaling,\n // but we must fall back to scaling via CSS/styles\n // if this is a cross-origin image and the UA doesn't support CORS.\n if (isCrossOrigin(url) && !isImgCorsSupported()) {\n drawOnImgFromUrlWithCssScaling(url, container, draw, maxSize);\n }\n else {\n drawOnCanvasOrImgFromUrl(url, container, draw, maxSize);\n }\n }\n else {\n drawOnImgFromUrlWithCssScaling(url, container, draw, maxSize);\n }\n }\n // container is a canvas, scaling optional\n else if (isCanvas(container)) {\n drawOnCanvasOrImgFromUrl(url, container, draw, maxSize);\n }\n // container is an img & no scaling: just set the src attr to the passed url\n else if (registerThumbnailRenderedListener(container, draw)) {\n container.src = url;\n }\n\n return draw;\n }\n\n qq.extend(this, {\n /**\n * Generate a thumbnail. Depending on the arguments, this may either result in\n * a client-side rendering of an image (if a `Blob` is supplied) or a server-generated\n * image that may optionally be scaled client-side using or CSS/styles (as a fallback).\n *\n * @param fileBlobOrUrl a `File`, `Blob`, or a URL pointing to the image\n * @param container or to contain the preview\n * @param options possible properties include `maxSize` (int), `orient` (bool - default true), resize` (bool - default true), and `customResizeFunction`.\n * @returns qq.Promise fulfilled when the preview has been drawn, or the attempt has failed\n */\n generate: function(fileBlobOrUrl, container, options) {\n if (qq.isString(fileBlobOrUrl)) {\n log(\"Attempting to update thumbnail based on server response.\");\n return drawFromUrl(fileBlobOrUrl, container, options || {});\n }\n else {\n log(\"Attempting to draw client-side image preview.\");\n return draw(fileBlobOrUrl, container, options || {});\n }\n }\n });\n\n /**/\n this._testing = {};\n this._testing.isImg = isImg;\n this._testing.isCanvas = isCanvas;\n this._testing.isCrossOrigin = isCrossOrigin;\n this._testing.determineMimeOfFileName = determineMimeOfFileName;\n /* */\n};\n","/*globals qq */\n/**\n * EXIF image data parser. Currently only parses the Orientation tag value,\n * but this may be expanded to other tags in the future.\n *\n * @param fileOrBlob Attempt to parse EXIF data in this `Blob`\n * @constructor\n */\nqq.Exif = function(fileOrBlob, log) {\n \"use strict\";\n\n // Orientation is the only tag parsed here at this time.\n var TAG_IDS = [274],\n TAG_INFO = {\n 274: {\n name: \"Orientation\",\n bytes: 2\n }\n };\n\n // Convert a little endian (hex string) to big endian (decimal).\n function parseLittleEndian(hex) {\n var result = 0,\n pow = 0;\n\n while (hex.length > 0) {\n result += parseInt(hex.substring(0, 2), 16) * Math.pow(2, pow);\n hex = hex.substring(2, hex.length);\n pow += 8;\n }\n\n return result;\n }\n\n // Find the byte offset, of Application Segment 1 (EXIF).\n // External callers need not supply any arguments.\n function seekToApp1(offset, promise) {\n var theOffset = offset,\n thePromise = promise;\n if (theOffset === undefined) {\n theOffset = 2;\n thePromise = new qq.Promise();\n }\n\n qq.readBlobToHex(fileOrBlob, theOffset, 4).then(function(hex) {\n var match = /^ffe([0-9])/.exec(hex),\n segmentLength;\n\n if (match) {\n if (match[1] !== \"1\") {\n segmentLength = parseInt(hex.slice(4, 8), 16);\n seekToApp1(theOffset + segmentLength + 2, thePromise);\n }\n else {\n thePromise.success(theOffset);\n }\n }\n else {\n thePromise.failure(\"No EXIF header to be found!\");\n }\n });\n\n return thePromise;\n }\n\n // Find the byte offset of Application Segment 1 (EXIF) for valid JPEGs only.\n function getApp1Offset() {\n var promise = new qq.Promise();\n\n qq.readBlobToHex(fileOrBlob, 0, 6).then(function(hex) {\n if (hex.indexOf(\"ffd8\") !== 0) {\n promise.failure(\"Not a valid JPEG!\");\n }\n else {\n seekToApp1().then(function(offset) {\n promise.success(offset);\n },\n function(error) {\n promise.failure(error);\n });\n }\n });\n\n return promise;\n }\n\n // Determine the byte ordering of the EXIF header.\n function isLittleEndian(app1Start) {\n var promise = new qq.Promise();\n\n qq.readBlobToHex(fileOrBlob, app1Start + 10, 2).then(function(hex) {\n promise.success(hex === \"4949\");\n });\n\n return promise;\n }\n\n // Determine the number of directory entries in the EXIF header.\n function getDirEntryCount(app1Start, littleEndian) {\n var promise = new qq.Promise();\n\n qq.readBlobToHex(fileOrBlob, app1Start + 18, 2).then(function(hex) {\n if (littleEndian) {\n return promise.success(parseLittleEndian(hex));\n }\n else {\n promise.success(parseInt(hex, 16));\n }\n });\n\n return promise;\n }\n\n // Get the IFD portion of the EXIF header as a hex string.\n function getIfd(app1Start, dirEntries) {\n var offset = app1Start + 20,\n bytes = dirEntries * 12;\n\n return qq.readBlobToHex(fileOrBlob, offset, bytes);\n }\n\n // Obtain an array of all directory entries (as hex strings) in the EXIF header.\n function getDirEntries(ifdHex) {\n var entries = [],\n offset = 0;\n\n while (offset + 24 <= ifdHex.length) {\n entries.push(ifdHex.slice(offset, offset + 24));\n offset += 24;\n }\n\n return entries;\n }\n\n // Obtain values for all relevant tags and return them.\n function getTagValues(littleEndian, dirEntries) {\n var TAG_VAL_OFFSET = 16,\n tagsToFind = qq.extend([], TAG_IDS),\n vals = {};\n\n qq.each(dirEntries, function(idx, entry) {\n var idHex = entry.slice(0, 4),\n id = littleEndian ? parseLittleEndian(idHex) : parseInt(idHex, 16),\n tagsToFindIdx = tagsToFind.indexOf(id),\n tagValHex, tagName, tagValLength;\n\n if (tagsToFindIdx >= 0) {\n tagName = TAG_INFO[id].name;\n tagValLength = TAG_INFO[id].bytes;\n tagValHex = entry.slice(TAG_VAL_OFFSET, TAG_VAL_OFFSET + (tagValLength * 2));\n vals[tagName] = littleEndian ? parseLittleEndian(tagValHex) : parseInt(tagValHex, 16);\n\n tagsToFind.splice(tagsToFindIdx, 1);\n }\n\n if (tagsToFind.length === 0) {\n return false;\n }\n });\n\n return vals;\n }\n\n qq.extend(this, {\n /**\n * Attempt to parse the EXIF header for the `Blob` associated with this instance.\n *\n * @returns {qq.Promise} To be fulfilled when the parsing is complete.\n * If successful, the parsed EXIF header as an object will be included.\n */\n parse: function() {\n var parser = new qq.Promise(),\n onParseFailure = function(message) {\n log(qq.format(\"EXIF header parse failed: '{}' \", message));\n parser.failure(message);\n };\n\n getApp1Offset().then(function(app1Offset) {\n log(qq.format(\"Moving forward with EXIF header parsing for '{}'\", fileOrBlob.name === undefined ? \"blob\" : fileOrBlob.name));\n\n isLittleEndian(app1Offset).then(function(littleEndian) {\n\n log(qq.format(\"EXIF Byte order is {} endian\", littleEndian ? \"little\" : \"big\"));\n\n getDirEntryCount(app1Offset, littleEndian).then(function(dirEntryCount) {\n\n log(qq.format(\"Found {} APP1 directory entries\", dirEntryCount));\n\n getIfd(app1Offset, dirEntryCount).then(function(ifdHex) {\n var dirEntries = getDirEntries(ifdHex),\n tagValues = getTagValues(littleEndian, dirEntries);\n\n log(\"Successfully parsed some EXIF tags\");\n\n parser.success(tagValues);\n }, onParseFailure);\n }, onParseFailure);\n }, onParseFailure);\n }, onParseFailure);\n\n return parser;\n }\n });\n\n /**/\n this._testing = {};\n this._testing.parseLittleEndian = parseLittleEndian;\n /* */\n};\n","/*globals qq */\nqq.Identify = function(fileOrBlob, log) {\n \"use strict\";\n\n function isIdentifiable(magicBytes, questionableBytes) {\n var identifiable = false,\n magicBytesEntries = [].concat(magicBytes);\n\n qq.each(magicBytesEntries, function(idx, magicBytesArrayEntry) {\n if (questionableBytes.indexOf(magicBytesArrayEntry) === 0) {\n identifiable = true;\n return false;\n }\n });\n\n return identifiable;\n }\n\n qq.extend(this, {\n /**\n * Determines if a Blob can be displayed natively in the current browser. This is done by reading magic\n * bytes in the beginning of the file, so this is an asynchronous operation. Before we attempt to read the\n * file, we will examine the blob's type attribute to save CPU cycles.\n *\n * @returns {qq.Promise} Promise that is fulfilled when identification is complete.\n * If successful, the MIME string is passed to the success handler.\n */\n isPreviewable: function() {\n var self = this,\n identifier = new qq.Promise(),\n previewable = false,\n name = fileOrBlob.name === undefined ? \"blob\" : fileOrBlob.name;\n\n log(qq.format(\"Attempting to determine if {} can be rendered in this browser\", name));\n\n log(\"First pass: check type attribute of blob object.\");\n\n if (this.isPreviewableSync()) {\n log(\"Second pass: check for magic bytes in file header.\");\n\n qq.readBlobToHex(fileOrBlob, 0, 4).then(function(hex) {\n qq.each(self.PREVIEWABLE_MIME_TYPES, function(mime, bytes) {\n if (isIdentifiable(bytes, hex)) {\n // Safari is the only supported browser that can deal with TIFFs natively,\n // so, if this is a TIFF and the UA isn't Safari, declare this file \"non-previewable\".\n if (mime !== \"image/tiff\" || qq.supportedFeatures.tiffPreviews) {\n previewable = true;\n identifier.success(mime);\n }\n\n return false;\n }\n });\n\n log(qq.format(\"'{}' is {} able to be rendered in this browser\", name, previewable ? \"\" : \"NOT\"));\n\n if (!previewable) {\n identifier.failure();\n }\n },\n function() {\n log(\"Error reading file w/ name '\" + name + \"'. Not able to be rendered in this browser.\");\n identifier.failure();\n });\n }\n else {\n identifier.failure();\n }\n\n return identifier;\n },\n\n /**\n * Determines if a Blob can be displayed natively in the current browser. This is done by checking the\n * blob's type attribute. This is a synchronous operation, useful for situations where an asynchronous operation\n * would be challenging to support. Note that the blob's type property is not as accurate as reading the\n * file's magic bytes.\n *\n * @returns {Boolean} true if the blob can be rendered in the current browser\n */\n isPreviewableSync: function() {\n var fileMime = fileOrBlob.type,\n // Assumption: This will only ever be executed in browsers that support `Object.keys`.\n isRecognizedImage = qq.indexOf(Object.keys(this.PREVIEWABLE_MIME_TYPES), fileMime) >= 0,\n previewable = false,\n name = fileOrBlob.name === undefined ? \"blob\" : fileOrBlob.name;\n\n if (isRecognizedImage) {\n if (fileMime === \"image/tiff\") {\n previewable = qq.supportedFeatures.tiffPreviews;\n }\n else {\n previewable = true;\n }\n }\n\n !previewable && log(name + \" is not previewable in this browser per the blob's type attr\");\n\n return previewable;\n }\n });\n};\n\nqq.Identify.prototype.PREVIEWABLE_MIME_TYPES = {\n \"image/jpeg\": \"ffd8ff\",\n \"image/gif\": \"474946\",\n \"image/png\": \"89504e\",\n \"image/bmp\": \"424d\",\n \"image/tiff\": [\"49492a00\", \"4d4d002a\"]\n};\n","/*globals qq*/\n/**\n * Attempts to validate an image, wherever possible.\n *\n * @param blob File or Blob representing a user-selecting image.\n * @param log Uses this to post log messages to the console.\n * @constructor\n */\nqq.ImageValidation = function(blob, log) {\n \"use strict\";\n\n /**\n * @param limits Object with possible image-related limits to enforce.\n * @returns {boolean} true if at least one of the limits has a non-zero value\n */\n function hasNonZeroLimits(limits) {\n var atLeastOne = false;\n\n qq.each(limits, function(limit, value) {\n if (value > 0) {\n atLeastOne = true;\n return false;\n }\n });\n\n return atLeastOne;\n }\n\n /**\n * @returns {qq.Promise} The promise is a failure if we can't obtain the width & height.\n * Otherwise, `success` is called on the returned promise with an object containing\n * `width` and `height` properties.\n */\n function getWidthHeight() {\n var sizeDetermination = new qq.Promise();\n\n new qq.Identify(blob, log).isPreviewable().then(function() {\n var image = new Image(),\n url = window.URL && window.URL.createObjectURL ? window.URL :\n window.webkitURL && window.webkitURL.createObjectURL ? window.webkitURL :\n null;\n\n if (url) {\n image.onerror = function() {\n log(\"Cannot determine dimensions for image. May be too large.\", \"error\");\n sizeDetermination.failure();\n };\n\n image.onload = function() {\n sizeDetermination.success({\n width: this.width,\n height: this.height\n });\n };\n\n image.src = url.createObjectURL(blob);\n }\n else {\n log(\"No createObjectURL function available to generate image URL!\", \"error\");\n sizeDetermination.failure();\n }\n }, sizeDetermination.failure);\n\n return sizeDetermination;\n }\n\n /**\n *\n * @param limits Object with possible image-related limits to enforce.\n * @param dimensions Object containing `width` & `height` properties for the image to test.\n * @returns {String || undefined} The name of the failing limit. Undefined if no failing limits.\n */\n function getFailingLimit(limits, dimensions) {\n var failingLimit;\n\n qq.each(limits, function(limitName, limitValue) {\n if (limitValue > 0) {\n var limitMatcher = /(max|min)(Width|Height)/.exec(limitName),\n dimensionPropName = limitMatcher[2].charAt(0).toLowerCase() + limitMatcher[2].slice(1),\n actualValue = dimensions[dimensionPropName];\n\n /*jshint -W015*/\n switch (limitMatcher[1]) {\n case \"min\":\n if (actualValue < limitValue) {\n failingLimit = limitName;\n return false;\n }\n break;\n case \"max\":\n if (actualValue > limitValue) {\n failingLimit = limitName;\n return false;\n }\n break;\n }\n }\n });\n\n return failingLimit;\n }\n\n /**\n * Validate the associated blob.\n *\n * @param limits\n * @returns {qq.Promise} `success` is called on the promise is the image is valid or\n * if the blob is not an image, or if the image is not verifiable.\n * Otherwise, `failure` with the name of the failing limit.\n */\n this.validate = function(limits) {\n var validationEffort = new qq.Promise();\n\n log(\"Attempting to validate image.\");\n\n if (hasNonZeroLimits(limits)) {\n getWidthHeight().then(function(dimensions) {\n var failingLimit = getFailingLimit(limits, dimensions);\n\n if (failingLimit) {\n validationEffort.failure(failingLimit);\n }\n else {\n validationEffort.success();\n }\n }, validationEffort.success);\n }\n else {\n validationEffort.success();\n }\n\n return validationEffort;\n };\n};\n","/* globals qq */\n/**\n * Module used to control populating the initial list of files.\n *\n * @constructor\n */\nqq.Session = function(spec) {\n \"use strict\";\n\n var options = {\n endpoint: null,\n params: {},\n customHeaders: {},\n cors: {},\n addFileRecord: function(sessionData) {},\n log: function(message, level) {}\n };\n\n qq.extend(options, spec, true);\n\n function isJsonResponseValid(response) {\n if (qq.isArray(response)) {\n return true;\n }\n\n options.log(\"Session response is not an array.\", \"error\");\n }\n\n function handleFileItems(fileItems, success, xhrOrXdr, promise) {\n var someItemsIgnored = false;\n\n success = success && isJsonResponseValid(fileItems);\n\n if (success) {\n qq.each(fileItems, function(idx, fileItem) {\n /* jshint eqnull:true */\n if (fileItem.uuid == null) {\n someItemsIgnored = true;\n options.log(qq.format(\"Session response item {} did not include a valid UUID - ignoring.\", idx), \"error\");\n }\n else if (fileItem.name == null) {\n someItemsIgnored = true;\n options.log(qq.format(\"Session response item {} did not include a valid name - ignoring.\", idx), \"error\");\n }\n else {\n try {\n options.addFileRecord(fileItem);\n return true;\n }\n catch (err) {\n someItemsIgnored = true;\n options.log(err.message, \"error\");\n }\n }\n\n return false;\n });\n }\n\n promise[success && !someItemsIgnored ? \"success\" : \"failure\"](fileItems, xhrOrXdr);\n }\n\n // Initiate a call to the server that will be used to populate the initial file list.\n // Returns a `qq.Promise`.\n this.refresh = function() {\n /*jshint indent:false */\n var refreshEffort = new qq.Promise(),\n refreshCompleteCallback = function(response, success, xhrOrXdr) {\n handleFileItems(response, success, xhrOrXdr, refreshEffort);\n },\n requesterOptions = qq.extend({}, options),\n requester = new qq.SessionAjaxRequester(\n qq.extend(requesterOptions, {onComplete: refreshCompleteCallback})\n );\n\n requester.queryServer();\n\n return refreshEffort;\n };\n};\n","/*globals qq, XMLHttpRequest*/\n/**\n * Thin module used to send GET requests to the server, expecting information about session\n * data used to initialize an uploader instance.\n *\n * @param spec Various options used to influence the associated request.\n * @constructor\n */\nqq.SessionAjaxRequester = function(spec) {\n \"use strict\";\n\n var requester,\n options = {\n endpoint: null,\n customHeaders: {},\n params: {},\n cors: {\n expected: false,\n sendCredentials: false\n },\n onComplete: function(response, success, xhrOrXdr) {},\n log: function(str, level) {}\n };\n\n qq.extend(options, spec);\n\n function onComplete(id, xhrOrXdr, isError) {\n var response = null;\n\n /* jshint eqnull:true */\n if (xhrOrXdr.responseText != null) {\n try {\n response = qq.parseJson(xhrOrXdr.responseText);\n }\n catch (err) {\n options.log(\"Problem parsing session response: \" + err.message, \"error\");\n isError = true;\n }\n }\n\n options.onComplete(response, !isError, xhrOrXdr);\n }\n\n requester = qq.extend(this, new qq.AjaxRequester({\n acceptHeader: \"application/json\",\n validMethods: [\"GET\"],\n method: \"GET\",\n endpointStore: {\n get: function() {\n return options.endpoint;\n }\n },\n customHeaders: options.customHeaders,\n log: options.log,\n onComplete: onComplete,\n cors: options.cors\n }));\n\n qq.extend(this, {\n queryServer: function() {\n var params = qq.extend({}, options.params);\n\n options.log(\"Session query request.\");\n\n requester.initTransport(\"sessionRefresh\")\n .withParams(params)\n .withCacheBuster()\n .send();\n }\n });\n};\n","/* globals qq, ExifRestorer */\n/**\n * Controls generation of scaled images based on a reference image encapsulated in a `File` or `Blob`.\n * Scaled images are generated and converted to blobs on-demand.\n * Multiple scaled images per reference image with varying sizes and other properties are supported.\n *\n * @param spec Information about the scaled images to generate.\n * @param log Logger instance\n * @constructor\n */\nqq.Scaler = function(spec, log) {\n \"use strict\";\n\n var self = this,\n customResizeFunction = spec.customResizer,\n includeOriginal = spec.sendOriginal,\n orient = spec.orient,\n defaultType = spec.defaultType,\n defaultQuality = spec.defaultQuality / 100,\n failedToScaleText = spec.failureText,\n includeExif = spec.includeExif,\n sizes = this._getSortedSizes(spec.sizes);\n\n // Revealed API for instances of this module\n qq.extend(this, {\n // If no targeted sizes have been declared or if this browser doesn't support\n // client-side image preview generation, there is no scaling to do.\n enabled: qq.supportedFeatures.scaling && sizes.length > 0,\n\n getFileRecords: function(originalFileUuid, originalFileName, originalBlobOrBlobData) {\n var self = this,\n records = [],\n originalBlob = originalBlobOrBlobData.blob ? originalBlobOrBlobData.blob : originalBlobOrBlobData,\n identifier = new qq.Identify(originalBlob, log);\n\n // If the reference file cannot be rendered natively, we can't create scaled versions.\n if (identifier.isPreviewableSync()) {\n // Create records for each scaled version & add them to the records array, smallest first.\n qq.each(sizes, function(idx, sizeRecord) {\n var outputType = self._determineOutputType({\n defaultType: defaultType,\n requestedType: sizeRecord.type,\n refType: originalBlob.type\n });\n\n records.push({\n uuid: qq.getUniqueId(),\n name: self._getName(originalFileName, {\n name: sizeRecord.name,\n type: outputType,\n refType: originalBlob.type\n }),\n blob: new qq.BlobProxy(originalBlob,\n qq.bind(self._generateScaledImage, self, {\n customResizeFunction: customResizeFunction,\n maxSize: sizeRecord.maxSize,\n orient: orient,\n type: outputType,\n quality: defaultQuality,\n failedText: failedToScaleText,\n includeExif: includeExif,\n log: log\n }))\n });\n });\n\n records.push({\n uuid: originalFileUuid,\n name: originalFileName,\n size: originalBlob.size,\n blob: includeOriginal ? originalBlob : null\n });\n }\n else {\n records.push({\n uuid: originalFileUuid,\n name: originalFileName,\n size: originalBlob.size,\n blob: originalBlob\n });\n }\n\n return records;\n },\n\n handleNewFile: function(file, name, uuid, size, fileList, batchId, uuidParamName, api) {\n var self = this,\n buttonId = file.qqButtonId || (file.blob && file.blob.qqButtonId),\n scaledIds = [],\n originalId = null,\n addFileToHandler = api.addFileToHandler,\n uploadData = api.uploadData,\n paramsStore = api.paramsStore,\n proxyGroupId = qq.getUniqueId();\n\n qq.each(self.getFileRecords(uuid, name, file), function(idx, record) {\n var blobSize = record.size,\n id;\n\n if (record.blob instanceof qq.BlobProxy) {\n blobSize = -1;\n }\n\n id = uploadData.addFile({\n uuid: record.uuid,\n name: record.name,\n size: blobSize,\n batchId: batchId,\n proxyGroupId: proxyGroupId\n });\n\n if (record.blob instanceof qq.BlobProxy) {\n scaledIds.push(id);\n }\n else {\n originalId = id;\n }\n\n if (record.blob) {\n addFileToHandler(id, record.blob);\n fileList.push({id: id, file: record.blob});\n }\n else {\n uploadData.setStatus(id, qq.status.REJECTED);\n }\n });\n\n // If we are potentially uploading an original file and some scaled versions,\n // ensure the scaled versions include reference's to the parent's UUID and size\n // in their associated upload requests.\n if (originalId !== null) {\n qq.each(scaledIds, function(idx, scaledId) {\n var params = {\n qqparentuuid: uploadData.retrieve({id: originalId}).uuid,\n qqparentsize: uploadData.retrieve({id: originalId}).size\n };\n\n // Make sure the UUID for each scaled image is sent with the upload request,\n // to be consistent (since we may need to ensure it is sent for the original file as well).\n params[uuidParamName] = uploadData.retrieve({id: scaledId}).uuid;\n\n uploadData.setParentId(scaledId, originalId);\n paramsStore.addReadOnly(scaledId, params);\n });\n\n // If any scaled images are tied to this parent image, be SURE we send its UUID as an upload request\n // parameter as well.\n if (scaledIds.length) {\n (function() {\n var param = {};\n param[uuidParamName] = uploadData.retrieve({id: originalId}).uuid;\n paramsStore.addReadOnly(originalId, param);\n }());\n }\n }\n }\n });\n};\n\nqq.extend(qq.Scaler.prototype, {\n scaleImage: function(id, specs, api) {\n \"use strict\";\n\n if (!qq.supportedFeatures.scaling) {\n throw new qq.Error(\"Scaling is not supported in this browser!\");\n }\n\n var scalingEffort = new qq.Promise(),\n log = api.log,\n file = api.getFile(id),\n uploadData = api.uploadData.retrieve({id: id}),\n name = uploadData && uploadData.name,\n uuid = uploadData && uploadData.uuid,\n scalingOptions = {\n customResizer: specs.customResizer,\n sendOriginal: false,\n orient: specs.orient,\n defaultType: specs.type || null,\n defaultQuality: specs.quality,\n failedToScaleText: \"Unable to scale\",\n sizes: [{name: \"\", maxSize: specs.maxSize}]\n },\n scaler = new qq.Scaler(scalingOptions, log);\n\n if (!qq.Scaler || !qq.supportedFeatures.imagePreviews || !file) {\n scalingEffort.failure();\n\n log(\"Could not generate requested scaled image for \" + id + \". \" +\n \"Scaling is either not possible in this browser, or the file could not be located.\", \"error\");\n }\n else {\n (qq.bind(function() {\n // Assumption: There will never be more than one record\n var record = scaler.getFileRecords(uuid, name, file)[0];\n\n if (record && record.blob instanceof qq.BlobProxy) {\n record.blob.create().then(scalingEffort.success, scalingEffort.failure);\n }\n else {\n log(id + \" is not a scalable image!\", \"error\");\n scalingEffort.failure();\n }\n }, this)());\n }\n\n return scalingEffort;\n },\n\n // NOTE: We cannot reliably determine at this time if the UA supports a specific MIME type for the target format.\n // image/jpeg and image/png are the only safe choices at this time.\n _determineOutputType: function(spec) {\n \"use strict\";\n\n var requestedType = spec.requestedType,\n defaultType = spec.defaultType,\n referenceType = spec.refType;\n\n // If a default type and requested type have not been specified, this should be a\n // JPEG if the original type is a JPEG, otherwise, a PNG.\n if (!defaultType && !requestedType) {\n if (referenceType !== \"image/jpeg\") {\n return \"image/png\";\n }\n return referenceType;\n }\n\n // A specified default type is used when a requested type is not specified.\n if (!requestedType) {\n return defaultType;\n }\n\n // If requested type is specified, use it, as long as this recognized type is supported by the current UA\n if (qq.indexOf(Object.keys(qq.Identify.prototype.PREVIEWABLE_MIME_TYPES), requestedType) >= 0) {\n if (requestedType === \"image/tiff\") {\n return qq.supportedFeatures.tiffPreviews ? requestedType : defaultType;\n }\n\n return requestedType;\n }\n\n return defaultType;\n },\n\n // Get a file name for a generated scaled file record, based on the provided scaled image description\n _getName: function(originalName, scaledVersionProperties) {\n \"use strict\";\n\n var startOfExt = originalName.lastIndexOf(\".\"),\n versionType = scaledVersionProperties.type || \"image/png\",\n referenceType = scaledVersionProperties.refType,\n scaledName = \"\",\n scaledExt = qq.getExtension(originalName),\n nameAppendage = \"\";\n\n if (scaledVersionProperties.name && scaledVersionProperties.name.trim().length) {\n nameAppendage = \" (\" + scaledVersionProperties.name + \")\";\n }\n\n if (startOfExt >= 0) {\n scaledName = originalName.substr(0, startOfExt);\n\n if (referenceType !== versionType) {\n scaledExt = versionType.split(\"/\")[1];\n }\n\n scaledName += nameAppendage + \".\" + scaledExt;\n }\n else {\n scaledName = originalName + nameAppendage;\n }\n\n return scaledName;\n },\n\n // We want the smallest scaled file to be uploaded first\n _getSortedSizes: function(sizes) {\n \"use strict\";\n\n sizes = qq.extend([], sizes);\n\n return sizes.sort(function(a, b) {\n if (a.maxSize > b.maxSize) {\n return 1;\n }\n if (a.maxSize < b.maxSize) {\n return -1;\n }\n return 0;\n });\n },\n\n _generateScaledImage: function(spec, sourceFile) {\n \"use strict\";\n\n var self = this,\n customResizeFunction = spec.customResizeFunction,\n log = spec.log,\n maxSize = spec.maxSize,\n orient = spec.orient,\n type = spec.type,\n quality = spec.quality,\n failedText = spec.failedText,\n includeExif = spec.includeExif && sourceFile.type === \"image/jpeg\" && type === \"image/jpeg\",\n scalingEffort = new qq.Promise(),\n imageGenerator = new qq.ImageGenerator(log),\n canvas = document.createElement(\"canvas\");\n\n log(\"Attempting to generate scaled version for \" + sourceFile.name);\n\n imageGenerator.generate(sourceFile, canvas, {maxSize: maxSize, orient: orient, customResizeFunction: customResizeFunction}).then(function() {\n var scaledImageDataUri = canvas.toDataURL(type, quality),\n signalSuccess = function() {\n log(\"Success generating scaled version for \" + sourceFile.name);\n var blob = qq.dataUriToBlob(scaledImageDataUri);\n scalingEffort.success(blob);\n };\n\n if (includeExif) {\n self._insertExifHeader(sourceFile, scaledImageDataUri, log).then(function(scaledImageDataUriWithExif) {\n scaledImageDataUri = scaledImageDataUriWithExif;\n signalSuccess();\n },\n function() {\n log(\"Problem inserting EXIF header into scaled image. Using scaled image w/out EXIF data.\", \"error\");\n signalSuccess();\n });\n }\n else {\n signalSuccess();\n }\n }, function() {\n log(\"Failed attempt to generate scaled version for \" + sourceFile.name, \"error\");\n scalingEffort.failure(failedText);\n });\n\n return scalingEffort;\n },\n\n // Attempt to insert the original image's EXIF header into a scaled version.\n _insertExifHeader: function(originalImage, scaledImageDataUri, log) {\n \"use strict\";\n\n var reader = new FileReader(),\n insertionEffort = new qq.Promise(),\n originalImageDataUri = \"\";\n\n reader.onload = function() {\n originalImageDataUri = reader.result;\n insertionEffort.success(qq.ExifRestorer.restore(originalImageDataUri, scaledImageDataUri));\n };\n\n reader.onerror = function() {\n log(\"Problem reading \" + originalImage.name + \" during attempt to transfer EXIF data to scaled version.\", \"error\");\n insertionEffort.failure();\n };\n\n reader.readAsDataURL(originalImage);\n\n return insertionEffort;\n },\n\n _dataUriToBlob: function(dataUri) {\n \"use strict\";\n\n var byteString, mimeString, arrayBuffer, intArray;\n\n // convert base64 to raw binary data held in a string\n if (dataUri.split(\",\")[0].indexOf(\"base64\") >= 0) {\n byteString = atob(dataUri.split(\",\")[1]);\n }\n else {\n byteString = decodeURI(dataUri.split(\",\")[1]);\n }\n\n // extract the MIME\n mimeString = dataUri.split(\",\")[0]\n .split(\":\")[1]\n .split(\";\")[0];\n\n // write the bytes of the binary string to an ArrayBuffer\n arrayBuffer = new ArrayBuffer(byteString.length);\n intArray = new Uint8Array(arrayBuffer);\n qq.each(byteString, function(idx, character) {\n intArray[idx] = character.charCodeAt(0);\n });\n\n return this._createBlob(arrayBuffer, mimeString);\n },\n\n _createBlob: function(data, mime) {\n \"use strict\";\n\n var BlobBuilder = window.BlobBuilder ||\n window.WebKitBlobBuilder ||\n window.MozBlobBuilder ||\n window.MSBlobBuilder,\n blobBuilder = BlobBuilder && new BlobBuilder();\n\n if (blobBuilder) {\n blobBuilder.append(data);\n return blobBuilder.getBlob(mime);\n }\n else {\n return new Blob([data], {type: mime});\n }\n }\n});\n","//Based on MinifyJpeg\n//http://elicon.blog57.fc2.com/blog-entry-206.html\n\nqq.ExifRestorer = (function()\n{\n \n\tvar ExifRestorer = {};\n\t \n ExifRestorer.KEY_STR = \"ABCDEFGHIJKLMNOP\" +\n \"QRSTUVWXYZabcdef\" +\n \"ghijklmnopqrstuv\" +\n \"wxyz0123456789+/\" +\n \"=\";\n\n ExifRestorer.encode64 = function(input)\n {\n var output = \"\",\n chr1, chr2, chr3 = \"\",\n enc1, enc2, enc3, enc4 = \"\",\n i = 0;\n\n do {\n chr1 = input[i++];\n chr2 = input[i++];\n chr3 = input[i++];\n\n enc1 = chr1 >> 2;\n enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);\n enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);\n enc4 = chr3 & 63;\n\n if (isNaN(chr2)) {\n enc3 = enc4 = 64;\n } else if (isNaN(chr3)) {\n enc4 = 64;\n }\n\n output = output +\n this.KEY_STR.charAt(enc1) +\n this.KEY_STR.charAt(enc2) +\n this.KEY_STR.charAt(enc3) +\n this.KEY_STR.charAt(enc4);\n chr1 = chr2 = chr3 = \"\";\n enc1 = enc2 = enc3 = enc4 = \"\";\n } while (i < input.length);\n\n return output;\n };\n \n ExifRestorer.restore = function(origFileBase64, resizedFileBase64)\n {\n var expectedBase64Header = \"data:image/jpeg;base64,\";\n\n if (!origFileBase64.match(expectedBase64Header))\n {\n \treturn resizedFileBase64;\n } \n \n var rawImage = this.decode64(origFileBase64.replace(expectedBase64Header, \"\"));\n var segments = this.slice2Segments(rawImage);\n \n var image = this.exifManipulation(resizedFileBase64, segments);\n \n return expectedBase64Header + this.encode64(image);\n \n };\n\n\n ExifRestorer.exifManipulation = function(resizedFileBase64, segments)\n {\n var exifArray = this.getExifArray(segments),\n newImageArray = this.insertExif(resizedFileBase64, exifArray),\n aBuffer = new Uint8Array(newImageArray);\n\n return aBuffer;\n };\n\n\n ExifRestorer.getExifArray = function(segments)\n {\n var seg;\n for (var x = 0; x < segments.length; x++)\n {\n seg = segments[x];\n if (seg[0] == 255 & seg[1] == 225) //(ff e1)\n {\n return seg;\n }\n }\n return [];\n };\n\n\n ExifRestorer.insertExif = function(resizedFileBase64, exifArray)\n {\n var imageData = resizedFileBase64.replace(\"data:image/jpeg;base64,\", \"\"),\n buf = this.decode64(imageData),\n separatePoint = buf.indexOf(255,3),\n mae = buf.slice(0, separatePoint),\n ato = buf.slice(separatePoint),\n array = mae;\n\n array = array.concat(exifArray);\n array = array.concat(ato);\n return array;\n };\n\n\n \n ExifRestorer.slice2Segments = function(rawImageArray)\n {\n var head = 0,\n segments = [];\n\n while (1)\n {\n if (rawImageArray[head] == 255 & rawImageArray[head + 1] == 218){break;}\n if (rawImageArray[head] == 255 & rawImageArray[head + 1] == 216)\n {\n head += 2;\n }\n else\n {\n var length = rawImageArray[head + 2] * 256 + rawImageArray[head + 3],\n endPoint = head + length + 2,\n seg = rawImageArray.slice(head, endPoint);\n segments.push(seg);\n head = endPoint;\n }\n if (head > rawImageArray.length){break;}\n }\n\n return segments;\n };\n\n\n \n ExifRestorer.decode64 = function(input) \n {\n var output = \"\",\n chr1, chr2, chr3 = \"\",\n enc1, enc2, enc3, enc4 = \"\",\n i = 0,\n buf = [];\n\n // remove all characters that are not A-Z, a-z, 0-9, +, /, or =\n var base64test = /[^A-Za-z0-9\\+\\/\\=]/g;\n if (base64test.exec(input)) {\n throw new Error(\"There were invalid base64 characters in the input text. \" +\n \"Valid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='\");\n }\n input = input.replace(/[^A-Za-z0-9\\+\\/\\=]/g, \"\");\n\n do {\n enc1 = this.KEY_STR.indexOf(input.charAt(i++));\n enc2 = this.KEY_STR.indexOf(input.charAt(i++));\n enc3 = this.KEY_STR.indexOf(input.charAt(i++));\n enc4 = this.KEY_STR.indexOf(input.charAt(i++));\n\n chr1 = (enc1 << 2) | (enc2 >> 4);\n chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);\n chr3 = ((enc3 & 3) << 6) | enc4;\n\n buf.push(chr1);\n\n if (enc3 != 64) {\n buf.push(chr2);\n }\n if (enc4 != 64) {\n buf.push(chr3);\n }\n\n chr1 = chr2 = chr3 = \"\";\n enc1 = enc2 = enc3 = enc4 = \"\";\n\n } while (i < input.length);\n\n return buf;\n };\n\n \n return ExifRestorer;\n})();\n","/* globals qq */\n/**\n * Keeps a running tally of total upload progress for a batch of files.\n *\n * @param callback Invoked when total progress changes, passing calculated total loaded & total size values.\n * @param getSize Function that returns the size of a file given its ID\n * @constructor\n */\nqq.TotalProgress = function(callback, getSize) {\n \"use strict\";\n\n var perFileProgress = {},\n totalLoaded = 0,\n totalSize = 0,\n\n lastLoadedSent = -1,\n lastTotalSent = -1,\n callbackProxy = function(loaded, total) {\n if (loaded !== lastLoadedSent || total !== lastTotalSent) {\n callback(loaded, total);\n }\n\n lastLoadedSent = loaded;\n lastTotalSent = total;\n },\n\n /**\n * @param failed Array of file IDs that have failed\n * @param retryable Array of file IDs that are retryable\n * @returns true if none of the failed files are eligible for retry\n */\n noRetryableFiles = function(failed, retryable) {\n var none = true;\n\n qq.each(failed, function(idx, failedId) {\n if (qq.indexOf(retryable, failedId) >= 0) {\n none = false;\n return false;\n }\n });\n\n return none;\n },\n\n onCancel = function(id) {\n updateTotalProgress(id, -1, -1);\n delete perFileProgress[id];\n },\n\n onAllComplete = function(successful, failed, retryable) {\n if (failed.length === 0 || noRetryableFiles(failed, retryable)) {\n callbackProxy(totalSize, totalSize);\n this.reset();\n }\n },\n\n onNew = function(id) {\n var size = getSize(id);\n\n // We might not know the size yet, such as for blob proxies\n if (size > 0) {\n updateTotalProgress(id, 0, size);\n perFileProgress[id] = {loaded: 0, total: size};\n }\n },\n\n /**\n * Invokes the callback with the current total progress of all files in the batch. Called whenever it may\n * be appropriate to re-calculate and disseminate this data.\n *\n * @param id ID of a file that has changed in some important way\n * @param newLoaded New loaded value for this file. -1 if this value should no longer be part of calculations\n * @param newTotal New total size of the file. -1 if this value should no longer be part of calculations\n */\n updateTotalProgress = function(id, newLoaded, newTotal) {\n var oldLoaded = perFileProgress[id] ? perFileProgress[id].loaded : 0,\n oldTotal = perFileProgress[id] ? perFileProgress[id].total : 0;\n\n if (newLoaded === -1 && newTotal === -1) {\n totalLoaded -= oldLoaded;\n totalSize -= oldTotal;\n }\n else {\n if (newLoaded) {\n totalLoaded += newLoaded - oldLoaded;\n }\n if (newTotal) {\n totalSize += newTotal - oldTotal;\n }\n }\n\n callbackProxy(totalLoaded, totalSize);\n };\n\n qq.extend(this, {\n // Called when a batch of files has completed uploading.\n onAllComplete: onAllComplete,\n\n // Called when the status of a file has changed.\n onStatusChange: function(id, oldStatus, newStatus) {\n if (newStatus === qq.status.CANCELED || newStatus === qq.status.REJECTED) {\n onCancel(id);\n }\n else if (newStatus === qq.status.SUBMITTING) {\n onNew(id);\n }\n },\n\n // Called whenever the upload progress of an individual file has changed.\n onIndividualProgress: function(id, loaded, total) {\n updateTotalProgress(id, loaded, total);\n perFileProgress[id] = {loaded: loaded, total: total};\n },\n\n // Called whenever the total size of a file has changed, such as when the size of a generated blob is known.\n onNewSize: function(id) {\n onNew(id);\n },\n\n reset: function() {\n perFileProgress = {};\n totalLoaded = 0;\n totalSize = 0;\n }\n });\n};\n","/*globals qq*/\nqq.PasteSupport = function(o) {\n \"use strict\";\n\n var options, detachPasteHandler;\n\n options = {\n targetElement: null,\n callbacks: {\n log: function(message, level) {},\n pasteReceived: function(blob) {}\n }\n };\n\n function isImage(item) {\n return item.type &&\n item.type.indexOf(\"image/\") === 0;\n }\n\n function registerPasteHandler() {\n detachPasteHandler = qq(options.targetElement).attach(\"paste\", function(event) {\n var clipboardData = event.clipboardData;\n\n if (clipboardData) {\n qq.each(clipboardData.items, function(idx, item) {\n if (isImage(item)) {\n var blob = item.getAsFile();\n options.callbacks.pasteReceived(blob);\n }\n });\n }\n });\n }\n\n function unregisterPasteHandler() {\n if (detachPasteHandler) {\n detachPasteHandler();\n }\n }\n\n qq.extend(options, o);\n registerPasteHandler();\n\n qq.extend(this, {\n reset: function() {\n unregisterPasteHandler();\n }\n });\n};\n","/* globals qq */\n/**\n * Module that handles support for existing forms.\n *\n * @param options Options passed from the integrator-supplied options related to form support.\n * @param startUpload Callback to invoke when files \"stored\" should be uploaded.\n * @param log Proxy for the logger\n * @constructor\n */\nqq.FormSupport = function(options, startUpload, log) {\n \"use strict\";\n var self = this,\n interceptSubmit = options.interceptSubmit,\n formEl = options.element,\n autoUpload = options.autoUpload;\n\n // Available on the public API associated with this module.\n qq.extend(this, {\n // To be used by the caller to determine if the endpoint will be determined by some processing\n // that occurs in this module, such as if the form has an action attribute.\n // Ignore if `attachToForm === false`.\n newEndpoint: null,\n\n // To be used by the caller to determine if auto uploading should be allowed.\n // Ignore if `attachToForm === false`.\n newAutoUpload: autoUpload,\n\n // true if a form was detected and is being tracked by this module\n attachedToForm: false,\n\n // Returns an object with names and values for all valid form elements associated with the attached form.\n getFormInputsAsObject: function() {\n /* jshint eqnull:true */\n if (formEl == null) {\n return null;\n }\n\n return self._form2Obj(formEl);\n }\n });\n\n // If the form contains an action attribute, this should be the new upload endpoint.\n function determineNewEndpoint(formEl) {\n if (formEl.getAttribute(\"action\")) {\n self.newEndpoint = formEl.getAttribute(\"action\");\n }\n }\n\n // Return true only if the form is valid, or if we cannot make this determination.\n // If the form is invalid, ensure invalid field(s) are highlighted in the UI.\n function validateForm(formEl, nativeSubmit) {\n if (formEl.checkValidity && !formEl.checkValidity()) {\n log(\"Form did not pass validation checks - will not upload.\", \"error\");\n nativeSubmit();\n }\n else {\n return true;\n }\n }\n\n // Intercept form submit attempts, unless the integrator has told us not to do this.\n function maybeUploadOnSubmit(formEl) {\n var nativeSubmit = formEl.submit;\n\n // Intercept and squelch submit events.\n qq(formEl).attach(\"submit\", function(event) {\n event = event || window.event;\n\n if (event.preventDefault) {\n event.preventDefault();\n }\n else {\n event.returnValue = false;\n }\n\n validateForm(formEl, nativeSubmit) && startUpload();\n });\n\n // The form's `submit()` function may be called instead (i.e. via jQuery.submit()).\n // Intercept that too.\n formEl.submit = function() {\n validateForm(formEl, nativeSubmit) && startUpload();\n };\n }\n\n // If the element value passed from the uploader is a string, assume it is an element ID - select it.\n // The rest of the code in this module depends on this being an HTMLElement.\n function determineFormEl(formEl) {\n if (formEl) {\n if (qq.isString(formEl)) {\n formEl = document.getElementById(formEl);\n }\n\n if (formEl) {\n log(\"Attaching to form element.\");\n determineNewEndpoint(formEl);\n interceptSubmit && maybeUploadOnSubmit(formEl);\n }\n }\n\n return formEl;\n }\n\n formEl = determineFormEl(formEl);\n this.attachedToForm = !!formEl;\n};\n\nqq.extend(qq.FormSupport.prototype, {\n // Converts all relevant form fields to key/value pairs. This is meant to mimic the data a browser will\n // construct from a given form when the form is submitted.\n _form2Obj: function(form) {\n \"use strict\";\n var obj = {},\n notIrrelevantType = function(type) {\n var irrelevantTypes = [\n \"button\",\n \"image\",\n \"reset\",\n \"submit\"\n ];\n\n return qq.indexOf(irrelevantTypes, type.toLowerCase()) < 0;\n },\n radioOrCheckbox = function(type) {\n return qq.indexOf([\"checkbox\", \"radio\"], type.toLowerCase()) >= 0;\n },\n ignoreValue = function(el) {\n if (radioOrCheckbox(el.type) && !el.checked) {\n return true;\n }\n\n return el.disabled && el.type.toLowerCase() !== \"hidden\";\n },\n selectValue = function(select) {\n var value = null;\n\n qq.each(qq(select).children(), function(idx, child) {\n if (child.tagName.toLowerCase() === \"option\" && child.selected) {\n value = child.value;\n return false;\n }\n });\n\n return value;\n };\n\n qq.each(form.elements, function(idx, el) {\n if ((qq.isInput(el, true) || el.tagName.toLowerCase() === \"textarea\") &&\n notIrrelevantType(el.type) &&\n !ignoreValue(el)) {\n\n obj[el.name] = el.value;\n }\n else if (el.tagName.toLowerCase() === \"select\" && !ignoreValue(el)) {\n var value = selectValue(el);\n\n if (value !== null) {\n obj[el.name] = value;\n }\n }\n });\n\n return obj;\n }\n});\n","/*globals qq*/\n/**\n * Upload handler used that assumes the current user agent does not have any support for the\n * File API, and, therefore, makes use of iframes and forms to submit the files directly to\n * a generic server.\n *\n * @param options Options passed from the base handler\n * @param proxy Callbacks & methods used to query for or push out data/changes\n */\nqq.traditional = qq.traditional || {};\nqq.traditional.FormUploadHandler = function(options, proxy) {\n \"use strict\";\n\n var handler = this,\n getName = proxy.getName,\n getUuid = proxy.getUuid,\n log = proxy.log;\n\n /**\n * Returns json object received by iframe from server.\n */\n function getIframeContentJson(id, iframe) {\n /*jshint evil: true*/\n\n var response, doc, innerHtml;\n\n //IE may throw an \"access is denied\" error when attempting to access contentDocument on the iframe in some cases\n try {\n // iframe.contentWindow.document - for IE<7\n doc = iframe.contentDocument || iframe.contentWindow.document;\n innerHtml = doc.body.innerHTML;\n\n log(\"converting iframe's innerHTML to JSON\");\n log(\"innerHTML = \" + innerHtml);\n //plain text response may be wrapped in tag\n if (innerHtml && innerHtml.match(/^ 1 && !options.allowMultipleItems) {\n options.callbacks.processingDroppedFilesComplete([]);\n options.callbacks.dropError(\"tooManyFilesError\", \"\");\n uploadDropZone.dropDisabled(false);\n handleDataTransferPromise.failure();\n }\n else {\n droppedFiles = [];\n\n if (qq.isFolderDropSupported(dataTransfer)) {\n qq.each(dataTransfer.items, function(idx, item) {\n var entry = item.webkitGetAsEntry();\n\n if (entry) {\n //due to a bug in Chrome's File System API impl - #149735\n if (entry.isFile) {\n droppedFiles.push(item.getAsFile());\n }\n\n else {\n pendingFolderPromises.push(traverseFileTree(entry).done(function() {\n pendingFolderPromises.pop();\n if (pendingFolderPromises.length === 0) {\n handleDataTransferPromise.success();\n }\n }));\n }\n }\n });\n }\n else {\n droppedFiles = dataTransfer.files;\n }\n\n if (pendingFolderPromises.length === 0) {\n handleDataTransferPromise.success();\n }\n }\n\n return handleDataTransferPromise;\n }\n\n function setupDropzone(dropArea) {\n var dropZone = new qq.UploadDropZone({\n HIDE_ZONES_EVENT_NAME: HIDE_ZONES_EVENT_NAME,\n element: dropArea,\n onEnter: function(e) {\n qq(dropArea).addClass(options.classes.dropActive);\n e.stopPropagation();\n },\n onLeaveNotDescendants: function(e) {\n qq(dropArea).removeClass(options.classes.dropActive);\n },\n onDrop: function(e) {\n handleDataTransfer(e.dataTransfer, dropZone).then(\n function() {\n uploadDroppedFiles(droppedFiles, dropZone);\n },\n function() {\n options.callbacks.dropLog(\"Drop event DataTransfer parsing failed. No files will be uploaded.\", \"error\");\n }\n );\n }\n });\n\n disposeSupport.addDisposer(function() {\n dropZone.dispose();\n });\n\n qq(dropArea).hasAttribute(HIDE_BEFORE_ENTER_ATTR) && qq(dropArea).hide();\n\n uploadDropZones.push(dropZone);\n\n return dropZone;\n }\n\n function isFileDrag(dragEvent) {\n var fileDrag;\n\n qq.each(dragEvent.dataTransfer.types, function(key, val) {\n if (val === \"Files\") {\n fileDrag = true;\n return false;\n }\n });\n\n return fileDrag;\n }\n\n // Attempt to determine when the file has left the document. It is not always possible to detect this\n // in all cases, but it is generally possible in all browsers, with a few exceptions.\n //\n // Exceptions:\n // * IE10+ & Safari: We can't detect a file leaving the document if the Explorer window housing the file\n // overlays the browser window.\n // * IE10+: If the file is dragged out of the window too quickly, IE does not set the expected values of the\n // event's X & Y properties.\n function leavingDocumentOut(e) {\n if (qq.safari()) {\n return e.x < 0 || e.y < 0;\n }\n\n return e.x === 0 && e.y === 0;\n }\n\n function setupDragDrop() {\n var dropZones = options.dropZoneElements,\n\n maybeHideDropZones = function() {\n setTimeout(function() {\n qq.each(dropZones, function(idx, dropZone) {\n qq(dropZone).hasAttribute(HIDE_BEFORE_ENTER_ATTR) && qq(dropZone).hide();\n qq(dropZone).removeClass(options.classes.dropActive);\n });\n }, 10);\n };\n\n qq.each(dropZones, function(idx, dropZone) {\n var uploadDropZone = setupDropzone(dropZone);\n\n // IE <= 9 does not support the File API used for drag+drop uploads\n if (dropZones.length && qq.supportedFeatures.fileDrop) {\n disposeSupport.attach(document, \"dragenter\", function(e) {\n if (!uploadDropZone.dropDisabled() && isFileDrag(e)) {\n qq.each(dropZones, function(idx, dropZone) {\n // We can't apply styles to non-HTMLElements, since they lack the `style` property.\n // Also, if the drop zone isn't initially hidden, let's not mess with `style.display`.\n if (dropZone instanceof HTMLElement &&\n qq(dropZone).hasAttribute(HIDE_BEFORE_ENTER_ATTR)) {\n\n qq(dropZone).css({display: \"block\"});\n }\n });\n }\n });\n }\n });\n\n disposeSupport.attach(document, \"dragleave\", function(e) {\n if (leavingDocumentOut(e)) {\n maybeHideDropZones();\n }\n });\n\n // Just in case we were not able to detect when a dragged file has left the document,\n // hide all relevant drop zones the next time the mouse enters the document.\n // Note that mouse events such as this one are not fired during drag operations.\n disposeSupport.attach(qq(document).children()[0], \"mouseenter\", function(e) {\n maybeHideDropZones();\n });\n\n disposeSupport.attach(document, \"drop\", function(e) {\n if (isFileDrag(e)) {\n e.preventDefault();\n maybeHideDropZones();\n }\n });\n\n disposeSupport.attach(document, HIDE_ZONES_EVENT_NAME, maybeHideDropZones);\n }\n\n setupDragDrop();\n\n qq.extend(this, {\n setupExtraDropzone: function(element) {\n options.dropZoneElements.push(element);\n setupDropzone(element);\n },\n\n removeDropzone: function(element) {\n var i,\n dzs = options.dropZoneElements;\n\n for (i in dzs) {\n if (dzs[i] === element) {\n return dzs.splice(i, 1);\n }\n }\n },\n\n dispose: function() {\n disposeSupport.dispose();\n qq.each(uploadDropZones, function(idx, dropZone) {\n dropZone.dispose();\n });\n }\n });\n\n this._testing = {};\n this._testing.extractDirectoryPath = extractDirectoryPath;\n};\n\nqq.DragAndDrop.callbacks = function() {\n \"use strict\";\n\n return {\n processingDroppedFiles: function() {},\n processingDroppedFilesComplete: function(files, targetEl) {},\n dropError: function(code, errorSpecifics) {\n qq.log(\"Drag & drop error code '\" + code + \" with these specifics: '\" + errorSpecifics + \"'\", \"error\");\n },\n dropLog: function(message, level) {\n qq.log(message, level);\n }\n };\n};\n\nqq.UploadDropZone = function(o) {\n \"use strict\";\n\n var disposeSupport = new qq.DisposeSupport(),\n options, element, preventDrop, dropOutsideDisabled;\n\n options = {\n element: null,\n onEnter: function(e) {},\n onLeave: function(e) {},\n // is not fired when leaving element by hovering descendants\n onLeaveNotDescendants: function(e) {},\n onDrop: function(e) {}\n };\n\n qq.extend(options, o);\n element = options.element;\n\n function dragoverShouldBeCanceled() {\n return qq.safari() || (qq.firefox() && qq.windows());\n }\n\n function disableDropOutside(e) {\n // run only once for all instances\n if (!dropOutsideDisabled) {\n\n // for these cases we need to catch onDrop to reset dropArea\n if (dragoverShouldBeCanceled) {\n disposeSupport.attach(document, \"dragover\", function(e) {\n e.preventDefault();\n });\n } else {\n disposeSupport.attach(document, \"dragover\", function(e) {\n if (e.dataTransfer) {\n e.dataTransfer.dropEffect = \"none\";\n e.preventDefault();\n }\n });\n }\n\n dropOutsideDisabled = true;\n }\n }\n\n function isValidFileDrag(e) {\n // e.dataTransfer currently causing IE errors\n // IE9 does NOT support file API, so drag-and-drop is not possible\n if (!qq.supportedFeatures.fileDrop) {\n return false;\n }\n\n var effectTest, dt = e.dataTransfer,\n // do not check dt.types.contains in webkit, because it crashes safari 4\n isSafari = qq.safari();\n\n // dt.effectAllowed is none in Safari 5\n\n // dt.effectAllowed crashes IE 11 & 10 when files have been dragged from\n // the filesystem\n effectTest = qq.ie() && qq.supportedFeatures.fileDrop ? true : dt.effectAllowed !== \"none\";\n return dt && effectTest &&\n (\n (dt.files && dt.files.length) || // Valid for drop events with files\n (!isSafari && dt.types.contains && dt.types.contains(\"Files\")) || // Valid in Chrome/Firefox\n (dt.types.includes && dt.types.includes(\"Files\")) // Valid in IE\n );\n }\n\n function isOrSetDropDisabled(isDisabled) {\n if (isDisabled !== undefined) {\n preventDrop = isDisabled;\n }\n return preventDrop;\n }\n\n function triggerHidezonesEvent() {\n var hideZonesEvent;\n\n function triggerUsingOldApi() {\n hideZonesEvent = document.createEvent(\"Event\");\n hideZonesEvent.initEvent(options.HIDE_ZONES_EVENT_NAME, true, true);\n }\n\n if (window.CustomEvent) {\n try {\n hideZonesEvent = new CustomEvent(options.HIDE_ZONES_EVENT_NAME);\n }\n catch (err) {\n triggerUsingOldApi();\n }\n }\n else {\n triggerUsingOldApi();\n }\n\n document.dispatchEvent(hideZonesEvent);\n }\n\n function attachEvents() {\n disposeSupport.attach(element, \"dragover\", function(e) {\n if (!isValidFileDrag(e)) {\n return;\n }\n\n // dt.effectAllowed crashes IE 11 & 10 when files have been dragged from\n // the filesystem\n var effect = qq.ie() && qq.supportedFeatures.fileDrop ? null : e.dataTransfer.effectAllowed;\n if (effect === \"move\" || effect === \"linkMove\") {\n e.dataTransfer.dropEffect = \"move\"; // for FF (only move allowed)\n } else {\n e.dataTransfer.dropEffect = \"copy\"; // for Chrome\n }\n\n e.stopPropagation();\n e.preventDefault();\n });\n\n disposeSupport.attach(element, \"dragenter\", function(e) {\n if (!isOrSetDropDisabled()) {\n if (!isValidFileDrag(e)) {\n return;\n }\n options.onEnter(e);\n }\n });\n\n disposeSupport.attach(element, \"dragleave\", function(e) {\n if (!isValidFileDrag(e)) {\n return;\n }\n\n options.onLeave(e);\n\n var relatedTarget = document.elementFromPoint(e.clientX, e.clientY);\n // do not fire when moving a mouse over a descendant\n if (qq(this).contains(relatedTarget)) {\n return;\n }\n\n options.onLeaveNotDescendants(e);\n });\n\n disposeSupport.attach(element, \"drop\", function(e) {\n if (!isOrSetDropDisabled()) {\n if (!isValidFileDrag(e)) {\n return;\n }\n\n e.preventDefault();\n e.stopPropagation();\n options.onDrop(e);\n\n triggerHidezonesEvent();\n }\n });\n }\n\n disableDropOutside();\n attachEvents();\n\n qq.extend(this, {\n dropDisabled: function(isDisabled) {\n return isOrSetDropDisabled(isDisabled);\n },\n\n dispose: function() {\n disposeSupport.dispose();\n },\n\n getElement: function() {\n return element;\n }\n });\n\n this._testing = {};\n this._testing.isValidFileDrag = isValidFileDrag;\n};\n","/*globals qq */\n/**\n * Defines the public API for FineUploader mode.\n */\n(function() {\n \"use strict\";\n\n qq.uiPublicApi = {\n addInitialFiles: function(cannedFileList) {\n this._parent.prototype.addInitialFiles.apply(this, arguments);\n this._templating.addCacheToDom();\n },\n\n clearStoredFiles: function() {\n this._parent.prototype.clearStoredFiles.apply(this, arguments);\n this._templating.clearFiles();\n },\n\n addExtraDropzone: function(element) {\n this._dnd && this._dnd.setupExtraDropzone(element);\n },\n\n removeExtraDropzone: function(element) {\n if (this._dnd) {\n return this._dnd.removeDropzone(element);\n }\n },\n\n getItemByFileId: function(id) {\n if (!this._templating.isHiddenForever(id)) {\n return this._templating.getFileContainer(id);\n }\n },\n\n reset: function() {\n this._parent.prototype.reset.apply(this, arguments);\n this._templating.reset();\n\n if (!this._options.button && this._templating.getButton()) {\n this._defaultButtonId = this._createUploadButton({\n element: this._templating.getButton(),\n title: this._options.text.fileInputTitle\n }).getButtonId();\n }\n\n if (this._dnd) {\n this._dnd.dispose();\n this._dnd = this._setupDragAndDrop();\n }\n\n this._totalFilesInBatch = 0;\n this._filesInBatchAddedToUi = 0;\n\n this._setupClickAndEditEventHandlers();\n },\n\n setName: function(id, newName) {\n var formattedFilename = this._options.formatFileName(newName);\n\n this._parent.prototype.setName.apply(this, arguments);\n this._templating.updateFilename(id, formattedFilename);\n },\n\n pauseUpload: function(id) {\n var paused = this._parent.prototype.pauseUpload.apply(this, arguments);\n\n paused && this._templating.uploadPaused(id);\n return paused;\n },\n\n continueUpload: function(id) {\n var continued = this._parent.prototype.continueUpload.apply(this, arguments);\n\n continued && this._templating.uploadContinued(id);\n return continued;\n },\n\n getId: function(fileContainerOrChildEl) {\n return this._templating.getFileId(fileContainerOrChildEl);\n },\n\n getDropTarget: function(fileId) {\n var file = this.getFile(fileId);\n\n return file.qqDropTarget;\n }\n };\n\n /**\n * Defines the private (internal) API for FineUploader mode.\n */\n qq.uiPrivateApi = {\n _getButton: function(buttonId) {\n var button = this._parent.prototype._getButton.apply(this, arguments);\n\n if (!button) {\n if (buttonId === this._defaultButtonId) {\n button = this._templating.getButton();\n }\n }\n\n return button;\n },\n\n _removeFileItem: function(fileId) {\n this._templating.removeFile(fileId);\n },\n\n _setupClickAndEditEventHandlers: function() {\n this._fileButtonsClickHandler = qq.FileButtonsClickHandler && this._bindFileButtonsClickEvent();\n\n // A better approach would be to check specifically for focusin event support by querying the DOM API,\n // but the DOMFocusIn event is not exposed as a property, so we have to resort to UA string sniffing.\n this._focusinEventSupported = !qq.firefox();\n\n if (this._isEditFilenameEnabled())\n {\n this._filenameClickHandler = this._bindFilenameClickEvent();\n this._filenameInputFocusInHandler = this._bindFilenameInputFocusInEvent();\n this._filenameInputFocusHandler = this._bindFilenameInputFocusEvent();\n }\n },\n\n _setupDragAndDrop: function() {\n var self = this,\n dropZoneElements = this._options.dragAndDrop.extraDropzones,\n templating = this._templating,\n defaultDropZone = templating.getDropZone();\n\n defaultDropZone && dropZoneElements.push(defaultDropZone);\n\n return new qq.DragAndDrop({\n dropZoneElements: dropZoneElements,\n allowMultipleItems: this._options.multiple,\n classes: {\n dropActive: this._options.classes.dropActive\n },\n callbacks: {\n processingDroppedFiles: function() {\n templating.showDropProcessing();\n },\n processingDroppedFilesComplete: function(files, targetEl) {\n templating.hideDropProcessing();\n\n qq.each(files, function(idx, file) {\n file.qqDropTarget = targetEl;\n });\n\n if (files.length) {\n self.addFiles(files, null, null);\n }\n },\n dropError: function(code, errorData) {\n self._itemError(code, errorData);\n },\n dropLog: function(message, level) {\n self.log(message, level);\n }\n }\n });\n },\n\n _bindFileButtonsClickEvent: function() {\n var self = this;\n\n return new qq.FileButtonsClickHandler({\n templating: this._templating,\n\n log: function(message, lvl) {\n self.log(message, lvl);\n },\n\n onDeleteFile: function(fileId) {\n self.deleteFile(fileId);\n },\n\n onCancel: function(fileId) {\n self.cancel(fileId);\n },\n\n onRetry: function(fileId) {\n self.retry(fileId);\n },\n\n onPause: function(fileId) {\n self.pauseUpload(fileId);\n },\n\n onContinue: function(fileId) {\n self.continueUpload(fileId);\n },\n\n onGetName: function(fileId) {\n return self.getName(fileId);\n }\n });\n },\n\n _isEditFilenameEnabled: function() {\n /*jshint -W014 */\n return this._templating.isEditFilenamePossible()\n && !this._options.autoUpload\n && qq.FilenameClickHandler\n && qq.FilenameInputFocusHandler\n && qq.FilenameInputFocusHandler;\n },\n\n _filenameEditHandler: function() {\n var self = this,\n templating = this._templating;\n\n return {\n templating: templating,\n log: function(message, lvl) {\n self.log(message, lvl);\n },\n onGetUploadStatus: function(fileId) {\n return self.getUploads({id: fileId}).status;\n },\n onGetName: function(fileId) {\n return self.getName(fileId);\n },\n onSetName: function(id, newName) {\n self.setName(id, newName);\n },\n onEditingStatusChange: function(id, isEditing) {\n var qqInput = qq(templating.getEditInput(id)),\n qqFileContainer = qq(templating.getFileContainer(id));\n\n if (isEditing) {\n qqInput.addClass(\"qq-editing\");\n templating.hideFilename(id);\n templating.hideEditIcon(id);\n }\n else {\n qqInput.removeClass(\"qq-editing\");\n templating.showFilename(id);\n templating.showEditIcon(id);\n }\n\n // Force IE8 and older to repaint\n qqFileContainer.addClass(\"qq-temp\").removeClass(\"qq-temp\");\n }\n };\n },\n\n _onUploadStatusChange: function(id, oldStatus, newStatus) {\n this._parent.prototype._onUploadStatusChange.apply(this, arguments);\n\n if (this._isEditFilenameEnabled()) {\n // Status for a file exists before it has been added to the DOM, so we must be careful here.\n if (this._templating.getFileContainer(id) && newStatus !== qq.status.SUBMITTED) {\n this._templating.markFilenameEditable(id);\n this._templating.hideEditIcon(id);\n }\n }\n\n if (oldStatus === qq.status.UPLOAD_RETRYING && newStatus === qq.status.UPLOADING) {\n this._templating.hideRetry(id);\n this._templating.setStatusText(id);\n qq(this._templating.getFileContainer(id)).removeClass(this._classes.retrying);\n }\n else if (newStatus === qq.status.UPLOAD_FAILED) {\n this._templating.hidePause(id);\n }\n },\n\n _bindFilenameInputFocusInEvent: function() {\n var spec = qq.extend({}, this._filenameEditHandler());\n\n return new qq.FilenameInputFocusInHandler(spec);\n },\n\n _bindFilenameInputFocusEvent: function() {\n var spec = qq.extend({}, this._filenameEditHandler());\n\n return new qq.FilenameInputFocusHandler(spec);\n },\n\n _bindFilenameClickEvent: function() {\n var spec = qq.extend({}, this._filenameEditHandler());\n\n return new qq.FilenameClickHandler(spec);\n },\n\n _storeForLater: function(id) {\n this._parent.prototype._storeForLater.apply(this, arguments);\n this._templating.hideSpinner(id);\n },\n\n _onAllComplete: function(successful, failed) {\n this._parent.prototype._onAllComplete.apply(this, arguments);\n this._templating.resetTotalProgress();\n },\n\n _onSubmit: function(id, name) {\n var file = this.getFile(id);\n\n if (file && file.qqPath && this._options.dragAndDrop.reportDirectoryPaths) {\n this._paramsStore.addReadOnly(id, {\n qqpath: file.qqPath\n });\n }\n\n this._parent.prototype._onSubmit.apply(this, arguments);\n this._addToList(id, name);\n },\n\n // The file item has been added to the DOM.\n _onSubmitted: function(id) {\n // If the edit filename feature is enabled, mark the filename element as \"editable\" and the associated edit icon\n if (this._isEditFilenameEnabled()) {\n this._templating.markFilenameEditable(id);\n this._templating.showEditIcon(id);\n\n // If the focusin event is not supported, we must add a focus handler to the newly create edit filename text input\n if (!this._focusinEventSupported) {\n this._filenameInputFocusHandler.addHandler(this._templating.getEditInput(id));\n }\n }\n },\n\n // Update the progress bar & percentage as the file is uploaded\n _onProgress: function(id, name, loaded, total) {\n this._parent.prototype._onProgress.apply(this, arguments);\n\n this._templating.updateProgress(id, loaded, total);\n\n if (total === 0 || Math.round(loaded / total * 100) === 100) {\n this._templating.hideCancel(id);\n this._templating.hidePause(id);\n this._templating.hideProgress(id);\n this._templating.setStatusText(id, this._options.text.waitingForResponse);\n\n // If ~last byte was sent, display total file size\n this._displayFileSize(id);\n }\n else {\n // If still uploading, display percentage - total size is actually the total request(s) size\n this._displayFileSize(id, loaded, total);\n }\n },\n\n _onTotalProgress: function(loaded, total) {\n this._parent.prototype._onTotalProgress.apply(this, arguments);\n this._templating.updateTotalProgress(loaded, total);\n },\n\n _onComplete: function(id, name, result, xhr) {\n var parentRetVal = this._parent.prototype._onComplete.apply(this, arguments),\n templating = this._templating,\n fileContainer = templating.getFileContainer(id),\n self = this;\n\n function completeUpload(result) {\n // If this file is not represented in the templating module, perhaps it was hidden intentionally.\n // If so, don't perform any UI-related tasks related to this file.\n if (!fileContainer) {\n return;\n }\n\n templating.setStatusText(id);\n\n qq(fileContainer).removeClass(self._classes.retrying);\n templating.hideProgress(id);\n\n if (self.getUploads({id: id}).status !== qq.status.UPLOAD_FAILED) {\n templating.hideCancel(id);\n }\n templating.hideSpinner(id);\n\n if (result.success) {\n self._markFileAsSuccessful(id);\n }\n else {\n qq(fileContainer).addClass(self._classes.fail);\n templating.showCancel(id);\n\n if (templating.isRetryPossible() && !self._preventRetries[id]) {\n qq(fileContainer).addClass(self._classes.retryable);\n templating.showRetry(id);\n }\n self._controlFailureTextDisplay(id, result);\n }\n }\n\n // The parent may need to perform some async operation before we can accurately determine the status of the upload.\n if (parentRetVal instanceof qq.Promise) {\n parentRetVal.done(function(newResult) {\n completeUpload(newResult);\n });\n\n }\n else {\n completeUpload(result);\n }\n\n return parentRetVal;\n },\n\n _markFileAsSuccessful: function(id) {\n var templating = this._templating;\n\n if (this._isDeletePossible()) {\n templating.showDeleteButton(id);\n }\n\n qq(templating.getFileContainer(id)).addClass(this._classes.success);\n\n this._maybeUpdateThumbnail(id);\n },\n\n _onUploadPrep: function(id) {\n this._parent.prototype._onUploadPrep.apply(this, arguments);\n this._templating.showSpinner(id);\n },\n\n _onUpload: function(id, name) {\n var parentRetVal = this._parent.prototype._onUpload.apply(this, arguments);\n\n this._templating.showSpinner(id);\n\n return parentRetVal;\n },\n\n _onUploadChunk: function(id, chunkData) {\n this._parent.prototype._onUploadChunk.apply(this, arguments);\n\n // Only display the pause button if we have finished uploading at least one chunk\n // & this file can be resumed\n if (chunkData.partIndex > 0 && this._handler.isResumable(id)) {\n this._templating.allowPause(id);\n }\n },\n\n _onCancel: function(id, name) {\n this._parent.prototype._onCancel.apply(this, arguments);\n this._removeFileItem(id);\n\n if (this._getNotFinished() === 0) {\n this._templating.resetTotalProgress();\n }\n },\n\n _onBeforeAutoRetry: function(id) {\n var retryNumForDisplay, maxAuto, retryNote;\n\n this._parent.prototype._onBeforeAutoRetry.apply(this, arguments);\n\n this._showCancelLink(id);\n\n if (this._options.retry.showAutoRetryNote) {\n retryNumForDisplay = this._autoRetries[id];\n maxAuto = this._options.retry.maxAutoAttempts;\n\n retryNote = this._options.retry.autoRetryNote.replace(/\\{retryNum\\}/g, retryNumForDisplay);\n retryNote = retryNote.replace(/\\{maxAuto\\}/g, maxAuto);\n\n this._templating.setStatusText(id, retryNote);\n qq(this._templating.getFileContainer(id)).addClass(this._classes.retrying);\n }\n },\n\n //return false if we should not attempt the requested retry\n _onBeforeManualRetry: function(id) {\n if (this._parent.prototype._onBeforeManualRetry.apply(this, arguments)) {\n this._templating.resetProgress(id);\n qq(this._templating.getFileContainer(id)).removeClass(this._classes.fail);\n this._templating.setStatusText(id);\n this._templating.showSpinner(id);\n this._showCancelLink(id);\n return true;\n }\n else {\n qq(this._templating.getFileContainer(id)).addClass(this._classes.retryable);\n this._templating.showRetry(id);\n return false;\n }\n },\n\n _onSubmitDelete: function(id) {\n var onSuccessCallback = qq.bind(this._onSubmitDeleteSuccess, this);\n\n this._parent.prototype._onSubmitDelete.call(this, id, onSuccessCallback);\n },\n\n _onSubmitDeleteSuccess: function(id, uuid, additionalMandatedParams) {\n if (this._options.deleteFile.forceConfirm) {\n this._showDeleteConfirm.apply(this, arguments);\n }\n else {\n this._sendDeleteRequest.apply(this, arguments);\n }\n },\n\n _onDeleteComplete: function(id, xhr, isError) {\n this._parent.prototype._onDeleteComplete.apply(this, arguments);\n\n this._templating.hideSpinner(id);\n\n if (isError) {\n this._templating.setStatusText(id, this._options.deleteFile.deletingFailedText);\n this._templating.showDeleteButton(id);\n }\n else {\n this._removeFileItem(id);\n }\n },\n\n _sendDeleteRequest: function(id, uuid, additionalMandatedParams) {\n this._templating.hideDeleteButton(id);\n this._templating.showSpinner(id);\n this._templating.setStatusText(id, this._options.deleteFile.deletingStatusText);\n this._deleteHandler.sendDelete.apply(this, arguments);\n },\n\n _showDeleteConfirm: function(id, uuid, mandatedParams) {\n /*jshint -W004 */\n var fileName = this.getName(id),\n confirmMessage = this._options.deleteFile.confirmMessage.replace(/\\{filename\\}/g, fileName),\n uuid = this.getUuid(id),\n deleteRequestArgs = arguments,\n self = this,\n retVal;\n\n retVal = this._options.showConfirm(confirmMessage);\n\n if (qq.isGenericPromise(retVal)) {\n retVal.then(function() {\n self._sendDeleteRequest.apply(self, deleteRequestArgs);\n });\n }\n else if (retVal !== false) {\n self._sendDeleteRequest.apply(self, deleteRequestArgs);\n }\n },\n\n _addToList: function(id, name, canned) {\n var prependData,\n prependIndex = 0,\n dontDisplay = this._handler.isProxied(id) && this._options.scaling.hideScaled,\n record;\n\n if (this._options.display.prependFiles) {\n if (this._totalFilesInBatch > 1 && this._filesInBatchAddedToUi > 0) {\n prependIndex = this._filesInBatchAddedToUi - 1;\n }\n\n prependData = {\n index: prependIndex\n };\n }\n\n if (!canned) {\n if (this._options.disableCancelForFormUploads && !qq.supportedFeatures.ajaxUploading) {\n this._templating.disableCancel();\n }\n\n // Cancel all existing (previous) files and clear the list if this file is not part of\n // a scaled file group that has already been accepted, or if this file is not part of\n // a scaled file group at all.\n if (!this._options.multiple) {\n record = this.getUploads({id: id});\n\n this._handledProxyGroup = this._handledProxyGroup || record.proxyGroupId;\n\n if (record.proxyGroupId !== this._handledProxyGroup || !record.proxyGroupId) {\n this._handler.cancelAll();\n this._clearList();\n this._handledProxyGroup = null;\n }\n }\n }\n\n if (canned) {\n this._templating.addFileToCache(id, this._options.formatFileName(name), prependData, dontDisplay);\n this._templating.updateThumbnail(id, this._thumbnailUrls[id], true, this._options.thumbnails.customResizer);\n }\n else {\n this._templating.addFile(id, this._options.formatFileName(name), prependData, dontDisplay);\n this._templating.generatePreview(id, this.getFile(id), this._options.thumbnails.customResizer);\n }\n\n this._filesInBatchAddedToUi += 1;\n\n if (canned ||\n (this._options.display.fileSizeOnSubmit && qq.supportedFeatures.ajaxUploading)) {\n\n this._displayFileSize(id);\n }\n },\n\n _clearList: function() {\n this._templating.clearFiles();\n this.clearStoredFiles();\n },\n\n _displayFileSize: function(id, loadedSize, totalSize) {\n var size = this.getSize(id),\n sizeForDisplay = this._formatSize(size);\n\n if (size >= 0) {\n if (loadedSize !== undefined && totalSize !== undefined) {\n sizeForDisplay = this._formatProgress(loadedSize, totalSize);\n }\n\n this._templating.updateSize(id, sizeForDisplay);\n }\n },\n\n _formatProgress: function(uploadedSize, totalSize) {\n var message = this._options.text.formatProgress;\n function r(name, replacement) { message = message.replace(name, replacement); }\n\n r(\"{percent}\", Math.round(uploadedSize / totalSize * 100));\n r(\"{total_size}\", this._formatSize(totalSize));\n return message;\n },\n\n _controlFailureTextDisplay: function(id, response) {\n var mode, responseProperty, failureReason;\n\n mode = this._options.failedUploadTextDisplay.mode;\n responseProperty = this._options.failedUploadTextDisplay.responseProperty;\n\n if (mode === \"custom\") {\n failureReason = response[responseProperty];\n if (!failureReason) {\n failureReason = this._options.text.failUpload;\n }\n\n this._templating.setStatusText(id, failureReason);\n\n if (this._options.failedUploadTextDisplay.enableTooltip) {\n this._showTooltip(id, failureReason);\n }\n }\n else if (mode === \"default\") {\n this._templating.setStatusText(id, this._options.text.failUpload);\n }\n else if (mode !== \"none\") {\n this.log(\"failedUploadTextDisplay.mode value of '\" + mode + \"' is not valid\", \"warn\");\n }\n },\n\n _showTooltip: function(id, text) {\n this._templating.getFileContainer(id).title = text;\n },\n\n _showCancelLink: function(id) {\n if (!this._options.disableCancelForFormUploads || qq.supportedFeatures.ajaxUploading) {\n this._templating.showCancel(id);\n }\n },\n\n _itemError: function(code, name, item) {\n var message = this._parent.prototype._itemError.apply(this, arguments);\n this._options.showMessage(message);\n },\n\n _batchError: function(message) {\n this._parent.prototype._batchError.apply(this, arguments);\n this._options.showMessage(message);\n },\n\n _setupPastePrompt: function() {\n var self = this;\n\n this._options.callbacks.onPasteReceived = function() {\n var message = self._options.paste.namePromptMessage,\n defaultVal = self._options.paste.defaultName;\n\n return self._options.showPrompt(message, defaultVal);\n };\n },\n\n _fileOrBlobRejected: function(id, name) {\n this._totalFilesInBatch -= 1;\n this._parent.prototype._fileOrBlobRejected.apply(this, arguments);\n },\n\n _prepareItemsForUpload: function(items, params, endpoint) {\n this._totalFilesInBatch = items.length;\n this._filesInBatchAddedToUi = 0;\n this._parent.prototype._prepareItemsForUpload.apply(this, arguments);\n },\n\n _maybeUpdateThumbnail: function(fileId) {\n var thumbnailUrl = this._thumbnailUrls[fileId],\n fileStatus = this.getUploads({id: fileId}).status;\n\n if (fileStatus !== qq.status.DELETED &&\n (thumbnailUrl ||\n this._options.thumbnails.placeholders.waitUntilResponse ||\n !qq.supportedFeatures.imagePreviews)) {\n\n // This will replace the \"waiting\" placeholder with a \"preview not available\" placeholder\n // if called with a null thumbnailUrl.\n this._templating.updateThumbnail(fileId, thumbnailUrl, this._options.thumbnails.customResizer);\n }\n },\n\n _addCannedFile: function(sessionData) {\n var id = this._parent.prototype._addCannedFile.apply(this, arguments);\n\n this._addToList(id, this.getName(id), true);\n this._templating.hideSpinner(id);\n this._templating.hideCancel(id);\n this._markFileAsSuccessful(id);\n\n return id;\n },\n\n _setSize: function(id, newSize) {\n this._parent.prototype._setSize.apply(this, arguments);\n\n this._templating.updateSize(id, this._formatSize(newSize));\n },\n\n _sessionRequestComplete: function() {\n this._templating.addCacheToDom();\n this._parent.prototype._sessionRequestComplete.apply(this, arguments);\n }\n };\n}());\n","/*globals qq */\n/**\n * This defines FineUploader mode, which is a default UI w/ drag & drop uploading.\n */\nqq.FineUploader = function(o, namespace) {\n \"use strict\";\n\n var self = this;\n\n // By default this should inherit instance data from FineUploaderBasic, but this can be overridden\n // if the (internal) caller defines a different parent. The parent is also used by\n // the private and public API functions that need to delegate to a parent function.\n this._parent = namespace ? qq[namespace].FineUploaderBasic : qq.FineUploaderBasic;\n this._parent.apply(this, arguments);\n\n // Options provided by FineUploader mode\n qq.extend(this._options, {\n element: null,\n\n button: null,\n\n listElement: null,\n\n dragAndDrop: {\n extraDropzones: [],\n reportDirectoryPaths: false\n },\n\n text: {\n formatProgress: \"{percent}% of {total_size}\",\n failUpload: \"Upload failed\",\n waitingForResponse: \"Processing...\",\n paused: \"Paused\"\n },\n\n template: \"qq-template\",\n\n classes: {\n retrying: \"qq-upload-retrying\",\n retryable: \"qq-upload-retryable\",\n success: \"qq-upload-success\",\n fail: \"qq-upload-fail\",\n editable: \"qq-editable\",\n hide: \"qq-hide\",\n dropActive: \"qq-upload-drop-area-active\"\n },\n\n failedUploadTextDisplay: {\n mode: \"default\", //default, custom, or none\n responseProperty: \"error\",\n enableTooltip: true\n },\n\n messages: {\n tooManyFilesError: \"You may only drop one file\",\n unsupportedBrowser: \"Unrecoverable error - this browser does not permit file uploading of any kind.\"\n },\n\n retry: {\n showAutoRetryNote: true,\n autoRetryNote: \"Retrying {retryNum}/{maxAuto}...\"\n },\n\n deleteFile: {\n forceConfirm: false,\n confirmMessage: \"Are you sure you want to delete {filename}?\",\n deletingStatusText: \"Deleting...\",\n deletingFailedText: \"Delete failed\"\n\n },\n\n display: {\n fileSizeOnSubmit: false,\n prependFiles: false\n },\n\n paste: {\n promptForName: false,\n namePromptMessage: \"Please name this image\"\n },\n\n thumbnails: {\n customResizer: null,\n maxCount: 0,\n placeholders: {\n waitUntilResponse: false,\n notAvailablePath: null,\n waitingPath: null\n },\n timeBetweenThumbs: 750\n },\n\n scaling: {\n hideScaled: false\n },\n\n showMessage: function(message) {\n if (self._templating.hasDialog(\"alert\")) {\n return self._templating.showDialog(\"alert\", message);\n }\n else {\n setTimeout(function() {\n window.alert(message);\n }, 0);\n }\n },\n\n showConfirm: function(message) {\n if (self._templating.hasDialog(\"confirm\")) {\n return self._templating.showDialog(\"confirm\", message);\n }\n else {\n return window.confirm(message);\n }\n },\n\n showPrompt: function(message, defaultValue) {\n if (self._templating.hasDialog(\"prompt\")) {\n return self._templating.showDialog(\"prompt\", message, defaultValue);\n }\n else {\n return window.prompt(message, defaultValue);\n }\n }\n }, true);\n\n // Replace any default options with user defined ones\n qq.extend(this._options, o, true);\n\n this._templating = new qq.Templating({\n log: qq.bind(this.log, this),\n templateIdOrEl: this._options.template,\n containerEl: this._options.element,\n fileContainerEl: this._options.listElement,\n button: this._options.button,\n imageGenerator: this._imageGenerator,\n classes: {\n hide: this._options.classes.hide,\n editable: this._options.classes.editable\n },\n limits: {\n maxThumbs: this._options.thumbnails.maxCount,\n timeBetweenThumbs: this._options.thumbnails.timeBetweenThumbs\n },\n placeholders: {\n waitUntilUpdate: this._options.thumbnails.placeholders.waitUntilResponse,\n thumbnailNotAvailable: this._options.thumbnails.placeholders.notAvailablePath,\n waitingForThumbnail: this._options.thumbnails.placeholders.waitingPath\n },\n text: this._options.text\n });\n\n if (this._options.workarounds.ios8SafariUploads && qq.ios800() && qq.iosSafari()) {\n this._templating.renderFailure(this._options.messages.unsupportedBrowserIos8Safari);\n }\n else if (!qq.supportedFeatures.uploading || (this._options.cors.expected && !qq.supportedFeatures.uploadCors)) {\n this._templating.renderFailure(this._options.messages.unsupportedBrowser);\n }\n else {\n this._wrapCallbacks();\n\n this._templating.render();\n\n this._classes = this._options.classes;\n\n if (!this._options.button && this._templating.getButton()) {\n this._defaultButtonId = this._createUploadButton({\n element: this._templating.getButton(),\n title: this._options.text.fileInputTitle\n }).getButtonId();\n }\n\n this._setupClickAndEditEventHandlers();\n\n if (qq.DragAndDrop && qq.supportedFeatures.fileDrop) {\n this._dnd = this._setupDragAndDrop();\n }\n\n if (this._options.paste.targetElement && this._options.paste.promptForName) {\n if (qq.PasteSupport) {\n this._setupPastePrompt();\n }\n else {\n this.log(\"Paste support module not found.\", \"error\");\n }\n }\n\n this._totalFilesInBatch = 0;\n this._filesInBatchAddedToUi = 0;\n }\n};\n\n// Inherit the base public & private API methods\nqq.extend(qq.FineUploader.prototype, qq.basePublicApi);\nqq.extend(qq.FineUploader.prototype, qq.basePrivateApi);\n\n// Add the FineUploader/default UI public & private UI methods, which may override some base methods.\nqq.extend(qq.FineUploader.prototype, qq.uiPublicApi);\nqq.extend(qq.FineUploader.prototype, qq.uiPrivateApi);\n","/* globals qq */\n/* jshint -W065 */\n/**\n * Module responsible for rendering all Fine Uploader UI templates. This module also asserts at least\n * a limited amount of control over the template elements after they are added to the DOM.\n * Wherever possible, this module asserts total control over template elements present in the DOM.\n *\n * @param spec Specification object used to control various templating behaviors\n * @constructor\n */\nqq.Templating = function(spec) {\n \"use strict\";\n\n var FILE_ID_ATTR = \"qq-file-id\",\n FILE_CLASS_PREFIX = \"qq-file-id-\",\n THUMBNAIL_MAX_SIZE_ATTR = \"qq-max-size\",\n THUMBNAIL_SERVER_SCALE_ATTR = \"qq-server-scale\",\n // This variable is duplicated in the DnD module since it can function as a standalone as well\n HIDE_DROPZONE_ATTR = \"qq-hide-dropzone\",\n DROPZPONE_TEXT_ATTR = \"qq-drop-area-text\",\n IN_PROGRESS_CLASS = \"qq-in-progress\",\n HIDDEN_FOREVER_CLASS = \"qq-hidden-forever\",\n fileBatch = {\n content: document.createDocumentFragment(),\n map: {}\n },\n isCancelDisabled = false,\n generatedThumbnails = 0,\n thumbnailQueueMonitorRunning = false,\n thumbGenerationQueue = [],\n thumbnailMaxSize = -1,\n options = {\n log: null,\n limits: {\n maxThumbs: 0,\n timeBetweenThumbs: 750\n },\n templateIdOrEl: \"qq-template\",\n containerEl: null,\n fileContainerEl: null,\n button: null,\n imageGenerator: null,\n classes: {\n hide: \"qq-hide\",\n editable: \"qq-editable\"\n },\n placeholders: {\n waitUntilUpdate: false,\n thumbnailNotAvailable: null,\n waitingForThumbnail: null\n },\n text: {\n paused: \"Paused\"\n }\n },\n selectorClasses = {\n button: \"qq-upload-button-selector\",\n alertDialog: \"qq-alert-dialog-selector\",\n dialogCancelButton: \"qq-cancel-button-selector\",\n confirmDialog: \"qq-confirm-dialog-selector\",\n dialogMessage: \"qq-dialog-message-selector\",\n dialogOkButton: \"qq-ok-button-selector\",\n promptDialog: \"qq-prompt-dialog-selector\",\n uploader: \"qq-uploader-selector\",\n drop: \"qq-upload-drop-area-selector\",\n list: \"qq-upload-list-selector\",\n progressBarContainer: \"qq-progress-bar-container-selector\",\n progressBar: \"qq-progress-bar-selector\",\n totalProgressBarContainer: \"qq-total-progress-bar-container-selector\",\n totalProgressBar: \"qq-total-progress-bar-selector\",\n file: \"qq-upload-file-selector\",\n spinner: \"qq-upload-spinner-selector\",\n size: \"qq-upload-size-selector\",\n cancel: \"qq-upload-cancel-selector\",\n pause: \"qq-upload-pause-selector\",\n continueButton: \"qq-upload-continue-selector\",\n deleteButton: \"qq-upload-delete-selector\",\n retry: \"qq-upload-retry-selector\",\n statusText: \"qq-upload-status-text-selector\",\n editFilenameInput: \"qq-edit-filename-selector\",\n editNameIcon: \"qq-edit-filename-icon-selector\",\n dropText: \"qq-upload-drop-area-text-selector\",\n dropProcessing: \"qq-drop-processing-selector\",\n dropProcessingSpinner: \"qq-drop-processing-spinner-selector\",\n thumbnail: \"qq-thumbnail-selector\"\n },\n previewGeneration = {},\n cachedThumbnailNotAvailableImg = new qq.Promise(),\n cachedWaitingForThumbnailImg = new qq.Promise(),\n log,\n isEditElementsExist,\n isRetryElementExist,\n templateDom,\n container,\n fileList,\n showThumbnails,\n serverScale,\n\n // During initialization of the templating module we should cache any\n // placeholder images so we can quickly swap them into the file list on demand.\n // Any placeholder images that cannot be loaded/found are simply ignored.\n cacheThumbnailPlaceholders = function() {\n var notAvailableUrl = options.placeholders.thumbnailNotAvailable,\n waitingUrl = options.placeholders.waitingForThumbnail,\n spec = {\n maxSize: thumbnailMaxSize,\n scale: serverScale\n };\n\n if (showThumbnails) {\n if (notAvailableUrl) {\n options.imageGenerator.generate(notAvailableUrl, new Image(), spec).then(\n function(updatedImg) {\n cachedThumbnailNotAvailableImg.success(updatedImg);\n },\n function() {\n cachedThumbnailNotAvailableImg.failure();\n log(\"Problem loading 'not available' placeholder image at \" + notAvailableUrl, \"error\");\n }\n );\n }\n else {\n cachedThumbnailNotAvailableImg.failure();\n }\n\n if (waitingUrl) {\n options.imageGenerator.generate(waitingUrl, new Image(), spec).then(\n function(updatedImg) {\n cachedWaitingForThumbnailImg.success(updatedImg);\n },\n function() {\n cachedWaitingForThumbnailImg.failure();\n log(\"Problem loading 'waiting for thumbnail' placeholder image at \" + waitingUrl, \"error\");\n }\n );\n }\n else {\n cachedWaitingForThumbnailImg.failure();\n }\n }\n },\n\n // Displays a \"waiting for thumbnail\" type placeholder image\n // iff we were able to load it during initialization of the templating module.\n displayWaitingImg = function(thumbnail) {\n var waitingImgPlacement = new qq.Promise();\n\n cachedWaitingForThumbnailImg.then(function(img) {\n maybeScalePlaceholderViaCss(img, thumbnail);\n /* jshint eqnull:true */\n if (!thumbnail.src) {\n thumbnail.src = img.src;\n thumbnail.onload = function() {\n thumbnail.onload = null;\n show(thumbnail);\n waitingImgPlacement.success();\n };\n }\n else {\n waitingImgPlacement.success();\n }\n }, function() {\n // In some browsers (such as IE9 and older) an img w/out a src attribute\n // are displayed as \"broken\" images, so we should just hide the img tag\n // if we aren't going to display the \"waiting\" placeholder.\n hide(thumbnail);\n waitingImgPlacement.success();\n });\n\n return waitingImgPlacement;\n },\n\n generateNewPreview = function(id, blob, spec) {\n var thumbnail = getThumbnail(id);\n\n log(\"Generating new thumbnail for \" + id);\n blob.qqThumbnailId = id;\n\n return options.imageGenerator.generate(blob, thumbnail, spec).then(\n function() {\n generatedThumbnails++;\n show(thumbnail);\n previewGeneration[id].success();\n },\n function() {\n previewGeneration[id].failure();\n\n // Display the \"not available\" placeholder img only if we are\n // not expecting a thumbnail at a later point, such as in a server response.\n if (!options.placeholders.waitUntilUpdate) {\n maybeSetDisplayNotAvailableImg(id, thumbnail);\n }\n });\n },\n\n generateNextQueuedPreview = function() {\n if (thumbGenerationQueue.length) {\n thumbnailQueueMonitorRunning = true;\n\n var queuedThumbRequest = thumbGenerationQueue.shift();\n\n if (queuedThumbRequest.update) {\n processUpdateQueuedPreviewRequest(queuedThumbRequest);\n }\n else {\n processNewQueuedPreviewRequest(queuedThumbRequest);\n }\n }\n else {\n thumbnailQueueMonitorRunning = false;\n }\n },\n\n getCancel = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.cancel);\n },\n\n getContinue = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.continueButton);\n },\n\n getDialog = function(type) {\n return getTemplateEl(container, selectorClasses[type + \"Dialog\"]);\n },\n\n getDelete = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.deleteButton);\n },\n\n getDropProcessing = function() {\n return getTemplateEl(container, selectorClasses.dropProcessing);\n },\n\n getEditIcon = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.editNameIcon);\n },\n\n getFile = function(id) {\n return fileBatch.map[id] || qq(fileList).getFirstByClass(FILE_CLASS_PREFIX + id);\n },\n\n getFilename = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.file);\n },\n\n getPause = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.pause);\n },\n\n getProgress = function(id) {\n /* jshint eqnull:true */\n // Total progress bar\n if (id == null) {\n return getTemplateEl(container, selectorClasses.totalProgressBarContainer) ||\n getTemplateEl(container, selectorClasses.totalProgressBar);\n }\n\n // Per-file progress bar\n return getTemplateEl(getFile(id), selectorClasses.progressBarContainer) ||\n getTemplateEl(getFile(id), selectorClasses.progressBar);\n },\n\n getRetry = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.retry);\n },\n\n getSize = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.size);\n },\n\n getSpinner = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.spinner);\n },\n\n getTemplateEl = function(context, cssClass) {\n return context && qq(context).getFirstByClass(cssClass);\n },\n\n getThumbnail = function(id) {\n return showThumbnails && getTemplateEl(getFile(id), selectorClasses.thumbnail);\n },\n\n hide = function(el) {\n el && qq(el).addClass(options.classes.hide);\n },\n\n // Ensures a placeholder image does not exceed any max size specified\n // via `style` attribute properties iff was not used to scale\n // the placeholder AND the target doesn't already have these `style` attribute properties set.\n maybeScalePlaceholderViaCss = function(placeholder, thumbnail) {\n var maxWidth = placeholder.style.maxWidth,\n maxHeight = placeholder.style.maxHeight;\n\n if (maxHeight && maxWidth && !thumbnail.style.maxWidth && !thumbnail.style.maxHeight) {\n qq(thumbnail).css({\n maxWidth: maxWidth,\n maxHeight: maxHeight\n });\n }\n },\n\n // Displays a \"thumbnail not available\" type placeholder image\n // iff we were able to load this placeholder during initialization\n // of the templating module or after preview generation has failed.\n maybeSetDisplayNotAvailableImg = function(id, thumbnail) {\n var previewing = previewGeneration[id] || new qq.Promise().failure(),\n notAvailableImgPlacement = new qq.Promise();\n\n cachedThumbnailNotAvailableImg.then(function(img) {\n previewing.then(\n function() {\n notAvailableImgPlacement.success();\n },\n function() {\n maybeScalePlaceholderViaCss(img, thumbnail);\n\n thumbnail.onload = function() {\n thumbnail.onload = null;\n notAvailableImgPlacement.success();\n };\n\n thumbnail.src = img.src;\n show(thumbnail);\n }\n );\n });\n\n return notAvailableImgPlacement;\n },\n\n /**\n * Grabs the HTML from the script tag holding the template markup. This function will also adjust\n * some internally-tracked state variables based on the contents of the template.\n * The template is filtered so that irrelevant elements (such as the drop zone if DnD is not supported)\n * are omitted from the DOM. Useful errors will be thrown if the template cannot be parsed.\n *\n * @returns {{template: *, fileTemplate: *}} HTML for the top-level file items templates\n */\n parseAndGetTemplate = function() {\n var scriptEl,\n scriptHtml,\n fileListNode,\n tempTemplateEl,\n fileListEl,\n defaultButton,\n dropArea,\n thumbnail,\n dropProcessing,\n dropTextEl,\n uploaderEl;\n\n log(\"Parsing template\");\n\n /*jshint -W116*/\n if (options.templateIdOrEl == null) {\n throw new Error(\"You MUST specify either a template element or ID!\");\n }\n\n // Grab the contents of the script tag holding the template.\n if (qq.isString(options.templateIdOrEl)) {\n scriptEl = document.getElementById(options.templateIdOrEl);\n\n if (scriptEl === null) {\n throw new Error(qq.format(\"Cannot find template script at ID '{}'!\", options.templateIdOrEl));\n }\n\n scriptHtml = scriptEl.innerHTML;\n }\n else {\n if (options.templateIdOrEl.innerHTML === undefined) {\n throw new Error(\"You have specified an invalid value for the template option! \" +\n \"It must be an ID or an Element.\");\n }\n\n scriptHtml = options.templateIdOrEl.innerHTML;\n }\n\n scriptHtml = qq.trimStr(scriptHtml);\n tempTemplateEl = document.createElement(\"div\");\n tempTemplateEl.appendChild(qq.toElement(scriptHtml));\n uploaderEl = qq(tempTemplateEl).getFirstByClass(selectorClasses.uploader);\n\n // Don't include the default template button in the DOM\n // if an alternate button container has been specified.\n if (options.button) {\n defaultButton = qq(tempTemplateEl).getFirstByClass(selectorClasses.button);\n if (defaultButton) {\n qq(defaultButton).remove();\n }\n }\n\n // Omit the drop processing element from the DOM if DnD is not supported by the UA,\n // or the drag and drop module is not found.\n // NOTE: We are consciously not removing the drop zone if the UA doesn't support DnD\n // to support layouts where the drop zone is also a container for visible elements,\n // such as the file list.\n if (!qq.DragAndDrop || !qq.supportedFeatures.fileDrop) {\n dropProcessing = qq(tempTemplateEl).getFirstByClass(selectorClasses.dropProcessing);\n if (dropProcessing) {\n qq(dropProcessing).remove();\n }\n }\n\n dropArea = qq(tempTemplateEl).getFirstByClass(selectorClasses.drop);\n\n // If DnD is not available then remove\n // it from the DOM as well.\n if (dropArea && !qq.DragAndDrop) {\n log(\"DnD module unavailable.\", \"info\");\n qq(dropArea).remove();\n }\n\n if (!qq.supportedFeatures.fileDrop) {\n // don't display any \"drop files to upload\" background text\n uploaderEl.removeAttribute(DROPZPONE_TEXT_ATTR);\n\n if (dropArea && qq(dropArea).hasAttribute(HIDE_DROPZONE_ATTR)) {\n // If there is a drop area defined in the template, and the current UA doesn't support DnD,\n // and the drop area is marked as \"hide before enter\", ensure it is hidden as the DnD module\n // will not do this (since we will not be loading the DnD module)\n qq(dropArea).css({\n display: \"none\"\n });\n }\n }\n else if (qq(uploaderEl).hasAttribute(DROPZPONE_TEXT_ATTR) && dropArea) {\n dropTextEl = qq(dropArea).getFirstByClass(selectorClasses.dropText);\n dropTextEl && qq(dropTextEl).remove();\n }\n\n // Ensure the `showThumbnails` flag is only set if the thumbnail element\n // is present in the template AND the current UA is capable of generating client-side previews.\n thumbnail = qq(tempTemplateEl).getFirstByClass(selectorClasses.thumbnail);\n if (!showThumbnails) {\n thumbnail && qq(thumbnail).remove();\n }\n else if (thumbnail) {\n thumbnailMaxSize = parseInt(thumbnail.getAttribute(THUMBNAIL_MAX_SIZE_ATTR));\n // Only enforce max size if the attr value is non-zero\n thumbnailMaxSize = thumbnailMaxSize > 0 ? thumbnailMaxSize : null;\n\n serverScale = qq(thumbnail).hasAttribute(THUMBNAIL_SERVER_SCALE_ATTR);\n }\n showThumbnails = showThumbnails && thumbnail;\n\n isEditElementsExist = qq(tempTemplateEl).getByClass(selectorClasses.editFilenameInput).length > 0;\n isRetryElementExist = qq(tempTemplateEl).getByClass(selectorClasses.retry).length > 0;\n\n fileListNode = qq(tempTemplateEl).getFirstByClass(selectorClasses.list);\n /*jshint -W116*/\n if (fileListNode == null) {\n throw new Error(\"Could not find the file list container in the template!\");\n }\n\n fileListEl = fileListNode.children[0].cloneNode(true);\n fileListNode.innerHTML = \"\";\n\n // We must call `createElement` in IE8 in order to target and hide any via CSS\n if (tempTemplateEl.getElementsByTagName(\"DIALOG\").length) {\n document.createElement(\"dialog\");\n }\n\n log(\"Template parsing complete\");\n\n return {\n template: tempTemplateEl,\n fileTemplate: fileListEl\n };\n },\n\n prependFile = function(el, index, fileList) {\n var parentEl = fileList,\n beforeEl = parentEl.firstChild;\n\n if (index > 0) {\n beforeEl = qq(parentEl).children()[index].nextSibling;\n\n }\n\n parentEl.insertBefore(el, beforeEl);\n },\n\n processNewQueuedPreviewRequest = function(queuedThumbRequest) {\n var id = queuedThumbRequest.id,\n optFileOrBlob = queuedThumbRequest.optFileOrBlob,\n relatedThumbnailId = optFileOrBlob && optFileOrBlob.qqThumbnailId,\n thumbnail = getThumbnail(id),\n spec = {\n customResizeFunction: queuedThumbRequest.customResizeFunction,\n maxSize: thumbnailMaxSize,\n orient: true,\n scale: true\n };\n\n if (qq.supportedFeatures.imagePreviews) {\n if (thumbnail) {\n if (options.limits.maxThumbs && options.limits.maxThumbs <= generatedThumbnails) {\n maybeSetDisplayNotAvailableImg(id, thumbnail);\n generateNextQueuedPreview();\n }\n else {\n displayWaitingImg(thumbnail).done(function() {\n previewGeneration[id] = new qq.Promise();\n\n previewGeneration[id].done(function() {\n setTimeout(generateNextQueuedPreview, options.limits.timeBetweenThumbs);\n });\n\n /* jshint eqnull: true */\n // If we've already generated an for this file, use the one that exists,\n // don't waste resources generating a new one.\n if (relatedThumbnailId != null) {\n useCachedPreview(id, relatedThumbnailId);\n }\n else {\n generateNewPreview(id, optFileOrBlob, spec);\n }\n });\n }\n }\n // File element in template may have been removed, so move on to next item in queue\n else {\n generateNextQueuedPreview();\n }\n }\n else if (thumbnail) {\n displayWaitingImg(thumbnail);\n generateNextQueuedPreview();\n }\n },\n\n processUpdateQueuedPreviewRequest = function(queuedThumbRequest) {\n var id = queuedThumbRequest.id,\n thumbnailUrl = queuedThumbRequest.thumbnailUrl,\n showWaitingImg = queuedThumbRequest.showWaitingImg,\n thumbnail = getThumbnail(id),\n spec = {\n customResizeFunction: queuedThumbRequest.customResizeFunction,\n scale: serverScale,\n maxSize: thumbnailMaxSize\n };\n\n if (thumbnail) {\n if (thumbnailUrl) {\n if (options.limits.maxThumbs && options.limits.maxThumbs <= generatedThumbnails) {\n maybeSetDisplayNotAvailableImg(id, thumbnail);\n generateNextQueuedPreview();\n }\n else {\n if (showWaitingImg) {\n displayWaitingImg(thumbnail);\n }\n\n return options.imageGenerator.generate(thumbnailUrl, thumbnail, spec).then(\n function() {\n show(thumbnail);\n generatedThumbnails++;\n setTimeout(generateNextQueuedPreview, options.limits.timeBetweenThumbs);\n },\n\n function() {\n maybeSetDisplayNotAvailableImg(id, thumbnail);\n setTimeout(generateNextQueuedPreview, options.limits.timeBetweenThumbs);\n }\n );\n }\n }\n else {\n maybeSetDisplayNotAvailableImg(id, thumbnail);\n generateNextQueuedPreview();\n }\n }\n },\n\n setProgressBarWidth = function(id, percent) {\n var bar = getProgress(id),\n /* jshint eqnull:true */\n progressBarSelector = id == null ? selectorClasses.totalProgressBar : selectorClasses.progressBar;\n\n if (bar && !qq(bar).hasClass(progressBarSelector)) {\n bar = qq(bar).getFirstByClass(progressBarSelector);\n }\n\n if (bar) {\n qq(bar).css({width: percent + \"%\"});\n bar.setAttribute(\"aria-valuenow\", percent);\n }\n },\n\n show = function(el) {\n el && qq(el).removeClass(options.classes.hide);\n },\n\n useCachedPreview = function(targetThumbnailId, cachedThumbnailId) {\n var targetThumbnail = getThumbnail(targetThumbnailId),\n cachedThumbnail = getThumbnail(cachedThumbnailId);\n\n log(qq.format(\"ID {} is the same file as ID {}. Will use generated thumbnail from ID {} instead.\", targetThumbnailId, cachedThumbnailId, cachedThumbnailId));\n\n // Generation of the related thumbnail may still be in progress, so, wait until it is done.\n previewGeneration[cachedThumbnailId].then(function() {\n generatedThumbnails++;\n previewGeneration[targetThumbnailId].success();\n log(qq.format(\"Now using previously generated thumbnail created for ID {} on ID {}.\", cachedThumbnailId, targetThumbnailId));\n targetThumbnail.src = cachedThumbnail.src;\n show(targetThumbnail);\n },\n function() {\n previewGeneration[targetThumbnailId].failure();\n if (!options.placeholders.waitUntilUpdate) {\n maybeSetDisplayNotAvailableImg(targetThumbnailId, targetThumbnail);\n }\n });\n };\n\n qq.extend(options, spec);\n log = options.log;\n\n // No need to worry about conserving CPU or memory on older browsers,\n // since there is no ability to preview, and thumbnail display is primitive and quick.\n if (!qq.supportedFeatures.imagePreviews) {\n options.limits.timeBetweenThumbs = 0;\n options.limits.maxThumbs = 0;\n }\n\n container = options.containerEl;\n showThumbnails = options.imageGenerator !== undefined;\n templateDom = parseAndGetTemplate();\n\n cacheThumbnailPlaceholders();\n\n qq.extend(this, {\n render: function() {\n log(\"Rendering template in DOM.\");\n\n generatedThumbnails = 0;\n\n container.appendChild(templateDom.template.cloneNode(true));\n hide(getDropProcessing());\n this.hideTotalProgress();\n fileList = options.fileContainerEl || getTemplateEl(container, selectorClasses.list);\n\n log(\"Template rendering complete\");\n },\n\n renderFailure: function(message) {\n var cantRenderEl = qq.toElement(message);\n container.innerHTML = \"\";\n container.appendChild(cantRenderEl);\n },\n\n reset: function() {\n container.innerHTML = \"\";\n this.render();\n },\n\n clearFiles: function() {\n fileList.innerHTML = \"\";\n },\n\n disableCancel: function() {\n isCancelDisabled = true;\n },\n\n addFile: function(id, name, prependInfo, hideForever, batch) {\n var fileEl = templateDom.fileTemplate.cloneNode(true),\n fileNameEl = getTemplateEl(fileEl, selectorClasses.file),\n uploaderEl = getTemplateEl(container, selectorClasses.uploader),\n fileContainer = batch ? fileBatch.content : fileList,\n thumb;\n\n if (batch) {\n fileBatch.map[id] = fileEl;\n }\n\n qq(fileEl).addClass(FILE_CLASS_PREFIX + id);\n uploaderEl.removeAttribute(DROPZPONE_TEXT_ATTR);\n\n if (fileNameEl) {\n qq(fileNameEl).setText(name);\n fileNameEl.setAttribute(\"title\", name);\n }\n\n fileEl.setAttribute(FILE_ID_ATTR, id);\n\n if (prependInfo) {\n prependFile(fileEl, prependInfo.index, fileContainer);\n }\n else {\n fileContainer.appendChild(fileEl);\n }\n\n if (hideForever) {\n fileEl.style.display = \"none\";\n qq(fileEl).addClass(HIDDEN_FOREVER_CLASS);\n }\n else {\n hide(getProgress(id));\n hide(getSize(id));\n hide(getDelete(id));\n hide(getRetry(id));\n hide(getPause(id));\n hide(getContinue(id));\n\n if (isCancelDisabled) {\n this.hideCancel(id);\n }\n\n thumb = getThumbnail(id);\n if (thumb && !thumb.src) {\n cachedWaitingForThumbnailImg.then(function(waitingImg) {\n thumb.src = waitingImg.src;\n if (waitingImg.style.maxHeight && waitingImg.style.maxWidth) {\n qq(thumb).css({\n maxHeight: waitingImg.style.maxHeight,\n maxWidth: waitingImg.style.maxWidth\n });\n }\n\n show(thumb);\n });\n }\n }\n },\n\n addFileToCache: function(id, name, prependInfo, hideForever) {\n this.addFile(id, name, prependInfo, hideForever, true);\n },\n\n addCacheToDom: function() {\n fileList.appendChild(fileBatch.content);\n fileBatch.content = document.createDocumentFragment();\n fileBatch.map = {};\n },\n\n removeFile: function(id) {\n qq(getFile(id)).remove();\n },\n\n getFileId: function(el) {\n var currentNode = el;\n\n if (currentNode) {\n /*jshint -W116*/\n while (currentNode.getAttribute(FILE_ID_ATTR) == null) {\n currentNode = currentNode.parentNode;\n }\n\n return parseInt(currentNode.getAttribute(FILE_ID_ATTR));\n }\n },\n\n getFileList: function() {\n return fileList;\n },\n\n markFilenameEditable: function(id) {\n var filename = getFilename(id);\n\n filename && qq(filename).addClass(options.classes.editable);\n },\n\n updateFilename: function(id, name) {\n var filenameEl = getFilename(id);\n\n if (filenameEl) {\n qq(filenameEl).setText(name);\n filenameEl.setAttribute(\"title\", name);\n }\n },\n\n hideFilename: function(id) {\n hide(getFilename(id));\n },\n\n showFilename: function(id) {\n show(getFilename(id));\n },\n\n isFileName: function(el) {\n return qq(el).hasClass(selectorClasses.file);\n },\n\n getButton: function() {\n return options.button || getTemplateEl(container, selectorClasses.button);\n },\n\n hideDropProcessing: function() {\n hide(getDropProcessing());\n },\n\n showDropProcessing: function() {\n show(getDropProcessing());\n },\n\n getDropZone: function() {\n return getTemplateEl(container, selectorClasses.drop);\n },\n\n isEditFilenamePossible: function() {\n return isEditElementsExist;\n },\n\n hideRetry: function(id) {\n hide(getRetry(id));\n },\n\n isRetryPossible: function() {\n return isRetryElementExist;\n },\n\n showRetry: function(id) {\n show(getRetry(id));\n },\n\n getFileContainer: function(id) {\n return getFile(id);\n },\n\n showEditIcon: function(id) {\n var icon = getEditIcon(id);\n\n icon && qq(icon).addClass(options.classes.editable);\n },\n\n isHiddenForever: function(id) {\n return qq(getFile(id)).hasClass(HIDDEN_FOREVER_CLASS);\n },\n\n hideEditIcon: function(id) {\n var icon = getEditIcon(id);\n\n icon && qq(icon).removeClass(options.classes.editable);\n },\n\n isEditIcon: function(el) {\n return qq(el).hasClass(selectorClasses.editNameIcon, true);\n },\n\n getEditInput: function(id) {\n return getTemplateEl(getFile(id), selectorClasses.editFilenameInput);\n },\n\n isEditInput: function(el) {\n return qq(el).hasClass(selectorClasses.editFilenameInput, true);\n },\n\n updateProgress: function(id, loaded, total) {\n var bar = getProgress(id),\n percent;\n\n if (bar && total > 0) {\n percent = Math.round(loaded / total * 100);\n\n if (percent === 100) {\n hide(bar);\n }\n else {\n show(bar);\n }\n\n setProgressBarWidth(id, percent);\n }\n },\n\n updateTotalProgress: function(loaded, total) {\n this.updateProgress(null, loaded, total);\n },\n\n hideProgress: function(id) {\n var bar = getProgress(id);\n\n bar && hide(bar);\n },\n\n hideTotalProgress: function() {\n this.hideProgress();\n },\n\n resetProgress: function(id) {\n setProgressBarWidth(id, 0);\n this.hideTotalProgress(id);\n },\n\n resetTotalProgress: function() {\n this.resetProgress();\n },\n\n showCancel: function(id) {\n if (!isCancelDisabled) {\n var cancel = getCancel(id);\n\n cancel && qq(cancel).removeClass(options.classes.hide);\n }\n },\n\n hideCancel: function(id) {\n hide(getCancel(id));\n },\n\n isCancel: function(el) {\n return qq(el).hasClass(selectorClasses.cancel, true);\n },\n\n allowPause: function(id) {\n show(getPause(id));\n hide(getContinue(id));\n },\n\n uploadPaused: function(id) {\n this.setStatusText(id, options.text.paused);\n this.allowContinueButton(id);\n hide(getSpinner(id));\n },\n\n hidePause: function(id) {\n hide(getPause(id));\n },\n\n isPause: function(el) {\n return qq(el).hasClass(selectorClasses.pause, true);\n },\n\n isContinueButton: function(el) {\n return qq(el).hasClass(selectorClasses.continueButton, true);\n },\n\n allowContinueButton: function(id) {\n show(getContinue(id));\n hide(getPause(id));\n },\n\n uploadContinued: function(id) {\n this.setStatusText(id, \"\");\n this.allowPause(id);\n show(getSpinner(id));\n },\n\n showDeleteButton: function(id) {\n show(getDelete(id));\n },\n\n hideDeleteButton: function(id) {\n hide(getDelete(id));\n },\n\n isDeleteButton: function(el) {\n return qq(el).hasClass(selectorClasses.deleteButton, true);\n },\n\n isRetry: function(el) {\n return qq(el).hasClass(selectorClasses.retry, true);\n },\n\n updateSize: function(id, text) {\n var size = getSize(id);\n\n if (size) {\n show(size);\n qq(size).setText(text);\n }\n },\n\n setStatusText: function(id, text) {\n var textEl = getTemplateEl(getFile(id), selectorClasses.statusText);\n\n if (textEl) {\n /*jshint -W116*/\n if (text == null) {\n qq(textEl).clearText();\n }\n else {\n qq(textEl).setText(text);\n }\n }\n },\n\n hideSpinner: function(id) {\n qq(getFile(id)).removeClass(IN_PROGRESS_CLASS);\n hide(getSpinner(id));\n },\n\n showSpinner: function(id) {\n qq(getFile(id)).addClass(IN_PROGRESS_CLASS);\n show(getSpinner(id));\n },\n\n generatePreview: function(id, optFileOrBlob, customResizeFunction) {\n if (!this.isHiddenForever(id)) {\n thumbGenerationQueue.push({id: id, customResizeFunction: customResizeFunction, optFileOrBlob: optFileOrBlob});\n !thumbnailQueueMonitorRunning && generateNextQueuedPreview();\n }\n },\n\n updateThumbnail: function(id, thumbnailUrl, showWaitingImg, customResizeFunction) {\n if (!this.isHiddenForever(id)) {\n thumbGenerationQueue.push({customResizeFunction: customResizeFunction, update: true, id: id, thumbnailUrl: thumbnailUrl, showWaitingImg: showWaitingImg});\n !thumbnailQueueMonitorRunning && generateNextQueuedPreview();\n }\n },\n\n hasDialog: function(type) {\n return qq.supportedFeatures.dialogElement && !!getDialog(type);\n },\n\n showDialog: function(type, message, defaultValue) {\n var dialog = getDialog(type),\n messageEl = getTemplateEl(dialog, selectorClasses.dialogMessage),\n inputEl = dialog.getElementsByTagName(\"INPUT\")[0],\n cancelBtn = getTemplateEl(dialog, selectorClasses.dialogCancelButton),\n okBtn = getTemplateEl(dialog, selectorClasses.dialogOkButton),\n promise = new qq.Promise(),\n\n closeHandler = function() {\n cancelBtn.removeEventListener(\"click\", cancelClickHandler);\n okBtn && okBtn.removeEventListener(\"click\", okClickHandler);\n promise.failure();\n },\n\n cancelClickHandler = function() {\n cancelBtn.removeEventListener(\"click\", cancelClickHandler);\n dialog.close();\n },\n\n okClickHandler = function() {\n dialog.removeEventListener(\"close\", closeHandler);\n okBtn.removeEventListener(\"click\", okClickHandler);\n dialog.close();\n\n promise.success(inputEl && inputEl.value);\n };\n\n dialog.addEventListener(\"close\", closeHandler);\n cancelBtn.addEventListener(\"click\", cancelClickHandler);\n okBtn && okBtn.addEventListener(\"click\", okClickHandler);\n\n if (inputEl) {\n inputEl.value = defaultValue;\n }\n messageEl.textContent = message;\n\n dialog.showModal();\n\n return promise;\n }\n });\n};\n","/*globals qq */\n// Base handler for UI (FineUploader mode) events.\n// Some more specific handlers inherit from this one.\nqq.UiEventHandler = function(s, protectedApi) {\n \"use strict\";\n\n var disposer = new qq.DisposeSupport(),\n spec = {\n eventType: \"click\",\n attachTo: null,\n onHandled: function(target, event) {}\n };\n\n // This makes up the \"public\" API methods that will be accessible\n // to instances constructing a base or child handler\n qq.extend(this, {\n addHandler: function(element) {\n addHandler(element);\n },\n\n dispose: function() {\n disposer.dispose();\n }\n });\n\n function addHandler(element) {\n disposer.attach(element, spec.eventType, function(event) {\n // Only in IE: the `event` is a property of the `window`.\n event = event || window.event;\n\n // On older browsers, we must check the `srcElement` instead of the `target`.\n var target = event.target || event.srcElement;\n\n spec.onHandled(target, event);\n });\n }\n\n // These make up the \"protected\" API methods that children of this base handler will utilize.\n qq.extend(protectedApi, {\n getFileIdFromItem: function(item) {\n return item.qqFileId;\n },\n\n getDisposeSupport: function() {\n return disposer;\n }\n });\n\n qq.extend(spec, s);\n\n if (spec.attachTo) {\n addHandler(spec.attachTo);\n }\n};\n","/* global qq */\nqq.FileButtonsClickHandler = function(s) {\n \"use strict\";\n\n var inheritedInternalApi = {},\n spec = {\n templating: null,\n log: function(message, lvl) {},\n onDeleteFile: function(fileId) {},\n onCancel: function(fileId) {},\n onRetry: function(fileId) {},\n onPause: function(fileId) {},\n onContinue: function(fileId) {},\n onGetName: function(fileId) {}\n },\n buttonHandlers = {\n cancel: function(id) { spec.onCancel(id); },\n retry: function(id) { spec.onRetry(id); },\n deleteButton: function(id) { spec.onDeleteFile(id); },\n pause: function(id) { spec.onPause(id); },\n continueButton: function(id) { spec.onContinue(id); }\n };\n\n function examineEvent(target, event) {\n qq.each(buttonHandlers, function(buttonType, handler) {\n var firstLetterCapButtonType = buttonType.charAt(0).toUpperCase() + buttonType.slice(1),\n fileId;\n\n if (spec.templating[\"is\" + firstLetterCapButtonType](target)) {\n fileId = spec.templating.getFileId(target);\n qq.preventDefault(event);\n spec.log(qq.format(\"Detected valid file button click event on file '{}', ID: {}.\", spec.onGetName(fileId), fileId));\n handler(fileId);\n return false;\n }\n });\n }\n\n qq.extend(spec, s);\n\n spec.eventType = \"click\";\n spec.onHandled = examineEvent;\n spec.attachTo = spec.templating.getFileList();\n\n qq.extend(this, new qq.UiEventHandler(spec, inheritedInternalApi));\n};\n","/*globals qq */\n// Child of FilenameEditHandler. Used to detect click events on filename display elements.\nqq.FilenameClickHandler = function(s) {\n \"use strict\";\n\n var inheritedInternalApi = {},\n spec = {\n templating: null,\n log: function(message, lvl) {},\n classes: {\n file: \"qq-upload-file\",\n editNameIcon: \"qq-edit-filename-icon\"\n },\n onGetUploadStatus: function(fileId) {},\n onGetName: function(fileId) {}\n };\n\n qq.extend(spec, s);\n\n // This will be called by the parent handler when a `click` event is received on the list element.\n function examineEvent(target, event) {\n if (spec.templating.isFileName(target) || spec.templating.isEditIcon(target)) {\n var fileId = spec.templating.getFileId(target),\n status = spec.onGetUploadStatus(fileId);\n\n // We only allow users to change filenames of files that have been submitted but not yet uploaded.\n if (status === qq.status.SUBMITTED) {\n spec.log(qq.format(\"Detected valid filename click event on file '{}', ID: {}.\", spec.onGetName(fileId), fileId));\n qq.preventDefault(event);\n\n inheritedInternalApi.handleFilenameEdit(fileId, target, true);\n }\n }\n }\n\n spec.eventType = \"click\";\n spec.onHandled = examineEvent;\n\n qq.extend(this, new qq.FilenameEditHandler(spec, inheritedInternalApi));\n};\n","/*globals qq */\n// Child of FilenameEditHandler. Used to detect focusin events on file edit input elements.\nqq.FilenameInputFocusInHandler = function(s, inheritedInternalApi) {\n \"use strict\";\n\n var spec = {\n templating: null,\n onGetUploadStatus: function(fileId) {},\n log: function(message, lvl) {}\n };\n\n if (!inheritedInternalApi) {\n inheritedInternalApi = {};\n }\n\n // This will be called by the parent handler when a `focusin` event is received on the list element.\n function handleInputFocus(target, event) {\n if (spec.templating.isEditInput(target)) {\n var fileId = spec.templating.getFileId(target),\n status = spec.onGetUploadStatus(fileId);\n\n if (status === qq.status.SUBMITTED) {\n spec.log(qq.format(\"Detected valid filename input focus event on file '{}', ID: {}.\", spec.onGetName(fileId), fileId));\n inheritedInternalApi.handleFilenameEdit(fileId, target);\n }\n }\n }\n\n spec.eventType = \"focusin\";\n spec.onHandled = handleInputFocus;\n\n qq.extend(spec, s);\n qq.extend(this, new qq.FilenameEditHandler(spec, inheritedInternalApi));\n};\n","/*globals qq */\n/**\n * Child of FilenameInputFocusInHandler. Used to detect focus events on file edit input elements. This child module is only\n * needed for UAs that do not support the focusin event. Currently, only Firefox lacks this event.\n *\n * @param spec Overrides for default specifications\n */\nqq.FilenameInputFocusHandler = function(spec) {\n \"use strict\";\n\n spec.eventType = \"focus\";\n spec.attachTo = null;\n\n qq.extend(this, new qq.FilenameInputFocusInHandler(spec, {}));\n};\n","/*globals qq */\n// Handles edit-related events on a file item (FineUploader mode). This is meant to be a parent handler.\n// Children will delegate to this handler when specific edit-related actions are detected.\nqq.FilenameEditHandler = function(s, inheritedInternalApi) {\n \"use strict\";\n\n var spec = {\n templating: null,\n log: function(message, lvl) {},\n onGetUploadStatus: function(fileId) {},\n onGetName: function(fileId) {},\n onSetName: function(fileId, newName) {},\n onEditingStatusChange: function(fileId, isEditing) {}\n };\n\n function getFilenameSansExtension(fileId) {\n var filenameSansExt = spec.onGetName(fileId),\n extIdx = filenameSansExt.lastIndexOf(\".\");\n\n if (extIdx > 0) {\n filenameSansExt = filenameSansExt.substr(0, extIdx);\n }\n\n return filenameSansExt;\n }\n\n function getOriginalExtension(fileId) {\n var origName = spec.onGetName(fileId);\n return qq.getExtension(origName);\n }\n\n // Callback iff the name has been changed\n function handleNameUpdate(newFilenameInputEl, fileId) {\n var newName = newFilenameInputEl.value,\n origExtension;\n\n if (newName !== undefined && qq.trimStr(newName).length > 0) {\n origExtension = getOriginalExtension(fileId);\n\n if (origExtension !== undefined) {\n newName = newName + \".\" + origExtension;\n }\n\n spec.onSetName(fileId, newName);\n }\n\n spec.onEditingStatusChange(fileId, false);\n }\n\n // The name has been updated if the filename edit input loses focus.\n function registerInputBlurHandler(inputEl, fileId) {\n inheritedInternalApi.getDisposeSupport().attach(inputEl, \"blur\", function() {\n handleNameUpdate(inputEl, fileId);\n });\n }\n\n // The name has been updated if the user presses enter.\n function registerInputEnterKeyHandler(inputEl, fileId) {\n inheritedInternalApi.getDisposeSupport().attach(inputEl, \"keyup\", function(event) {\n\n var code = event.keyCode || event.which;\n\n if (code === 13) {\n handleNameUpdate(inputEl, fileId);\n }\n });\n }\n\n qq.extend(spec, s);\n\n spec.attachTo = spec.templating.getFileList();\n\n qq.extend(this, new qq.UiEventHandler(spec, inheritedInternalApi));\n\n qq.extend(inheritedInternalApi, {\n handleFilenameEdit: function(id, target, focusInput) {\n var newFilenameInputEl = spec.templating.getEditInput(id);\n\n spec.onEditingStatusChange(id, true);\n\n newFilenameInputEl.value = getFilenameSansExtension(id);\n\n if (focusInput) {\n newFilenameInputEl.focus();\n }\n\n registerInputBlurHandler(newFilenameInputEl, id);\n registerInputEnterKeyHandler(newFilenameInputEl, id);\n }\n });\n};\n"]}
\ No newline at end of file
diff --git a/styles/bootstrap/fine-uploader/fine-uploader.min.css b/styles/bootstrap/fine-uploader/fine-uploader.min.css
index 488d8eba2..9aff7b49b 100644
--- a/styles/bootstrap/fine-uploader/fine-uploader.min.css
+++ b/styles/bootstrap/fine-uploader/fine-uploader.min.css
@@ -1 +1 @@
-.qq-uploader{position:relative;width:100%}.qq-upload-button{display:block;width:105px;padding:7px 0;text-align:center;background:#800;border-bottom:1px solid #DDD;color:#FFF}.qq-upload-button-hover{background:#C00}.qq-upload-button-focus{outline:#000 dotted 1px}.qq-upload-drop-area,.qq-upload-extra-drop-area{position:absolute;top:0;left:0;width:100%;height:100%;min-height:30px;z-index:2;background:#FF9797;text-align:center}.qq-upload-drop-area span{display:block;position:absolute;top:50%;width:100%;margin-top:-8px;font-size:16px}.qq-upload-extra-drop-area{position:relative;margin-top:50px;font-size:16px;padding-top:30px;height:20px;min-height:40px}.qq-upload-drop-area-active{background:#FF7171}.qq-upload-list{margin:0;padding:0;list-style:none}.qq-upload-list li{margin:0;padding:9px;line-height:15px;font-size:16px;background-color:#FFF0BD}.qq-upload-cancel,.qq-upload-continue,.qq-upload-delete,.qq-upload-failed-text,.qq-upload-file,.qq-upload-pause,.qq-upload-retry,.qq-upload-size,.qq-upload-spinner{margin-right:12px;display:inline}.qq-upload-spinner{display:inline-block;background:url(loading.gif);width:15px;height:15px;vertical-align:text-bottom}.qq-drop-processing{display:block}.qq-drop-processing-spinner{display:inline-block;background:url(processing.gif);width:24px;height:24px;vertical-align:text-bottom}.qq-upload-continue,.qq-upload-delete,.qq-upload-pause{display:inline}.qq-upload-cancel,.qq-upload-continue,.qq-upload-delete,.qq-upload-pause,.qq-upload-retry{color:#000}.qq-upload-cancel,.qq-upload-continue,.qq-upload-delete,.qq-upload-pause,.qq-upload-retry,.qq-upload-size{font-size:12px;font-weight:400}.qq-upload-failed-text{display:none;font-style:italic;font-weight:700}.qq-upload-failed-icon{display:none;width:15px;height:15px;vertical-align:text-bottom}.qq-upload-fail .qq-upload-failed-text{display:inline}.qq-upload-retrying .qq-upload-failed-text{display:inline;color:#D60000}.qq-upload-list li.qq-upload-success{background-color:#5DA30C;color:#FFF}.qq-upload-list li.qq-upload-fail{background-color:#D60000;color:#FFF}.qq-progress-bar{display:block;background:-moz-linear-gradient(top,rgba(30,87,153,1) 0,rgba(41,137,216,1) 50%,rgba(32,124,202,1) 51%,rgba(125,185,232,1) 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,rgba(30,87,153,1)),color-stop(50%,rgba(41,137,216,1)),color-stop(51%,rgba(32,124,202,1)),color-stop(100%,rgba(125,185,232,1)));background:-webkit-linear-gradient(top,rgba(30,87,153,1) 0,rgba(41,137,216,1) 50%,rgba(32,124,202,1) 51%,rgba(125,185,232,1) 100%);background:-o-linear-gradient(top,rgba(30,87,153,1) 0,rgba(41,137,216,1) 50%,rgba(32,124,202,1) 51%,rgba(125,185,232,1) 100%);background:-ms-linear-gradient(top,rgba(30,87,153,1) 0,rgba(41,137,216,1) 50%,rgba(32,124,202,1) 51%,rgba(125,185,232,1) 100%);background:linear-gradient(to bottom,rgba(30,87,153,1) 0,rgba(41,137,216,1) 50%,rgba(32,124,202,1) 51%,rgba(125,185,232,1) 100%);width:0;height:15px;border-radius:6px;margin-bottom:3px}.qq-total-progress-bar{height:25px;border-radius:9px}.qq-total-progress-bar-container{margin:9px}INPUT.qq-edit-filename{position:absolute;opacity:0;filter:alpha(opacity=0);z-index:-1;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"}.qq-upload-file.qq-editable{cursor:pointer}.qq-edit-filename-icon.qq-editable{display:inline-block;cursor:pointer}.qq-hide,.qq-uploader DIALOG{display:none}INPUT.qq-edit-filename.qq-editing{position:static;margin-top:-5px;margin-right:10px;margin-bottom:-5px;opacity:1;filter:alpha(opacity=100);-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"}.qq-edit-filename-icon{display:none;background:url(edit.gif);width:15px;height:15px;vertical-align:text-bottom;margin-right:5px}.qq-uploader DIALOG[open]{display:block}.qq-uploader DIALOG .qq-dialog-buttons{text-align:center;padding-top:10px}.qq-uploader DIALOG .qq-dialog-buttons BUTTON{margin-left:5px;margin-right:5px}.qq-uploader DIALOG .qq-dialog-message-selector{padding-bottom:10px}.qq-uploader DIALOG::backdrop{background-color:rgba(0,0,0,.7)}/*# sourceMappingURL=fine-uploader.min.css.map */
\ No newline at end of file
+.qq-uploader{position:relative;width:100%}.qq-upload-button{display:block;width:105px;padding:7px 0;text-align:center;background:#800;border-bottom:1px solid #ddd;color:#fff}.qq-upload-button-hover{background:#c00}.qq-upload-button-focus{outline:1px dotted #000}.qq-upload-drop-area,.qq-upload-extra-drop-area{position:absolute;top:0;left:0;width:100%;height:100%;min-height:30px;z-index:2;background:#ff9797;text-align:center}.qq-upload-drop-area span{display:block;position:absolute;top:50%;width:100%;margin-top:-8px;font-size:16px}.qq-upload-extra-drop-area{position:relative;margin-top:50px;font-size:16px;padding-top:30px;height:20px;min-height:40px}.qq-upload-drop-area-active{background:#ff7171}.qq-upload-list{margin:0;padding:0;list-style:none}.qq-upload-list li{margin:0;padding:9px;line-height:15px;font-size:16px;background-color:#fff0bd}.qq-upload-cancel,.qq-upload-continue,.qq-upload-delete,.qq-upload-failed-text,.qq-upload-file,.qq-upload-pause,.qq-upload-retry,.qq-upload-size,.qq-upload-spinner{margin-right:12px;display:inline}.qq-upload-spinner{display:inline-block;background:url(loading.gif);width:15px;height:15px;vertical-align:text-bottom}.qq-drop-processing{display:block}.qq-drop-processing-spinner{display:inline-block;background:url(processing.gif);width:24px;height:24px;vertical-align:text-bottom}.qq-upload-continue,.qq-upload-delete,.qq-upload-pause{display:inline}.qq-upload-cancel,.qq-upload-continue,.qq-upload-delete,.qq-upload-pause,.qq-upload-retry{color:#000}.qq-upload-cancel,.qq-upload-continue,.qq-upload-delete,.qq-upload-pause,.qq-upload-retry,.qq-upload-size{font-size:12px;font-weight:400}.qq-upload-failed-text{display:none;font-style:italic;font-weight:700}.qq-upload-failed-icon{display:none;width:15px;height:15px;vertical-align:text-bottom}.qq-upload-fail .qq-upload-failed-text{display:inline}.qq-upload-retrying .qq-upload-failed-text{display:inline;color:#d60000}.qq-upload-list li.qq-upload-success{background-color:#5da30c;color:#fff}.qq-upload-list li.qq-upload-fail{background-color:#d60000;color:#fff}.qq-progress-bar{display:block;background:-moz-linear-gradient(top,rgba(30,87,153,1) 0,rgba(41,137,216,1) 50%,rgba(32,124,202,1) 51%,rgba(125,185,232,1) 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,rgba(30,87,153,1)),color-stop(50%,rgba(41,137,216,1)),color-stop(51%,rgba(32,124,202,1)),color-stop(100%,rgba(125,185,232,1)));background:-webkit-linear-gradient(top,rgba(30,87,153,1) 0,rgba(41,137,216,1) 50%,rgba(32,124,202,1) 51%,rgba(125,185,232,1) 100%);background:-o-linear-gradient(top,rgba(30,87,153,1) 0,rgba(41,137,216,1) 50%,rgba(32,124,202,1) 51%,rgba(125,185,232,1) 100%);background:-ms-linear-gradient(top,rgba(30,87,153,1) 0,rgba(41,137,216,1) 50%,rgba(32,124,202,1) 51%,rgba(125,185,232,1) 100%);background:linear-gradient(to bottom,rgba(30,87,153,1) 0,rgba(41,137,216,1) 50%,rgba(32,124,202,1) 51%,rgba(125,185,232,1) 100%);width:0;height:15px;border-radius:6px;margin-bottom:3px}.qq-total-progress-bar{height:25px;border-radius:9px}.qq-total-progress-bar-container{margin:9px}INPUT.qq-edit-filename{position:absolute;opacity:0;z-index:-1}.qq-upload-file.qq-editable{cursor:pointer}.qq-edit-filename-icon.qq-editable{display:inline-block;cursor:pointer}INPUT.qq-edit-filename.qq-editing{position:static;margin-top:-5px;margin-right:10px;margin-bottom:-5px;opacity:1}.qq-edit-filename-icon{display:none;background:url(edit.gif);width:15px;height:15px;vertical-align:text-bottom;margin-right:5px}.qq-hide{display:none}.qq-uploader DIALOG{display:none}.qq-uploader DIALOG[open]{display:block}.qq-uploader DIALOG{display:none}.qq-uploader DIALOG[open]{display:block}.qq-uploader DIALOG .qq-dialog-buttons{text-align:center;padding-top:10px}.qq-uploader DIALOG .qq-dialog-buttons BUTTON{margin-left:5px;margin-right:5px}.qq-uploader DIALOG .qq-dialog-message-selector{padding-bottom:10px}.qq-uploader DIALOG::backdrop{background-color:rgba(0,0,0,.7)}/*# sourceMappingURL=fine-uploader.min.css.map */
\ No newline at end of file
diff --git a/styles/bootstrap/fine-uploader/fine-uploader.min.css.map b/styles/bootstrap/fine-uploader/fine-uploader.min.css.map
index 3ee17ba9b..f1896da99 100644
--- a/styles/bootstrap/fine-uploader/fine-uploader.min.css.map
+++ b/styles/bootstrap/fine-uploader/fine-uploader.min.css.map
@@ -1 +1 @@
-{"version":3,"sources":["_build/fine-uploader.css"],"names":[],"mappings":"AAAA,aACI,SAAU,SACV,MAAO,KAEX,kBACI,QAAS,MACT,MAAO,MACP,QAAS,IAAI,EACb,WAAY,OACZ,WAAY,KACZ,cAAe,IAAI,MAAM,KACzB,MAAO,KAEX,wBACI,WAAY,KAEhB,wBACI,QAAoB,KAAP,OAAJ,IAEb,qBAAsB,2BAClB,SAAU,SACV,IAAK,EACL,KAAM,EACN,MAAO,KACP,OAAQ,KACR,WAAY,KACZ,QAAS,EACT,WAAY,QACZ,WAAY,OAEhB,0BACI,QAAS,MACT,SAAU,SACV,IAAK,IACL,MAAO,KACP,WAAY,KACZ,UAAW,KAEf,2BACI,SAAU,SACV,WAAY,KACZ,UAAW,KACX,YAAa,KACb,OAAQ,KACR,WAAY,KAEhB,4BACI,WAAY,QAEhB,gBACI,OAAQ,EACR,QAAS,EACT,WAAY,KAEhB,mBACI,OAAQ,EACR,QAAS,IACT,YAAa,KACb,UAAW,KACX,iBAAkB,QAGtB,kBACqC,oBAArC,kBADqC,uBADrC,gBAEmB,iBADA,iBADkB,gBAApB,mBAGb,aAAc,KACd,QAAS,OAIb,mBACI,QAAS,aACT,WAAY,iBACZ,MAAO,KACP,OAAQ,KACR,eAAgB,YAEpB,oBACI,QAAS,MAEb,4BACI,QAAS,aACT,WAAY,oBACZ,MAAO,KACP,OAAQ,KACR,eAAgB,YAGiB,oBAArC,kBAAmB,iBACf,QAAS,OAGwB,kBACnB,oBADA,kBAClB,iBADA,iBAEI,MAAO,KAGM,kBACoB,oBAArC,kBAAmB,iBADiB,iBAApC,gBAEI,UAAW,KACX,YAAa,IAEjB,uBACI,QAAS,KACT,WAAY,OACZ,YAAa,IAEjB,uBACI,QAAQ,KACR,MAAM,KACN,OAAO,KACP,eAAe,YAEnB,uCACI,QAAS,OAEb,2CACI,QAAS,OACT,MAAO,QAEX,qCACI,iBAAkB,QAClB,MAAO,KAEX,kCACI,iBAAkB,QAClB,MAAO,KAEX,iBACI,QAAS,MACT,WAAY,qHACZ,WAAwB,yLACxB,WAA8C,wHAC9C,WAAyE,mHACzE,WAA4F,oHAC5F,WAAwG,sHACxG,MAA6G,EAC7G,OAAQ,KACR,cAAe,IACf,cAAe,IAGnB,uBACI,OAAQ,KACR,cAAe,IAGnB,iCACI,OAAQ,IAGZ,uBACI,SAAU,SACV,QAAS,EACT,OAAQ,iBACR,QAAS,GACT,WAAY,qDAGhB,4BACI,OAAQ,QAGZ,mCACI,QAAS,aACT,OAAQ,QAuBZ,SAaA,oBACI,QAAS,KAlCb,kCACI,SAAU,OACV,WAAY,KACZ,aAAc,KACd,cAAe,KAEf,QAAS,EACT,OAAQ,mBACR,WAAY,uDAGhB,uBACI,QAAS,KACT,WAAY,cACZ,MAAO,KACP,OAAQ,KACR,eAAgB,YAChB,aAAc,IAoBlB,0BACI,QAAS,MAGb,uCACI,WAAY,OACZ,YAAa,KAGjB,8CACI,YAAa,IACb,aAAc,IAGlB,gDACI,eAAgB,KAGpB,8BACI,iBAAkB"}
\ No newline at end of file
+{"version":3,"sources":["_build/fine-uploader.css"],"names":[],"mappings":"AAAA,aACI,SAAU,SACV,MAAO,KAEX,kBACI,QAAS,MACT,MAAO,MACP,QAAS,IAAI,EACb,WAAY,OACZ,WAAY,KACZ,cAAe,IAAI,MAAM,KACzB,MAAO,KAEX,wBACI,WAAY,KAEhB,wBACI,QAAS,IAAI,OAAO,KAExB,qBAAsB,2BAClB,SAAU,SACV,IAAK,EACL,KAAM,EACN,MAAO,KACP,OAAQ,KACR,WAAY,KACZ,QAAS,EACT,WAAY,QACZ,WAAY,OAEhB,0BACI,QAAS,MACT,SAAU,SACV,IAAK,IACL,MAAO,KACP,WAAY,KACZ,UAAW,KAEf,2BACI,SAAU,SACV,WAAY,KACZ,UAAW,KACX,YAAa,KACb,OAAQ,KACR,WAAY,KAEhB,4BACI,WAAY,QAEhB,gBACI,OAAQ,EACR,QAAS,EACT,WAAY,KAEhB,mBACI,OAAQ,EACR,QAAS,IACT,YAAa,KACb,UAAW,KACX,iBAAkB,QAGtB,kBACqC,oBAArC,kBADqC,uBADrC,gBAEmB,iBADA,iBADkB,gBAApB,mBAGb,aAAc,KACd,QAAS,OAIb,mBACI,QAAS,aACT,WAAY,iBACZ,MAAO,KACP,OAAQ,KACR,eAAgB,YAEpB,oBACI,QAAS,MAEb,4BACI,QAAS,aACT,WAAY,oBACZ,MAAO,KACP,OAAQ,KACR,eAAgB,YAGiB,oBAArC,kBAAmB,iBACf,QAAS,OAGwB,kBACnB,oBADA,kBAClB,iBADA,iBAEI,MAAO,KAGM,kBACoB,oBAArC,kBAAmB,iBADiB,iBAApC,gBAEI,UAAW,KACX,YAAa,IAEjB,uBACI,QAAS,KACT,WAAY,OACZ,YAAa,IAEjB,uBACI,QAAQ,KACR,MAAM,KACN,OAAO,KACP,eAAe,YAEnB,uCACI,QAAS,OAEb,2CACI,QAAS,OACT,MAAO,QAEX,qCACI,iBAAkB,QAClB,MAAO,KAEX,kCACI,iBAAkB,QAClB,MAAO,KAEX,iBACI,QAAS,MACT,WAAY,qHACZ,WAAY,yLACZ,WAAY,wHACZ,WAAY,mHACZ,WAAY,oHACZ,WAAY,sHACZ,MAAO,EACP,OAAQ,KACR,cAAe,IACf,cAAe,IAGnB,uBACI,OAAQ,KACR,cAAe,IAGnB,iCACI,OAAQ,IAGZ,uBACI,SAAU,SACV,QAAS,EAET,QAAS,GAIb,4BACI,OAAQ,QAGZ,mCACI,QAAS,aACT,OAAQ,QAGZ,kCACI,SAAU,OACV,WAAY,KACZ,aAAc,KACd,cAAe,KAEf,QAAS,EAKb,uBACI,QAAS,KACT,WAAY,cACZ,MAAO,KACP,OAAQ,KACR,eAAgB,YAChB,aAAc,IAGlB,SACI,QAAS,KAIb,oBACI,QAAS,KAGb,0BACI,QAAS,MAGb,oBACI,QAAS,KAGb,0BACI,QAAS,MAGb,uCACI,WAAY,OACZ,YAAa,KAGjB,8CACI,YAAa,IACb,aAAc,IAGlB,gDACI,eAAgB,KAGpB,8BACI,iBAAkB"}
\ No newline at end of file
diff --git a/styles/bootstrap/fine-uploader/fine-uploader.min.js b/styles/bootstrap/fine-uploader/fine-uploader.min.js
index bcee499fc..add39e107 100644
--- a/styles/bootstrap/fine-uploader/fine-uploader.min.js
+++ b/styles/bootstrap/fine-uploader/fine-uploader.min.js
@@ -1,7 +1,7 @@
-// Fine Uploader 5.12.0 - (c) 2013-present Widen Enterprises, Inc. MIT licensed. http://fineuploader.com
-!function(global){var qq=function(e){"use strict";return{hide:function(){return e.style.display="none",this},attach:function(t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent&&e.attachEvent("on"+t,n),function(){qq(e).detach(t,n)}},detach:function(t,n){return e.removeEventListener?e.removeEventListener(t,n,!1):e.attachEvent&&e.detachEvent("on"+t,n),this},contains:function(t){return!!t&&(e===t||(e.contains?e.contains(t):!!(8&t.compareDocumentPosition(e))))},insertBefore:function(t){return t.parentNode.insertBefore(e,t),this},remove:function(){return e.parentNode.removeChild(e),this},css:function(t){if(null==e.style)throw new qq.Error("Can't apply style to node as it is not on the HTMLElement prototype chain!");return null!=t.opacity&&"string"!=typeof e.style.opacity&&"undefined"!=typeof e.filters&&(t.filter="alpha(opacity="+Math.round(100*t.opacity)+")"),qq.extend(e.style,t),this},hasClass:function(t,n){var i=new RegExp("(^| )"+t+"( |$)");return i.test(e.className)||!(!n||!i.test(e.parentNode.className))},addClass:function(t){return qq(e).hasClass(t)||(e.className+=" "+t),this},removeClass:function(t){var n=new RegExp("(^| )"+t+"( |$)");return e.className=e.className.replace(n," ").replace(/^\s+|\s+$/g,""),this},getByClass:function(t,n){var i,o=[];return n&&e.querySelector?e.querySelector("."+t):e.querySelectorAll?e.querySelectorAll("."+t):(i=e.getElementsByTagName("*"),qq.each(i,function(e,n){qq(n).hasClass(t)&&o.push(n)}),n?o[0]:o)},getFirstByClass:function(t){return qq(e).getByClass(t,!0)},children:function(){for(var t=[],n=e.firstChild;n;)1===n.nodeType&&t.push(n),n=n.nextSibling;return t},setText:function(t){return e.innerText=t,e.textContent=t,this},clearText:function(){return qq(e).setText("")},hasAttribute:function(t){var n;return e.hasAttribute?!!e.hasAttribute(t)&&null==/^false$/i.exec(e.getAttribute(t)):(n=e[t],void 0!==n&&null==/^false$/i.exec(n))}}};!function(){"use strict";qq.canvasToBlob=function(e,t,n){return qq.dataUriToBlob(e.toDataURL(t,n))},qq.dataUriToBlob=function(e){var t,n,i,o,r=function(e,t){var n=window.BlobBuilder||window.WebKitBlobBuilder||window.MozBlobBuilder||window.MSBlobBuilder,i=n&&new n;return i?(i.append(e),i.getBlob(t)):new Blob([e],{type:t})};return n=e.split(",")[0].indexOf("base64")>=0?atob(e.split(",")[1]):decodeURI(e.split(",")[1]),o=e.split(",")[0].split(":")[1].split(";")[0],t=new ArrayBuffer(n.length),i=new Uint8Array(t),qq.each(n,function(e,t){i[e]=t.charCodeAt(0)}),r(t,o)},qq.log=function(e,t){window.console&&(t&&"info"!==t?window.console[t]?window.console[t](e):window.console.log("<"+t+"> "+e):window.console.log(e))},qq.isObject=function(e){return e&&!e.nodeType&&"[object Object]"===Object.prototype.toString.call(e)},qq.isFunction=function(e){return"function"==typeof e},qq.isArray=function(e){return"[object Array]"===Object.prototype.toString.call(e)||e&&window.ArrayBuffer&&e.buffer&&e.buffer.constructor===ArrayBuffer},qq.isItemList=function(e){return"[object DataTransferItemList]"===Object.prototype.toString.call(e)},qq.isNodeList=function(e){return"[object NodeList]"===Object.prototype.toString.call(e)||e.item&&e.namedItem},qq.isString=function(e){return"[object String]"===Object.prototype.toString.call(e)},qq.trimStr=function(e){return String.prototype.trim?e.trim():e.replace(/^\s+|\s+$/g,"")},qq.format=function(e){var t=Array.prototype.slice.call(arguments,1),n=e,i=n.indexOf("{}");return qq.each(t,function(e,t){var o=n.substring(0,i),r=n.substring(i+2);if(n=o+t+r,i=n.indexOf("{}",i+t.length),i<0)return!1}),n},qq.isFile=function(e){return window.File&&"[object File]"===Object.prototype.toString.call(e)},qq.isFileList=function(e){return window.FileList&&"[object FileList]"===Object.prototype.toString.call(e)},qq.isFileOrInput=function(e){return qq.isFile(e)||qq.isInput(e)},qq.isInput=function(e,t){var n=function(e){var n=e.toLowerCase();return t?"file"!==n:"file"===n};return!!(window.HTMLInputElement&&"[object HTMLInputElement]"===Object.prototype.toString.call(e)&&e.type&&n(e.type))||!!(e.tagName&&"input"===e.tagName.toLowerCase()&&e.type&&n(e.type))},qq.isBlob=function(e){if(window.Blob&&"[object Blob]"===Object.prototype.toString.call(e))return!0},qq.isXhrUploadSupported=function(){var e=document.createElement("input");return e.type="file",void 0!==e.multiple&&"undefined"!=typeof File&&"undefined"!=typeof FormData&&"undefined"!=typeof qq.createXhrInstance().upload},qq.createXhrInstance=function(){if(window.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(e){return qq.log("Neither XHR or ActiveX are supported!","error"),null}},qq.isFolderDropSupported=function(e){return e.items&&e.items.length>0&&e.items[0].webkitGetAsEntry},qq.isFileChunkingSupported=function(){return!qq.androidStock()&&qq.isXhrUploadSupported()&&(void 0!==File.prototype.slice||void 0!==File.prototype.webkitSlice||void 0!==File.prototype.mozSlice)},qq.sliceBlob=function(e,t,n){var i=e.slice||e.mozSlice||e.webkitSlice;return i.call(e,t,n)},qq.arrayBufferToHex=function(e){var t="",n=new Uint8Array(e);return qq.each(n,function(e,n){var i=n.toString(16);i.length<2&&(i="0"+i),t+=i}),t},qq.readBlobToHex=function(e,t,n){var i=qq.sliceBlob(e,t,t+n),o=new FileReader,r=new qq.Promise;return o.onload=function(){r.success(qq.arrayBufferToHex(o.result))},o.onerror=r.failure,o.readAsArrayBuffer(i),r},qq.extend=function(e,t,n){return qq.each(t,function(t,i){n&&qq.isObject(i)?(void 0===e[t]&&(e[t]={}),qq.extend(e[t],i,!0)):e[t]=i}),e},qq.override=function(e,t){var n={},i=t(n);return qq.each(i,function(t,i){void 0!==e[t]&&(n[t]=e[t]),e[t]=i}),e},qq.indexOf=function(e,t,n){if(e.indexOf)return e.indexOf(t,n);n=n||0;var i=e.length;for(n<0&&(n+=i);n=0},qq.safari=function(){return void 0!==navigator.vendor&&navigator.vendor.indexOf("Apple")!==-1},qq.chrome=function(){return void 0!==navigator.vendor&&navigator.vendor.indexOf("Google")!==-1},qq.opera=function(){return void 0!==navigator.vendor&&navigator.vendor.indexOf("Opera")!==-1},qq.firefox=function(){return!qq.edge()&&!qq.ie11()&&navigator.userAgent.indexOf("Mozilla")!==-1&&void 0!==navigator.vendor&&""===navigator.vendor},qq.windows=function(){return"Win32"===navigator.platform},qq.android=function(){return navigator.userAgent.toLowerCase().indexOf("android")!==-1},qq.androidStock=function(){return qq.android()&&navigator.userAgent.toLowerCase().indexOf("chrome")<0},qq.ios6=function(){return qq.ios()&&navigator.userAgent.indexOf(" OS 6_")!==-1},qq.ios7=function(){return qq.ios()&&navigator.userAgent.indexOf(" OS 7_")!==-1},qq.ios8=function(){return qq.ios()&&navigator.userAgent.indexOf(" OS 8_")!==-1},qq.ios800=function(){return qq.ios()&&navigator.userAgent.indexOf(" OS 8_0 ")!==-1},qq.ios=function(){return navigator.userAgent.indexOf("iPad")!==-1||navigator.userAgent.indexOf("iPod")!==-1||navigator.userAgent.indexOf("iPhone")!==-1},qq.iosChrome=function(){return qq.ios()&&navigator.userAgent.indexOf("CriOS")!==-1},qq.iosSafari=function(){return qq.ios()&&!qq.iosChrome()&&navigator.userAgent.indexOf("Safari")!==-1},qq.iosSafariWebView=function(){return qq.ios()&&!qq.iosChrome()&&!qq.iosSafari()},qq.preventDefault=function(e){e.preventDefault?e.preventDefault():e.returnValue=!1},qq.toElement=function(){var e=document.createElement("div");return function(t){e.innerHTML=t;var n=e.firstChild;return e.removeChild(n),n}}(),qq.each=function(e,t){var n,i;if(e)if(window.Storage&&e.constructor===window.Storage)for(n=0;n0)return e.substr(t,e.length-t)},qq.getFilename=function(e){return qq.isInput(e)?e.value.replace(/.*(\/|\\)/,""):qq.isFile(e)&&null!==e.fileName&&void 0!==e.fileName?e.fileName:e.name},qq.DisposeSupport=function(){var e=[];return{dispose:function(){var t;do t=e.shift(),t&&t();while(t)},attach:function(){var e=arguments;this.addDisposer(qq(e[0]).attach.apply(this,Array.prototype.slice.call(arguments,1)))},addDisposer:function(t){e.push(t)}}}}(),function(){"use strict";"function"==typeof define&&define.amd?define(function(){return qq}):"undefined"!=typeof module&&module.exports?module.exports=qq:global.qq=qq}(),function(){"use strict";qq.Error=function(e){this.message="[Fine Uploader "+qq.version+"] "+e},qq.Error.prototype=new Error}(),qq.version="5.12.0",qq.supportedFeatures=function(){"use strict";function e(){var e,t=!0;try{e=document.createElement("input"),e.type="file",qq(e).hide(),e.disabled&&(t=!1)}catch(e){t=!1}return t}function t(){return(qq.chrome()||qq.opera())&&void 0!==navigator.userAgent.match(/Chrome\/[2][1-9]|Chrome\/[3-9][0-9]/)}function n(){return(qq.chrome()||qq.opera())&&void 0!==navigator.userAgent.match(/Chrome\/[1][4-9]|Chrome\/[2-9][0-9]/)}function i(){if(window.XMLHttpRequest){var e=qq.createXhrInstance();return void 0!==e.withCredentials}return!1}function o(){return void 0!==window.XDomainRequest}function r(){return!!i()||o()}function a(){return void 0!==document.createElement("input").webkitdirectory}function s(){try{return!!window.localStorage&&qq.isFunction(window.localStorage.setItem)}catch(e){return!1}}function l(){var e=document.createElement("span");return("draggable"in e||"ondragstart"in e&&"ondrop"in e)&&!qq.android()&&!qq.ios()}var u,c,d,p,h,q,f,m,g,_,v,b,y,S,w;return u=e(),p=u&&qq.isXhrUploadSupported(),c=p&&!qq.androidStock(),d=p&&l(),h=d&&t(),q=p&&qq.isFileChunkingSupported(),f=p&&q&&s(),m=p&&n(),g=u&&(void 0!==window.postMessage||p),v=i(),_=o(),b=r(),y=a(),S=p&&void 0!==window.FileReader,w=function(){return!!p&&(!qq.androidStock()&&!qq.iosChrome())}(),{ajaxUploading:p,blobUploading:c,canDetermineSize:p,chunking:q,deleteFileCors:b,deleteFileCorsXdr:_,deleteFileCorsXhr:v,dialogElement:!!window.HTMLDialogElement,fileDrop:d,folderDrop:h,folderSelection:y,imagePreviews:S,imageValidation:S,itemSizeValidation:p,pause:q,progressBar:w,resume:f,scaling:S&&c,tiffPreviews:qq.safari(),unlimitedScaledImageSize:!qq.ios(),uploading:u,uploadCors:g,uploadCustomHeaders:p,uploadNonMultipart:p,uploadViaPaste:m}}(),qq.isGenericPromise=function(e){"use strict";return!!(e&&e.then&&qq.isFunction(e.then))},qq.Promise=function(){"use strict";var e,t,n=[],i=[],o=[],r=0;qq.extend(this,{then:function(o,a){return 0===r?(o&&n.push(o),a&&i.push(a)):r===-1?a&&a.apply(null,t):o&&o.apply(null,e),this},done:function(n){return 0===r?o.push(n):n.apply(null,void 0===t?e:t),this},success:function(){return r=1,e=arguments,n.length&&qq.each(n,function(t,n){n.apply(null,e)}),o.length&&qq.each(o,function(t,n){n.apply(null,e)}),this},failure:function(){return r=-1,t=arguments,i.length&&qq.each(i,function(e,n){n.apply(null,t)}),o.length&&qq.each(o,function(e,n){n.apply(null,t)}),this}})},qq.BlobProxy=function(e,t){"use strict";qq.extend(this,{referenceBlob:e,create:function(){return t(e)}})},qq.UploadButton=function(e){"use strict";function t(){var e=document.createElement("input");return e.setAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME,i),e.setAttribute("title",a.title),o.setMultiple(a.multiple,e),a.folders&&qq.supportedFeatures.folderSelection&&e.setAttribute("webkitdirectory",""),a.acceptFiles&&e.setAttribute("accept",a.acceptFiles),e.setAttribute("type","file"),e.setAttribute("name",a.name),qq(e).css({position:"absolute",right:0,top:0,fontFamily:"Arial",fontSize:qq.ie()&&!qq.ie8()?"3500px":"118px",margin:0,padding:0,cursor:"pointer",opacity:0}),!qq.ie7()&&qq(e).css({height:"100%"}),a.element.appendChild(e),r.attach(e,"change",function(){a.onChange(e)}),r.attach(e,"mouseover",function(){qq(a.element).addClass(a.hoverClass)}),r.attach(e,"mouseout",function(){qq(a.element).removeClass(a.hoverClass)}),r.attach(e,"focus",function(){qq(a.element).addClass(a.focusClass)}),r.attach(e,"blur",function(){qq(a.element).removeClass(a.focusClass)}),e}var n,i,o=this,r=new qq.DisposeSupport,a={acceptFiles:null,element:null,focusClass:"qq-upload-button-focus",folders:!1,hoverClass:"qq-upload-button-hover",ios8BrowserCrashWorkaround:!1,multiple:!1,name:"qqfile",onChange:function(e){},title:null};qq.extend(a,e),i=qq.getUniqueId(),qq(a.element).css({position:"relative",overflow:"hidden",direction:"ltr"}),qq.extend(this,{getInput:function(){return n},getButtonId:function(){return i},setMultiple:function(e,t){var n=t||this.getInput();a.ios8BrowserCrashWorkaround&&qq.ios8()&&(qq.iosChrome()||qq.iosSafariWebView())?n.setAttribute("multiple",""):e?n.setAttribute("multiple",""):n.removeAttribute("multiple")},setAcceptFiles:function(e){e!==a.acceptFiles&&n.setAttribute("accept",e)},reset:function(){n.parentNode&&qq(n).remove(),qq(a.element).removeClass(a.focusClass),n=null,n=t()}}),n=t()},qq.UploadButton.BUTTON_ID_ATTR_NAME="qq-button-id",qq.UploadData=function(e){"use strict";function t(e){if(qq.isArray(e)){var t=[];return qq.each(e,function(e,n){t.push(o[n])}),t}return o[e]}function n(e){if(qq.isArray(e)){var t=[];return qq.each(e,function(e,n){t.push(o[r[n]])}),t}return o[r[e]]}function i(e){var t=[],n=[].concat(e);return qq.each(n,function(e,n){var i=a[n];void 0!==i&&qq.each(i,function(e,n){t.push(o[n])})}),t}var o=[],r={},a={},s={},l={};qq.extend(this,{addFile:function(t){var n=t.status||qq.status.SUBMITTING,i=o.push({name:t.name,originalName:t.name,uuid:t.uuid,size:null==t.size?-1:t.size,status:n})-1;return t.batchId&&(o[i].batchId=t.batchId,void 0===l[t.batchId]&&(l[t.batchId]=[]),l[t.batchId].push(i)),t.proxyGroupId&&(o[i].proxyGroupId=t.proxyGroupId,void 0===s[t.proxyGroupId]&&(s[t.proxyGroupId]=[]),s[t.proxyGroupId].push(i)),o[i].id=i,r[t.uuid]=i,void 0===a[n]&&(a[n]=[]),a[n].push(i),e.onStatusChange(i,null,n),i},retrieve:function(e){return qq.isObject(e)&&o.length?void 0!==e.id?t(e.id):void 0!==e.uuid?n(e.uuid):e.status?i(e.status):void 0:qq.extend([],o,!0)},reset:function(){o=[],r={},a={},l={}},setStatus:function(t,n){var i=o[t].status,r=qq.indexOf(a[i],t);a[i].splice(r,1),o[t].status=n,void 0===a[n]&&(a[n]=[]),a[n].push(t),e.onStatusChange(t,i,n)},uuidChanged:function(e,t){var n=o[e].uuid;o[e].uuid=t,r[t]=e,delete r[n]},updateName:function(e,t){o[e].name=t},updateSize:function(e,t){o[e].size=t},setParentId:function(e,t){o[e].parentId=t},getIdsInProxyGroup:function(e){var t=o[e].proxyGroupId;return t?s[t]:[]},getIdsInBatch:function(e){var t=o[e].batchId;return l[t]}})},qq.status={SUBMITTING:"submitting",SUBMITTED:"submitted",REJECTED:"rejected",QUEUED:"queued",CANCELED:"canceled",PAUSED:"paused",UPLOADING:"uploading",UPLOAD_RETRYING:"retrying upload",UPLOAD_SUCCESSFUL:"upload successful",UPLOAD_FAILED:"upload failed",DELETE_FAILED:"delete failed",DELETING:"deleting",DELETED:"deleted"},function(){"use strict";qq.basePublicApi={addBlobs:function(e,t,n){this.addFiles(e,t,n)},addInitialFiles:function(e){var t=this;qq.each(e,function(e,n){t._addCannedFile(n)})},addFiles:function(e,t,n){this._maybeHandleIos8SafariWorkaround();var i=0===this._storedIds.length?qq.getUniqueId():this._currentBatchId,o=qq.bind(function(e){this._handleNewFile({blob:e,name:this._options.blobs.defaultName},i,d)},this),r=qq.bind(function(e){this._handleNewFile(e,i,d)},this),a=qq.bind(function(e){var t=qq.canvasToBlob(e);this._handleNewFile({blob:t,name:this._options.blobs.defaultName+".png"},i,d)},this),s=qq.bind(function(e){var t=e.quality&&e.quality/100,n=qq.canvasToBlob(e.canvas,e.type,t);this._handleNewFile({blob:n,name:e.name},i,d)},this),l=qq.bind(function(e){if(qq.isInput(e)&&qq.supportedFeatures.ajaxUploading){var t=Array.prototype.slice.call(e.files),n=this;qq.each(t,function(e,t){n._handleNewFile(t,i,d)})}else this._handleNewFile(e,i,d)},this),u=function(){qq.isFileList(e)&&(e=Array.prototype.slice.call(e)),e=[].concat(e)},c=this,d=[];this._currentBatchId=i,e&&(u(),qq.each(e,function(e,t){qq.isFileOrInput(t)?l(t):qq.isBlob(t)?o(t):qq.isObject(t)?t.blob&&t.name?r(t):t.canvas&&t.name&&s(t):t.tagName&&"canvas"===t.tagName.toLowerCase()?a(t):c.log(t+" is not a valid file container! Ignoring!","warn")}),this.log("Received "+d.length+" files."),this._prepareItemsForUpload(d,t,n))},cancel:function(e){this._handler.cancel(e)},cancelAll:function(){var e=[],t=this;qq.extend(e,this._storedIds),qq.each(e,function(e,n){t.cancel(n)}),this._handler.cancelAll()},clearStoredFiles:function(){this._storedIds=[]},continueUpload:function(e){var t=this._uploadData.retrieve({id:e});return!(!qq.supportedFeatures.pause||!this._options.chunking.enabled)&&(t.status===qq.status.PAUSED?(this.log(qq.format("Paused file ID {} ({}) will be continued. Not paused.",e,this.getName(e))),this._uploadFile(e),!0):(this.log(qq.format("Ignoring continue for file ID {} ({}). Not paused.",e,this.getName(e)),"error"),!1))},deleteFile:function(e){return this._onSubmitDelete(e)},doesExist:function(e){return this._handler.isValid(e)},drawThumbnail:function(e,t,n,i,o){var r,a,s=new qq.Promise;return this._imageGenerator?(r=this._thumbnailUrls[e],a={customResizeFunction:o,maxSize:n>0?n:null,scale:n>0},!i&&qq.supportedFeatures.imagePreviews&&(r=this.getFile(e)),null==r?s.failure({container:t,error:"File or URL not found."}):this._imageGenerator.generate(r,t,a).then(function(e){s.success(e)},function(e,t){s.failure({container:e,error:t||"Problem generating thumbnail"})})):s.failure({container:t,error:"Missing image generator module"}),s},getButton:function(e){return this._getButton(this._buttonIdsForFileIds[e])},getEndpoint:function(e){return this._endpointStore.get(e)},getFile:function(e){return this._handler.getFile(e)||null},getInProgress:function(){return this._uploadData.retrieve({status:[qq.status.UPLOADING,qq.status.UPLOAD_RETRYING,qq.status.QUEUED]}).length},getName:function(e){return this._uploadData.retrieve({id:e}).name},getParentId:function(e){var t=this.getUploads({id:e}),n=null;return t&&void 0!==t.parentId&&(n=t.parentId),n},getResumableFilesData:function(){return this._handler.getResumableFilesData()},getSize:function(e){return this._uploadData.retrieve({id:e}).size},getNetUploads:function(){return this._netUploaded},getRemainingAllowedItems:function(){var e=this._currentItemLimit;return e>0?e-this._netUploadedOrQueued:null},getUploads:function(e){return this._uploadData.retrieve(e)},getUuid:function(e){return this._uploadData.retrieve({id:e}).uuid},log:function(e,t){!this._options.debug||t&&"info"!==t?t&&"info"!==t&&qq.log("[Fine Uploader "+qq.version+"] "+e,t):qq.log("[Fine Uploader "+qq.version+"] "+e)},pauseUpload:function(e){var t=this._uploadData.retrieve({id:e});if(!qq.supportedFeatures.pause||!this._options.chunking.enabled)return!1;if(qq.indexOf([qq.status.UPLOADING,qq.status.UPLOAD_RETRYING],t.status)>=0){if(this._handler.pause(e))return this._uploadData.setStatus(e,qq.status.PAUSED),!0;this.log(qq.format("Unable to pause file ID {} ({}).",e,this.getName(e)),"error")}else this.log(qq.format("Ignoring pause for file ID {} ({}). Not in progress.",e,this.getName(e)),"error");return!1},reset:function(){this.log("Resetting uploader..."),this._handler.reset(),this._storedIds=[],this._autoRetries=[],this._retryTimeouts=[],this._preventRetries=[],this._thumbnailUrls=[],qq.each(this._buttons,function(e,t){t.reset()}),this._paramsStore.reset(),this._endpointStore.reset(),this._netUploadedOrQueued=0,this._netUploaded=0,this._uploadData.reset(),this._buttonIdsForFileIds=[],this._pasteHandler&&this._pasteHandler.reset(),this._options.session.refreshOnReset&&this._refreshSessionData(),this._succeededSinceLastAllComplete=[],this._failedSinceLastAllComplete=[],this._totalProgress&&this._totalProgress.reset()},retry:function(e){return this._manualRetry(e)},scaleImage:function(e,t){var n=this;return qq.Scaler.prototype.scaleImage(e,t,{log:qq.bind(n.log,n),getFile:qq.bind(n.getFile,n),uploadData:n._uploadData})},setCustomHeaders:function(e,t){this._customHeadersStore.set(e,t)},setDeleteFileCustomHeaders:function(e,t){this._deleteFileCustomHeadersStore.set(e,t)},setDeleteFileEndpoint:function(e,t){this._deleteFileEndpointStore.set(e,t)},setDeleteFileParams:function(e,t){this._deleteFileParamsStore.set(e,t)},setEndpoint:function(e,t){this._endpointStore.set(e,t)},setForm:function(e){this._updateFormSupportAndParams(e)},setItemLimit:function(e){this._currentItemLimit=e},setName:function(e,t){this._uploadData.updateName(e,t)},setParams:function(e,t){this._paramsStore.set(e,t)},setUuid:function(e,t){return this._uploadData.uuidChanged(e,t)},uploadStoredFiles:function(){0===this._storedIds.length?this._itemError("noFilesError"):this._uploadStoredFiles()}},qq.basePrivateApi={_addCannedFile:function(e){var t=this._uploadData.addFile({uuid:e.uuid,name:e.name,size:e.size,status:qq.status.UPLOAD_SUCCESSFUL});return e.deleteFileEndpoint&&this.setDeleteFileEndpoint(e.deleteFileEndpoint,t),e.deleteFileParams&&this.setDeleteFileParams(e.deleteFileParams,t),e.thumbnailUrl&&(this._thumbnailUrls[t]=e.thumbnailUrl),this._netUploaded++,this._netUploadedOrQueued++,t},_annotateWithButtonId:function(e,t){qq.isFile(e)&&(e.qqButtonId=this._getButtonId(t))},_batchError:function(e){this._options.callbacks.onError(null,null,e,void 0)},_createDeleteHandler:function(){var e=this;return new qq.DeleteFileAjaxRequester({method:this._options.deleteFile.method.toUpperCase(),maxConnections:this._options.maxConnections,uuidParamName:this._options.request.uuidName,customHeaders:this._deleteFileCustomHeadersStore,paramsStore:this._deleteFileParamsStore,endpointStore:this._deleteFileEndpointStore,cors:this._options.cors,log:qq.bind(e.log,e),onDelete:function(t){e._onDelete(t),e._options.callbacks.onDelete(t)},onDeleteComplete:function(t,n,i){e._onDeleteComplete(t,n,i),e._options.callbacks.onDeleteComplete(t,n,i)}})},_createPasteHandler:function(){var e=this;return new qq.PasteSupport({targetElement:this._options.paste.targetElement,callbacks:{log:qq.bind(e.log,e),pasteReceived:function(t){e._handleCheckedCallback({name:"onPasteReceived",callback:qq.bind(e._options.callbacks.onPasteReceived,e,t),onSuccess:qq.bind(e._handlePasteSuccess,e,t),identifier:"pasted image"})}}})},_createStore:function(e,t){var n={},i=e,o={},r=t,a=function(e){return qq.isObject(e)?qq.extend({},e):e},s=function(){return qq.isFunction(r)?r():r},l=function(e,t){r&&qq.isObject(t)&&qq.extend(t,s()),o[e]&&qq.extend(t,o[e])};return{set:function(e,t){null==t?(n={},i=a(e)):n[t]=a(e)},get:function(e){var t;return t=null!=e&&n[e]?n[e]:a(i),l(e,t),a(t)},addReadOnly:function(e,t){qq.isObject(n)&&(null===e?qq.isFunction(t)?r=t:(r=r||{},qq.extend(r,t)):(o[e]=o[e]||{},qq.extend(o[e],t)))},remove:function(e){return delete n[e]},reset:function(){n={},o={},i=e}}},_createUploadDataTracker:function(){var e=this;return new qq.UploadData({getName:function(t){return e.getName(t)},getUuid:function(t){return e.getUuid(t)},getSize:function(t){return e.getSize(t)},onStatusChange:function(t,n,i){e._onUploadStatusChange(t,n,i),e._options.callbacks.onStatusChange(t,n,i),e._maybeAllComplete(t,i),e._totalProgress&&setTimeout(function(){e._totalProgress.onStatusChange(t,n,i)},0)}})},_createUploadButton:function(e){function t(){return!!qq.supportedFeatures.ajaxUploading&&(!(i._options.workarounds.iosEmptyVideos&&qq.ios()&&!qq.ios6()&&i._isAllowedExtension(r,".mov"))&&(void 0===e.multiple?i._options.multiple:e.multiple))}var n,i=this,o=e.accept||this._options.validation.acceptFiles,r=e.allowedExtensions||this._options.validation.allowedExtensions;return n=new qq.UploadButton({acceptFiles:o,element:e.element,focusClass:this._options.classes.buttonFocus,folders:e.folders,hoverClass:this._options.classes.buttonHover,ios8BrowserCrashWorkaround:this._options.workarounds.ios8BrowserCrash,multiple:t(),name:this._options.request.inputName,onChange:function(e){i._onInputChange(e)},title:null==e.title?this._options.text.fileInputTitle:e.title}),this._disposeSupport.addDisposer(function(){n.dispose()}),i._buttons.push(n),n},_createUploadHandler:function(e,t){var n=this,i={},o={debug:this._options.debug,maxConnections:this._options.maxConnections,cors:this._options.cors,paramsStore:this._paramsStore,endpointStore:this._endpointStore,chunking:this._options.chunking,resume:this._options.resume,blobs:this._options.blobs,log:qq.bind(n.log,n),preventRetryParam:this._options.retry.preventRetryResponseProperty,onProgress:function(e,t,o,r){o<0||r<0||(i[e]?i[e].loaded===o&&i[e].total===r||(n._onProgress(e,t,o,r),n._options.callbacks.onProgress(e,t,o,r)):(n._onProgress(e,t,o,r),n._options.callbacks.onProgress(e,t,o,r)),i[e]={loaded:o,total:r})},onComplete:function(e,t,o,r){delete i[e];var a,s=n.getUploads({id:e}).status;s!==qq.status.UPLOAD_SUCCESSFUL&&s!==qq.status.UPLOAD_FAILED&&(a=n._onComplete(e,t,o,r),a instanceof qq.Promise?a.done(function(){n._options.callbacks.onComplete(e,t,o,r)}):n._options.callbacks.onComplete(e,t,o,r))},onCancel:function(e,t,i){var o=new qq.Promise;return n._handleCheckedCallback({name:"onCancel",callback:qq.bind(n._options.callbacks.onCancel,n,e,t),onFailure:o.failure,onSuccess:function(){i.then(function(){n._onCancel(e,t)}),o.success()},identifier:e}),o},onUploadPrep:qq.bind(this._onUploadPrep,this),onUpload:function(e,t){n._onUpload(e,t),n._options.callbacks.onUpload(e,t)},onUploadChunk:function(e,t,i){n._onUploadChunk(e,i),n._options.callbacks.onUploadChunk(e,t,i)},onUploadChunkSuccess:function(e,t,i,o){n._options.callbacks.onUploadChunkSuccess.apply(n,arguments)},onResume:function(e,t,i){return n._options.callbacks.onResume(e,t,i)},onAutoRetry:function(e,t,i,o){return n._onAutoRetry.apply(n,arguments)},onUuidChanged:function(e,t){n.log("Server requested UUID change from '"+n.getUuid(e)+"' to '"+t+"'"),n.setUuid(e,t)},getName:qq.bind(n.getName,n),getUuid:qq.bind(n.getUuid,n),getSize:qq.bind(n.getSize,n),setSize:qq.bind(n._setSize,n),getDataByUuid:function(e){return n.getUploads({uuid:e})},isQueued:function(e){var t=n.getUploads({id:e}).status;return t===qq.status.QUEUED||t===qq.status.SUBMITTED||t===qq.status.UPLOAD_RETRYING||t===qq.status.PAUSED},getIdsInProxyGroup:n._uploadData.getIdsInProxyGroup,getIdsInBatch:n._uploadData.getIdsInBatch};return qq.each(this._options.request,function(e,t){o[e]=t}),o.customHeaders=this._customHeadersStore,e&&qq.each(e,function(e,t){o[e]=t}),new qq.UploadHandlerController(o,t)},_fileOrBlobRejected:function(e){this._netUploadedOrQueued--,this._uploadData.setStatus(e,qq.status.REJECTED)},_formatSize:function(e){if(0===e)return e+this._options.text.sizeSymbols[0];var t=-1;do e/=1e3,t++;while(e>999);return Math.max(e,.1).toFixed(1)+this._options.text.sizeSymbols[t]},_generateExtraButtonSpecs:function(){var e=this;this._extraButtonSpecs={},qq.each(this._options.extraButtons,function(t,n){var i=n.multiple,o=qq.extend({},e._options.validation,!0),r=qq.extend({},n);void 0===i&&(i=e._options.multiple),r.validation&&qq.extend(o,n.validation,!0),qq.extend(r,{multiple:i,validation:o},!0),e._initExtraButton(r)})},_getButton:function(e){var t=this._extraButtonSpecs[e];return t?t.element:e===this._defaultButtonId?this._options.button:void 0},_getButtonId:function(e){var t,n,i=e;if(i instanceof qq.BlobProxy&&(i=i.referenceBlob),i&&!qq.isBlob(i)){if(qq.isFile(i))return i.qqButtonId;if("input"===i.tagName.toLowerCase()&&"file"===i.type.toLowerCase())return i.getAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME);if(t=i.getElementsByTagName("input"),qq.each(t,function(e,t){if("file"===t.getAttribute("type"))return n=t,!1}),n)return n.getAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME)}},_getNotFinished:function(){return this._uploadData.retrieve({status:[qq.status.UPLOADING,qq.status.UPLOAD_RETRYING,qq.status.QUEUED,qq.status.SUBMITTING,qq.status.SUBMITTED,qq.status.PAUSED]}).length},_getValidationBase:function(e){var t=this._extraButtonSpecs[e];return t?t.validation:this._options.validation},_getValidationDescriptor:function(e){return e.file instanceof qq.BlobProxy?{name:qq.getFilename(e.file.referenceBlob),size:e.file.referenceBlob.size}:{name:this.getUploads({id:e.id}).name,size:this.getUploads({id:e.id}).size}},_getValidationDescriptors:function(e){var t=this,n=[];return qq.each(e,function(e,i){n.push(t._getValidationDescriptor(i))}),n},_handleCameraAccess:function(){if(this._options.camera.ios&&qq.ios()){var e="image/*;capture=camera",t=this._options.camera.button,n=t?this._getButtonId(t):this._defaultButtonId,i=this._options;n&&n!==this._defaultButtonId&&(i=this._extraButtonSpecs[n]),i.multiple=!1,null===i.validation.acceptFiles?i.validation.acceptFiles=e:i.validation.acceptFiles+=","+e,qq.each(this._buttons,function(e,t){if(t.getButtonId()===n)return t.setMultiple(i.multiple),t.setAcceptFiles(i.acceptFiles),!1})}},_handleCheckedCallback:function(e){var t=this,n=e.callback();return qq.isGenericPromise(n)?(this.log(e.name+" - waiting for "+e.name+" promise to be fulfilled for "+e.identifier),n.then(function(n){t.log(e.name+" promise success for "+e.identifier),e.onSuccess(n)},function(){e.onFailure?(t.log(e.name+" promise failure for "+e.identifier),e.onFailure()):t.log(e.name+" promise failure for "+e.identifier)})):(n!==!1?e.onSuccess(n):e.onFailure?(this.log(e.name+" - return value was 'false' for "+e.identifier+". Invoking failure callback."),e.onFailure()):this.log(e.name+" - return value was 'false' for "+e.identifier+". Will not proceed."),n)},_handleNewFile:function(e,t,n){var i=this,o=qq.getUniqueId(),r=-1,a=qq.getFilename(e),s=e.blob||e,l=this._customNewFileHandler?this._customNewFileHandler:qq.bind(i._handleNewFileGeneric,i);!qq.isInput(s)&&s.size>=0&&(r=s.size),l(s,a,o,r,n,t,this._options.request.uuidName,{uploadData:i._uploadData,paramsStore:i._paramsStore,addFileToHandler:function(e,t){i._handler.add(e,t),i._netUploadedOrQueued++,i._trackButton(e);
-}})},_handleNewFileGeneric:function(e,t,n,i,o,r){var a=this._uploadData.addFile({uuid:n,name:t,size:i,batchId:r});this._handler.add(a,e),this._trackButton(a),this._netUploadedOrQueued++,o.push({id:a,file:e})},_handlePasteSuccess:function(e,t){var n=e.type.split("/")[1],i=t;null==i&&(i=this._options.paste.defaultName),i+="."+n,this.addFiles({name:i,blob:e})},_initExtraButton:function(e){var t=this._createUploadButton({accept:e.validation.acceptFiles,allowedExtensions:e.validation.allowedExtensions,element:e.element,folders:e.folders,multiple:e.multiple,title:e.fileInputTitle});this._extraButtonSpecs[t.getButtonId()]=e},_initFormSupportAndParams:function(){this._formSupport=qq.FormSupport&&new qq.FormSupport(this._options.form,qq.bind(this.uploadStoredFiles,this),qq.bind(this.log,this)),this._formSupport&&this._formSupport.attachedToForm?(this._paramsStore=this._createStore(this._options.request.params,this._formSupport.getFormInputsAsObject),this._options.autoUpload=this._formSupport.newAutoUpload,this._formSupport.newEndpoint&&(this._options.request.endpoint=this._formSupport.newEndpoint)):this._paramsStore=this._createStore(this._options.request.params)},_isDeletePossible:function(){return!(!qq.DeleteFileAjaxRequester||!this._options.deleteFile.enabled)&&(!this._options.cors.expected||(!!qq.supportedFeatures.deleteFileCorsXhr||!(!qq.supportedFeatures.deleteFileCorsXdr||!this._options.cors.allowXdr)))},_isAllowedExtension:function(e,t){var n=!1;return!e.length||(qq.each(e,function(e,i){if(qq.isString(i)){var o=new RegExp("\\."+i+"$","i");if(null!=t.match(o))return n=!0,!1}}),n)},_itemError:function(e,t,n){function i(e,t){a=a.replace(e,t)}var o,r,a=this._options.messages[e],s=[],l=[].concat(t),u=l[0],c=this._getButtonId(n),d=this._getValidationBase(c);return qq.each(d.allowedExtensions,function(e,t){qq.isString(t)&&s.push(t)}),o=s.join(", ").toLowerCase(),i("{file}",this._options.formatFileName(u)),i("{extensions}",o),i("{sizeLimit}",this._formatSize(d.sizeLimit)),i("{minSizeLimit}",this._formatSize(d.minSizeLimit)),r=a.match(/(\{\w+\})/g),null!==r&&qq.each(r,function(e,t){i(t,l[e])}),this._options.callbacks.onError(null,u,a,void 0),a},_manualRetry:function(e,t){if(this._onBeforeManualRetry(e))return this._netUploadedOrQueued++,this._uploadData.setStatus(e,qq.status.UPLOAD_RETRYING),t?t(e):this._handler.retry(e),!0},_maybeAllComplete:function(e,t){var n=this,i=this._getNotFinished();t===qq.status.UPLOAD_SUCCESSFUL?this._succeededSinceLastAllComplete.push(e):t===qq.status.UPLOAD_FAILED&&this._failedSinceLastAllComplete.push(e),0===i&&(this._succeededSinceLastAllComplete.length||this._failedSinceLastAllComplete.length)&&setTimeout(function(){n._onAllComplete(n._succeededSinceLastAllComplete,n._failedSinceLastAllComplete)},0)},_maybeHandleIos8SafariWorkaround:function(){var e=this;if(this._options.workarounds.ios8SafariUploads&&qq.ios800()&&qq.iosSafari())throw setTimeout(function(){window.alert(e._options.messages.unsupportedBrowserIos8Safari)},0),new qq.Error(this._options.messages.unsupportedBrowserIos8Safari)},_maybeParseAndSendUploadError:function(e,t,n,i){if(!n.success)if(i&&200!==i.status&&!n.error)this._options.callbacks.onError(e,t,"XHR returned response code "+i.status,i);else{var o=n.error?n.error:this._options.text.defaultResponseError;this._options.callbacks.onError(e,t,o,i)}},_maybeProcessNextItemAfterOnValidateCallback:function(e,t,n,i,o){var r=this;if(t.length>n)if(e||!this._options.validation.stopOnFirstInvalidFile)setTimeout(function(){var e=r._getValidationDescriptor(t[n]),a=r._getButtonId(t[n].file),s=r._getButton(a);r._handleCheckedCallback({name:"onValidate",callback:qq.bind(r._options.callbacks.onValidate,r,e,s),onSuccess:qq.bind(r._onValidateCallbackSuccess,r,t,n,i,o),onFailure:qq.bind(r._onValidateCallbackFailure,r,t,n,i,o),identifier:"Item '"+e.name+"', size: "+e.size})},0);else if(!e)for(;n0&&this._netUploadedOrQueued+1>n?(this._itemError("retryFailTooManyItems"),!1):(this.log("Retrying upload for '"+t+"' (id: "+e+")..."),!0))):(this.log("'"+e+"' is not a valid file ID","error"),!1)},_onCancel:function(e,t){this._netUploadedOrQueued--,clearTimeout(this._retryTimeouts[e]);var n=qq.indexOf(this._storedIds,e);!this._options.autoUpload&&n>=0&&this._storedIds.splice(n,1),this._uploadData.setStatus(e,qq.status.CANCELED)},_onComplete:function(e,t,n,i){return n.success?(n.thumbnailUrl&&(this._thumbnailUrls[e]=n.thumbnailUrl),this._netUploaded++,this._uploadData.setStatus(e,qq.status.UPLOAD_SUCCESSFUL)):(this._netUploadedOrQueued--,this._uploadData.setStatus(e,qq.status.UPLOAD_FAILED),n[this._options.retry.preventRetryResponseProperty]===!0&&(this._preventRetries[e]=!0)),this._maybeParseAndSendUploadError(e,t,n,i),!!n.success},_onDelete:function(e){this._uploadData.setStatus(e,qq.status.DELETING)},_onDeleteComplete:function(e,t,n){var i=this.getName(e);n?(this._uploadData.setStatus(e,qq.status.DELETE_FAILED),this.log("Delete request for '"+i+"' has failed.","error"),void 0===t.withCredentials?this._options.callbacks.onError(e,i,"Delete request failed",t):this._options.callbacks.onError(e,i,"Delete request failed with response code "+t.status,t)):(this._netUploadedOrQueued--,this._netUploaded--,this._handler.expunge(e),this._uploadData.setStatus(e,qq.status.DELETED),this.log("Delete request for '"+i+"' has succeeded."))},_onInputChange:function(e){var t;if(qq.supportedFeatures.ajaxUploading){for(t=0;t0&&this.addFiles(e);qq.each(this._buttons,function(e,t){t.reset()})},_onProgress:function(e,t,n,i){this._totalProgress&&this._totalProgress.onIndividualProgress(e,n,i)},_onSubmit:function(e,t){},_onSubmitCallbackSuccess:function(e,t){this._onSubmit.apply(this,arguments),this._uploadData.setStatus(e,qq.status.SUBMITTED),this._onSubmitted.apply(this,arguments),this._options.autoUpload?(this._options.callbacks.onSubmitted.apply(this,arguments),this._uploadFile(e)):(this._storeForLater(e),this._options.callbacks.onSubmitted.apply(this,arguments))},_onSubmitDelete:function(e,t,n){var i,o=this.getUuid(e);return t&&(i=qq.bind(t,this,e,o,n)),this._isDeletePossible()?(this._handleCheckedCallback({name:"onSubmitDelete",callback:qq.bind(this._options.callbacks.onSubmitDelete,this,e),onSuccess:i||qq.bind(this._deleteHandler.sendDelete,this,e,o,n),identifier:e}),!0):(this.log("Delete request ignored for ID "+e+", delete feature is disabled or request not possible due to CORS on a user agent that does not support pre-flighting.","warn"),!1)},_onSubmitted:function(e){},_onTotalProgress:function(e,t){this._options.callbacks.onTotalProgress(e,t)},_onUploadPrep:function(e){},_onUpload:function(e,t){this._uploadData.setStatus(e,qq.status.UPLOADING)},_onUploadChunk:function(e,t){},_onUploadStatusChange:function(e,t,n){n===qq.status.PAUSED&&clearTimeout(this._retryTimeouts[e])},_onValidateBatchCallbackFailure:function(e){var t=this;qq.each(e,function(e,n){t._fileOrBlobRejected(n.id)})},_onValidateBatchCallbackSuccess:function(e,t,n,i,o){var r,a=this._currentItemLimit,s=this._netUploadedOrQueued;0===a||s<=a?t.length>0?this._handleCheckedCallback({name:"onValidate",callback:qq.bind(this._options.callbacks.onValidate,this,e[0],o),onSuccess:qq.bind(this._onValidateCallbackSuccess,this,t,0,n,i),onFailure:qq.bind(this._onValidateCallbackFailure,this,t,0,n,i),identifier:"Item '"+t[0].file.name+"', size: "+t[0].file.size}):this._itemError("noFilesError"):(this._onValidateBatchCallbackFailure(t),r=this._options.messages.tooManyItemsError.replace(/\{netItems\}/g,s).replace(/\{itemLimit\}/g,a),this._batchError(r))},_onValidateCallbackFailure:function(e,t,n,i){var o=t+1;this._fileOrBlobRejected(e[t].id,e[t].file.name),this._maybeProcessNextItemAfterOnValidateCallback(!1,e,o,n,i)},_onValidateCallbackSuccess:function(e,t,n,i){var o=this,r=t+1,a=this._getValidationDescriptor(e[t]);this._validateFileOrBlobData(e[t],a).then(function(){o._upload(e[t].id,n,i),o._maybeProcessNextItemAfterOnValidateCallback(!0,e,r,n,i)},function(){o._maybeProcessNextItemAfterOnValidateCallback(!1,e,r,n,i)})},_prepareItemsForUpload:function(e,t,n){if(0===e.length)return void this._itemError("noFilesError");var i=this._getValidationDescriptors(e),o=this._getButtonId(e[0].file),r=this._getButton(o);this._handleCheckedCallback({name:"onValidateBatch",callback:qq.bind(this._options.callbacks.onValidateBatch,this,i,r),onSuccess:qq.bind(this._onValidateBatchCallbackSuccess,this,i,e,t,n,r),onFailure:qq.bind(this._onValidateBatchCallbackFailure,this,e),identifier:"batch validation"})},_preventLeaveInProgress:function(){var e=this;this._disposeSupport.attach(window,"beforeunload",function(t){if(e.getInProgress())return t=t||window.event,t.returnValue=e._options.messages.onLeave,e._options.messages.onLeave})},_refreshSessionData:function(){var e=this,t=this._options.session;qq.Session&&null!=this._options.session.endpoint&&(this._session||(qq.extend(t,{cors:this._options.cors}),t.log=qq.bind(this.log,this),t.addFileRecord=qq.bind(this._addCannedFile,this),this._session=new qq.Session(t)),setTimeout(function(){e._session.refresh().then(function(t,n){e._sessionRequestComplete(),e._options.callbacks.onSessionRequestComplete(t,!0,n)},function(t,n){e._options.callbacks.onSessionRequestComplete(t,!1,n)})},0))},_sessionRequestComplete:function(){},_setSize:function(e,t){this._uploadData.updateSize(e,t),this._totalProgress&&this._totalProgress.onNewSize(e)},_shouldAutoRetry:function(e,t,n){var i=this._uploadData.retrieve({id:e});return!!(!this._preventRetries[e]&&this._options.retry.enableAuto&&i.status!==qq.status.PAUSED&&(void 0===this._autoRetries[e]&&(this._autoRetries[e]=0),this._autoRetries[e]0&&s.sizeLimit&&r>s.sizeLimit?(this._itemError("sizeError",o,i),l.failure()):r>0&&r=0}function n(e){var t=!1;return qq.each(t,function(e,n){if(qq.indexOf(["Accept","Accept-Language","Content-Language","Content-Type"],n)<0)return t=!0,!1}),t}function i(e){return S.cors.expected&&void 0===e.withCredentials}function o(){var e;return(window.XMLHttpRequest||window.ActiveXObject)&&(e=qq.createXhrInstance(),void 0===e.withCredentials&&(e=new XDomainRequest,e.onload=function(){},e.onerror=function(){},e.ontimeout=function(){},e.onprogress=function(){})),e}function r(e,t){var n=y[e].xhr;return n||(n=t?t:S.cors.expected?o():qq.createXhrInstance(),y[e].xhr=n),n}function a(e){var t,n=qq.indexOf(b,e),i=S.maxConnections;delete y[e],b.splice(n,1),b.length>=i&&n=0?o.send(qq.obj2url(s,"")):s&&S.contentType&&S.contentType.toLowerCase().indexOf("application/json")>=0?o.send(JSON.stringify(s)):o.send(s),o}function c(e,t,n){var i=S.endpointStore.get(e),o=y[e].addToPath;return void 0!=o&&(i+="/"+o),v&&t&&(i=qq.obj2url(t,i)),n&&(i=qq.obj2url(n,i)),i}function d(e){return function(){4===r(e).readyState&&s(e)}}function p(e){var t=S.onProgress;t&&(r(e).upload.onprogress=function(n){n.lengthComputable&&t(e,n.loaded,n.total)})}function h(e){return function(){s(e)}}function q(e){return function(){s(e,!0)}}function f(e){var o=r(e),a=S.customHeaders,s=y[e].additionalHeaders||{},l=S.method,u={};i(o)||(S.acceptHeader&&o.setRequestHeader("Accept",S.acceptHeader),S.allowXRequestedWithAndCacheControl&&(S.cors.expected&&t()&&!n(a)||(o.setRequestHeader("X-Requested-With","XMLHttpRequest"),o.setRequestHeader("Cache-Control","no-cache"))),!S.contentType||"POST"!==l&&"PUT"!==l||o.setRequestHeader("Content-Type",S.contentType),qq.extend(u,qq.isFunction(a)?a(e):a),qq.extend(u,s),qq.each(u,function(e,t){o.setRequestHeader(e,t)}))}function m(e){return qq.indexOf(S.successfulResponseCodes[S.method],e)>=0}function g(e,t,n,i,o,r,a){y[e]={addToPath:n,additionalParams:i,additionalQueryParams:o,additionalHeaders:r,payload:a};var s=b.push(e);if(s<=S.maxConnections)return u(e,t)}var _,v,b=[],y={},S={acceptHeader:null,validMethods:["PATCH","POST","PUT"],method:"POST",contentType:"application/x-www-form-urlencoded",maxConnections:3,customHeaders:{},endpointStore:{},paramsStore:{},mandatedParams:{},allowXRequestedWithAndCacheControl:!0,successfulResponseCodes:{DELETE:[200,202,204],PATCH:[200,201,202,203,204],POST:[200,201,202,203,204],PUT:[200,201,202,203,204],GET:[200]},cors:{expected:!1,sendCredentials:!1},log:function(e,t){},onSend:function(e){},onComplete:function(e,t,n){},onProgress:null};if(qq.extend(S,e),_=S.log,qq.indexOf(S.validMethods,S.method)<0)throw new Error("'"+S.method+"' is not a supported method for this type of request!");v="GET"===S.method||"DELETE"===S.method,qq.extend(this,{initTransport:function(e){var t,n,i,o,r,a;return{withPath:function(e){return t=e,this},withParams:function(e){return n=e,this},withQueryParams:function(e){return a=e,this},withHeaders:function(e){return i=e,this},withPayload:function(e){return o=e,this},withCacheBuster:function(){return r=!0,this},send:function(s){return r&&qq.indexOf(["GET","DELETE"],S.method)>=0&&(n.qqtimestamp=(new Date).getTime()),g(e,s,t,n,a,i,o)}}},canceled:function(e){a(e)}})},qq.UploadHandler=function(e){"use strict";var t=e.proxy,n={},i=t.onCancel,o=t.getName;qq.extend(this,{add:function(e,t){n[e]=t,n[e].temp={}},cancel:function(e){var t=this,r=new qq.Promise,a=i(e,o(e),r);a.then(function(){t.isValid(e)&&(n[e].canceled=!0,t.expunge(e)),r.success()})},expunge:function(e){delete n[e]},getThirdPartyFileId:function(e){return n[e].key},isValid:function(e){return void 0!==n[e]},reset:function(){n={}},_getFileState:function(e){return n[e]},_setThirdPartyFileId:function(e,t){n[e].key=t},_wasCanceled:function(e){return!!n[e].canceled}})},qq.UploadHandlerController=function(e,t){"use strict";var n,i,o,r=this,a=!1,s=!1,l={paramsStore:{},maxConnections:3,chunking:{enabled:!1,multiple:{enabled:!1}},log:function(e,t){},onProgress:function(e,t,n,i){},onComplete:function(e,t,n,i){},onCancel:function(e,t){},onUploadPrep:function(e){},onUpload:function(e,t){},onUploadChunk:function(e,t,n){},onUploadChunkSuccess:function(e,t,n,i){},onAutoRetry:function(e,t,n,i){},onResume:function(e,t,n){},onUuidChanged:function(e,t){},getName:function(e){},setSize:function(e,t){},isQueued:function(e){},getIdsInProxyGroup:function(e){},getIdsInBatch:function(e){}},u={done:function(e,t,n,i){var r=o._getChunkData(e,t);o._getFileState(e).attemptingResume=!1,delete o._getFileState(e).temp.chunkProgress[t],o._getFileState(e).loaded+=r.size,l.onUploadChunkSuccess(e,o._getChunkDataForCallback(r),n,i)},finalize:function(e){var t=l.getSize(e),n=l.getName(e);i("All chunks have been uploaded for "+e+" - finalizing...."),o.finalizeChunks(e).then(function(r,a){i("Finalize successful for "+e);var s=p.normalizeResponse(r,!0);l.onProgress(e,n,t,t),o._maybeDeletePersistedChunkData(e),p.cleanup(e,s,a)},function(t,o){var r=p.normalizeResponse(t,!1);i("Problem finalizing chunks for file ID "+e+" - "+r.error,"error"),r.reset&&u.reset(e),l.onAutoRetry(e,n,r,o)||p.cleanup(e,r,o)})},handleFailure:function(e,t,n,r){var a=l.getName(t);i("Chunked upload request failed for "+t+", chunk "+e),o.clearCachedChunk(t,e);var d,h=p.normalizeResponse(n,!1);h.reset?u.reset(t):(d=qq.indexOf(o._getFileState(t).chunking.inProgress,e),d>=0&&(o._getFileState(t).chunking.inProgress.splice(d,1),o._getFileState(t).chunking.remaining.unshift(e))),o._getFileState(t).temp.ignoreFailure||(s&&(o._getFileState(t).temp.ignoreFailure=!0,i(qq.format("Going to attempt to abort these chunks: {}. These are currently in-progress: {}.",JSON.stringify(Object.keys(o._getXhrs(t))),JSON.stringify(o._getFileState(t).chunking.inProgress))),qq.each(o._getXhrs(t),function(e,n){i(qq.format("Attempting to abort file {}.{}. XHR readyState {}. ",t,e,n.readyState)),n.abort(),n._cancelled=!0}),o.moveInProgressToRemaining(t),c.free(t,!0)),l.onAutoRetry(t,a,h,r)||p.cleanup(t,h,r))},hasMoreParts:function(e){return!!o._getFileState(e).chunking.remaining.length},nextPart:function(e){var t=o._getFileState(e).chunking.remaining.shift();return t>=o._getTotalChunks(e)&&(t=null),t},reset:function(e){i("Server or callback has ordered chunking effort to be restarted on next attempt for item ID "+e,"error"),o._maybeDeletePersistedChunkData(e),o.reevaluateChunking(e),o._getFileState(e).loaded=0},sendNext:function(e){var t=l.getSize(e),n=l.getName(e),r=u.nextPart(e),a=o._getChunkData(e,r),d=o._getFileState(e).attemptingResume,h=o._getFileState(e).chunking.inProgress||[];null==o._getFileState(e).loaded&&(o._getFileState(e).loaded=0),d&&l.onResume(e,n,a)===!1&&(u.reset(e),r=u.nextPart(e),a=o._getChunkData(e,r),d=!1),null==r&&0===h.length?u.finalize(e):(i(qq.format("Sending chunked upload request for item {}.{}, bytes {}-{} of {}.",e,r,a.start+1,a.end,t)),l.onUploadChunk(e,n,o._getChunkDataForCallback(a)),h.push(r),o._getFileState(e).chunking.inProgress=h,s&&c.open(e,r),s&&c.available()&&o._getFileState(e).chunking.remaining.length&&u.sendNext(e),0===a.blob.size?(i(qq.format("Chunk {} for file {} will not be uploaded, zero sized chunk.",r,e),"error"),u.handleFailure(r,e,"File is no longer available",null)):o.uploadChunk(e,r,d).then(function(t,n){i("Chunked upload request succeeded for "+e+", chunk "+r),o.clearCachedChunk(e,r);var a=o._getFileState(e).chunking.inProgress||[],s=p.normalizeResponse(t,!0),l=qq.indexOf(a,r);i(qq.format("Chunk {} for file {} uploaded successfully.",r,e)),u.done(e,r,s,n),l>=0&&a.splice(l,1),o._maybePersistChunkedState(e),u.hasMoreParts(e)||0!==a.length?u.hasMoreParts(e)?u.sendNext(e):i(qq.format("File ID {} has no more chunks to send and these chunk indexes are still marked as in-progress: {}",e,JSON.stringify(a))):u.finalize(e)},function(t,n){u.handleFailure(r,e,t,n)}).done(function(){o.clearXhr(e,r)}))}},c={_open:[],_openChunks:{},_waiting:[],available:function(){var e=l.maxConnections,t=0,n=0;return qq.each(c._openChunks,function(e,i){t++,n+=i.length}),e-(c._open.length-t+n)},free:function(e,t){var n,r=!t,a=qq.indexOf(c._waiting,e),s=qq.indexOf(c._open,e);delete c._openChunks[e],p.getProxyOrBlob(e)instanceof qq.BlobProxy&&(i("Generated blob upload has ended for "+e+", disposing generated blob."),delete o._getFileState(e).file),a>=0?c._waiting.splice(a,1):r&&s>=0&&(c._open.splice(s,1),n=c._waiting.shift(),n>=0&&(c._open.push(n),p.start(n)))},getWaitingOrConnected:function(){var e=[];return qq.each(c._openChunks,function(t,n){n&&n.length&&e.push(parseInt(t))}),qq.each(c._open,function(t,n){c._openChunks[n]||e.push(parseInt(n))}),e=e.concat(c._waiting)},isUsingConnection:function(e){return qq.indexOf(c._open,e)>=0},open:function(e,t){return null==t&&c._waiting.push(e),!!c.available()&&(null==t?(c._waiting.pop(),c._open.push(e)):!function(){var n=c._openChunks[e]||[];n.push(t),c._openChunks[e]=n}(),!0)},reset:function(){c._waiting=[],c._open=[]}},d={send:function(e,t){o._getFileState(e).loaded=0,i("Sending simple upload request for "+e),o.uploadFile(e).then(function(n,o){i("Simple upload request succeeded for "+e);var r=p.normalizeResponse(n,!0),a=l.getSize(e);l.onProgress(e,t,a,a),p.maybeNewUuid(e,r),p.cleanup(e,r,o)},function(n,o){i("Simple upload request failed for "+e);var r=p.normalizeResponse(n,!1);l.onAutoRetry(e,t,r,o)||p.cleanup(e,r,o)})}},p={cancel:function(e){i("Cancelling "+e),l.paramsStore.remove(e),c.free(e)},cleanup:function(e,t,n){var i=l.getName(e);l.onComplete(e,i,t,n),o._getFileState(e)&&o._clearXhrs&&o._clearXhrs(e),c.free(e)},getProxyOrBlob:function(e){return o.getProxy&&o.getProxy(e)||o.getFile&&o.getFile(e)},initHandler:function(){var e=t?qq[t]:qq.traditional,n=qq.supportedFeatures.ajaxUploading?"Xhr":"Form";o=new e[n+"UploadHandler"](l,{getDataByUuid:l.getDataByUuid,getName:l.getName,getSize:l.getSize,getUuid:l.getUuid,log:i,onCancel:l.onCancel,onProgress:l.onProgress,onUuidChanged:l.onUuidChanged}),o._removeExpiredChunkingRecords&&o._removeExpiredChunkingRecords()},isDeferredEligibleForUpload:function(e){return l.isQueued(e)},maybeDefer:function(e,t){return t&&!o.getFile(e)&&t instanceof qq.BlobProxy?(l.onUploadPrep(e),i("Attempting to generate a blob on-demand for "+e),t.create().then(function(t){i("Generated an on-demand blob for "+e),o.updateBlob(e,t),l.setSize(e,t.size),o.reevaluateChunking(e),p.maybeSendDeferredFiles(e)},function(t){var o={};t&&(o.error=t),i(qq.format("Failed to generate blob for ID {}. Error message: {}.",e,t),"error"),l.onComplete(e,l.getName(e),qq.extend(o,n),null),p.maybeSendDeferredFiles(e),c.free(e)}),!1):p.maybeSendDeferredFiles(e)},maybeSendDeferredFiles:function(e){var t=l.getIdsInProxyGroup(e),n=!1;return t&&t.length?(i("Maybe ready to upload proxy group file "+e),qq.each(t,function(t,i){if(p.isDeferredEligibleForUpload(i)&&o.getFile(i))n=i===e,p.now(i);else if(p.isDeferredEligibleForUpload(i))return!1})):(n=!0,p.now(e)),n},maybeNewUuid:function(e,t){void 0!==t.newUuid&&l.onUuidChanged(e,t.newUuid)},normalizeResponse:function(e,t){var n=e;return qq.isObject(e)||(n={},qq.isString(e)&&!t&&(n.error=e)),n.success=t,n},now:function(e){var t=l.getName(e);if(!r.isValid(e))throw new qq.Error(e+" is not a valid file ID to upload!");l.onUpload(e,t),a&&o._shouldChunkThisFile(e)?u.sendNext(e):d.send(e,t)},start:function(e){var t=p.getProxyOrBlob(e);return t?p.maybeDefer(e,t):(p.now(e),!0)}};qq.extend(this,{add:function(e,t){o.add.apply(this,arguments)},upload:function(e){return!!c.open(e)&&p.start(e)},retry:function(e){return s&&(o._getFileState(e).temp.ignoreFailure=!1),c.isUsingConnection(e)?p.start(e):r.upload(e)},cancel:function(e){var t=o.cancel(e);qq.isGenericPromise(t)?t.then(function(){p.cancel(e)}):t!==!1&&p.cancel(e)},cancelAll:function(){var e,t=c.getWaitingOrConnected();if(t.length)for(e=t.length-1;e>=0;e--)r.cancel(t[e]);c.reset()},getFile:function(e){return o.getProxy&&o.getProxy(e)?o.getProxy(e).referenceBlob:o.getFile&&o.getFile(e);
-},isProxied:function(e){return!(!o.getProxy||!o.getProxy(e))},getInput:function(e){if(o.getInput)return o.getInput(e)},reset:function(){i("Resetting upload handler"),r.cancelAll(),c.reset(),o.reset()},expunge:function(e){if(r.isValid(e))return o.expunge(e)},isValid:function(e){return o.isValid(e)},getResumableFilesData:function(){return o.getResumableFilesData?o.getResumableFilesData():[]},getThirdPartyFileId:function(e){if(r.isValid(e))return o.getThirdPartyFileId(e)},pause:function(e){return!!(r.isResumable(e)&&o.pause&&r.isValid(e)&&o.pause(e))&&(c.free(e),o.moveInProgressToRemaining(e),!0)},isResumable:function(e){return!!o.isResumable&&o.isResumable(e)}}),qq.extend(l,e),i=l.log,a=l.chunking.enabled&&qq.supportedFeatures.chunking,s=a&&l.chunking.concurrent.enabled,n=function(){var e={};return e[l.preventRetryParam]=!0,e}(),p.initHandler()},qq.WindowReceiveMessage=function(e){"use strict";var t={log:function(e,t){}},n={};qq.extend(t,e),qq.extend(this,{receiveMessage:function(e,t){var i=function(e){t(e.data)};window.postMessage?n[e]=qq(window).attach("message",i):log("iframe message passing not supported in this browser!","error")},stopReceivingMessages:function(e){if(window.postMessage){var t=n[e];t&&t()}}})},qq.FormUploadHandler=function(e){"use strict";function t(e){delete c[e],p&&(clearTimeout(d[e]),delete d[e],m.stopReceivingMessages(e));var t=document.getElementById(a._getIframeName(e));t&&(t.setAttribute("src","javascript:false;"),qq(t).remove())}function n(e){return e.split("_")[0]}function i(e){var t=qq.toElement("");return t.setAttribute("id",e),t.style.display="none",document.body.appendChild(t),t}function o(e,t){var i=e.id,o=n(i),r=q(o);u[r]=t,c[o]=qq(e).attach("load",function(){a.getInput(o)&&(f("Received iframe load event for CORS upload request (iframe name "+i+")"),d[i]=setTimeout(function(){var e="No valid message received from loaded iframe for iframe name "+i;f(e,"error"),t({error:e})},1e3))}),m.receiveMessage(i,function(e){f("Received the following window message: '"+e+"'");var t,o=(n(i),a._parseJsonResponse(e)),r=o.uuid;r&&u[r]?(f("Handling response for iframe name "+i),clearTimeout(d[i]),delete d[i],a._detachLoadEvent(i),t=u[r],delete u[r],m.stopReceivingMessages(i),t(o)):r||f("'"+e+"' does not contain a UUID - ignoring.")})}var r=e.options,a=this,s=e.proxy,l=qq.getUniqueId(),u={},c={},d={},p=r.isCors,h=r.inputName,q=s.getUuid,f=s.log,m=new qq.WindowReceiveMessage({log:f});qq.extend(this,new qq.UploadHandler(e)),qq.override(this,function(e){return{add:function(t,n){e.add(t,{input:n}),n.setAttribute("name",h),n.parentNode&&qq(n).remove()},expunge:function(n){t(n),e.expunge(n)},isValid:function(t){return e.isValid(t)&&void 0!==a._getFileState(t).input}}}),qq.extend(this,{getInput:function(e){return a._getFileState(e).input},_attachLoadEvent:function(e,t){var n;p?o(e,t):c[e.id]=qq(e).attach("load",function(){if(f("Received response for "+e.id),e.parentNode){try{if(e.contentDocument&&e.contentDocument.body&&"false"==e.contentDocument.body.innerHTML)return}catch(e){f("Error when attempting to access iframe during handling of upload response ("+e.message+")","error"),n={success:!1}}t(n)}})},_createIframe:function(e){var t=a._getIframeName(e);return i(t)},_detachLoadEvent:function(e){void 0!==c[e]&&(c[e](),delete c[e])},_getIframeName:function(e){return e+"_"+l},_initFormForUpload:function(e){var t=e.method,n=e.endpoint,i=e.params,o=e.paramsInBody,r=e.targetName,a=qq.toElement(""),s=n;return o?qq.obj2Inputs(i,a):s=qq.obj2url(i,n),a.setAttribute("action",s),a.setAttribute("target",r),a.style.display="none",document.body.appendChild(a),a},_parseJsonResponse:function(e){var t={};try{t=qq.parseJson(e)}catch(e){f("Error when attempting to parse iframe upload response ("+e.message+")","error")}return t}})},qq.XhrUploadHandler=function(e){"use strict";function t(e){qq.each(n._getXhrs(e),function(t,i){var o=n._getAjaxRequester(e,t);i.onreadystatechange=null,i.upload.onprogress=null,i.abort(),o&&o.canceled&&o.canceled(e)})}var n=this,i=e.options.namespace,o=e.proxy,r=e.options.chunking,a=e.options.resume,s=r&&e.options.chunking.enabled&&qq.supportedFeatures.chunking,l=a&&e.options.resume.enabled&&s&&qq.supportedFeatures.resume,u=o.getName,c=o.getSize,d=o.getUuid,p=o.getEndpoint,h=o.getDataByUuid,q=o.onUuidChanged,f=o.onProgress,m=o.log;qq.extend(this,new qq.UploadHandler(e)),qq.override(this,function(e){return{add:function(t,i){if(qq.isFile(i)||qq.isBlob(i))e.add(t,{file:i});else{if(!(i instanceof qq.BlobProxy))throw new Error("Passed obj is not a File, Blob, or proxy");e.add(t,{proxy:i})}n._initTempState(t),l&&n._maybePrepareForResume(t)},expunge:function(i){t(i),n._maybeDeletePersistedChunkData(i),n._clearXhrs(i),e.expunge(i)}}}),qq.extend(this,{clearCachedChunk:function(e,t){delete n._getFileState(e).temp.cachedChunks[t]},clearXhr:function(e,t){var i=n._getFileState(e).temp;i.xhrs&&delete i.xhrs[t],i.ajaxRequesters&&delete i.ajaxRequesters[t]},finalizeChunks:function(e,t){var i=n._getTotalChunks(e)-1,o=n._getXhr(e,i);return t?(new qq.Promise).success(t(o),o):(new qq.Promise).success({},o)},getFile:function(e){return n.isValid(e)&&n._getFileState(e).file},getProxy:function(e){return n.isValid(e)&&n._getFileState(e).proxy},getResumableFilesData:function(){var e=[];return n._iterateResumeRecords(function(t,i){n.moveInProgressToRemaining(null,i.chunking.inProgress,i.chunking.remaining);var o={name:i.name,remaining:i.chunking.remaining,size:i.size,uuid:i.uuid};i.key&&(o.key=i.key),e.push(o)}),e},isResumable:function(e){return!!r&&n.isValid(e)&&!n._getFileState(e).notResumable},moveInProgressToRemaining:function(e,t,i){var o=t||n._getFileState(e).chunking.inProgress,r=i||n._getFileState(e).chunking.remaining;o&&(m(qq.format("Moving these chunks from in-progress {}, to remaining.",JSON.stringify(o))),o.reverse(),qq.each(o,function(e,t){r.unshift(t)}),o.length=0)},pause:function(e){if(n.isValid(e))return m(qq.format("Aborting XHR upload for {} '{}' due to pause instruction.",e,u(e))),n._getFileState(e).paused=!0,t(e),!0},reevaluateChunking:function(e){if(r&&n.isValid(e)){var t,i,o=n._getFileState(e);if(delete o.chunking,o.chunking={},t=n._getTotalChunks(e),t>1||r.mandatory){for(o.chunking.enabled=!0,o.chunking.parts=t,o.chunking.remaining=[],i=0;i=o?o:s+i,u=n._getTotalChunks(e),d=this._getFileState(e).temp.cachedChunks,p=d[t]||qq.sliceBlob(a,s,l);return d[t]=p,{part:t,start:s,end:l,count:u,blob:p,size:l-s}},_getChunkDataForCallback:function(e){return{partIndex:e.part,startByte:e.start+1,endByte:e.end,totalParts:e.count}},_getLocalStorageId:function(e){var t="5.0",n=u(e),o=c(e),a=r.partSize,s=p(e);return qq.format("qq{}resume{}-{}-{}-{}-{}",i,t,n,o,a,s)},_getMimeType:function(e){return n.getFile(e).type},_getPersistableData:function(e){return n._getFileState(e).chunking},_getTotalChunks:function(e){if(r){var t=c(e),n=r.partSize;return Math.ceil(t/n)}},_getXhr:function(e,t){var i=null==t?-1:t;return n._getFileState(e).temp.xhrs[i]},_getXhrs:function(e){return n._getFileState(e).temp.xhrs},_iterateResumeRecords:function(e){l&&qq.each(localStorage,function(t,n){if(0===t.indexOf(qq.format("qq{}resume",i))){var o=JSON.parse(n);e(t,o)}})},_initTempState:function(e){n._getFileState(e).temp={ajaxRequesters:{},chunkProgress:{},xhrs:{},cachedChunks:{}}},_markNotResumable:function(e){n._getFileState(e).notResumable=!0},_maybeDeletePersistedChunkData:function(e){var t;return!!(l&&n.isResumable(e)&&(t=n._getLocalStorageId(e),t&&localStorage.getItem(t)))&&(localStorage.removeItem(t),!0)},_maybePrepareForResume:function(e){var t,i,o=n._getFileState(e);l&&void 0===o.key&&(t=n._getLocalStorageId(e),i=localStorage.getItem(t),i&&(i=JSON.parse(i),h(i.uuid)?n._markNotResumable(e):(m(qq.format("Identified file with ID {} and name of {} as resumable.",e,u(e))),q(e,i.uuid),o.key=i.key,o.chunking=i.chunking,o.loaded=i.loaded,o.attemptingResume=!0,n.moveInProgressToRemaining(e))))},_maybePersistChunkedState:function(e){var t,i,o=n._getFileState(e);if(l&&n.isResumable(e)){t=n._getLocalStorageId(e),i={name:u(e),size:c(e),uuid:d(e),key:o.key,chunking:o.chunking,loaded:o.loaded,lastUpdated:Date.now()};try{localStorage.setItem(t,JSON.stringify(i))}catch(t){m(qq.format("Unable to save resume data for '{}' due to error: '{}'.",e,t.toString()),"warn")}}},_registerProgressHandler:function(e,t,i){var o=n._getXhr(e,t),r=u(e),a={simple:function(t,n){var i=c(e);t===n?f(e,r,i,i):f(e,r,t>=i?i-1:t,i)},chunked:function(o,a){var s=n._getFileState(e).temp.chunkProgress,l=n._getFileState(e).loaded,u=o,d=a,p=c(e),h=u-(d-i),q=l;s[t]=h,qq.each(s,function(e,t){q+=t}),f(e,r,q,p)}};o.upload.onprogress=function(e){if(e.lengthComputable){var t=null==i?"simple":"chunked";a[t](e.loaded,e.total)}}},_registerXhr:function(e,t,i,o){var r=null==t?-1:t,a=n._getFileState(e).temp;return a.xhrs=a.xhrs||{},a.ajaxRequesters=a.ajaxRequesters||{},a.xhrs[r]=i,o&&(a.ajaxRequesters[r]=o),i},_removeExpiredChunkingRecords:function(){var e=a.recordsExpireIn;n._iterateResumeRecords(function(t,n){var i=new Date(n.lastUpdated);i.setDate(i.getDate()+e),i.getTime()<=Date.now()&&(m("Removing expired resume record with key "+t),localStorage.removeItem(t))})},_shouldChunkThisFile:function(e){var t=n._getFileState(e);return t.chunking||n.reevaluateChunking(e),t.chunking.enabled}})},qq.DeleteFileAjaxRequester=function(e){"use strict";function t(){return"POST"===i.method.toUpperCase()?{_method:"DELETE"}:{}}var n,i={method:"DELETE",uuidParamName:"qquuid",endpointStore:{},maxConnections:3,customHeaders:function(e){return{}},paramsStore:{},cors:{expected:!1,sendCredentials:!1},log:function(e,t){},onDelete:function(e){},onDeleteComplete:function(e,t,n){}};qq.extend(i,e),n=qq.extend(this,new qq.AjaxRequester({acceptHeader:"application/json",validMethods:["POST","DELETE"],method:i.method,endpointStore:i.endpointStore,paramsStore:i.paramsStore,mandatedParams:t(),maxConnections:i.maxConnections,customHeaders:function(e){return i.customHeaders.get(e)},log:i.log,onSend:i.onDelete,onComplete:i.onDeleteComplete,cors:i.cors})),qq.extend(this,{sendDelete:function(e,t,o){var r=o||{};i.log("Submitting delete file request for "+e),"DELETE"===i.method?n.initTransport(e).withPath(t).withParams(r).send():(r[i.uuidParamName]=t,n.initTransport(e).withParams(r).send())}})},function(){function e(e){var t,n=e.naturalWidth,i=e.naturalHeight,o=document.createElement("canvas");return n*i>1048576&&(o.width=o.height=1,t=o.getContext("2d"),t.drawImage(e,-n+1,0),0===t.getImageData(0,0,1,1).data[3])}function t(e,t,n){var i,o,r,a,s=document.createElement("canvas"),l=0,u=n,c=n;for(s.width=1,s.height=n,i=s.getContext("2d"),i.drawImage(e,0,0),o=i.getImageData(0,0,1,n).data;c>l;)r=o[4*(c-1)+3],0===r?u=c:l=c,c=u+l>>1;return a=c/n,0===a?1:a}function n(e,t,n,i){var r=document.createElement("canvas"),a=n.mime||"image/jpeg",s=new qq.Promise;return o(e,t,r,n,i).then(function(){s.success(r.toDataURL(a,n.quality||.8))}),s}function i(e){var t=5241e3;if(!qq.ios())throw new qq.Error("Downsampled dimensions can only be reliably calculated for iOS!");if(e.origHeight*e.origWidth>t)return{newHeight:Math.round(Math.sqrt(t*(e.origHeight/e.origWidth))),newWidth:Math.round(Math.sqrt(t*(e.origWidth/e.origHeight)))}}function o(n,o,s,l,u){var c,d=n.naturalWidth,p=n.naturalHeight,h=l.width,q=l.height,f=s.getContext("2d"),m=new qq.Promise;return f.save(),l.resize?r({blob:o,canvas:s,image:n,imageHeight:p,imageWidth:d,orientation:l.orientation,resize:l.resize,targetHeight:q,targetWidth:h}):(qq.supportedFeatures.unlimitedScaledImageSize||(c=i({origWidth:h,origHeight:q}),c&&(qq.log(qq.format("Had to reduce dimensions due to device limitations from {}w / {}h to {}w / {}h",h,q,c.newWidth,c.newHeight),"warn"),h=c.newWidth,q=c.newHeight)),a(s,h,q,l.orientation),qq.ios()?!function(){e(n)&&(d/=2,p/=2);var i,o,r,a=1024,s=document.createElement("canvas"),l=u?t(n,d,p):1,c=Math.ceil(a*h/d),m=Math.ceil(a*q/p/l),g=0,_=0;for(s.width=s.height=a,i=s.getContext("2d");gc&&(l=c,u=s*l/a<<0),d&&u>d&&(u=d,l=a*u/s<<0),i={width:l,height:u},qq.each(t,function(e,t){i[e]=t}),"img"===h?!function(){var t=e.src;n(r.srcImage,r.blob,i,p).then(function(n){e.src=n,t===e.src&&e.onload()})}():"canvas"===h&&o(this.srcImage,this.blob,e,i,p),void("function"==typeof this.onrender&&this.onrender(e)))},qq.MegaPixImage=s}(),qq.ImageGenerator=function(e){"use strict";function t(e){return"img"===e.tagName.toLowerCase()}function n(e){return"canvas"===e.tagName.toLowerCase()}function i(){return void 0!==(new Image).crossOrigin}function o(){var e=document.createElement("canvas");return e.getContext&&e.getContext("2d")}function r(e){var t=e.split("/"),n=t[t.length-1].split("?")[0],i=qq.getExtension(n);switch(i=i&&i.toLowerCase()){case"jpeg":case"jpg":return"image/jpeg";case"png":return"image/png";case"bmp":return"image/bmp";case"gif":return"image/gif";case"tiff":case"tif":return"image/tiff"}}function a(e){var t,n,i,o=document.createElement("a");return o.href=e,t=o.protocol,i=o.port,n=o.hostname,t.toLowerCase()!==window.location.protocol.toLowerCase()||(n.toLowerCase()!==window.location.hostname.toLowerCase()||i!==window.location.port&&!qq.ie())}function s(t,n){t.onload=function(){t.onload=null,t.onerror=null,n.success(t)},t.onerror=function(){t.onload=null,t.onerror=null,e("Problem drawing thumbnail!","error"),n.failure(t,"Problem drawing thumbnail!")}}function l(e,t){e.qqImageRendered=function(){t.success(e)}}function u(i,o){var r=t(i)||n(i);return t(i)?s(i,o):n(i)?l(i,o):(o.failure(i),e(qq.format("Element container of type {} is not supported!",i.tagName),"error")),r}function c(t,n,i){var o=new qq.Promise,r=new qq.Identify(t,e),a=i.maxSize,s=null==i.orient||i.orient,l=function(){n.onerror=null,n.onload=null,e("Could not render preview, file may be too large!","error"),o.failure(n,"Browser cannot render image!")};return r.isPreviewable().then(function(r){var c={parse:function(){return(new qq.Promise).success()}},d=s?new qq.Exif(t,e):c,p=new qq.MegaPixImage(t,l);u(n,o)&&d.parse().then(function(e){var t=e&&e.Orientation;p.render(n,{maxWidth:a,maxHeight:a,orientation:t,mime:r,resize:i.customResizeFunction})},function(t){e(qq.format("EXIF data could not be parsed ({}). Assuming orientation = 1.",t)),p.render(n,{maxWidth:a,maxHeight:a,mime:r,resize:i.customResizeFunction})})},function(){e("Not previewable"),o.failure(n,"Not previewable")}),o}function d(e,t,n,i,o){var s=new Image,l=new qq.Promise;u(s,l),a(e)&&(s.crossOrigin="anonymous"),s.src=e,l.then(function(){u(t,n);var a=new qq.MegaPixImage(s);a.render(t,{maxWidth:i,maxHeight:i,mime:r(e),resize:o})},n.failure)}function p(e,t,n,i){u(t,n),qq(t).css({maxWidth:i+"px",maxHeight:i+"px"}),t.src=e}function h(e,r,s){var l=new qq.Promise,c=s.scale,h=c?s.maxSize:null;return c&&t(r)?o()?a(e)&&!i()?p(e,r,l,h):d(e,r,l,h):p(e,r,l,h):n(r)?d(e,r,l,h):u(r,l)&&(r.src=e),l}qq.extend(this,{generate:function(t,n,i){return qq.isString(t)?(e("Attempting to update thumbnail based on server response."),h(t,n,i||{})):(e("Attempting to draw client-side image preview."),c(t,n,i||{}))}}),this._testing={},this._testing.isImg=t,this._testing.isCanvas=n,this._testing.isCrossOrigin=a,this._testing.determineMimeOfFileName=r},qq.Exif=function(e,t){"use strict";function n(e){for(var t=0,n=0;e.length>0;)t+=parseInt(e.substring(0,2),16)*Math.pow(2,n),e=e.substring(2,e.length),n+=8;return t}function i(t,n){var o=t,r=n;return void 0===o&&(o=2,r=new qq.Promise),qq.readBlobToHex(e,o,4).then(function(e){var t,n=/^ffe([0-9])/.exec(e);n?"1"!==n[1]?(t=parseInt(e.slice(4,8),16),i(o+t+2,r)):r.success(o):r.failure("No EXIF header to be found!")}),r}function o(){var t=new qq.Promise;return qq.readBlobToHex(e,0,6).then(function(e){0!==e.indexOf("ffd8")?t.failure("Not a valid JPEG!"):i().then(function(e){t.success(e)},function(e){t.failure(e)})}),t}function r(t){var n=new qq.Promise;return qq.readBlobToHex(e,t+10,2).then(function(e){n.success("4949"===e)}),n}function a(t,i){var o=new qq.Promise;return qq.readBlobToHex(e,t+18,2).then(function(e){return i?o.success(n(e)):void o.success(parseInt(e,16))}),o}function s(t,n){var i=t+20,o=12*n;return qq.readBlobToHex(e,i,o)}function l(e){for(var t=[],n=0;n+24<=e.length;)t.push(e.slice(n,n+24)),n+=24;return t}function u(e,t){var i=16,o=qq.extend([],c),r={};return qq.each(t,function(t,a){var s,l,u,c=a.slice(0,4),p=e?n(c):parseInt(c,16),h=o.indexOf(p);if(h>=0&&(l=d[p].name,u=d[p].bytes,s=a.slice(i,i+2*u),r[l]=e?n(s):parseInt(s,16),o.splice(h,1)),0===o.length)return!1}),r}var c=[274],d={274:{name:"Orientation",bytes:2}};qq.extend(this,{parse:function(){var n=new qq.Promise,i=function(e){t(qq.format("EXIF header parse failed: '{}' ",e)),n.failure(e)};return o().then(function(o){t(qq.format("Moving forward with EXIF header parsing for '{}'",void 0===e.name?"blob":e.name)),r(o).then(function(e){t(qq.format("EXIF Byte order is {} endian",e?"little":"big")),a(o,e).then(function(r){t(qq.format("Found {} APP1 directory entries",r)),s(o,r).then(function(i){var o=l(i),r=u(e,o);t("Successfully parsed some EXIF tags"),n.success(r)},i)},i)},i)},i),n}}),this._testing={},this._testing.parseLittleEndian=n},qq.Identify=function(e,t){"use strict";function n(e,t){var n=!1,i=[].concat(e);return qq.each(i,function(e,i){if(0===t.indexOf(i))return n=!0,!1}),n}qq.extend(this,{isPreviewable:function(){var i=this,o=new qq.Promise,r=!1,a=void 0===e.name?"blob":e.name;return t(qq.format("Attempting to determine if {} can be rendered in this browser",a)),t("First pass: check type attribute of blob object."),this.isPreviewableSync()?(t("Second pass: check for magic bytes in file header."),qq.readBlobToHex(e,0,4).then(function(e){qq.each(i.PREVIEWABLE_MIME_TYPES,function(t,i){if(n(i,e))return("image/tiff"!==t||qq.supportedFeatures.tiffPreviews)&&(r=!0,o.success(t)),!1}),t(qq.format("'{}' is {} able to be rendered in this browser",a,r?"":"NOT")),r||o.failure()},function(){t("Error reading file w/ name '"+a+"'. Not able to be rendered in this browser."),o.failure()})):o.failure(),o},isPreviewableSync:function(){var n=e.type,i=qq.indexOf(Object.keys(this.PREVIEWABLE_MIME_TYPES),n)>=0,o=!1,r=void 0===e.name?"blob":e.name;return i&&(o="image/tiff"!==n||qq.supportedFeatures.tiffPreviews),!o&&t(r+" is not previewable in this browser per the blob's type attr"),o}})},qq.Identify.prototype.PREVIEWABLE_MIME_TYPES={"image/jpeg":"ffd8ff","image/gif":"474946","image/png":"89504e","image/bmp":"424d","image/tiff":["49492a00","4d4d002a"]},qq.ImageValidation=function(e,t){"use strict";function n(e){var t=!1;return qq.each(e,function(e,n){if(n>0)return t=!0,!1}),t}function i(){var n=new qq.Promise;return new qq.Identify(e,t).isPreviewable().then(function(){var i=new Image,o=window.URL&&window.URL.createObjectURL?window.URL:window.webkitURL&&window.webkitURL.createObjectURL?window.webkitURL:null;o?(i.onerror=function(){t("Cannot determine dimensions for image. May be too large.","error"),n.failure()},i.onload=function(){n.success({width:this.width,height:this.height})},i.src=o.createObjectURL(e)):(t("No createObjectURL function available to generate image URL!","error"),n.failure())},n.failure),n}function o(e,t){var n;return qq.each(e,function(e,i){if(i>0){var o=/(max|min)(Width|Height)/.exec(e),r=o[2].charAt(0).toLowerCase()+o[2].slice(1),a=t[r];switch(o[1]){case"min":if(ai)return n=e,!1}}}),n}this.validate=function(e){var r=new qq.Promise;return t("Attempting to validate image."),n(e)?i().then(function(t){var n=o(e,t);n?r.failure(n):r.success()},r.success):r.success(),r}},qq.Session=function(e){"use strict";function t(e){return!!qq.isArray(e)||void i.log("Session response is not an array.","error")}function n(e,n,o,r){var a=!1;n=n&&t(e),n&&qq.each(e,function(e,t){if(null==t.uuid)a=!0,i.log(qq.format("Session response item {} did not include a valid UUID - ignoring.",e),"error");else if(null==t.name)a=!0,i.log(qq.format("Session response item {} did not include a valid name - ignoring.",e),"error");else try{return i.addFileRecord(t),!0}catch(e){a=!0,i.log(e.message,"error")}return!1}),r[n&&!a?"success":"failure"](e,o)}var i={endpoint:null,params:{},customHeaders:{},cors:{},addFileRecord:function(e){},log:function(e,t){}};qq.extend(i,e,!0),this.refresh=function(){var e=new qq.Promise,t=function(t,i,o){n(t,i,o,e)},o=qq.extend({},i),r=new qq.SessionAjaxRequester(qq.extend(o,{onComplete:t}));return r.queryServer(),e}},qq.SessionAjaxRequester=function(e){"use strict";function t(e,t,n){var o=null;if(null!=t.responseText)try{o=qq.parseJson(t.responseText)}catch(e){i.log("Problem parsing session response: "+e.message,"error"),n=!0}i.onComplete(o,!n,t)}var n,i={endpoint:null,customHeaders:{},params:{},cors:{expected:!1,sendCredentials:!1},onComplete:function(e,t,n){},log:function(e,t){}};qq.extend(i,e),n=qq.extend(this,new qq.AjaxRequester({acceptHeader:"application/json",validMethods:["GET"],method:"GET",endpointStore:{get:function(){return i.endpoint}},customHeaders:i.customHeaders,log:i.log,onComplete:t,cors:i.cors})),qq.extend(this,{queryServer:function(){var e=qq.extend({},i.params);i.log("Session query request."),n.initTransport("sessionRefresh").withParams(e).withCacheBuster().send()}})},qq.Scaler=function(e,t){"use strict";var n=e.customResizer,i=e.sendOriginal,o=e.orient,r=e.defaultType,a=e.defaultQuality/100,s=e.failureText,l=e.includeExif,u=this._getSortedSizes(e.sizes);qq.extend(this,{enabled:qq.supportedFeatures.scaling&&u.length>0,getFileRecords:function(e,c,d){var p=this,h=[],q=d.blob?d.blob:d,f=new qq.Identify(q,t);return f.isPreviewableSync()?(qq.each(u,function(e,i){var u=p._determineOutputType({defaultType:r,requestedType:i.type,refType:q.type});h.push({uuid:qq.getUniqueId(),name:p._getName(c,{name:i.name,type:u,refType:q.type}),blob:new qq.BlobProxy(q,qq.bind(p._generateScaledImage,p,{customResizeFunction:n,maxSize:i.maxSize,orient:o,type:u,quality:a,failedText:s,includeExif:l,log:t}))})}),h.push({uuid:e,name:c,size:q.size,blob:i?q:null})):h.push({uuid:e,name:c,size:q.size,blob:q}),h},handleNewFile:function(e,t,n,i,o,r,a,s){var l=this,u=(e.qqButtonId||e.blob&&e.blob.qqButtonId,[]),c=null,d=s.addFileToHandler,p=s.uploadData,h=s.paramsStore,q=qq.getUniqueId();qq.each(l.getFileRecords(n,t,e),function(e,t){var n,i=t.size;t.blob instanceof qq.BlobProxy&&(i=-1),n=p.addFile({uuid:t.uuid,name:t.name,size:i,batchId:r,proxyGroupId:q}),t.blob instanceof qq.BlobProxy?u.push(n):c=n,t.blob?(d(n,t.blob),o.push({id:n,file:t.blob})):p.setStatus(n,qq.status.REJECTED)}),null!==c&&(qq.each(u,function(e,t){var n={qqparentuuid:p.retrieve({id:c}).uuid,qqparentsize:p.retrieve({id:c}).size};n[a]=p.retrieve({id:t}).uuid,p.setParentId(t,c),h.addReadOnly(t,n)}),u.length&&!function(){var e={};e[a]=p.retrieve({id:c}).uuid,h.addReadOnly(c,e)}())}})},qq.extend(qq.Scaler.prototype,{scaleImage:function(e,t,n){"use strict";if(!qq.supportedFeatures.scaling)throw new qq.Error("Scaling is not supported in this browser!");var i=new qq.Promise,o=n.log,r=n.getFile(e),a=n.uploadData.retrieve({id:e}),s=a&&a.name,l=a&&a.uuid,u={customResizer:t.customResizer,sendOriginal:!1,orient:t.orient,defaultType:t.type||null,defaultQuality:t.quality,failedToScaleText:"Unable to scale",sizes:[{name:"",maxSize:t.maxSize}]},c=new qq.Scaler(u,o);return qq.Scaler&&qq.supportedFeatures.imagePreviews&&r?qq.bind(function(){var t=c.getFileRecords(l,s,r)[0];t&&t.blob instanceof qq.BlobProxy?t.blob.create().then(i.success,i.failure):(o(e+" is not a scalable image!","error"),i.failure())},this)():(i.failure(),o("Could not generate requested scaled image for "+e+". Scaling is either not possible in this browser, or the file could not be located.","error")),i},_determineOutputType:function(e){"use strict";var t=e.requestedType,n=e.defaultType,i=e.refType;return n||t?t&&qq.indexOf(Object.keys(qq.Identify.prototype.PREVIEWABLE_MIME_TYPES),t)>=0?"image/tiff"===t?qq.supportedFeatures.tiffPreviews?t:n:t:n:"image/jpeg"!==i?"image/png":i},_getName:function(e,t){"use strict";var n=e.lastIndexOf("."),i=t.type||"image/png",o=t.refType,r="",a=qq.getExtension(e),s="";return t.name&&t.name.trim().length&&(s=" ("+t.name+")"),n>=0?(r=e.substr(0,n),o!==i&&(a=i.split("/")[1]),r+=s+"."+a):r=e+s,r},_getSortedSizes:function(e){"use strict";return e=qq.extend([],e),e.sort(function(e,t){return e.maxSize>t.maxSize?1:e.maxSize=0?atob(e.split(",")[1]):decodeURI(e.split(",")[1]),n=e.split(",")[0].split(":")[1].split(";")[0],i=new ArrayBuffer(t.length),o=new Uint8Array(i),qq.each(t,function(e,t){o[e]=t.charCodeAt(0)}),this._createBlob(i,n)},_createBlob:function(e,t){"use strict";var n=window.BlobBuilder||window.WebKitBlobBuilder||window.MozBlobBuilder||window.MSBlobBuilder,i=n&&new n;return i?(i.append(e),i.getBlob(t)):new Blob([e],{type:t})}}),qq.ExifRestorer=function(){var e={};return e.KEY_STR="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",e.encode64=function(e){var t,n,i,o,r,a="",s="",l="",u=0;do t=e[u++],n=e[u++],s=e[u++],i=t>>2,o=(3&t)<<4|n>>4,r=(15&n)<<2|s>>6,l=63&s,isNaN(n)?r=l=64:isNaN(s)&&(l=64),a=a+this.KEY_STR.charAt(i)+this.KEY_STR.charAt(o)+this.KEY_STR.charAt(r)+this.KEY_STR.charAt(l),t=n=s="",i=o=r=l="";while(ue.length)break}return n},e.decode64=function(e){var t,n,i,o,r,a="",s="",l=0,u=[],c=/[^A-Za-z0-9\+\/\=]/g;if(c.exec(e))throw new Error("There were invalid base64 characters in the input text. Valid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='");e=e.replace(/[^A-Za-z0-9\+\/\=]/g,"");do i=this.KEY_STR.indexOf(e.charAt(l++)),o=this.KEY_STR.indexOf(e.charAt(l++)),r=this.KEY_STR.indexOf(e.charAt(l++)),s=this.KEY_STR.indexOf(e.charAt(l++)),t=i<<2|o>>4,n=(15&o)<<4|r>>2,a=(3&r)<<6|s,u.push(t),64!=r&&u.push(n),64!=s&&u.push(a),t=n=a="",i=o=r=s="";while(l=0)return n=!1,!1}),n},u=function(e){p(e,-1,-1),delete n[e]},c=function(e,t,n){(0===t.length||l(t,n))&&(s(o,o),this.reset())},d=function(e){var i=t(e);i>0&&(p(e,0,i),n[e]={loaded:0,total:i})},p=function(e,t,r){var a=n[e]?n[e].loaded:0,l=n[e]?n[e].total:0;t===-1&&r===-1?(i-=a,o-=l):(t&&(i+=t-a),r&&(o+=r-l)),s(i,o)};qq.extend(this,{onAllComplete:c,onStatusChange:function(e,t,n){n===qq.status.CANCELED||n===qq.status.REJECTED?u(e):n===qq.status.SUBMITTING&&d(e)},onIndividualProgress:function(e,t,i){p(e,t,i),n[e]={loaded:t,total:i}},onNewSize:function(e){d(e)},reset:function(){n={},i=0,o=0}})},qq.PasteSupport=function(e){"use strict";function t(e){return e.type&&0===e.type.indexOf("image/")}function n(){r=qq(o.targetElement).attach("paste",function(e){var n=e.clipboardData;n&&qq.each(n.items,function(e,n){if(t(n)){var i=n.getAsFile();o.callbacks.pasteReceived(i)}})})}function i(){r&&r()}var o,r;o={targetElement:null,callbacks:{log:function(e,t){},pasteReceived:function(e){}}},qq.extend(o,e),n(),qq.extend(this,{reset:function(){i()}})},qq.FormSupport=function(e,t,n){"use strict";function i(e){e.getAttribute("action")&&(s.newEndpoint=e.getAttribute("action"))}function o(e,t){return!(e.checkValidity&&!e.checkValidity())||(n("Form did not pass validation checks - will not upload.","error"),void t())}function r(e){var n=e.submit;
-qq(e).attach("submit",function(i){i=i||window.event,i.preventDefault?i.preventDefault():i.returnValue=!1,o(e,n)&&t()}),e.submit=function(){o(e,n)&&t()}}function a(e){return e&&(qq.isString(e)&&(e=document.getElementById(e)),e&&(n("Attaching to form element."),i(e),l&&r(e))),e}var s=this,l=e.interceptSubmit,u=e.element,c=e.autoUpload;qq.extend(this,{newEndpoint:null,newAutoUpload:c,attachedToForm:!1,getFormInputsAsObject:function(){return null==u?null:s._form2Obj(u)}}),u=a(u),this.attachedToForm=!!u},qq.extend(qq.FormSupport.prototype,{_form2Obj:function(e){"use strict";var t={},n=function(e){var t=["button","image","reset","submit"];return qq.indexOf(t,e.toLowerCase())<0},i=function(e){return qq.indexOf(["checkbox","radio"],e.toLowerCase())>=0},o=function(e){return!(!i(e.type)||e.checked)||e.disabled&&"hidden"!==e.type.toLowerCase()},r=function(e){var t=null;return qq.each(qq(e).children(),function(e,n){if("option"===n.tagName.toLowerCase()&&n.selected)return t=n.value,!1}),t};return qq.each(e.elements,function(e,i){if(!qq.isInput(i,!0)&&"textarea"!==i.tagName.toLowerCase()||!n(i.type)||o(i)){if("select"===i.tagName.toLowerCase()&&!o(i)){var a=r(i);null!==a&&(t[i.name]=a)}}else t[i.name]=i.value}),t}}),qq.traditional=qq.traditional||{},qq.traditional.FormUploadHandler=function(e,t){"use strict";function n(e,t){var n,i,r;try{i=t.contentDocument||t.contentWindow.document,r=i.body.innerHTML,s("converting iframe's innerHTML to JSON"),s("innerHTML = "+r),r&&r.match(/^1&&!u.allowMultipleItems?(u.callbacks.processingDroppedFilesComplete([]),u.callbacks.dropError("tooManyFilesError",""),t.dropDisabled(!1),o.failure()):(h=[],qq.isFolderDropSupported(e)?qq.each(e.items,function(e,t){var r=t.webkitGetAsEntry();r&&(r.isFile?h.push(t.getAsFile()):i.push(n(r).done(function(){i.pop(),0===i.length&&o.success()})))}):h=e.files,0===i.length&&o.success()),o}function r(e){var n=new qq.UploadDropZone({HIDE_ZONES_EVENT_NAME:c,element:e,onEnter:function(t){qq(e).addClass(u.classes.dropActive),t.stopPropagation()},onLeaveNotDescendants:function(t){qq(e).removeClass(u.classes.dropActive)},onDrop:function(e){o(e.dataTransfer,n).then(function(){t(h,n)},function(){u.callbacks.dropLog("Drop event DataTransfer parsing failed. No files will be uploaded.","error")})}});return q.addDisposer(function(){n.dispose()}),qq(e).hasAttribute(d)&&qq(e).hide(),p.push(n),n}function a(e){var t;return qq.each(e.dataTransfer.types,function(e,n){if("Files"===n)return t=!0,!1}),t}function s(e){return qq.firefox()?!e.relatedTarget:qq.safari()?e.x<0||e.y<0:0===e.x&&0===e.y}function l(){var e=u.dropZoneElements,t=function(){setTimeout(function(){qq.each(e,function(e,t){qq(t).hasAttribute(d)&&qq(t).hide(),qq(t).removeClass(u.classes.dropActive)})},10)};qq.each(e,function(t,n){var i=r(n);e.length&&qq.supportedFeatures.fileDrop&&q.attach(document,"dragenter",function(t){!i.dropDisabled()&&a(t)&&qq.each(e,function(e,t){t instanceof HTMLElement&&qq(t).hasAttribute(d)&&qq(t).css({display:"block"})})})}),q.attach(document,"dragleave",function(e){s(e)&&t()}),q.attach(qq(document).children()[0],"mouseenter",function(e){t()}),q.attach(document,"drop",function(e){e.preventDefault(),t()}),q.attach(document,c,t)}var u,c="qq-hidezones",d="qq-hide-dropzone",p=[],h=[],q=new qq.DisposeSupport;u={dropZoneElements:[],allowMultipleItems:!0,classes:{dropActive:null},callbacks:new qq.DragAndDrop.callbacks},qq.extend(u,e,!0),l(),qq.extend(this,{setupExtraDropzone:function(e){u.dropZoneElements.push(e),r(e)},removeDropzone:function(e){var t,n=u.dropZoneElements;for(t in n)if(n[t]===e)return n.splice(t,1)},dispose:function(){q.dispose(),qq.each(p,function(e,t){t.dispose()})}})},qq.DragAndDrop.callbacks=function(){"use strict";return{processingDroppedFiles:function(){},processingDroppedFilesComplete:function(e,t){},dropError:function(e,t){qq.log("Drag & drop error code '"+e+" with these specifics: '"+t+"'","error")},dropLog:function(e,t){qq.log(e,t)}}},qq.UploadDropZone=function(e){"use strict";function t(){return qq.safari()||qq.firefox()&&qq.windows()}function n(e){c||(t?d.attach(document,"dragover",function(e){e.preventDefault()}):d.attach(document,"dragover",function(e){e.dataTransfer&&(e.dataTransfer.dropEffect="none",e.preventDefault())}),c=!0)}function i(e){if(!qq.supportedFeatures.fileDrop)return!1;var t,n=e.dataTransfer,i=qq.safari();return t=!(!qq.ie()||!qq.supportedFeatures.fileDrop)||"none"!==n.effectAllowed,n&&t&&(n.files||!i&&n.types.contains&&n.types.contains("Files"))}function o(e){return void 0!==e&&(u=e),u}function r(){function e(){t=document.createEvent("Event"),t.initEvent(s.HIDE_ZONES_EVENT_NAME,!0,!0)}var t;if(window.CustomEvent)try{t=new CustomEvent(s.HIDE_ZONES_EVENT_NAME)}catch(t){e()}else e();document.dispatchEvent(t)}function a(){d.attach(l,"dragover",function(e){if(i(e)){var t=qq.ie()&&qq.supportedFeatures.fileDrop?null:e.dataTransfer.effectAllowed;"move"===t||"linkMove"===t?e.dataTransfer.dropEffect="move":e.dataTransfer.dropEffect="copy",e.stopPropagation(),e.preventDefault()}}),d.attach(l,"dragenter",function(e){if(!o()){if(!i(e))return;s.onEnter(e)}}),d.attach(l,"dragleave",function(e){if(i(e)){s.onLeave(e);var t=document.elementFromPoint(e.clientX,e.clientY);qq(this).contains(t)||s.onLeaveNotDescendants(e)}}),d.attach(l,"drop",function(e){if(!o()){if(!i(e))return;e.preventDefault(),e.stopPropagation(),s.onDrop(e),r()}})}var s,l,u,c,d=new qq.DisposeSupport;s={element:null,onEnter:function(e){},onLeave:function(e){},onLeaveNotDescendants:function(e){},onDrop:function(e){}},qq.extend(s,e),l=s.element,n(),a(),qq.extend(this,{dropDisabled:function(e){return o(e)},dispose:function(){d.dispose()},getElement:function(){return l}})},function(){"use strict";qq.uiPublicApi={addInitialFiles:function(e){this._parent.prototype.addInitialFiles.apply(this,arguments),this._templating.addCacheToDom()},clearStoredFiles:function(){this._parent.prototype.clearStoredFiles.apply(this,arguments),this._templating.clearFiles()},addExtraDropzone:function(e){this._dnd&&this._dnd.setupExtraDropzone(e)},removeExtraDropzone:function(e){if(this._dnd)return this._dnd.removeDropzone(e)},getItemByFileId:function(e){if(!this._templating.isHiddenForever(e))return this._templating.getFileContainer(e)},reset:function(){this._parent.prototype.reset.apply(this,arguments),this._templating.reset(),!this._options.button&&this._templating.getButton()&&(this._defaultButtonId=this._createUploadButton({element:this._templating.getButton(),title:this._options.text.fileInputTitle}).getButtonId()),this._dnd&&(this._dnd.dispose(),this._dnd=this._setupDragAndDrop()),this._totalFilesInBatch=0,this._filesInBatchAddedToUi=0,this._setupClickAndEditEventHandlers()},setName:function(e,t){var n=this._options.formatFileName(t);this._parent.prototype.setName.apply(this,arguments),this._templating.updateFilename(e,n)},pauseUpload:function(e){var t=this._parent.prototype.pauseUpload.apply(this,arguments);return t&&this._templating.uploadPaused(e),t},continueUpload:function(e){var t=this._parent.prototype.continueUpload.apply(this,arguments);return t&&this._templating.uploadContinued(e),t},getId:function(e){return this._templating.getFileId(e)},getDropTarget:function(e){var t=this.getFile(e);return t.qqDropTarget}},qq.uiPrivateApi={_getButton:function(e){var t=this._parent.prototype._getButton.apply(this,arguments);return t||e===this._defaultButtonId&&(t=this._templating.getButton()),t},_removeFileItem:function(e){this._templating.removeFile(e)},_setupClickAndEditEventHandlers:function(){this._fileButtonsClickHandler=qq.FileButtonsClickHandler&&this._bindFileButtonsClickEvent(),this._focusinEventSupported=!qq.firefox(),this._isEditFilenameEnabled()&&(this._filenameClickHandler=this._bindFilenameClickEvent(),this._filenameInputFocusInHandler=this._bindFilenameInputFocusInEvent(),this._filenameInputFocusHandler=this._bindFilenameInputFocusEvent())},_setupDragAndDrop:function(){var e=this,t=this._options.dragAndDrop.extraDropzones,n=this._templating,i=n.getDropZone();return i&&t.push(i),new qq.DragAndDrop({dropZoneElements:t,allowMultipleItems:this._options.multiple,classes:{dropActive:this._options.classes.dropActive},callbacks:{processingDroppedFiles:function(){n.showDropProcessing()},processingDroppedFilesComplete:function(t,i){n.hideDropProcessing(),qq.each(t,function(e,t){t.qqDropTarget=i}),t.length&&e.addFiles(t,null,null)},dropError:function(t,n){e._itemError(t,n)},dropLog:function(t,n){e.log(t,n)}}})},_bindFileButtonsClickEvent:function(){var e=this;return new qq.FileButtonsClickHandler({templating:this._templating,log:function(t,n){e.log(t,n)},onDeleteFile:function(t){e.deleteFile(t)},onCancel:function(t){e.cancel(t)},onRetry:function(t){e.retry(t)},onPause:function(t){e.pauseUpload(t)},onContinue:function(t){e.continueUpload(t)},onGetName:function(t){return e.getName(t)}})},_isEditFilenameEnabled:function(){return this._templating.isEditFilenamePossible()&&!this._options.autoUpload&&qq.FilenameClickHandler&&qq.FilenameInputFocusHandler&&qq.FilenameInputFocusHandler},_filenameEditHandler:function(){var e=this,t=this._templating;return{templating:t,log:function(t,n){e.log(t,n)},onGetUploadStatus:function(t){return e.getUploads({id:t}).status},onGetName:function(t){return e.getName(t)},onSetName:function(t,n){e.setName(t,n)},onEditingStatusChange:function(e,n){var i=qq(t.getEditInput(e)),o=qq(t.getFileContainer(e));n?(i.addClass("qq-editing"),t.hideFilename(e),t.hideEditIcon(e)):(i.removeClass("qq-editing"),t.showFilename(e),t.showEditIcon(e)),o.addClass("qq-temp").removeClass("qq-temp")}}},_onUploadStatusChange:function(e,t,n){this._parent.prototype._onUploadStatusChange.apply(this,arguments),this._isEditFilenameEnabled()&&this._templating.getFileContainer(e)&&n!==qq.status.SUBMITTED&&(this._templating.markFilenameEditable(e),this._templating.hideEditIcon(e)),t===qq.status.UPLOAD_RETRYING&&n===qq.status.UPLOADING?(this._templating.hideRetry(e),this._templating.setStatusText(e),qq(this._templating.getFileContainer(e)).removeClass(this._classes.retrying)):n===qq.status.UPLOAD_FAILED&&this._templating.hidePause(e)},_bindFilenameInputFocusInEvent:function(){var e=qq.extend({},this._filenameEditHandler());return new qq.FilenameInputFocusInHandler(e)},_bindFilenameInputFocusEvent:function(){var e=qq.extend({},this._filenameEditHandler());return new qq.FilenameInputFocusHandler(e)},_bindFilenameClickEvent:function(){var e=qq.extend({},this._filenameEditHandler());return new qq.FilenameClickHandler(e)},_storeForLater:function(e){this._parent.prototype._storeForLater.apply(this,arguments),this._templating.hideSpinner(e)},_onAllComplete:function(e,t){this._parent.prototype._onAllComplete.apply(this,arguments),this._templating.resetTotalProgress()},_onSubmit:function(e,t){var n=this.getFile(e);n&&n.qqPath&&this._options.dragAndDrop.reportDirectoryPaths&&this._paramsStore.addReadOnly(e,{qqpath:n.qqPath}),this._parent.prototype._onSubmit.apply(this,arguments),this._addToList(e,t)},_onSubmitted:function(e){this._isEditFilenameEnabled()&&(this._templating.markFilenameEditable(e),this._templating.showEditIcon(e),this._focusinEventSupported||this._filenameInputFocusHandler.addHandler(this._templating.getEditInput(e)))},_onProgress:function(e,t,n,i){this._parent.prototype._onProgress.apply(this,arguments),this._templating.updateProgress(e,n,i),0===i||100===Math.round(n/i*100)?(this._templating.hideCancel(e),this._templating.hidePause(e),this._templating.hideProgress(e),this._templating.setStatusText(e,this._options.text.waitingForResponse),this._displayFileSize(e)):this._displayFileSize(e,n,i)},_onTotalProgress:function(e,t){this._parent.prototype._onTotalProgress.apply(this,arguments),this._templating.updateTotalProgress(e,t)},_onComplete:function(e,t,n,i){function o(t){s&&(a.setStatusText(e),qq(s).removeClass(l._classes.retrying),a.hideProgress(e),l.getUploads({id:e}).status!==qq.status.UPLOAD_FAILED&&a.hideCancel(e),a.hideSpinner(e),t.success?l._markFileAsSuccessful(e):(qq(s).addClass(l._classes.fail),a.showCancel(e),a.isRetryPossible()&&!l._preventRetries[e]&&(qq(s).addClass(l._classes.retryable),a.showRetry(e)),l._controlFailureTextDisplay(e,t)))}var r=this._parent.prototype._onComplete.apply(this,arguments),a=this._templating,s=a.getFileContainer(e),l=this;return r instanceof qq.Promise?r.done(function(e){o(e)}):o(n),r},_markFileAsSuccessful:function(e){var t=this._templating;this._isDeletePossible()&&t.showDeleteButton(e),qq(t.getFileContainer(e)).addClass(this._classes.success),this._maybeUpdateThumbnail(e)},_onUploadPrep:function(e){this._parent.prototype._onUploadPrep.apply(this,arguments),this._templating.showSpinner(e)},_onUpload:function(e,t){var n=this._parent.prototype._onUpload.apply(this,arguments);return this._templating.showSpinner(e),n},_onUploadChunk:function(e,t){this._parent.prototype._onUploadChunk.apply(this,arguments),t.partIndex>0&&this._handler.isResumable(e)&&this._templating.allowPause(e)},_onCancel:function(e,t){this._parent.prototype._onCancel.apply(this,arguments),this._removeFileItem(e),0===this._getNotFinished()&&this._templating.resetTotalProgress()},_onBeforeAutoRetry:function(e){var t,n,i;this._parent.prototype._onBeforeAutoRetry.apply(this,arguments),this._showCancelLink(e),this._options.retry.showAutoRetryNote&&(t=this._autoRetries[e],n=this._options.retry.maxAutoAttempts,i=this._options.retry.autoRetryNote.replace(/\{retryNum\}/g,t),i=i.replace(/\{maxAuto\}/g,n),this._templating.setStatusText(e,i),qq(this._templating.getFileContainer(e)).addClass(this._classes.retrying))},_onBeforeManualRetry:function(e){return this._parent.prototype._onBeforeManualRetry.apply(this,arguments)?(this._templating.resetProgress(e),qq(this._templating.getFileContainer(e)).removeClass(this._classes.fail),this._templating.setStatusText(e),this._templating.showSpinner(e),this._showCancelLink(e),!0):(qq(this._templating.getFileContainer(e)).addClass(this._classes.retryable),this._templating.showRetry(e),!1)},_onSubmitDelete:function(e){var t=qq.bind(this._onSubmitDeleteSuccess,this);this._parent.prototype._onSubmitDelete.call(this,e,t)},_onSubmitDeleteSuccess:function(e,t,n){this._options.deleteFile.forceConfirm?this._showDeleteConfirm.apply(this,arguments):this._sendDeleteRequest.apply(this,arguments)},_onDeleteComplete:function(e,t,n){this._parent.prototype._onDeleteComplete.apply(this,arguments),this._templating.hideSpinner(e),n?(this._templating.setStatusText(e,this._options.deleteFile.deletingFailedText),this._templating.showDeleteButton(e)):this._removeFileItem(e)},_sendDeleteRequest:function(e,t,n){this._templating.hideDeleteButton(e),this._templating.showSpinner(e),this._templating.setStatusText(e,this._options.deleteFile.deletingStatusText),this._deleteHandler.sendDelete.apply(this,arguments)},_showDeleteConfirm:function(e,t,n){var i,o=this.getName(e),r=this._options.deleteFile.confirmMessage.replace(/\{filename\}/g,o),a=(this.getUuid(e),arguments),s=this;i=this._options.showConfirm(r),qq.isGenericPromise(i)?i.then(function(){s._sendDeleteRequest.apply(s,a)}):i!==!1&&s._sendDeleteRequest.apply(s,a)},_addToList:function(e,t,n){var i,o,r=0,a=this._handler.isProxied(e)&&this._options.scaling.hideScaled;this._options.display.prependFiles&&(this._totalFilesInBatch>1&&this._filesInBatchAddedToUi>0&&(r=this._filesInBatchAddedToUi-1),i={index:r}),n||(this._options.disableCancelForFormUploads&&!qq.supportedFeatures.ajaxUploading&&this._templating.disableCancel(),this._options.multiple||(o=this.getUploads({id:e}),this._handledProxyGroup=this._handledProxyGroup||o.proxyGroupId,o.proxyGroupId===this._handledProxyGroup&&o.proxyGroupId||(this._handler.cancelAll(),this._clearList(),this._handledProxyGroup=null))),n?(this._templating.addFileToCache(e,this._options.formatFileName(t),i,a),this._templating.updateThumbnail(e,this._thumbnailUrls[e],!0,this._options.thumbnails.customResizer)):(this._templating.addFile(e,this._options.formatFileName(t),i,a),this._templating.generatePreview(e,this.getFile(e),this._options.thumbnails.customResizer)),this._filesInBatchAddedToUi+=1,(n||this._options.display.fileSizeOnSubmit&&qq.supportedFeatures.ajaxUploading)&&this._displayFileSize(e)},_clearList:function(){this._templating.clearFiles(),this.clearStoredFiles()},_displayFileSize:function(e,t,n){var i=this.getSize(e),o=this._formatSize(i);i>=0&&(void 0!==t&&void 0!==n&&(o=this._formatProgress(t,n)),this._templating.updateSize(e,o))},_formatProgress:function(e,t){function n(e,t){i=i.replace(e,t)}var i=this._options.text.formatProgress;return n("{percent}",Math.round(e/t*100)),n("{total_size}",this._formatSize(t)),i},_controlFailureTextDisplay:function(e,t){var n,i,o;n=this._options.failedUploadTextDisplay.mode,i=this._options.failedUploadTextDisplay.responseProperty,"custom"===n?(o=t[i],o||(o=this._options.text.failUpload),this._templating.setStatusText(e,o),this._options.failedUploadTextDisplay.enableTooltip&&this._showTooltip(e,o)):"default"===n?this._templating.setStatusText(e,this._options.text.failUpload):"none"!==n&&this.log("failedUploadTextDisplay.mode value of '"+n+"' is not valid","warn")},_showTooltip:function(e,t){this._templating.getFileContainer(e).title=t},_showCancelLink:function(e){this._options.disableCancelForFormUploads&&!qq.supportedFeatures.ajaxUploading||this._templating.showCancel(e)},_itemError:function(e,t,n){var i=this._parent.prototype._itemError.apply(this,arguments);this._options.showMessage(i)},_batchError:function(e){this._parent.prototype._batchError.apply(this,arguments),this._options.showMessage(e)},_setupPastePrompt:function(){var e=this;this._options.callbacks.onPasteReceived=function(){var t=e._options.paste.namePromptMessage,n=e._options.paste.defaultName;return e._options.showPrompt(t,n)}},_fileOrBlobRejected:function(e,t){this._totalFilesInBatch-=1,this._parent.prototype._fileOrBlobRejected.apply(this,arguments)},_prepareItemsForUpload:function(e,t,n){this._totalFilesInBatch=e.length,this._filesInBatchAddedToUi=0,this._parent.prototype._prepareItemsForUpload.apply(this,arguments)},_maybeUpdateThumbnail:function(e){var t=this._thumbnailUrls[e],n=this.getUploads({id:e}).status;n===qq.status.DELETED||!t&&!this._options.thumbnails.placeholders.waitUntilResponse&&qq.supportedFeatures.imagePreviews||this._templating.updateThumbnail(e,t,this._options.thumbnails.customResizer)},_addCannedFile:function(e){var t=this._parent.prototype._addCannedFile.apply(this,arguments);return this._addToList(t,this.getName(t),!0),this._templating.hideSpinner(t),this._templating.hideCancel(t),this._markFileAsSuccessful(t),t},_setSize:function(e,t){this._parent.prototype._setSize.apply(this,arguments),this._templating.updateSize(e,this._formatSize(t))},_sessionRequestComplete:function(){this._templating.addCacheToDom(),this._parent.prototype._sessionRequestComplete.apply(this,arguments)}}}(),qq.FineUploader=function(e,t){"use strict";var n=this;this._parent=t?qq[t].FineUploaderBasic:qq.FineUploaderBasic,this._parent.apply(this,arguments),qq.extend(this._options,{element:null,button:null,listElement:null,dragAndDrop:{extraDropzones:[],reportDirectoryPaths:!1},text:{formatProgress:"{percent}% of {total_size}",failUpload:"Upload failed",waitingForResponse:"Processing...",paused:"Paused"},template:"qq-template",classes:{retrying:"qq-upload-retrying",retryable:"qq-upload-retryable",success:"qq-upload-success",fail:"qq-upload-fail",editable:"qq-editable",hide:"qq-hide",dropActive:"qq-upload-drop-area-active"},failedUploadTextDisplay:{mode:"default",responseProperty:"error",enableTooltip:!0},messages:{tooManyFilesError:"You may only drop one file",unsupportedBrowser:"Unrecoverable error - this browser does not permit file uploading of any kind."},retry:{showAutoRetryNote:!0,autoRetryNote:"Retrying {retryNum}/{maxAuto}..."},deleteFile:{forceConfirm:!1,confirmMessage:"Are you sure you want to delete {filename}?",deletingStatusText:"Deleting...",deletingFailedText:"Delete failed"},display:{fileSizeOnSubmit:!1,prependFiles:!1},paste:{promptForName:!1,namePromptMessage:"Please name this image"},thumbnails:{customResizer:null,maxCount:0,placeholders:{waitUntilResponse:!1,notAvailablePath:null,waitingPath:null},timeBetweenThumbs:750},scaling:{hideScaled:!1},showMessage:function(e){return n._templating.hasDialog("alert")?n._templating.showDialog("alert",e):void setTimeout(function(){window.alert(e)},0)},showConfirm:function(e){return n._templating.hasDialog("confirm")?n._templating.showDialog("confirm",e):window.confirm(e)},showPrompt:function(e,t){return n._templating.hasDialog("prompt")?n._templating.showDialog("prompt",e,t):window.prompt(e,t)}},!0),qq.extend(this._options,e,!0),this._templating=new qq.Templating({log:qq.bind(this.log,this),templateIdOrEl:this._options.template,containerEl:this._options.element,fileContainerEl:this._options.listElement,button:this._options.button,imageGenerator:this._imageGenerator,classes:{hide:this._options.classes.hide,editable:this._options.classes.editable},limits:{maxThumbs:this._options.thumbnails.maxCount,timeBetweenThumbs:this._options.thumbnails.timeBetweenThumbs},placeholders:{waitUntilUpdate:this._options.thumbnails.placeholders.waitUntilResponse,thumbnailNotAvailable:this._options.thumbnails.placeholders.notAvailablePath,waitingForThumbnail:this._options.thumbnails.placeholders.waitingPath},text:this._options.text}),this._options.workarounds.ios8SafariUploads&&qq.ios800()&&qq.iosSafari()?this._templating.renderFailure(this._options.messages.unsupportedBrowserIos8Safari):!qq.supportedFeatures.uploading||this._options.cors.expected&&!qq.supportedFeatures.uploadCors?this._templating.renderFailure(this._options.messages.unsupportedBrowser):(this._wrapCallbacks(),this._templating.render(),this._classes=this._options.classes,!this._options.button&&this._templating.getButton()&&(this._defaultButtonId=this._createUploadButton({element:this._templating.getButton(),title:this._options.text.fileInputTitle}).getButtonId()),this._setupClickAndEditEventHandlers(),qq.DragAndDrop&&qq.supportedFeatures.fileDrop&&(this._dnd=this._setupDragAndDrop()),this._options.paste.targetElement&&this._options.paste.promptForName&&(qq.PasteSupport?this._setupPastePrompt():this.log("Paste support module not found.","error")),this._totalFilesInBatch=0,this._filesInBatchAddedToUi=0)},qq.extend(qq.FineUploader.prototype,qq.basePublicApi),qq.extend(qq.FineUploader.prototype,qq.basePrivateApi),qq.extend(qq.FineUploader.prototype,qq.uiPublicApi),qq.extend(qq.FineUploader.prototype,qq.uiPrivateApi),qq.Templating=function(e){"use strict";var t,n,i,o,r,a,s,l,u="qq-file-id",c="qq-file-id-",d="qq-max-size",p="qq-server-scale",h="qq-hide-dropzone",q="qq-drop-area-text",f="qq-in-progress",m="qq-hidden-forever",g={content:document.createDocumentFragment(),map:{}},_=!1,v=0,b=!1,y=[],S=-1,w={log:null,limits:{maxThumbs:0,timeBetweenThumbs:750},templateIdOrEl:"qq-template",containerEl:null,fileContainerEl:null,button:null,imageGenerator:null,classes:{hide:"qq-hide",editable:"qq-editable"},placeholders:{waitUntilUpdate:!1,thumbnailNotAvailable:null,waitingForThumbnail:null},text:{paused:"Paused"}},F={button:"qq-upload-button-selector",alertDialog:"qq-alert-dialog-selector",dialogCancelButton:"qq-cancel-button-selector",confirmDialog:"qq-confirm-dialog-selector",dialogMessage:"qq-dialog-message-selector",dialogOkButton:"qq-ok-button-selector",promptDialog:"qq-prompt-dialog-selector",uploader:"qq-uploader-selector",drop:"qq-upload-drop-area-selector",list:"qq-upload-list-selector",progressBarContainer:"qq-progress-bar-container-selector",progressBar:"qq-progress-bar-selector",totalProgressBarContainer:"qq-total-progress-bar-container-selector",totalProgressBar:"qq-total-progress-bar-selector",file:"qq-upload-file-selector",spinner:"qq-upload-spinner-selector",size:"qq-upload-size-selector",cancel:"qq-upload-cancel-selector",pause:"qq-upload-pause-selector",continueButton:"qq-upload-continue-selector",deleteButton:"qq-upload-delete-selector",retry:"qq-upload-retry-selector",statusText:"qq-upload-status-text-selector",editFilenameInput:"qq-edit-filename-selector",editNameIcon:"qq-edit-filename-icon-selector",dropText:"qq-upload-drop-area-text-selector",dropProcessing:"qq-drop-processing-selector",dropProcessingSpinner:"qq-drop-processing-spinner-selector",thumbnail:"qq-thumbnail-selector"},x={},C=new qq.Promise,E=new qq.Promise,I=function(){var e=w.placeholders.thumbnailNotAvailable,n=w.placeholders.waitingForThumbnail,i={maxSize:S,scale:l};s&&(e?w.imageGenerator.generate(e,new Image,i).then(function(e){C.success(e)},function(){C.failure(),t("Problem loading 'not available' placeholder image at "+e,"error")}):C.failure(),n?w.imageGenerator.generate(n,new Image,i).then(function(e){E.success(e)},function(){E.failure(),t("Problem loading 'waiting for thumbnail' placeholder image at "+n,"error")}):E.failure())},P=function(e){var t=new qq.Promise;return E.then(function(n){Q(n,e),e.src?t.success():(e.src=n.src,e.onload=function(){e.onload=null,te(e),t.success()})},function(){W(e),t.success()}),t},D=function(e,n,i){var o=X(e);return t("Generating new thumbnail for "+e),n.qqThumbnailId=e,w.imageGenerator.generate(n,o,i).then(function(){v++,te(o),x[e].success()},function(){x[e].failure(),w.placeholders.waitUntilUpdate||Y(e,o)})},T=function(){if(y.length){b=!0;var e=y.shift();e.update?$(e):K(e)}else b=!1},U=function(e){return V(L(e),F.cancel)},k=function(e){return V(L(e),F.continueButton)},A=function(e){return V(r,F[e+"Dialog"])},R=function(e){return V(L(e),F.deleteButton)},B=function(){return V(r,F.dropProcessing)},N=function(e){return V(L(e),F.editNameIcon)},L=function(e){return g.map[e]||qq(a).getFirstByClass(c+e)},O=function(e){return V(L(e),F.file)},H=function(e){return V(L(e),F.pause)},z=function(e){return null==e?V(r,F.totalProgressBarContainer)||V(r,F.totalProgressBar):V(L(e),F.progressBarContainer)||V(L(e),F.progressBar)},M=function(e){return V(L(e),F.retry)},j=function(e){return V(L(e),F.size)},G=function(e){return V(L(e),F.spinner)},V=function(e,t){return e&&qq(e).getFirstByClass(t)},X=function(e){return s&&V(L(e),F.thumbnail)},W=function(e){e&&qq(e).addClass(w.classes.hide)},Q=function(e,t){
-var n=e.style.maxWidth,i=e.style.maxHeight;i&&n&&!t.style.maxWidth&&!t.style.maxHeight&&qq(t).css({maxWidth:n,maxHeight:i})},Y=function(e,t){var n=x[e]||(new qq.Promise).failure(),i=new qq.Promise;return C.then(function(e){n.then(function(){i.success()},function(){Q(e,t),t.onload=function(){t.onload=null,i.success()},t.src=e.src,te(t)})}),i},J=function(){var e,o,r,a,u,c,f,m,g,_,v;if(t("Parsing template"),null==w.templateIdOrEl)throw new Error("You MUST specify either a template element or ID!");if(qq.isString(w.templateIdOrEl)){if(e=document.getElementById(w.templateIdOrEl),null===e)throw new Error(qq.format("Cannot find template script at ID '{}'!",w.templateIdOrEl));o=e.innerHTML}else{if(void 0===w.templateIdOrEl.innerHTML)throw new Error("You have specified an invalid value for the template option! It must be an ID or an Element.");o=w.templateIdOrEl.innerHTML}if(o=qq.trimStr(o),a=document.createElement("div"),a.appendChild(qq.toElement(o)),v=qq(a).getFirstByClass(F.uploader),w.button&&(c=qq(a).getFirstByClass(F.button),c&&qq(c).remove()),qq.DragAndDrop&&qq.supportedFeatures.fileDrop||(g=qq(a).getFirstByClass(F.dropProcessing),g&&qq(g).remove()),f=qq(a).getFirstByClass(F.drop),f&&!qq.DragAndDrop&&(t("DnD module unavailable.","info"),qq(f).remove()),qq.supportedFeatures.fileDrop?qq(v).hasAttribute(q)&&f&&(_=qq(f).getFirstByClass(F.dropText),_&&qq(_).remove()):(v.removeAttribute(q),f&&qq(f).hasAttribute(h)&&qq(f).css({display:"none"})),m=qq(a).getFirstByClass(F.thumbnail),s?m&&(S=parseInt(m.getAttribute(d)),S=S>0?S:null,l=qq(m).hasAttribute(p)):m&&qq(m).remove(),s=s&&m,n=qq(a).getByClass(F.editFilenameInput).length>0,i=qq(a).getByClass(F.retry).length>0,r=qq(a).getFirstByClass(F.list),null==r)throw new Error("Could not find the file list container in the template!");return u=r.innerHTML,r.innerHTML="",a.getElementsByTagName("DIALOG").length&&document.createElement("dialog"),t("Template parsing complete"),{template:qq.trimStr(a.innerHTML),fileTemplate:qq.trimStr(u)}},Z=function(e,t,n){var i=n,o=i.firstChild;t>0&&(o=qq(i).children()[t].nextSibling),i.insertBefore(e,o)},K=function(e){var t=e.id,n=e.optFileOrBlob,i=n&&n.qqThumbnailId,o=X(t),r={customResizeFunction:e.customResizeFunction,maxSize:S,orient:!0,scale:!0};qq.supportedFeatures.imagePreviews?o?w.limits.maxThumbs&&w.limits.maxThumbs<=v?(Y(t,o),T()):P(o).done(function(){x[t]=new qq.Promise,x[t].done(function(){setTimeout(T,w.limits.timeBetweenThumbs)}),null!=i?ne(t,i):D(t,n,r)}):T():o&&(P(o),T())},$=function(e){var t=e.id,n=e.thumbnailUrl,i=e.showWaitingImg,o=X(t),r={customResizeFunction:e.customResizeFunction,scale:l,maxSize:S};if(o)if(n){if(!(w.limits.maxThumbs&&w.limits.maxThumbs<=v))return i&&P(o),w.imageGenerator.generate(n,o,r).then(function(){te(o),v++,setTimeout(T,w.limits.timeBetweenThumbs)},function(){Y(t,o),setTimeout(T,w.limits.timeBetweenThumbs)});Y(t,o),T()}else Y(t,o),T()},ee=function(e,t){var n=z(e),i=null==e?F.totalProgressBar:F.progressBar;n&&!qq(n).hasClass(i)&&(n=qq(n).getFirstByClass(i)),n&&(qq(n).css({width:t+"%"}),n.setAttribute("aria-valuenow",t))},te=function(e){e&&qq(e).removeClass(w.classes.hide)},ne=function(e,n){var i=X(e),o=X(n);t(qq.format("ID {} is the same file as ID {}. Will use generated thumbnail from ID {} instead.",e,n,n)),x[n].then(function(){v++,x[e].success(),t(qq.format("Now using previously generated thumbnail created for ID {} on ID {}.",n,e)),i.src=o.src,te(i)},function(){x[e].failure(),w.placeholders.waitUntilUpdate||Y(e,i)})};qq.extend(w,e),t=w.log,qq.supportedFeatures.imagePreviews||(w.limits.timeBetweenThumbs=0,w.limits.maxThumbs=0),r=w.containerEl,s=void 0!==w.imageGenerator,o=J(),I(),qq.extend(this,{render:function(){t("Rendering template in DOM."),v=0,r.innerHTML=o.template,W(B()),this.hideTotalProgress(),a=w.fileContainerEl||V(r,F.list),t("Template rendering complete")},renderFailure:function(e){var t=qq.toElement(e);r.innerHTML="",r.appendChild(t)},reset:function(){this.render()},clearFiles:function(){a.innerHTML=""},disableCancel:function(){_=!0},addFile:function(e,t,n,i,s){var l,d=qq.toElement(o.fileTemplate),p=V(d,F.file),h=V(r,F.uploader),f=s?g.content:a;s&&(g.map[e]=d),qq(d).addClass(c+e),h.removeAttribute(q),p&&(qq(p).setText(t),p.setAttribute("title",t)),d.setAttribute(u,e),n?Z(d,n.index,f):f.appendChild(d),i?(d.style.display="none",qq(d).addClass(m)):(W(z(e)),W(j(e)),W(R(e)),W(M(e)),W(H(e)),W(k(e)),_&&this.hideCancel(e),l=X(e),l&&!l.src&&E.then(function(e){l.src=e.src,e.style.maxHeight&&e.style.maxWidth&&qq(l).css({maxHeight:e.style.maxHeight,maxWidth:e.style.maxWidth}),te(l)}))},addFileToCache:function(e,t,n,i){this.addFile(e,t,n,i,!0)},addCacheToDom:function(){a.appendChild(g.content),g.content=document.createDocumentFragment(),g.map={}},removeFile:function(e){qq(L(e)).remove()},getFileId:function(e){var t=e;if(t){for(;null==t.getAttribute(u);)t=t.parentNode;return parseInt(t.getAttribute(u))}},getFileList:function(){return a},markFilenameEditable:function(e){var t=O(e);t&&qq(t).addClass(w.classes.editable)},updateFilename:function(e,t){var n=O(e);n&&(qq(n).setText(t),n.setAttribute("title",t))},hideFilename:function(e){W(O(e))},showFilename:function(e){te(O(e))},isFileName:function(e){return qq(e).hasClass(F.file)},getButton:function(){return w.button||V(r,F.button)},hideDropProcessing:function(){W(B())},showDropProcessing:function(){te(B())},getDropZone:function(){return V(r,F.drop)},isEditFilenamePossible:function(){return n},hideRetry:function(e){W(M(e))},isRetryPossible:function(){return i},showRetry:function(e){te(M(e))},getFileContainer:function(e){return L(e)},showEditIcon:function(e){var t=N(e);t&&qq(t).addClass(w.classes.editable)},isHiddenForever:function(e){return qq(L(e)).hasClass(m)},hideEditIcon:function(e){var t=N(e);t&&qq(t).removeClass(w.classes.editable)},isEditIcon:function(e){return qq(e).hasClass(F.editNameIcon,!0)},getEditInput:function(e){return V(L(e),F.editFilenameInput)},isEditInput:function(e){return qq(e).hasClass(F.editFilenameInput,!0)},updateProgress:function(e,t,n){var i,o=z(e);o&&n>0&&(i=Math.round(t/n*100),100===i?W(o):te(o),ee(e,i))},updateTotalProgress:function(e,t){this.updateProgress(null,e,t)},hideProgress:function(e){var t=z(e);t&&W(t)},hideTotalProgress:function(){this.hideProgress()},resetProgress:function(e){ee(e,0),this.hideTotalProgress(e)},resetTotalProgress:function(){this.resetProgress()},showCancel:function(e){if(!_){var t=U(e);t&&qq(t).removeClass(w.classes.hide)}},hideCancel:function(e){W(U(e))},isCancel:function(e){return qq(e).hasClass(F.cancel,!0)},allowPause:function(e){te(H(e)),W(k(e))},uploadPaused:function(e){this.setStatusText(e,w.text.paused),this.allowContinueButton(e),W(G(e))},hidePause:function(e){W(H(e))},isPause:function(e){return qq(e).hasClass(F.pause,!0)},isContinueButton:function(e){return qq(e).hasClass(F.continueButton,!0)},allowContinueButton:function(e){te(k(e)),W(H(e))},uploadContinued:function(e){this.setStatusText(e,""),this.allowPause(e),te(G(e))},showDeleteButton:function(e){te(R(e))},hideDeleteButton:function(e){W(R(e))},isDeleteButton:function(e){return qq(e).hasClass(F.deleteButton,!0)},isRetry:function(e){return qq(e).hasClass(F.retry,!0)},updateSize:function(e,t){var n=j(e);n&&(te(n),qq(n).setText(t))},setStatusText:function(e,t){var n=V(L(e),F.statusText);n&&(null==t?qq(n).clearText():qq(n).setText(t))},hideSpinner:function(e){qq(L(e)).removeClass(f),W(G(e))},showSpinner:function(e){qq(L(e)).addClass(f),te(G(e))},generatePreview:function(e,t,n){this.isHiddenForever(e)||(y.push({id:e,customResizeFunction:n,optFileOrBlob:t}),!b&&T())},updateThumbnail:function(e,t,n,i){this.isHiddenForever(e)||(y.push({customResizeFunction:i,update:!0,id:e,thumbnailUrl:t,showWaitingImg:n}),!b&&T())},hasDialog:function(e){return qq.supportedFeatures.dialogElement&&!!A(e)},showDialog:function(e,t,n){var i=A(e),o=V(i,F.dialogMessage),r=i.getElementsByTagName("INPUT")[0],a=V(i,F.dialogCancelButton),s=V(i,F.dialogOkButton),l=new qq.Promise,u=function(){a.removeEventListener("click",c),s&&s.removeEventListener("click",d),l.failure()},c=function(){a.removeEventListener("click",c),i.close()},d=function(){i.removeEventListener("close",u),s.removeEventListener("click",d),i.close(),l.success(r&&r.value)};return i.addEventListener("close",u),a.addEventListener("click",c),s&&s.addEventListener("click",d),r&&(r.value=n),o.textContent=t,i.showModal(),l}})},qq.UiEventHandler=function(e,t){"use strict";function n(e){i.attach(e,o.eventType,function(e){e=e||window.event;var t=e.target||e.srcElement;o.onHandled(t,e)})}var i=new qq.DisposeSupport,o={eventType:"click",attachTo:null,onHandled:function(e,t){}};qq.extend(this,{addHandler:function(e){n(e)},dispose:function(){i.dispose()}}),qq.extend(t,{getFileIdFromItem:function(e){return e.qqFileId},getDisposeSupport:function(){return i}}),qq.extend(o,e),o.attachTo&&n(o.attachTo)},qq.FileButtonsClickHandler=function(e){"use strict";function t(e,t){qq.each(o,function(n,o){var r,a=n.charAt(0).toUpperCase()+n.slice(1);if(i.templating["is"+a](e))return r=i.templating.getFileId(e),qq.preventDefault(t),i.log(qq.format("Detected valid file button click event on file '{}', ID: {}.",i.onGetName(r),r)),o(r),!1})}var n={},i={templating:null,log:function(e,t){},onDeleteFile:function(e){},onCancel:function(e){},onRetry:function(e){},onPause:function(e){},onContinue:function(e){},onGetName:function(e){}},o={cancel:function(e){i.onCancel(e)},retry:function(e){i.onRetry(e)},deleteButton:function(e){i.onDeleteFile(e)},pause:function(e){i.onPause(e)},continueButton:function(e){i.onContinue(e)}};qq.extend(i,e),i.eventType="click",i.onHandled=t,i.attachTo=i.templating.getFileList(),qq.extend(this,new qq.UiEventHandler(i,n))},qq.FilenameClickHandler=function(e){"use strict";function t(e,t){if(i.templating.isFileName(e)||i.templating.isEditIcon(e)){var o=i.templating.getFileId(e),r=i.onGetUploadStatus(o);r===qq.status.SUBMITTED&&(i.log(qq.format("Detected valid filename click event on file '{}', ID: {}.",i.onGetName(o),o)),qq.preventDefault(t),n.handleFilenameEdit(o,e,!0))}}var n={},i={templating:null,log:function(e,t){},classes:{file:"qq-upload-file",editNameIcon:"qq-edit-filename-icon"},onGetUploadStatus:function(e){},onGetName:function(e){}};qq.extend(i,e),i.eventType="click",i.onHandled=t,qq.extend(this,new qq.FilenameEditHandler(i,n))},qq.FilenameInputFocusInHandler=function(e,t){"use strict";function n(e,n){if(i.templating.isEditInput(e)){var o=i.templating.getFileId(e),r=i.onGetUploadStatus(o);r===qq.status.SUBMITTED&&(i.log(qq.format("Detected valid filename input focus event on file '{}', ID: {}.",i.onGetName(o),o)),t.handleFilenameEdit(o,e))}}var i={templating:null,onGetUploadStatus:function(e){},log:function(e,t){}};t||(t={}),i.eventType="focusin",i.onHandled=n,qq.extend(i,e),qq.extend(this,new qq.FilenameEditHandler(i,t))},qq.FilenameInputFocusHandler=function(e){"use strict";e.eventType="focus",e.attachTo=null,qq.extend(this,new qq.FilenameInputFocusInHandler(e,{}))},qq.FilenameEditHandler=function(e,t){"use strict";function n(e){var t=s.onGetName(e),n=t.lastIndexOf(".");return n>0&&(t=t.substr(0,n)),t}function i(e){var t=s.onGetName(e);return qq.getExtension(t)}function o(e,t){var n,o=e.value;void 0!==o&&qq.trimStr(o).length>0&&(n=i(t),void 0!==n&&(o=o+"."+n),s.onSetName(t,o)),s.onEditingStatusChange(t,!1)}function r(e,n){t.getDisposeSupport().attach(e,"blur",function(){o(e,n)})}function a(e,n){t.getDisposeSupport().attach(e,"keyup",function(t){var i=t.keyCode||t.which;13===i&&o(e,n)})}var s={templating:null,log:function(e,t){},onGetUploadStatus:function(e){},onGetName:function(e){},onSetName:function(e,t){},onEditingStatusChange:function(e,t){}};qq.extend(s,e),s.attachTo=s.templating.getFileList(),qq.extend(this,new qq.UiEventHandler(s,t)),qq.extend(t,{handleFilenameEdit:function(e,t,i){var o=s.templating.getEditInput(e);s.onEditingStatusChange(e,!0),o.value=n(e),i&&o.focus(),r(o,e),a(o,e)}})}}(window);
+// Fine Uploader 5.16.2 - MIT licensed. http://fineuploader.com
+!function(global){var qq=function(e){"use strict";return{hide:function(){return e.style.display="none",this},attach:function(t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent&&e.attachEvent("on"+t,n),function(){qq(e).detach(t,n)}},detach:function(t,n){return e.removeEventListener?e.removeEventListener(t,n,!1):e.attachEvent&&e.detachEvent("on"+t,n),this},contains:function(t){return!!t&&(e===t||(e.contains?e.contains(t):!!(8&t.compareDocumentPosition(e))))},insertBefore:function(t){return t.parentNode.insertBefore(e,t),this},remove:function(){return e.parentNode.removeChild(e),this},css:function(t){if(null==e.style)throw new qq.Error("Can't apply style to node as it is not on the HTMLElement prototype chain!");return null!=t.opacity&&"string"!=typeof e.style.opacity&&void 0!==e.filters&&(t.filter="alpha(opacity="+Math.round(100*t.opacity)+")"),qq.extend(e.style,t),this},hasClass:function(t,n){var i=new RegExp("(^| )"+t+"( |$)");return i.test(e.className)||!(!n||!i.test(e.parentNode.className))},addClass:function(t){return qq(e).hasClass(t)||(e.className+=" "+t),this},removeClass:function(t){var n=new RegExp("(^| )"+t+"( |$)");return e.className=e.className.replace(n," ").replace(/^\s+|\s+$/g,""),this},getByClass:function(t,n){var i,o=[];return n&&e.querySelector?e.querySelector("."+t):e.querySelectorAll?e.querySelectorAll("."+t):(i=e.getElementsByTagName("*"),qq.each(i,function(e,n){qq(n).hasClass(t)&&o.push(n)}),n?o[0]:o)},getFirstByClass:function(t){return qq(e).getByClass(t,!0)},children:function(){for(var t=[],n=e.firstChild;n;)1===n.nodeType&&t.push(n),n=n.nextSibling;return t},setText:function(t){return e.innerText=t,e.textContent=t,this},clearText:function(){return qq(e).setText("")},hasAttribute:function(t){var n;return e.hasAttribute?!!e.hasAttribute(t)&&null==/^false$/i.exec(e.getAttribute(t)):(n=e[t],void 0!==n&&null==/^false$/i.exec(n))}}};!function(){"use strict";qq.canvasToBlob=function(e,t,n){return qq.dataUriToBlob(e.toDataURL(t,n))},qq.dataUriToBlob=function(e){var t,n,i,o,r=function(e,t){var n=window.BlobBuilder||window.WebKitBlobBuilder||window.MozBlobBuilder||window.MSBlobBuilder,i=n&&new n;return i?(i.append(e),i.getBlob(t)):new Blob([e],{type:t})};return n=e.split(",")[0].indexOf("base64")>=0?atob(e.split(",")[1]):decodeURI(e.split(",")[1]),o=e.split(",")[0].split(":")[1].split(";")[0],t=new ArrayBuffer(n.length),i=new Uint8Array(t),qq.each(n,function(e,t){i[e]=t.charCodeAt(0)}),r(t,o)},qq.log=function(e,t){window.console&&(t&&"info"!==t?window.console[t]?window.console[t](e):window.console.log("<"+t+"> "+e):window.console.log(e))},qq.isObject=function(e){return e&&!e.nodeType&&"[object Object]"===Object.prototype.toString.call(e)},qq.isFunction=function(e){return"function"==typeof e},qq.isArray=function(e){return"[object Array]"===Object.prototype.toString.call(e)||e&&window.ArrayBuffer&&e.buffer&&e.buffer.constructor===ArrayBuffer},qq.isItemList=function(e){return"[object DataTransferItemList]"===Object.prototype.toString.call(e)},qq.isNodeList=function(e){return"[object NodeList]"===Object.prototype.toString.call(e)||e.item&&e.namedItem},qq.isString=function(e){return"[object String]"===Object.prototype.toString.call(e)},qq.trimStr=function(e){return String.prototype.trim?e.trim():e.replace(/^\s+|\s+$/g,"")},qq.format=function(e){var t=Array.prototype.slice.call(arguments,1),n=e,i=n.indexOf("{}");return qq.each(t,function(e,t){if(n=n.substring(0,i)+t+n.substring(i+2),i=n.indexOf("{}",i+t.length),i<0)return!1}),n},qq.isFile=function(e){return window.File&&"[object File]"===Object.prototype.toString.call(e)},qq.isFileList=function(e){return window.FileList&&"[object FileList]"===Object.prototype.toString.call(e)},qq.isFileOrInput=function(e){return qq.isFile(e)||qq.isInput(e)},qq.isInput=function(e,t){var n=function(e){var n=e.toLowerCase();return t?"file"!==n:"file"===n};return!!(window.HTMLInputElement&&"[object HTMLInputElement]"===Object.prototype.toString.call(e)&&e.type&&n(e.type))||!!(e.tagName&&"input"===e.tagName.toLowerCase()&&e.type&&n(e.type))},qq.isBlob=function(e){if(window.Blob&&"[object Blob]"===Object.prototype.toString.call(e))return!0},qq.isXhrUploadSupported=function(){var e=document.createElement("input");return e.type="file",void 0!==e.multiple&&"undefined"!=typeof File&&"undefined"!=typeof FormData&&void 0!==qq.createXhrInstance().upload},qq.createXhrInstance=function(){if(window.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(e){return qq.log("Neither XHR or ActiveX are supported!","error"),null}},qq.isFolderDropSupported=function(e){return e.items&&e.items.length>0&&e.items[0].webkitGetAsEntry},qq.isFileChunkingSupported=function(){return!qq.androidStock()&&qq.isXhrUploadSupported()&&(void 0!==File.prototype.slice||void 0!==File.prototype.webkitSlice||void 0!==File.prototype.mozSlice)},qq.sliceBlob=function(e,t,n){return(e.slice||e.mozSlice||e.webkitSlice).call(e,t,n)},qq.arrayBufferToHex=function(e){var t="",n=new Uint8Array(e);return qq.each(n,function(e,n){var i=n.toString(16);i.length<2&&(i="0"+i),t+=i}),t},qq.readBlobToHex=function(e,t,n){var i=qq.sliceBlob(e,t,t+n),o=new FileReader,r=new qq.Promise;return o.onload=function(){r.success(qq.arrayBufferToHex(o.result))},o.onerror=r.failure,o.readAsArrayBuffer(i),r},qq.extend=function(e,t,n){return qq.each(t,function(t,i){n&&qq.isObject(i)?(void 0===e[t]&&(e[t]={}),qq.extend(e[t],i,!0)):e[t]=i}),e},qq.override=function(e,t){var n={},i=t(n);return qq.each(i,function(t,i){void 0!==e[t]&&(n[t]=e[t]),e[t]=i}),e},qq.indexOf=function(e,t,n){if(e.indexOf)return e.indexOf(t,n);n=n||0;var i=e.length;for(n<0&&(n+=i);n=0},qq.safari=function(){return void 0!==navigator.vendor&&navigator.vendor.indexOf("Apple")!==-1},qq.chrome=function(){return void 0!==navigator.vendor&&navigator.vendor.indexOf("Google")!==-1},qq.opera=function(){return void 0!==navigator.vendor&&navigator.vendor.indexOf("Opera")!==-1},qq.firefox=function(){return!qq.edge()&&!qq.ie11()&&navigator.userAgent.indexOf("Mozilla")!==-1&&void 0!==navigator.vendor&&""===navigator.vendor},qq.windows=function(){return"Win32"===navigator.platform},qq.android=function(){return navigator.userAgent.toLowerCase().indexOf("android")!==-1},qq.androidStock=function(){return qq.android()&&navigator.userAgent.toLowerCase().indexOf("chrome")<0},qq.ios6=function(){return qq.ios()&&navigator.userAgent.indexOf(" OS 6_")!==-1},qq.ios7=function(){return qq.ios()&&navigator.userAgent.indexOf(" OS 7_")!==-1},qq.ios8=function(){return qq.ios()&&navigator.userAgent.indexOf(" OS 8_")!==-1},qq.ios800=function(){return qq.ios()&&navigator.userAgent.indexOf(" OS 8_0 ")!==-1},qq.ios=function(){return navigator.userAgent.indexOf("iPad")!==-1||navigator.userAgent.indexOf("iPod")!==-1||navigator.userAgent.indexOf("iPhone")!==-1},qq.iosChrome=function(){return qq.ios()&&navigator.userAgent.indexOf("CriOS")!==-1},qq.iosSafari=function(){return qq.ios()&&!qq.iosChrome()&&navigator.userAgent.indexOf("Safari")!==-1},qq.iosSafariWebView=function(){return qq.ios()&&!qq.iosChrome()&&!qq.iosSafari()},qq.preventDefault=function(e){e.preventDefault?e.preventDefault():e.returnValue=!1},qq.toElement=function(){var e=document.createElement("div");return function(t){e.innerHTML=t;var n=e.firstChild;return e.removeChild(n),n}}(),qq.each=function(e,t){var n,i;if(e)if(window.Storage&&e.constructor===window.Storage)for(n=0;n0)return e.substr(t,e.length-t)},qq.getFilename=function(e){return qq.isInput(e)?e.value.replace(/.*(\/|\\)/,""):qq.isFile(e)&&null!==e.fileName&&void 0!==e.fileName?e.fileName:e.name},qq.DisposeSupport=function(){var e=[];return{dispose:function(){var t;do t=e.shift(),t&&t();while(t)},attach:function(){var e=arguments;this.addDisposer(qq(e[0]).attach.apply(this,Array.prototype.slice.call(arguments,1)))},addDisposer:function(t){e.push(t)}}}}(),function(){"use strict";"function"==typeof define&&define.amd?define(function(){return qq}):"undefined"!=typeof module&&module.exports?module.exports=qq:global.qq=qq}(),function(){"use strict";qq.Error=function(e){this.message="[Fine Uploader "+qq.version+"] "+e},qq.Error.prototype=new Error}(),qq.version="5.16.2",qq.supportedFeatures=function(){"use strict";function e(){var e,t=!0;try{e=document.createElement("input"),e.type="file",qq(e).hide(),e.disabled&&(t=!1)}catch(e){t=!1}return t}function t(){return(qq.chrome()||qq.opera())&&void 0!==navigator.userAgent.match(/Chrome\/[1][4-9]|Chrome\/[2-9][0-9]/)}function n(){if(window.XMLHttpRequest){return void 0!==qq.createXhrInstance().withCredentials}return!1}function i(){return void 0!==window.XDomainRequest}function o(){return!!n()||i()}function r(){return void 0!==document.createElement("input").webkitdirectory}function a(){try{return!!window.localStorage&&qq.isFunction(window.localStorage.setItem)}catch(e){return!1}}function s(){var e=document.createElement("span");return("draggable"in e||"ondragstart"in e&&"ondrop"in e)&&!qq.android()&&!qq.ios()}var u,l,c,d,p,h,q,f,m,g,_,v,b,y,S;return u=e(),d=u&&qq.isXhrUploadSupported(),l=d&&!qq.androidStock(),c=d&&s(),p=c&&function(){var e=document.createElement("input");return e.type="file",!!("webkitdirectory"in(e||document.querySelectorAll("input[type=file]")[0]))}(),h=d&&qq.isFileChunkingSupported(),q=d&&h&&a(),f=d&&t(),m=u&&(void 0!==window.postMessage||d),_=n(),g=i(),v=o(),b=r(),y=d&&void 0!==window.FileReader,S=function(){return!!d&&(!qq.androidStock()&&!qq.iosChrome())}(),{ajaxUploading:d,blobUploading:l,canDetermineSize:d,chunking:h,deleteFileCors:v,deleteFileCorsXdr:g,deleteFileCorsXhr:_,dialogElement:!!window.HTMLDialogElement,fileDrop:c,folderDrop:p,folderSelection:b,imagePreviews:y,imageValidation:y,itemSizeValidation:d,pause:h,progressBar:S,resume:q,scaling:y&&l,tiffPreviews:qq.safari(),unlimitedScaledImageSize:!qq.ios(),uploading:u,uploadCors:m,uploadCustomHeaders:d,uploadNonMultipart:d,uploadViaPaste:f}}(),qq.isGenericPromise=function(e){"use strict";return!!(e&&e.then&&qq.isFunction(e.then))},qq.Promise=function(){"use strict";var e,t,n=[],i=[],o=[],r=0;qq.extend(this,{then:function(o,a){return 0===r?(o&&n.push(o),a&&i.push(a)):r===-1?a&&a.apply(null,t):o&&o.apply(null,e),this},done:function(n){return 0===r?o.push(n):n.apply(null,void 0===t?e:t),this},success:function(){return r=1,e=arguments,n.length&&qq.each(n,function(t,n){n.apply(null,e)}),o.length&&qq.each(o,function(t,n){n.apply(null,e)}),this},failure:function(){return r=-1,t=arguments,i.length&&qq.each(i,function(e,n){n.apply(null,t)}),o.length&&qq.each(o,function(e,n){n.apply(null,t)}),this}})},qq.BlobProxy=function(e,t){"use strict";qq.extend(this,{referenceBlob:e,create:function(){return t(e)}})},qq.UploadButton=function(e){"use strict";function t(){var e=document.createElement("input");return e.setAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME,i),e.setAttribute("title",a.title),o.setMultiple(a.multiple,e),a.folders&&qq.supportedFeatures.folderSelection&&e.setAttribute("webkitdirectory",""),a.acceptFiles&&e.setAttribute("accept",a.acceptFiles),e.setAttribute("type","file"),e.setAttribute("name",a.name),qq(e).css({position:"absolute",right:0,top:0,fontFamily:"Arial",fontSize:qq.ie()&&!qq.ie8()?"3500px":"118px",margin:0,padding:0,cursor:"pointer",opacity:0}),!qq.ie7()&&qq(e).css({height:"100%"}),a.element.appendChild(e),r.attach(e,"change",function(){a.onChange(e)}),r.attach(e,"mouseover",function(){qq(a.element).addClass(a.hoverClass)}),r.attach(e,"mouseout",function(){qq(a.element).removeClass(a.hoverClass)}),r.attach(e,"focus",function(){qq(a.element).addClass(a.focusClass)}),r.attach(e,"blur",function(){qq(a.element).removeClass(a.focusClass)}),e}var n,i,o=this,r=new qq.DisposeSupport,a={acceptFiles:null,element:null,focusClass:"qq-upload-button-focus",folders:!1,hoverClass:"qq-upload-button-hover",ios8BrowserCrashWorkaround:!1,multiple:!1,name:"qqfile",onChange:function(e){},title:null};qq.extend(a,e),i=qq.getUniqueId(),qq(a.element).css({position:"relative",overflow:"hidden",direction:"ltr"}),qq.extend(this,{getInput:function(){return n},getButtonId:function(){return i},setMultiple:function(e,t){var n=t||this.getInput();a.ios8BrowserCrashWorkaround&&qq.ios8()&&(qq.iosChrome()||qq.iosSafariWebView())?n.setAttribute("multiple",""):e?n.setAttribute("multiple",""):n.removeAttribute("multiple")},setAcceptFiles:function(e){e!==a.acceptFiles&&n.setAttribute("accept",e)},reset:function(){n.parentNode&&qq(n).remove(),qq(a.element).removeClass(a.focusClass),n=null,n=t()}}),n=t()},qq.UploadButton.BUTTON_ID_ATTR_NAME="qq-button-id",qq.UploadData=function(e){"use strict";function t(e){if(qq.isArray(e)){var t=[];return qq.each(e,function(e,n){t.push(o[n])}),t}return o[e]}function n(e){if(qq.isArray(e)){var t=[];return qq.each(e,function(e,n){t.push(o[r[n]])}),t}return o[r[e]]}function i(e){var t=[],n=[].concat(e);return qq.each(n,function(e,n){var i=a[n];void 0!==i&&qq.each(i,function(e,n){t.push(o[n])})}),t}var o=[],r={},a={},s={},u={};qq.extend(this,{addFile:function(t){var n=t.status||qq.status.SUBMITTING,i=o.push({name:t.name,originalName:t.name,uuid:t.uuid,size:null==t.size?-1:t.size,status:n,file:t.file})-1;return t.batchId&&(o[i].batchId=t.batchId,void 0===u[t.batchId]&&(u[t.batchId]=[]),u[t.batchId].push(i)),t.proxyGroupId&&(o[i].proxyGroupId=t.proxyGroupId,void 0===s[t.proxyGroupId]&&(s[t.proxyGroupId]=[]),s[t.proxyGroupId].push(i)),o[i].id=i,r[t.uuid]=i,void 0===a[n]&&(a[n]=[]),a[n].push(i),t.onBeforeStatusChange&&t.onBeforeStatusChange(i),e.onStatusChange(i,null,n),i},retrieve:function(e){return qq.isObject(e)&&o.length?void 0!==e.id?t(e.id):void 0!==e.uuid?n(e.uuid):e.status?i(e.status):void 0:qq.extend([],o,!0)},removeFileRef:function(e){var n=t(e);n&&delete n.file},reset:function(){o=[],r={},a={},u={}},setStatus:function(t,n){var i=o[t].status,r=qq.indexOf(a[i],t);a[i].splice(r,1),o[t].status=n,void 0===a[n]&&(a[n]=[]),a[n].push(t),e.onStatusChange(t,i,n)},uuidChanged:function(e,t){var n=o[e].uuid;o[e].uuid=t,r[t]=e,delete r[n]},updateName:function(e,t){o[e].name=t},updateSize:function(e,t){o[e].size=t},setParentId:function(e,t){o[e].parentId=t},getIdsInProxyGroup:function(e){var t=o[e].proxyGroupId;return t?s[t]:[]},getIdsInBatch:function(e){return u[o[e].batchId]}})},qq.status={SUBMITTING:"submitting",SUBMITTED:"submitted",REJECTED:"rejected",QUEUED:"queued",CANCELED:"canceled",PAUSED:"paused",UPLOADING:"uploading",UPLOAD_FINALIZING:"upload finalizing",UPLOAD_RETRYING:"retrying upload",UPLOAD_SUCCESSFUL:"upload successful",UPLOAD_FAILED:"upload failed",DELETE_FAILED:"delete failed",DELETING:"deleting",DELETED:"deleted"},function(){"use strict";qq.basePublicApi={addBlobs:function(e,t,n){this.addFiles(e,t,n)},addInitialFiles:function(e){var t=this;qq.each(e,function(e,n){t._addCannedFile(n)})},addFiles:function(e,t,n){this._maybeHandleIos8SafariWorkaround();var i=0===this._storedIds.length?qq.getUniqueId():this._currentBatchId,o=qq.bind(function(e){this._handleNewFile({blob:e,name:this._options.blobs.defaultName},i,d)},this),r=qq.bind(function(e){this._handleNewFile(e,i,d)},this),a=qq.bind(function(e){var t=qq.canvasToBlob(e);this._handleNewFile({blob:t,name:this._options.blobs.defaultName+".png"},i,d)},this),s=qq.bind(function(e){var t=e.quality&&e.quality/100,n=qq.canvasToBlob(e.canvas,e.type,t);this._handleNewFile({blob:n,name:e.name},i,d)},this),u=qq.bind(function(e){if(qq.isInput(e)&&qq.supportedFeatures.ajaxUploading){var t=Array.prototype.slice.call(e.files),n=this;qq.each(t,function(e,t){n._handleNewFile(t,i,d)})}else this._handleNewFile(e,i,d)},this),l=function(){qq.isFileList(e)&&(e=Array.prototype.slice.call(e)),e=[].concat(e)},c=this,d=[];this._currentBatchId=i,e&&(l(),qq.each(e,function(e,t){qq.isFileOrInput(t)?u(t):qq.isBlob(t)?o(t):qq.isObject(t)?t.blob&&t.name?r(t):t.canvas&&t.name&&s(t):t.tagName&&"canvas"===t.tagName.toLowerCase()?a(t):c.log(t+" is not a valid file container! Ignoring!","warn")}),this.log("Received "+d.length+" files."),this._prepareItemsForUpload(d,t,n))},cancel:function(e){var t=this._uploadData.retrieve({id:e});t&&t.status===qq.status.UPLOAD_FINALIZING?this.log(qq.format("Ignoring cancel for file ID {} ({}). Finalizing upload.",e,this.getName(e)),"error"):this._handler.cancel(e)},cancelAll:function(){var e=[],t=this;qq.extend(e,this._storedIds),qq.each(e,function(e,n){t.cancel(n)}),this._handler.cancelAll()},clearStoredFiles:function(){this._storedIds=[]},continueUpload:function(e){var t=this._uploadData.retrieve({id:e});return!(!qq.supportedFeatures.pause||!this._options.chunking.enabled)&&(t.status===qq.status.PAUSED?(this.log(qq.format("Paused file ID {} ({}) will be continued. Not paused.",e,this.getName(e))),this._uploadFile(e),!0):(this.log(qq.format("Ignoring continue for file ID {} ({}). Not paused.",e,this.getName(e)),"error"),!1))},deleteFile:function(e){return this._onSubmitDelete(e)},doesExist:function(e){return this._handler.isValid(e)},drawThumbnail:function(e,t,n,i,o){var r,a,s=new qq.Promise;return this._imageGenerator?(r=this._thumbnailUrls[e],a={customResizeFunction:o,maxSize:n>0?n:null,scale:n>0},!i&&qq.supportedFeatures.imagePreviews&&(r=this.getFile(e)),null==r?s.failure({container:t,error:"File or URL not found."}):this._imageGenerator.generate(r,t,a).then(function(e){s.success(e)},function(e,t){s.failure({container:e,error:t||"Problem generating thumbnail"})})):s.failure({container:t,error:"Missing image generator module"}),s},getButton:function(e){return this._getButton(this._buttonIdsForFileIds[e])},getEndpoint:function(e){return this._endpointStore.get(e)},getFile:function(e){var t,n=this._handler.getFile(e);return n||(t=this._uploadData.retrieve({id:e}),t&&(n=t.file)),n||null},getInProgress:function(){return this._uploadData.retrieve({status:[qq.status.UPLOADING,qq.status.UPLOAD_RETRYING,qq.status.QUEUED]}).length},getName:function(e){return this._uploadData.retrieve({id:e}).name},getParentId:function(e){var t=this.getUploads({id:e}),n=null;return t&&void 0!==t.parentId&&(n=t.parentId),n},getResumableFilesData:function(){return this._handler.getResumableFilesData()},getSize:function(e){return this._uploadData.retrieve({id:e}).size},getNetUploads:function(){return this._netUploaded},getRemainingAllowedItems:function(){var e=this._currentItemLimit;return e>0?e-this._netUploadedOrQueued:null},getUploads:function(e){return this._uploadData.retrieve(e)},getUuid:function(e){return this._uploadData.retrieve({id:e}).uuid},isResumable:function(e){return this._handler.hasResumeRecord(e)},log:function(e,t){!this._options.debug||t&&"info"!==t?t&&"info"!==t&&qq.log("[Fine Uploader "+qq.version+"] "+e,t):qq.log("[Fine Uploader "+qq.version+"] "+e)},pauseUpload:function(e){var t=this._uploadData.retrieve({id:e});if(!qq.supportedFeatures.pause||!this._options.chunking.enabled)return!1;if(qq.indexOf([qq.status.UPLOADING,qq.status.UPLOAD_RETRYING],t.status)>=0){if(this._handler.pause(e))return this._uploadData.setStatus(e,qq.status.PAUSED),!0;this.log(qq.format("Unable to pause file ID {} ({}).",e,this.getName(e)),"error")}else this.log(qq.format("Ignoring pause for file ID {} ({}). Not in progress.",e,this.getName(e)),"error");return!1},removeFileRef:function(e){this._handler.expunge(e),this._uploadData.removeFileRef(e)},reset:function(){this.log("Resetting uploader..."),this._handler.reset(),this._storedIds=[],this._autoRetries=[],this._retryTimeouts=[],this._preventRetries=[],this._thumbnailUrls=[],qq.each(this._buttons,function(e,t){t.reset()}),this._paramsStore.reset(),this._endpointStore.reset(),this._netUploadedOrQueued=0,this._netUploaded=0,this._uploadData.reset(),this._buttonIdsForFileIds=[],this._pasteHandler&&this._pasteHandler.reset(),this._options.session.refreshOnReset&&this._refreshSessionData(),this._succeededSinceLastAllComplete=[],this._failedSinceLastAllComplete=[],this._totalProgress&&this._totalProgress.reset(),this._customResumeDataStore.reset()},retry:function(e){return this._manualRetry(e)},scaleImage:function(e,t){var n=this;return qq.Scaler.prototype.scaleImage(e,t,{log:qq.bind(n.log,n),getFile:qq.bind(n.getFile,n),uploadData:n._uploadData})},setCustomHeaders:function(e,t){this._customHeadersStore.set(e,t)},setCustomResumeData:function(e,t){this._customResumeDataStore.set(t,e)},setDeleteFileCustomHeaders:function(e,t){this._deleteFileCustomHeadersStore.set(e,t)},setDeleteFileEndpoint:function(e,t){this._deleteFileEndpointStore.set(e,t)},setDeleteFileParams:function(e,t){this._deleteFileParamsStore.set(e,t)},setEndpoint:function(e,t){this._endpointStore.set(e,t)},setForm:function(e){this._updateFormSupportAndParams(e)},setItemLimit:function(e){this._currentItemLimit=e},setName:function(e,t){this._uploadData.updateName(e,t)},setParams:function(e,t){this._paramsStore.set(e,t)},setUuid:function(e,t){return this._uploadData.uuidChanged(e,t)},setStatus:function(e,t){if(!this.getUploads({id:e}))throw new qq.Error(e+" is not a valid file ID.");switch(t){case qq.status.DELETED:this._onDeleteComplete(e,null,!1);break;case qq.status.DELETE_FAILED:this._onDeleteComplete(e,null,!0);break;default:var n="Method setStatus called on '"+name+"' not implemented yet for "+t;throw this.log(n),new qq.Error(n)}},uploadStoredFiles:function(){0===this._storedIds.length?this._itemError("noFilesError"):this._uploadStoredFiles()}},qq.basePrivateApi={_addCannedFile:function(e){var t=this;return this._uploadData.addFile({uuid:e.uuid,name:e.name,size:e.size,status:qq.status.UPLOAD_SUCCESSFUL,onBeforeStatusChange:function(n){e.deleteFileEndpoint&&t.setDeleteFileEndpoint(e.deleteFileEndpoint,n),e.deleteFileParams&&t.setDeleteFileParams(e.deleteFileParams,n),e.thumbnailUrl&&(t._thumbnailUrls[n]=e.thumbnailUrl),t._netUploaded++,t._netUploadedOrQueued++}})},_annotateWithButtonId:function(e,t){qq.isFile(e)&&(e.qqButtonId=this._getButtonId(t))},_batchError:function(e){this._options.callbacks.onError(null,null,e,void 0)},_createDeleteHandler:function(){var e=this;return new qq.DeleteFileAjaxRequester({method:this._options.deleteFile.method.toUpperCase(),maxConnections:this._options.maxConnections,uuidParamName:this._options.request.uuidName,customHeaders:this._deleteFileCustomHeadersStore,paramsStore:this._deleteFileParamsStore,endpointStore:this._deleteFileEndpointStore,cors:this._options.cors,log:qq.bind(e.log,e),onDelete:function(t){e._onDelete(t),e._options.callbacks.onDelete(t)},onDeleteComplete:function(t,n,i){e._onDeleteComplete(t,n,i),e._options.callbacks.onDeleteComplete(t,n,i)}})},_createPasteHandler:function(){var e=this;return new qq.PasteSupport({targetElement:this._options.paste.targetElement,callbacks:{log:qq.bind(e.log,e),pasteReceived:function(t){e._handleCheckedCallback({name:"onPasteReceived",callback:qq.bind(e._options.callbacks.onPasteReceived,e,t),onSuccess:qq.bind(e._handlePasteSuccess,e,t),identifier:"pasted image"})}}})},_createStore:function(e,t){var n={},i=e,o={},r=t,a=function(e){return qq.isObject(e)?qq.extend({},e):e},s=function(){return qq.isFunction(r)?r():r},u=function(e,t){r&&qq.isObject(t)&&qq.extend(t,s()),o[e]&&qq.extend(t,o[e])};return{set:function(e,t){null==t?(n={},i=a(e)):n[t]=a(e)},get:function(e){var t;return t=null!=e&&n[e]?n[e]:a(i),u(e,t),a(t)},addReadOnly:function(e,t){qq.isObject(n)&&(null===e?qq.isFunction(t)?r=t:(r=r||{},qq.extend(r,t)):(o[e]=o[e]||{},qq.extend(o[e],t)))},remove:function(e){return delete n[e]},reset:function(){n={},o={},i=e}}},_createUploadDataTracker:function(){var e=this;return new qq.UploadData({getName:function(t){return e.getName(t)},getUuid:function(t){return e.getUuid(t)},getSize:function(t){return e.getSize(t)},onStatusChange:function(t,n,i){e._onUploadStatusChange(t,n,i),e._options.callbacks.onStatusChange(t,n,i),e._maybeAllComplete(t,i),e._totalProgress&&setTimeout(function(){e._totalProgress.onStatusChange(t,n,i)},0)}})},_createUploadButton:function(e){function t(){return!!qq.supportedFeatures.ajaxUploading&&(!(i._options.workarounds.iosEmptyVideos&&qq.ios()&&!qq.ios6()&&i._isAllowedExtension(r,".mov"))&&(void 0===e.multiple?i._options.multiple:e.multiple))}var n,i=this,o=e.accept||this._options.validation.acceptFiles,r=e.allowedExtensions||this._options.validation.allowedExtensions;return n=new qq.UploadButton({acceptFiles:o,element:e.element,focusClass:this._options.classes.buttonFocus,folders:e.folders,hoverClass:this._options.classes.buttonHover,ios8BrowserCrashWorkaround:this._options.workarounds.ios8BrowserCrash,multiple:t(),name:this._options.request.inputName,onChange:function(e){i._onInputChange(e)},title:null==e.title?this._options.text.fileInputTitle:e.title}),this._disposeSupport.addDisposer(function(){n.dispose()}),i._buttons.push(n),n},_createUploadHandler:function(e,t){var n=this,i={},o={debug:this._options.debug,maxConnections:this._options.maxConnections,cors:this._options.cors,paramsStore:this._paramsStore,endpointStore:this._endpointStore,chunking:this._options.chunking,resume:this._options.resume,blobs:this._options.blobs,log:qq.bind(n.log,n),preventRetryParam:this._options.retry.preventRetryResponseProperty,onProgress:function(e,t,o,r){o<0||r<0||(i[e]?i[e].loaded===o&&i[e].total===r||(n._onProgress(e,t,o,r),n._options.callbacks.onProgress(e,t,o,r)):(n._onProgress(e,t,o,r),n._options.callbacks.onProgress(e,t,o,r)),i[e]={loaded:o,total:r})},onComplete:function(e,t,o,r){delete i[e];var a,s=n.getUploads({id:e}).status;s!==qq.status.UPLOAD_SUCCESSFUL&&s!==qq.status.UPLOAD_FAILED&&(a=n._onComplete(e,t,o,r),a instanceof qq.Promise?a.done(function(){n._options.callbacks.onComplete(e,t,o,r)}):n._options.callbacks.onComplete(e,t,o,r))},onCancel:function(e,t,i){var o=new qq.Promise;return n._handleCheckedCallback({name:"onCancel",callback:qq.bind(n._options.callbacks.onCancel,n,e,t),onFailure:o.failure,onSuccess:function(){i.then(function(){n._onCancel(e,t)}),o.success()},identifier:e}),o},onUploadPrep:qq.bind(this._onUploadPrep,this),onUpload:function(e,t){n._onUpload(e,t);var i=n._options.callbacks.onUpload(e,t);return qq.isGenericPromise(i)?(n.log(qq.format("onUpload for {} returned a Promise - waiting for resolution.",e)),i):(new qq.Promise).success()},onUploadChunk:function(e,t,i){n._onUploadChunk(e,i);var o=n._options.callbacks.onUploadChunk(e,t,i);return qq.isGenericPromise(o)?(n.log(qq.format("onUploadChunk for {}.{} returned a Promise - waiting for resolution.",e,i.partIndex)),o):(new qq.Promise).success()},onUploadChunkSuccess:function(e,t,i,o){n._onUploadChunkSuccess(e,t),n._options.callbacks.onUploadChunkSuccess.apply(n,arguments)},onResume:function(e,t,i,o){return n._options.callbacks.onResume(e,t,i,o)},onAutoRetry:function(e,t,i,o){return n._onAutoRetry.apply(n,arguments)},onUuidChanged:function(e,t){n.log("Server requested UUID change from '"+n.getUuid(e)+"' to '"+t+"'"),n.setUuid(e,t)},getName:qq.bind(n.getName,n),getUuid:qq.bind(n.getUuid,n),getSize:qq.bind(n.getSize,n),setSize:qq.bind(n._setSize,n),getDataByUuid:function(e){return n.getUploads({uuid:e})},isQueued:function(e){var t=n.getUploads({id:e}).status;return t===qq.status.QUEUED||t===qq.status.SUBMITTED||t===qq.status.UPLOAD_RETRYING||t===qq.status.PAUSED},getIdsInProxyGroup:n._uploadData.getIdsInProxyGroup,getIdsInBatch:n._uploadData.getIdsInBatch,isInProgress:function(e){return n.getUploads({id:e}).status===qq.status.UPLOADING},getCustomResumeData:qq.bind(n._getCustomResumeData,n),setStatus:function(e,t){n._uploadData.setStatus(e,t)}};return qq.each(this._options.request,function(e,t){o[e]=t}),o.customHeaders=this._customHeadersStore,e&&qq.each(e,function(e,t){o[e]=t}),new qq.UploadHandlerController(o,t)},_fileOrBlobRejected:function(e){this._netUploadedOrQueued--,this._uploadData.setStatus(e,qq.status.REJECTED)},_formatSize:function(e){if(0===e)return e+this._options.text.sizeSymbols[0];var t=-1;do e/=1e3,t++;while(e>999);return Math.max(e,.1).toFixed(1)+this._options.text.sizeSymbols[t]},_generateExtraButtonSpecs:function(){var e=this;this._extraButtonSpecs={},qq.each(this._options.extraButtons,function(t,n){var i=n.multiple,o=qq.extend({},e._options.validation,!0),r=qq.extend({},n);void 0===i&&(i=e._options.multiple),r.validation&&qq.extend(o,n.validation,!0),qq.extend(r,{multiple:i,validation:o},!0),e._initExtraButton(r)})},_getButton:function(e){var t=this._extraButtonSpecs[e];return t?t.element:e===this._defaultButtonId?this._options.button:void 0},_getButtonId:function(e){var t,n,i=e;if(i instanceof qq.BlobProxy&&(i=i.referenceBlob),i&&!qq.isBlob(i)){if(qq.isFile(i))return i.qqButtonId;if("input"===i.tagName.toLowerCase()&&"file"===i.type.toLowerCase())return i.getAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME);if(t=i.getElementsByTagName("input"),qq.each(t,function(e,t){if("file"===t.getAttribute("type"))return n=t,!1}),n)return n.getAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME)}},_getCustomResumeData:function(e){return this._customResumeDataStore.get(e)},_getNotFinished:function(){return this._uploadData.retrieve({status:[qq.status.UPLOADING,qq.status.UPLOAD_RETRYING,qq.status.QUEUED,qq.status.SUBMITTING,qq.status.SUBMITTED,qq.status.PAUSED]}).length},_getValidationBase:function(e){var t=this._extraButtonSpecs[e];return t?t.validation:this._options.validation},_getValidationDescriptor:function(e){return e.file instanceof qq.BlobProxy?{name:qq.getFilename(e.file.referenceBlob),size:e.file.referenceBlob.size}:{name:this.getUploads({id:e.id}).name,size:this.getUploads({id:e.id}).size}},_getValidationDescriptors:function(e){var t=this,n=[]
+;return qq.each(e,function(e,i){n.push(t._getValidationDescriptor(i))}),n},_handleCameraAccess:function(){if(this._options.camera.ios&&qq.ios()){var e=this._options.camera.button,t=e?this._getButtonId(e):this._defaultButtonId,n=this._options;t&&t!==this._defaultButtonId&&(n=this._extraButtonSpecs[t]),n.multiple=!1,null===n.validation.acceptFiles?n.validation.acceptFiles="image/*;capture=camera":n.validation.acceptFiles+=",image/*;capture=camera",qq.each(this._buttons,function(e,i){if(i.getButtonId()===t)return i.setMultiple(n.multiple),i.setAcceptFiles(n.acceptFiles),!1})}},_handleCheckedCallback:function(e){var t=this,n=e.callback();return qq.isGenericPromise(n)?(this.log(e.name+" - waiting for "+e.name+" promise to be fulfilled for "+e.identifier),n.then(function(n){t.log(e.name+" promise success for "+e.identifier),e.onSuccess(n)},function(){e.onFailure?(t.log(e.name+" promise failure for "+e.identifier),e.onFailure()):t.log(e.name+" promise failure for "+e.identifier)})):(n!==!1?e.onSuccess(n):e.onFailure?(this.log(e.name+" - return value was 'false' for "+e.identifier+". Invoking failure callback."),e.onFailure()):this.log(e.name+" - return value was 'false' for "+e.identifier+". Will not proceed."),n)},_handleNewFile:function(e,t,n){var i=this,o=qq.getUniqueId(),r=-1,a=qq.getFilename(e),s=e.blob||e,u=this._customNewFileHandler?this._customNewFileHandler:qq.bind(i._handleNewFileGeneric,i);!qq.isInput(s)&&s.size>=0&&(r=s.size),u(s,a,o,r,n,t,this._options.request.uuidName,{uploadData:i._uploadData,paramsStore:i._paramsStore,addFileToHandler:function(e,t){i._handler.add(e,t),i._netUploadedOrQueued++,i._trackButton(e)}})},_handleNewFileGeneric:function(e,t,n,i,o,r){var a=this._uploadData.addFile({uuid:n,name:t,size:i,batchId:r,file:e});this._handler.add(a,e),this._trackButton(a),this._netUploadedOrQueued++,o.push({id:a,file:e})},_handlePasteSuccess:function(e,t){var n=e.type.split("/")[1],i=t;null==i&&(i=this._options.paste.defaultName),i+="."+n,this.addFiles({name:i,blob:e})},_handleDeleteSuccess:function(e){if(this.getUploads({id:e}).status!==qq.status.DELETED){var t=this.getName(e);this._netUploadedOrQueued--,this._netUploaded--,this._handler.expunge(e),this._uploadData.setStatus(e,qq.status.DELETED),this.log("Delete request for '"+t+"' has succeeded.")}},_handleDeleteFailed:function(e,t){var n=this.getName(e);this._uploadData.setStatus(e,qq.status.DELETE_FAILED),this.log("Delete request for '"+n+"' has failed.","error"),t&&void 0!==t.withCredentials?this._options.callbacks.onError(e,n,"Delete request failed with response code "+t.status,t):this._options.callbacks.onError(e,n,"Delete request failed",t)},_initExtraButton:function(e){var t=this._createUploadButton({accept:e.validation.acceptFiles,allowedExtensions:e.validation.allowedExtensions,element:e.element,folders:e.folders,multiple:e.multiple,title:e.fileInputTitle});this._extraButtonSpecs[t.getButtonId()]=e},_initFormSupportAndParams:function(){this._formSupport=qq.FormSupport&&new qq.FormSupport(this._options.form,qq.bind(this.uploadStoredFiles,this),qq.bind(this.log,this)),this._formSupport&&this._formSupport.attachedToForm?(this._paramsStore=this._createStore(this._options.request.params,this._formSupport.getFormInputsAsObject),this._options.autoUpload=this._formSupport.newAutoUpload,this._formSupport.newEndpoint&&(this._options.request.endpoint=this._formSupport.newEndpoint)):this._paramsStore=this._createStore(this._options.request.params)},_isDeletePossible:function(){return!(!qq.DeleteFileAjaxRequester||!this._options.deleteFile.enabled)&&(!this._options.cors.expected||(!!qq.supportedFeatures.deleteFileCorsXhr||!(!qq.supportedFeatures.deleteFileCorsXdr||!this._options.cors.allowXdr)))},_isAllowedExtension:function(e,t){var n=!1;return!e.length||(qq.each(e,function(e,i){if(qq.isString(i)){var o=new RegExp("\\."+i+"$","i");if(null!=t.match(o))return n=!0,!1}}),n)},_itemError:function(e,t,n){function i(e,t){a=a.replace(e,t)}var o,r,a=this._options.messages[e],s=[],u=[].concat(t),l=u[0],c=this._getButtonId(n),d=this._getValidationBase(c);return qq.each(d.allowedExtensions,function(e,t){qq.isString(t)&&s.push(t)}),o=s.join(", ").toLowerCase(),i("{file}",this._options.formatFileName(l)),i("{extensions}",o),i("{sizeLimit}",this._formatSize(d.sizeLimit)),i("{minSizeLimit}",this._formatSize(d.minSizeLimit)),r=a.match(/(\{\w+\})/g),null!==r&&qq.each(r,function(e,t){i(t,u[e])}),this._options.callbacks.onError(null,l,a,void 0),a},_manualRetry:function(e,t){if(this._onBeforeManualRetry(e))return this._netUploadedOrQueued++,this._uploadData.setStatus(e,qq.status.UPLOAD_RETRYING),t?t(e):this._handler.retry(e),!0},_maybeAllComplete:function(e,t){var n=this,i=this._getNotFinished();t===qq.status.UPLOAD_SUCCESSFUL?this._succeededSinceLastAllComplete.push(e):t===qq.status.UPLOAD_FAILED&&this._failedSinceLastAllComplete.push(e),0===i&&(this._succeededSinceLastAllComplete.length||this._failedSinceLastAllComplete.length)&&setTimeout(function(){n._onAllComplete(n._succeededSinceLastAllComplete,n._failedSinceLastAllComplete)},0)},_maybeHandleIos8SafariWorkaround:function(){var e=this;if(this._options.workarounds.ios8SafariUploads&&qq.ios800()&&qq.iosSafari())throw setTimeout(function(){window.alert(e._options.messages.unsupportedBrowserIos8Safari)},0),new qq.Error(this._options.messages.unsupportedBrowserIos8Safari)},_maybeParseAndSendUploadError:function(e,t,n,i){if(!n.success)if(i&&200!==i.status&&!n.error)this._options.callbacks.onError(e,t,"XHR returned response code "+i.status,i);else{var o=n.error?n.error:this._options.text.defaultResponseError;this._options.callbacks.onError(e,t,o,i)}},_maybeProcessNextItemAfterOnValidateCallback:function(e,t,n,i,o){var r=this;if(t.length>n)if(e||!this._options.validation.stopOnFirstInvalidFile)setTimeout(function(){var e=r._getValidationDescriptor(t[n]),a=r._getButtonId(t[n].file),s=r._getButton(a);r._handleCheckedCallback({name:"onValidate",callback:qq.bind(r._options.callbacks.onValidate,r,e,s),onSuccess:qq.bind(r._onValidateCallbackSuccess,r,t,n,i,o),onFailure:qq.bind(r._onValidateCallbackFailure,r,t,n,i,o),identifier:"Item '"+e.name+"', size: "+e.size})},0);else if(!e)for(;n0&&this._netUploadedOrQueued+1>n?(this._itemError("retryFailTooManyItems"),!1):(this.log("Retrying upload for '"+t+"' (id: "+e+")..."),!0))):(this.log("'"+e+"' is not a valid file ID","error"),!1)},_onCancel:function(e,t){this._netUploadedOrQueued--,clearTimeout(this._retryTimeouts[e]);var n=qq.indexOf(this._storedIds,e);!this._options.autoUpload&&n>=0&&this._storedIds.splice(n,1),this._uploadData.setStatus(e,qq.status.CANCELED)},_onComplete:function(e,t,n,i){return n.success?(n.thumbnailUrl&&(this._thumbnailUrls[e]=n.thumbnailUrl),this._netUploaded++,this._uploadData.setStatus(e,qq.status.UPLOAD_SUCCESSFUL)):(this._netUploadedOrQueued--,this._uploadData.setStatus(e,qq.status.UPLOAD_FAILED),n[this._options.retry.preventRetryResponseProperty]===!0&&(this._preventRetries[e]=!0)),this._maybeParseAndSendUploadError(e,t,n,i),!!n.success},_onDelete:function(e){this._uploadData.setStatus(e,qq.status.DELETING)},_onDeleteComplete:function(e,t,n){this.getName(e);n?this._handleDeleteFailed(e,t):this._handleDeleteSuccess(e)},_onInputChange:function(e){var t;if(qq.supportedFeatures.ajaxUploading){for(t=0;t0&&this.addFiles(e);qq.each(this._buttons,function(e,t){t.reset()})},_onProgress:function(e,t,n,i){this._totalProgress&&this._totalProgress.onIndividualProgress(e,n,i)},_onSubmit:function(e,t){},_onSubmitCallbackSuccess:function(e,t){this._onSubmit.apply(this,arguments),this._uploadData.setStatus(e,qq.status.SUBMITTED),this._onSubmitted.apply(this,arguments),this._options.autoUpload?(this._options.callbacks.onSubmitted.apply(this,arguments),this._uploadFile(e)):(this._storeForLater(e),this._options.callbacks.onSubmitted.apply(this,arguments))},_onSubmitDelete:function(e,t,n){var i,o=this.getUuid(e);return t&&(i=qq.bind(t,this,e,o,n)),this._isDeletePossible()?(this._handleCheckedCallback({name:"onSubmitDelete",callback:qq.bind(this._options.callbacks.onSubmitDelete,this,e),onSuccess:i||qq.bind(this._deleteHandler.sendDelete,this,e,o,n),identifier:e}),!0):(this.log("Delete request ignored for ID "+e+", delete feature is disabled or request not possible due to CORS on a user agent that does not support pre-flighting.","warn"),!1)},_onSubmitted:function(e){},_onTotalProgress:function(e,t){this._options.callbacks.onTotalProgress(e,t)},_onUploadPrep:function(e){},_onUpload:function(e,t){this._uploadData.setStatus(e,qq.status.UPLOADING)},_onUploadChunk:function(e,t){},_onUploadChunkSuccess:function(e,t){!this._preventRetries[e]&&this._options.retry.enableAuto&&(this._autoRetries[e]=0)},_onUploadStatusChange:function(e,t,n){n===qq.status.PAUSED&&clearTimeout(this._retryTimeouts[e])},_onValidateBatchCallbackFailure:function(e){var t=this;qq.each(e,function(e,n){t._fileOrBlobRejected(n.id)})},_onValidateBatchCallbackSuccess:function(e,t,n,i,o){var r,a=this._currentItemLimit,s=this._netUploadedOrQueued;0===a||s<=a?t.length>0?this._handleCheckedCallback({name:"onValidate",callback:qq.bind(this._options.callbacks.onValidate,this,e[0],o),onSuccess:qq.bind(this._onValidateCallbackSuccess,this,t,0,n,i),onFailure:qq.bind(this._onValidateCallbackFailure,this,t,0,n,i),identifier:"Item '"+t[0].file.name+"', size: "+t[0].file.size}):this._itemError("noFilesError"):(this._onValidateBatchCallbackFailure(t),r=this._options.messages.tooManyItemsError.replace(/\{netItems\}/g,s).replace(/\{itemLimit\}/g,a),this._batchError(r))},_onValidateCallbackFailure:function(e,t,n,i){var o=t+1;this._fileOrBlobRejected(e[t].id,e[t].file.name),this._maybeProcessNextItemAfterOnValidateCallback(!1,e,o,n,i)},_onValidateCallbackSuccess:function(e,t,n,i){var o=this,r=t+1,a=this._getValidationDescriptor(e[t]);this._validateFileOrBlobData(e[t],a).then(function(){o._upload(e[t].id,n,i),o._maybeProcessNextItemAfterOnValidateCallback(!0,e,r,n,i)},function(){o._maybeProcessNextItemAfterOnValidateCallback(!1,e,r,n,i)})},_prepareItemsForUpload:function(e,t,n){if(0===e.length)return void this._itemError("noFilesError");var i=this._getValidationDescriptors(e),o=this._getButtonId(e[0].file),r=this._getButton(o);this._handleCheckedCallback({name:"onValidateBatch",callback:qq.bind(this._options.callbacks.onValidateBatch,this,i,r),onSuccess:qq.bind(this._onValidateBatchCallbackSuccess,this,i,e,t,n,r),onFailure:qq.bind(this._onValidateBatchCallbackFailure,this,e),identifier:"batch validation"})},_preventLeaveInProgress:function(){var e=this;this._disposeSupport.attach(window,"beforeunload",function(t){if(e.getInProgress())return t=t||window.event,t.returnValue=e._options.messages.onLeave,e._options.messages.onLeave})},_refreshSessionData:function(){var e=this,t=this._options.session;qq.Session&&null!=this._options.session.endpoint&&(this._session||(qq.extend(t,{cors:this._options.cors}),t.log=qq.bind(this.log,this),t.addFileRecord=qq.bind(this._addCannedFile,this),this._session=new qq.Session(t)),setTimeout(function(){e._session.refresh().then(function(t,n){e._sessionRequestComplete(),e._options.callbacks.onSessionRequestComplete(t,!0,n)},function(t,n){e._options.callbacks.onSessionRequestComplete(t,!1,n)})},0))},_sessionRequestComplete:function(){},_setSize:function(e,t){this._uploadData.updateSize(e,t),this._totalProgress&&this._totalProgress.onNewSize(e)},_shouldAutoRetry:function(e){var t=this._uploadData.retrieve({id:e});return!!(!this._preventRetries[e]&&this._options.retry.enableAuto&&t.status!==qq.status.PAUSED&&(void 0===this._autoRetries[e]&&(this._autoRetries[e]=0),this._autoRetries[e]0&&s.sizeLimit&&r>s.sizeLimit?(this._itemError("sizeError",o,i),u.failure()):r>0&&r=0}function n(e){var t=!1;return qq.each(t,function(e,n){if(qq.indexOf(["Accept","Accept-Language","Content-Language","Content-Type"],n)<0)return t=!0,!1}),t}function i(e){return S.cors.expected&&void 0===e.withCredentials}function o(){var e;return(window.XMLHttpRequest||window.ActiveXObject)&&(e=qq.createXhrInstance(),void 0===e.withCredentials&&(e=new XDomainRequest,e.onload=function(){},e.onerror=function(){},e.ontimeout=function(){},e.onprogress=function(){})),e}function r(e,t){var n=y[e]&&y[e].xhr;return n||(n=t?t:S.cors.expected?o():qq.createXhrInstance(),y[e].xhr=n),n}function a(e){var t,n=qq.indexOf(b,e),i=S.maxConnections;delete y[e],b.splice(n,1),b.length>=i&&n=0?o.send(qq.obj2url(s,"")):s&&S.contentType&&S.contentType.toLowerCase().indexOf("application/json")>=0?o.send(JSON.stringify(s)):o.send(s),o}function c(e,t,n){var i=S.endpointStore.get(e),o=y[e].addToPath;return void 0!=o&&(i+="/"+o),v&&t&&(i=qq.obj2url(t,i)),n&&(i=qq.obj2url(n,i)),i}function d(e){return function(){4===r(e).readyState&&s(e)}}function p(e){var t=S.onProgress;t&&(r(e).upload.onprogress=function(n){n.lengthComputable&&t(e,n.loaded,n.total)})}function h(e){return function(){s(e)}}function q(e){return function(){s(e,!0)}}function f(e){var o=r(e),a=S.customHeaders,s=y[e].additionalHeaders||{},u=S.method,l={};i(o)||(S.acceptHeader&&o.setRequestHeader("Accept",S.acceptHeader),S.allowXRequestedWithAndCacheControl&&(S.cors.expected&&t()&&!n(a)||(o.setRequestHeader("X-Requested-With","XMLHttpRequest"),o.setRequestHeader("Cache-Control","no-cache"))),!S.contentType||"POST"!==u&&"PUT"!==u||o.setRequestHeader("Content-Type",S.contentType),qq.extend(l,qq.isFunction(a)?a(e):a),qq.extend(l,s),qq.each(l,function(e,t){o.setRequestHeader(e,t)}))}function m(e){return qq.indexOf(S.successfulResponseCodes[S.method],e)>=0}function g(e,t,n,i,o,r,a){if(y[e]={addToPath:n,additionalParams:i,additionalQueryParams:o,additionalHeaders:r,payload:a},b.push(e)<=S.maxConnections)return l(e,t)}var _,v,b=[],y={},S={acceptHeader:null,validMethods:["PATCH","POST","PUT"],method:"POST",contentType:"application/x-www-form-urlencoded",maxConnections:3,customHeaders:{},endpointStore:{},paramsStore:{},mandatedParams:{},allowXRequestedWithAndCacheControl:!0,successfulResponseCodes:{DELETE:[200,202,204],PATCH:[200,201,202,203,204],POST:[200,201,202,203,204],PUT:[200,201,202,203,204],GET:[200]},cors:{expected:!1,sendCredentials:!1},log:function(e,t){},onSend:function(e){},onComplete:function(e,t,n){},onProgress:null};if(qq.extend(S,e),_=S.log,qq.indexOf(S.validMethods,S.method)<0)throw new Error("'"+S.method+"' is not a supported method for this type of request!");v="GET"===S.method||"DELETE"===S.method,qq.extend(this,{initTransport:function(e){var t,n,i,o,r,a;return{withPath:function(e){return t=e,this},withParams:function(e){return n=e,this},withQueryParams:function(e){return a=e,this},withHeaders:function(e){return i=e,this},withPayload:function(e){return o=e,this},withCacheBuster:function(){return r=!0,this},send:function(s){return r&&qq.indexOf(["GET","DELETE"],S.method)>=0&&(n.qqtimestamp=(new Date).getTime()),g(e,s,t,n,a,i,o)}}},canceled:function(e){a(e)}})},qq.UploadHandler=function(e){"use strict";var t=e.proxy,n={},i=t.onCancel,o=t.getName;qq.extend(this,{add:function(e,t){n[e]=t,n[e].temp={}},cancel:function(e){var t=this,r=new qq.Promise;i(e,o(e),r).then(function(){t.isValid(e)&&(n[e].canceled=!0,t.expunge(e)),r.success()})},expunge:function(e){delete n[e]},getThirdPartyFileId:function(e){return n[e].key},isValid:function(e){return void 0!==n[e]},reset:function(){n={}},_getFileState:function(e){return n[e]},_setThirdPartyFileId:function(e,t){n[e].key=t},_wasCanceled:function(e){return!!n[e].canceled}})},qq.UploadHandlerController=function(e,t){"use strict";var n,i,o,r=this,a=!1,s=!1,u={paramsStore:{},maxConnections:3,chunking:{enabled:!1,multiple:{enabled:!1}},log:function(e,t){},onProgress:function(e,t,n,i){},onComplete:function(e,t,n,i){},onCancel:function(e,t){},onUploadPrep:function(e){},onUpload:function(e,t){},onUploadChunk:function(e,t,n){},onUploadChunkSuccess:function(e,t,n,i){},onAutoRetry:function(e,t,n,i){},onResume:function(e,t,n,i){},onUuidChanged:function(e,t){},getName:function(e){},setSize:function(e,t){},isQueued:function(e){},getIdsInProxyGroup:function(e){},getIdsInBatch:function(e){},isInProgress:function(e){}},l={done:function(e,t,n,i){var r=o._getChunkData(e,t);o._getFileState(e).attemptingResume=!1,delete o._getFileState(e).temp.chunkProgress[t],o._getFileState(e).loaded+=r.size,u.onUploadChunkSuccess(e,o._getChunkDataForCallback(r),n,i)},finalize:function(e){var t=u.getSize(e),n=u.getName(e);i("All chunks have been uploaded for "+e+" - finalizing...."),o.finalizeChunks(e).then(function(r,a){i("Finalize successful for "+e);var s=p.normalizeResponse(r,!0);u.onProgress(e,n,t,t),o._maybeDeletePersistedChunkData(e),p.cleanup(e,s,a)},function(t,o){var r=p.normalizeResponse(t,!1);i("Problem finalizing chunks for file ID "+e+" - "+r.error,"error"),(r.reset||o&&u.chunking.success.resetOnStatus.indexOf(o.status)>=0)&&l.reset(e),u.onAutoRetry(e,n,r,o)||p.cleanup(e,r,o)})},handleFailure:function(e,t,n,r){var a=u.getName(t);i("Chunked upload request failed for "+t+", chunk "+e),o.clearCachedChunk(t,e);var d,h=p.normalizeResponse(n,!1);if(h.reset)l.reset(t);else{var q=o._getFileState(t).chunking.inProgress;d=q?qq.indexOf(q,e):-1,d>=0&&(o._getFileState(t).chunking.inProgress.splice(d,1),o._getFileState(t).chunking.remaining.unshift(e))}o._getFileState(t).temp.ignoreFailure||(s&&(o._getFileState(t).temp.ignoreFailure=!0,i(qq.format("Going to attempt to abort these chunks: {}. These are currently in-progress: {}.",JSON.stringify(Object.keys(o._getXhrs(t))),JSON.stringify(o._getFileState(t).chunking.inProgress))),qq.each(o._getXhrs(t),function(e,n){i(qq.format("Attempting to abort file {}.{}. XHR readyState {}. ",t,e,n.readyState)),n.abort(),n._cancelled=!0}),o.moveInProgressToRemaining(t),c.free(t,!0)),u.onAutoRetry(t,a,h,r)||p.cleanup(t,h,r))},hasMoreParts:function(e){return!!o._getFileState(e).chunking.remaining.length},nextPart:function(e){var t=o._getFileState(e).chunking.remaining.shift();return t>=o._getTotalChunks(e)&&(t=null),t},reset:function(e){i("Server or callback has ordered chunking effort to be restarted on next attempt for item ID "+e,"error"),o._maybeDeletePersistedChunkData(e),o.reevaluateChunking(e),o._getFileState(e).loaded=0,o._getFileState(e).attemptingResume=!1},sendNext:function(e){var t=u.getSize(e),n=u.getName(e),r=l.nextPart(e),a=o._getChunkData(e,r),d=o._getFileState(e),h=d.attemptingResume,q=d.chunking.inProgress||[];if(null==d.loaded&&(d.loaded=0),h&&u.onResume(e,n,a,d.customResumeData)===!1&&(l.reset(e),r=l.nextPart(e),a=o._getChunkData(e,r),h=!1),null==r&&0===q.length)l.finalize(e);else{q.push(r),o._getFileState(e).chunking.inProgress=q,s&&c.open(e,r),s&&c.available()&&o._getFileState(e).chunking.remaining.length&&l.sendNext(e),0===a.blob.size&&(i(qq.format("Chunk {} for file {} will not be uploaded, zero sized chunk.",r,e),"error"),l.handleFailure(r,e,"File is no longer available",null));u.onUploadChunk(e,n,o._getChunkDataForCallback(a)).then(function(n){if(u.isInProgress(e)){i(qq.format("Sending chunked upload request for item {}.{}, bytes {}-{} of {}.",e,r,a.start+1,a.end,t));var s={chunkIdx:r,id:e,overrides:n,resuming:h};o.uploadChunk(s).then(function(t,n){i("Chunked upload request succeeded for "+e+", chunk "+r),o.clearCachedChunk(e,r);var a=o._getFileState(e).chunking.inProgress||[],s=p.normalizeResponse(t,!0),u=qq.indexOf(a,r);i(qq.format("Chunk {} for file {} uploaded successfully.",r,e)),l.done(e,r,s,n),u>=0&&a.splice(u,1),o._maybePersistChunkedState(e),l.hasMoreParts(e)||0!==a.length?l.hasMoreParts(e)?l.sendNext(e):i(qq.format("File ID {} has no more chunks to send and these chunk indexes are still marked as in-progress: {}",e,JSON.stringify(a))):l.finalize(e)},function(t,n){l.handleFailure(r,e,t,n)}).done(function(){o.clearXhr(e,r)})}else i(qq.format("Not sending chunked upload request for item {}.{} - no longer in progress.",e,r))},function(t){l.handleFailure(r,e,t,null)})}}},c={_open:[],_openChunks:{},_waiting:[],available:function(){var e=u.maxConnections,t=0,n=0;return qq.each(c._openChunks,function(e,i){t++,n+=i.length}),e-(c._open.length-t+n)},free:function(e,t){var n,r=!t,a=qq.indexOf(c._waiting,e),s=qq.indexOf(c._open,e);delete c._openChunks[e],p.getProxyOrBlob(e)instanceof qq.BlobProxy&&(i("Generated blob upload has ended for "+e+", disposing generated blob."),delete o._getFileState(e).file),a>=0?c._waiting.splice(a,1):r&&s>=0&&(c._open.splice(s,1),n=c._waiting.shift(),n>=0&&(c._open.push(n),p.start(n)))},getWaitingOrConnected:function(){var e=[];return qq.each(c._openChunks,function(t,n){n&&n.length&&e.push(parseInt(t))}),qq.each(c._open,function(t,n){c._openChunks[n]||e.push(parseInt(n))}),e=e.concat(c._waiting)},isUsingConnection:function(e){return qq.indexOf(c._open,e)>=0},open:function(e,t){return null==t&&c._waiting.push(e),!!c.available()&&(null==t?(c._waiting.pop(),c._open.push(e)):function(){var n=c._openChunks[e]||[];n.push(t),c._openChunks[e]=n}(),!0)},reset:function(){c._waiting=[],c._open=[]}},d={send:function(e,t){var n=o._getFileState(e);if(!n)return void i("Ignoring send request as this upload may have been cancelled, File ID "+e,"warn");n.loaded=0,i("Sending simple upload request for "+e),o.uploadFile(e).then(function(n,o){i("Simple upload request succeeded for "+e)
+;var r=p.normalizeResponse(n,!0),a=u.getSize(e);u.onProgress(e,t,a,a),p.maybeNewUuid(e,r),p.cleanup(e,r,o)},function(n,o){i("Simple upload request failed for "+e);var r=p.normalizeResponse(n,!1);u.onAutoRetry(e,t,r,o)||p.cleanup(e,r,o)})}},p={cancel:function(e){i("Cancelling "+e),u.paramsStore.remove(e),c.free(e)},cleanup:function(e,t,n){var i=u.getName(e);u.onComplete(e,i,t,n),o._getFileState(e)&&o._clearXhrs&&o._clearXhrs(e),c.free(e)},getProxyOrBlob:function(e){return o.getProxy&&o.getProxy(e)||o.getFile&&o.getFile(e)},initHandler:function(){o=new(t?qq[t]:qq.traditional)[(qq.supportedFeatures.ajaxUploading?"Xhr":"Form")+"UploadHandler"](u,{getCustomResumeData:u.getCustomResumeData,getDataByUuid:u.getDataByUuid,getName:u.getName,getSize:u.getSize,getUuid:u.getUuid,log:i,onCancel:u.onCancel,onProgress:u.onProgress,onUuidChanged:u.onUuidChanged,onFinalizing:function(e){u.setStatus(e,qq.status.UPLOAD_FINALIZING)}}),o._removeExpiredChunkingRecords&&o._removeExpiredChunkingRecords()},isDeferredEligibleForUpload:function(e){return u.isQueued(e)},maybeDefer:function(e,t){return t&&!o.getFile(e)&&t instanceof qq.BlobProxy?(u.onUploadPrep(e),i("Attempting to generate a blob on-demand for "+e),t.create().then(function(t){i("Generated an on-demand blob for "+e),o.updateBlob(e,t),u.setSize(e,t.size),o.reevaluateChunking(e),p.maybeSendDeferredFiles(e)},function(t){var o={};t&&(o.error=t),i(qq.format("Failed to generate blob for ID {}. Error message: {}.",e,t),"error"),u.onComplete(e,u.getName(e),qq.extend(o,n),null),p.maybeSendDeferredFiles(e),c.free(e)}),!1):p.maybeSendDeferredFiles(e)},maybeSendDeferredFiles:function(e){var t=u.getIdsInProxyGroup(e),n=!1;return t&&t.length?(i("Maybe ready to upload proxy group file "+e),qq.each(t,function(t,i){if(p.isDeferredEligibleForUpload(i)&&o.getFile(i))n=i===e,p.now(i);else if(p.isDeferredEligibleForUpload(i))return!1})):(n=!0,p.now(e)),n},maybeNewUuid:function(e,t){void 0!==t.newUuid&&u.onUuidChanged(e,t.newUuid)},normalizeResponse:function(e,t){var n=e;return qq.isObject(e)||(n={},qq.isString(e)&&!t&&(n.error=e)),n.success=t,n},now:function(e){var t=u.getName(e);if(!r.isValid(e))throw new qq.Error(e+" is not a valid file ID to upload!");u.onUpload(e,t).then(function(n){n&&n.pause?(u.setStatus(e,qq.status.PAUSED),o.pause(e),c.free(e)):a&&o._shouldChunkThisFile(e)?l.sendNext(e):d.send(e,t)},function(n){if(n=n||{},i(e+" upload start aborted due to rejected onUpload Promise - details: "+n,"error"),!u.onAutoRetry(e,t,n.responseJSON||{})){var o=p.normalizeResponse(n.responseJSON,!1);p.cleanup(e,o)}})},start:function(e){var t=p.getProxyOrBlob(e);return t?p.maybeDefer(e,t):(p.now(e),!0)}};qq.extend(this,{add:function(e,t){o.add.apply(this,arguments)},upload:function(e){return!!c.open(e)&&p.start(e)},retry:function(e){return s&&(o._getFileState(e).temp.ignoreFailure=!1),c.isUsingConnection(e)?p.start(e):r.upload(e)},cancel:function(e){var t=o.cancel(e);qq.isGenericPromise(t)?t.then(function(){p.cancel(e)}):t!==!1&&p.cancel(e)},cancelAll:function(){var e,t=c.getWaitingOrConnected();if(t.length)for(e=t.length-1;e>=0;e--)r.cancel(t[e]);c.reset()},getFile:function(e){return o.getProxy&&o.getProxy(e)?o.getProxy(e).referenceBlob:o.getFile&&o.getFile(e)},isProxied:function(e){return!(!o.getProxy||!o.getProxy(e))},getInput:function(e){if(o.getInput)return o.getInput(e)},reset:function(){i("Resetting upload handler"),r.cancelAll(),c.reset(),o.reset()},expunge:function(e){if(r.isValid(e))return o.expunge(e)},isValid:function(e){return o.isValid(e)},hasResumeRecord:function(e){var t=o.isValid(e)&&o._getLocalStorageId&&o._getLocalStorageId(e);return!!t&&!!localStorage.getItem(t)},getResumableFilesData:function(){return o.getResumableFilesData?o.getResumableFilesData():[]},getThirdPartyFileId:function(e){if(r.isValid(e))return o.getThirdPartyFileId(e)},pause:function(e){return!!(r.isResumable(e)&&o.pause&&r.isValid(e)&&o.pause(e))&&(c.free(e),o.moveInProgressToRemaining(e),!0)},isAttemptingResume:function(e){return!!o.isAttemptingResume&&o.isAttemptingResume(e)},isResumable:function(e){return!!o.isResumable&&o.isResumable(e)}}),qq.extend(u,e),i=u.log,a=u.chunking.enabled&&qq.supportedFeatures.chunking,s=a&&u.chunking.concurrent.enabled,n=function(){var e={};return e[u.preventRetryParam]=!0,e}(),p.initHandler()},qq.WindowReceiveMessage=function(e){"use strict";var t={log:function(e,t){}},n={};qq.extend(t,e),qq.extend(this,{receiveMessage:function(e,t){var i=function(e){t(e.data)};window.postMessage?n[e]=qq(window).attach("message",i):log("iframe message passing not supported in this browser!","error")},stopReceivingMessages:function(e){if(window.postMessage){var t=n[e];t&&t()}}})},qq.FormUploadHandler=function(e){"use strict";function t(e){delete c[e],p&&(clearTimeout(d[e]),delete d[e],m.stopReceivingMessages(e));var t=document.getElementById(a._getIframeName(e));t&&(t.setAttribute("src","javascript:false;"),qq(t).remove())}function n(e){return e.split("_")[0]}function i(e){var t=qq.toElement("");return t.setAttribute("id",e),t.style.display="none",document.body.appendChild(t),t}function o(e,t){var i=e.id,o=n(i);l[q(o)]=t,c[o]=qq(e).attach("load",function(){a.getInput(o)&&(f("Received iframe load event for CORS upload request (iframe name "+i+")"),d[i]=setTimeout(function(){var e="No valid message received from loaded iframe for iframe name "+i;f(e,"error"),t({error:e})},1e3))}),m.receiveMessage(i,function(e){f("Received the following window message: '"+e+"'");var t,o=(n(i),a._parseJsonResponse(e)),r=o.uuid;r&&l[r]?(f("Handling response for iframe name "+i),clearTimeout(d[i]),delete d[i],a._detachLoadEvent(i),t=l[r],delete l[r],m.stopReceivingMessages(i),t(o)):r||f("'"+e+"' does not contain a UUID - ignoring.")})}var r=e.options,a=this,s=e.proxy,u=qq.getUniqueId(),l={},c={},d={},p=r.isCors,h=r.inputName,q=s.getUuid,f=s.log,m=new qq.WindowReceiveMessage({log:f});qq.extend(this,new qq.UploadHandler(e)),qq.override(this,function(e){return{add:function(t,n){e.add(t,{input:n}),n.setAttribute("name",h),n.parentNode&&qq(n).remove()},expunge:function(n){t(n),e.expunge(n)},isValid:function(t){return e.isValid(t)&&void 0!==a._getFileState(t).input}}}),qq.extend(this,{getInput:function(e){return a._getFileState(e).input},_attachLoadEvent:function(e,t){var n;p?o(e,t):c[e.id]=qq(e).attach("load",function(){if(f("Received response for "+e.id),e.parentNode){try{if(e.contentDocument&&e.contentDocument.body&&"false"==e.contentDocument.body.innerHTML)return}catch(e){f("Error when attempting to access iframe during handling of upload response ("+e.message+")","error"),n={success:!1}}t(n)}})},_createIframe:function(e){return i(a._getIframeName(e))},_detachLoadEvent:function(e){void 0!==c[e]&&(c[e](),delete c[e])},_getIframeName:function(e){return e+"_"+u},_initFormForUpload:function(e){var t=e.method,n=e.endpoint,i=e.params,o=e.paramsInBody,r=e.targetName,a=qq.toElement(""),s=n;return o?qq.obj2Inputs(i,a):s=qq.obj2url(i,n),a.setAttribute("action",s),a.setAttribute("target",r),a.style.display="none",document.body.appendChild(a),a},_parseJsonResponse:function(e){var t={};try{t=qq.parseJson(e)}catch(e){f("Error when attempting to parse iframe upload response ("+e.message+")","error")}return t}})},qq.XhrUploadHandler=function(e){"use strict";function t(e){qq.each(n._getXhrs(e),function(t,i){var o=n._getAjaxRequester(e,t);i.onreadystatechange=null,i.upload.onprogress=null,i.abort(),o&&o.canceled&&o.canceled(e)})}var n=this,i=e.options.namespace,o=e.proxy,r=e.options.chunking,a=function(e){var t=n._getFileState(e);if(t.chunkSize)return t.chunkSize;var i=r.partSize;return qq.isFunction(i)&&(i=i(e,d(e))),t.chunkSize=i,i},s=e.options.resume,u=r&&e.options.chunking.enabled&&qq.supportedFeatures.chunking,l=s&&e.options.resume.enabled&&u&&qq.supportedFeatures.resume,c=o.getName,d=o.getSize,p=o.getUuid,h=o.getEndpoint,q=o.getDataByUuid,f=o.onUuidChanged,m=o.onProgress,g=o.log,_=o.getCustomResumeData;qq.extend(this,new qq.UploadHandler(e)),qq.override(this,function(e){return{add:function(t,i){if(qq.isFile(i)||qq.isBlob(i))e.add(t,{file:i});else{if(!(i instanceof qq.BlobProxy))throw new Error("Passed obj is not a File, Blob, or proxy");e.add(t,{proxy:i})}n._initTempState(t),l&&n._maybePrepareForResume(t)},expunge:function(i){t(i),n._maybeDeletePersistedChunkData(i),n._clearXhrs(i),e.expunge(i)}}}),qq.extend(this,{clearCachedChunk:function(e,t){var i=n._getFileState(e);i&&delete i.temp.cachedChunks[t]},clearXhr:function(e,t){var i=n._getFileState(e).temp;i.xhrs&&delete i.xhrs[t],i.ajaxRequesters&&delete i.ajaxRequesters[t]},finalizeChunks:function(e,t){var i=n._getTotalChunks(e)-1,o=n._getXhr(e,i);return t?(new qq.Promise).success(t(o),o):(new qq.Promise).success({},o)},getFile:function(e){return n.isValid(e)&&n._getFileState(e).file},getProxy:function(e){return n.isValid(e)&&n._getFileState(e).proxy},getResumableFilesData:function(){var e=[];return n._iterateResumeRecords(function(t,i){n.moveInProgressToRemaining(null,i.chunking.inProgress,i.chunking.remaining);var o={name:i.name,remaining:i.chunking.remaining,size:i.size,uuid:i.uuid};i.key&&(o.key=i.key),i.customResumeData&&(o.customResumeData=i.customResumeData),e.push(o)}),e},isAttemptingResume:function(e){return n._getFileState(e).attemptingResume},isResumable:function(e){return!!r&&n.isValid(e)&&!n._getFileState(e).notResumable},moveInProgressToRemaining:function(e,t,i){var o=n._getFileState(e)||{},r=o.chunking||{},a=t||r.inProgress,s=i||r.remaining;a&&(g(qq.format("Moving these chunks from in-progress {}, to remaining.",JSON.stringify(a))),a.reverse(),qq.each(a,function(e,t){s.unshift(t)}),a.length=0)},pause:function(e){if(n.isValid(e))return g(qq.format("Aborting XHR upload for {} '{}' due to pause instruction.",e,c(e))),n._getFileState(e).paused=!0,t(e),!0},reevaluateChunking:function(e){if(r&&n.isValid(e)){var t,i,o=n._getFileState(e);if(delete o.chunking,o.chunking={},t=n._getTotalChunks(e),t>1||r.mandatory){for(o.chunking.enabled=!0,o.chunking.parts=t,o.chunking.remaining=[],i=0;i=o?o:s+i,l=n._getTotalChunks(e),c=this._getFileState(e).temp.cachedChunks,p=c[t]||qq.sliceBlob(r,s,u);return c[t]=p,{part:t,start:s,end:u,count:l,blob:p,size:u-s}},_getChunkDataForCallback:function(e){return{partIndex:e.part,startByte:e.start+1,endByte:e.end,totalParts:e.count}},_getLocalStorageId:function(e){var t=c(e),n=d(e),o=a(e),r=h(e),u=s.customKeys(e),l=qq.format("qq{}resume{}-{}-{}-{}-{}",i,"5.0",t,n,o,r);return u.forEach(function(e){l+="-"+e}),l},_getMimeType:function(e){return n.getFile(e).type},_getPersistableData:function(e){return n._getFileState(e).chunking},_getTotalChunks:function(e){if(r){var t=d(e),n=a(e);return Math.ceil(t/n)}},_getXhr:function(e,t){var i=null==t?-1:t;return n._getFileState(e).temp.xhrs[i]},_getXhrs:function(e){return n._getFileState(e).temp.xhrs},_iterateResumeRecords:function(e){l&&qq.each(localStorage,function(t,n){if(0===t.indexOf(qq.format("qq{}resume",i))){e(t,JSON.parse(n))}})},_initTempState:function(e){n._getFileState(e).temp={ajaxRequesters:{},chunkProgress:{},xhrs:{},cachedChunks:{}}},_markNotResumable:function(e){n._getFileState(e).notResumable=!0},_maybeDeletePersistedChunkData:function(e){var t;return!!(l&&n.isResumable(e)&&(t=n._getLocalStorageId(e),t&&localStorage.getItem(t)))&&(localStorage.removeItem(t),!0)},_maybePrepareForResume:function(e){var t,i,o=n._getFileState(e);l&&void 0===o.key&&(t=n._getLocalStorageId(e),i=localStorage.getItem(t),i&&(i=JSON.parse(i),q(i.uuid)?n._markNotResumable(e):(g(qq.format("Identified file with ID {} and name of {} as resumable.",e,c(e))),f(e,i.uuid),o.key=i.key,o.chunking=i.chunking,o.loaded=i.loaded,o.customResumeData=i.customResumeData,o.attemptingResume=!0,n.moveInProgressToRemaining(e))))},_maybePersistChunkedState:function(e){var t,i,o=n._getFileState(e);if(l&&n.isResumable(e)){var r=_(e);t=n._getLocalStorageId(e),i={name:c(e),size:d(e),uuid:p(e),key:o.key,chunking:o.chunking,loaded:o.loaded,lastUpdated:Date.now()},r&&(i.customResumeData=r);try{localStorage.setItem(t,JSON.stringify(i))}catch(t){g(qq.format("Unable to save resume data for '{}' due to error: '{}'.",e,t.toString()),"warn")}}},_registerProgressHandler:function(e,t,i){var o=n._getXhr(e,t),r=c(e),a={simple:function(t,n){var i=d(e);t===n?m(e,r,i,i):m(e,r,t>=i?i-1:t,i)},chunked:function(o,a){var s=n._getFileState(e).temp.chunkProgress,u=n._getFileState(e).loaded,l=o,c=a,p=d(e),h=l-(c-i),q=u;s[t]=h,qq.each(s,function(e,t){q+=t}),m(e,r,q,p)}};o.upload.onprogress=function(e){if(e.lengthComputable){a[null==i?"simple":"chunked"](e.loaded,e.total)}}},_registerXhr:function(e,t,i,o){var r=null==t?-1:t,a=n._getFileState(e).temp;return a.xhrs=a.xhrs||{},a.ajaxRequesters=a.ajaxRequesters||{},a.xhrs[r]=i,o&&(a.ajaxRequesters[r]=o),i},_removeExpiredChunkingRecords:function(){var e=s.recordsExpireIn;n._iterateResumeRecords(function(t,n){var i=new Date(n.lastUpdated);i.setDate(i.getDate()+e),i.getTime()<=Date.now()&&(g("Removing expired resume record with key "+t),localStorage.removeItem(t))})},_shouldChunkThisFile:function(e){var t=n._getFileState(e);if(t)return t.chunking||n.reevaluateChunking(e),t.chunking.enabled}})},qq.DeleteFileAjaxRequester=function(e){"use strict";function t(){return"POST"===i.method.toUpperCase()?{_method:"DELETE"}:{}}var n,i={method:"DELETE",uuidParamName:"qquuid",endpointStore:{},maxConnections:3,customHeaders:function(e){return{}},paramsStore:{},cors:{expected:!1,sendCredentials:!1},log:function(e,t){},onDelete:function(e){},onDeleteComplete:function(e,t,n){}};qq.extend(i,e),n=qq.extend(this,new qq.AjaxRequester({acceptHeader:"application/json",validMethods:["POST","DELETE"],method:i.method,endpointStore:i.endpointStore,paramsStore:i.paramsStore,mandatedParams:t(),maxConnections:i.maxConnections,customHeaders:function(e){return i.customHeaders.get(e)},log:i.log,onSend:i.onDelete,onComplete:i.onDeleteComplete,cors:i.cors})),qq.extend(this,{sendDelete:function(e,t,o){var r=o||{};i.log("Submitting delete file request for "+e),"DELETE"===i.method?n.initTransport(e).withPath(t).withParams(r).send():(r[i.uuidParamName]=t,n.initTransport(e).withParams(r).send())}})},function(){function e(e){var t,n=e.naturalWidth,i=e.naturalHeight,o=document.createElement("canvas");return n*i>1048576&&(o.width=o.height=1,t=o.getContext("2d"),t.drawImage(e,-n+1,0),0===t.getImageData(0,0,1,1).data[3])}function t(e,t,n){var i,o,r,a,s=document.createElement("canvas"),u=0,l=n,c=n;for(s.width=1,s.height=n,i=s.getContext("2d"),i.drawImage(e,0,0),o=i.getImageData(0,0,1,n).data;c>u;)r=o[4*(c-1)+3],0===r?l=c:u=c,c=l+u>>1;return a=c/n,0===a?1:a}function n(e,t,n,i){var r=document.createElement("canvas"),a=n.mime||"image/jpeg",s=new qq.Promise;return o(e,t,r,n,i).then(function(){s.success(r.toDataURL(a,n.quality||.8))}),s}function i(e){if(!qq.ios())throw new qq.Error("Downsampled dimensions can only be reliably calculated for iOS!");if(e.origHeight*e.origWidth>5241e3)return{newHeight:Math.round(Math.sqrt(5241e3*(e.origHeight/e.origWidth))),newWidth:Math.round(Math.sqrt(5241e3*(e.origWidth/e.origHeight)))}}function o(n,o,s,u,l){var c,d=n.naturalWidth,p=n.naturalHeight,h=u.width,q=u.height,f=s.getContext("2d"),m=new qq.Promise;return f.save(),u.resize?r({blob:o,canvas:s,image:n,imageHeight:p,imageWidth:d,orientation:u.orientation,resize:u.resize,targetHeight:q,targetWidth:h}):(qq.supportedFeatures.unlimitedScaledImageSize||(c=i({origWidth:h,origHeight:q}),c&&(qq.log(qq.format("Had to reduce dimensions due to device limitations from {}w / {}h to {}w / {}h",h,q,c.newWidth,c.newHeight),"warn"),h=c.newWidth,q=c.newHeight)),a(s,h,q,u.orientation),qq.ios()?function(){e(n)&&(d/=2,p/=2);var i,o,r,a=1024,s=document.createElement("canvas"),u=l?t(n,d,p):1,c=Math.ceil(a*h/d),m=Math.ceil(a*q/p/u),g=0,_=0;for(s.width=s.height=a,i=s.getContext("2d");gc&&(u=c,l=s*u/a<<0),d&&l>d&&(l=d,u=a*l/s<<0),i={width:u,height:l},qq.each(t,function(e,t){i[e]=t}),"img"===h?function(){var t=e.src;n(r.srcImage,r.blob,i,p).then(function(n){e.src=n,t===e.src&&e.onload()})}():"canvas"===h&&o(this.srcImage,this.blob,e,i,p),"function"==typeof this.onrender&&this.onrender(e)},qq.MegaPixImage=s}(),qq.ImageGenerator=function(e){"use strict";function t(e){return"img"===e.tagName.toLowerCase()}function n(e){return"canvas"===e.tagName.toLowerCase()}function i(){return void 0!==(new Image).crossOrigin}function o(){var e=document.createElement("canvas");return e.getContext&&e.getContext("2d")}function r(e){var t=e.split("/"),n=t[t.length-1].split("?")[0],i=qq.getExtension(n);switch(i=i&&i.toLowerCase()){case"jpeg":case"jpg":return"image/jpeg";case"png":return"image/png";case"bmp":return"image/bmp";case"gif":return"image/gif";case"tiff":case"tif":return"image/tiff"}}function a(e){var t,n,i,o=document.createElement("a");return o.href=e,t=o.protocol,i=o.port,n=o.hostname,t.toLowerCase()!==window.location.protocol.toLowerCase()||(n.toLowerCase()!==window.location.hostname.toLowerCase()||i!==window.location.port&&!qq.ie())}function s(t,n){t.onload=function(){t.onload=null,t.onerror=null,n.success(t)},t.onerror=function(){t.onload=null,t.onerror=null,e("Problem drawing thumbnail!","error"),n.failure(t,"Problem drawing thumbnail!")}}function u(e,t){e.qqImageRendered=function(){t.success(e)}}function l(i,o){var r=t(i)||n(i);return t(i)?s(i,o):n(i)?u(i,o):(o.failure(i),e(qq.format("Element container of type {} is not supported!",i.tagName),"error")),r}function c(t,n,i){var o=new qq.Promise,r=new qq.Identify(t,e),a=i.maxSize,s=null==i.orient||i.orient,u=function(){n.onerror=null,n.onload=null,e("Could not render preview, file may be too large!","error"),o.failure(n,"Browser cannot render image!")};return r.isPreviewable().then(function(r){var c={parse:function(){return(new qq.Promise).success()}},d=s?new qq.Exif(t,e):c,p=new qq.MegaPixImage(t,u);l(n,o)&&d.parse().then(function(e){var t=e&&e.Orientation;p.render(n,{maxWidth:a,maxHeight:a,orientation:t,mime:r,resize:i.customResizeFunction})},function(t){e(qq.format("EXIF data could not be parsed ({}). Assuming orientation = 1.",t)),p.render(n,{maxWidth:a,maxHeight:a,mime:r,resize:i.customResizeFunction})})},function(){e("Not previewable"),o.failure(n,"Not previewable")}),o}function d(e,t,n,i,o){var s=new Image,u=new qq.Promise;l(s,u),a(e)&&(s.crossOrigin="anonymous"),s.src=e,u.then(function(){l(t,n),new qq.MegaPixImage(s).render(t,{maxWidth:i,maxHeight:i,mime:r(e),resize:o})},n.failure)}function p(e,t,n,i){l(t,n),qq(t).css({maxWidth:i+"px",maxHeight:i+"px"}),t.src=e}function h(e,r,s){var u=new qq.Promise,c=s.scale,h=c?s.maxSize:null;return c&&t(r)?o()?a(e)&&!i()?p(e,r,u,h):d(e,r,u,h):p(e,r,u,h):n(r)?d(e,r,u,h):l(r,u)&&(r.src=e),u}qq.extend(this,{generate:function(t,n,i){return qq.isString(t)?(e("Attempting to update thumbnail based on server response."),h(t,n,i||{})):(e("Attempting to draw client-side image preview."),c(t,n,i||{}))}}),this._testing={},this._testing.isImg=t,this._testing.isCanvas=n,this._testing.isCrossOrigin=a,this._testing.determineMimeOfFileName=r},qq.Exif=function(e,t){"use strict";function n(e){for(var t=0,n=0;e.length>0;)t+=parseInt(e.substring(0,2),16)*Math.pow(2,n),e=e.substring(2,e.length),n+=8;return t}function i(t,n){var o=t,r=n;return void 0===o&&(o=2,r=new qq.Promise),qq.readBlobToHex(e,o,4).then(function(e){var t,n=/^ffe([0-9])/.exec(e);n?"1"!==n[1]?(t=parseInt(e.slice(4,8),16),i(o+t+2,r)):r.success(o):r.failure("No EXIF header to be found!")}),r}function o(){var t=new qq.Promise;return qq.readBlobToHex(e,0,6).then(function(e){0!==e.indexOf("ffd8")?t.failure("Not a valid JPEG!"):i().then(function(e){t.success(e)},function(e){t.failure(e)})}),t}function r(t){var n=new qq.Promise;return qq.readBlobToHex(e,t+10,2).then(function(e){n.success("4949"===e)}),n}function a(t,i){var o=new qq.Promise;return qq.readBlobToHex(e,t+18,2).then(function(e){if(i)return o.success(n(e));o.success(parseInt(e,16))}),o}function s(t,n){var i=t+20,o=12*n;return qq.readBlobToHex(e,i,o)}function u(e){for(var t=[],n=0;n+24<=e.length;)t.push(e.slice(n,n+24)),n+=24;return t}function l(e,t){var i=qq.extend([],c),o={};return qq.each(t,function(t,r){var a,s,u,l=r.slice(0,4),c=e?n(l):parseInt(l,16),p=i.indexOf(c);if(p>=0&&(s=d[c].name,u=d[c].bytes,a=r.slice(16,16+2*u),o[s]=e?n(a):parseInt(a,16),i.splice(p,1)),0===i.length)return!1}),o}var c=[274],d={274:{name:"Orientation",bytes:2}};qq.extend(this,{parse:function(){var n=new qq.Promise,i=function(e){t(qq.format("EXIF header parse failed: '{}' ",e)),n.failure(e)};return o().then(function(o){t(qq.format("Moving forward with EXIF header parsing for '{}'",void 0===e.name?"blob":e.name)),r(o).then(function(e){t(qq.format("EXIF Byte order is {} endian",e?"little":"big")),a(o,e).then(function(r){t(qq.format("Found {} APP1 directory entries",r)),s(o,r).then(function(i){var o=u(i),r=l(e,o);t("Successfully parsed some EXIF tags"),n.success(r)},i)},i)},i)},i),n}}),this._testing={},this._testing.parseLittleEndian=n},qq.Identify=function(e,t){"use strict";function n(e,t){var n=!1,i=[].concat(e);return qq.each(i,function(e,i){if(0===t.indexOf(i))return n=!0,!1}),n}qq.extend(this,{isPreviewable:function(){var i=this,o=new qq.Promise,r=!1,a=void 0===e.name?"blob":e.name;return t(qq.format("Attempting to determine if {} can be rendered in this browser",a)),t("First pass: check type attribute of blob object."),this.isPreviewableSync()?(t("Second pass: check for magic bytes in file header."),qq.readBlobToHex(e,0,4).then(function(e){qq.each(i.PREVIEWABLE_MIME_TYPES,function(t,i){if(n(i,e))return("image/tiff"!==t||qq.supportedFeatures.tiffPreviews)&&(r=!0,o.success(t)),!1}),t(qq.format("'{}' is {} able to be rendered in this browser",a,r?"":"NOT")),r||o.failure()},function(){t("Error reading file w/ name '"+a+"'. Not able to be rendered in this browser."),o.failure()})):o.failure(),o},isPreviewableSync:function(){var n=e.type,i=qq.indexOf(Object.keys(this.PREVIEWABLE_MIME_TYPES),n)>=0,o=!1,r=void 0===e.name?"blob":e.name;return i&&(o="image/tiff"!==n||qq.supportedFeatures.tiffPreviews),!o&&t(r+" is not previewable in this browser per the blob's type attr"),o}})},qq.Identify.prototype.PREVIEWABLE_MIME_TYPES={"image/jpeg":"ffd8ff","image/gif":"474946","image/png":"89504e","image/bmp":"424d","image/tiff":["49492a00","4d4d002a"]},qq.ImageValidation=function(e,t){"use strict";function n(e){var t=!1;return qq.each(e,function(e,n){if(n>0)return t=!0,!1}),t}function i(){var n=new qq.Promise;return new qq.Identify(e,t).isPreviewable().then(function(){var i=new Image,o=window.URL&&window.URL.createObjectURL?window.URL:window.webkitURL&&window.webkitURL.createObjectURL?window.webkitURL:null;o?(i.onerror=function(){t("Cannot determine dimensions for image. May be too large.","error"),n.failure()},i.onload=function(){n.success({width:this.width,height:this.height})},i.src=o.createObjectURL(e)):(t("No createObjectURL function available to generate image URL!","error"),n.failure())},n.failure),n}function o(e,t){var n;return qq.each(e,function(e,i){if(i>0){var o=/(max|min)(Width|Height)/.exec(e),r=o[2].charAt(0).toLowerCase()+o[2].slice(1),a=t[r];switch(o[1]){case"min":if(ai)return n=e,!1}}}),n}this.validate=function(e){var r=new qq.Promise;return t("Attempting to validate image."),n(e)?i().then(function(t){var n=o(e,t);n?r.failure(n):r.success()},r.success):r.success(),r}},qq.Session=function(e){"use strict";function t(e){if(qq.isArray(e))return!0;i.log("Session response is not an array.","error")}function n(e,n,o,r){var a=!1;n=n&&t(e),n&&qq.each(e,function(e,t){if(null==t.uuid)a=!0,i.log(qq.format("Session response item {} did not include a valid UUID - ignoring.",e),"error");else if(null==t.name)a=!0,i.log(qq.format("Session response item {} did not include a valid name - ignoring.",e),"error");else try{return i.addFileRecord(t),!0}catch(e){a=!0,i.log(e.message,"error")}return!1}),r[n&&!a?"success":"failure"](e,o)}var i={endpoint:null,params:{},customHeaders:{},cors:{},addFileRecord:function(e){},log:function(e,t){}};qq.extend(i,e,!0),this.refresh=function(){var e=new qq.Promise,t=function(t,i,o){n(t,i,o,e)},o=qq.extend({},i);return new qq.SessionAjaxRequester(qq.extend(o,{onComplete:t})).queryServer(),e}},qq.SessionAjaxRequester=function(e){"use strict";function t(e,t,n){var o=null;if(null!=t.responseText)try{o=qq.parseJson(t.responseText)}catch(e){i.log("Problem parsing session response: "+e.message,"error"),n=!0}i.onComplete(o,!n,t)}var n,i={endpoint:null,customHeaders:{},params:{},cors:{expected:!1,sendCredentials:!1},onComplete:function(e,t,n){},log:function(e,t){}};qq.extend(i,e),n=qq.extend(this,new qq.AjaxRequester({acceptHeader:"application/json",validMethods:["GET"],method:"GET",endpointStore:{get:function(){return i.endpoint}},customHeaders:i.customHeaders,log:i.log,onComplete:t,cors:i.cors})),qq.extend(this,{queryServer:function(){var e=qq.extend({},i.params);i.log("Session query request."),n.initTransport("sessionRefresh").withParams(e).withCacheBuster().send()}})},qq.Scaler=function(e,t){"use strict";var n=e.customResizer,i=e.sendOriginal,o=e.orient,r=e.defaultType,a=e.defaultQuality/100,s=e.failureText,u=e.includeExif,l=this._getSortedSizes(e.sizes);qq.extend(this,{enabled:qq.supportedFeatures.scaling&&l.length>0,getFileRecords:function(e,c,d){var p=this,h=[],q=d.blob?d.blob:d;return new qq.Identify(q,t).isPreviewableSync()?(qq.each(l,function(e,i){var l=p._determineOutputType({defaultType:r,requestedType:i.type,refType:q.type});h.push({uuid:qq.getUniqueId(),name:p._getName(c,{name:i.name,type:l,refType:q.type}),blob:new qq.BlobProxy(q,qq.bind(p._generateScaledImage,p,{customResizeFunction:n,maxSize:i.maxSize,orient:o,type:l,quality:a,failedText:s,includeExif:u,log:t}))})}),h.push({uuid:e,name:c,size:q.size,blob:i?q:null})):h.push({uuid:e,name:c,size:q.size,blob:q}),h},handleNewFile:function(e,t,n,i,o,r,a,s){var u=this,l=(e.qqButtonId||e.blob&&e.blob.qqButtonId,[]),c=null,d=s.addFileToHandler,p=s.uploadData,h=s.paramsStore,q=qq.getUniqueId();qq.each(u.getFileRecords(n,t,e),function(e,t){var n,i=t.size;t.blob instanceof qq.BlobProxy&&(i=-1),n=p.addFile({uuid:t.uuid,name:t.name,size:i,batchId:r,proxyGroupId:q}),t.blob instanceof qq.BlobProxy?l.push(n):c=n,t.blob?(d(n,t.blob),o.push({id:n,file:t.blob})):p.setStatus(n,qq.status.REJECTED)}),null!==c&&(qq.each(l,function(e,t){var n={qqparentuuid:p.retrieve({id:c}).uuid,qqparentsize:p.retrieve({id:c}).size};n[a]=p.retrieve({id:t}).uuid,p.setParentId(t,c),h.addReadOnly(t,n)}),l.length&&function(){var e={};e[a]=p.retrieve({id:c}).uuid,h.addReadOnly(c,e)}())}})},qq.extend(qq.Scaler.prototype,{scaleImage:function(e,t,n){"use strict";if(!qq.supportedFeatures.scaling)throw new qq.Error("Scaling is not supported in this browser!");var i=new qq.Promise,o=n.log,r=n.getFile(e),a=n.uploadData.retrieve({id:e}),s=a&&a.name,u=a&&a.uuid,l={customResizer:t.customResizer,sendOriginal:!1,orient:t.orient,defaultType:t.type||null,defaultQuality:t.quality,failedToScaleText:"Unable to scale",sizes:[{name:"",maxSize:t.maxSize}]},c=new qq.Scaler(l,o);return qq.Scaler&&qq.supportedFeatures.imagePreviews&&r?qq.bind(function(){var t=c.getFileRecords(u,s,r)[0];t&&t.blob instanceof qq.BlobProxy?t.blob.create().then(i.success,i.failure):(o(e+" is not a scalable image!","error"),i.failure())},this)():(i.failure(),o("Could not generate requested scaled image for "+e+". Scaling is either not possible in this browser, or the file could not be located.","error")),i},_determineOutputType:function(e){"use strict";var t=e.requestedType,n=e.defaultType,i=e.refType;return n||t?t&&qq.indexOf(Object.keys(qq.Identify.prototype.PREVIEWABLE_MIME_TYPES),t)>=0?"image/tiff"===t?qq.supportedFeatures.tiffPreviews?t:n:t:n:"image/jpeg"!==i?"image/png":i},_getName:function(e,t){"use strict";var n=e.lastIndexOf("."),i=t.type||"image/png",o=t.refType,r="",a=qq.getExtension(e),s="";return t.name&&t.name.trim().length&&(s=" ("+t.name+")"),n>=0?(r=e.substr(0,n),o!==i&&(a=i.split("/")[1]),r+=s+"."+a):r=e+s,r},_getSortedSizes:function(e){"use strict";return e=qq.extend([],e),e.sort(function(e,t){return e.maxSize>t.maxSize?1:e.maxSize=0?atob(e.split(",")[1]):decodeURI(e.split(",")[1]),n=e.split(",")[0].split(":")[1].split(";")[0],i=new ArrayBuffer(t.length),o=new Uint8Array(i),qq.each(t,function(e,t){o[e]=t.charCodeAt(0)}),this._createBlob(i,n)},_createBlob:function(e,t){"use strict";var n=window.BlobBuilder||window.WebKitBlobBuilder||window.MozBlobBuilder||window.MSBlobBuilder,i=n&&new n;return i?(i.append(e),i.getBlob(t)):new Blob([e],{type:t})}}),qq.ExifRestorer=function(){var e={};return e.KEY_STR="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",e.encode64=function(e){var t,n,i,o,r,a="",s="",u="",l=0;do t=e[l++],n=e[l++],s=e[l++],i=t>>2,o=(3&t)<<4|n>>4,r=(15&n)<<2|s>>6,u=63&s,isNaN(n)?r=u=64:isNaN(s)&&(u=64),a=a+this.KEY_STR.charAt(i)+this.KEY_STR.charAt(o)+this.KEY_STR.charAt(r)+this.KEY_STR.charAt(u),t=n=s="",i=o=r=u="";while(le.length)break}return n},e.decode64=function(e){var t,n,i,o,r,a="",s="",u=0,l=[];if(/[^A-Za-z0-9\+\/\=]/g.exec(e))throw new Error("There were invalid base64 characters in the input text. Valid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='");e=e.replace(/[^A-Za-z0-9\+\/\=]/g,"");do i=this.KEY_STR.indexOf(e.charAt(u++)),o=this.KEY_STR.indexOf(e.charAt(u++)),r=this.KEY_STR.indexOf(e.charAt(u++)),s=this.KEY_STR.indexOf(e.charAt(u++)),t=i<<2|o>>4,n=(15&o)<<4|r>>2,a=(3&r)<<6|s,l.push(t),64!=r&&l.push(n),64!=s&&l.push(a),t=n=a="",i=o=r=s="";while(u=0)return n=!1,!1}),n},l=function(e){p(e,-1,-1),delete n[e]},c=function(e,t,n){(0===t.length||u(t,n))&&(s(o,o),this.reset())},d=function(e){var i=t(e);i>0&&(p(e,0,i),n[e]={loaded:0,total:i})},p=function(e,t,r){var a=n[e]?n[e].loaded:0,u=n[e]?n[e].total:0;t===-1&&r===-1?(i-=a,o-=u):(t&&(i+=t-a),r&&(o+=r-u)),s(i,o)};qq.extend(this,{onAllComplete:c,onStatusChange:function(e,t,n){n===qq.status.CANCELED||n===qq.status.REJECTED?l(e):n===qq.status.SUBMITTING&&d(e)},onIndividualProgress:function(e,t,i){p(e,t,i),n[e]={loaded:t,total:i}},onNewSize:function(e){d(e)},reset:function(){n={},i=0,o=0}})},qq.PasteSupport=function(e){"use strict";function t(e){return e.type&&0===e.type.indexOf("image/")}function n(){r=qq(o.targetElement).attach("paste",function(e){var n=e.clipboardData;n&&qq.each(n.items,function(e,n){if(t(n)){var i=n.getAsFile();o.callbacks.pasteReceived(i)}})})}function i(){r&&r()}var o,r;o={targetElement:null,callbacks:{log:function(e,t){},pasteReceived:function(e){}}},qq.extend(o,e),n(),qq.extend(this,{reset:function(){i()}})},qq.FormSupport=function(e,t,n){"use strict";function i(e){e.getAttribute("action")&&(s.newEndpoint=e.getAttribute("action"))}function o(e,t){if(!e.checkValidity||e.checkValidity())return!0;n("Form did not pass validation checks - will not upload.","error"),t()}function r(e){var n=e.submit;qq(e).attach("submit",function(i){i=i||window.event,i.preventDefault?i.preventDefault():i.returnValue=!1,o(e,n)&&t()}),e.submit=function(){o(e,n)&&t()}}function a(e){return e&&(qq.isString(e)&&(e=document.getElementById(e)),e&&(n("Attaching to form element."),i(e),u&&r(e))),e}var s=this,u=e.interceptSubmit,l=e.element,c=e.autoUpload;qq.extend(this,{newEndpoint:null,newAutoUpload:c,attachedToForm:!1,getFormInputsAsObject:function(){return null==l?null:s._form2Obj(l)}}),l=a(l),this.attachedToForm=!!l},qq.extend(qq.FormSupport.prototype,{_form2Obj:function(e){"use strict";var t={},n=function(e){var t=["button","image","reset","submit"];return qq.indexOf(t,e.toLowerCase())<0},i=function(e){return qq.indexOf(["checkbox","radio"],e.toLowerCase())>=0},o=function(e){return!(!i(e.type)||e.checked)||e.disabled&&"hidden"!==e.type.toLowerCase()},r=function(e){var t=null;return qq.each(qq(e).children(),function(e,n){if("option"===n.tagName.toLowerCase()&&n.selected)return t=n.value,!1}),t};return qq.each(e.elements,function(e,i){if(!qq.isInput(i,!0)&&"textarea"!==i.tagName.toLowerCase()||!n(i.type)||o(i)){if("select"===i.tagName.toLowerCase()&&!o(i)){var a=r(i);null!==a&&(t[i.name]=a)}}else t[i.name]=i.value}),t}}),qq.traditional=qq.traditional||{},qq.traditional.FormUploadHandler=function(e,t){"use strict";function n(e,t){var n,i,r;try{i=t.contentDocument||t.contentWindow.document,r=i.body.innerHTML,s("converting iframe's innerHTML to JSON"),s("innerHTML = "+r),r&&r.match(/^1&&!c.allowMultipleItems?(c.callbacks.processingDroppedFilesComplete([]),c.callbacks.dropError("tooManyFilesError",""),t.dropDisabled(!1),o.failure()):(p=[],qq.isFolderDropSupported(e)?qq.each(e.items,function(e,t){var r=t.webkitGetAsEntry();r&&(r.isFile?p.push(t.getAsFile()):i.push(n(r).done(function(){i.pop(),0===i.length&&o.success()})))}):p=e.files,0===i.length&&o.success()),o}function a(e){var n=new qq.UploadDropZone({HIDE_ZONES_EVENT_NAME:"qq-hidezones",element:e,onEnter:function(t){qq(e).addClass(c.classes.dropActive),t.stopPropagation()},onLeaveNotDescendants:function(t){qq(e).removeClass(c.classes.dropActive)},onDrop:function(e){r(e.dataTransfer,n).then(function(){t(p,n)},function(){c.callbacks.dropLog("Drop event DataTransfer parsing failed. No files will be uploaded.","error")})}});return h.addDisposer(function(){n.dispose()}),qq(e).hasAttribute("qq-hide-dropzone")&&qq(e).hide(),d.push(n),n}function s(e){var t;return qq.each(e.dataTransfer.types,function(e,n){if("Files"===n)return t=!0,!1}),t}function u(e){return qq.safari()?e.x<0||e.y<0:0===e.x&&0===e.y}function l(){var e=c.dropZoneElements,t=function(){setTimeout(function(){qq.each(e,function(e,t){qq(t).hasAttribute("qq-hide-dropzone")&&qq(t).hide(),qq(t).removeClass(c.classes.dropActive)})},10)};qq.each(e,function(t,n){var i=a(n);e.length&&qq.supportedFeatures.fileDrop&&h.attach(document,"dragenter",function(t){!i.dropDisabled()&&s(t)&&qq.each(e,function(e,t){t instanceof HTMLElement&&qq(t).hasAttribute("qq-hide-dropzone")&&qq(t).css({display:"block"})})})}),h.attach(document,"dragleave",function(e){u(e)&&t()}),h.attach(qq(document).children()[0],"mouseenter",function(e){t()}),h.attach(document,"drop",function(e){s(e)&&(e.preventDefault(),t())}),h.attach(document,"qq-hidezones",t)}var c,d=[],p=[],h=new qq.DisposeSupport;c={dropZoneElements:[],allowMultipleItems:!0,classes:{dropActive:null},callbacks:new qq.DragAndDrop.callbacks},qq.extend(c,e,!0),l(),qq.extend(this,{setupExtraDropzone:function(e){c.dropZoneElements.push(e),a(e)},removeDropzone:function(e){var t,n=c.dropZoneElements;for(t in n)if(n[t]===e)return n.splice(t,1)},dispose:function(){h.dispose(),qq.each(d,function(e,t){t.dispose()})}}),this._testing={},this._testing.extractDirectoryPath=i},qq.DragAndDrop.callbacks=function(){"use strict";return{processingDroppedFiles:function(){},processingDroppedFilesComplete:function(e,t){},dropError:function(e,t){qq.log("Drag & drop error code '"+e+" with these specifics: '"+t+"'","error")},dropLog:function(e,t){qq.log(e,t)}}},qq.UploadDropZone=function(e){"use strict";function t(){return qq.safari()||qq.firefox()&&qq.windows()}function n(e){c||(t?d.attach(document,"dragover",function(e){e.preventDefault()}):d.attach(document,"dragover",function(e){e.dataTransfer&&(e.dataTransfer.dropEffect="none",e.preventDefault())}),c=!0)}function i(e){if(!qq.supportedFeatures.fileDrop)return!1;var t,n=e.dataTransfer,i=qq.safari();return t=!(!qq.ie()||!qq.supportedFeatures.fileDrop)||"none"!==n.effectAllowed,n&&t&&(n.files&&n.files.length||!i&&n.types.contains&&n.types.contains("Files")||n.types.includes&&n.types.includes("Files"))}function o(e){return void 0!==e&&(l=e),l}function r(){function e(){t=document.createEvent("Event"),t.initEvent(s.HIDE_ZONES_EVENT_NAME,!0,!0)}var t;if(window.CustomEvent)try{t=new CustomEvent(s.HIDE_ZONES_EVENT_NAME)}catch(t){e()}else e();document.dispatchEvent(t)}function a(){d.attach(u,"dragover",function(e){if(i(e)){var t=qq.ie()&&qq.supportedFeatures.fileDrop?null:e.dataTransfer.effectAllowed;e.dataTransfer.dropEffect="move"===t||"linkMove"===t?"move":"copy",e.stopPropagation(),e.preventDefault()}}),d.attach(u,"dragenter",function(e){if(!o()){if(!i(e))return;s.onEnter(e)}}),d.attach(u,"dragleave",function(e){if(i(e)){s.onLeave(e);var t=document.elementFromPoint(e.clientX,e.clientY);qq(this).contains(t)||s.onLeaveNotDescendants(e)}}),d.attach(u,"drop",function(e){if(!o()){if(!i(e))return;e.preventDefault(),e.stopPropagation(),s.onDrop(e),r()}})}var s,u,l,c,d=new qq.DisposeSupport;s={element:null,onEnter:function(e){},onLeave:function(e){},onLeaveNotDescendants:function(e){},onDrop:function(e){}},qq.extend(s,e),u=s.element,n(),a(),qq.extend(this,{dropDisabled:function(e){return o(e)},dispose:function(){d.dispose()},getElement:function(){return u}}),this._testing={},this._testing.isValidFileDrag=i},function(){"use strict";qq.uiPublicApi={addInitialFiles:function(e){this._parent.prototype.addInitialFiles.apply(this,arguments),this._templating.addCacheToDom()},clearStoredFiles:function(){this._parent.prototype.clearStoredFiles.apply(this,arguments),this._templating.clearFiles()},addExtraDropzone:function(e){this._dnd&&this._dnd.setupExtraDropzone(e)},removeExtraDropzone:function(e){if(this._dnd)return this._dnd.removeDropzone(e)},getItemByFileId:function(e){if(!this._templating.isHiddenForever(e))return this._templating.getFileContainer(e)},reset:function(){this._parent.prototype.reset.apply(this,arguments),this._templating.reset(),!this._options.button&&this._templating.getButton()&&(this._defaultButtonId=this._createUploadButton({element:this._templating.getButton(),title:this._options.text.fileInputTitle}).getButtonId()),this._dnd&&(this._dnd.dispose(),this._dnd=this._setupDragAndDrop()),this._totalFilesInBatch=0,this._filesInBatchAddedToUi=0,this._setupClickAndEditEventHandlers()},setName:function(e,t){var n=this._options.formatFileName(t);this._parent.prototype.setName.apply(this,arguments),this._templating.updateFilename(e,n)},pauseUpload:function(e){var t=this._parent.prototype.pauseUpload.apply(this,arguments);return t&&this._templating.uploadPaused(e),t},continueUpload:function(e){var t=this._parent.prototype.continueUpload.apply(this,arguments);return t&&this._templating.uploadContinued(e),t},getId:function(e){return this._templating.getFileId(e)},getDropTarget:function(e){return this.getFile(e).qqDropTarget}},qq.uiPrivateApi={_getButton:function(e){var t=this._parent.prototype._getButton.apply(this,arguments);return t||e===this._defaultButtonId&&(t=this._templating.getButton()),t},_removeFileItem:function(e){this._templating.removeFile(e)},_setupClickAndEditEventHandlers:function(){this._fileButtonsClickHandler=qq.FileButtonsClickHandler&&this._bindFileButtonsClickEvent(),this._focusinEventSupported=!qq.firefox(),this._isEditFilenameEnabled()&&(this._filenameClickHandler=this._bindFilenameClickEvent(),this._filenameInputFocusInHandler=this._bindFilenameInputFocusInEvent(),this._filenameInputFocusHandler=this._bindFilenameInputFocusEvent())},_setupDragAndDrop:function(){var e=this,t=this._options.dragAndDrop.extraDropzones,n=this._templating,i=n.getDropZone();return i&&t.push(i),new qq.DragAndDrop({dropZoneElements:t,allowMultipleItems:this._options.multiple,classes:{dropActive:this._options.classes.dropActive},callbacks:{processingDroppedFiles:function(){n.showDropProcessing()},processingDroppedFilesComplete:function(t,i){n.hideDropProcessing(),qq.each(t,function(e,t){t.qqDropTarget=i}),t.length&&e.addFiles(t,null,null)},dropError:function(t,n){e._itemError(t,n)},dropLog:function(t,n){e.log(t,n)}}})},_bindFileButtonsClickEvent:function(){var e=this;return new qq.FileButtonsClickHandler({templating:this._templating,log:function(t,n){e.log(t,n)},onDeleteFile:function(t){e.deleteFile(t)},onCancel:function(t){e.cancel(t)},onRetry:function(t){e.retry(t)},onPause:function(t){e.pauseUpload(t)},onContinue:function(t){e.continueUpload(t)},onGetName:function(t){return e.getName(t)}})},_isEditFilenameEnabled:function(){return this._templating.isEditFilenamePossible()&&!this._options.autoUpload&&qq.FilenameClickHandler&&qq.FilenameInputFocusHandler&&qq.FilenameInputFocusHandler},_filenameEditHandler:function(){var e=this,t=this._templating;return{templating:t,log:function(t,n){e.log(t,n)},onGetUploadStatus:function(t){return e.getUploads({id:t}).status},onGetName:function(t){return e.getName(t)},onSetName:function(t,n){e.setName(t,n)},onEditingStatusChange:function(e,n){var i=qq(t.getEditInput(e)),o=qq(t.getFileContainer(e));n?(i.addClass("qq-editing"),t.hideFilename(e),t.hideEditIcon(e)):(i.removeClass("qq-editing"),t.showFilename(e),t.showEditIcon(e)),o.addClass("qq-temp").removeClass("qq-temp")}}},_onUploadStatusChange:function(e,t,n){this._parent.prototype._onUploadStatusChange.apply(this,arguments),this._isEditFilenameEnabled()&&this._templating.getFileContainer(e)&&n!==qq.status.SUBMITTED&&(this._templating.markFilenameEditable(e),this._templating.hideEditIcon(e)),t===qq.status.UPLOAD_RETRYING&&n===qq.status.UPLOADING?(this._templating.hideRetry(e),this._templating.setStatusText(e),qq(this._templating.getFileContainer(e)).removeClass(this._classes.retrying)):n===qq.status.UPLOAD_FAILED&&this._templating.hidePause(e)},_bindFilenameInputFocusInEvent:function(){var e=qq.extend({},this._filenameEditHandler());return new qq.FilenameInputFocusInHandler(e)},_bindFilenameInputFocusEvent:function(){var e=qq.extend({},this._filenameEditHandler());return new qq.FilenameInputFocusHandler(e)},_bindFilenameClickEvent:function(){var e=qq.extend({},this._filenameEditHandler());return new qq.FilenameClickHandler(e)},_storeForLater:function(e){this._parent.prototype._storeForLater.apply(this,arguments),this._templating.hideSpinner(e)},_onAllComplete:function(e,t){this._parent.prototype._onAllComplete.apply(this,arguments),this._templating.resetTotalProgress()},_onSubmit:function(e,t){var n=this.getFile(e);n&&n.qqPath&&this._options.dragAndDrop.reportDirectoryPaths&&this._paramsStore.addReadOnly(e,{qqpath:n.qqPath}),this._parent.prototype._onSubmit.apply(this,arguments),this._addToList(e,t)},_onSubmitted:function(e){this._isEditFilenameEnabled()&&(this._templating.markFilenameEditable(e),this._templating.showEditIcon(e),this._focusinEventSupported||this._filenameInputFocusHandler.addHandler(this._templating.getEditInput(e)))},_onProgress:function(e,t,n,i){this._parent.prototype._onProgress.apply(this,arguments),this._templating.updateProgress(e,n,i),0===i||100===Math.round(n/i*100)?(this._templating.hideCancel(e),this._templating.hidePause(e),this._templating.hideProgress(e),this._templating.setStatusText(e,this._options.text.waitingForResponse),this._displayFileSize(e)):this._displayFileSize(e,n,i)},_onTotalProgress:function(e,t){this._parent.prototype._onTotalProgress.apply(this,arguments),this._templating.updateTotalProgress(e,t)},_onComplete:function(e,t,n,i){function o(t){s&&(a.setStatusText(e),qq(s).removeClass(u._classes.retrying),a.hideProgress(e),u.getUploads({id:e}).status!==qq.status.UPLOAD_FAILED&&a.hideCancel(e),a.hideSpinner(e),t.success?u._markFileAsSuccessful(e):(qq(s).addClass(u._classes.fail),a.showCancel(e),a.isRetryPossible()&&!u._preventRetries[e]&&(qq(s).addClass(u._classes.retryable),a.showRetry(e)),u._controlFailureTextDisplay(e,t)))}var r=this._parent.prototype._onComplete.apply(this,arguments),a=this._templating,s=a.getFileContainer(e),u=this;return r instanceof qq.Promise?r.done(function(e){o(e)}):o(n),r},_markFileAsSuccessful:function(e){var t=this._templating;this._isDeletePossible()&&t.showDeleteButton(e),qq(t.getFileContainer(e)).addClass(this._classes.success),this._maybeUpdateThumbnail(e)},_onUploadPrep:function(e){this._parent.prototype._onUploadPrep.apply(this,arguments),this._templating.showSpinner(e)},_onUpload:function(e,t){var n=this._parent.prototype._onUpload.apply(this,arguments);return this._templating.showSpinner(e),n},_onUploadChunk:function(e,t){this._parent.prototype._onUploadChunk.apply(this,arguments),t.partIndex>0&&this._handler.isResumable(e)&&this._templating.allowPause(e)},_onCancel:function(e,t){this._parent.prototype._onCancel.apply(this,arguments),this._removeFileItem(e),0===this._getNotFinished()&&this._templating.resetTotalProgress()},_onBeforeAutoRetry:function(e){var t,n,i;this._parent.prototype._onBeforeAutoRetry.apply(this,arguments),this._showCancelLink(e),this._options.retry.showAutoRetryNote&&(t=this._autoRetries[e],n=this._options.retry.maxAutoAttempts,i=this._options.retry.autoRetryNote.replace(/\{retryNum\}/g,t),i=i.replace(/\{maxAuto\}/g,n),this._templating.setStatusText(e,i),qq(this._templating.getFileContainer(e)).addClass(this._classes.retrying))},_onBeforeManualRetry:function(e){return this._parent.prototype._onBeforeManualRetry.apply(this,arguments)?(this._templating.resetProgress(e),qq(this._templating.getFileContainer(e)).removeClass(this._classes.fail),this._templating.setStatusText(e),this._templating.showSpinner(e),this._showCancelLink(e),!0):(qq(this._templating.getFileContainer(e)).addClass(this._classes.retryable),this._templating.showRetry(e),!1)},_onSubmitDelete:function(e){var t=qq.bind(this._onSubmitDeleteSuccess,this);this._parent.prototype._onSubmitDelete.call(this,e,t)},_onSubmitDeleteSuccess:function(e,t,n){this._options.deleteFile.forceConfirm?this._showDeleteConfirm.apply(this,arguments):this._sendDeleteRequest.apply(this,arguments)},_onDeleteComplete:function(e,t,n){this._parent.prototype._onDeleteComplete.apply(this,arguments),this._templating.hideSpinner(e),n?(this._templating.setStatusText(e,this._options.deleteFile.deletingFailedText),this._templating.showDeleteButton(e)):this._removeFileItem(e)},_sendDeleteRequest:function(e,t,n){this._templating.hideDeleteButton(e),this._templating.showSpinner(e),this._templating.setStatusText(e,this._options.deleteFile.deletingStatusText),this._deleteHandler.sendDelete.apply(this,arguments)},_showDeleteConfirm:function(e,t,n){var i,o=this.getName(e),r=this._options.deleteFile.confirmMessage.replace(/\{filename\}/g,o),a=(this.getUuid(e),arguments),s=this;i=this._options.showConfirm(r),qq.isGenericPromise(i)?i.then(function(){s._sendDeleteRequest.apply(s,a)}):i!==!1&&s._sendDeleteRequest.apply(s,a)},_addToList:function(e,t,n){var i,o,r=0,a=this._handler.isProxied(e)&&this._options.scaling.hideScaled;this._options.display.prependFiles&&(this._totalFilesInBatch>1&&this._filesInBatchAddedToUi>0&&(r=this._filesInBatchAddedToUi-1),i={index:r}),n||(this._options.disableCancelForFormUploads&&!qq.supportedFeatures.ajaxUploading&&this._templating.disableCancel(),this._options.multiple||(o=this.getUploads({id:e}),this._handledProxyGroup=this._handledProxyGroup||o.proxyGroupId,o.proxyGroupId===this._handledProxyGroup&&o.proxyGroupId||(this._handler.cancelAll(),this._clearList(),this._handledProxyGroup=null))),n?(this._templating.addFileToCache(e,this._options.formatFileName(t),i,a),this._templating.updateThumbnail(e,this._thumbnailUrls[e],!0,this._options.thumbnails.customResizer)):(this._templating.addFile(e,this._options.formatFileName(t),i,a),this._templating.generatePreview(e,this.getFile(e),this._options.thumbnails.customResizer)),this._filesInBatchAddedToUi+=1,(n||this._options.display.fileSizeOnSubmit&&qq.supportedFeatures.ajaxUploading)&&this._displayFileSize(e)},_clearList:function(){this._templating.clearFiles(),this.clearStoredFiles()},_displayFileSize:function(e,t,n){var i=this.getSize(e),o=this._formatSize(i);i>=0&&(void 0!==t&&void 0!==n&&(o=this._formatProgress(t,n)),this._templating.updateSize(e,o))},_formatProgress:function(e,t){function n(e,t){i=i.replace(e,t)}var i=this._options.text.formatProgress;return n("{percent}",Math.round(e/t*100)),n("{total_size}",this._formatSize(t)),i},_controlFailureTextDisplay:function(e,t){var n,i,o;n=this._options.failedUploadTextDisplay.mode,i=this._options.failedUploadTextDisplay.responseProperty,"custom"===n?(o=t[i],o||(o=this._options.text.failUpload),this._templating.setStatusText(e,o),this._options.failedUploadTextDisplay.enableTooltip&&this._showTooltip(e,o)):"default"===n?this._templating.setStatusText(e,this._options.text.failUpload):"none"!==n&&this.log("failedUploadTextDisplay.mode value of '"+n+"' is not valid","warn")},_showTooltip:function(e,t){this._templating.getFileContainer(e).title=t},_showCancelLink:function(e){this._options.disableCancelForFormUploads&&!qq.supportedFeatures.ajaxUploading||this._templating.showCancel(e)},_itemError:function(e,t,n){var i=this._parent.prototype._itemError.apply(this,arguments);this._options.showMessage(i)},_batchError:function(e){this._parent.prototype._batchError.apply(this,arguments),this._options.showMessage(e)},_setupPastePrompt:function(){var e=this;this._options.callbacks.onPasteReceived=function(){var t=e._options.paste.namePromptMessage,n=e._options.paste.defaultName;return e._options.showPrompt(t,n)}},_fileOrBlobRejected:function(e,t){this._totalFilesInBatch-=1,this._parent.prototype._fileOrBlobRejected.apply(this,arguments)},_prepareItemsForUpload:function(e,t,n){this._totalFilesInBatch=e.length,this._filesInBatchAddedToUi=0,this._parent.prototype._prepareItemsForUpload.apply(this,arguments)},_maybeUpdateThumbnail:function(e){var t=this._thumbnailUrls[e];this.getUploads({id:e}).status===qq.status.DELETED||!t&&!this._options.thumbnails.placeholders.waitUntilResponse&&qq.supportedFeatures.imagePreviews||this._templating.updateThumbnail(e,t,this._options.thumbnails.customResizer)},_addCannedFile:function(e){var t=this._parent.prototype._addCannedFile.apply(this,arguments);return this._addToList(t,this.getName(t),!0),this._templating.hideSpinner(t),this._templating.hideCancel(t),this._markFileAsSuccessful(t),t},_setSize:function(e,t){this._parent.prototype._setSize.apply(this,arguments),this._templating.updateSize(e,this._formatSize(t))},_sessionRequestComplete:function(){this._templating.addCacheToDom(),this._parent.prototype._sessionRequestComplete.apply(this,arguments)}}}(),qq.FineUploader=function(e,t){"use strict";var n=this;this._parent=t?qq[t].FineUploaderBasic:qq.FineUploaderBasic,this._parent.apply(this,arguments),qq.extend(this._options,{element:null,button:null,listElement:null,dragAndDrop:{extraDropzones:[],reportDirectoryPaths:!1},text:{formatProgress:"{percent}% of {total_size}",failUpload:"Upload failed",waitingForResponse:"Processing...",paused:"Paused"},template:"qq-template",classes:{retrying:"qq-upload-retrying",retryable:"qq-upload-retryable",success:"qq-upload-success",fail:"qq-upload-fail",editable:"qq-editable",hide:"qq-hide",dropActive:"qq-upload-drop-area-active"},failedUploadTextDisplay:{mode:"default",responseProperty:"error",enableTooltip:!0},messages:{tooManyFilesError:"You may only drop one file",unsupportedBrowser:"Unrecoverable error - this browser does not permit file uploading of any kind."},retry:{showAutoRetryNote:!0,autoRetryNote:"Retrying {retryNum}/{maxAuto}..."},deleteFile:{forceConfirm:!1,confirmMessage:"Are you sure you want to delete {filename}?",deletingStatusText:"Deleting...",deletingFailedText:"Delete failed"},display:{fileSizeOnSubmit:!1,prependFiles:!1},paste:{promptForName:!1,namePromptMessage:"Please name this image"},thumbnails:{customResizer:null,maxCount:0,placeholders:{waitUntilResponse:!1,notAvailablePath:null,waitingPath:null},timeBetweenThumbs:750},scaling:{hideScaled:!1},showMessage:function(e){if(n._templating.hasDialog("alert"))return n._templating.showDialog("alert",e);setTimeout(function(){window.alert(e)},0)},showConfirm:function(e){return n._templating.hasDialog("confirm")?n._templating.showDialog("confirm",e):window.confirm(e)},showPrompt:function(e,t){return n._templating.hasDialog("prompt")?n._templating.showDialog("prompt",e,t):window.prompt(e,t)}},!0),qq.extend(this._options,e,!0),this._templating=new qq.Templating({log:qq.bind(this.log,this),templateIdOrEl:this._options.template,containerEl:this._options.element,fileContainerEl:this._options.listElement,button:this._options.button,imageGenerator:this._imageGenerator,classes:{hide:this._options.classes.hide,editable:this._options.classes.editable},limits:{maxThumbs:this._options.thumbnails.maxCount,timeBetweenThumbs:this._options.thumbnails.timeBetweenThumbs},placeholders:{waitUntilUpdate:this._options.thumbnails.placeholders.waitUntilResponse,
+thumbnailNotAvailable:this._options.thumbnails.placeholders.notAvailablePath,waitingForThumbnail:this._options.thumbnails.placeholders.waitingPath},text:this._options.text}),this._options.workarounds.ios8SafariUploads&&qq.ios800()&&qq.iosSafari()?this._templating.renderFailure(this._options.messages.unsupportedBrowserIos8Safari):!qq.supportedFeatures.uploading||this._options.cors.expected&&!qq.supportedFeatures.uploadCors?this._templating.renderFailure(this._options.messages.unsupportedBrowser):(this._wrapCallbacks(),this._templating.render(),this._classes=this._options.classes,!this._options.button&&this._templating.getButton()&&(this._defaultButtonId=this._createUploadButton({element:this._templating.getButton(),title:this._options.text.fileInputTitle}).getButtonId()),this._setupClickAndEditEventHandlers(),qq.DragAndDrop&&qq.supportedFeatures.fileDrop&&(this._dnd=this._setupDragAndDrop()),this._options.paste.targetElement&&this._options.paste.promptForName&&(qq.PasteSupport?this._setupPastePrompt():this.log("Paste support module not found.","error")),this._totalFilesInBatch=0,this._filesInBatchAddedToUi=0)},qq.extend(qq.FineUploader.prototype,qq.basePublicApi),qq.extend(qq.FineUploader.prototype,qq.basePrivateApi),qq.extend(qq.FineUploader.prototype,qq.uiPublicApi),qq.extend(qq.FineUploader.prototype,qq.uiPrivateApi),qq.Templating=function(e){"use strict";var t,n,i,o,r,a,s,u,l={content:document.createDocumentFragment(),map:{}},c=!1,d=0,p=!1,h=[],q=-1,f={log:null,limits:{maxThumbs:0,timeBetweenThumbs:750},templateIdOrEl:"qq-template",containerEl:null,fileContainerEl:null,button:null,imageGenerator:null,classes:{hide:"qq-hide",editable:"qq-editable"},placeholders:{waitUntilUpdate:!1,thumbnailNotAvailable:null,waitingForThumbnail:null},text:{paused:"Paused"}},m={button:"qq-upload-button-selector",alertDialog:"qq-alert-dialog-selector",dialogCancelButton:"qq-cancel-button-selector",confirmDialog:"qq-confirm-dialog-selector",dialogMessage:"qq-dialog-message-selector",dialogOkButton:"qq-ok-button-selector",promptDialog:"qq-prompt-dialog-selector",uploader:"qq-uploader-selector",drop:"qq-upload-drop-area-selector",list:"qq-upload-list-selector",progressBarContainer:"qq-progress-bar-container-selector",progressBar:"qq-progress-bar-selector",totalProgressBarContainer:"qq-total-progress-bar-container-selector",totalProgressBar:"qq-total-progress-bar-selector",file:"qq-upload-file-selector",spinner:"qq-upload-spinner-selector",size:"qq-upload-size-selector",cancel:"qq-upload-cancel-selector",pause:"qq-upload-pause-selector",continueButton:"qq-upload-continue-selector",deleteButton:"qq-upload-delete-selector",retry:"qq-upload-retry-selector",statusText:"qq-upload-status-text-selector",editFilenameInput:"qq-edit-filename-selector",editNameIcon:"qq-edit-filename-icon-selector",dropText:"qq-upload-drop-area-text-selector",dropProcessing:"qq-drop-processing-selector",dropProcessingSpinner:"qq-drop-processing-spinner-selector",thumbnail:"qq-thumbnail-selector"},g={},_=new qq.Promise,v=new qq.Promise,b=function(){var e=f.placeholders.thumbnailNotAvailable,n=f.placeholders.waitingForThumbnail,i={maxSize:q,scale:u};s&&(e?f.imageGenerator.generate(e,new Image,i).then(function(e){_.success(e)},function(){_.failure(),t("Problem loading 'not available' placeholder image at "+e,"error")}):_.failure(),n?f.imageGenerator.generate(n,new Image,i).then(function(e){v.success(e)},function(){v.failure(),t("Problem loading 'waiting for thumbnail' placeholder image at "+n,"error")}):v.failure())},y=function(e){var t=new qq.Promise;return v.then(function(n){z(n,e),e.src?t.success():(e.src=n.src,e.onload=function(){e.onload=null,W(e),t.success()})},function(){L(e),t.success()}),t},S=function(e,n,i){var o=O(e);return t("Generating new thumbnail for "+e),n.qqThumbnailId=e,f.imageGenerator.generate(n,o,i).then(function(){d++,W(o),g[e].success()},function(){g[e].failure(),f.placeholders.waitUntilUpdate||H(e,o)})},w=function(){if(h.length){p=!0;var e=h.shift();e.update?V(e):G(e)}else p=!1},F=function(e){return N(P(e),m.cancel)},x=function(e){return N(P(e),m.continueButton)},C=function(e){return N(r,m[e+"Dialog"])},I=function(e){return N(P(e),m.deleteButton)},E=function(){return N(r,m.dropProcessing)},D=function(e){return N(P(e),m.editNameIcon)},P=function(e){return l.map[e]||qq(a).getFirstByClass("qq-file-id-"+e)},U=function(e){return N(P(e),m.file)},T=function(e){return N(P(e),m.pause)},R=function(e){return null==e?N(r,m.totalProgressBarContainer)||N(r,m.totalProgressBar):N(P(e),m.progressBarContainer)||N(P(e),m.progressBar)},k=function(e){return N(P(e),m.retry)},A=function(e){return N(P(e),m.size)},B=function(e){return N(P(e),m.spinner)},N=function(e,t){return e&&qq(e).getFirstByClass(t)},O=function(e){return s&&N(P(e),m.thumbnail)},L=function(e){e&&qq(e).addClass(f.classes.hide)},z=function(e,t){var n=e.style.maxWidth,i=e.style.maxHeight;i&&n&&!t.style.maxWidth&&!t.style.maxHeight&&qq(t).css({maxWidth:n,maxHeight:i})},H=function(e,t){var n=g[e]||(new qq.Promise).failure(),i=new qq.Promise;return _.then(function(e){n.then(function(){i.success()},function(){z(e,t),t.onload=function(){t.onload=null,i.success()},t.src=e.src,W(t)})}),i},M=function(){var e,o,r,a,l,c,d,p,h,g,_;if(t("Parsing template"),null==f.templateIdOrEl)throw new Error("You MUST specify either a template element or ID!");if(qq.isString(f.templateIdOrEl)){if(e=document.getElementById(f.templateIdOrEl),null===e)throw new Error(qq.format("Cannot find template script at ID '{}'!",f.templateIdOrEl));o=e.innerHTML}else{if(void 0===f.templateIdOrEl.innerHTML)throw new Error("You have specified an invalid value for the template option! It must be an ID or an Element.");o=f.templateIdOrEl.innerHTML}if(o=qq.trimStr(o),a=document.createElement("div"),a.appendChild(qq.toElement(o)),_=qq(a).getFirstByClass(m.uploader),f.button&&(c=qq(a).getFirstByClass(m.button),c&&qq(c).remove()),qq.DragAndDrop&&qq.supportedFeatures.fileDrop||(h=qq(a).getFirstByClass(m.dropProcessing),h&&qq(h).remove()),d=qq(a).getFirstByClass(m.drop),d&&!qq.DragAndDrop&&(t("DnD module unavailable.","info"),qq(d).remove()),qq.supportedFeatures.fileDrop?qq(_).hasAttribute("qq-drop-area-text")&&d&&(g=qq(d).getFirstByClass(m.dropText),g&&qq(g).remove()):(_.removeAttribute("qq-drop-area-text"),d&&qq(d).hasAttribute("qq-hide-dropzone")&&qq(d).css({display:"none"})),p=qq(a).getFirstByClass(m.thumbnail),s?p&&(q=parseInt(p.getAttribute("qq-max-size")),q=q>0?q:null,u=qq(p).hasAttribute("qq-server-scale")):p&&qq(p).remove(),s=s&&p,n=qq(a).getByClass(m.editFilenameInput).length>0,i=qq(a).getByClass(m.retry).length>0,r=qq(a).getFirstByClass(m.list),null==r)throw new Error("Could not find the file list container in the template!");return l=r.children[0].cloneNode(!0),r.innerHTML="",a.getElementsByTagName("DIALOG").length&&document.createElement("dialog"),t("Template parsing complete"),{template:a,fileTemplate:l}},j=function(e,t,n){var i=n,o=i.firstChild;t>0&&(o=qq(i).children()[t].nextSibling),i.insertBefore(e,o)},G=function(e){var t=e.id,n=e.optFileOrBlob,i=n&&n.qqThumbnailId,o=O(t),r={customResizeFunction:e.customResizeFunction,maxSize:q,orient:!0,scale:!0};qq.supportedFeatures.imagePreviews?o?f.limits.maxThumbs&&f.limits.maxThumbs<=d?(H(t,o),w()):y(o).done(function(){g[t]=new qq.Promise,g[t].done(function(){setTimeout(w,f.limits.timeBetweenThumbs)}),null!=i?J(t,i):S(t,n,r)}):w():o&&(y(o),w())},V=function(e){var t=e.id,n=e.thumbnailUrl,i=e.showWaitingImg,o=O(t),r={customResizeFunction:e.customResizeFunction,scale:u,maxSize:q};if(o)if(n){if(!(f.limits.maxThumbs&&f.limits.maxThumbs<=d))return i&&y(o),f.imageGenerator.generate(n,o,r).then(function(){W(o),d++,setTimeout(w,f.limits.timeBetweenThumbs)},function(){H(t,o),setTimeout(w,f.limits.timeBetweenThumbs)});H(t,o),w()}else H(t,o),w()},X=function(e,t){var n=R(e),i=null==e?m.totalProgressBar:m.progressBar;n&&!qq(n).hasClass(i)&&(n=qq(n).getFirstByClass(i)),n&&(qq(n).css({width:t+"%"}),n.setAttribute("aria-valuenow",t))},W=function(e){e&&qq(e).removeClass(f.classes.hide)},J=function(e,n){var i=O(e),o=O(n);t(qq.format("ID {} is the same file as ID {}. Will use generated thumbnail from ID {} instead.",e,n,n)),g[n].then(function(){d++,g[e].success(),t(qq.format("Now using previously generated thumbnail created for ID {} on ID {}.",n,e)),i.src=o.src,W(i)},function(){g[e].failure(),f.placeholders.waitUntilUpdate||H(e,i)})};qq.extend(f,e),t=f.log,qq.supportedFeatures.imagePreviews||(f.limits.timeBetweenThumbs=0,f.limits.maxThumbs=0),r=f.containerEl,s=void 0!==f.imageGenerator,o=M(),b(),qq.extend(this,{render:function(){t("Rendering template in DOM."),d=0,r.appendChild(o.template.cloneNode(!0)),L(E()),this.hideTotalProgress(),a=f.fileContainerEl||N(r,m.list),t("Template rendering complete")},renderFailure:function(e){var t=qq.toElement(e);r.innerHTML="",r.appendChild(t)},reset:function(){r.innerHTML="",this.render()},clearFiles:function(){a.innerHTML=""},disableCancel:function(){c=!0},addFile:function(e,t,n,i,s){var u,d=o.fileTemplate.cloneNode(!0),p=N(d,m.file),h=N(r,m.uploader),q=s?l.content:a;s&&(l.map[e]=d),qq(d).addClass("qq-file-id-"+e),h.removeAttribute("qq-drop-area-text"),p&&(qq(p).setText(t),p.setAttribute("title",t)),d.setAttribute("qq-file-id",e),n?j(d,n.index,q):q.appendChild(d),i?(d.style.display="none",qq(d).addClass("qq-hidden-forever")):(L(R(e)),L(A(e)),L(I(e)),L(k(e)),L(T(e)),L(x(e)),c&&this.hideCancel(e),u=O(e),u&&!u.src&&v.then(function(e){u.src=e.src,e.style.maxHeight&&e.style.maxWidth&&qq(u).css({maxHeight:e.style.maxHeight,maxWidth:e.style.maxWidth}),W(u)}))},addFileToCache:function(e,t,n,i){this.addFile(e,t,n,i,!0)},addCacheToDom:function(){a.appendChild(l.content),l.content=document.createDocumentFragment(),l.map={}},removeFile:function(e){qq(P(e)).remove()},getFileId:function(e){var t=e;if(t){for(;null==t.getAttribute("qq-file-id");)t=t.parentNode;return parseInt(t.getAttribute("qq-file-id"))}},getFileList:function(){return a},markFilenameEditable:function(e){var t=U(e);t&&qq(t).addClass(f.classes.editable)},updateFilename:function(e,t){var n=U(e);n&&(qq(n).setText(t),n.setAttribute("title",t))},hideFilename:function(e){L(U(e))},showFilename:function(e){W(U(e))},isFileName:function(e){return qq(e).hasClass(m.file)},getButton:function(){return f.button||N(r,m.button)},hideDropProcessing:function(){L(E())},showDropProcessing:function(){W(E())},getDropZone:function(){return N(r,m.drop)},isEditFilenamePossible:function(){return n},hideRetry:function(e){L(k(e))},isRetryPossible:function(){return i},showRetry:function(e){W(k(e))},getFileContainer:function(e){return P(e)},showEditIcon:function(e){var t=D(e);t&&qq(t).addClass(f.classes.editable)},isHiddenForever:function(e){return qq(P(e)).hasClass("qq-hidden-forever")},hideEditIcon:function(e){var t=D(e);t&&qq(t).removeClass(f.classes.editable)},isEditIcon:function(e){return qq(e).hasClass(m.editNameIcon,!0)},getEditInput:function(e){return N(P(e),m.editFilenameInput)},isEditInput:function(e){return qq(e).hasClass(m.editFilenameInput,!0)},updateProgress:function(e,t,n){var i,o=R(e);o&&n>0&&(i=Math.round(t/n*100),100===i?L(o):W(o),X(e,i))},updateTotalProgress:function(e,t){this.updateProgress(null,e,t)},hideProgress:function(e){var t=R(e);t&&L(t)},hideTotalProgress:function(){this.hideProgress()},resetProgress:function(e){X(e,0),this.hideTotalProgress(e)},resetTotalProgress:function(){this.resetProgress()},showCancel:function(e){if(!c){var t=F(e);t&&qq(t).removeClass(f.classes.hide)}},hideCancel:function(e){L(F(e))},isCancel:function(e){return qq(e).hasClass(m.cancel,!0)},allowPause:function(e){W(T(e)),L(x(e))},uploadPaused:function(e){this.setStatusText(e,f.text.paused),this.allowContinueButton(e),L(B(e))},hidePause:function(e){L(T(e))},isPause:function(e){return qq(e).hasClass(m.pause,!0)},isContinueButton:function(e){return qq(e).hasClass(m.continueButton,!0)},allowContinueButton:function(e){W(x(e)),L(T(e))},uploadContinued:function(e){this.setStatusText(e,""),this.allowPause(e),W(B(e))},showDeleteButton:function(e){W(I(e))},hideDeleteButton:function(e){L(I(e))},isDeleteButton:function(e){return qq(e).hasClass(m.deleteButton,!0)},isRetry:function(e){return qq(e).hasClass(m.retry,!0)},updateSize:function(e,t){var n=A(e);n&&(W(n),qq(n).setText(t))},setStatusText:function(e,t){var n=N(P(e),m.statusText);n&&(null==t?qq(n).clearText():qq(n).setText(t))},hideSpinner:function(e){qq(P(e)).removeClass("qq-in-progress"),L(B(e))},showSpinner:function(e){qq(P(e)).addClass("qq-in-progress"),W(B(e))},generatePreview:function(e,t,n){this.isHiddenForever(e)||(h.push({id:e,customResizeFunction:n,optFileOrBlob:t}),!p&&w())},updateThumbnail:function(e,t,n,i){this.isHiddenForever(e)||(h.push({customResizeFunction:i,update:!0,id:e,thumbnailUrl:t,showWaitingImg:n}),!p&&w())},hasDialog:function(e){return qq.supportedFeatures.dialogElement&&!!C(e)},showDialog:function(e,t,n){var i=C(e),o=N(i,m.dialogMessage),r=i.getElementsByTagName("INPUT")[0],a=N(i,m.dialogCancelButton),s=N(i,m.dialogOkButton),u=new qq.Promise,l=function(){a.removeEventListener("click",c),s&&s.removeEventListener("click",d),u.failure()},c=function(){a.removeEventListener("click",c),i.close()},d=function(){i.removeEventListener("close",l),s.removeEventListener("click",d),i.close(),u.success(r&&r.value)};return i.addEventListener("close",l),a.addEventListener("click",c),s&&s.addEventListener("click",d),r&&(r.value=n),o.textContent=t,i.showModal(),u}})},qq.UiEventHandler=function(e,t){"use strict";function n(e){i.attach(e,o.eventType,function(e){e=e||window.event;var t=e.target||e.srcElement;o.onHandled(t,e)})}var i=new qq.DisposeSupport,o={eventType:"click",attachTo:null,onHandled:function(e,t){}};qq.extend(this,{addHandler:function(e){n(e)},dispose:function(){i.dispose()}}),qq.extend(t,{getFileIdFromItem:function(e){return e.qqFileId},getDisposeSupport:function(){return i}}),qq.extend(o,e),o.attachTo&&n(o.attachTo)},qq.FileButtonsClickHandler=function(e){"use strict";function t(e,t){qq.each(o,function(n,o){var r,a=n.charAt(0).toUpperCase()+n.slice(1);if(i.templating["is"+a](e))return r=i.templating.getFileId(e),qq.preventDefault(t),i.log(qq.format("Detected valid file button click event on file '{}', ID: {}.",i.onGetName(r),r)),o(r),!1})}var n={},i={templating:null,log:function(e,t){},onDeleteFile:function(e){},onCancel:function(e){},onRetry:function(e){},onPause:function(e){},onContinue:function(e){},onGetName:function(e){}},o={cancel:function(e){i.onCancel(e)},retry:function(e){i.onRetry(e)},deleteButton:function(e){i.onDeleteFile(e)},pause:function(e){i.onPause(e)},continueButton:function(e){i.onContinue(e)}};qq.extend(i,e),i.eventType="click",i.onHandled=t,i.attachTo=i.templating.getFileList(),qq.extend(this,new qq.UiEventHandler(i,n))},qq.FilenameClickHandler=function(e){"use strict";function t(e,t){if(i.templating.isFileName(e)||i.templating.isEditIcon(e)){var o=i.templating.getFileId(e);i.onGetUploadStatus(o)===qq.status.SUBMITTED&&(i.log(qq.format("Detected valid filename click event on file '{}', ID: {}.",i.onGetName(o),o)),qq.preventDefault(t),n.handleFilenameEdit(o,e,!0))}}var n={},i={templating:null,log:function(e,t){},classes:{file:"qq-upload-file",editNameIcon:"qq-edit-filename-icon"},onGetUploadStatus:function(e){},onGetName:function(e){}};qq.extend(i,e),i.eventType="click",i.onHandled=t,qq.extend(this,new qq.FilenameEditHandler(i,n))},qq.FilenameInputFocusInHandler=function(e,t){"use strict";function n(e,n){if(i.templating.isEditInput(e)){var o=i.templating.getFileId(e);i.onGetUploadStatus(o)===qq.status.SUBMITTED&&(i.log(qq.format("Detected valid filename input focus event on file '{}', ID: {}.",i.onGetName(o),o)),t.handleFilenameEdit(o,e))}}var i={templating:null,onGetUploadStatus:function(e){},log:function(e,t){}};t||(t={}),i.eventType="focusin",i.onHandled=n,qq.extend(i,e),qq.extend(this,new qq.FilenameEditHandler(i,t))},qq.FilenameInputFocusHandler=function(e){"use strict";e.eventType="focus",e.attachTo=null,qq.extend(this,new qq.FilenameInputFocusInHandler(e,{}))},qq.FilenameEditHandler=function(e,t){"use strict";function n(e){var t=s.onGetName(e),n=t.lastIndexOf(".");return n>0&&(t=t.substr(0,n)),t}function i(e){var t=s.onGetName(e);return qq.getExtension(t)}function o(e,t){var n,o=e.value;void 0!==o&&qq.trimStr(o).length>0&&(n=i(t),void 0!==n&&(o=o+"."+n),s.onSetName(t,o)),s.onEditingStatusChange(t,!1)}function r(e,n){t.getDisposeSupport().attach(e,"blur",function(){o(e,n)})}function a(e,n){t.getDisposeSupport().attach(e,"keyup",function(t){13===(t.keyCode||t.which)&&o(e,n)})}var s={templating:null,log:function(e,t){},onGetUploadStatus:function(e){},onGetName:function(e){},onSetName:function(e,t){},onEditingStatusChange:function(e,t){}};qq.extend(s,e),s.attachTo=s.templating.getFileList(),qq.extend(this,new qq.UiEventHandler(s,t)),qq.extend(t,{handleFilenameEdit:function(e,t,i){var o=s.templating.getEditInput(e);s.onEditingStatusChange(e,!0),o.value=n(e),i&&o.focus(),r(o,e),a(o,e)}})}}(window);
//# sourceMappingURL=fine-uploader.min.js.map
\ No newline at end of file
diff --git a/styles/bootstrap/fine-uploader/fine-uploader.min.js.map b/styles/bootstrap/fine-uploader/fine-uploader.min.js.map
index 1f6fedda2..872c1e3cc 100644
--- a/styles/bootstrap/fine-uploader/fine-uploader.min.js.map
+++ b/styles/bootstrap/fine-uploader/fine-uploader.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["?","../client/js/util.js","../client/js/export.js","../client/js/error/error.js","../client/js/version.js","../client/js/features.js","../client/js/promise.js","../client/js/blob-proxy.js","../client/js/button.js","../client/js/upload-data.js","../client/js/uploader.basic.api.js","../client/js/uploader.basic.js","../client/js/ajax.requester.js","../client/js/upload-handler/upload.handler.js","../client/js/upload-handler/upload.handler.controller.js","../client/js/window.receive.message.js","../client/js/upload-handler/form.upload.handler.js","../client/js/upload-handler/xhr.upload.handler.js","../client/js/deletefile.ajax.requester.js","../client/js/image-support/megapix-image.js","../client/js/image-support/image.js","../client/js/image-support/exif.js","../client/js/identify.js","../client/js/image-support/validation.image.js","../client/js/session.js","../client/js/session.ajax.requester.js","../client/js/image-support/scaler.js","../client/js/third-party/ExifRestorer.js","../client/js/total-progress.js","../client/js/paste.js","../client/js/form-support.js","../client/js/traditional/traditional.form.upload.handler.js","../client/js/traditional/traditional.xhr.upload.handler.js","../client/js/traditional/all-chunks-done.ajax.requester.js","../client/js/dnd.js","../client/js/uploader.api.js","../client/js/uploader.js","../client/js/templating.js","../client/js/ui.handler.events.js","../client/js/ui.handler.click.filebuttons.js","../client/js/ui.handler.click.filename.js","../client/js/ui.handler.focusin.filenameinput.js","../client/js/ui.handler.focus.filenameinput.js","../client/js/ui.handler.edit.filename.js"],"names":["global","qq","element","hide","style","display","this","attach","type","fn","addEventListener","attachEvent","detach","removeEventListener","detachEvent","contains","descendant","compareDocumentPosition","insertBefore","elementB","parentNode","remove","removeChild","css","styles","Error","opacity","filter","Math","round","extend","hasClass","name","considerParent","re","RegExp","test","className","addClass","removeClass","replace","getByClass","first","candidates","result","querySelector","querySelectorAll","getElementsByTagName","each","idx","val","push","getFirstByClass","children","child","firstChild","nodeType","nextSibling","setText","text","innerText","textContent","clearText","hasAttribute","attrName","attrVal","exec","getAttribute","undefined","canvasToBlob","canvas","mime","quality","dataUriToBlob","toDataURL","dataUri","arrayBuffer","byteString","intArray","mimeString","createBlob","data","BlobBuilder","window","WebKitBlobBuilder","MozBlobBuilder","MSBlobBuilder","blobBuilder","append","getBlob","Blob","split","indexOf","atob","decodeURI","ArrayBuffer","length","Uint8Array","character","charCodeAt","log","message","level","console","isObject","variable","Object","prototype","toString","call","isFunction","isArray","value","buffer","constructor","isItemList","maybeItemList","isNodeList","maybeNodeList","item","namedItem","isString","maybeString","trimStr","string","String","trim","format","str","args","Array","slice","arguments","newStr","nextIdxToReplace","strBefore","substring","strAfter","isFile","maybeFile","File","isFileList","maybeFileList","FileList","isFileOrInput","maybeFileOrInput","isInput","maybeInput","notFile","evaluateType","normalizedType","toLowerCase","HTMLInputElement","tagName","isBlob","maybeBlob","isXhrUploadSupported","input","document","createElement","multiple","FormData","createXhrInstance","upload","XMLHttpRequest","ActiveXObject","error","isFolderDropSupported","dataTransfer","items","webkitGetAsEntry","isFileChunkingSupported","androidStock","webkitSlice","mozSlice","sliceBlob","fileOrBlob","start","end","slicer","arrayBufferToHex","bytesAsHex","bytes","byt","byteAsHexStr","readBlobToHex","blob","startOffset","initialBlob","fileReader","FileReader","promise","Promise","onload","success","onerror","failure","readAsArrayBuffer","second","extendNested","prop","override","target","sourceFn","super_","source","srcPropName","srcPropVal","arr","elt","from","len","hasOwnProperty","getUniqueId","c","r","random","v","ie","navigator","userAgent","ie7","ie8","ie10","ie11","edge","safari","vendor","chrome","opera","firefox","windows","platform","android","ios6","ios","ios7","ios8","ios800","iosChrome","iosSafari","iosSafariWebView","preventDefault","e","returnValue","toElement","div","html","innerHTML","iterableItem","callback","keyOrIndex","retVal","Storage","key","getItem","charAt","bind","oldFunc","context","newArgs","concat","apply","obj2url","obj","temp","prefixDone","uristrings","prefix","add","nextObj","i","nextTemp","encodeURIComponent","join","obj2FormData","formData","arrayKeyName","obj2Inputs","form","setAttribute","appendChild","parseJson","json","JSON","parse","eval","getExtension","filename","extIdx","lastIndexOf","substr","getFilename","blobOrFileInput","fileName","DisposeSupport","disposers","dispose","disposer","shift","addDisposer","disposeFunction","define","amd","module","exports","version","supportedFeatures","testSupportsFileInputElement","tempInput","supported","disabled","ex","isChrome21OrHigher","match","isChrome14OrHigher","isCrossOriginXhrSupported","xhr","withCredentials","isXdrSupported","XDomainRequest","isCrossOriginAjaxSupported","isFolderSelectionSupported","webkitdirectory","isLocalStorageSupported","localStorage","setItem","isDragAndDropSupported","span","supportsUploading","supportsUploadingBlobs","supportsFileDrop","supportsAjaxFileUploading","supportsFolderDrop","supportsChunking","supportsResume","supportsUploadViaPaste","supportsUploadCors","supportsDeleteFileXdr","supportsDeleteFileCorsXhr","supportsDeleteFileCors","supportsFolderSelection","supportsImagePreviews","supportsUploadProgress","postMessage","ajaxUploading","blobUploading","canDetermineSize","chunking","deleteFileCors","deleteFileCorsXdr","deleteFileCorsXhr","dialogElement","HTMLDialogElement","fileDrop","folderDrop","folderSelection","imagePreviews","imageValidation","itemSizeValidation","pause","progressBar","resume","scaling","tiffPreviews","unlimitedScaledImageSize","uploading","uploadCors","uploadCustomHeaders","uploadNonMultipart","uploadViaPaste","isGenericPromise","maybePromise","then","successArgs","failureArgs","successCallbacks","failureCallbacks","doneCallbacks","state","onSuccess","onFailure","done","BlobProxy","referenceBlob","onCreate","create","UploadButton","o","createInput","BUTTON_ID_ATTR_NAME","buttonId","options","title","self","setMultiple","folders","acceptFiles","position","right","top","fontFamily","fontSize","margin","padding","cursor","height","disposeSupport","onChange","hoverClass","focusClass","ios8BrowserCrashWorkaround","overflow","direction","getInput","getButtonId","isMultiple","optInput","removeAttribute","setAcceptFiles","reset","UploadData","uploaderProxy","getDataByIds","idOrIds","entries","id","getDataByUuids","uuids","uuid","byUuid","getDataByStatus","status","statusResults","statuses","index","statusEnum","statusResultIndexes","byStatus","dataIndex","byProxyGroupId","byBatchId","addFile","spec","SUBMITTING","originalName","size","batchId","proxyGroupId","onStatusChange","retrieve","optionalFilter","setStatus","newStatus","oldStatus","byStatusOldStatusIndex","splice","uuidChanged","newUuid","oldUuid","updateName","newName","updateSize","newSize","setParentId","targetId","parentId","getIdsInProxyGroup","getIdsInBatch","SUBMITTED","REJECTED","QUEUED","CANCELED","PAUSED","UPLOADING","UPLOAD_RETRYING","UPLOAD_SUCCESSFUL","UPLOAD_FAILED","DELETE_FAILED","DELETING","DELETED","basePublicApi","addBlobs","blobDataOrArray","params","endpoint","addFiles","addInitialFiles","cannedFileList","cannedFile","_addCannedFile","_maybeHandleIos8SafariWorkaround","_storedIds","_currentBatchId","processBlob","_handleNewFile","_options","blobs","defaultName","verifiedFiles","processBlobData","blobData","processCanvas","processCanvasData","canvasData","normalizedQuality","processFileOrInput","fileOrInput","files","file","normalizeData","fileContainer","_prepareItemsForUpload","cancel","_handler","cancelAll","storedIdsCopy","storedFileId","clearStoredFiles","continueUpload","uploadData","_uploadData","enabled","getName","_uploadFile","deleteFile","_onSubmitDelete","doesExist","fileOrBlobId","isValid","drawThumbnail","fileId","imgOrCanvas","maxSize","fromServer","customResizeFunction","fileOrUrl","promiseToReturn","_imageGenerator","_thumbnailUrls","scale","getFile","container","generate","modifiedContainer","reason","getButton","_getButton","_buttonIdsForFileIds","getEndpoint","_endpointStore","get","getInProgress","getParentId","uploadDataEntry","getUploads","getResumableFilesData","getSize","getNetUploads","_netUploaded","getRemainingAllowedItems","allowedItems","_currentItemLimit","_netUploadedOrQueued","getUuid","debug","pauseUpload","_autoRetries","_retryTimeouts","_preventRetries","_buttons","button","_paramsStore","_pasteHandler","session","refreshOnReset","_refreshSessionData","_succeededSinceLastAllComplete","_failedSinceLastAllComplete","_totalProgress","retry","_manualRetry","scaleImage","specs","Scaler","setCustomHeaders","headers","_customHeadersStore","set","setDeleteFileCustomHeaders","_deleteFileCustomHeadersStore","setDeleteFileEndpoint","_deleteFileEndpointStore","setDeleteFileParams","_deleteFileParamsStore","setEndpoint","setForm","elementOrId","_updateFormSupportAndParams","setItemLimit","newItemLimit","setName","setParams","setUuid","uploadStoredFiles","_itemError","_uploadStoredFiles","basePrivateApi","sessionData","deleteFileEndpoint","deleteFileParams","thumbnailUrl","_annotateWithButtonId","associatedInput","qqButtonId","_getButtonId","_batchError","callbacks","onError","_createDeleteHandler","DeleteFileAjaxRequester","method","toUpperCase","maxConnections","uuidParamName","request","uuidName","customHeaders","paramsStore","endpointStore","cors","onDelete","_onDelete","onDeleteComplete","xhrOrXdr","isError","_onDeleteComplete","_createPasteHandler","PasteSupport","targetElement","paste","pasteReceived","_handleCheckedCallback","onPasteReceived","_handlePasteSuccess","identifier","_createStore","initialValue","_readOnlyValues_","store","catchall","perIdReadOnlyValues","readOnlyValues","copy","orig","getReadOnlyValues","includeReadOnlyValues","existing","values","addReadOnly","_createUploadDataTracker","_onUploadStatusChange","_maybeAllComplete","setTimeout","_createUploadButton","allowMultiple","workarounds","iosEmptyVideos","_isAllowedExtension","allowedExtensions","accept","validation","classes","buttonFocus","buttonHover","ios8BrowserCrash","inputName","_onInputChange","fileInputTitle","_disposeSupport","_createUploadHandler","additionalOptions","namespace","lastOnProgress","preventRetryParam","preventRetryResponseProperty","onProgress","loaded","total","_onProgress","onComplete","_onComplete","onCancel","cancelFinalizationEffort","_onCancel","onUploadPrep","_onUploadPrep","onUpload","_onUpload","onUploadChunk","chunkData","_onUploadChunk","onUploadChunkSuccess","onResume","onAutoRetry","responseJSON","_onAutoRetry","onUuidChanged","setSize","_setSize","getDataByUuid","isQueued","UploadHandlerController","_fileOrBlobRejected","_formatSize","sizeSymbols","max","toFixed","_generateExtraButtonSpecs","_extraButtonSpecs","extraButtons","extraButtonOptionEntry","extraButtonSpec","_initExtraButton","extraButtonsSpec","_defaultButtonId","buttonOrFileInputOrFile","inputs","fileInput","fileBlobOrInput","_getNotFinished","_getValidationBase","_getValidationDescriptor","fileWrapper","_getValidationDescriptors","fileWrappers","fileDescriptors","_handleCameraAccess","camera","acceptIosCamera","optionRoot","details","callbackRetVal","successParam","newFileWrapperList","actualFile","handler","_customNewFileHandler","_handleNewFileGeneric","addFileToHandler","_trackButton","fileList","extSuppliedName","extension","_initFormSupportAndParams","_formSupport","FormSupport","attachedToForm","getFormInputsAsObject","autoUpload","newAutoUpload","newEndpoint","_isDeletePossible","expected","allowXdr","allowed","valid","allowedExt","extRegex","code","maybeNameOrNames","replacement","extensionsForMessage","placeholderMatch","messages","names","validationBase","allowedExtension","formatFileName","sizeLimit","minSizeLimit","placeholder","_onBeforeManualRetry","notFinished","_onAllComplete","ios8SafariUploads","alert","unsupportedBrowserIos8Safari","_maybeParseAndSendUploadError","response","errorReason","defaultResponseError","_maybeProcessNextItemAfterOnValidateCallback","validItem","stopOnFirstInvalidFile","validationDescriptor","onValidate","_onValidateCallbackSuccess","_onValidateCallbackFailure","successful","failed","onAllComplete","_shouldAutoRetry","retryWaitPeriod","autoAttemptDelay","_onBeforeAutoRetry","itemLimit","onManualRetry","clearTimeout","storedItemIndex","expunge","fileIndex","onIndividualProgress","_onSubmit","_onSubmitCallbackSuccess","_onSubmitted","onSubmitted","_storeForLater","onSuccessCallback","additionalMandatedParams","adjustedOnSuccessCallback","onSubmitDelete","_deleteHandler","sendDelete","_onTotalProgress","onTotalProgress","_onValidateBatchCallbackFailure","_onValidateBatchCallbackSuccess","validationDescriptors","errorMessage","proposedNetFilesUploadedOrQueued","tooManyItemsError","nextIndex","_validateFileOrBlobData","_upload","onValidateBatch","_preventLeaveInProgress","event","onLeave","Session","_session","addFileRecord","refresh","_sessionRequestComplete","onSessionRequestComplete","onNewSize","enableAuto","maxAutoAttempts","formElementOrId","onSubmit","idToUpload","stillSubmitting","validityChecker","allowEmpty","ImageValidation","validate","image","errorCode","_wrapCallbacks","safeCallback","errorMsg","exception","callbackName","callbackFunc","FineUploaderBasic","disableCancelForFormUploads","filenameParam","forceMultipart","paramsInBody","totalFileSizeName","maxHeight","maxWidth","minHeight","minWidth","maybeXhr","maybeXhrOrXdr","attemptNumber","fileOrBlobData","typeError","sizeError","minSizeError","emptyError","noFilesError","maxHeightImageError","maxWidthImageError","minHeightImageError","minWidthImageError","retryFailTooManyItems","concurrent","mandatory","paramNames","partIndex","partByteOffset","chunkSize","totalFileSize","totalParts","partSize","recordsExpireIn","resuming","fileOrBlobName","sendCredentials","interceptSubmit","customResizer","sendOriginal","orient","defaultType","defaultQuality","failureText","includeExif","sizes","ImageGenerator","_scaler","handleNewFile","TotalProgress","entry","AjaxRequester","isSimpleMethod","containsNonSimpleHeaders","containsNonSimple","header","isXdr","getCorsAjaxTransport","ontimeout","onprogress","getXhrOrXdr","suppliedXhr","requestData","dequeue","nextId","queue","sendRequest","xdrError","isResponseSuccessful","getParams","onDemandParams","additionalParams","mandatedParams","optXhr","url","payload","onSend","createUrl","additionalQueryParams","getXdrLoadHandler","getXdrErrorHandler","onreadystatechange","getXhrReadyStateChangeHandler","registerForUploadProgress","open","setHeaders","send","shouldParamsBeInQueryString","contentType","stringify","addToPath","readyState","lengthComputable","onDemandHeaders","additionalHeaders","allHeaders","acceptHeader","setRequestHeader","allowXRequestedWithAndCacheControl","responseCode","successfulResponseCodes","prepareToSend","validMethods","DELETE","PATCH","POST","PUT","GET","initTransport","path","cacheBuster","withPath","appendToPath","withParams","withQueryParams","_additionalQueryParams_","withHeaders","withPayload","thePayload","withCacheBuster","qqtimestamp","Date","getTime","canceled","UploadHandler","proxy","fileState","fileItem","onCancelRetVal","getThirdPartyFileId","_getFileState","_setThirdPartyFileId","thirdPartyFileId","_wasCanceled","preventRetryResponse","controller","chunkingPossible","concurrentChunkingPossible","chunked","chunkIdx","_getChunkData","attemptingResume","chunkProgress","_getChunkDataForCallback","finalize","finalizeChunks","normaizedResponse","normalizeResponse","_maybeDeletePersistedChunkData","cleanup","handleFailure","clearCachedChunk","inProgressIdx","responseToReport","inProgress","remaining","unshift","ignoreFailure","keys","_getXhrs","ckid","ckXhr","abort","_cancelled","moveInProgressToRemaining","connectionManager","free","hasMoreParts","nextPart","nextIdx","_getTotalChunks","reevaluateChunking","sendNext","inProgressChunks","available","uploadChunk","inProgressChunkIdx","_maybePersistChunkedState","clearXhr","_open","_openChunks","_waiting","openChunkEntriesCount","openChunksCount","openChunkIndexes","dontAllowNext","allowNext","waitingIndex","connectionsIndex","getProxyOrBlob","getWaitingOrConnected","waitingOrConnected","chunks","parseInt","isUsingConnection","pop","openChunksEntry","simple","uploadFile","maybeNewUuid","_clearXhrs","getProxy","initHandler","handlerType","traditional","handlerModuleSubtype","_removeExpiredChunkingRecords","isDeferredEligibleForUpload","maybeDefer","generatedBlob","updateBlob","maybeSendDeferredFiles","errorResponse","idsInGroup","uploadedThisId","idInGroup","now","originalResponse","_shouldChunkThisFile","blobToUpload","cancelRetVal","isProxied","isResumable","WindowReceiveMessage","callbackWrapperDetachers","receiveMessage","onMessageCallbackWrapper","stopReceivingMessages","detacher","FormUploadHandler","expungeFile","detachLoadEvents","isCors","postMessageCallbackTimers","corsMessageReceiver","iframe","getElementById","_getIframeName","getFileIdForIframeName","iframeName","initIframeForUpload","body","registerPostMessageCallback","onloadCallbacks","onloadCallback","_parseJsonResponse","_detachLoadEvent","formHandlerInstanceId","_attachLoadEvent","responseDescriptor","contentDocument","_createIframe","_initFormForUpload","targetName","innerHtmlOrMessage","XhrUploadHandler","xhrId","ajaxRequester","_getAjaxRequester","chunkFiles","resumeEnabled","blobOrProxy","_initTempState","_maybePrepareForResume","cachedChunks","tempState","xhrs","ajaxRequesters","responseParser","lastChunkIdx","_getXhr","resumableFilesData","_iterateResumeRecords","notResumable","optInProgress","optRemaining","reverse","paused","totalChunks","parts","newBlob","chunkId","_createXhr","optChunkIdx","_registerXhr","chunkIndex","fileSize","startBytes","endBytes","part","count","startByte","endByte","_getLocalStorageId","formatVersion","_getMimeType","_getPersistableData","ceil","_markNotResumable","localStorageId","removeItem","persistedData","lastUpdated","_registerProgressHandler","progressCalculator","totalSuccessfullyLoadedForFile","loadedForRequest","totalForRequest","estActualChunkLoaded","totalLoadedForFile","chunkLoaded","optAjaxRequester","xhrsId","expirationDays","expirationDate","setDate","getDate","getMandatedParams","_method","requester","detectSubsampling","img","ctx","iw","naturalWidth","ih","naturalHeight","width","getContext","drawImage","getImageData","detectVerticalSquash","alpha","ratio","sy","ey","py","renderImageToDataURL","doSquash","renderImageToCanvas","maybeCalculateDownsampledDimensions","maxPixels","origHeight","origWidth","newHeight","sqrt","newWidth","modifiedDimensions","save","resize","renderImageToCanvasWithCustomResizer","imageHeight","imageWidth","orientation","targetHeight","targetWidth","transformCoordinate","tmpCtx","sx","dx","d","tmpCanvas","vertSquashRatio","dw","dh","dy","clearRect","restore","qqImageRendered","resizeInfo","sourceCanvas","sourceCanvasContext","targetCanvas","translate","rotate","PI","MegaPixImage","srcImage","errorCallback","Image","URL","createObjectURL","webkitURL","src","listeners","imageLoadListeners","render","opt","imgWidth","imgHeight","optionsKey","optionsValue","oldTargetSrc","onrender","isImg","el","isCanvas","isImgCorsSupported","crossOrigin","isCanvasSupported","determineMimeOfFileName","nameWithPath","pathSegments","isCrossOrigin","targetProtocol","targetHostname","targetPort","targetAnchor","href","protocol","port","hostname","location","registerImgLoadListeners","registerCanvasDrawImageListener","registerThumbnailRenderedListener","registered","draw","drawPreview","Identify","megapixErrorHandler","isPreviewable","dummyExif","exif","Exif","mpImg","Orientation","failureMsg","drawOnCanvasOrImgFromUrl","canvasOrImg","tempImg","tempImgRender","drawOnImgFromUrlWithCssScaling","drawFromUrl","fileBlobOrUrl","_testing","parseLittleEndian","hex","pow","seekToApp1","offset","theOffset","thePromise","segmentLength","getApp1Offset","isLittleEndian","app1Start","getDirEntryCount","littleEndian","getIfd","dirEntries","getDirEntries","ifdHex","getTagValues","TAG_VAL_OFFSET","tagsToFind","TAG_IDS","vals","tagValHex","tagValLength","idHex","tagsToFindIdx","TAG_INFO","274","parser","onParseFailure","app1Offset","dirEntryCount","tagValues","isIdentifiable","magicBytes","questionableBytes","identifiable","magicBytesEntries","magicBytesArrayEntry","previewable","isPreviewableSync","PREVIEWABLE_MIME_TYPES","fileMime","isRecognizedImage","image/jpeg","image/gif","image/png","image/bmp","image/tiff","hasNonZeroLimits","limits","atLeastOne","limit","getWidthHeight","sizeDetermination","getFailingLimit","dimensions","failingLimit","limitName","limitValue","limitMatcher","dimensionPropName","actualValue","validationEffort","isJsonResponseValid","handleFileItems","fileItems","someItemsIgnored","err","refreshEffort","refreshCompleteCallback","requesterOptions","SessionAjaxRequester","queryServer","responseText","includeOriginal","failedToScaleText","_getSortedSizes","getFileRecords","originalFileUuid","originalFileName","originalBlobOrBlobData","records","originalBlob","sizeRecord","outputType","_determineOutputType","requestedType","refType","_getName","_generateScaledImage","failedText","api","scaledIds","originalId","record","blobSize","scaledId","qqparentuuid","qqparentsize","param","scalingEffort","scalingOptions","scaler","referenceType","scaledVersionProperties","startOfExt","versionType","scaledName","scaledExt","nameAppendage","sort","a","b","sourceFile","imageGenerator","scaledImageDataUri","signalSuccess","_insertExifHeader","scaledImageDataUriWithExif","originalImage","reader","insertionEffort","originalImageDataUri","ExifRestorer","readAsDataURL","_dataUriToBlob","_createBlob","KEY_STR","encode64","chr1","chr2","enc1","enc2","enc3","output","chr3","enc4","isNaN","origFileBase64","resizedFileBase64","expectedBase64Header","rawImage","decode64","segments","slice2Segments","exifManipulation","exifArray","getExifArray","newImageArray","insertExif","aBuffer","seg","x","imageData","buf","separatePoint","mae","ato","array","rawImageArray","head","endPoint","base64test","perFileProgress","totalLoaded","totalSize","lastLoadedSent","lastTotalSent","callbackProxy","noRetryableFiles","retryable","none","failedId","updateTotalProgress","onNew","newLoaded","newTotal","oldLoaded","oldTotal","isImage","registerPasteHandler","detachPasteHandler","clipboardData","getAsFile","unregisterPasteHandler","startUpload","determineNewEndpoint","formEl","validateForm","nativeSubmit","checkValidity","maybeUploadOnSubmit","submit","determineFormEl","_form2Obj","notIrrelevantType","irrelevantTypes","radioOrCheckbox","ignoreValue","checked","selectValue","select","selected","elements","getIframeContentJson","doc","innerHtml","contentWindow","nodeValue","createForm","responseFromMessage","multipart","addChunkingSpecificParams","allChunksDoneRequester","AllChunksDoneAjaxRequester","createReadyStateChangedHandler","onUploadOrChunkComplete","getChunksCompleteParams","isErrorUploadResponse","parseResponse","sendChunksCompleteRequest","complete","setParamsAndGetEntityToSend","setUploadHeaders","extraHeaders","toSend","promises","endpointHandler","DragAndDrop","uploadDroppedFiles","uploadDropZone","filesAsArray","dropLog","dropDisabled","processingDroppedFilesComplete","getElement","traverseFileTree","parseEntryPromise","fullPath","indexOfNameInFullPath","qqPath","droppedFiles","fileError","isDirectory","getFilesInDirectory","entriesLeft","accumEntries","existingPromise","dirReader","createReader","readEntries","newEntries","handleDataTransfer","pendingFolderPromises","handleDataTransferPromise","processingDroppedFiles","allowMultipleItems","dropError","setupDropzone","dropArea","dropZone","UploadDropZone","HIDE_ZONES_EVENT_NAME","onEnter","dropActive","stopPropagation","onLeaveNotDescendants","onDrop","HIDE_BEFORE_ENTER_ATTR","uploadDropZones","isFileDrag","dragEvent","fileDrag","types","leavingDocumentOut","relatedTarget","y","setupDragDrop","dropZones","dropZoneElements","maybeHideDropZones","HTMLElement","setupExtraDropzone","removeDropzone","dzs","targetEl","errorSpecifics","dragoverShouldBeCanceled","disableDropOutside","dropOutsideDisabled","dropEffect","isValidFileDrag","effectTest","dt","isSafari","effectAllowed","isOrSetDropDisabled","isDisabled","preventDrop","triggerHidezonesEvent","triggerUsingOldApi","hideZonesEvent","createEvent","initEvent","CustomEvent","dispatchEvent","attachEvents","effect","elementFromPoint","clientX","clientY","uiPublicApi","_parent","_templating","addCacheToDom","clearFiles","addExtraDropzone","_dnd","removeExtraDropzone","getItemByFileId","isHiddenForever","getFileContainer","_setupDragAndDrop","_totalFilesInBatch","_filesInBatchAddedToUi","_setupClickAndEditEventHandlers","formattedFilename","updateFilename","uploadPaused","continued","uploadContinued","getId","fileContainerOrChildEl","getFileId","getDropTarget","qqDropTarget","uiPrivateApi","_removeFileItem","removeFile","_fileButtonsClickHandler","FileButtonsClickHandler","_bindFileButtonsClickEvent","_focusinEventSupported","_isEditFilenameEnabled","_filenameClickHandler","_bindFilenameClickEvent","_filenameInputFocusInHandler","_bindFilenameInputFocusInEvent","_filenameInputFocusHandler","_bindFilenameInputFocusEvent","dragAndDrop","extraDropzones","templating","defaultDropZone","getDropZone","showDropProcessing","hideDropProcessing","errorData","lvl","onDeleteFile","onRetry","onPause","onContinue","onGetName","isEditFilenamePossible","FilenameClickHandler","FilenameInputFocusHandler","_filenameEditHandler","onGetUploadStatus","onSetName","onEditingStatusChange","isEditing","qqInput","getEditInput","qqFileContainer","hideFilename","hideEditIcon","showFilename","showEditIcon","markFilenameEditable","hideRetry","setStatusText","_classes","retrying","hidePause","FilenameInputFocusInHandler","hideSpinner","resetTotalProgress","reportDirectoryPaths","qqpath","_addToList","addHandler","updateProgress","hideCancel","hideProgress","waitingForResponse","_displayFileSize","completeUpload","_markFileAsSuccessful","fail","showCancel","isRetryPossible","showRetry","_controlFailureTextDisplay","parentRetVal","newResult","showDeleteButton","_maybeUpdateThumbnail","showSpinner","allowPause","retryNumForDisplay","maxAuto","retryNote","_showCancelLink","showAutoRetryNote","autoRetryNote","resetProgress","_onSubmitDeleteSuccess","forceConfirm","_showDeleteConfirm","_sendDeleteRequest","deletingFailedText","hideDeleteButton","deletingStatusText","confirmMessage","deleteRequestArgs","showConfirm","canned","prependData","prependIndex","dontDisplay","hideScaled","prependFiles","disableCancel","_handledProxyGroup","_clearList","addFileToCache","updateThumbnail","thumbnails","generatePreview","fileSizeOnSubmit","loadedSize","sizeForDisplay","_formatProgress","uploadedSize","formatProgress","mode","responseProperty","failureReason","failedUploadTextDisplay","failUpload","enableTooltip","_showTooltip","showMessage","_setupPastePrompt","namePromptMessage","defaultVal","showPrompt","fileStatus","placeholders","waitUntilResponse","FineUploader","listElement","template","editable","tooManyFilesError","unsupportedBrowser","promptForName","maxCount","notAvailablePath","waitingPath","timeBetweenThumbs","hasDialog","showDialog","confirm","defaultValue","prompt","Templating","templateIdOrEl","containerEl","fileContainerEl","maxThumbs","waitUntilUpdate","thumbnailNotAvailable","waitingForThumbnail","renderFailure","isEditElementsExist","isRetryElementExist","templateHtml","showThumbnails","serverScale","FILE_ID_ATTR","FILE_CLASS_PREFIX","THUMBNAIL_MAX_SIZE_ATTR","THUMBNAIL_SERVER_SCALE_ATTR","HIDE_DROPZONE_ATTR","DROPZPONE_TEXT_ATTR","IN_PROGRESS_CLASS","HIDDEN_FOREVER_CLASS","fileBatch","content","createDocumentFragment","map","isCancelDisabled","generatedThumbnails","thumbnailQueueMonitorRunning","thumbGenerationQueue","thumbnailMaxSize","selectorClasses","alertDialog","dialogCancelButton","confirmDialog","dialogMessage","dialogOkButton","promptDialog","uploader","drop","list","progressBarContainer","totalProgressBarContainer","totalProgressBar","spinner","continueButton","deleteButton","statusText","editFilenameInput","editNameIcon","dropText","dropProcessing","dropProcessingSpinner","thumbnail","previewGeneration","cachedThumbnailNotAvailableImg","cachedWaitingForThumbnailImg","cacheThumbnailPlaceholders","notAvailableUrl","waitingUrl","updatedImg","displayWaitingImg","waitingImgPlacement","maybeScalePlaceholderViaCss","show","generateNewPreview","getThumbnail","qqThumbnailId","maybeSetDisplayNotAvailableImg","generateNextQueuedPreview","queuedThumbRequest","update","processUpdateQueuedPreviewRequest","processNewQueuedPreviewRequest","getCancel","getTemplateEl","getContinue","getDialog","getDelete","getDropProcessing","getEditIcon","getPause","getProgress","getRetry","getSpinner","cssClass","previewing","notAvailableImgPlacement","parseAndGetTemplate","scriptEl","scriptHtml","fileListNode","tempTemplateEl","fileListHtml","defaultButton","dropTextEl","uploaderEl","fileTemplate","prependFile","parentEl","beforeEl","optFileOrBlob","relatedThumbnailId","useCachedPreview","showWaitingImg","setProgressBarWidth","percent","bar","progressBarSelector","targetThumbnailId","cachedThumbnailId","targetThumbnail","cachedThumbnail","hideTotalProgress","cantRenderEl","prependInfo","hideForever","batch","thumb","fileEl","fileNameEl","waitingImg","currentNode","getFileList","filenameEl","isFileName","icon","isEditIcon","isEditInput","isCancel","allowContinueButton","isPause","isContinueButton","isDeleteButton","isRetry","textEl","dialog","messageEl","inputEl","cancelBtn","okBtn","closeHandler","cancelClickHandler","okClickHandler","close","showModal","UiEventHandler","s","protectedApi","eventType","srcElement","onHandled","attachTo","getFileIdFromItem","qqFileId","getDisposeSupport","examineEvent","buttonHandlers","buttonType","firstLetterCapButtonType","inheritedInternalApi","handleFilenameEdit","FilenameEditHandler","handleInputFocus","getFilenameSansExtension","filenameSansExt","getOriginalExtension","origName","handleNameUpdate","newFilenameInputEl","origExtension","registerInputBlurHandler","registerInputEnterKeyHandler","keyCode","which","focusInput","focus"],"mappings":"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","file":"fine-uploader.min.js","sourcesContent":[null,"/*globals window, navigator, document, FormData, File, HTMLInputElement, XMLHttpRequest, Blob, Storage, ActiveXObject */\n/* jshint -W079 */\nvar qq = function(element) {\n \"use strict\";\n\n return {\n hide: function() {\n element.style.display = \"none\";\n return this;\n },\n\n /** Returns the function which detaches attached event */\n attach: function(type, fn) {\n if (element.addEventListener) {\n element.addEventListener(type, fn, false);\n } else if (element.attachEvent) {\n element.attachEvent(\"on\" + type, fn);\n }\n return function() {\n qq(element).detach(type, fn);\n };\n },\n\n detach: function(type, fn) {\n if (element.removeEventListener) {\n element.removeEventListener(type, fn, false);\n } else if (element.attachEvent) {\n element.detachEvent(\"on\" + type, fn);\n }\n return this;\n },\n\n contains: function(descendant) {\n // The [W3C spec](http://www.w3.org/TR/domcore/#dom-node-contains)\n // says a `null` (or ostensibly `undefined`) parameter\n // passed into `Node.contains` should result in a false return value.\n // IE7 throws an exception if the parameter is `undefined` though.\n if (!descendant) {\n return false;\n }\n\n // compareposition returns false in this case\n if (element === descendant) {\n return true;\n }\n\n if (element.contains) {\n return element.contains(descendant);\n } else {\n /*jslint bitwise: true*/\n return !!(descendant.compareDocumentPosition(element) & 8);\n }\n },\n\n /**\n * Insert this element before elementB.\n */\n insertBefore: function(elementB) {\n elementB.parentNode.insertBefore(element, elementB);\n return this;\n },\n\n remove: function() {\n element.parentNode.removeChild(element);\n return this;\n },\n\n /**\n * Sets styles for an element.\n * Fixes opacity in IE6-8.\n */\n css: function(styles) {\n /*jshint eqnull: true*/\n if (element.style == null) {\n throw new qq.Error(\"Can't apply style to node as it is not on the HTMLElement prototype chain!\");\n }\n\n /*jshint -W116*/\n if (styles.opacity != null) {\n if (typeof element.style.opacity !== \"string\" && typeof (element.filters) !== \"undefined\") {\n styles.filter = \"alpha(opacity=\" + Math.round(100 * styles.opacity) + \")\";\n }\n }\n qq.extend(element.style, styles);\n\n return this;\n },\n\n hasClass: function(name, considerParent) {\n var re = new RegExp(\"(^| )\" + name + \"( |$)\");\n return re.test(element.className) || !!(considerParent && re.test(element.parentNode.className));\n },\n\n addClass: function(name) {\n if (!qq(element).hasClass(name)) {\n element.className += \" \" + name;\n }\n return this;\n },\n\n removeClass: function(name) {\n var re = new RegExp(\"(^| )\" + name + \"( |$)\");\n element.className = element.className.replace(re, \" \").replace(/^\\s+|\\s+$/g, \"\");\n return this;\n },\n\n getByClass: function(className, first) {\n var candidates,\n result = [];\n\n if (first && element.querySelector) {\n return element.querySelector(\".\" + className);\n }\n else if (element.querySelectorAll) {\n return element.querySelectorAll(\".\" + className);\n }\n\n candidates = element.getElementsByTagName(\"*\");\n\n qq.each(candidates, function(idx, val) {\n if (qq(val).hasClass(className)) {\n result.push(val);\n }\n });\n return first ? result[0] : result;\n },\n\n getFirstByClass: function(className) {\n return qq(element).getByClass(className, true);\n },\n\n children: function() {\n var children = [],\n child = element.firstChild;\n\n while (child) {\n if (child.nodeType === 1) {\n children.push(child);\n }\n child = child.nextSibling;\n }\n\n return children;\n },\n\n setText: function(text) {\n element.innerText = text;\n element.textContent = text;\n return this;\n },\n\n clearText: function() {\n return qq(element).setText(\"\");\n },\n\n // Returns true if the attribute exists on the element\n // AND the value of the attribute is NOT \"false\" (case-insensitive)\n hasAttribute: function(attrName) {\n var attrVal;\n\n if (element.hasAttribute) {\n\n if (!element.hasAttribute(attrName)) {\n return false;\n }\n\n /*jshint -W116*/\n return (/^false$/i).exec(element.getAttribute(attrName)) == null;\n }\n else {\n attrVal = element[attrName];\n\n if (attrVal === undefined) {\n return false;\n }\n\n /*jshint -W116*/\n return (/^false$/i).exec(attrVal) == null;\n }\n }\n };\n};\n\n(function() {\n \"use strict\";\n\n qq.canvasToBlob = function(canvas, mime, quality) {\n return qq.dataUriToBlob(canvas.toDataURL(mime, quality));\n };\n\n qq.dataUriToBlob = function(dataUri) {\n var arrayBuffer, byteString,\n createBlob = function(data, mime) {\n var BlobBuilder = window.BlobBuilder ||\n window.WebKitBlobBuilder ||\n window.MozBlobBuilder ||\n window.MSBlobBuilder,\n blobBuilder = BlobBuilder && new BlobBuilder();\n\n if (blobBuilder) {\n blobBuilder.append(data);\n return blobBuilder.getBlob(mime);\n }\n else {\n return new Blob([data], {type: mime});\n }\n },\n intArray, mimeString;\n\n // convert base64 to raw binary data held in a string\n if (dataUri.split(\",\")[0].indexOf(\"base64\") >= 0) {\n byteString = atob(dataUri.split(\",\")[1]);\n }\n else {\n byteString = decodeURI(dataUri.split(\",\")[1]);\n }\n\n // extract the MIME\n mimeString = dataUri.split(\",\")[0]\n .split(\":\")[1]\n .split(\";\")[0];\n\n // write the bytes of the binary string to an ArrayBuffer\n arrayBuffer = new ArrayBuffer(byteString.length);\n intArray = new Uint8Array(arrayBuffer);\n qq.each(byteString, function(idx, character) {\n intArray[idx] = character.charCodeAt(0);\n });\n\n return createBlob(arrayBuffer, mimeString);\n };\n\n qq.log = function(message, level) {\n if (window.console) {\n if (!level || level === \"info\") {\n window.console.log(message);\n }\n else\n {\n if (window.console[level]) {\n window.console[level](message);\n }\n else {\n window.console.log(\"<\" + level + \"> \" + message);\n }\n }\n }\n };\n\n qq.isObject = function(variable) {\n return variable && !variable.nodeType && Object.prototype.toString.call(variable) === \"[object Object]\";\n };\n\n qq.isFunction = function(variable) {\n return typeof (variable) === \"function\";\n };\n\n /**\n * Check the type of a value. Is it an \"array\"?\n *\n * @param value value to test.\n * @returns true if the value is an array or associated with an `ArrayBuffer`\n */\n qq.isArray = function(value) {\n return Object.prototype.toString.call(value) === \"[object Array]\" ||\n (value && window.ArrayBuffer && value.buffer && value.buffer.constructor === ArrayBuffer);\n };\n\n // Looks for an object on a `DataTransfer` object that is associated with drop events when utilizing the Filesystem API.\n qq.isItemList = function(maybeItemList) {\n return Object.prototype.toString.call(maybeItemList) === \"[object DataTransferItemList]\";\n };\n\n // Looks for an object on a `NodeList` or an `HTMLCollection`|`HTMLFormElement`|`HTMLSelectElement`\n // object that is associated with collections of Nodes.\n qq.isNodeList = function(maybeNodeList) {\n return Object.prototype.toString.call(maybeNodeList) === \"[object NodeList]\" ||\n // If `HTMLCollection` is the actual type of the object, we must determine this\n // by checking for expected properties/methods on the object\n (maybeNodeList.item && maybeNodeList.namedItem);\n };\n\n qq.isString = function(maybeString) {\n return Object.prototype.toString.call(maybeString) === \"[object String]\";\n };\n\n qq.trimStr = function(string) {\n if (String.prototype.trim) {\n return string.trim();\n }\n\n return string.replace(/^\\s+|\\s+$/g, \"\");\n };\n\n /**\n * @param str String to format.\n * @returns {string} A string, swapping argument values with the associated occurrence of {} in the passed string.\n */\n qq.format = function(str) {\n\n var args = Array.prototype.slice.call(arguments, 1),\n newStr = str,\n nextIdxToReplace = newStr.indexOf(\"{}\");\n\n qq.each(args, function(idx, val) {\n var strBefore = newStr.substring(0, nextIdxToReplace),\n strAfter = newStr.substring(nextIdxToReplace + 2);\n\n newStr = strBefore + val + strAfter;\n nextIdxToReplace = newStr.indexOf(\"{}\", nextIdxToReplace + val.length);\n\n // End the loop if we have run out of tokens (when the arguments exceed the # of tokens)\n if (nextIdxToReplace < 0) {\n return false;\n }\n });\n\n return newStr;\n };\n\n qq.isFile = function(maybeFile) {\n return window.File && Object.prototype.toString.call(maybeFile) === \"[object File]\";\n };\n\n qq.isFileList = function(maybeFileList) {\n return window.FileList && Object.prototype.toString.call(maybeFileList) === \"[object FileList]\";\n };\n\n qq.isFileOrInput = function(maybeFileOrInput) {\n return qq.isFile(maybeFileOrInput) || qq.isInput(maybeFileOrInput);\n };\n\n qq.isInput = function(maybeInput, notFile) {\n var evaluateType = function(type) {\n var normalizedType = type.toLowerCase();\n\n if (notFile) {\n return normalizedType !== \"file\";\n }\n\n return normalizedType === \"file\";\n };\n\n if (window.HTMLInputElement) {\n if (Object.prototype.toString.call(maybeInput) === \"[object HTMLInputElement]\") {\n if (maybeInput.type && evaluateType(maybeInput.type)) {\n return true;\n }\n }\n }\n if (maybeInput.tagName) {\n if (maybeInput.tagName.toLowerCase() === \"input\") {\n if (maybeInput.type && evaluateType(maybeInput.type)) {\n return true;\n }\n }\n }\n\n return false;\n };\n\n qq.isBlob = function(maybeBlob) {\n if (window.Blob && Object.prototype.toString.call(maybeBlob) === \"[object Blob]\") {\n return true;\n }\n };\n\n qq.isXhrUploadSupported = function() {\n var input = document.createElement(\"input\");\n input.type = \"file\";\n\n return (\n input.multiple !== undefined &&\n typeof File !== \"undefined\" &&\n typeof FormData !== \"undefined\" &&\n typeof (qq.createXhrInstance()).upload !== \"undefined\");\n };\n\n // Fall back to ActiveX is native XHR is disabled (possible in any version of IE).\n qq.createXhrInstance = function() {\n if (window.XMLHttpRequest) {\n return new XMLHttpRequest();\n }\n\n try {\n return new ActiveXObject(\"MSXML2.XMLHTTP.3.0\");\n }\n catch (error) {\n qq.log(\"Neither XHR or ActiveX are supported!\", \"error\");\n return null;\n }\n };\n\n qq.isFolderDropSupported = function(dataTransfer) {\n return dataTransfer.items &&\n dataTransfer.items.length > 0 &&\n dataTransfer.items[0].webkitGetAsEntry;\n };\n\n qq.isFileChunkingSupported = function() {\n return !qq.androidStock() && //Android's stock browser cannot upload Blobs correctly\n qq.isXhrUploadSupported() &&\n (File.prototype.slice !== undefined || File.prototype.webkitSlice !== undefined || File.prototype.mozSlice !== undefined);\n };\n\n qq.sliceBlob = function(fileOrBlob, start, end) {\n var slicer = fileOrBlob.slice || fileOrBlob.mozSlice || fileOrBlob.webkitSlice;\n\n return slicer.call(fileOrBlob, start, end);\n };\n\n qq.arrayBufferToHex = function(buffer) {\n var bytesAsHex = \"\",\n bytes = new Uint8Array(buffer);\n\n qq.each(bytes, function(idx, byt) {\n var byteAsHexStr = byt.toString(16);\n\n if (byteAsHexStr.length < 2) {\n byteAsHexStr = \"0\" + byteAsHexStr;\n }\n\n bytesAsHex += byteAsHexStr;\n });\n\n return bytesAsHex;\n };\n\n qq.readBlobToHex = function(blob, startOffset, length) {\n var initialBlob = qq.sliceBlob(blob, startOffset, startOffset + length),\n fileReader = new FileReader(),\n promise = new qq.Promise();\n\n fileReader.onload = function() {\n promise.success(qq.arrayBufferToHex(fileReader.result));\n };\n\n fileReader.onerror = promise.failure;\n\n fileReader.readAsArrayBuffer(initialBlob);\n\n return promise;\n };\n\n qq.extend = function(first, second, extendNested) {\n qq.each(second, function(prop, val) {\n if (extendNested && qq.isObject(val)) {\n if (first[prop] === undefined) {\n first[prop] = {};\n }\n qq.extend(first[prop], val, true);\n }\n else {\n first[prop] = val;\n }\n });\n\n return first;\n };\n\n /**\n * Allow properties in one object to override properties in another,\n * keeping track of the original values from the target object.\n *\n * Note that the pre-overriden properties to be overriden by the source will be passed into the `sourceFn` when it is invoked.\n *\n * @param target Update properties in this object from some source\n * @param sourceFn A function that, when invoked, will return properties that will replace properties with the same name in the target.\n * @returns {object} The target object\n */\n qq.override = function(target, sourceFn) {\n var super_ = {},\n source = sourceFn(super_);\n\n qq.each(source, function(srcPropName, srcPropVal) {\n if (target[srcPropName] !== undefined) {\n super_[srcPropName] = target[srcPropName];\n }\n\n target[srcPropName] = srcPropVal;\n });\n\n return target;\n };\n\n /**\n * Searches for a given element (elt) in the array, returns -1 if it is not present.\n */\n qq.indexOf = function(arr, elt, from) {\n if (arr.indexOf) {\n return arr.indexOf(elt, from);\n }\n\n from = from || 0;\n var len = arr.length;\n\n if (from < 0) {\n from += len;\n }\n\n for (; from < len; from += 1) {\n if (arr.hasOwnProperty(from) && arr[from] === elt) {\n return from;\n }\n }\n return -1;\n };\n\n //this is a version 4 UUID\n qq.getUniqueId = function() {\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, function(c) {\n /*jslint eqeq: true, bitwise: true*/\n var r = Math.random() * 16 | 0, v = c == \"x\" ? r : (r & 0x3 | 0x8);\n return v.toString(16);\n });\n };\n\n //\n // Browsers and platforms detection\n qq.ie = function() {\n return navigator.userAgent.indexOf(\"MSIE\") !== -1 ||\n navigator.userAgent.indexOf(\"Trident\") !== -1;\n };\n\n qq.ie7 = function() {\n return navigator.userAgent.indexOf(\"MSIE 7\") !== -1;\n };\n\n qq.ie8 = function() {\n return navigator.userAgent.indexOf(\"MSIE 8\") !== -1;\n };\n\n qq.ie10 = function() {\n return navigator.userAgent.indexOf(\"MSIE 10\") !== -1;\n };\n\n qq.ie11 = function() {\n return qq.ie() && navigator.userAgent.indexOf(\"rv:11\") !== -1;\n };\n\n qq.edge = function() {\n return navigator.userAgent.indexOf(\"Edge\") >= 0;\n };\n\n qq.safari = function() {\n return navigator.vendor !== undefined && navigator.vendor.indexOf(\"Apple\") !== -1;\n };\n\n qq.chrome = function() {\n return navigator.vendor !== undefined && navigator.vendor.indexOf(\"Google\") !== -1;\n };\n\n qq.opera = function() {\n return navigator.vendor !== undefined && navigator.vendor.indexOf(\"Opera\") !== -1;\n };\n\n qq.firefox = function() {\n return (!qq.edge() && !qq.ie11() && navigator.userAgent.indexOf(\"Mozilla\") !== -1 && navigator.vendor !== undefined && navigator.vendor === \"\");\n };\n\n qq.windows = function() {\n return navigator.platform === \"Win32\";\n };\n\n qq.android = function() {\n return navigator.userAgent.toLowerCase().indexOf(\"android\") !== -1;\n };\n\n // We need to identify the Android stock browser via the UA string to work around various bugs in this browser,\n // such as the one that prevents a `Blob` from being uploaded.\n qq.androidStock = function() {\n return qq.android() && navigator.userAgent.toLowerCase().indexOf(\"chrome\") < 0;\n };\n\n qq.ios6 = function() {\n return qq.ios() && navigator.userAgent.indexOf(\" OS 6_\") !== -1;\n };\n\n qq.ios7 = function() {\n return qq.ios() && navigator.userAgent.indexOf(\" OS 7_\") !== -1;\n };\n\n qq.ios8 = function() {\n return qq.ios() && navigator.userAgent.indexOf(\" OS 8_\") !== -1;\n };\n\n // iOS 8.0.0\n qq.ios800 = function() {\n return qq.ios() && navigator.userAgent.indexOf(\" OS 8_0 \") !== -1;\n };\n\n qq.ios = function() {\n /*jshint -W014 */\n return navigator.userAgent.indexOf(\"iPad\") !== -1\n || navigator.userAgent.indexOf(\"iPod\") !== -1\n || navigator.userAgent.indexOf(\"iPhone\") !== -1;\n };\n\n qq.iosChrome = function() {\n return qq.ios() && navigator.userAgent.indexOf(\"CriOS\") !== -1;\n };\n\n qq.iosSafari = function() {\n return qq.ios() && !qq.iosChrome() && navigator.userAgent.indexOf(\"Safari\") !== -1;\n };\n\n qq.iosSafariWebView = function() {\n return qq.ios() && !qq.iosChrome() && !qq.iosSafari();\n };\n\n //\n // Events\n\n qq.preventDefault = function(e) {\n if (e.preventDefault) {\n e.preventDefault();\n } else {\n e.returnValue = false;\n }\n };\n\n /**\n * Creates and returns element from html string\n * Uses innerHTML to create an element\n */\n qq.toElement = (function() {\n var div = document.createElement(\"div\");\n return function(html) {\n div.innerHTML = html;\n var element = div.firstChild;\n div.removeChild(element);\n return element;\n };\n }());\n\n //key and value are passed to callback for each entry in the iterable item\n qq.each = function(iterableItem, callback) {\n var keyOrIndex, retVal;\n\n if (iterableItem) {\n // Iterate through [`Storage`](http://www.w3.org/TR/webstorage/#the-storage-interface) items\n if (window.Storage && iterableItem.constructor === window.Storage) {\n for (keyOrIndex = 0; keyOrIndex < iterableItem.length; keyOrIndex++) {\n retVal = callback(iterableItem.key(keyOrIndex), iterableItem.getItem(iterableItem.key(keyOrIndex)));\n if (retVal === false) {\n break;\n }\n }\n }\n // `DataTransferItemList` & `NodeList` objects are array-like and should be treated as arrays\n // when iterating over items inside the object.\n else if (qq.isArray(iterableItem) || qq.isItemList(iterableItem) || qq.isNodeList(iterableItem)) {\n for (keyOrIndex = 0; keyOrIndex < iterableItem.length; keyOrIndex++) {\n retVal = callback(keyOrIndex, iterableItem[keyOrIndex]);\n if (retVal === false) {\n break;\n }\n }\n }\n else if (qq.isString(iterableItem)) {\n for (keyOrIndex = 0; keyOrIndex < iterableItem.length; keyOrIndex++) {\n retVal = callback(keyOrIndex, iterableItem.charAt(keyOrIndex));\n if (retVal === false) {\n break;\n }\n }\n }\n else {\n for (keyOrIndex in iterableItem) {\n if (Object.prototype.hasOwnProperty.call(iterableItem, keyOrIndex)) {\n retVal = callback(keyOrIndex, iterableItem[keyOrIndex]);\n if (retVal === false) {\n break;\n }\n }\n }\n }\n }\n };\n\n //include any args that should be passed to the new function after the context arg\n qq.bind = function(oldFunc, context) {\n if (qq.isFunction(oldFunc)) {\n var args = Array.prototype.slice.call(arguments, 2);\n\n return function() {\n var newArgs = qq.extend([], args);\n if (arguments.length) {\n newArgs = newArgs.concat(Array.prototype.slice.call(arguments));\n }\n return oldFunc.apply(context, newArgs);\n };\n }\n\n throw new Error(\"first parameter must be a function!\");\n };\n\n /**\n * obj2url() takes a json-object as argument and generates\n * a querystring. pretty much like jQuery.param()\n *\n * how to use:\n *\n * `qq.obj2url({a:'b',c:'d'},'http://any.url/upload?otherParam=value');`\n *\n * will result in:\n *\n * `http://any.url/upload?otherParam=value&a=b&c=d`\n *\n * @param Object JSON-Object\n * @param String current querystring-part\n * @return String encoded querystring\n */\n qq.obj2url = function(obj, temp, prefixDone) {\n /*jshint laxbreak: true*/\n var uristrings = [],\n prefix = \"&\",\n add = function(nextObj, i) {\n var nextTemp = temp\n ? (/\\[\\]$/.test(temp)) // prevent double-encoding\n ? temp\n : temp + \"[\" + i + \"]\"\n : i;\n if ((nextTemp !== \"undefined\") && (i !== \"undefined\")) {\n uristrings.push(\n (typeof nextObj === \"object\")\n ? qq.obj2url(nextObj, nextTemp, true)\n : (Object.prototype.toString.call(nextObj) === \"[object Function]\")\n ? encodeURIComponent(nextTemp) + \"=\" + encodeURIComponent(nextObj())\n : encodeURIComponent(nextTemp) + \"=\" + encodeURIComponent(nextObj)\n );\n }\n };\n\n if (!prefixDone && temp) {\n prefix = (/\\?/.test(temp)) ? (/\\?$/.test(temp)) ? \"\" : \"&\" : \"?\";\n uristrings.push(temp);\n uristrings.push(qq.obj2url(obj));\n } else if ((Object.prototype.toString.call(obj) === \"[object Array]\") && (typeof obj !== \"undefined\")) {\n qq.each(obj, function(idx, val) {\n add(val, idx);\n });\n } else if ((typeof obj !== \"undefined\") && (obj !== null) && (typeof obj === \"object\")) {\n qq.each(obj, function(prop, val) {\n add(val, prop);\n });\n } else {\n uristrings.push(encodeURIComponent(temp) + \"=\" + encodeURIComponent(obj));\n }\n\n if (temp) {\n return uristrings.join(prefix);\n } else {\n return uristrings.join(prefix)\n .replace(/^&/, \"\")\n .replace(/%20/g, \"+\");\n }\n };\n\n qq.obj2FormData = function(obj, formData, arrayKeyName) {\n if (!formData) {\n formData = new FormData();\n }\n\n qq.each(obj, function(key, val) {\n key = arrayKeyName ? arrayKeyName + \"[\" + key + \"]\" : key;\n\n if (qq.isObject(val)) {\n qq.obj2FormData(val, formData, key);\n }\n else if (qq.isFunction(val)) {\n formData.append(key, val());\n }\n else {\n formData.append(key, val);\n }\n });\n\n return formData;\n };\n\n qq.obj2Inputs = function(obj, form) {\n var input;\n\n if (!form) {\n form = document.createElement(\"form\");\n }\n\n qq.obj2FormData(obj, {\n append: function(key, val) {\n input = document.createElement(\"input\");\n input.setAttribute(\"name\", key);\n input.setAttribute(\"value\", val);\n form.appendChild(input);\n }\n });\n\n return form;\n };\n\n /**\n * Not recommended for use outside of Fine Uploader since this falls back to an unchecked eval if JSON.parse is not\n * implemented. For a more secure JSON.parse polyfill, use Douglas Crockford's json2.js.\n */\n qq.parseJson = function(json) {\n /*jshint evil: true*/\n if (window.JSON && qq.isFunction(JSON.parse)) {\n return JSON.parse(json);\n } else {\n return eval(\"(\" + json + \")\");\n }\n };\n\n /**\n * Retrieve the extension of a file, if it exists.\n *\n * @param filename\n * @returns {string || undefined}\n */\n qq.getExtension = function(filename) {\n var extIdx = filename.lastIndexOf(\".\") + 1;\n\n if (extIdx > 0) {\n return filename.substr(extIdx, filename.length - extIdx);\n }\n };\n\n qq.getFilename = function(blobOrFileInput) {\n /*jslint regexp: true*/\n\n if (qq.isInput(blobOrFileInput)) {\n // get input value and remove path to normalize\n return blobOrFileInput.value.replace(/.*(\\/|\\\\)/, \"\");\n }\n else if (qq.isFile(blobOrFileInput)) {\n if (blobOrFileInput.fileName !== null && blobOrFileInput.fileName !== undefined) {\n return blobOrFileInput.fileName;\n }\n }\n\n return blobOrFileInput.name;\n };\n\n /**\n * A generic module which supports object disposing in dispose() method.\n * */\n qq.DisposeSupport = function() {\n var disposers = [];\n\n return {\n /** Run all registered disposers */\n dispose: function() {\n var disposer;\n do {\n disposer = disposers.shift();\n if (disposer) {\n disposer();\n }\n }\n while (disposer);\n },\n\n /** Attach event handler and register de-attacher as a disposer */\n attach: function() {\n var args = arguments;\n /*jslint undef:true*/\n this.addDisposer(qq(args[0]).attach.apply(this, Array.prototype.slice.call(arguments, 1)));\n },\n\n /** Add disposer to the collection */\n addDisposer: function(disposeFunction) {\n disposers.push(disposeFunction);\n }\n };\n };\n}());\n","/* globals define, module, global, qq */\n(function() {\n \"use strict\";\n if (typeof define === \"function\" && define.amd) {\n define(function() {\n return qq;\n });\n }\n else if (typeof module !== \"undefined\" && module.exports) {\n module.exports = qq;\n }\n else {\n global.qq = qq;\n }\n}());\n","/* globals qq */\n/**\n * Fine Uploader top-level Error container. Inherits from `Error`.\n */\n(function() {\n \"use strict\";\n\n qq.Error = function(message) {\n this.message = \"[Fine Uploader \" + qq.version + \"] \" + message;\n };\n\n qq.Error.prototype = new Error();\n}());\n","/*global qq */\nqq.version = \"5.12.0\";\n","/* globals qq */\nqq.supportedFeatures = (function() {\n \"use strict\";\n\n var supportsUploading,\n supportsUploadingBlobs,\n supportsFileDrop,\n supportsAjaxFileUploading,\n supportsFolderDrop,\n supportsChunking,\n supportsResume,\n supportsUploadViaPaste,\n supportsUploadCors,\n supportsDeleteFileXdr,\n supportsDeleteFileCorsXhr,\n supportsDeleteFileCors,\n supportsFolderSelection,\n supportsImagePreviews,\n supportsUploadProgress;\n\n function testSupportsFileInputElement() {\n var supported = true,\n tempInput;\n\n try {\n tempInput = document.createElement(\"input\");\n tempInput.type = \"file\";\n qq(tempInput).hide();\n\n if (tempInput.disabled) {\n supported = false;\n }\n }\n catch (ex) {\n supported = false;\n }\n\n return supported;\n }\n\n //only way to test for Filesystem API support since webkit does not expose the DataTransfer interface\n function isChrome21OrHigher() {\n return (qq.chrome() || qq.opera()) &&\n navigator.userAgent.match(/Chrome\\/[2][1-9]|Chrome\\/[3-9][0-9]/) !== undefined;\n }\n\n //only way to test for complete Clipboard API support at this time\n function isChrome14OrHigher() {\n return (qq.chrome() || qq.opera()) &&\n navigator.userAgent.match(/Chrome\\/[1][4-9]|Chrome\\/[2-9][0-9]/) !== undefined;\n }\n\n //Ensure we can send cross-origin `XMLHttpRequest`s\n function isCrossOriginXhrSupported() {\n if (window.XMLHttpRequest) {\n var xhr = qq.createXhrInstance();\n\n //Commonly accepted test for XHR CORS support.\n return xhr.withCredentials !== undefined;\n }\n\n return false;\n }\n\n //Test for (terrible) cross-origin ajax transport fallback for IE9 and IE8\n function isXdrSupported() {\n return window.XDomainRequest !== undefined;\n }\n\n // CORS Ajax requests are supported if it is either possible to send credentialed `XMLHttpRequest`s,\n // or if `XDomainRequest` is an available alternative.\n function isCrossOriginAjaxSupported() {\n if (isCrossOriginXhrSupported()) {\n return true;\n }\n\n return isXdrSupported();\n }\n\n function isFolderSelectionSupported() {\n // We know that folder selection is only supported in Chrome via this proprietary attribute for now\n return document.createElement(\"input\").webkitdirectory !== undefined;\n }\n\n function isLocalStorageSupported() {\n try {\n return !!window.localStorage &&\n // unpatched versions of IE10/11 have buggy impls of localStorage where setItem is a string\n qq.isFunction(window.localStorage.setItem);\n }\n catch (error) {\n // probably caught a security exception, so no localStorage for you\n return false;\n }\n }\n\n function isDragAndDropSupported() {\n var span = document.createElement(\"span\");\n\n return (\"draggable\" in span || (\"ondragstart\" in span && \"ondrop\" in span)) &&\n !qq.android() && !qq.ios();\n }\n\n supportsUploading = testSupportsFileInputElement();\n\n supportsAjaxFileUploading = supportsUploading && qq.isXhrUploadSupported();\n\n supportsUploadingBlobs = supportsAjaxFileUploading && !qq.androidStock();\n\n supportsFileDrop = supportsAjaxFileUploading && isDragAndDropSupported();\n\n supportsFolderDrop = supportsFileDrop && isChrome21OrHigher();\n\n supportsChunking = supportsAjaxFileUploading && qq.isFileChunkingSupported();\n\n supportsResume = supportsAjaxFileUploading && supportsChunking && isLocalStorageSupported();\n\n supportsUploadViaPaste = supportsAjaxFileUploading && isChrome14OrHigher();\n\n supportsUploadCors = supportsUploading && (window.postMessage !== undefined || supportsAjaxFileUploading);\n\n supportsDeleteFileCorsXhr = isCrossOriginXhrSupported();\n\n supportsDeleteFileXdr = isXdrSupported();\n\n supportsDeleteFileCors = isCrossOriginAjaxSupported();\n\n supportsFolderSelection = isFolderSelectionSupported();\n\n supportsImagePreviews = supportsAjaxFileUploading && window.FileReader !== undefined;\n\n supportsUploadProgress = (function() {\n if (supportsAjaxFileUploading) {\n return !qq.androidStock() && !qq.iosChrome();\n }\n return false;\n }());\n\n return {\n ajaxUploading: supportsAjaxFileUploading,\n blobUploading: supportsUploadingBlobs,\n canDetermineSize: supportsAjaxFileUploading,\n chunking: supportsChunking,\n deleteFileCors: supportsDeleteFileCors,\n deleteFileCorsXdr: supportsDeleteFileXdr, //NOTE: will also return true in IE10, where XDR is also supported\n deleteFileCorsXhr: supportsDeleteFileCorsXhr,\n dialogElement: !!window.HTMLDialogElement,\n fileDrop: supportsFileDrop,\n folderDrop: supportsFolderDrop,\n folderSelection: supportsFolderSelection,\n imagePreviews: supportsImagePreviews,\n imageValidation: supportsImagePreviews,\n itemSizeValidation: supportsAjaxFileUploading,\n pause: supportsChunking,\n progressBar: supportsUploadProgress,\n resume: supportsResume,\n scaling: supportsImagePreviews && supportsUploadingBlobs,\n tiffPreviews: qq.safari(), // Not the best solution, but simple and probably accurate enough (for now)\n unlimitedScaledImageSize: !qq.ios(), // false simply indicates that there is some known limit\n uploading: supportsUploading,\n uploadCors: supportsUploadCors,\n uploadCustomHeaders: supportsAjaxFileUploading,\n uploadNonMultipart: supportsAjaxFileUploading,\n uploadViaPaste: supportsUploadViaPaste\n };\n\n}());\n","/*globals qq*/\n\n// Is the passed object a promise instance?\nqq.isGenericPromise = function(maybePromise) {\n \"use strict\";\n return !!(maybePromise && maybePromise.then && qq.isFunction(maybePromise.then));\n};\n\nqq.Promise = function() {\n \"use strict\";\n\n var successArgs, failureArgs,\n successCallbacks = [],\n failureCallbacks = [],\n doneCallbacks = [],\n state = 0;\n\n qq.extend(this, {\n then: function(onSuccess, onFailure) {\n if (state === 0) {\n if (onSuccess) {\n successCallbacks.push(onSuccess);\n }\n if (onFailure) {\n failureCallbacks.push(onFailure);\n }\n }\n else if (state === -1) {\n onFailure && onFailure.apply(null, failureArgs);\n }\n else if (onSuccess) {\n onSuccess.apply(null, successArgs);\n }\n\n return this;\n },\n\n done: function(callback) {\n if (state === 0) {\n doneCallbacks.push(callback);\n }\n else {\n callback.apply(null, failureArgs === undefined ? successArgs : failureArgs);\n }\n\n return this;\n },\n\n success: function() {\n state = 1;\n successArgs = arguments;\n\n if (successCallbacks.length) {\n qq.each(successCallbacks, function(idx, callback) {\n callback.apply(null, successArgs);\n });\n }\n\n if (doneCallbacks.length) {\n qq.each(doneCallbacks, function(idx, callback) {\n callback.apply(null, successArgs);\n });\n }\n\n return this;\n },\n\n failure: function() {\n state = -1;\n failureArgs = arguments;\n\n if (failureCallbacks.length) {\n qq.each(failureCallbacks, function(idx, callback) {\n callback.apply(null, failureArgs);\n });\n }\n\n if (doneCallbacks.length) {\n qq.each(doneCallbacks, function(idx, callback) {\n callback.apply(null, failureArgs);\n });\n }\n\n return this;\n }\n });\n};\n","/* globals qq */\n/**\n * Placeholder for a Blob that will be generated on-demand.\n *\n * @param referenceBlob Parent of the generated blob\n * @param onCreate Function to invoke when the blob must be created. Must be promissory.\n * @constructor\n */\nqq.BlobProxy = function(referenceBlob, onCreate) {\n \"use strict\";\n\n qq.extend(this, {\n referenceBlob: referenceBlob,\n\n create: function() {\n return onCreate(referenceBlob);\n }\n });\n};\n","/*globals qq*/\n\n/**\n * This module represents an upload or \"Select File(s)\" button. It's job is to embed an opaque ` `\n * element as a child of a provided \"container\" element. This \"container\" element (`options.element`) is used to provide\n * a custom style for the ` ` element. The ability to change the style of the container element is also\n * provided here by adding CSS classes to the container on hover/focus.\n *\n * TODO Eliminate the mouseover and mouseout event handlers since the :hover CSS pseudo-class should now be\n * available on all supported browsers.\n *\n * @param o Options to override the default values\n */\nqq.UploadButton = function(o) {\n \"use strict\";\n\n var self = this,\n\n disposeSupport = new qq.DisposeSupport(),\n\n options = {\n // Corresponds to the `accept` attribute on the associated ` `\n acceptFiles: null,\n\n // \"Container\" element\n element: null,\n\n focusClass: \"qq-upload-button-focus\",\n\n // A true value allows folders to be selected, if supported by the UA\n folders: false,\n\n // **This option will be removed** in the future as the :hover CSS pseudo-class is available on all supported browsers\n hoverClass: \"qq-upload-button-hover\",\n\n ios8BrowserCrashWorkaround: false,\n\n // If true adds `multiple` attribute to ` `\n multiple: false,\n\n // `name` attribute of ` `\n name: \"qqfile\",\n\n // Called when the browser invokes the onchange handler on the ` `\n onChange: function(input) {},\n\n title: null\n },\n input, buttonId;\n\n // Overrides any of the default option values with any option values passed in during construction.\n qq.extend(options, o);\n\n buttonId = qq.getUniqueId();\n\n // Embed an opaque ` ` element as a child of `options.element`.\n function createInput() {\n var input = document.createElement(\"input\");\n\n input.setAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME, buttonId);\n input.setAttribute(\"title\", options.title);\n\n self.setMultiple(options.multiple, input);\n\n if (options.folders && qq.supportedFeatures.folderSelection) {\n // selecting directories is only possible in Chrome now, via a vendor-specific prefixed attribute\n input.setAttribute(\"webkitdirectory\", \"\");\n }\n\n if (options.acceptFiles) {\n input.setAttribute(\"accept\", options.acceptFiles);\n }\n\n input.setAttribute(\"type\", \"file\");\n input.setAttribute(\"name\", options.name);\n\n qq(input).css({\n position: \"absolute\",\n // in Opera only 'browse' button\n // is clickable and it is located at\n // the right side of the input\n right: 0,\n top: 0,\n fontFamily: \"Arial\",\n // It's especially important to make this an arbitrarily large value\n // to ensure the rendered input button in IE takes up the entire\n // space of the container element. Otherwise, the left side of the\n // button will require a double-click to invoke the file chooser.\n // In other browsers, this might cause other issues, so a large font-size\n // is only used in IE. There is a bug in IE8 where the opacity style is ignored\n // in some cases when the font-size is large. So, this workaround is not applied\n // to IE8.\n fontSize: qq.ie() && !qq.ie8() ? \"3500px\" : \"118px\",\n margin: 0,\n padding: 0,\n cursor: \"pointer\",\n opacity: 0\n });\n\n // Setting the file input's height to 100% in IE7 causes\n // most of the visible button to be unclickable.\n !qq.ie7() && qq(input).css({height: \"100%\"});\n\n options.element.appendChild(input);\n\n disposeSupport.attach(input, \"change\", function() {\n options.onChange(input);\n });\n\n // **These event handlers will be removed** in the future as the :hover CSS pseudo-class is available on all supported browsers\n disposeSupport.attach(input, \"mouseover\", function() {\n qq(options.element).addClass(options.hoverClass);\n });\n disposeSupport.attach(input, \"mouseout\", function() {\n qq(options.element).removeClass(options.hoverClass);\n });\n\n disposeSupport.attach(input, \"focus\", function() {\n qq(options.element).addClass(options.focusClass);\n });\n disposeSupport.attach(input, \"blur\", function() {\n qq(options.element).removeClass(options.focusClass);\n });\n\n return input;\n }\n\n // Make button suitable container for input\n qq(options.element).css({\n position: \"relative\",\n overflow: \"hidden\",\n // Make sure browse button is in the right side in Internet Explorer\n direction: \"ltr\"\n });\n\n // Exposed API\n qq.extend(this, {\n getInput: function() {\n return input;\n },\n\n getButtonId: function() {\n return buttonId;\n },\n\n setMultiple: function(isMultiple, optInput) {\n var input = optInput || this.getInput();\n\n // Temporary workaround for bug in in iOS8 UIWebView that causes the browser to crash\n // before the file chooser appears if the file input doesn't contain a multiple attribute.\n // See #1283.\n if (options.ios8BrowserCrashWorkaround && qq.ios8() && (qq.iosChrome() || qq.iosSafariWebView())) {\n input.setAttribute(\"multiple\", \"\");\n }\n\n else {\n if (isMultiple) {\n input.setAttribute(\"multiple\", \"\");\n }\n else {\n input.removeAttribute(\"multiple\");\n }\n }\n },\n\n setAcceptFiles: function(acceptFiles) {\n if (acceptFiles !== options.acceptFiles) {\n input.setAttribute(\"accept\", acceptFiles);\n }\n },\n\n reset: function() {\n if (input.parentNode) {\n qq(input).remove();\n }\n\n qq(options.element).removeClass(options.focusClass);\n input = null;\n input = createInput();\n }\n });\n\n input = createInput();\n};\n\nqq.UploadButton.BUTTON_ID_ATTR_NAME = \"qq-button-id\";\n","/*globals qq */\nqq.UploadData = function(uploaderProxy) {\n \"use strict\";\n\n var data = [],\n byUuid = {},\n byStatus = {},\n byProxyGroupId = {},\n byBatchId = {};\n\n function getDataByIds(idOrIds) {\n if (qq.isArray(idOrIds)) {\n var entries = [];\n\n qq.each(idOrIds, function(idx, id) {\n entries.push(data[id]);\n });\n\n return entries;\n }\n\n return data[idOrIds];\n }\n\n function getDataByUuids(uuids) {\n if (qq.isArray(uuids)) {\n var entries = [];\n\n qq.each(uuids, function(idx, uuid) {\n entries.push(data[byUuid[uuid]]);\n });\n\n return entries;\n }\n\n return data[byUuid[uuids]];\n }\n\n function getDataByStatus(status) {\n var statusResults = [],\n statuses = [].concat(status);\n\n qq.each(statuses, function(index, statusEnum) {\n var statusResultIndexes = byStatus[statusEnum];\n\n if (statusResultIndexes !== undefined) {\n qq.each(statusResultIndexes, function(i, dataIndex) {\n statusResults.push(data[dataIndex]);\n });\n }\n });\n\n return statusResults;\n }\n\n qq.extend(this, {\n /**\n * Adds a new file to the data cache for tracking purposes.\n *\n * @param spec Data that describes this file. Possible properties are:\n *\n * - uuid: Initial UUID for this file.\n * - name: Initial name of this file.\n * - size: Size of this file, omit if this cannot be determined\n * - status: Initial `qq.status` for this file. Omit for `qq.status.SUBMITTING`.\n * - batchId: ID of the batch this file belongs to\n * - proxyGroupId: ID of the proxy group associated with this file\n *\n * @returns {number} Internal ID for this file.\n */\n addFile: function(spec) {\n var status = spec.status || qq.status.SUBMITTING,\n id = data.push({\n name: spec.name,\n originalName: spec.name,\n uuid: spec.uuid,\n size: spec.size == null ? -1 : spec.size,\n status: status\n }) - 1;\n\n if (spec.batchId) {\n data[id].batchId = spec.batchId;\n\n if (byBatchId[spec.batchId] === undefined) {\n byBatchId[spec.batchId] = [];\n }\n byBatchId[spec.batchId].push(id);\n }\n\n if (spec.proxyGroupId) {\n data[id].proxyGroupId = spec.proxyGroupId;\n\n if (byProxyGroupId[spec.proxyGroupId] === undefined) {\n byProxyGroupId[spec.proxyGroupId] = [];\n }\n byProxyGroupId[spec.proxyGroupId].push(id);\n }\n\n data[id].id = id;\n byUuid[spec.uuid] = id;\n\n if (byStatus[status] === undefined) {\n byStatus[status] = [];\n }\n byStatus[status].push(id);\n\n uploaderProxy.onStatusChange(id, null, status);\n\n return id;\n },\n\n retrieve: function(optionalFilter) {\n if (qq.isObject(optionalFilter) && data.length) {\n if (optionalFilter.id !== undefined) {\n return getDataByIds(optionalFilter.id);\n }\n\n else if (optionalFilter.uuid !== undefined) {\n return getDataByUuids(optionalFilter.uuid);\n }\n\n else if (optionalFilter.status) {\n return getDataByStatus(optionalFilter.status);\n }\n }\n else {\n return qq.extend([], data, true);\n }\n },\n\n reset: function() {\n data = [];\n byUuid = {};\n byStatus = {};\n byBatchId = {};\n },\n\n setStatus: function(id, newStatus) {\n var oldStatus = data[id].status,\n byStatusOldStatusIndex = qq.indexOf(byStatus[oldStatus], id);\n\n byStatus[oldStatus].splice(byStatusOldStatusIndex, 1);\n\n data[id].status = newStatus;\n\n if (byStatus[newStatus] === undefined) {\n byStatus[newStatus] = [];\n }\n byStatus[newStatus].push(id);\n\n uploaderProxy.onStatusChange(id, oldStatus, newStatus);\n },\n\n uuidChanged: function(id, newUuid) {\n var oldUuid = data[id].uuid;\n\n data[id].uuid = newUuid;\n byUuid[newUuid] = id;\n delete byUuid[oldUuid];\n },\n\n updateName: function(id, newName) {\n data[id].name = newName;\n },\n\n updateSize: function(id, newSize) {\n data[id].size = newSize;\n },\n\n // Only applicable if this file has a parent that we may want to reference later.\n setParentId: function(targetId, parentId) {\n data[targetId].parentId = parentId;\n },\n\n getIdsInProxyGroup: function(id) {\n var proxyGroupId = data[id].proxyGroupId;\n\n if (proxyGroupId) {\n return byProxyGroupId[proxyGroupId];\n }\n return [];\n },\n\n getIdsInBatch: function(id) {\n var batchId = data[id].batchId;\n\n return byBatchId[batchId];\n }\n });\n};\n\nqq.status = {\n SUBMITTING: \"submitting\",\n SUBMITTED: \"submitted\",\n REJECTED: \"rejected\",\n QUEUED: \"queued\",\n CANCELED: \"canceled\",\n PAUSED: \"paused\",\n UPLOADING: \"uploading\",\n UPLOAD_RETRYING: \"retrying upload\",\n UPLOAD_SUCCESSFUL: \"upload successful\",\n UPLOAD_FAILED: \"upload failed\",\n DELETE_FAILED: \"delete failed\",\n DELETING: \"deleting\",\n DELETED: \"deleted\"\n};\n","/*globals qq*/\n/**\n * Defines the public API for FineUploaderBasic mode.\n */\n(function() {\n \"use strict\";\n\n qq.basePublicApi = {\n // DEPRECATED - TODO REMOVE IN NEXT MAJOR RELEASE (replaced by addFiles)\n addBlobs: function(blobDataOrArray, params, endpoint) {\n this.addFiles(blobDataOrArray, params, endpoint);\n },\n\n addInitialFiles: function(cannedFileList) {\n var self = this;\n\n qq.each(cannedFileList, function(index, cannedFile) {\n self._addCannedFile(cannedFile);\n });\n },\n\n addFiles: function(data, params, endpoint) {\n this._maybeHandleIos8SafariWorkaround();\n\n var batchId = this._storedIds.length === 0 ? qq.getUniqueId() : this._currentBatchId,\n\n processBlob = qq.bind(function(blob) {\n this._handleNewFile({\n blob: blob,\n name: this._options.blobs.defaultName\n }, batchId, verifiedFiles);\n }, this),\n\n processBlobData = qq.bind(function(blobData) {\n this._handleNewFile(blobData, batchId, verifiedFiles);\n }, this),\n\n processCanvas = qq.bind(function(canvas) {\n var blob = qq.canvasToBlob(canvas);\n\n this._handleNewFile({\n blob: blob,\n name: this._options.blobs.defaultName + \".png\"\n }, batchId, verifiedFiles);\n }, this),\n\n processCanvasData = qq.bind(function(canvasData) {\n var normalizedQuality = canvasData.quality && canvasData.quality / 100,\n blob = qq.canvasToBlob(canvasData.canvas, canvasData.type, normalizedQuality);\n\n this._handleNewFile({\n blob: blob,\n name: canvasData.name\n }, batchId, verifiedFiles);\n }, this),\n\n processFileOrInput = qq.bind(function(fileOrInput) {\n if (qq.isInput(fileOrInput) && qq.supportedFeatures.ajaxUploading) {\n var files = Array.prototype.slice.call(fileOrInput.files),\n self = this;\n\n qq.each(files, function(idx, file) {\n self._handleNewFile(file, batchId, verifiedFiles);\n });\n }\n else {\n this._handleNewFile(fileOrInput, batchId, verifiedFiles);\n }\n }, this),\n\n normalizeData = function() {\n if (qq.isFileList(data)) {\n data = Array.prototype.slice.call(data);\n }\n data = [].concat(data);\n },\n\n self = this,\n verifiedFiles = [];\n\n this._currentBatchId = batchId;\n\n if (data) {\n normalizeData();\n\n qq.each(data, function(idx, fileContainer) {\n if (qq.isFileOrInput(fileContainer)) {\n processFileOrInput(fileContainer);\n }\n else if (qq.isBlob(fileContainer)) {\n processBlob(fileContainer);\n }\n else if (qq.isObject(fileContainer)) {\n if (fileContainer.blob && fileContainer.name) {\n processBlobData(fileContainer);\n }\n else if (fileContainer.canvas && fileContainer.name) {\n processCanvasData(fileContainer);\n }\n }\n else if (fileContainer.tagName && fileContainer.tagName.toLowerCase() === \"canvas\") {\n processCanvas(fileContainer);\n }\n else {\n self.log(fileContainer + \" is not a valid file container! Ignoring!\", \"warn\");\n }\n });\n\n this.log(\"Received \" + verifiedFiles.length + \" files.\");\n this._prepareItemsForUpload(verifiedFiles, params, endpoint);\n }\n },\n\n cancel: function(id) {\n this._handler.cancel(id);\n },\n\n cancelAll: function() {\n var storedIdsCopy = [],\n self = this;\n\n qq.extend(storedIdsCopy, this._storedIds);\n qq.each(storedIdsCopy, function(idx, storedFileId) {\n self.cancel(storedFileId);\n });\n\n this._handler.cancelAll();\n },\n\n clearStoredFiles: function() {\n this._storedIds = [];\n },\n\n continueUpload: function(id) {\n var uploadData = this._uploadData.retrieve({id: id});\n\n if (!qq.supportedFeatures.pause || !this._options.chunking.enabled) {\n return false;\n }\n\n if (uploadData.status === qq.status.PAUSED) {\n this.log(qq.format(\"Paused file ID {} ({}) will be continued. Not paused.\", id, this.getName(id)));\n this._uploadFile(id);\n return true;\n }\n else {\n this.log(qq.format(\"Ignoring continue for file ID {} ({}). Not paused.\", id, this.getName(id)), \"error\");\n }\n\n return false;\n },\n\n deleteFile: function(id) {\n return this._onSubmitDelete(id);\n },\n\n // TODO document?\n doesExist: function(fileOrBlobId) {\n return this._handler.isValid(fileOrBlobId);\n },\n\n // Generate a variable size thumbnail on an img or canvas,\n // returning a promise that is fulfilled when the attempt completes.\n // Thumbnail can either be based off of a URL for an image returned\n // by the server in the upload response, or the associated `Blob`.\n drawThumbnail: function(fileId, imgOrCanvas, maxSize, fromServer, customResizeFunction) {\n var promiseToReturn = new qq.Promise(),\n fileOrUrl, options;\n\n if (this._imageGenerator) {\n fileOrUrl = this._thumbnailUrls[fileId];\n options = {\n customResizeFunction: customResizeFunction,\n maxSize: maxSize > 0 ? maxSize : null,\n scale: maxSize > 0\n };\n\n // If client-side preview generation is possible\n // and we are not specifically looking for the image URl returned by the server...\n if (!fromServer && qq.supportedFeatures.imagePreviews) {\n fileOrUrl = this.getFile(fileId);\n }\n\n /* jshint eqeqeq:false,eqnull:true */\n if (fileOrUrl == null) {\n promiseToReturn.failure({container: imgOrCanvas, error: \"File or URL not found.\"});\n }\n else {\n this._imageGenerator.generate(fileOrUrl, imgOrCanvas, options).then(\n function success(modifiedContainer) {\n promiseToReturn.success(modifiedContainer);\n },\n\n function failure(container, reason) {\n promiseToReturn.failure({container: container, error: reason || \"Problem generating thumbnail\"});\n }\n );\n }\n }\n else {\n promiseToReturn.failure({container: imgOrCanvas, error: \"Missing image generator module\"});\n }\n\n return promiseToReturn;\n },\n\n getButton: function(fileId) {\n return this._getButton(this._buttonIdsForFileIds[fileId]);\n },\n\n getEndpoint: function(fileId) {\n return this._endpointStore.get(fileId);\n },\n\n getFile: function(fileOrBlobId) {\n return this._handler.getFile(fileOrBlobId) || null;\n },\n\n getInProgress: function() {\n return this._uploadData.retrieve({\n status: [\n qq.status.UPLOADING,\n qq.status.UPLOAD_RETRYING,\n qq.status.QUEUED\n ]\n }).length;\n },\n\n getName: function(id) {\n return this._uploadData.retrieve({id: id}).name;\n },\n\n // Parent ID for a specific file, or null if this is the parent, or if it has no parent.\n getParentId: function(id) {\n var uploadDataEntry = this.getUploads({id: id}),\n parentId = null;\n\n if (uploadDataEntry) {\n if (uploadDataEntry.parentId !== undefined) {\n parentId = uploadDataEntry.parentId;\n }\n }\n\n return parentId;\n },\n\n getResumableFilesData: function() {\n return this._handler.getResumableFilesData();\n },\n\n getSize: function(id) {\n return this._uploadData.retrieve({id: id}).size;\n },\n\n getNetUploads: function() {\n return this._netUploaded;\n },\n\n getRemainingAllowedItems: function() {\n var allowedItems = this._currentItemLimit;\n\n if (allowedItems > 0) {\n return allowedItems - this._netUploadedOrQueued;\n }\n\n return null;\n },\n\n getUploads: function(optionalFilter) {\n return this._uploadData.retrieve(optionalFilter);\n },\n\n getUuid: function(id) {\n return this._uploadData.retrieve({id: id}).uuid;\n },\n\n log: function(str, level) {\n if (this._options.debug && (!level || level === \"info\")) {\n qq.log(\"[Fine Uploader \" + qq.version + \"] \" + str);\n }\n else if (level && level !== \"info\") {\n qq.log(\"[Fine Uploader \" + qq.version + \"] \" + str, level);\n\n }\n },\n\n pauseUpload: function(id) {\n var uploadData = this._uploadData.retrieve({id: id});\n\n if (!qq.supportedFeatures.pause || !this._options.chunking.enabled) {\n return false;\n }\n\n // Pause only really makes sense if the file is uploading or retrying\n if (qq.indexOf([qq.status.UPLOADING, qq.status.UPLOAD_RETRYING], uploadData.status) >= 0) {\n if (this._handler.pause(id)) {\n this._uploadData.setStatus(id, qq.status.PAUSED);\n return true;\n }\n else {\n this.log(qq.format(\"Unable to pause file ID {} ({}).\", id, this.getName(id)), \"error\");\n }\n }\n else {\n this.log(qq.format(\"Ignoring pause for file ID {} ({}). Not in progress.\", id, this.getName(id)), \"error\");\n }\n\n return false;\n },\n\n reset: function() {\n this.log(\"Resetting uploader...\");\n\n this._handler.reset();\n this._storedIds = [];\n this._autoRetries = [];\n this._retryTimeouts = [];\n this._preventRetries = [];\n this._thumbnailUrls = [];\n\n qq.each(this._buttons, function(idx, button) {\n button.reset();\n });\n\n this._paramsStore.reset();\n this._endpointStore.reset();\n this._netUploadedOrQueued = 0;\n this._netUploaded = 0;\n this._uploadData.reset();\n this._buttonIdsForFileIds = [];\n\n this._pasteHandler && this._pasteHandler.reset();\n this._options.session.refreshOnReset && this._refreshSessionData();\n\n this._succeededSinceLastAllComplete = [];\n this._failedSinceLastAllComplete = [];\n\n this._totalProgress && this._totalProgress.reset();\n },\n\n retry: function(id) {\n return this._manualRetry(id);\n },\n\n scaleImage: function(id, specs) {\n var self = this;\n\n return qq.Scaler.prototype.scaleImage(id, specs, {\n log: qq.bind(self.log, self),\n getFile: qq.bind(self.getFile, self),\n uploadData: self._uploadData\n });\n },\n\n setCustomHeaders: function(headers, id) {\n this._customHeadersStore.set(headers, id);\n },\n\n setDeleteFileCustomHeaders: function(headers, id) {\n this._deleteFileCustomHeadersStore.set(headers, id);\n },\n\n setDeleteFileEndpoint: function(endpoint, id) {\n this._deleteFileEndpointStore.set(endpoint, id);\n },\n\n setDeleteFileParams: function(params, id) {\n this._deleteFileParamsStore.set(params, id);\n },\n\n // Re-sets the default endpoint, an endpoint for a specific file, or an endpoint for a specific button\n setEndpoint: function(endpoint, id) {\n this._endpointStore.set(endpoint, id);\n },\n\n setForm: function(elementOrId) {\n this._updateFormSupportAndParams(elementOrId);\n },\n\n setItemLimit: function(newItemLimit) {\n this._currentItemLimit = newItemLimit;\n },\n\n setName: function(id, newName) {\n this._uploadData.updateName(id, newName);\n },\n\n setParams: function(params, id) {\n this._paramsStore.set(params, id);\n },\n\n setUuid: function(id, newUuid) {\n return this._uploadData.uuidChanged(id, newUuid);\n },\n\n uploadStoredFiles: function() {\n if (this._storedIds.length === 0) {\n this._itemError(\"noFilesError\");\n }\n else {\n this._uploadStoredFiles();\n }\n }\n };\n\n /**\n * Defines the private (internal) API for FineUploaderBasic mode.\n */\n qq.basePrivateApi = {\n // Updates internal state with a file record (not backed by a live file). Returns the assigned ID.\n _addCannedFile: function(sessionData) {\n var id = this._uploadData.addFile({\n uuid: sessionData.uuid,\n name: sessionData.name,\n size: sessionData.size,\n status: qq.status.UPLOAD_SUCCESSFUL\n });\n\n sessionData.deleteFileEndpoint && this.setDeleteFileEndpoint(sessionData.deleteFileEndpoint, id);\n sessionData.deleteFileParams && this.setDeleteFileParams(sessionData.deleteFileParams, id);\n\n if (sessionData.thumbnailUrl) {\n this._thumbnailUrls[id] = sessionData.thumbnailUrl;\n }\n\n this._netUploaded++;\n this._netUploadedOrQueued++;\n\n return id;\n },\n\n _annotateWithButtonId: function(file, associatedInput) {\n if (qq.isFile(file)) {\n file.qqButtonId = this._getButtonId(associatedInput);\n }\n },\n\n _batchError: function(message) {\n this._options.callbacks.onError(null, null, message, undefined);\n },\n\n _createDeleteHandler: function() {\n var self = this;\n\n return new qq.DeleteFileAjaxRequester({\n method: this._options.deleteFile.method.toUpperCase(),\n maxConnections: this._options.maxConnections,\n uuidParamName: this._options.request.uuidName,\n customHeaders: this._deleteFileCustomHeadersStore,\n paramsStore: this._deleteFileParamsStore,\n endpointStore: this._deleteFileEndpointStore,\n cors: this._options.cors,\n log: qq.bind(self.log, self),\n onDelete: function(id) {\n self._onDelete(id);\n self._options.callbacks.onDelete(id);\n },\n onDeleteComplete: function(id, xhrOrXdr, isError) {\n self._onDeleteComplete(id, xhrOrXdr, isError);\n self._options.callbacks.onDeleteComplete(id, xhrOrXdr, isError);\n }\n\n });\n },\n\n _createPasteHandler: function() {\n var self = this;\n\n return new qq.PasteSupport({\n targetElement: this._options.paste.targetElement,\n callbacks: {\n log: qq.bind(self.log, self),\n pasteReceived: function(blob) {\n self._handleCheckedCallback({\n name: \"onPasteReceived\",\n callback: qq.bind(self._options.callbacks.onPasteReceived, self, blob),\n onSuccess: qq.bind(self._handlePasteSuccess, self, blob),\n identifier: \"pasted image\"\n });\n }\n }\n });\n },\n\n _createStore: function(initialValue, _readOnlyValues_) {\n var store = {},\n catchall = initialValue,\n perIdReadOnlyValues = {},\n readOnlyValues = _readOnlyValues_,\n copy = function(orig) {\n if (qq.isObject(orig)) {\n return qq.extend({}, orig);\n }\n return orig;\n },\n getReadOnlyValues = function() {\n if (qq.isFunction(readOnlyValues)) {\n return readOnlyValues();\n }\n return readOnlyValues;\n },\n includeReadOnlyValues = function(id, existing) {\n if (readOnlyValues && qq.isObject(existing)) {\n qq.extend(existing, getReadOnlyValues());\n }\n\n if (perIdReadOnlyValues[id]) {\n qq.extend(existing, perIdReadOnlyValues[id]);\n }\n };\n\n return {\n set: function(val, id) {\n /*jshint eqeqeq: true, eqnull: true*/\n if (id == null) {\n store = {};\n catchall = copy(val);\n }\n else {\n store[id] = copy(val);\n }\n },\n\n get: function(id) {\n var values;\n\n /*jshint eqeqeq: true, eqnull: true*/\n if (id != null && store[id]) {\n values = store[id];\n }\n else {\n values = copy(catchall);\n }\n\n includeReadOnlyValues(id, values);\n\n return copy(values);\n },\n\n addReadOnly: function(id, values) {\n // Only applicable to Object stores\n if (qq.isObject(store)) {\n // If null ID, apply readonly values to all files\n if (id === null) {\n if (qq.isFunction(values)) {\n readOnlyValues = values;\n }\n else {\n readOnlyValues = readOnlyValues || {};\n qq.extend(readOnlyValues, values);\n }\n }\n else {\n perIdReadOnlyValues[id] = perIdReadOnlyValues[id] || {};\n qq.extend(perIdReadOnlyValues[id], values);\n }\n }\n },\n\n remove: function(fileId) {\n return delete store[fileId];\n },\n\n reset: function() {\n store = {};\n perIdReadOnlyValues = {};\n catchall = initialValue;\n }\n };\n },\n\n _createUploadDataTracker: function() {\n var self = this;\n\n return new qq.UploadData({\n getName: function(id) {\n return self.getName(id);\n },\n getUuid: function(id) {\n return self.getUuid(id);\n },\n getSize: function(id) {\n return self.getSize(id);\n },\n onStatusChange: function(id, oldStatus, newStatus) {\n self._onUploadStatusChange(id, oldStatus, newStatus);\n self._options.callbacks.onStatusChange(id, oldStatus, newStatus);\n self._maybeAllComplete(id, newStatus);\n\n if (self._totalProgress) {\n setTimeout(function() {\n self._totalProgress.onStatusChange(id, oldStatus, newStatus);\n }, 0);\n }\n }\n });\n },\n\n /**\n * Generate a tracked upload button.\n *\n * @param spec Object containing a required `element` property\n * along with optional `multiple`, `accept`, and `folders`.\n * @returns {qq.UploadButton}\n * @private\n */\n _createUploadButton: function(spec) {\n var self = this,\n acceptFiles = spec.accept || this._options.validation.acceptFiles,\n allowedExtensions = spec.allowedExtensions || this._options.validation.allowedExtensions,\n button;\n\n function allowMultiple() {\n if (qq.supportedFeatures.ajaxUploading) {\n // Workaround for bug in iOS7+ (see #1039)\n if (self._options.workarounds.iosEmptyVideos &&\n qq.ios() &&\n !qq.ios6() &&\n self._isAllowedExtension(allowedExtensions, \".mov\")) {\n\n return false;\n }\n\n if (spec.multiple === undefined) {\n return self._options.multiple;\n }\n\n return spec.multiple;\n }\n\n return false;\n }\n\n button = new qq.UploadButton({\n acceptFiles: acceptFiles,\n element: spec.element,\n focusClass: this._options.classes.buttonFocus,\n folders: spec.folders,\n hoverClass: this._options.classes.buttonHover,\n ios8BrowserCrashWorkaround: this._options.workarounds.ios8BrowserCrash,\n multiple: allowMultiple(),\n name: this._options.request.inputName,\n onChange: function(input) {\n self._onInputChange(input);\n },\n title: spec.title == null ? this._options.text.fileInputTitle : spec.title\n });\n\n this._disposeSupport.addDisposer(function() {\n button.dispose();\n });\n\n self._buttons.push(button);\n\n return button;\n },\n\n _createUploadHandler: function(additionalOptions, namespace) {\n var self = this,\n lastOnProgress = {},\n options = {\n debug: this._options.debug,\n maxConnections: this._options.maxConnections,\n cors: this._options.cors,\n paramsStore: this._paramsStore,\n endpointStore: this._endpointStore,\n chunking: this._options.chunking,\n resume: this._options.resume,\n blobs: this._options.blobs,\n log: qq.bind(self.log, self),\n preventRetryParam: this._options.retry.preventRetryResponseProperty,\n onProgress: function(id, name, loaded, total) {\n if (loaded < 0 || total < 0) {\n return;\n }\n\n if (lastOnProgress[id]) {\n if (lastOnProgress[id].loaded !== loaded || lastOnProgress[id].total !== total) {\n self._onProgress(id, name, loaded, total);\n self._options.callbacks.onProgress(id, name, loaded, total);\n }\n }\n else {\n self._onProgress(id, name, loaded, total);\n self._options.callbacks.onProgress(id, name, loaded, total);\n }\n\n lastOnProgress[id] = {loaded: loaded, total: total};\n\n },\n onComplete: function(id, name, result, xhr) {\n delete lastOnProgress[id];\n\n var status = self.getUploads({id: id}).status,\n retVal;\n\n // This is to deal with some observed cases where the XHR readyStateChange handler is\n // invoked by the browser multiple times for the same XHR instance with the same state\n // readyState value. Higher level: don't invoke complete-related code if we've already\n // done this.\n if (status === qq.status.UPLOAD_SUCCESSFUL || status === qq.status.UPLOAD_FAILED) {\n return;\n }\n\n retVal = self._onComplete(id, name, result, xhr);\n\n // If the internal `_onComplete` handler returns a promise, don't invoke the `onComplete` callback\n // until the promise has been fulfilled.\n if (retVal instanceof qq.Promise) {\n retVal.done(function() {\n self._options.callbacks.onComplete(id, name, result, xhr);\n });\n }\n else {\n self._options.callbacks.onComplete(id, name, result, xhr);\n }\n },\n onCancel: function(id, name, cancelFinalizationEffort) {\n var promise = new qq.Promise();\n\n self._handleCheckedCallback({\n name: \"onCancel\",\n callback: qq.bind(self._options.callbacks.onCancel, self, id, name),\n onFailure: promise.failure,\n onSuccess: function() {\n cancelFinalizationEffort.then(function() {\n self._onCancel(id, name);\n });\n\n promise.success();\n },\n identifier: id\n });\n\n return promise;\n },\n onUploadPrep: qq.bind(this._onUploadPrep, this),\n onUpload: function(id, name) {\n self._onUpload(id, name);\n self._options.callbacks.onUpload(id, name);\n },\n onUploadChunk: function(id, name, chunkData) {\n self._onUploadChunk(id, chunkData);\n self._options.callbacks.onUploadChunk(id, name, chunkData);\n },\n onUploadChunkSuccess: function(id, chunkData, result, xhr) {\n self._options.callbacks.onUploadChunkSuccess.apply(self, arguments);\n },\n onResume: function(id, name, chunkData) {\n return self._options.callbacks.onResume(id, name, chunkData);\n },\n onAutoRetry: function(id, name, responseJSON, xhr) {\n return self._onAutoRetry.apply(self, arguments);\n },\n onUuidChanged: function(id, newUuid) {\n self.log(\"Server requested UUID change from '\" + self.getUuid(id) + \"' to '\" + newUuid + \"'\");\n self.setUuid(id, newUuid);\n },\n getName: qq.bind(self.getName, self),\n getUuid: qq.bind(self.getUuid, self),\n getSize: qq.bind(self.getSize, self),\n setSize: qq.bind(self._setSize, self),\n getDataByUuid: function(uuid) {\n return self.getUploads({uuid: uuid});\n },\n isQueued: function(id) {\n var status = self.getUploads({id: id}).status;\n return status === qq.status.QUEUED ||\n status === qq.status.SUBMITTED ||\n status === qq.status.UPLOAD_RETRYING ||\n status === qq.status.PAUSED;\n },\n getIdsInProxyGroup: self._uploadData.getIdsInProxyGroup,\n getIdsInBatch: self._uploadData.getIdsInBatch\n };\n\n qq.each(this._options.request, function(prop, val) {\n options[prop] = val;\n });\n\n options.customHeaders = this._customHeadersStore;\n\n if (additionalOptions) {\n qq.each(additionalOptions, function(key, val) {\n options[key] = val;\n });\n }\n\n return new qq.UploadHandlerController(options, namespace);\n },\n\n _fileOrBlobRejected: function(id) {\n this._netUploadedOrQueued--;\n this._uploadData.setStatus(id, qq.status.REJECTED);\n },\n\n _formatSize: function(bytes) {\n if (bytes === 0) {\n return bytes + this._options.text.sizeSymbols[0];\n }\n var i = -1;\n do {\n bytes = bytes / 1000;\n i++;\n } while (bytes > 999);\n\n return Math.max(bytes, 0.1).toFixed(1) + this._options.text.sizeSymbols[i];\n },\n\n // Creates an internal object that tracks various properties of each extra button,\n // and then actually creates the extra button.\n _generateExtraButtonSpecs: function() {\n var self = this;\n\n this._extraButtonSpecs = {};\n\n qq.each(this._options.extraButtons, function(idx, extraButtonOptionEntry) {\n var multiple = extraButtonOptionEntry.multiple,\n validation = qq.extend({}, self._options.validation, true),\n extraButtonSpec = qq.extend({}, extraButtonOptionEntry);\n\n if (multiple === undefined) {\n multiple = self._options.multiple;\n }\n\n if (extraButtonSpec.validation) {\n qq.extend(validation, extraButtonOptionEntry.validation, true);\n }\n\n qq.extend(extraButtonSpec, {\n multiple: multiple,\n validation: validation\n }, true);\n\n self._initExtraButton(extraButtonSpec);\n });\n },\n\n _getButton: function(buttonId) {\n var extraButtonsSpec = this._extraButtonSpecs[buttonId];\n\n if (extraButtonsSpec) {\n return extraButtonsSpec.element;\n }\n else if (buttonId === this._defaultButtonId) {\n return this._options.button;\n }\n },\n\n /**\n * Gets the internally used tracking ID for a button.\n *\n * @param buttonOrFileInputOrFile `File`, ` `, or a button container element\n * @returns {*} The button's ID, or undefined if no ID is recoverable\n * @private\n */\n _getButtonId: function(buttonOrFileInputOrFile) {\n var inputs, fileInput,\n fileBlobOrInput = buttonOrFileInputOrFile;\n\n // We want the reference file/blob here if this is a proxy (a file that will be generated on-demand later)\n if (fileBlobOrInput instanceof qq.BlobProxy) {\n fileBlobOrInput = fileBlobOrInput.referenceBlob;\n }\n\n // If the item is a `Blob` it will never be associated with a button or drop zone.\n if (fileBlobOrInput && !qq.isBlob(fileBlobOrInput)) {\n if (qq.isFile(fileBlobOrInput)) {\n return fileBlobOrInput.qqButtonId;\n }\n else if (fileBlobOrInput.tagName.toLowerCase() === \"input\" &&\n fileBlobOrInput.type.toLowerCase() === \"file\") {\n\n return fileBlobOrInput.getAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME);\n }\n\n inputs = fileBlobOrInput.getElementsByTagName(\"input\");\n\n qq.each(inputs, function(idx, input) {\n if (input.getAttribute(\"type\") === \"file\") {\n fileInput = input;\n return false;\n }\n });\n\n if (fileInput) {\n return fileInput.getAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME);\n }\n }\n },\n\n _getNotFinished: function() {\n return this._uploadData.retrieve({\n status: [\n qq.status.UPLOADING,\n qq.status.UPLOAD_RETRYING,\n qq.status.QUEUED,\n qq.status.SUBMITTING,\n qq.status.SUBMITTED,\n qq.status.PAUSED\n ]\n }).length;\n },\n\n // Get the validation options for this button. Could be the default validation option\n // or a specific one assigned to this particular button.\n _getValidationBase: function(buttonId) {\n var extraButtonSpec = this._extraButtonSpecs[buttonId];\n\n return extraButtonSpec ? extraButtonSpec.validation : this._options.validation;\n },\n\n _getValidationDescriptor: function(fileWrapper) {\n if (fileWrapper.file instanceof qq.BlobProxy) {\n return {\n name: qq.getFilename(fileWrapper.file.referenceBlob),\n size: fileWrapper.file.referenceBlob.size\n };\n }\n\n return {\n name: this.getUploads({id: fileWrapper.id}).name,\n size: this.getUploads({id: fileWrapper.id}).size\n };\n },\n\n _getValidationDescriptors: function(fileWrappers) {\n var self = this,\n fileDescriptors = [];\n\n qq.each(fileWrappers, function(idx, fileWrapper) {\n fileDescriptors.push(self._getValidationDescriptor(fileWrapper));\n });\n\n return fileDescriptors;\n },\n\n // Allows camera access on either the default or an extra button for iOS devices.\n _handleCameraAccess: function() {\n if (this._options.camera.ios && qq.ios()) {\n var acceptIosCamera = \"image/*;capture=camera\",\n button = this._options.camera.button,\n buttonId = button ? this._getButtonId(button) : this._defaultButtonId,\n optionRoot = this._options;\n\n // If we are not targeting the default button, it is an \"extra\" button\n if (buttonId && buttonId !== this._defaultButtonId) {\n optionRoot = this._extraButtonSpecs[buttonId];\n }\n\n // Camera access won't work in iOS if the `multiple` attribute is present on the file input\n optionRoot.multiple = false;\n\n // update the options\n if (optionRoot.validation.acceptFiles === null) {\n optionRoot.validation.acceptFiles = acceptIosCamera;\n }\n else {\n optionRoot.validation.acceptFiles += \",\" + acceptIosCamera;\n }\n\n // update the already-created button\n qq.each(this._buttons, function(idx, button) {\n if (button.getButtonId() === buttonId) {\n button.setMultiple(optionRoot.multiple);\n button.setAcceptFiles(optionRoot.acceptFiles);\n\n return false;\n }\n });\n }\n },\n\n _handleCheckedCallback: function(details) {\n var self = this,\n callbackRetVal = details.callback();\n\n if (qq.isGenericPromise(callbackRetVal)) {\n this.log(details.name + \" - waiting for \" + details.name + \" promise to be fulfilled for \" + details.identifier);\n return callbackRetVal.then(\n function(successParam) {\n self.log(details.name + \" promise success for \" + details.identifier);\n details.onSuccess(successParam);\n },\n function() {\n if (details.onFailure) {\n self.log(details.name + \" promise failure for \" + details.identifier);\n details.onFailure();\n }\n else {\n self.log(details.name + \" promise failure for \" + details.identifier);\n }\n });\n }\n\n if (callbackRetVal !== false) {\n details.onSuccess(callbackRetVal);\n }\n else {\n if (details.onFailure) {\n this.log(details.name + \" - return value was 'false' for \" + details.identifier + \". Invoking failure callback.\");\n details.onFailure();\n }\n else {\n this.log(details.name + \" - return value was 'false' for \" + details.identifier + \". Will not proceed.\");\n }\n }\n\n return callbackRetVal;\n },\n\n // Updates internal state when a new file has been received, and adds it along with its ID to a passed array.\n _handleNewFile: function(file, batchId, newFileWrapperList) {\n var self = this,\n uuid = qq.getUniqueId(),\n size = -1,\n name = qq.getFilename(file),\n actualFile = file.blob || file,\n handler = this._customNewFileHandler ?\n this._customNewFileHandler :\n qq.bind(self._handleNewFileGeneric, self);\n\n if (!qq.isInput(actualFile) && actualFile.size >= 0) {\n size = actualFile.size;\n }\n\n handler(actualFile, name, uuid, size, newFileWrapperList, batchId, this._options.request.uuidName, {\n uploadData: self._uploadData,\n paramsStore: self._paramsStore,\n addFileToHandler: function(id, file) {\n self._handler.add(id, file);\n self._netUploadedOrQueued++;\n self._trackButton(id);\n }\n });\n },\n\n _handleNewFileGeneric: function(file, name, uuid, size, fileList, batchId) {\n var id = this._uploadData.addFile({uuid: uuid, name: name, size: size, batchId: batchId});\n\n this._handler.add(id, file);\n this._trackButton(id);\n\n this._netUploadedOrQueued++;\n\n fileList.push({id: id, file: file});\n },\n\n _handlePasteSuccess: function(blob, extSuppliedName) {\n var extension = blob.type.split(\"/\")[1],\n name = extSuppliedName;\n\n /*jshint eqeqeq: true, eqnull: true*/\n if (name == null) {\n name = this._options.paste.defaultName;\n }\n\n name += \".\" + extension;\n\n this.addFiles({\n name: name,\n blob: blob\n });\n },\n\n // Creates an extra button element\n _initExtraButton: function(spec) {\n var button = this._createUploadButton({\n accept: spec.validation.acceptFiles,\n allowedExtensions: spec.validation.allowedExtensions,\n element: spec.element,\n folders: spec.folders,\n multiple: spec.multiple,\n title: spec.fileInputTitle\n });\n\n this._extraButtonSpecs[button.getButtonId()] = spec;\n },\n\n _initFormSupportAndParams: function() {\n this._formSupport = qq.FormSupport && new qq.FormSupport(\n this._options.form, qq.bind(this.uploadStoredFiles, this), qq.bind(this.log, this)\n );\n\n if (this._formSupport && this._formSupport.attachedToForm) {\n this._paramsStore = this._createStore(\n this._options.request.params, this._formSupport.getFormInputsAsObject\n );\n\n this._options.autoUpload = this._formSupport.newAutoUpload;\n if (this._formSupport.newEndpoint) {\n this._options.request.endpoint = this._formSupport.newEndpoint;\n }\n }\n else {\n this._paramsStore = this._createStore(this._options.request.params);\n }\n },\n\n _isDeletePossible: function() {\n if (!qq.DeleteFileAjaxRequester || !this._options.deleteFile.enabled) {\n return false;\n }\n\n if (this._options.cors.expected) {\n if (qq.supportedFeatures.deleteFileCorsXhr) {\n return true;\n }\n\n if (qq.supportedFeatures.deleteFileCorsXdr && this._options.cors.allowXdr) {\n return true;\n }\n\n return false;\n }\n\n return true;\n },\n\n _isAllowedExtension: function(allowed, fileName) {\n var valid = false;\n\n if (!allowed.length) {\n return true;\n }\n\n qq.each(allowed, function(idx, allowedExt) {\n /**\n * If an argument is not a string, ignore it. Added when a possible issue with MooTools hijacking the\n * `allowedExtensions` array was discovered. See case #735 in the issue tracker for more details.\n */\n if (qq.isString(allowedExt)) {\n /*jshint eqeqeq: true, eqnull: true*/\n var extRegex = new RegExp(\"\\\\.\" + allowedExt + \"$\", \"i\");\n\n if (fileName.match(extRegex) != null) {\n valid = true;\n return false;\n }\n }\n });\n\n return valid;\n },\n\n /**\n * Constructs and returns a message that describes an item/file error. Also calls `onError` callback.\n *\n * @param code REQUIRED - a code that corresponds to a stock message describing this type of error\n * @param maybeNameOrNames names of the items that have failed, if applicable\n * @param item `File`, `Blob`, or ` `\n * @private\n */\n _itemError: function(code, maybeNameOrNames, item) {\n var message = this._options.messages[code],\n allowedExtensions = [],\n names = [].concat(maybeNameOrNames),\n name = names[0],\n buttonId = this._getButtonId(item),\n validationBase = this._getValidationBase(buttonId),\n extensionsForMessage, placeholderMatch;\n\n function r(name, replacement) { message = message.replace(name, replacement); }\n\n qq.each(validationBase.allowedExtensions, function(idx, allowedExtension) {\n /**\n * If an argument is not a string, ignore it. Added when a possible issue with MooTools hijacking the\n * `allowedExtensions` array was discovered. See case #735 in the issue tracker for more details.\n */\n if (qq.isString(allowedExtension)) {\n allowedExtensions.push(allowedExtension);\n }\n });\n\n extensionsForMessage = allowedExtensions.join(\", \").toLowerCase();\n\n r(\"{file}\", this._options.formatFileName(name));\n r(\"{extensions}\", extensionsForMessage);\n r(\"{sizeLimit}\", this._formatSize(validationBase.sizeLimit));\n r(\"{minSizeLimit}\", this._formatSize(validationBase.minSizeLimit));\n\n placeholderMatch = message.match(/(\\{\\w+\\})/g);\n if (placeholderMatch !== null) {\n qq.each(placeholderMatch, function(idx, placeholder) {\n r(placeholder, names[idx]);\n });\n }\n\n this._options.callbacks.onError(null, name, message, undefined);\n\n return message;\n },\n\n /**\n * Conditionally orders a manual retry of a failed upload.\n *\n * @param id File ID of the failed upload\n * @param callback Optional callback to invoke if a retry is prudent.\n * In lieu of asking the upload handler to retry.\n * @returns {boolean} true if a manual retry will occur\n * @private\n */\n _manualRetry: function(id, callback) {\n if (this._onBeforeManualRetry(id)) {\n this._netUploadedOrQueued++;\n this._uploadData.setStatus(id, qq.status.UPLOAD_RETRYING);\n\n if (callback) {\n callback(id);\n }\n else {\n this._handler.retry(id);\n }\n\n return true;\n }\n },\n\n _maybeAllComplete: function(id, status) {\n var self = this,\n notFinished = this._getNotFinished();\n\n if (status === qq.status.UPLOAD_SUCCESSFUL) {\n this._succeededSinceLastAllComplete.push(id);\n }\n else if (status === qq.status.UPLOAD_FAILED) {\n this._failedSinceLastAllComplete.push(id);\n }\n\n if (notFinished === 0 &&\n (this._succeededSinceLastAllComplete.length || this._failedSinceLastAllComplete.length)) {\n // Attempt to ensure onAllComplete is not invoked before other callbacks, such as onCancel & onComplete\n setTimeout(function() {\n self._onAllComplete(self._succeededSinceLastAllComplete, self._failedSinceLastAllComplete);\n }, 0);\n }\n },\n\n _maybeHandleIos8SafariWorkaround: function() {\n var self = this;\n\n if (this._options.workarounds.ios8SafariUploads && qq.ios800() && qq.iosSafari()) {\n setTimeout(function() {\n window.alert(self._options.messages.unsupportedBrowserIos8Safari);\n }, 0);\n throw new qq.Error(this._options.messages.unsupportedBrowserIos8Safari);\n }\n },\n\n _maybeParseAndSendUploadError: function(id, name, response, xhr) {\n // Assuming no one will actually set the response code to something other than 200\n // and still set 'success' to true...\n if (!response.success) {\n if (xhr && xhr.status !== 200 && !response.error) {\n this._options.callbacks.onError(id, name, \"XHR returned response code \" + xhr.status, xhr);\n }\n else {\n var errorReason = response.error ? response.error : this._options.text.defaultResponseError;\n this._options.callbacks.onError(id, name, errorReason, xhr);\n }\n }\n },\n\n _maybeProcessNextItemAfterOnValidateCallback: function(validItem, items, index, params, endpoint) {\n var self = this;\n\n if (items.length > index) {\n if (validItem || !this._options.validation.stopOnFirstInvalidFile) {\n //use setTimeout to prevent a stack overflow with a large number of files in the batch & non-promissory callbacks\n setTimeout(function() {\n var validationDescriptor = self._getValidationDescriptor(items[index]),\n buttonId = self._getButtonId(items[index].file),\n button = self._getButton(buttonId);\n\n self._handleCheckedCallback({\n name: \"onValidate\",\n callback: qq.bind(self._options.callbacks.onValidate, self, validationDescriptor, button),\n onSuccess: qq.bind(self._onValidateCallbackSuccess, self, items, index, params, endpoint),\n onFailure: qq.bind(self._onValidateCallbackFailure, self, items, index, params, endpoint),\n identifier: \"Item '\" + validationDescriptor.name + \"', size: \" + validationDescriptor.size\n });\n }, 0);\n }\n else if (!validItem) {\n for (; index < items.length; index++) {\n self._fileOrBlobRejected(items[index].id);\n }\n }\n }\n },\n\n _onAllComplete: function(successful, failed) {\n this._totalProgress && this._totalProgress.onAllComplete(successful, failed, this._preventRetries);\n\n this._options.callbacks.onAllComplete(qq.extend([], successful), qq.extend([], failed));\n\n this._succeededSinceLastAllComplete = [];\n this._failedSinceLastAllComplete = [];\n },\n\n /**\n * Attempt to automatically retry a failed upload.\n *\n * @param id The file ID of the failed upload\n * @param name The name of the file associated with the failed upload\n * @param responseJSON Response from the server, parsed into a javascript object\n * @param xhr Ajax transport used to send the failed request\n * @param callback Optional callback to be invoked if a retry is prudent.\n * Invoked in lieu of asking the upload handler to retry.\n * @returns {boolean} true if an auto-retry will occur\n * @private\n */\n _onAutoRetry: function(id, name, responseJSON, xhr, callback) {\n var self = this;\n\n self._preventRetries[id] = responseJSON[self._options.retry.preventRetryResponseProperty];\n\n if (self._shouldAutoRetry(id, name, responseJSON)) {\n var retryWaitPeriod = self._options.retry.autoAttemptDelay * 1000;\n\n self._maybeParseAndSendUploadError.apply(self, arguments);\n self._options.callbacks.onAutoRetry(id, name, self._autoRetries[id]);\n self._onBeforeAutoRetry(id, name);\n\n self._uploadData.setStatus(id, qq.status.UPLOAD_RETRYING);\n self._retryTimeouts[id] = setTimeout(function() {\n self.log(\"Starting retry for \" + name + \"...\");\n\n if (callback) {\n callback(id);\n }\n else {\n self._handler.retry(id);\n }\n }, retryWaitPeriod);\n\n return true;\n }\n },\n\n _onBeforeAutoRetry: function(id, name) {\n this.log(\"Waiting \" + this._options.retry.autoAttemptDelay + \" seconds before retrying \" + name + \"...\");\n },\n\n //return false if we should not attempt the requested retry\n _onBeforeManualRetry: function(id) {\n var itemLimit = this._currentItemLimit,\n fileName;\n\n if (this._preventRetries[id]) {\n this.log(\"Retries are forbidden for id \" + id, \"warn\");\n return false;\n }\n else if (this._handler.isValid(id)) {\n fileName = this.getName(id);\n\n if (this._options.callbacks.onManualRetry(id, fileName) === false) {\n return false;\n }\n\n if (itemLimit > 0 && this._netUploadedOrQueued + 1 > itemLimit) {\n this._itemError(\"retryFailTooManyItems\");\n return false;\n }\n\n this.log(\"Retrying upload for '\" + fileName + \"' (id: \" + id + \")...\");\n return true;\n }\n else {\n this.log(\"'\" + id + \"' is not a valid file ID\", \"error\");\n return false;\n }\n },\n\n _onCancel: function(id, name) {\n this._netUploadedOrQueued--;\n\n clearTimeout(this._retryTimeouts[id]);\n\n var storedItemIndex = qq.indexOf(this._storedIds, id);\n if (!this._options.autoUpload && storedItemIndex >= 0) {\n this._storedIds.splice(storedItemIndex, 1);\n }\n\n this._uploadData.setStatus(id, qq.status.CANCELED);\n },\n\n _onComplete: function(id, name, result, xhr) {\n if (!result.success) {\n this._netUploadedOrQueued--;\n this._uploadData.setStatus(id, qq.status.UPLOAD_FAILED);\n\n if (result[this._options.retry.preventRetryResponseProperty] === true) {\n this._preventRetries[id] = true;\n }\n }\n else {\n if (result.thumbnailUrl) {\n this._thumbnailUrls[id] = result.thumbnailUrl;\n }\n\n this._netUploaded++;\n this._uploadData.setStatus(id, qq.status.UPLOAD_SUCCESSFUL);\n }\n\n this._maybeParseAndSendUploadError(id, name, result, xhr);\n\n return result.success ? true : false;\n },\n\n _onDelete: function(id) {\n this._uploadData.setStatus(id, qq.status.DELETING);\n },\n\n _onDeleteComplete: function(id, xhrOrXdr, isError) {\n var name = this.getName(id);\n\n if (isError) {\n this._uploadData.setStatus(id, qq.status.DELETE_FAILED);\n this.log(\"Delete request for '\" + name + \"' has failed.\", \"error\");\n\n // For error reporting, we only have access to the response status if this is not\n // an `XDomainRequest`.\n if (xhrOrXdr.withCredentials === undefined) {\n this._options.callbacks.onError(id, name, \"Delete request failed\", xhrOrXdr);\n }\n else {\n this._options.callbacks.onError(id, name, \"Delete request failed with response code \" + xhrOrXdr.status, xhrOrXdr);\n }\n }\n else {\n this._netUploadedOrQueued--;\n this._netUploaded--;\n this._handler.expunge(id);\n this._uploadData.setStatus(id, qq.status.DELETED);\n this.log(\"Delete request for '\" + name + \"' has succeeded.\");\n }\n },\n\n _onInputChange: function(input) {\n var fileIndex;\n\n if (qq.supportedFeatures.ajaxUploading) {\n for (fileIndex = 0; fileIndex < input.files.length; fileIndex++) {\n this._annotateWithButtonId(input.files[fileIndex], input);\n }\n\n this.addFiles(input.files);\n }\n // Android 2.3.x will fire `onchange` even if no file has been selected\n else if (input.value.length > 0) {\n this.addFiles(input);\n }\n\n qq.each(this._buttons, function(idx, button) {\n button.reset();\n });\n },\n\n _onProgress: function(id, name, loaded, total) {\n this._totalProgress && this._totalProgress.onIndividualProgress(id, loaded, total);\n },\n\n _onSubmit: function(id, name) {\n //nothing to do yet in core uploader\n },\n\n _onSubmitCallbackSuccess: function(id, name) {\n this._onSubmit.apply(this, arguments);\n this._uploadData.setStatus(id, qq.status.SUBMITTED);\n this._onSubmitted.apply(this, arguments);\n\n if (this._options.autoUpload) {\n this._options.callbacks.onSubmitted.apply(this, arguments);\n this._uploadFile(id);\n }\n else {\n this._storeForLater(id);\n this._options.callbacks.onSubmitted.apply(this, arguments);\n }\n },\n\n _onSubmitDelete: function(id, onSuccessCallback, additionalMandatedParams) {\n var uuid = this.getUuid(id),\n adjustedOnSuccessCallback;\n\n if (onSuccessCallback) {\n adjustedOnSuccessCallback = qq.bind(onSuccessCallback, this, id, uuid, additionalMandatedParams);\n }\n\n if (this._isDeletePossible()) {\n this._handleCheckedCallback({\n name: \"onSubmitDelete\",\n callback: qq.bind(this._options.callbacks.onSubmitDelete, this, id),\n onSuccess: adjustedOnSuccessCallback ||\n qq.bind(this._deleteHandler.sendDelete, this, id, uuid, additionalMandatedParams),\n identifier: id\n });\n return true;\n }\n else {\n this.log(\"Delete request ignored for ID \" + id + \", delete feature is disabled or request not possible \" +\n \"due to CORS on a user agent that does not support pre-flighting.\", \"warn\");\n return false;\n }\n },\n\n _onSubmitted: function(id) {\n //nothing to do in the base uploader\n },\n\n _onTotalProgress: function(loaded, total) {\n this._options.callbacks.onTotalProgress(loaded, total);\n },\n\n _onUploadPrep: function(id) {\n // nothing to do in the core uploader for now\n },\n\n _onUpload: function(id, name) {\n this._uploadData.setStatus(id, qq.status.UPLOADING);\n },\n\n _onUploadChunk: function(id, chunkData) {\n //nothing to do in the base uploader\n },\n\n _onUploadStatusChange: function(id, oldStatus, newStatus) {\n // Make sure a \"queued\" retry attempt is canceled if the upload has been paused\n if (newStatus === qq.status.PAUSED) {\n clearTimeout(this._retryTimeouts[id]);\n }\n },\n\n _onValidateBatchCallbackFailure: function(fileWrappers) {\n var self = this;\n\n qq.each(fileWrappers, function(idx, fileWrapper) {\n self._fileOrBlobRejected(fileWrapper.id);\n });\n },\n\n _onValidateBatchCallbackSuccess: function(validationDescriptors, items, params, endpoint, button) {\n var errorMessage,\n itemLimit = this._currentItemLimit,\n proposedNetFilesUploadedOrQueued = this._netUploadedOrQueued;\n\n if (itemLimit === 0 || proposedNetFilesUploadedOrQueued <= itemLimit) {\n if (items.length > 0) {\n this._handleCheckedCallback({\n name: \"onValidate\",\n callback: qq.bind(this._options.callbacks.onValidate, this, validationDescriptors[0], button),\n onSuccess: qq.bind(this._onValidateCallbackSuccess, this, items, 0, params, endpoint),\n onFailure: qq.bind(this._onValidateCallbackFailure, this, items, 0, params, endpoint),\n identifier: \"Item '\" + items[0].file.name + \"', size: \" + items[0].file.size\n });\n }\n else {\n this._itemError(\"noFilesError\");\n }\n }\n else {\n this._onValidateBatchCallbackFailure(items);\n errorMessage = this._options.messages.tooManyItemsError\n .replace(/\\{netItems\\}/g, proposedNetFilesUploadedOrQueued)\n .replace(/\\{itemLimit\\}/g, itemLimit);\n this._batchError(errorMessage);\n }\n },\n\n _onValidateCallbackFailure: function(items, index, params, endpoint) {\n var nextIndex = index + 1;\n\n this._fileOrBlobRejected(items[index].id, items[index].file.name);\n\n this._maybeProcessNextItemAfterOnValidateCallback(false, items, nextIndex, params, endpoint);\n },\n\n _onValidateCallbackSuccess: function(items, index, params, endpoint) {\n var self = this,\n nextIndex = index + 1,\n validationDescriptor = this._getValidationDescriptor(items[index]);\n\n this._validateFileOrBlobData(items[index], validationDescriptor)\n .then(\n function() {\n self._upload(items[index].id, params, endpoint);\n self._maybeProcessNextItemAfterOnValidateCallback(true, items, nextIndex, params, endpoint);\n },\n function() {\n self._maybeProcessNextItemAfterOnValidateCallback(false, items, nextIndex, params, endpoint);\n }\n );\n },\n\n _prepareItemsForUpload: function(items, params, endpoint) {\n if (items.length === 0) {\n this._itemError(\"noFilesError\");\n return;\n }\n\n var validationDescriptors = this._getValidationDescriptors(items),\n buttonId = this._getButtonId(items[0].file),\n button = this._getButton(buttonId);\n\n this._handleCheckedCallback({\n name: \"onValidateBatch\",\n callback: qq.bind(this._options.callbacks.onValidateBatch, this, validationDescriptors, button),\n onSuccess: qq.bind(this._onValidateBatchCallbackSuccess, this, validationDescriptors, items, params, endpoint, button),\n onFailure: qq.bind(this._onValidateBatchCallbackFailure, this, items),\n identifier: \"batch validation\"\n });\n },\n\n _preventLeaveInProgress: function() {\n var self = this;\n\n this._disposeSupport.attach(window, \"beforeunload\", function(e) {\n if (self.getInProgress()) {\n e = e || window.event;\n // for ie, ff\n e.returnValue = self._options.messages.onLeave;\n // for webkit\n return self._options.messages.onLeave;\n }\n });\n },\n\n // Attempts to refresh session data only if the `qq.Session` module exists\n // and a session endpoint has been specified. The `onSessionRequestComplete`\n // callback will be invoked once the refresh is complete.\n _refreshSessionData: function() {\n var self = this,\n options = this._options.session;\n\n /* jshint eqnull:true */\n if (qq.Session && this._options.session.endpoint != null) {\n if (!this._session) {\n qq.extend(options, {cors: this._options.cors});\n\n options.log = qq.bind(this.log, this);\n options.addFileRecord = qq.bind(this._addCannedFile, this);\n\n this._session = new qq.Session(options);\n }\n\n setTimeout(function() {\n self._session.refresh().then(function(response, xhrOrXdr) {\n self._sessionRequestComplete();\n self._options.callbacks.onSessionRequestComplete(response, true, xhrOrXdr);\n\n }, function(response, xhrOrXdr) {\n\n self._options.callbacks.onSessionRequestComplete(response, false, xhrOrXdr);\n });\n }, 0);\n }\n },\n\n _sessionRequestComplete: function() {},\n\n _setSize: function(id, newSize) {\n this._uploadData.updateSize(id, newSize);\n this._totalProgress && this._totalProgress.onNewSize(id);\n },\n\n _shouldAutoRetry: function(id, name, responseJSON) {\n var uploadData = this._uploadData.retrieve({id: id});\n\n /*jshint laxbreak: true */\n if (!this._preventRetries[id]\n && this._options.retry.enableAuto\n && uploadData.status !== qq.status.PAUSED) {\n\n if (this._autoRetries[id] === undefined) {\n this._autoRetries[id] = 0;\n }\n\n if (this._autoRetries[id] < this._options.retry.maxAutoAttempts) {\n this._autoRetries[id] += 1;\n return true;\n }\n }\n\n return false;\n },\n\n _storeForLater: function(id) {\n this._storedIds.push(id);\n },\n\n // Maps a file with the button that was used to select it.\n _trackButton: function(id) {\n var buttonId;\n\n if (qq.supportedFeatures.ajaxUploading) {\n buttonId = this._handler.getFile(id).qqButtonId;\n }\n else {\n buttonId = this._getButtonId(this._handler.getInput(id));\n }\n\n if (buttonId) {\n this._buttonIdsForFileIds[id] = buttonId;\n }\n },\n\n _updateFormSupportAndParams: function(formElementOrId) {\n this._options.form.element = formElementOrId;\n\n this._formSupport = qq.FormSupport && new qq.FormSupport(\n this._options.form, qq.bind(this.uploadStoredFiles, this), qq.bind(this.log, this)\n );\n\n if (this._formSupport && this._formSupport.attachedToForm) {\n this._paramsStore.addReadOnly(null, this._formSupport.getFormInputsAsObject);\n\n this._options.autoUpload = this._formSupport.newAutoUpload;\n if (this._formSupport.newEndpoint) {\n this.setEndpoint(this._formSupport.newEndpoint);\n }\n }\n },\n\n _upload: function(id, params, endpoint) {\n var name = this.getName(id);\n\n if (params) {\n this.setParams(params, id);\n }\n\n if (endpoint) {\n this.setEndpoint(endpoint, id);\n }\n\n this._handleCheckedCallback({\n name: \"onSubmit\",\n callback: qq.bind(this._options.callbacks.onSubmit, this, id, name),\n onSuccess: qq.bind(this._onSubmitCallbackSuccess, this, id, name),\n onFailure: qq.bind(this._fileOrBlobRejected, this, id, name),\n identifier: id\n });\n },\n\n _uploadFile: function(id) {\n if (!this._handler.upload(id)) {\n this._uploadData.setStatus(id, qq.status.QUEUED);\n }\n },\n\n _uploadStoredFiles: function() {\n var idToUpload, stillSubmitting,\n self = this;\n\n while (this._storedIds.length) {\n idToUpload = this._storedIds.shift();\n this._uploadFile(idToUpload);\n }\n\n // If we are still waiting for some files to clear validation, attempt to upload these again in a bit\n stillSubmitting = this.getUploads({status: qq.status.SUBMITTING}).length;\n if (stillSubmitting) {\n qq.log(\"Still waiting for \" + stillSubmitting + \" files to clear submit queue. Will re-parse stored IDs array shortly.\");\n setTimeout(function() {\n self._uploadStoredFiles();\n }, 1000);\n }\n },\n\n /**\n * Performs some internal validation checks on an item, defined in the `validation` option.\n *\n * @param fileWrapper Wrapper containing a `file` along with an `id`\n * @param validationDescriptor Normalized information about the item (`size`, `name`).\n * @returns qq.Promise with appropriate callbacks invoked depending on the validity of the file\n * @private\n */\n _validateFileOrBlobData: function(fileWrapper, validationDescriptor) {\n var self = this,\n file = (function() {\n if (fileWrapper.file instanceof qq.BlobProxy) {\n return fileWrapper.file.referenceBlob;\n }\n return fileWrapper.file;\n }()),\n name = validationDescriptor.name,\n size = validationDescriptor.size,\n buttonId = this._getButtonId(fileWrapper.file),\n validationBase = this._getValidationBase(buttonId),\n validityChecker = new qq.Promise();\n\n validityChecker.then(\n function() {},\n function() {\n self._fileOrBlobRejected(fileWrapper.id, name);\n });\n\n if (qq.isFileOrInput(file) && !this._isAllowedExtension(validationBase.allowedExtensions, name)) {\n this._itemError(\"typeError\", name, file);\n return validityChecker.failure();\n }\n\n if (!this._options.validation.allowEmpty && size === 0) {\n this._itemError(\"emptyError\", name, file);\n return validityChecker.failure();\n }\n\n if (size > 0 && validationBase.sizeLimit && size > validationBase.sizeLimit) {\n this._itemError(\"sizeError\", name, file);\n return validityChecker.failure();\n }\n\n if (size > 0 && size < validationBase.minSizeLimit) {\n this._itemError(\"minSizeError\", name, file);\n return validityChecker.failure();\n }\n\n if (qq.ImageValidation && qq.supportedFeatures.imagePreviews && qq.isFile(file)) {\n new qq.ImageValidation(file, qq.bind(self.log, self)).validate(validationBase.image).then(\n validityChecker.success,\n function(errorCode) {\n self._itemError(errorCode + \"ImageError\", name, file);\n validityChecker.failure();\n }\n );\n }\n else {\n validityChecker.success();\n }\n\n return validityChecker;\n },\n\n _wrapCallbacks: function() {\n var self, safeCallback, prop;\n\n self = this;\n\n safeCallback = function(name, callback, args) {\n var errorMsg;\n\n try {\n return callback.apply(self, args);\n }\n catch (exception) {\n errorMsg = exception.message || exception.toString();\n self.log(\"Caught exception in '\" + name + \"' callback - \" + errorMsg, \"error\");\n }\n };\n\n /* jshint forin: false, loopfunc: true */\n for (prop in this._options.callbacks) {\n (function() {\n var callbackName, callbackFunc;\n callbackName = prop;\n callbackFunc = self._options.callbacks[callbackName];\n self._options.callbacks[callbackName] = function() {\n return safeCallback(callbackName, callbackFunc, arguments);\n };\n }());\n }\n }\n };\n}());\n","/*globals qq*/\n(function() {\n \"use strict\";\n\n qq.FineUploaderBasic = function(o) {\n var self = this;\n\n // These options define FineUploaderBasic mode.\n this._options = {\n debug: false,\n button: null,\n multiple: true,\n maxConnections: 3,\n disableCancelForFormUploads: false,\n autoUpload: true,\n\n request: {\n customHeaders: {},\n endpoint: \"/server/upload\",\n filenameParam: \"qqfilename\",\n forceMultipart: true,\n inputName: \"qqfile\",\n method: \"POST\",\n params: {},\n paramsInBody: true,\n totalFileSizeName: \"qqtotalfilesize\",\n uuidName: \"qquuid\"\n },\n\n validation: {\n allowedExtensions: [],\n sizeLimit: 0,\n minSizeLimit: 0,\n itemLimit: 0,\n stopOnFirstInvalidFile: true,\n acceptFiles: null,\n image: {\n maxHeight: 0,\n maxWidth: 0,\n minHeight: 0,\n minWidth: 0\n },\n allowEmpty: false\n },\n\n callbacks: {\n onSubmit: function(id, name) {},\n onSubmitted: function(id, name) {},\n onComplete: function(id, name, responseJSON, maybeXhr) {},\n onAllComplete: function(successful, failed) {},\n onCancel: function(id, name) {},\n onUpload: function(id, name) {},\n onUploadChunk: function(id, name, chunkData) {},\n onUploadChunkSuccess: function(id, chunkData, responseJSON, xhr) {},\n onResume: function(id, fileName, chunkData) {},\n onProgress: function(id, name, loaded, total) {},\n onTotalProgress: function(loaded, total) {},\n onError: function(id, name, reason, maybeXhrOrXdr) {},\n onAutoRetry: function(id, name, attemptNumber) {},\n onManualRetry: function(id, name) {},\n onValidateBatch: function(fileOrBlobData) {},\n onValidate: function(fileOrBlobData) {},\n onSubmitDelete: function(id) {},\n onDelete: function(id) {},\n onDeleteComplete: function(id, xhrOrXdr, isError) {},\n onPasteReceived: function(blob) {},\n onStatusChange: function(id, oldStatus, newStatus) {},\n onSessionRequestComplete: function(response, success, xhrOrXdr) {}\n },\n\n messages: {\n typeError: \"{file} has an invalid extension. Valid extension(s): {extensions}.\",\n sizeError: \"{file} is too large, maximum file size is {sizeLimit}.\",\n minSizeError: \"{file} is too small, minimum file size is {minSizeLimit}.\",\n emptyError: \"{file} is empty, please select files again without it.\",\n noFilesError: \"No files to upload.\",\n tooManyItemsError: \"Too many items ({netItems}) would be uploaded. Item limit is {itemLimit}.\",\n maxHeightImageError: \"Image is too tall.\",\n maxWidthImageError: \"Image is too wide.\",\n minHeightImageError: \"Image is not tall enough.\",\n minWidthImageError: \"Image is not wide enough.\",\n retryFailTooManyItems: \"Retry failed - you have reached your file limit.\",\n onLeave: \"The files are being uploaded, if you leave now the upload will be canceled.\",\n unsupportedBrowserIos8Safari: \"Unrecoverable error - this browser does not permit file uploading of any kind due to serious bugs in iOS8 Safari. Please use iOS8 Chrome until Apple fixes these issues.\"\n },\n\n retry: {\n enableAuto: false,\n maxAutoAttempts: 3,\n autoAttemptDelay: 5,\n preventRetryResponseProperty: \"preventRetry\"\n },\n\n classes: {\n buttonHover: \"qq-upload-button-hover\",\n buttonFocus: \"qq-upload-button-focus\"\n },\n\n chunking: {\n enabled: false,\n concurrent: {\n enabled: false\n },\n mandatory: false,\n paramNames: {\n partIndex: \"qqpartindex\",\n partByteOffset: \"qqpartbyteoffset\",\n chunkSize: \"qqchunksize\",\n totalFileSize: \"qqtotalfilesize\",\n totalParts: \"qqtotalparts\"\n },\n partSize: 2000000,\n // only relevant for traditional endpoints, only required when concurrent.enabled === true\n success: {\n endpoint: null\n }\n },\n\n resume: {\n enabled: false,\n recordsExpireIn: 7, //days\n paramNames: {\n resuming: \"qqresume\"\n }\n },\n\n formatFileName: function(fileOrBlobName) {\n return fileOrBlobName;\n },\n\n text: {\n defaultResponseError: \"Upload failure reason unknown\",\n fileInputTitle: \"file input\",\n sizeSymbols: [\"kB\", \"MB\", \"GB\", \"TB\", \"PB\", \"EB\"]\n },\n\n deleteFile: {\n enabled: false,\n method: \"DELETE\",\n endpoint: \"/server/upload\",\n customHeaders: {},\n params: {}\n },\n\n cors: {\n expected: false,\n sendCredentials: false,\n allowXdr: false\n },\n\n blobs: {\n defaultName: \"misc_data\"\n },\n\n paste: {\n targetElement: null,\n defaultName: \"pasted_image\"\n },\n\n camera: {\n ios: false,\n\n // if ios is true: button is null means target the default button, otherwise target the button specified\n button: null\n },\n\n // This refers to additional upload buttons to be handled by Fine Uploader.\n // Each element is an object, containing `element` as the only required\n // property. The `element` must be a container that will ultimately\n // contain an invisible ` ` created by Fine Uploader.\n // Optional properties of each object include `multiple`, `validation`,\n // and `folders`.\n extraButtons: [],\n\n // Depends on the session module. Used to query the server for an initial file list\n // during initialization and optionally after a `reset`.\n session: {\n endpoint: null,\n params: {},\n customHeaders: {},\n refreshOnReset: true\n },\n\n // Send parameters associated with an existing form along with the files\n form: {\n // Element ID, HTMLElement, or null\n element: \"qq-form\",\n\n // Overrides the base `autoUpload`, unless `element` is null.\n autoUpload: false,\n\n // true = upload files on form submission (and squelch submit event)\n interceptSubmit: true\n },\n\n // scale images client side, upload a new file for each scaled version\n scaling: {\n customResizer: null,\n\n // send the original file as well\n sendOriginal: true,\n\n // fox orientation for scaled images\n orient: true,\n\n // If null, scaled image type will match reference image type. This value will be referred to\n // for any size record that does not specific a type.\n defaultType: null,\n\n defaultQuality: 80,\n\n failureText: \"Failed to scale\",\n\n includeExif: false,\n\n // metadata about each requested scaled version\n sizes: []\n },\n\n workarounds: {\n iosEmptyVideos: true,\n ios8SafariUploads: true,\n ios8BrowserCrash: false\n }\n };\n\n // Replace any default options with user defined ones\n qq.extend(this._options, o, true);\n\n this._buttons = [];\n this._extraButtonSpecs = {};\n this._buttonIdsForFileIds = [];\n\n this._wrapCallbacks();\n this._disposeSupport = new qq.DisposeSupport();\n\n this._storedIds = [];\n this._autoRetries = [];\n this._retryTimeouts = [];\n this._preventRetries = [];\n this._thumbnailUrls = [];\n\n this._netUploadedOrQueued = 0;\n this._netUploaded = 0;\n this._uploadData = this._createUploadDataTracker();\n\n this._initFormSupportAndParams();\n\n this._customHeadersStore = this._createStore(this._options.request.customHeaders);\n this._deleteFileCustomHeadersStore = this._createStore(this._options.deleteFile.customHeaders);\n\n this._deleteFileParamsStore = this._createStore(this._options.deleteFile.params);\n\n this._endpointStore = this._createStore(this._options.request.endpoint);\n this._deleteFileEndpointStore = this._createStore(this._options.deleteFile.endpoint);\n\n this._handler = this._createUploadHandler();\n\n this._deleteHandler = qq.DeleteFileAjaxRequester && this._createDeleteHandler();\n\n if (this._options.button) {\n this._defaultButtonId = this._createUploadButton({\n element: this._options.button,\n title: this._options.text.fileInputTitle\n }).getButtonId();\n }\n\n this._generateExtraButtonSpecs();\n\n this._handleCameraAccess();\n\n if (this._options.paste.targetElement) {\n if (qq.PasteSupport) {\n this._pasteHandler = this._createPasteHandler();\n }\n else {\n this.log(\"Paste support module not found\", \"error\");\n }\n }\n\n this._preventLeaveInProgress();\n\n this._imageGenerator = qq.ImageGenerator && new qq.ImageGenerator(qq.bind(this.log, this));\n this._refreshSessionData();\n\n this._succeededSinceLastAllComplete = [];\n this._failedSinceLastAllComplete = [];\n\n this._scaler = (qq.Scaler && new qq.Scaler(this._options.scaling, qq.bind(this.log, this))) || {};\n if (this._scaler.enabled) {\n this._customNewFileHandler = qq.bind(this._scaler.handleNewFile, this._scaler);\n }\n\n if (qq.TotalProgress && qq.supportedFeatures.progressBar) {\n this._totalProgress = new qq.TotalProgress(\n qq.bind(this._onTotalProgress, this),\n\n function(id) {\n var entry = self._uploadData.retrieve({id: id});\n return (entry && entry.size) || 0;\n }\n );\n }\n\n this._currentItemLimit = this._options.validation.itemLimit;\n };\n\n // Define the private & public API methods.\n qq.FineUploaderBasic.prototype = qq.basePublicApi;\n qq.extend(qq.FineUploaderBasic.prototype, qq.basePrivateApi);\n}());\n","/*globals qq, XDomainRequest*/\n/** Generic class for sending non-upload ajax requests and handling the associated responses **/\nqq.AjaxRequester = function(o) {\n \"use strict\";\n\n var log, shouldParamsBeInQueryString,\n queue = [],\n requestData = {},\n options = {\n acceptHeader: null,\n validMethods: [\"PATCH\", \"POST\", \"PUT\"],\n method: \"POST\",\n contentType: \"application/x-www-form-urlencoded\",\n maxConnections: 3,\n customHeaders: {},\n endpointStore: {},\n paramsStore: {},\n mandatedParams: {},\n allowXRequestedWithAndCacheControl: true,\n successfulResponseCodes: {\n DELETE: [200, 202, 204],\n PATCH: [200, 201, 202, 203, 204],\n POST: [200, 201, 202, 203, 204],\n PUT: [200, 201, 202, 203, 204],\n GET: [200]\n },\n cors: {\n expected: false,\n sendCredentials: false\n },\n log: function(str, level) {},\n onSend: function(id) {},\n onComplete: function(id, xhrOrXdr, isError) {},\n onProgress: null\n };\n\n qq.extend(options, o);\n log = options.log;\n\n if (qq.indexOf(options.validMethods, options.method) < 0) {\n throw new Error(\"'\" + options.method + \"' is not a supported method for this type of request!\");\n }\n\n // [Simple methods](http://www.w3.org/TR/cors/#simple-method)\n // are defined by the W3C in the CORS spec as a list of methods that, in part,\n // make a CORS request eligible to be exempt from preflighting.\n function isSimpleMethod() {\n return qq.indexOf([\"GET\", \"POST\", \"HEAD\"], options.method) >= 0;\n }\n\n // [Simple headers](http://www.w3.org/TR/cors/#simple-header)\n // are defined by the W3C in the CORS spec as a list of headers that, in part,\n // make a CORS request eligible to be exempt from preflighting.\n function containsNonSimpleHeaders(headers) {\n var containsNonSimple = false;\n\n qq.each(containsNonSimple, function(idx, header) {\n if (qq.indexOf([\"Accept\", \"Accept-Language\", \"Content-Language\", \"Content-Type\"], header) < 0) {\n containsNonSimple = true;\n return false;\n }\n });\n\n return containsNonSimple;\n }\n\n function isXdr(xhr) {\n //The `withCredentials` test is a commonly accepted way to determine if XHR supports CORS.\n return options.cors.expected && xhr.withCredentials === undefined;\n }\n\n // Returns either a new `XMLHttpRequest` or `XDomainRequest` instance.\n function getCorsAjaxTransport() {\n var xhrOrXdr;\n\n if (window.XMLHttpRequest || window.ActiveXObject) {\n xhrOrXdr = qq.createXhrInstance();\n\n if (xhrOrXdr.withCredentials === undefined) {\n xhrOrXdr = new XDomainRequest();\n // Workaround for XDR bug in IE9 - https://social.msdn.microsoft.com/Forums/ie/en-US/30ef3add-767c-4436-b8a9-f1ca19b4812e/ie9-rtm-xdomainrequest-issued-requests-may-abort-if-all-event-handlers-not-specified?forum=iewebdevelopment\n xhrOrXdr.onload = function() {};\n xhrOrXdr.onerror = function() {};\n xhrOrXdr.ontimeout = function() {};\n xhrOrXdr.onprogress = function() {};\n }\n }\n\n return xhrOrXdr;\n }\n\n // Returns either a new XHR/XDR instance, or an existing one for the associated `File` or `Blob`.\n function getXhrOrXdr(id, suppliedXhr) {\n var xhrOrXdr = requestData[id].xhr;\n\n if (!xhrOrXdr) {\n if (suppliedXhr) {\n xhrOrXdr = suppliedXhr;\n }\n else {\n if (options.cors.expected) {\n xhrOrXdr = getCorsAjaxTransport();\n }\n else {\n xhrOrXdr = qq.createXhrInstance();\n }\n }\n\n requestData[id].xhr = xhrOrXdr;\n }\n\n return xhrOrXdr;\n }\n\n // Removes element from queue, sends next request\n function dequeue(id) {\n var i = qq.indexOf(queue, id),\n max = options.maxConnections,\n nextId;\n\n delete requestData[id];\n queue.splice(i, 1);\n\n if (queue.length >= max && i < max) {\n nextId = queue[max - 1];\n sendRequest(nextId);\n }\n }\n\n function onComplete(id, xdrError) {\n var xhr = getXhrOrXdr(id),\n method = options.method,\n isError = xdrError === true;\n\n dequeue(id);\n\n if (isError) {\n log(method + \" request for \" + id + \" has failed\", \"error\");\n }\n else if (!isXdr(xhr) && !isResponseSuccessful(xhr.status)) {\n isError = true;\n log(method + \" request for \" + id + \" has failed - response code \" + xhr.status, \"error\");\n }\n\n options.onComplete(id, xhr, isError);\n }\n\n function getParams(id) {\n var onDemandParams = requestData[id].additionalParams,\n mandatedParams = options.mandatedParams,\n params;\n\n if (options.paramsStore.get) {\n params = options.paramsStore.get(id);\n }\n\n if (onDemandParams) {\n qq.each(onDemandParams, function(name, val) {\n params = params || {};\n params[name] = val;\n });\n }\n\n if (mandatedParams) {\n qq.each(mandatedParams, function(name, val) {\n params = params || {};\n params[name] = val;\n });\n }\n\n return params;\n }\n\n function sendRequest(id, optXhr) {\n var xhr = getXhrOrXdr(id, optXhr),\n method = options.method,\n params = getParams(id),\n payload = requestData[id].payload,\n url;\n\n options.onSend(id);\n\n url = createUrl(id, params, requestData[id].additionalQueryParams);\n\n // XDR and XHR status detection APIs differ a bit.\n if (isXdr(xhr)) {\n xhr.onload = getXdrLoadHandler(id);\n xhr.onerror = getXdrErrorHandler(id);\n }\n else {\n xhr.onreadystatechange = getXhrReadyStateChangeHandler(id);\n }\n\n registerForUploadProgress(id);\n\n // The last parameter is assumed to be ignored if we are actually using `XDomainRequest`.\n xhr.open(method, url, true);\n\n // Instruct the transport to send cookies along with the CORS request,\n // unless we are using `XDomainRequest`, which is not capable of this.\n if (options.cors.expected && options.cors.sendCredentials && !isXdr(xhr)) {\n xhr.withCredentials = true;\n }\n\n setHeaders(id);\n\n log(\"Sending \" + method + \" request for \" + id);\n\n if (payload) {\n xhr.send(payload);\n }\n else if (shouldParamsBeInQueryString || !params) {\n xhr.send();\n }\n else if (params && options.contentType && options.contentType.toLowerCase().indexOf(\"application/x-www-form-urlencoded\") >= 0) {\n xhr.send(qq.obj2url(params, \"\"));\n }\n else if (params && options.contentType && options.contentType.toLowerCase().indexOf(\"application/json\") >= 0) {\n xhr.send(JSON.stringify(params));\n }\n else {\n xhr.send(params);\n }\n\n return xhr;\n }\n\n function createUrl(id, params, additionalQueryParams) {\n var endpoint = options.endpointStore.get(id),\n addToPath = requestData[id].addToPath;\n\n /*jshint -W116,-W041 */\n if (addToPath != undefined) {\n endpoint += \"/\" + addToPath;\n }\n\n if (shouldParamsBeInQueryString && params) {\n endpoint = qq.obj2url(params, endpoint);\n }\n\n if (additionalQueryParams) {\n endpoint = qq.obj2url(additionalQueryParams, endpoint);\n }\n\n return endpoint;\n }\n\n // Invoked by the UA to indicate a number of possible states that describe\n // a live `XMLHttpRequest` transport.\n function getXhrReadyStateChangeHandler(id) {\n return function() {\n if (getXhrOrXdr(id).readyState === 4) {\n onComplete(id);\n }\n };\n }\n\n function registerForUploadProgress(id) {\n var onProgress = options.onProgress;\n\n if (onProgress) {\n getXhrOrXdr(id).upload.onprogress = function(e) {\n if (e.lengthComputable) {\n onProgress(id, e.loaded, e.total);\n }\n };\n }\n }\n\n // This will be called by IE to indicate **success** for an associated\n // `XDomainRequest` transported request.\n function getXdrLoadHandler(id) {\n return function() {\n onComplete(id);\n };\n }\n\n // This will be called by IE to indicate **failure** for an associated\n // `XDomainRequest` transported request.\n function getXdrErrorHandler(id) {\n return function() {\n onComplete(id, true);\n };\n }\n\n function setHeaders(id) {\n var xhr = getXhrOrXdr(id),\n customHeaders = options.customHeaders,\n onDemandHeaders = requestData[id].additionalHeaders || {},\n method = options.method,\n allHeaders = {};\n\n // If XDomainRequest is being used, we can't set headers, so just ignore this block.\n if (!isXdr(xhr)) {\n options.acceptHeader && xhr.setRequestHeader(\"Accept\", options.acceptHeader);\n\n // Only attempt to add X-Requested-With & Cache-Control if permitted\n if (options.allowXRequestedWithAndCacheControl) {\n // Do not add X-Requested-With & Cache-Control if this is a cross-origin request\n // OR the cross-origin request contains a non-simple method or header.\n // This is done to ensure a preflight is not triggered exclusively based on the\n // addition of these 2 non-simple headers.\n if (!options.cors.expected || (!isSimpleMethod() || containsNonSimpleHeaders(customHeaders))) {\n xhr.setRequestHeader(\"X-Requested-With\", \"XMLHttpRequest\");\n xhr.setRequestHeader(\"Cache-Control\", \"no-cache\");\n }\n }\n\n if (options.contentType && (method === \"POST\" || method === \"PUT\")) {\n xhr.setRequestHeader(\"Content-Type\", options.contentType);\n }\n\n qq.extend(allHeaders, qq.isFunction(customHeaders) ? customHeaders(id) : customHeaders);\n qq.extend(allHeaders, onDemandHeaders);\n\n qq.each(allHeaders, function(name, val) {\n xhr.setRequestHeader(name, val);\n });\n }\n }\n\n function isResponseSuccessful(responseCode) {\n return qq.indexOf(options.successfulResponseCodes[options.method], responseCode) >= 0;\n }\n\n function prepareToSend(id, optXhr, addToPath, additionalParams, additionalQueryParams, additionalHeaders, payload) {\n requestData[id] = {\n addToPath: addToPath,\n additionalParams: additionalParams,\n additionalQueryParams: additionalQueryParams,\n additionalHeaders: additionalHeaders,\n payload: payload\n };\n\n var len = queue.push(id);\n\n // if too many active connections, wait...\n if (len <= options.maxConnections) {\n return sendRequest(id, optXhr);\n }\n }\n\n shouldParamsBeInQueryString = options.method === \"GET\" || options.method === \"DELETE\";\n\n qq.extend(this, {\n // Start the process of sending the request. The ID refers to the file associated with the request.\n initTransport: function(id) {\n var path, params, headers, payload, cacheBuster, additionalQueryParams;\n\n return {\n // Optionally specify the end of the endpoint path for the request.\n withPath: function(appendToPath) {\n path = appendToPath;\n return this;\n },\n\n // Optionally specify additional parameters to send along with the request.\n // These will be added to the query string for GET/DELETE requests or the payload\n // for POST/PUT requests. The Content-Type of the request will be used to determine\n // how these parameters should be formatted as well.\n withParams: function(additionalParams) {\n params = additionalParams;\n return this;\n },\n\n withQueryParams: function(_additionalQueryParams_) {\n additionalQueryParams = _additionalQueryParams_;\n return this;\n },\n\n // Optionally specify additional headers to send along with the request.\n withHeaders: function(additionalHeaders) {\n headers = additionalHeaders;\n return this;\n },\n\n // Optionally specify a payload/body for the request.\n withPayload: function(thePayload) {\n payload = thePayload;\n return this;\n },\n\n // Appends a cache buster (timestamp) to the request URL as a query parameter (only if GET or DELETE)\n withCacheBuster: function() {\n cacheBuster = true;\n return this;\n },\n\n // Send the constructed request.\n send: function(optXhr) {\n if (cacheBuster && qq.indexOf([\"GET\", \"DELETE\"], options.method) >= 0) {\n params.qqtimestamp = new Date().getTime();\n }\n\n return prepareToSend(id, optXhr, path, params, additionalQueryParams, headers, payload);\n }\n };\n },\n\n canceled: function(id) {\n dequeue(id);\n }\n });\n};\n","/* globals qq */\n/**\n * Common upload handler functions.\n *\n * @constructor\n */\nqq.UploadHandler = function(spec) {\n \"use strict\";\n\n var proxy = spec.proxy,\n fileState = {},\n onCancel = proxy.onCancel,\n getName = proxy.getName;\n\n qq.extend(this, {\n add: function(id, fileItem) {\n fileState[id] = fileItem;\n fileState[id].temp = {};\n },\n\n cancel: function(id) {\n var self = this,\n cancelFinalizationEffort = new qq.Promise(),\n onCancelRetVal = onCancel(id, getName(id), cancelFinalizationEffort);\n\n onCancelRetVal.then(function() {\n if (self.isValid(id)) {\n fileState[id].canceled = true;\n self.expunge(id);\n }\n cancelFinalizationEffort.success();\n });\n },\n\n expunge: function(id) {\n delete fileState[id];\n },\n\n getThirdPartyFileId: function(id) {\n return fileState[id].key;\n },\n\n isValid: function(id) {\n return fileState[id] !== undefined;\n },\n\n reset: function() {\n fileState = {};\n },\n\n _getFileState: function(id) {\n return fileState[id];\n },\n\n _setThirdPartyFileId: function(id, thirdPartyFileId) {\n fileState[id].key = thirdPartyFileId;\n },\n\n _wasCanceled: function(id) {\n return !!fileState[id].canceled;\n }\n });\n};\n","/*globals qq*/\n/**\n * Base upload handler module. Controls more specific handlers.\n *\n * @param o Options. Passed along to the specific handler submodule as well.\n * @param namespace [optional] Namespace for the specific handler.\n */\nqq.UploadHandlerController = function(o, namespace) {\n \"use strict\";\n\n var controller = this,\n chunkingPossible = false,\n concurrentChunkingPossible = false,\n chunking, preventRetryResponse, log, handler,\n\n options = {\n paramsStore: {},\n maxConnections: 3, // maximum number of concurrent uploads\n chunking: {\n enabled: false,\n multiple: {\n enabled: false\n }\n },\n log: function(str, level) {},\n onProgress: function(id, fileName, loaded, total) {},\n onComplete: function(id, fileName, response, xhr) {},\n onCancel: function(id, fileName) {},\n onUploadPrep: function(id) {}, // Called if non-trivial operations will be performed before onUpload\n onUpload: function(id, fileName) {},\n onUploadChunk: function(id, fileName, chunkData) {},\n onUploadChunkSuccess: function(id, chunkData, response, xhr) {},\n onAutoRetry: function(id, fileName, response, xhr) {},\n onResume: function(id, fileName, chunkData) {},\n onUuidChanged: function(id, newUuid) {},\n getName: function(id) {},\n setSize: function(id, newSize) {},\n isQueued: function(id) {},\n getIdsInProxyGroup: function(id) {},\n getIdsInBatch: function(id) {}\n },\n\n chunked = {\n // Called when each chunk has uploaded successfully\n done: function(id, chunkIdx, response, xhr) {\n var chunkData = handler._getChunkData(id, chunkIdx);\n\n handler._getFileState(id).attemptingResume = false;\n\n delete handler._getFileState(id).temp.chunkProgress[chunkIdx];\n handler._getFileState(id).loaded += chunkData.size;\n\n options.onUploadChunkSuccess(id, handler._getChunkDataForCallback(chunkData), response, xhr);\n },\n\n // Called when all chunks have been successfully uploaded and we want to ask the handler to perform any\n // logic associated with closing out the file, such as combining the chunks.\n finalize: function(id) {\n var size = options.getSize(id),\n name = options.getName(id);\n\n log(\"All chunks have been uploaded for \" + id + \" - finalizing....\");\n handler.finalizeChunks(id).then(\n function(response, xhr) {\n log(\"Finalize successful for \" + id);\n\n var normaizedResponse = upload.normalizeResponse(response, true);\n\n options.onProgress(id, name, size, size);\n handler._maybeDeletePersistedChunkData(id);\n upload.cleanup(id, normaizedResponse, xhr);\n },\n function(response, xhr) {\n var normaizedResponse = upload.normalizeResponse(response, false);\n\n log(\"Problem finalizing chunks for file ID \" + id + \" - \" + normaizedResponse.error, \"error\");\n\n if (normaizedResponse.reset) {\n chunked.reset(id);\n }\n\n if (!options.onAutoRetry(id, name, normaizedResponse, xhr)) {\n upload.cleanup(id, normaizedResponse, xhr);\n }\n }\n );\n },\n\n handleFailure: function(chunkIdx, id, response, xhr) {\n var name = options.getName(id);\n\n log(\"Chunked upload request failed for \" + id + \", chunk \" + chunkIdx);\n\n handler.clearCachedChunk(id, chunkIdx);\n\n var responseToReport = upload.normalizeResponse(response, false),\n inProgressIdx;\n\n if (responseToReport.reset) {\n chunked.reset(id);\n }\n else {\n inProgressIdx = qq.indexOf(handler._getFileState(id).chunking.inProgress, chunkIdx);\n if (inProgressIdx >= 0) {\n handler._getFileState(id).chunking.inProgress.splice(inProgressIdx, 1);\n handler._getFileState(id).chunking.remaining.unshift(chunkIdx);\n }\n }\n\n // We may have aborted all other in-progress chunks for this file due to a failure.\n // If so, ignore the failures associated with those aborts.\n if (!handler._getFileState(id).temp.ignoreFailure) {\n // If this chunk has failed, we want to ignore all other failures of currently in-progress\n // chunks since they will be explicitly aborted\n if (concurrentChunkingPossible) {\n handler._getFileState(id).temp.ignoreFailure = true;\n\n log(qq.format(\"Going to attempt to abort these chunks: {}. These are currently in-progress: {}.\", JSON.stringify(Object.keys(handler._getXhrs(id))), JSON.stringify(handler._getFileState(id).chunking.inProgress)));\n qq.each(handler._getXhrs(id), function(ckid, ckXhr) {\n log(qq.format(\"Attempting to abort file {}.{}. XHR readyState {}. \", id, ckid, ckXhr.readyState));\n ckXhr.abort();\n // Flag the transport, in case we are waiting for some other async operation\n // to complete before attempting to upload the chunk\n ckXhr._cancelled = true;\n });\n\n // We must indicate that all aborted chunks are no longer in progress\n handler.moveInProgressToRemaining(id);\n\n // Free up any connections used by these chunks, but don't allow any\n // other files to take up the connections (until we have exhausted all auto-retries)\n connectionManager.free(id, true);\n }\n\n if (!options.onAutoRetry(id, name, responseToReport, xhr)) {\n // If one chunk fails, abort all of the others to avoid odd race conditions that occur\n // if a chunk succeeds immediately after one fails before we have determined if the upload\n // is a failure or not.\n upload.cleanup(id, responseToReport, xhr);\n }\n }\n },\n\n hasMoreParts: function(id) {\n return !!handler._getFileState(id).chunking.remaining.length;\n },\n\n nextPart: function(id) {\n var nextIdx = handler._getFileState(id).chunking.remaining.shift();\n\n if (nextIdx >= handler._getTotalChunks(id)) {\n nextIdx = null;\n }\n\n return nextIdx;\n },\n\n reset: function(id) {\n log(\"Server or callback has ordered chunking effort to be restarted on next attempt for item ID \" + id, \"error\");\n\n handler._maybeDeletePersistedChunkData(id);\n handler.reevaluateChunking(id);\n handler._getFileState(id).loaded = 0;\n },\n\n sendNext: function(id) {\n var size = options.getSize(id),\n name = options.getName(id),\n chunkIdx = chunked.nextPart(id),\n chunkData = handler._getChunkData(id, chunkIdx),\n resuming = handler._getFileState(id).attemptingResume,\n inProgressChunks = handler._getFileState(id).chunking.inProgress || [];\n\n if (handler._getFileState(id).loaded == null) {\n handler._getFileState(id).loaded = 0;\n }\n\n // Don't follow-through with the resume attempt if the integrator returns false from onResume\n if (resuming && options.onResume(id, name, chunkData) === false) {\n chunked.reset(id);\n chunkIdx = chunked.nextPart(id);\n chunkData = handler._getChunkData(id, chunkIdx);\n resuming = false;\n }\n\n // If all chunks have already uploaded successfully, we must be re-attempting the finalize step.\n if (chunkIdx == null && inProgressChunks.length === 0) {\n chunked.finalize(id);\n }\n\n // Send the next chunk\n else {\n log(qq.format(\"Sending chunked upload request for item {}.{}, bytes {}-{} of {}.\", id, chunkIdx, chunkData.start + 1, chunkData.end, size));\n options.onUploadChunk(id, name, handler._getChunkDataForCallback(chunkData));\n inProgressChunks.push(chunkIdx);\n handler._getFileState(id).chunking.inProgress = inProgressChunks;\n\n if (concurrentChunkingPossible) {\n connectionManager.open(id, chunkIdx);\n }\n\n if (concurrentChunkingPossible && connectionManager.available() && handler._getFileState(id).chunking.remaining.length) {\n chunked.sendNext(id);\n }\n\n if (chunkData.blob.size === 0) {\n log(qq.format(\"Chunk {} for file {} will not be uploaded, zero sized chunk.\", chunkIdx, id), \"error\");\n chunked.handleFailure(chunkIdx, id, \"File is no longer available\", null);\n }\n else {\n handler.uploadChunk(id, chunkIdx, resuming).then(\n // upload chunk success\n function success(response, xhr) {\n log(\"Chunked upload request succeeded for \" + id + \", chunk \" + chunkIdx);\n\n handler.clearCachedChunk(id, chunkIdx);\n\n var inProgressChunks = handler._getFileState(id).chunking.inProgress || [],\n responseToReport = upload.normalizeResponse(response, true),\n inProgressChunkIdx = qq.indexOf(inProgressChunks, chunkIdx);\n\n log(qq.format(\"Chunk {} for file {} uploaded successfully.\", chunkIdx, id));\n\n chunked.done(id, chunkIdx, responseToReport, xhr);\n\n if (inProgressChunkIdx >= 0) {\n inProgressChunks.splice(inProgressChunkIdx, 1);\n }\n\n handler._maybePersistChunkedState(id);\n\n if (!chunked.hasMoreParts(id) && inProgressChunks.length === 0) {\n chunked.finalize(id);\n }\n else if (chunked.hasMoreParts(id)) {\n chunked.sendNext(id);\n }\n else {\n log(qq.format(\"File ID {} has no more chunks to send and these chunk indexes are still marked as in-progress: {}\", id, JSON.stringify(inProgressChunks)));\n }\n },\n\n // upload chunk failure\n function failure(response, xhr) {\n chunked.handleFailure(chunkIdx, id, response, xhr);\n }\n )\n .done(function() {\n handler.clearXhr(id, chunkIdx);\n });\n }\n }\n }\n },\n\n connectionManager = {\n _open: [],\n _openChunks: {},\n _waiting: [],\n\n available: function() {\n var max = options.maxConnections,\n openChunkEntriesCount = 0,\n openChunksCount = 0;\n\n qq.each(connectionManager._openChunks, function(fileId, openChunkIndexes) {\n openChunkEntriesCount++;\n openChunksCount += openChunkIndexes.length;\n });\n\n return max - (connectionManager._open.length - openChunkEntriesCount + openChunksCount);\n },\n\n /**\n * Removes element from queue, starts upload of next\n */\n free: function(id, dontAllowNext) {\n var allowNext = !dontAllowNext,\n waitingIndex = qq.indexOf(connectionManager._waiting, id),\n connectionsIndex = qq.indexOf(connectionManager._open, id),\n nextId;\n\n delete connectionManager._openChunks[id];\n\n if (upload.getProxyOrBlob(id) instanceof qq.BlobProxy) {\n log(\"Generated blob upload has ended for \" + id + \", disposing generated blob.\");\n delete handler._getFileState(id).file;\n }\n\n // If this file was not consuming a connection, it was just waiting, so remove it from the waiting array\n if (waitingIndex >= 0) {\n connectionManager._waiting.splice(waitingIndex, 1);\n }\n // If this file was consuming a connection, allow the next file to be uploaded\n else if (allowNext && connectionsIndex >= 0) {\n connectionManager._open.splice(connectionsIndex, 1);\n\n nextId = connectionManager._waiting.shift();\n if (nextId >= 0) {\n connectionManager._open.push(nextId);\n upload.start(nextId);\n }\n }\n },\n\n getWaitingOrConnected: function() {\n var waitingOrConnected = [];\n\n // Chunked files may have multiple connections open per chunk (if concurrent chunking is enabled)\n // We need to grab the file ID of any file that has at least one chunk consuming a connection.\n qq.each(connectionManager._openChunks, function(fileId, chunks) {\n if (chunks && chunks.length) {\n waitingOrConnected.push(parseInt(fileId));\n }\n });\n\n // For non-chunked files, only one connection will be consumed per file.\n // This is where we aggregate those file IDs.\n qq.each(connectionManager._open, function(idx, fileId) {\n if (!connectionManager._openChunks[fileId]) {\n waitingOrConnected.push(parseInt(fileId));\n }\n });\n\n // There may be files waiting for a connection.\n waitingOrConnected = waitingOrConnected.concat(connectionManager._waiting);\n\n return waitingOrConnected;\n },\n\n isUsingConnection: function(id) {\n return qq.indexOf(connectionManager._open, id) >= 0;\n },\n\n open: function(id, chunkIdx) {\n if (chunkIdx == null) {\n connectionManager._waiting.push(id);\n }\n\n if (connectionManager.available()) {\n if (chunkIdx == null) {\n connectionManager._waiting.pop();\n connectionManager._open.push(id);\n }\n else {\n (function() {\n var openChunksEntry = connectionManager._openChunks[id] || [];\n openChunksEntry.push(chunkIdx);\n connectionManager._openChunks[id] = openChunksEntry;\n }());\n }\n\n return true;\n }\n\n return false;\n },\n\n reset: function() {\n connectionManager._waiting = [];\n connectionManager._open = [];\n }\n },\n\n simple = {\n send: function(id, name) {\n handler._getFileState(id).loaded = 0;\n\n log(\"Sending simple upload request for \" + id);\n handler.uploadFile(id).then(\n function(response, optXhr) {\n log(\"Simple upload request succeeded for \" + id);\n\n var responseToReport = upload.normalizeResponse(response, true),\n size = options.getSize(id);\n\n options.onProgress(id, name, size, size);\n upload.maybeNewUuid(id, responseToReport);\n upload.cleanup(id, responseToReport, optXhr);\n },\n\n function(response, optXhr) {\n log(\"Simple upload request failed for \" + id);\n\n var responseToReport = upload.normalizeResponse(response, false);\n\n if (!options.onAutoRetry(id, name, responseToReport, optXhr)) {\n upload.cleanup(id, responseToReport, optXhr);\n }\n }\n );\n }\n },\n\n upload = {\n cancel: function(id) {\n log(\"Cancelling \" + id);\n options.paramsStore.remove(id);\n connectionManager.free(id);\n },\n\n cleanup: function(id, response, optXhr) {\n var name = options.getName(id);\n\n options.onComplete(id, name, response, optXhr);\n\n if (handler._getFileState(id)) {\n handler._clearXhrs && handler._clearXhrs(id);\n }\n\n connectionManager.free(id);\n },\n\n // Returns a qq.BlobProxy, or an actual File/Blob if no proxy is involved, or undefined\n // if none of these are available for the ID\n getProxyOrBlob: function(id) {\n return (handler.getProxy && handler.getProxy(id)) ||\n (handler.getFile && handler.getFile(id));\n },\n\n initHandler: function() {\n var handlerType = namespace ? qq[namespace] : qq.traditional,\n handlerModuleSubtype = qq.supportedFeatures.ajaxUploading ? \"Xhr\" : \"Form\";\n\n handler = new handlerType[handlerModuleSubtype + \"UploadHandler\"](\n options,\n {\n getDataByUuid: options.getDataByUuid,\n getName: options.getName,\n getSize: options.getSize,\n getUuid: options.getUuid,\n log: log,\n onCancel: options.onCancel,\n onProgress: options.onProgress,\n onUuidChanged: options.onUuidChanged\n }\n );\n\n if (handler._removeExpiredChunkingRecords) {\n handler._removeExpiredChunkingRecords();\n }\n },\n\n isDeferredEligibleForUpload: function(id) {\n return options.isQueued(id);\n },\n\n // For Blobs that are part of a group of generated images, along with a reference image,\n // this will ensure the blobs in the group are uploaded in the order they were triggered,\n // even if some async processing must be completed on one or more Blobs first.\n maybeDefer: function(id, blob) {\n // If we don't have a file/blob yet & no file/blob exists for this item, request it,\n // and then submit the upload to the specific handler once the blob is available.\n // ASSUMPTION: This condition will only ever be true if XHR uploading is supported.\n if (blob && !handler.getFile(id) && blob instanceof qq.BlobProxy) {\n\n // Blob creation may take some time, so the caller may want to update the\n // UI to indicate that an operation is in progress, even before the actual\n // upload begins and an onUpload callback is invoked.\n options.onUploadPrep(id);\n\n log(\"Attempting to generate a blob on-demand for \" + id);\n blob.create().then(function(generatedBlob) {\n log(\"Generated an on-demand blob for \" + id);\n\n // Update record associated with this file by providing the generated Blob\n handler.updateBlob(id, generatedBlob);\n\n // Propagate the size for this generated Blob\n options.setSize(id, generatedBlob.size);\n\n // Order handler to recalculate chunking possibility, if applicable\n handler.reevaluateChunking(id);\n\n upload.maybeSendDeferredFiles(id);\n },\n\n // Blob could not be generated. Fail the upload & attempt to prevent retries. Also bubble error message.\n function(errorMessage) {\n var errorResponse = {};\n\n if (errorMessage) {\n errorResponse.error = errorMessage;\n }\n\n log(qq.format(\"Failed to generate blob for ID {}. Error message: {}.\", id, errorMessage), \"error\");\n\n options.onComplete(id, options.getName(id), qq.extend(errorResponse, preventRetryResponse), null);\n upload.maybeSendDeferredFiles(id);\n connectionManager.free(id);\n });\n }\n else {\n return upload.maybeSendDeferredFiles(id);\n }\n\n return false;\n },\n\n // Upload any grouped blobs, in the proper order, that are ready to be uploaded\n maybeSendDeferredFiles: function(id) {\n var idsInGroup = options.getIdsInProxyGroup(id),\n uploadedThisId = false;\n\n if (idsInGroup && idsInGroup.length) {\n log(\"Maybe ready to upload proxy group file \" + id);\n\n qq.each(idsInGroup, function(idx, idInGroup) {\n if (upload.isDeferredEligibleForUpload(idInGroup) && !!handler.getFile(idInGroup)) {\n uploadedThisId = idInGroup === id;\n upload.now(idInGroup);\n }\n else if (upload.isDeferredEligibleForUpload(idInGroup)) {\n return false;\n }\n });\n }\n else {\n uploadedThisId = true;\n upload.now(id);\n }\n\n return uploadedThisId;\n },\n\n maybeNewUuid: function(id, response) {\n if (response.newUuid !== undefined) {\n options.onUuidChanged(id, response.newUuid);\n }\n },\n\n // The response coming from handler implementations may be in various formats.\n // Instead of hoping a promise nested 5 levels deep will always return an object\n // as its first param, let's just normalize the response here.\n normalizeResponse: function(originalResponse, successful) {\n var response = originalResponse;\n\n // The passed \"response\" param may not be a response at all.\n // It could be a string, detailing the error, for example.\n if (!qq.isObject(originalResponse)) {\n response = {};\n\n if (qq.isString(originalResponse) && !successful) {\n response.error = originalResponse;\n }\n }\n\n response.success = successful;\n\n return response;\n },\n\n now: function(id) {\n var name = options.getName(id);\n\n if (!controller.isValid(id)) {\n throw new qq.Error(id + \" is not a valid file ID to upload!\");\n }\n\n options.onUpload(id, name);\n\n if (chunkingPossible && handler._shouldChunkThisFile(id)) {\n chunked.sendNext(id);\n }\n else {\n simple.send(id, name);\n }\n },\n\n start: function(id) {\n var blobToUpload = upload.getProxyOrBlob(id);\n\n if (blobToUpload) {\n return upload.maybeDefer(id, blobToUpload);\n }\n else {\n upload.now(id);\n return true;\n }\n }\n };\n\n qq.extend(this, {\n /**\n * Adds file or file input to the queue\n **/\n add: function(id, file) {\n handler.add.apply(this, arguments);\n },\n\n /**\n * Sends the file identified by id\n */\n upload: function(id) {\n if (connectionManager.open(id)) {\n return upload.start(id);\n }\n return false;\n },\n\n retry: function(id) {\n // On retry, if concurrent chunking has been enabled, we may have aborted all other in-progress chunks\n // for a file when encountering a failed chunk upload. We then signaled the controller to ignore\n // all failures associated with these aborts. We are now retrying, so we don't want to ignore\n // any more failures at this point.\n if (concurrentChunkingPossible) {\n handler._getFileState(id).temp.ignoreFailure = false;\n }\n\n // If we are attempting to retry a file that is already consuming a connection, this is likely an auto-retry.\n // Just go ahead and ask the handler to upload again.\n if (connectionManager.isUsingConnection(id)) {\n return upload.start(id);\n }\n\n // If we are attempting to retry a file that is not currently consuming a connection,\n // this is likely a manual retry attempt. We will need to ensure a connection is available\n // before the retry commences.\n else {\n return controller.upload(id);\n }\n },\n\n /**\n * Cancels file upload by id\n */\n cancel: function(id) {\n var cancelRetVal = handler.cancel(id);\n\n if (qq.isGenericPromise(cancelRetVal)) {\n cancelRetVal.then(function() {\n upload.cancel(id);\n });\n }\n else if (cancelRetVal !== false) {\n upload.cancel(id);\n }\n },\n\n /**\n * Cancels all queued or in-progress uploads\n */\n cancelAll: function() {\n var waitingOrConnected = connectionManager.getWaitingOrConnected(),\n i;\n\n // ensure files are cancelled in reverse order which they were added\n // to avoid a flash of time where a queued file begins to upload before it is canceled\n if (waitingOrConnected.length) {\n for (i = waitingOrConnected.length - 1; i >= 0; i--) {\n controller.cancel(waitingOrConnected[i]);\n }\n }\n\n connectionManager.reset();\n },\n\n // Returns a File, Blob, or the Blob/File for the reference/parent file if the targeted blob is a proxy.\n // Undefined if no file record is available.\n getFile: function(id) {\n if (handler.getProxy && handler.getProxy(id)) {\n return handler.getProxy(id).referenceBlob;\n }\n\n return handler.getFile && handler.getFile(id);\n },\n\n // Returns true if the Blob associated with the ID is related to a proxy s\n isProxied: function(id) {\n return !!(handler.getProxy && handler.getProxy(id));\n },\n\n getInput: function(id) {\n if (handler.getInput) {\n return handler.getInput(id);\n }\n },\n\n reset: function() {\n log(\"Resetting upload handler\");\n controller.cancelAll();\n connectionManager.reset();\n handler.reset();\n },\n\n expunge: function(id) {\n if (controller.isValid(id)) {\n return handler.expunge(id);\n }\n },\n\n /**\n * Determine if the file exists.\n */\n isValid: function(id) {\n return handler.isValid(id);\n },\n\n getResumableFilesData: function() {\n if (handler.getResumableFilesData) {\n return handler.getResumableFilesData();\n }\n return [];\n },\n\n /**\n * This may or may not be implemented, depending on the handler. For handlers where a third-party ID is\n * available (such as the \"key\" for Amazon S3), this will return that value. Otherwise, the return value\n * will be undefined.\n *\n * @param id Internal file ID\n * @returns {*} Some identifier used by a 3rd-party service involved in the upload process\n */\n getThirdPartyFileId: function(id) {\n if (controller.isValid(id)) {\n return handler.getThirdPartyFileId(id);\n }\n },\n\n /**\n * Attempts to pause the associated upload if the specific handler supports this and the file is \"valid\".\n * @param id ID of the upload/file to pause\n * @returns {boolean} true if the upload was paused\n */\n pause: function(id) {\n if (controller.isResumable(id) && handler.pause && controller.isValid(id) && handler.pause(id)) {\n connectionManager.free(id);\n handler.moveInProgressToRemaining(id);\n return true;\n }\n return false;\n },\n\n // True if the file is eligible for pause/resume.\n isResumable: function(id) {\n return !!handler.isResumable && handler.isResumable(id);\n }\n });\n\n qq.extend(options, o);\n log = options.log;\n chunkingPossible = options.chunking.enabled && qq.supportedFeatures.chunking;\n concurrentChunkingPossible = chunkingPossible && options.chunking.concurrent.enabled;\n\n preventRetryResponse = (function() {\n var response = {};\n\n response[options.preventRetryParam] = true;\n\n return response;\n }());\n\n upload.initHandler();\n};\n","/*globals qq */\n/*jshint -W117 */\nqq.WindowReceiveMessage = function(o) {\n \"use strict\";\n\n var options = {\n log: function(message, level) {}\n },\n callbackWrapperDetachers = {};\n\n qq.extend(options, o);\n\n qq.extend(this, {\n receiveMessage: function(id, callback) {\n var onMessageCallbackWrapper = function(event) {\n callback(event.data);\n };\n\n if (window.postMessage) {\n callbackWrapperDetachers[id] = qq(window).attach(\"message\", onMessageCallbackWrapper);\n }\n else {\n log(\"iframe message passing not supported in this browser!\", \"error\");\n }\n },\n\n stopReceivingMessages: function(id) {\n if (window.postMessage) {\n var detacher = callbackWrapperDetachers[id];\n if (detacher) {\n detacher();\n }\n }\n }\n });\n};\n","/* globals qq */\n/**\n * Common APIs exposed to creators of upload via form/iframe handlers. This is reused and possibly overridden\n * in some cases by specific form upload handlers.\n *\n * @constructor\n */\nqq.FormUploadHandler = function(spec) {\n \"use strict\";\n\n var options = spec.options,\n handler = this,\n proxy = spec.proxy,\n formHandlerInstanceId = qq.getUniqueId(),\n onloadCallbacks = {},\n detachLoadEvents = {},\n postMessageCallbackTimers = {},\n isCors = options.isCors,\n inputName = options.inputName,\n getUuid = proxy.getUuid,\n log = proxy.log,\n corsMessageReceiver = new qq.WindowReceiveMessage({log: log});\n\n /**\n * Remove any trace of the file from the handler.\n *\n * @param id ID of the associated file\n */\n function expungeFile(id) {\n delete detachLoadEvents[id];\n\n // If we are dealing with CORS, we might still be waiting for a response from a loaded iframe.\n // In that case, terminate the timer waiting for a message from the loaded iframe\n // and stop listening for any more messages coming from this iframe.\n if (isCors) {\n clearTimeout(postMessageCallbackTimers[id]);\n delete postMessageCallbackTimers[id];\n corsMessageReceiver.stopReceivingMessages(id);\n }\n\n var iframe = document.getElementById(handler._getIframeName(id));\n if (iframe) {\n // To cancel request set src to something else. We use src=\"javascript:false;\"\n // because it doesn't trigger ie6 prompt on https\n /* jshint scripturl:true */\n iframe.setAttribute(\"src\", \"javascript:false;\");\n\n qq(iframe).remove();\n }\n }\n\n /**\n * @param iframeName `document`-unique Name of the associated iframe\n * @returns {*} ID of the associated file\n */\n function getFileIdForIframeName(iframeName) {\n return iframeName.split(\"_\")[0];\n }\n\n /**\n * Generates an iframe to be used as a target for upload-related form submits. This also adds the iframe\n * to the current `document`. Note that the iframe is hidden from view.\n *\n * @param name Name of the iframe.\n * @returns {HTMLIFrameElement} The created iframe\n */\n function initIframeForUpload(name) {\n var iframe = qq.toElement(\"\");\n\n iframe.setAttribute(\"id\", name);\n\n iframe.style.display = \"none\";\n document.body.appendChild(iframe);\n\n return iframe;\n }\n\n /**\n * If we are in CORS mode, we must listen for messages (containing the server response) from the associated\n * iframe, since we cannot directly parse the content of the iframe due to cross-origin restrictions.\n *\n * @param iframe Listen for messages on this iframe.\n * @param callback Invoke this callback with the message from the iframe.\n */\n function registerPostMessageCallback(iframe, callback) {\n var iframeName = iframe.id,\n fileId = getFileIdForIframeName(iframeName),\n uuid = getUuid(fileId);\n\n onloadCallbacks[uuid] = callback;\n\n // When the iframe has loaded (after the server responds to an upload request)\n // declare the attempt a failure if we don't receive a valid message shortly after the response comes in.\n detachLoadEvents[fileId] = qq(iframe).attach(\"load\", function() {\n if (handler.getInput(fileId)) {\n log(\"Received iframe load event for CORS upload request (iframe name \" + iframeName + \")\");\n\n postMessageCallbackTimers[iframeName] = setTimeout(function() {\n var errorMessage = \"No valid message received from loaded iframe for iframe name \" + iframeName;\n log(errorMessage, \"error\");\n callback({\n error: errorMessage\n });\n }, 1000);\n }\n });\n\n // Listen for messages coming from this iframe. When a message has been received, cancel the timer\n // that declares the upload a failure if a message is not received within a reasonable amount of time.\n corsMessageReceiver.receiveMessage(iframeName, function(message) {\n log(\"Received the following window message: '\" + message + \"'\");\n var fileId = getFileIdForIframeName(iframeName),\n response = handler._parseJsonResponse(message),\n uuid = response.uuid,\n onloadCallback;\n\n if (uuid && onloadCallbacks[uuid]) {\n log(\"Handling response for iframe name \" + iframeName);\n clearTimeout(postMessageCallbackTimers[iframeName]);\n delete postMessageCallbackTimers[iframeName];\n\n handler._detachLoadEvent(iframeName);\n\n onloadCallback = onloadCallbacks[uuid];\n\n delete onloadCallbacks[uuid];\n corsMessageReceiver.stopReceivingMessages(iframeName);\n onloadCallback(response);\n }\n else if (!uuid) {\n log(\"'\" + message + \"' does not contain a UUID - ignoring.\");\n }\n });\n }\n\n qq.extend(this, new qq.UploadHandler(spec));\n\n qq.override(this, function(super_) {\n return {\n /**\n * Adds File or Blob to the queue\n **/\n add: function(id, fileInput) {\n super_.add(id, {input: fileInput});\n\n fileInput.setAttribute(\"name\", inputName);\n\n // remove file input from DOM\n if (fileInput.parentNode) {\n qq(fileInput).remove();\n }\n },\n\n expunge: function(id) {\n expungeFile(id);\n super_.expunge(id);\n },\n\n isValid: function(id) {\n return super_.isValid(id) &&\n handler._getFileState(id).input !== undefined;\n }\n };\n });\n\n qq.extend(this, {\n getInput: function(id) {\n return handler._getFileState(id).input;\n },\n\n /**\n * This function either delegates to a more specific message handler if CORS is involved,\n * or simply registers a callback when the iframe has been loaded that invokes the passed callback\n * after determining if the content of the iframe is accessible.\n *\n * @param iframe Associated iframe\n * @param callback Callback to invoke after we have determined if the iframe content is accessible.\n */\n _attachLoadEvent: function(iframe, callback) {\n /*jslint eqeq: true*/\n var responseDescriptor;\n\n if (isCors) {\n registerPostMessageCallback(iframe, callback);\n }\n else {\n detachLoadEvents[iframe.id] = qq(iframe).attach(\"load\", function() {\n log(\"Received response for \" + iframe.id);\n\n // when we remove iframe from dom\n // the request stops, but in IE load\n // event fires\n if (!iframe.parentNode) {\n return;\n }\n\n try {\n // fixing Opera 10.53\n if (iframe.contentDocument &&\n iframe.contentDocument.body &&\n iframe.contentDocument.body.innerHTML == \"false\") {\n // In Opera event is fired second time\n // when body.innerHTML changed from false\n // to server response approx. after 1 sec\n // when we upload file with iframe\n return;\n }\n }\n catch (error) {\n //IE may throw an \"access is denied\" error when attempting to access contentDocument on the iframe in some cases\n log(\"Error when attempting to access iframe during handling of upload response (\" + error.message + \")\", \"error\");\n responseDescriptor = {success: false};\n }\n\n callback(responseDescriptor);\n });\n }\n },\n\n /**\n * Creates an iframe with a specific document-unique name.\n *\n * @param id ID of the associated file\n * @returns {HTMLIFrameElement}\n */\n _createIframe: function(id) {\n var iframeName = handler._getIframeName(id);\n\n return initIframeForUpload(iframeName);\n },\n\n /**\n * Called when we are no longer interested in being notified when an iframe has loaded.\n *\n * @param id Associated file ID\n */\n _detachLoadEvent: function(id) {\n if (detachLoadEvents[id] !== undefined) {\n detachLoadEvents[id]();\n delete detachLoadEvents[id];\n }\n },\n\n /**\n * @param fileId ID of the associated file\n * @returns {string} The `document`-unique name of the iframe\n */\n _getIframeName: function(fileId) {\n return fileId + \"_\" + formHandlerInstanceId;\n },\n\n /**\n * Generates a form element and appends it to the `document`. When the form is submitted, a specific iframe is targeted.\n * The name of the iframe is passed in as a property of the spec parameter, and must be unique in the `document`. Note\n * that the form is hidden from view.\n *\n * @param spec An object containing various properties to be used when constructing the form. Required properties are\n * currently: `method`, `endpoint`, `params`, `paramsInBody`, and `targetName`.\n * @returns {HTMLFormElement} The created form\n */\n _initFormForUpload: function(spec) {\n var method = spec.method,\n endpoint = spec.endpoint,\n params = spec.params,\n paramsInBody = spec.paramsInBody,\n targetName = spec.targetName,\n form = qq.toElement(\" \"),\n url = endpoint;\n\n if (paramsInBody) {\n qq.obj2Inputs(params, form);\n }\n else {\n url = qq.obj2url(params, endpoint);\n }\n\n form.setAttribute(\"action\", url);\n form.setAttribute(\"target\", targetName);\n form.style.display = \"none\";\n document.body.appendChild(form);\n\n return form;\n },\n\n /**\n * @param innerHtmlOrMessage JSON message\n * @returns {*} The parsed response, or an empty object if the response could not be parsed\n */\n _parseJsonResponse: function(innerHtmlOrMessage) {\n var response = {};\n\n try {\n response = qq.parseJson(innerHtmlOrMessage);\n }\n catch (error) {\n log(\"Error when attempting to parse iframe upload response (\" + error.message + \")\", \"error\");\n }\n\n return response;\n }\n });\n};\n","/* globals qq */\n/**\n * Common API exposed to creators of XHR handlers. This is reused and possibly overriding in some cases by specific\n * XHR upload handlers.\n *\n * @constructor\n */\nqq.XhrUploadHandler = function(spec) {\n \"use strict\";\n\n var handler = this,\n namespace = spec.options.namespace,\n proxy = spec.proxy,\n chunking = spec.options.chunking,\n resume = spec.options.resume,\n chunkFiles = chunking && spec.options.chunking.enabled && qq.supportedFeatures.chunking,\n resumeEnabled = resume && spec.options.resume.enabled && chunkFiles && qq.supportedFeatures.resume,\n getName = proxy.getName,\n getSize = proxy.getSize,\n getUuid = proxy.getUuid,\n getEndpoint = proxy.getEndpoint,\n getDataByUuid = proxy.getDataByUuid,\n onUuidChanged = proxy.onUuidChanged,\n onProgress = proxy.onProgress,\n log = proxy.log;\n\n function abort(id) {\n qq.each(handler._getXhrs(id), function(xhrId, xhr) {\n var ajaxRequester = handler._getAjaxRequester(id, xhrId);\n\n xhr.onreadystatechange = null;\n xhr.upload.onprogress = null;\n xhr.abort();\n ajaxRequester && ajaxRequester.canceled && ajaxRequester.canceled(id);\n });\n }\n\n qq.extend(this, new qq.UploadHandler(spec));\n\n qq.override(this, function(super_) {\n return {\n /**\n * Adds File or Blob to the queue\n **/\n add: function(id, blobOrProxy) {\n if (qq.isFile(blobOrProxy) || qq.isBlob(blobOrProxy)) {\n super_.add(id, {file: blobOrProxy});\n }\n else if (blobOrProxy instanceof qq.BlobProxy) {\n super_.add(id, {proxy: blobOrProxy});\n }\n else {\n throw new Error(\"Passed obj is not a File, Blob, or proxy\");\n }\n\n handler._initTempState(id);\n resumeEnabled && handler._maybePrepareForResume(id);\n },\n\n expunge: function(id) {\n abort(id);\n handler._maybeDeletePersistedChunkData(id);\n handler._clearXhrs(id);\n super_.expunge(id);\n }\n };\n });\n\n qq.extend(this, {\n // Clear the cached chunk `Blob` after we are done with it, just in case the `Blob` bytes are stored in memory.\n clearCachedChunk: function(id, chunkIdx) {\n delete handler._getFileState(id).temp.cachedChunks[chunkIdx];\n },\n\n clearXhr: function(id, chunkIdx) {\n var tempState = handler._getFileState(id).temp;\n\n if (tempState.xhrs) {\n delete tempState.xhrs[chunkIdx];\n }\n if (tempState.ajaxRequesters) {\n delete tempState.ajaxRequesters[chunkIdx];\n }\n },\n\n // Called when all chunks have been successfully uploaded. Expected promissory return type.\n // This defines the default behavior if nothing further is required when all chunks have been uploaded.\n finalizeChunks: function(id, responseParser) {\n var lastChunkIdx = handler._getTotalChunks(id) - 1,\n xhr = handler._getXhr(id, lastChunkIdx);\n\n if (responseParser) {\n return new qq.Promise().success(responseParser(xhr), xhr);\n }\n\n return new qq.Promise().success({}, xhr);\n },\n\n getFile: function(id) {\n return handler.isValid(id) && handler._getFileState(id).file;\n },\n\n getProxy: function(id) {\n return handler.isValid(id) && handler._getFileState(id).proxy;\n },\n\n /**\n * @returns {Array} Array of objects containing properties useful to integrators\n * when it is important to determine which files are potentially resumable.\n */\n getResumableFilesData: function() {\n var resumableFilesData = [];\n\n handler._iterateResumeRecords(function(key, uploadData) {\n handler.moveInProgressToRemaining(null, uploadData.chunking.inProgress, uploadData.chunking.remaining);\n\n var data = {\n name: uploadData.name,\n remaining: uploadData.chunking.remaining,\n size: uploadData.size,\n uuid: uploadData.uuid\n };\n\n if (uploadData.key) {\n data.key = uploadData.key;\n }\n\n resumableFilesData.push(data);\n });\n\n return resumableFilesData;\n },\n\n isResumable: function(id) {\n return !!chunking && handler.isValid(id) && !handler._getFileState(id).notResumable;\n },\n\n moveInProgressToRemaining: function(id, optInProgress, optRemaining) {\n var inProgress = optInProgress || handler._getFileState(id).chunking.inProgress,\n remaining = optRemaining || handler._getFileState(id).chunking.remaining;\n\n if (inProgress) {\n log(qq.format(\"Moving these chunks from in-progress {}, to remaining.\", JSON.stringify(inProgress)));\n inProgress.reverse();\n qq.each(inProgress, function(idx, chunkIdx) {\n remaining.unshift(chunkIdx);\n });\n inProgress.length = 0;\n }\n },\n\n pause: function(id) {\n if (handler.isValid(id)) {\n log(qq.format(\"Aborting XHR upload for {} '{}' due to pause instruction.\", id, getName(id)));\n handler._getFileState(id).paused = true;\n abort(id);\n return true;\n }\n },\n\n reevaluateChunking: function(id) {\n if (chunking && handler.isValid(id)) {\n var state = handler._getFileState(id),\n totalChunks,\n i;\n\n delete state.chunking;\n\n state.chunking = {};\n totalChunks = handler._getTotalChunks(id);\n if (totalChunks > 1 || chunking.mandatory) {\n state.chunking.enabled = true;\n state.chunking.parts = totalChunks;\n state.chunking.remaining = [];\n\n for (i = 0; i < totalChunks; i++) {\n state.chunking.remaining.push(i);\n }\n\n handler._initTempState(id);\n }\n else {\n state.chunking.enabled = false;\n }\n }\n },\n\n updateBlob: function(id, newBlob) {\n if (handler.isValid(id)) {\n handler._getFileState(id).file = newBlob;\n }\n },\n\n _clearXhrs: function(id) {\n var tempState = handler._getFileState(id).temp;\n\n qq.each(tempState.ajaxRequesters, function(chunkId) {\n delete tempState.ajaxRequesters[chunkId];\n });\n\n qq.each(tempState.xhrs, function(chunkId) {\n delete tempState.xhrs[chunkId];\n });\n },\n\n /**\n * Creates an XHR instance for this file and stores it in the fileState.\n *\n * @param id File ID\n * @param optChunkIdx The chunk index associated with this XHR, if applicable\n * @returns {XMLHttpRequest}\n */\n _createXhr: function(id, optChunkIdx) {\n return handler._registerXhr(id, optChunkIdx, qq.createXhrInstance());\n },\n\n _getAjaxRequester: function(id, optChunkIdx) {\n var chunkIdx = optChunkIdx == null ? -1 : optChunkIdx;\n return handler._getFileState(id).temp.ajaxRequesters[chunkIdx];\n },\n\n _getChunkData: function(id, chunkIndex) {\n var chunkSize = chunking.partSize,\n fileSize = getSize(id),\n fileOrBlob = handler.getFile(id),\n startBytes = chunkSize * chunkIndex,\n endBytes = startBytes + chunkSize >= fileSize ? fileSize : startBytes + chunkSize,\n totalChunks = handler._getTotalChunks(id),\n cachedChunks = this._getFileState(id).temp.cachedChunks,\n\n // To work around a Webkit GC bug, we must keep each chunk `Blob` in scope until we are done with it.\n // See https://github.com/Widen/fine-uploader/issues/937#issuecomment-41418760\n blob = cachedChunks[chunkIndex] || qq.sliceBlob(fileOrBlob, startBytes, endBytes);\n\n cachedChunks[chunkIndex] = blob;\n\n return {\n part: chunkIndex,\n start: startBytes,\n end: endBytes,\n count: totalChunks,\n blob: blob,\n size: endBytes - startBytes\n };\n },\n\n _getChunkDataForCallback: function(chunkData) {\n return {\n partIndex: chunkData.part,\n startByte: chunkData.start + 1,\n endByte: chunkData.end,\n totalParts: chunkData.count\n };\n },\n\n /**\n * @param id File ID\n * @returns {string} Identifier for this item that may appear in the browser's local storage\n */\n _getLocalStorageId: function(id) {\n var formatVersion = \"5.0\",\n name = getName(id),\n size = getSize(id),\n chunkSize = chunking.partSize,\n endpoint = getEndpoint(id);\n\n return qq.format(\"qq{}resume{}-{}-{}-{}-{}\", namespace, formatVersion, name, size, chunkSize, endpoint);\n },\n\n _getMimeType: function(id) {\n return handler.getFile(id).type;\n },\n\n _getPersistableData: function(id) {\n return handler._getFileState(id).chunking;\n },\n\n /**\n * @param id ID of the associated file\n * @returns {number} Number of parts this file can be divided into, or undefined if chunking is not supported in this UA\n */\n _getTotalChunks: function(id) {\n if (chunking) {\n var fileSize = getSize(id),\n chunkSize = chunking.partSize;\n\n return Math.ceil(fileSize / chunkSize);\n }\n },\n\n _getXhr: function(id, optChunkIdx) {\n var chunkIdx = optChunkIdx == null ? -1 : optChunkIdx;\n return handler._getFileState(id).temp.xhrs[chunkIdx];\n },\n\n _getXhrs: function(id) {\n return handler._getFileState(id).temp.xhrs;\n },\n\n // Iterates through all XHR handler-created resume records (in local storage),\n // invoking the passed callback and passing in the key and value of each local storage record.\n _iterateResumeRecords: function(callback) {\n if (resumeEnabled) {\n qq.each(localStorage, function(key, item) {\n if (key.indexOf(qq.format(\"qq{}resume\", namespace)) === 0) {\n var uploadData = JSON.parse(item);\n callback(key, uploadData);\n }\n });\n }\n },\n\n _initTempState: function(id) {\n handler._getFileState(id).temp = {\n ajaxRequesters: {},\n chunkProgress: {},\n xhrs: {},\n cachedChunks: {}\n };\n },\n\n _markNotResumable: function(id) {\n handler._getFileState(id).notResumable = true;\n },\n\n // Removes a chunked upload record from local storage, if possible.\n // Returns true if the item was removed, false otherwise.\n _maybeDeletePersistedChunkData: function(id) {\n var localStorageId;\n\n if (resumeEnabled && handler.isResumable(id)) {\n localStorageId = handler._getLocalStorageId(id);\n\n if (localStorageId && localStorage.getItem(localStorageId)) {\n localStorage.removeItem(localStorageId);\n return true;\n }\n }\n\n return false;\n },\n\n // If this is a resumable upload, grab the relevant data from storage and items in memory that track this upload\n // so we can pick up from where we left off.\n _maybePrepareForResume: function(id) {\n var state = handler._getFileState(id),\n localStorageId, persistedData;\n\n // Resume is enabled and possible and this is the first time we've tried to upload this file in this session,\n // so prepare for a resume attempt.\n if (resumeEnabled && state.key === undefined) {\n localStorageId = handler._getLocalStorageId(id);\n persistedData = localStorage.getItem(localStorageId);\n\n // If we found this item in local storage, maybe we should resume it.\n if (persistedData) {\n persistedData = JSON.parse(persistedData);\n\n // If we found a resume record but we have already handled this file in this session,\n // don't try to resume it & ensure we don't persist future check data\n if (getDataByUuid(persistedData.uuid)) {\n handler._markNotResumable(id);\n }\n else {\n log(qq.format(\"Identified file with ID {} and name of {} as resumable.\", id, getName(id)));\n\n onUuidChanged(id, persistedData.uuid);\n\n state.key = persistedData.key;\n state.chunking = persistedData.chunking;\n state.loaded = persistedData.loaded;\n state.attemptingResume = true;\n\n handler.moveInProgressToRemaining(id);\n }\n }\n }\n },\n\n // Persist any data needed to resume this upload in a new session.\n _maybePersistChunkedState: function(id) {\n var state = handler._getFileState(id),\n localStorageId, persistedData;\n\n // If local storage isn't supported by the browser, or if resume isn't enabled or possible, give up\n if (resumeEnabled && handler.isResumable(id)) {\n localStorageId = handler._getLocalStorageId(id);\n\n persistedData = {\n name: getName(id),\n size: getSize(id),\n uuid: getUuid(id),\n key: state.key,\n chunking: state.chunking,\n loaded: state.loaded,\n lastUpdated: Date.now()\n };\n\n try {\n localStorage.setItem(localStorageId, JSON.stringify(persistedData));\n }\n catch (error) {\n log(qq.format(\"Unable to save resume data for '{}' due to error: '{}'.\", id, error.toString()), \"warn\");\n }\n }\n },\n\n _registerProgressHandler: function(id, chunkIdx, chunkSize) {\n var xhr = handler._getXhr(id, chunkIdx),\n name = getName(id),\n progressCalculator = {\n simple: function(loaded, total) {\n var fileSize = getSize(id);\n\n if (loaded === total) {\n onProgress(id, name, fileSize, fileSize);\n }\n else {\n onProgress(id, name, (loaded >= fileSize ? fileSize - 1 : loaded), fileSize);\n }\n },\n\n chunked: function(loaded, total) {\n var chunkProgress = handler._getFileState(id).temp.chunkProgress,\n totalSuccessfullyLoadedForFile = handler._getFileState(id).loaded,\n loadedForRequest = loaded,\n totalForRequest = total,\n totalFileSize = getSize(id),\n estActualChunkLoaded = loadedForRequest - (totalForRequest - chunkSize),\n totalLoadedForFile = totalSuccessfullyLoadedForFile;\n\n chunkProgress[chunkIdx] = estActualChunkLoaded;\n\n qq.each(chunkProgress, function(chunkIdx, chunkLoaded) {\n totalLoadedForFile += chunkLoaded;\n });\n\n onProgress(id, name, totalLoadedForFile, totalFileSize);\n }\n };\n\n xhr.upload.onprogress = function(e) {\n if (e.lengthComputable) {\n /* jshint eqnull: true */\n var type = chunkSize == null ? \"simple\" : \"chunked\";\n progressCalculator[type](e.loaded, e.total);\n }\n };\n },\n\n /**\n * Registers an XHR transport instance created elsewhere.\n *\n * @param id ID of the associated file\n * @param optChunkIdx The chunk index associated with this XHR, if applicable\n * @param xhr XMLHttpRequest object instance\n * @param optAjaxRequester `qq.AjaxRequester` associated with this request, if applicable.\n * @returns {XMLHttpRequest}\n */\n _registerXhr: function(id, optChunkIdx, xhr, optAjaxRequester) {\n var xhrsId = optChunkIdx == null ? -1 : optChunkIdx,\n tempState = handler._getFileState(id).temp;\n\n tempState.xhrs = tempState.xhrs || {};\n tempState.ajaxRequesters = tempState.ajaxRequesters || {};\n\n tempState.xhrs[xhrsId] = xhr;\n\n if (optAjaxRequester) {\n tempState.ajaxRequesters[xhrsId] = optAjaxRequester;\n }\n\n return xhr;\n },\n\n // Deletes any local storage records that are \"expired\".\n _removeExpiredChunkingRecords: function() {\n var expirationDays = resume.recordsExpireIn;\n\n handler._iterateResumeRecords(function(key, uploadData) {\n var expirationDate = new Date(uploadData.lastUpdated);\n\n // transform updated date into expiration date\n expirationDate.setDate(expirationDate.getDate() + expirationDays);\n\n if (expirationDate.getTime() <= Date.now()) {\n log(\"Removing expired resume record with key \" + key);\n localStorage.removeItem(key);\n }\n });\n },\n\n /**\n * Determine if the associated file should be chunked.\n *\n * @param id ID of the associated file\n * @returns {*} true if chunking is enabled, possible, and the file can be split into more than 1 part\n */\n _shouldChunkThisFile: function(id) {\n var state = handler._getFileState(id);\n\n if (!state.chunking) {\n handler.reevaluateChunking(id);\n }\n\n return state.chunking.enabled;\n }\n });\n};\n","/*globals qq, XMLHttpRequest*/\nqq.DeleteFileAjaxRequester = function(o) {\n \"use strict\";\n\n var requester,\n options = {\n method: \"DELETE\",\n uuidParamName: \"qquuid\",\n endpointStore: {},\n maxConnections: 3,\n customHeaders: function(id) {return {};},\n paramsStore: {},\n cors: {\n expected: false,\n sendCredentials: false\n },\n log: function(str, level) {},\n onDelete: function(id) {},\n onDeleteComplete: function(id, xhrOrXdr, isError) {}\n };\n\n qq.extend(options, o);\n\n function getMandatedParams() {\n if (options.method.toUpperCase() === \"POST\") {\n return {\n _method: \"DELETE\"\n };\n }\n\n return {};\n }\n\n requester = qq.extend(this, new qq.AjaxRequester({\n acceptHeader: \"application/json\",\n validMethods: [\"POST\", \"DELETE\"],\n method: options.method,\n endpointStore: options.endpointStore,\n paramsStore: options.paramsStore,\n mandatedParams: getMandatedParams(),\n maxConnections: options.maxConnections,\n customHeaders: function(id) {\n return options.customHeaders.get(id);\n },\n log: options.log,\n onSend: options.onDelete,\n onComplete: options.onDeleteComplete,\n cors: options.cors\n }));\n\n qq.extend(this, {\n sendDelete: function(id, uuid, additionalMandatedParams) {\n var additionalOptions = additionalMandatedParams || {};\n\n options.log(\"Submitting delete file request for \" + id);\n\n if (options.method === \"DELETE\") {\n requester.initTransport(id)\n .withPath(uuid)\n .withParams(additionalOptions)\n .send();\n }\n else {\n additionalOptions[options.uuidParamName] = uuid;\n requester.initTransport(id)\n .withParams(additionalOptions)\n .send();\n }\n }\n });\n};\n","/*global qq, define */\n/*jshint strict:false,bitwise:false,nonew:false,asi:true,-W064,-W116,-W089 */\n/**\n * Mega pixel image rendering library for iOS6+\n *\n * Fixes iOS6+'s image file rendering issue for large size image (over mega-pixel),\n * which causes unexpected subsampling when drawing it in canvas.\n * By using this library, you can safely render the image with proper stretching.\n *\n * Copyright (c) 2012 Shinichi Tomita \n * Released under the MIT license\n *\n * Heavily modified by Widen for Fine Uploader\n */\n(function() {\n\n /**\n * Detect subsampling in loaded image.\n * In iOS, larger images than 2M pixels may be subsampled in rendering.\n */\n function detectSubsampling(img) {\n var iw = img.naturalWidth,\n ih = img.naturalHeight,\n canvas = document.createElement(\"canvas\"),\n ctx;\n\n if (iw * ih > 1024 * 1024) { // subsampling may happen over megapixel image\n canvas.width = canvas.height = 1;\n ctx = canvas.getContext(\"2d\");\n ctx.drawImage(img, -iw + 1, 0);\n // subsampled image becomes half smaller in rendering size.\n // check alpha channel value to confirm image is covering edge pixel or not.\n // if alpha value is 0 image is not covering, hence subsampled.\n return ctx.getImageData(0, 0, 1, 1).data[3] === 0;\n } else {\n return false;\n }\n }\n\n /**\n * Detecting vertical squash in loaded image.\n * Fixes a bug which squash image vertically while drawing into canvas for some images.\n */\n function detectVerticalSquash(img, iw, ih) {\n var canvas = document.createElement(\"canvas\"),\n sy = 0,\n ey = ih,\n py = ih,\n ctx, data, alpha, ratio;\n\n canvas.width = 1;\n canvas.height = ih;\n ctx = canvas.getContext(\"2d\");\n ctx.drawImage(img, 0, 0);\n data = ctx.getImageData(0, 0, 1, ih).data;\n\n // search image edge pixel position in case it is squashed vertically.\n while (py > sy) {\n alpha = data[(py - 1) * 4 + 3];\n if (alpha === 0) {\n ey = py;\n } else {\n sy = py;\n }\n py = (ey + sy) >> 1;\n }\n\n ratio = (py / ih);\n return (ratio === 0) ? 1 : ratio;\n }\n\n /**\n * Rendering image element (with resizing) and get its data URL\n */\n function renderImageToDataURL(img, blob, options, doSquash) {\n var canvas = document.createElement(\"canvas\"),\n mime = options.mime || \"image/jpeg\",\n promise = new qq.Promise();\n\n renderImageToCanvas(img, blob, canvas, options, doSquash)\n .then(function() {\n promise.success(\n canvas.toDataURL(mime, options.quality || 0.8)\n );\n });\n\n return promise;\n }\n\n function maybeCalculateDownsampledDimensions(spec) {\n var maxPixels = 5241000; //iOS specific value\n\n if (!qq.ios()) {\n throw new qq.Error(\"Downsampled dimensions can only be reliably calculated for iOS!\");\n }\n\n if (spec.origHeight * spec.origWidth > maxPixels) {\n return {\n newHeight: Math.round(Math.sqrt(maxPixels * (spec.origHeight / spec.origWidth))),\n newWidth: Math.round(Math.sqrt(maxPixels * (spec.origWidth / spec.origHeight)))\n };\n }\n }\n\n /**\n * Rendering image element (with resizing) into the canvas element\n */\n function renderImageToCanvas(img, blob, canvas, options, doSquash) {\n var iw = img.naturalWidth,\n ih = img.naturalHeight,\n width = options.width,\n height = options.height,\n ctx = canvas.getContext(\"2d\"),\n promise = new qq.Promise(),\n modifiedDimensions;\n\n ctx.save();\n\n if (options.resize) {\n return renderImageToCanvasWithCustomResizer({\n blob: blob,\n canvas: canvas,\n image: img,\n imageHeight: ih,\n imageWidth: iw,\n orientation: options.orientation,\n resize: options.resize,\n targetHeight: height,\n targetWidth: width\n });\n }\n\n if (!qq.supportedFeatures.unlimitedScaledImageSize) {\n modifiedDimensions = maybeCalculateDownsampledDimensions({\n origWidth: width,\n origHeight: height\n });\n\n if (modifiedDimensions) {\n qq.log(qq.format(\"Had to reduce dimensions due to device limitations from {}w / {}h to {}w / {}h\",\n width, height, modifiedDimensions.newWidth, modifiedDimensions.newHeight),\n \"warn\");\n\n width = modifiedDimensions.newWidth;\n height = modifiedDimensions.newHeight;\n }\n }\n\n transformCoordinate(canvas, width, height, options.orientation);\n\n // Fine Uploader specific: Save some CPU cycles if not using iOS\n // Assumption: This logic is only needed to overcome iOS image sampling issues\n if (qq.ios()) {\n (function() {\n if (detectSubsampling(img)) {\n iw /= 2;\n ih /= 2;\n }\n\n var d = 1024, // size of tiling canvas\n tmpCanvas = document.createElement(\"canvas\"),\n vertSquashRatio = doSquash ? detectVerticalSquash(img, iw, ih) : 1,\n dw = Math.ceil(d * width / iw),\n dh = Math.ceil(d * height / ih / vertSquashRatio),\n sy = 0,\n dy = 0,\n tmpCtx, sx, dx;\n\n tmpCanvas.width = tmpCanvas.height = d;\n tmpCtx = tmpCanvas.getContext(\"2d\");\n\n while (sy < ih) {\n sx = 0;\n dx = 0;\n while (sx < iw) {\n tmpCtx.clearRect(0, 0, d, d);\n tmpCtx.drawImage(img, -sx, -sy);\n ctx.drawImage(tmpCanvas, 0, 0, d, d, dx, dy, dw, dh);\n sx += d;\n dx += dw;\n }\n sy += d;\n dy += dh;\n }\n ctx.restore();\n tmpCanvas = tmpCtx = null;\n }());\n }\n else {\n ctx.drawImage(img, 0, 0, width, height);\n }\n\n canvas.qqImageRendered && canvas.qqImageRendered();\n promise.success();\n\n return promise;\n }\n\n function renderImageToCanvasWithCustomResizer(resizeInfo) {\n var blob = resizeInfo.blob,\n image = resizeInfo.image,\n imageHeight = resizeInfo.imageHeight,\n imageWidth = resizeInfo.imageWidth,\n orientation = resizeInfo.orientation,\n promise = new qq.Promise(),\n resize = resizeInfo.resize,\n sourceCanvas = document.createElement(\"canvas\"),\n sourceCanvasContext = sourceCanvas.getContext(\"2d\"),\n targetCanvas = resizeInfo.canvas,\n targetHeight = resizeInfo.targetHeight,\n targetWidth = resizeInfo.targetWidth;\n\n transformCoordinate(sourceCanvas, imageWidth, imageHeight, orientation);\n\n targetCanvas.height = targetHeight;\n targetCanvas.width = targetWidth;\n\n sourceCanvasContext.drawImage(image, 0, 0);\n\n resize({\n blob: blob,\n height: targetHeight,\n image: image,\n sourceCanvas: sourceCanvas,\n targetCanvas: targetCanvas,\n width: targetWidth\n })\n .then(\n function success() {\n targetCanvas.qqImageRendered && targetCanvas.qqImageRendered();\n promise.success();\n },\n promise.failure\n );\n\n return promise;\n }\n\n /**\n * Transform canvas coordination according to specified frame size and orientation\n * Orientation value is from EXIF tag\n */\n function transformCoordinate(canvas, width, height, orientation) {\n switch (orientation) {\n case 5:\n case 6:\n case 7:\n case 8:\n canvas.width = height;\n canvas.height = width;\n break;\n default:\n canvas.width = width;\n canvas.height = height;\n }\n var ctx = canvas.getContext(\"2d\");\n switch (orientation) {\n case 2:\n // horizontal flip\n ctx.translate(width, 0);\n ctx.scale(-1, 1);\n break;\n case 3:\n // 180 rotate left\n ctx.translate(width, height);\n ctx.rotate(Math.PI);\n break;\n case 4:\n // vertical flip\n ctx.translate(0, height);\n ctx.scale(1, -1);\n break;\n case 5:\n // vertical flip + 90 rotate right\n ctx.rotate(0.5 * Math.PI);\n ctx.scale(1, -1);\n break;\n case 6:\n // 90 rotate right\n ctx.rotate(0.5 * Math.PI);\n ctx.translate(0, -height);\n break;\n case 7:\n // horizontal flip + 90 rotate right\n ctx.rotate(0.5 * Math.PI);\n ctx.translate(width, -height);\n ctx.scale(-1, 1);\n break;\n case 8:\n // 90 rotate left\n ctx.rotate(-0.5 * Math.PI);\n ctx.translate(-width, 0);\n break;\n default:\n break;\n }\n }\n\n /**\n * MegaPixImage class\n */\n function MegaPixImage(srcImage, errorCallback) {\n var self = this;\n\n if (window.Blob && srcImage instanceof Blob) {\n (function() {\n var img = new Image(),\n URL = window.URL && window.URL.createObjectURL ? window.URL :\n window.webkitURL && window.webkitURL.createObjectURL ? window.webkitURL : null;\n if (!URL) { throw Error(\"No createObjectURL function found to create blob url\"); }\n img.src = URL.createObjectURL(srcImage);\n self.blob = srcImage;\n srcImage = img;\n }());\n }\n if (!srcImage.naturalWidth && !srcImage.naturalHeight) {\n srcImage.onload = function() {\n var listeners = self.imageLoadListeners;\n if (listeners) {\n self.imageLoadListeners = null;\n // IE11 doesn't reliably report actual image dimensions immediately after onload for small files,\n // so let's push this to the end of the UI thread queue.\n setTimeout(function() {\n for (var i = 0, len = listeners.length; i < len; i++) {\n listeners[i]();\n }\n }, 0);\n }\n };\n srcImage.onerror = errorCallback;\n this.imageLoadListeners = [];\n }\n this.srcImage = srcImage;\n }\n\n /**\n * Rendering megapix image into specified target element\n */\n MegaPixImage.prototype.render = function(target, options) {\n options = options || {};\n\n var self = this,\n imgWidth = this.srcImage.naturalWidth,\n imgHeight = this.srcImage.naturalHeight,\n width = options.width,\n height = options.height,\n maxWidth = options.maxWidth,\n maxHeight = options.maxHeight,\n doSquash = !this.blob || this.blob.type === \"image/jpeg\",\n tagName = target.tagName.toLowerCase(),\n opt;\n\n if (this.imageLoadListeners) {\n this.imageLoadListeners.push(function() { self.render(target, options); });\n return;\n }\n\n if (width && !height) {\n height = (imgHeight * width / imgWidth) << 0;\n } else if (height && !width) {\n width = (imgWidth * height / imgHeight) << 0;\n } else {\n width = imgWidth;\n height = imgHeight;\n }\n if (maxWidth && width > maxWidth) {\n width = maxWidth;\n height = (imgHeight * width / imgWidth) << 0;\n }\n if (maxHeight && height > maxHeight) {\n height = maxHeight;\n width = (imgWidth * height / imgHeight) << 0;\n }\n\n opt = { width: width, height: height },\n qq.each(options, function(optionsKey, optionsValue) {\n opt[optionsKey] = optionsValue;\n });\n\n if (tagName === \"img\") {\n (function() {\n var oldTargetSrc = target.src;\n renderImageToDataURL(self.srcImage, self.blob, opt, doSquash)\n .then(function(dataUri) {\n target.src = dataUri;\n oldTargetSrc === target.src && target.onload();\n });\n }());\n } else if (tagName === \"canvas\") {\n renderImageToCanvas(this.srcImage, this.blob, target, opt, doSquash);\n }\n if (typeof this.onrender === \"function\") {\n this.onrender(target);\n }\n };\n\n qq.MegaPixImage = MegaPixImage;\n})();\n","/*globals qq */\n/**\n * Draws a thumbnail of a Blob/File/URL onto an or .\n *\n * @constructor\n */\nqq.ImageGenerator = function(log) {\n \"use strict\";\n\n function isImg(el) {\n return el.tagName.toLowerCase() === \"img\";\n }\n\n function isCanvas(el) {\n return el.tagName.toLowerCase() === \"canvas\";\n }\n\n function isImgCorsSupported() {\n return new Image().crossOrigin !== undefined;\n }\n\n function isCanvasSupported() {\n var canvas = document.createElement(\"canvas\");\n\n return canvas.getContext && canvas.getContext(\"2d\");\n }\n\n // This is only meant to determine the MIME type of a renderable image file.\n // It is used to ensure images drawn from a URL that have transparent backgrounds\n // are rendered correctly, among other things.\n function determineMimeOfFileName(nameWithPath) {\n /*jshint -W015 */\n var pathSegments = nameWithPath.split(\"/\"),\n name = pathSegments[pathSegments.length - 1].split(\"?\")[0],\n extension = qq.getExtension(name);\n\n extension = extension && extension.toLowerCase();\n\n switch (extension) {\n case \"jpeg\":\n case \"jpg\":\n return \"image/jpeg\";\n case \"png\":\n return \"image/png\";\n case \"bmp\":\n return \"image/bmp\";\n case \"gif\":\n return \"image/gif\";\n case \"tiff\":\n case \"tif\":\n return \"image/tiff\";\n }\n }\n\n // This will likely not work correctly in IE8 and older.\n // It's only used as part of a formula to determine\n // if a canvas can be used to scale a server-hosted thumbnail.\n // If canvas isn't supported by the UA (IE8 and older)\n // this method should not even be called.\n function isCrossOrigin(url) {\n var targetAnchor = document.createElement(\"a\"),\n targetProtocol, targetHostname, targetPort;\n\n targetAnchor.href = url;\n\n targetProtocol = targetAnchor.protocol;\n targetPort = targetAnchor.port;\n targetHostname = targetAnchor.hostname;\n\n if (targetProtocol.toLowerCase() !== window.location.protocol.toLowerCase()) {\n return true;\n }\n\n if (targetHostname.toLowerCase() !== window.location.hostname.toLowerCase()) {\n return true;\n }\n\n // IE doesn't take ports into consideration when determining if two endpoints are same origin.\n if (targetPort !== window.location.port && !qq.ie()) {\n return true;\n }\n\n return false;\n }\n\n function registerImgLoadListeners(img, promise) {\n img.onload = function() {\n img.onload = null;\n img.onerror = null;\n promise.success(img);\n };\n\n img.onerror = function() {\n img.onload = null;\n img.onerror = null;\n log(\"Problem drawing thumbnail!\", \"error\");\n promise.failure(img, \"Problem drawing thumbnail!\");\n };\n }\n\n function registerCanvasDrawImageListener(canvas, promise) {\n // The image is drawn on the canvas by a third-party library,\n // and we want to know when this is completed. Since the library\n // may invoke drawImage many times in a loop, we need to be called\n // back when the image is fully rendered. So, we are expecting the\n // code that draws this image to follow a convention that involves a\n // function attached to the canvas instance be invoked when it is done.\n canvas.qqImageRendered = function() {\n promise.success(canvas);\n };\n }\n\n // Fulfills a `qq.Promise` when an image has been drawn onto the target,\n // whether that is a or an . The attempt is considered a\n // failure if the target is not an or a , or if the drawing\n // attempt was not successful.\n function registerThumbnailRenderedListener(imgOrCanvas, promise) {\n var registered = isImg(imgOrCanvas) || isCanvas(imgOrCanvas);\n\n if (isImg(imgOrCanvas)) {\n registerImgLoadListeners(imgOrCanvas, promise);\n }\n else if (isCanvas(imgOrCanvas)) {\n registerCanvasDrawImageListener(imgOrCanvas, promise);\n }\n else {\n promise.failure(imgOrCanvas);\n log(qq.format(\"Element container of type {} is not supported!\", imgOrCanvas.tagName), \"error\");\n }\n\n return registered;\n }\n\n // Draw a preview iff the current UA can natively display it.\n // Also rotate the image if necessary.\n function draw(fileOrBlob, container, options) {\n var drawPreview = new qq.Promise(),\n identifier = new qq.Identify(fileOrBlob, log),\n maxSize = options.maxSize,\n // jshint eqnull:true\n orient = options.orient == null ? true : options.orient,\n megapixErrorHandler = function() {\n container.onerror = null;\n container.onload = null;\n log(\"Could not render preview, file may be too large!\", \"error\");\n drawPreview.failure(container, \"Browser cannot render image!\");\n };\n\n identifier.isPreviewable().then(\n function(mime) {\n // If options explicitly specify that Orientation is not desired,\n // replace the orient task with a dummy promise that \"succeeds\" immediately.\n var dummyExif = {\n parse: function() {\n return new qq.Promise().success();\n }\n },\n exif = orient ? new qq.Exif(fileOrBlob, log) : dummyExif,\n mpImg = new qq.MegaPixImage(fileOrBlob, megapixErrorHandler);\n\n if (registerThumbnailRenderedListener(container, drawPreview)) {\n exif.parse().then(\n function(exif) {\n var orientation = exif && exif.Orientation;\n\n mpImg.render(container, {\n maxWidth: maxSize,\n maxHeight: maxSize,\n orientation: orientation,\n mime: mime,\n resize: options.customResizeFunction\n });\n },\n\n function(failureMsg) {\n log(qq.format(\"EXIF data could not be parsed ({}). Assuming orientation = 1.\", failureMsg));\n\n mpImg.render(container, {\n maxWidth: maxSize,\n maxHeight: maxSize,\n mime: mime,\n resize: options.customResizeFunction\n });\n }\n );\n }\n },\n\n function() {\n log(\"Not previewable\");\n drawPreview.failure(container, \"Not previewable\");\n }\n );\n\n return drawPreview;\n }\n\n function drawOnCanvasOrImgFromUrl(url, canvasOrImg, draw, maxSize, customResizeFunction) {\n var tempImg = new Image(),\n tempImgRender = new qq.Promise();\n\n registerThumbnailRenderedListener(tempImg, tempImgRender);\n\n if (isCrossOrigin(url)) {\n tempImg.crossOrigin = \"anonymous\";\n }\n\n tempImg.src = url;\n\n tempImgRender.then(\n function rendered() {\n registerThumbnailRenderedListener(canvasOrImg, draw);\n\n var mpImg = new qq.MegaPixImage(tempImg);\n mpImg.render(canvasOrImg, {\n maxWidth: maxSize,\n maxHeight: maxSize,\n mime: determineMimeOfFileName(url),\n resize: customResizeFunction\n });\n },\n\n draw.failure\n );\n }\n\n function drawOnImgFromUrlWithCssScaling(url, img, draw, maxSize) {\n registerThumbnailRenderedListener(img, draw);\n // NOTE: The fact that maxWidth/height is set on the thumbnail for scaled images\n // that must drop back to CSS is known and exploited by the templating module.\n // In this module, we pre-render \"waiting\" thumbs for all files immediately after they\n // are submitted, and we must be sure to pass any style associated with the \"waiting\" preview.\n qq(img).css({\n maxWidth: maxSize + \"px\",\n maxHeight: maxSize + \"px\"\n });\n\n img.src = url;\n }\n\n // Draw a (server-hosted) thumbnail given a URL.\n // This will optionally scale the thumbnail as well.\n // It attempts to use to scale, but will fall back\n // to max-width and max-height style properties if the UA\n // doesn't support canvas or if the images is cross-domain and\n // the UA doesn't support the crossorigin attribute on img tags,\n // which is required to scale a cross-origin image using &\n // then export it back to an .\n function drawFromUrl(url, container, options) {\n var draw = new qq.Promise(),\n scale = options.scale,\n maxSize = scale ? options.maxSize : null;\n\n // container is an img, scaling needed\n if (scale && isImg(container)) {\n // Iff canvas is available in this UA, try to use it for scaling.\n // Otherwise, fall back to CSS scaling\n if (isCanvasSupported()) {\n // Attempt to use for image scaling,\n // but we must fall back to scaling via CSS/styles\n // if this is a cross-origin image and the UA doesn't support CORS.\n if (isCrossOrigin(url) && !isImgCorsSupported()) {\n drawOnImgFromUrlWithCssScaling(url, container, draw, maxSize);\n }\n else {\n drawOnCanvasOrImgFromUrl(url, container, draw, maxSize);\n }\n }\n else {\n drawOnImgFromUrlWithCssScaling(url, container, draw, maxSize);\n }\n }\n // container is a canvas, scaling optional\n else if (isCanvas(container)) {\n drawOnCanvasOrImgFromUrl(url, container, draw, maxSize);\n }\n // container is an img & no scaling: just set the src attr to the passed url\n else if (registerThumbnailRenderedListener(container, draw)) {\n container.src = url;\n }\n\n return draw;\n }\n\n qq.extend(this, {\n /**\n * Generate a thumbnail. Depending on the arguments, this may either result in\n * a client-side rendering of an image (if a `Blob` is supplied) or a server-generated\n * image that may optionally be scaled client-side using or CSS/styles (as a fallback).\n *\n * @param fileBlobOrUrl a `File`, `Blob`, or a URL pointing to the image\n * @param container or to contain the preview\n * @param options possible properties include `maxSize` (int), `orient` (bool - default true), resize` (bool - default true), and `customResizeFunction`.\n * @returns qq.Promise fulfilled when the preview has been drawn, or the attempt has failed\n */\n generate: function(fileBlobOrUrl, container, options) {\n if (qq.isString(fileBlobOrUrl)) {\n log(\"Attempting to update thumbnail based on server response.\");\n return drawFromUrl(fileBlobOrUrl, container, options || {});\n }\n else {\n log(\"Attempting to draw client-side image preview.\");\n return draw(fileBlobOrUrl, container, options || {});\n }\n }\n });\n\n /**/\n this._testing = {};\n this._testing.isImg = isImg;\n this._testing.isCanvas = isCanvas;\n this._testing.isCrossOrigin = isCrossOrigin;\n this._testing.determineMimeOfFileName = determineMimeOfFileName;\n /* */\n};\n","/*globals qq */\n/**\n * EXIF image data parser. Currently only parses the Orientation tag value,\n * but this may be expanded to other tags in the future.\n *\n * @param fileOrBlob Attempt to parse EXIF data in this `Blob`\n * @constructor\n */\nqq.Exif = function(fileOrBlob, log) {\n \"use strict\";\n\n // Orientation is the only tag parsed here at this time.\n var TAG_IDS = [274],\n TAG_INFO = {\n 274: {\n name: \"Orientation\",\n bytes: 2\n }\n };\n\n // Convert a little endian (hex string) to big endian (decimal).\n function parseLittleEndian(hex) {\n var result = 0,\n pow = 0;\n\n while (hex.length > 0) {\n result += parseInt(hex.substring(0, 2), 16) * Math.pow(2, pow);\n hex = hex.substring(2, hex.length);\n pow += 8;\n }\n\n return result;\n }\n\n // Find the byte offset, of Application Segment 1 (EXIF).\n // External callers need not supply any arguments.\n function seekToApp1(offset, promise) {\n var theOffset = offset,\n thePromise = promise;\n if (theOffset === undefined) {\n theOffset = 2;\n thePromise = new qq.Promise();\n }\n\n qq.readBlobToHex(fileOrBlob, theOffset, 4).then(function(hex) {\n var match = /^ffe([0-9])/.exec(hex),\n segmentLength;\n\n if (match) {\n if (match[1] !== \"1\") {\n segmentLength = parseInt(hex.slice(4, 8), 16);\n seekToApp1(theOffset + segmentLength + 2, thePromise);\n }\n else {\n thePromise.success(theOffset);\n }\n }\n else {\n thePromise.failure(\"No EXIF header to be found!\");\n }\n });\n\n return thePromise;\n }\n\n // Find the byte offset of Application Segment 1 (EXIF) for valid JPEGs only.\n function getApp1Offset() {\n var promise = new qq.Promise();\n\n qq.readBlobToHex(fileOrBlob, 0, 6).then(function(hex) {\n if (hex.indexOf(\"ffd8\") !== 0) {\n promise.failure(\"Not a valid JPEG!\");\n }\n else {\n seekToApp1().then(function(offset) {\n promise.success(offset);\n },\n function(error) {\n promise.failure(error);\n });\n }\n });\n\n return promise;\n }\n\n // Determine the byte ordering of the EXIF header.\n function isLittleEndian(app1Start) {\n var promise = new qq.Promise();\n\n qq.readBlobToHex(fileOrBlob, app1Start + 10, 2).then(function(hex) {\n promise.success(hex === \"4949\");\n });\n\n return promise;\n }\n\n // Determine the number of directory entries in the EXIF header.\n function getDirEntryCount(app1Start, littleEndian) {\n var promise = new qq.Promise();\n\n qq.readBlobToHex(fileOrBlob, app1Start + 18, 2).then(function(hex) {\n if (littleEndian) {\n return promise.success(parseLittleEndian(hex));\n }\n else {\n promise.success(parseInt(hex, 16));\n }\n });\n\n return promise;\n }\n\n // Get the IFD portion of the EXIF header as a hex string.\n function getIfd(app1Start, dirEntries) {\n var offset = app1Start + 20,\n bytes = dirEntries * 12;\n\n return qq.readBlobToHex(fileOrBlob, offset, bytes);\n }\n\n // Obtain an array of all directory entries (as hex strings) in the EXIF header.\n function getDirEntries(ifdHex) {\n var entries = [],\n offset = 0;\n\n while (offset + 24 <= ifdHex.length) {\n entries.push(ifdHex.slice(offset, offset + 24));\n offset += 24;\n }\n\n return entries;\n }\n\n // Obtain values for all relevant tags and return them.\n function getTagValues(littleEndian, dirEntries) {\n var TAG_VAL_OFFSET = 16,\n tagsToFind = qq.extend([], TAG_IDS),\n vals = {};\n\n qq.each(dirEntries, function(idx, entry) {\n var idHex = entry.slice(0, 4),\n id = littleEndian ? parseLittleEndian(idHex) : parseInt(idHex, 16),\n tagsToFindIdx = tagsToFind.indexOf(id),\n tagValHex, tagName, tagValLength;\n\n if (tagsToFindIdx >= 0) {\n tagName = TAG_INFO[id].name;\n tagValLength = TAG_INFO[id].bytes;\n tagValHex = entry.slice(TAG_VAL_OFFSET, TAG_VAL_OFFSET + (tagValLength * 2));\n vals[tagName] = littleEndian ? parseLittleEndian(tagValHex) : parseInt(tagValHex, 16);\n\n tagsToFind.splice(tagsToFindIdx, 1);\n }\n\n if (tagsToFind.length === 0) {\n return false;\n }\n });\n\n return vals;\n }\n\n qq.extend(this, {\n /**\n * Attempt to parse the EXIF header for the `Blob` associated with this instance.\n *\n * @returns {qq.Promise} To be fulfilled when the parsing is complete.\n * If successful, the parsed EXIF header as an object will be included.\n */\n parse: function() {\n var parser = new qq.Promise(),\n onParseFailure = function(message) {\n log(qq.format(\"EXIF header parse failed: '{}' \", message));\n parser.failure(message);\n };\n\n getApp1Offset().then(function(app1Offset) {\n log(qq.format(\"Moving forward with EXIF header parsing for '{}'\", fileOrBlob.name === undefined ? \"blob\" : fileOrBlob.name));\n\n isLittleEndian(app1Offset).then(function(littleEndian) {\n\n log(qq.format(\"EXIF Byte order is {} endian\", littleEndian ? \"little\" : \"big\"));\n\n getDirEntryCount(app1Offset, littleEndian).then(function(dirEntryCount) {\n\n log(qq.format(\"Found {} APP1 directory entries\", dirEntryCount));\n\n getIfd(app1Offset, dirEntryCount).then(function(ifdHex) {\n var dirEntries = getDirEntries(ifdHex),\n tagValues = getTagValues(littleEndian, dirEntries);\n\n log(\"Successfully parsed some EXIF tags\");\n\n parser.success(tagValues);\n }, onParseFailure);\n }, onParseFailure);\n }, onParseFailure);\n }, onParseFailure);\n\n return parser;\n }\n });\n\n /**/\n this._testing = {};\n this._testing.parseLittleEndian = parseLittleEndian;\n /* */\n};\n","/*globals qq */\nqq.Identify = function(fileOrBlob, log) {\n \"use strict\";\n\n function isIdentifiable(magicBytes, questionableBytes) {\n var identifiable = false,\n magicBytesEntries = [].concat(magicBytes);\n\n qq.each(magicBytesEntries, function(idx, magicBytesArrayEntry) {\n if (questionableBytes.indexOf(magicBytesArrayEntry) === 0) {\n identifiable = true;\n return false;\n }\n });\n\n return identifiable;\n }\n\n qq.extend(this, {\n /**\n * Determines if a Blob can be displayed natively in the current browser. This is done by reading magic\n * bytes in the beginning of the file, so this is an asynchronous operation. Before we attempt to read the\n * file, we will examine the blob's type attribute to save CPU cycles.\n *\n * @returns {qq.Promise} Promise that is fulfilled when identification is complete.\n * If successful, the MIME string is passed to the success handler.\n */\n isPreviewable: function() {\n var self = this,\n identifier = new qq.Promise(),\n previewable = false,\n name = fileOrBlob.name === undefined ? \"blob\" : fileOrBlob.name;\n\n log(qq.format(\"Attempting to determine if {} can be rendered in this browser\", name));\n\n log(\"First pass: check type attribute of blob object.\");\n\n if (this.isPreviewableSync()) {\n log(\"Second pass: check for magic bytes in file header.\");\n\n qq.readBlobToHex(fileOrBlob, 0, 4).then(function(hex) {\n qq.each(self.PREVIEWABLE_MIME_TYPES, function(mime, bytes) {\n if (isIdentifiable(bytes, hex)) {\n // Safari is the only supported browser that can deal with TIFFs natively,\n // so, if this is a TIFF and the UA isn't Safari, declare this file \"non-previewable\".\n if (mime !== \"image/tiff\" || qq.supportedFeatures.tiffPreviews) {\n previewable = true;\n identifier.success(mime);\n }\n\n return false;\n }\n });\n\n log(qq.format(\"'{}' is {} able to be rendered in this browser\", name, previewable ? \"\" : \"NOT\"));\n\n if (!previewable) {\n identifier.failure();\n }\n },\n function() {\n log(\"Error reading file w/ name '\" + name + \"'. Not able to be rendered in this browser.\");\n identifier.failure();\n });\n }\n else {\n identifier.failure();\n }\n\n return identifier;\n },\n\n /**\n * Determines if a Blob can be displayed natively in the current browser. This is done by checking the\n * blob's type attribute. This is a synchronous operation, useful for situations where an asynchronous operation\n * would be challenging to support. Note that the blob's type property is not as accurate as reading the\n * file's magic bytes.\n *\n * @returns {Boolean} true if the blob can be rendered in the current browser\n */\n isPreviewableSync: function() {\n var fileMime = fileOrBlob.type,\n // Assumption: This will only ever be executed in browsers that support `Object.keys`.\n isRecognizedImage = qq.indexOf(Object.keys(this.PREVIEWABLE_MIME_TYPES), fileMime) >= 0,\n previewable = false,\n name = fileOrBlob.name === undefined ? \"blob\" : fileOrBlob.name;\n\n if (isRecognizedImage) {\n if (fileMime === \"image/tiff\") {\n previewable = qq.supportedFeatures.tiffPreviews;\n }\n else {\n previewable = true;\n }\n }\n\n !previewable && log(name + \" is not previewable in this browser per the blob's type attr\");\n\n return previewable;\n }\n });\n};\n\nqq.Identify.prototype.PREVIEWABLE_MIME_TYPES = {\n \"image/jpeg\": \"ffd8ff\",\n \"image/gif\": \"474946\",\n \"image/png\": \"89504e\",\n \"image/bmp\": \"424d\",\n \"image/tiff\": [\"49492a00\", \"4d4d002a\"]\n};\n","/*globals qq*/\n/**\n * Attempts to validate an image, wherever possible.\n *\n * @param blob File or Blob representing a user-selecting image.\n * @param log Uses this to post log messages to the console.\n * @constructor\n */\nqq.ImageValidation = function(blob, log) {\n \"use strict\";\n\n /**\n * @param limits Object with possible image-related limits to enforce.\n * @returns {boolean} true if at least one of the limits has a non-zero value\n */\n function hasNonZeroLimits(limits) {\n var atLeastOne = false;\n\n qq.each(limits, function(limit, value) {\n if (value > 0) {\n atLeastOne = true;\n return false;\n }\n });\n\n return atLeastOne;\n }\n\n /**\n * @returns {qq.Promise} The promise is a failure if we can't obtain the width & height.\n * Otherwise, `success` is called on the returned promise with an object containing\n * `width` and `height` properties.\n */\n function getWidthHeight() {\n var sizeDetermination = new qq.Promise();\n\n new qq.Identify(blob, log).isPreviewable().then(function() {\n var image = new Image(),\n url = window.URL && window.URL.createObjectURL ? window.URL :\n window.webkitURL && window.webkitURL.createObjectURL ? window.webkitURL :\n null;\n\n if (url) {\n image.onerror = function() {\n log(\"Cannot determine dimensions for image. May be too large.\", \"error\");\n sizeDetermination.failure();\n };\n\n image.onload = function() {\n sizeDetermination.success({\n width: this.width,\n height: this.height\n });\n };\n\n image.src = url.createObjectURL(blob);\n }\n else {\n log(\"No createObjectURL function available to generate image URL!\", \"error\");\n sizeDetermination.failure();\n }\n }, sizeDetermination.failure);\n\n return sizeDetermination;\n }\n\n /**\n *\n * @param limits Object with possible image-related limits to enforce.\n * @param dimensions Object containing `width` & `height` properties for the image to test.\n * @returns {String || undefined} The name of the failing limit. Undefined if no failing limits.\n */\n function getFailingLimit(limits, dimensions) {\n var failingLimit;\n\n qq.each(limits, function(limitName, limitValue) {\n if (limitValue > 0) {\n var limitMatcher = /(max|min)(Width|Height)/.exec(limitName),\n dimensionPropName = limitMatcher[2].charAt(0).toLowerCase() + limitMatcher[2].slice(1),\n actualValue = dimensions[dimensionPropName];\n\n /*jshint -W015*/\n switch (limitMatcher[1]) {\n case \"min\":\n if (actualValue < limitValue) {\n failingLimit = limitName;\n return false;\n }\n break;\n case \"max\":\n if (actualValue > limitValue) {\n failingLimit = limitName;\n return false;\n }\n break;\n }\n }\n });\n\n return failingLimit;\n }\n\n /**\n * Validate the associated blob.\n *\n * @param limits\n * @returns {qq.Promise} `success` is called on the promise is the image is valid or\n * if the blob is not an image, or if the image is not verifiable.\n * Otherwise, `failure` with the name of the failing limit.\n */\n this.validate = function(limits) {\n var validationEffort = new qq.Promise();\n\n log(\"Attempting to validate image.\");\n\n if (hasNonZeroLimits(limits)) {\n getWidthHeight().then(function(dimensions) {\n var failingLimit = getFailingLimit(limits, dimensions);\n\n if (failingLimit) {\n validationEffort.failure(failingLimit);\n }\n else {\n validationEffort.success();\n }\n }, validationEffort.success);\n }\n else {\n validationEffort.success();\n }\n\n return validationEffort;\n };\n};\n","/* globals qq */\n/**\n * Module used to control populating the initial list of files.\n *\n * @constructor\n */\nqq.Session = function(spec) {\n \"use strict\";\n\n var options = {\n endpoint: null,\n params: {},\n customHeaders: {},\n cors: {},\n addFileRecord: function(sessionData) {},\n log: function(message, level) {}\n };\n\n qq.extend(options, spec, true);\n\n function isJsonResponseValid(response) {\n if (qq.isArray(response)) {\n return true;\n }\n\n options.log(\"Session response is not an array.\", \"error\");\n }\n\n function handleFileItems(fileItems, success, xhrOrXdr, promise) {\n var someItemsIgnored = false;\n\n success = success && isJsonResponseValid(fileItems);\n\n if (success) {\n qq.each(fileItems, function(idx, fileItem) {\n /* jshint eqnull:true */\n if (fileItem.uuid == null) {\n someItemsIgnored = true;\n options.log(qq.format(\"Session response item {} did not include a valid UUID - ignoring.\", idx), \"error\");\n }\n else if (fileItem.name == null) {\n someItemsIgnored = true;\n options.log(qq.format(\"Session response item {} did not include a valid name - ignoring.\", idx), \"error\");\n }\n else {\n try {\n options.addFileRecord(fileItem);\n return true;\n }\n catch (err) {\n someItemsIgnored = true;\n options.log(err.message, \"error\");\n }\n }\n\n return false;\n });\n }\n\n promise[success && !someItemsIgnored ? \"success\" : \"failure\"](fileItems, xhrOrXdr);\n }\n\n // Initiate a call to the server that will be used to populate the initial file list.\n // Returns a `qq.Promise`.\n this.refresh = function() {\n /*jshint indent:false */\n var refreshEffort = new qq.Promise(),\n refreshCompleteCallback = function(response, success, xhrOrXdr) {\n handleFileItems(response, success, xhrOrXdr, refreshEffort);\n },\n requesterOptions = qq.extend({}, options),\n requester = new qq.SessionAjaxRequester(\n qq.extend(requesterOptions, {onComplete: refreshCompleteCallback})\n );\n\n requester.queryServer();\n\n return refreshEffort;\n };\n};\n","/*globals qq, XMLHttpRequest*/\n/**\n * Thin module used to send GET requests to the server, expecting information about session\n * data used to initialize an uploader instance.\n *\n * @param spec Various options used to influence the associated request.\n * @constructor\n */\nqq.SessionAjaxRequester = function(spec) {\n \"use strict\";\n\n var requester,\n options = {\n endpoint: null,\n customHeaders: {},\n params: {},\n cors: {\n expected: false,\n sendCredentials: false\n },\n onComplete: function(response, success, xhrOrXdr) {},\n log: function(str, level) {}\n };\n\n qq.extend(options, spec);\n\n function onComplete(id, xhrOrXdr, isError) {\n var response = null;\n\n /* jshint eqnull:true */\n if (xhrOrXdr.responseText != null) {\n try {\n response = qq.parseJson(xhrOrXdr.responseText);\n }\n catch (err) {\n options.log(\"Problem parsing session response: \" + err.message, \"error\");\n isError = true;\n }\n }\n\n options.onComplete(response, !isError, xhrOrXdr);\n }\n\n requester = qq.extend(this, new qq.AjaxRequester({\n acceptHeader: \"application/json\",\n validMethods: [\"GET\"],\n method: \"GET\",\n endpointStore: {\n get: function() {\n return options.endpoint;\n }\n },\n customHeaders: options.customHeaders,\n log: options.log,\n onComplete: onComplete,\n cors: options.cors\n }));\n\n qq.extend(this, {\n queryServer: function() {\n var params = qq.extend({}, options.params);\n\n options.log(\"Session query request.\");\n\n requester.initTransport(\"sessionRefresh\")\n .withParams(params)\n .withCacheBuster()\n .send();\n }\n });\n};\n","/* globals qq, ExifRestorer */\n/**\n * Controls generation of scaled images based on a reference image encapsulated in a `File` or `Blob`.\n * Scaled images are generated and converted to blobs on-demand.\n * Multiple scaled images per reference image with varying sizes and other properties are supported.\n *\n * @param spec Information about the scaled images to generate.\n * @param log Logger instance\n * @constructor\n */\nqq.Scaler = function(spec, log) {\n \"use strict\";\n\n var self = this,\n customResizeFunction = spec.customResizer,\n includeOriginal = spec.sendOriginal,\n orient = spec.orient,\n defaultType = spec.defaultType,\n defaultQuality = spec.defaultQuality / 100,\n failedToScaleText = spec.failureText,\n includeExif = spec.includeExif,\n sizes = this._getSortedSizes(spec.sizes);\n\n // Revealed API for instances of this module\n qq.extend(this, {\n // If no targeted sizes have been declared or if this browser doesn't support\n // client-side image preview generation, there is no scaling to do.\n enabled: qq.supportedFeatures.scaling && sizes.length > 0,\n\n getFileRecords: function(originalFileUuid, originalFileName, originalBlobOrBlobData) {\n var self = this,\n records = [],\n originalBlob = originalBlobOrBlobData.blob ? originalBlobOrBlobData.blob : originalBlobOrBlobData,\n identifier = new qq.Identify(originalBlob, log);\n\n // If the reference file cannot be rendered natively, we can't create scaled versions.\n if (identifier.isPreviewableSync()) {\n // Create records for each scaled version & add them to the records array, smallest first.\n qq.each(sizes, function(idx, sizeRecord) {\n var outputType = self._determineOutputType({\n defaultType: defaultType,\n requestedType: sizeRecord.type,\n refType: originalBlob.type\n });\n\n records.push({\n uuid: qq.getUniqueId(),\n name: self._getName(originalFileName, {\n name: sizeRecord.name,\n type: outputType,\n refType: originalBlob.type\n }),\n blob: new qq.BlobProxy(originalBlob,\n qq.bind(self._generateScaledImage, self, {\n customResizeFunction: customResizeFunction,\n maxSize: sizeRecord.maxSize,\n orient: orient,\n type: outputType,\n quality: defaultQuality,\n failedText: failedToScaleText,\n includeExif: includeExif,\n log: log\n }))\n });\n });\n\n records.push({\n uuid: originalFileUuid,\n name: originalFileName,\n size: originalBlob.size,\n blob: includeOriginal ? originalBlob : null\n });\n }\n else {\n records.push({\n uuid: originalFileUuid,\n name: originalFileName,\n size: originalBlob.size,\n blob: originalBlob\n });\n }\n\n return records;\n },\n\n handleNewFile: function(file, name, uuid, size, fileList, batchId, uuidParamName, api) {\n var self = this,\n buttonId = file.qqButtonId || (file.blob && file.blob.qqButtonId),\n scaledIds = [],\n originalId = null,\n addFileToHandler = api.addFileToHandler,\n uploadData = api.uploadData,\n paramsStore = api.paramsStore,\n proxyGroupId = qq.getUniqueId();\n\n qq.each(self.getFileRecords(uuid, name, file), function(idx, record) {\n var blobSize = record.size,\n id;\n\n if (record.blob instanceof qq.BlobProxy) {\n blobSize = -1;\n }\n\n id = uploadData.addFile({\n uuid: record.uuid,\n name: record.name,\n size: blobSize,\n batchId: batchId,\n proxyGroupId: proxyGroupId\n });\n\n if (record.blob instanceof qq.BlobProxy) {\n scaledIds.push(id);\n }\n else {\n originalId = id;\n }\n\n if (record.blob) {\n addFileToHandler(id, record.blob);\n fileList.push({id: id, file: record.blob});\n }\n else {\n uploadData.setStatus(id, qq.status.REJECTED);\n }\n });\n\n // If we are potentially uploading an original file and some scaled versions,\n // ensure the scaled versions include reference's to the parent's UUID and size\n // in their associated upload requests.\n if (originalId !== null) {\n qq.each(scaledIds, function(idx, scaledId) {\n var params = {\n qqparentuuid: uploadData.retrieve({id: originalId}).uuid,\n qqparentsize: uploadData.retrieve({id: originalId}).size\n };\n\n // Make sure the UUID for each scaled image is sent with the upload request,\n // to be consistent (since we may need to ensure it is sent for the original file as well).\n params[uuidParamName] = uploadData.retrieve({id: scaledId}).uuid;\n\n uploadData.setParentId(scaledId, originalId);\n paramsStore.addReadOnly(scaledId, params);\n });\n\n // If any scaled images are tied to this parent image, be SURE we send its UUID as an upload request\n // parameter as well.\n if (scaledIds.length) {\n (function() {\n var param = {};\n param[uuidParamName] = uploadData.retrieve({id: originalId}).uuid;\n paramsStore.addReadOnly(originalId, param);\n }());\n }\n }\n }\n });\n};\n\nqq.extend(qq.Scaler.prototype, {\n scaleImage: function(id, specs, api) {\n \"use strict\";\n\n if (!qq.supportedFeatures.scaling) {\n throw new qq.Error(\"Scaling is not supported in this browser!\");\n }\n\n var scalingEffort = new qq.Promise(),\n log = api.log,\n file = api.getFile(id),\n uploadData = api.uploadData.retrieve({id: id}),\n name = uploadData && uploadData.name,\n uuid = uploadData && uploadData.uuid,\n scalingOptions = {\n customResizer: specs.customResizer,\n sendOriginal: false,\n orient: specs.orient,\n defaultType: specs.type || null,\n defaultQuality: specs.quality,\n failedToScaleText: \"Unable to scale\",\n sizes: [{name: \"\", maxSize: specs.maxSize}]\n },\n scaler = new qq.Scaler(scalingOptions, log);\n\n if (!qq.Scaler || !qq.supportedFeatures.imagePreviews || !file) {\n scalingEffort.failure();\n\n log(\"Could not generate requested scaled image for \" + id + \". \" +\n \"Scaling is either not possible in this browser, or the file could not be located.\", \"error\");\n }\n else {\n (qq.bind(function() {\n // Assumption: There will never be more than one record\n var record = scaler.getFileRecords(uuid, name, file)[0];\n\n if (record && record.blob instanceof qq.BlobProxy) {\n record.blob.create().then(scalingEffort.success, scalingEffort.failure);\n }\n else {\n log(id + \" is not a scalable image!\", \"error\");\n scalingEffort.failure();\n }\n }, this)());\n }\n\n return scalingEffort;\n },\n\n // NOTE: We cannot reliably determine at this time if the UA supports a specific MIME type for the target format.\n // image/jpeg and image/png are the only safe choices at this time.\n _determineOutputType: function(spec) {\n \"use strict\";\n\n var requestedType = spec.requestedType,\n defaultType = spec.defaultType,\n referenceType = spec.refType;\n\n // If a default type and requested type have not been specified, this should be a\n // JPEG if the original type is a JPEG, otherwise, a PNG.\n if (!defaultType && !requestedType) {\n if (referenceType !== \"image/jpeg\") {\n return \"image/png\";\n }\n return referenceType;\n }\n\n // A specified default type is used when a requested type is not specified.\n if (!requestedType) {\n return defaultType;\n }\n\n // If requested type is specified, use it, as long as this recognized type is supported by the current UA\n if (qq.indexOf(Object.keys(qq.Identify.prototype.PREVIEWABLE_MIME_TYPES), requestedType) >= 0) {\n if (requestedType === \"image/tiff\") {\n return qq.supportedFeatures.tiffPreviews ? requestedType : defaultType;\n }\n\n return requestedType;\n }\n\n return defaultType;\n },\n\n // Get a file name for a generated scaled file record, based on the provided scaled image description\n _getName: function(originalName, scaledVersionProperties) {\n \"use strict\";\n\n var startOfExt = originalName.lastIndexOf(\".\"),\n versionType = scaledVersionProperties.type || \"image/png\",\n referenceType = scaledVersionProperties.refType,\n scaledName = \"\",\n scaledExt = qq.getExtension(originalName),\n nameAppendage = \"\";\n\n if (scaledVersionProperties.name && scaledVersionProperties.name.trim().length) {\n nameAppendage = \" (\" + scaledVersionProperties.name + \")\";\n }\n\n if (startOfExt >= 0) {\n scaledName = originalName.substr(0, startOfExt);\n\n if (referenceType !== versionType) {\n scaledExt = versionType.split(\"/\")[1];\n }\n\n scaledName += nameAppendage + \".\" + scaledExt;\n }\n else {\n scaledName = originalName + nameAppendage;\n }\n\n return scaledName;\n },\n\n // We want the smallest scaled file to be uploaded first\n _getSortedSizes: function(sizes) {\n \"use strict\";\n\n sizes = qq.extend([], sizes);\n\n return sizes.sort(function(a, b) {\n if (a.maxSize > b.maxSize) {\n return 1;\n }\n if (a.maxSize < b.maxSize) {\n return -1;\n }\n return 0;\n });\n },\n\n _generateScaledImage: function(spec, sourceFile) {\n \"use strict\";\n\n var self = this,\n customResizeFunction = spec.customResizeFunction,\n log = spec.log,\n maxSize = spec.maxSize,\n orient = spec.orient,\n type = spec.type,\n quality = spec.quality,\n failedText = spec.failedText,\n includeExif = spec.includeExif && sourceFile.type === \"image/jpeg\" && type === \"image/jpeg\",\n scalingEffort = new qq.Promise(),\n imageGenerator = new qq.ImageGenerator(log),\n canvas = document.createElement(\"canvas\");\n\n log(\"Attempting to generate scaled version for \" + sourceFile.name);\n\n imageGenerator.generate(sourceFile, canvas, {maxSize: maxSize, orient: orient, customResizeFunction: customResizeFunction}).then(function() {\n var scaledImageDataUri = canvas.toDataURL(type, quality),\n signalSuccess = function() {\n log(\"Success generating scaled version for \" + sourceFile.name);\n var blob = qq.dataUriToBlob(scaledImageDataUri);\n scalingEffort.success(blob);\n };\n\n if (includeExif) {\n self._insertExifHeader(sourceFile, scaledImageDataUri, log).then(function(scaledImageDataUriWithExif) {\n scaledImageDataUri = scaledImageDataUriWithExif;\n signalSuccess();\n },\n function() {\n log(\"Problem inserting EXIF header into scaled image. Using scaled image w/out EXIF data.\", \"error\");\n signalSuccess();\n });\n }\n else {\n signalSuccess();\n }\n }, function() {\n log(\"Failed attempt to generate scaled version for \" + sourceFile.name, \"error\");\n scalingEffort.failure(failedText);\n });\n\n return scalingEffort;\n },\n\n // Attempt to insert the original image's EXIF header into a scaled version.\n _insertExifHeader: function(originalImage, scaledImageDataUri, log) {\n \"use strict\";\n\n var reader = new FileReader(),\n insertionEffort = new qq.Promise(),\n originalImageDataUri = \"\";\n\n reader.onload = function() {\n originalImageDataUri = reader.result;\n insertionEffort.success(qq.ExifRestorer.restore(originalImageDataUri, scaledImageDataUri));\n };\n\n reader.onerror = function() {\n log(\"Problem reading \" + originalImage.name + \" during attempt to transfer EXIF data to scaled version.\", \"error\");\n insertionEffort.failure();\n };\n\n reader.readAsDataURL(originalImage);\n\n return insertionEffort;\n },\n\n _dataUriToBlob: function(dataUri) {\n \"use strict\";\n\n var byteString, mimeString, arrayBuffer, intArray;\n\n // convert base64 to raw binary data held in a string\n if (dataUri.split(\",\")[0].indexOf(\"base64\") >= 0) {\n byteString = atob(dataUri.split(\",\")[1]);\n }\n else {\n byteString = decodeURI(dataUri.split(\",\")[1]);\n }\n\n // extract the MIME\n mimeString = dataUri.split(\",\")[0]\n .split(\":\")[1]\n .split(\";\")[0];\n\n // write the bytes of the binary string to an ArrayBuffer\n arrayBuffer = new ArrayBuffer(byteString.length);\n intArray = new Uint8Array(arrayBuffer);\n qq.each(byteString, function(idx, character) {\n intArray[idx] = character.charCodeAt(0);\n });\n\n return this._createBlob(arrayBuffer, mimeString);\n },\n\n _createBlob: function(data, mime) {\n \"use strict\";\n\n var BlobBuilder = window.BlobBuilder ||\n window.WebKitBlobBuilder ||\n window.MozBlobBuilder ||\n window.MSBlobBuilder,\n blobBuilder = BlobBuilder && new BlobBuilder();\n\n if (blobBuilder) {\n blobBuilder.append(data);\n return blobBuilder.getBlob(mime);\n }\n else {\n return new Blob([data], {type: mime});\n }\n }\n});\n","//Based on MinifyJpeg\n//http://elicon.blog57.fc2.com/blog-entry-206.html\n\nqq.ExifRestorer = (function()\n{\n \n\tvar ExifRestorer = {};\n\t \n ExifRestorer.KEY_STR = \"ABCDEFGHIJKLMNOP\" +\n \"QRSTUVWXYZabcdef\" +\n \"ghijklmnopqrstuv\" +\n \"wxyz0123456789+/\" +\n \"=\";\n\n ExifRestorer.encode64 = function(input)\n {\n var output = \"\",\n chr1, chr2, chr3 = \"\",\n enc1, enc2, enc3, enc4 = \"\",\n i = 0;\n\n do {\n chr1 = input[i++];\n chr2 = input[i++];\n chr3 = input[i++];\n\n enc1 = chr1 >> 2;\n enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);\n enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);\n enc4 = chr3 & 63;\n\n if (isNaN(chr2)) {\n enc3 = enc4 = 64;\n } else if (isNaN(chr3)) {\n enc4 = 64;\n }\n\n output = output +\n this.KEY_STR.charAt(enc1) +\n this.KEY_STR.charAt(enc2) +\n this.KEY_STR.charAt(enc3) +\n this.KEY_STR.charAt(enc4);\n chr1 = chr2 = chr3 = \"\";\n enc1 = enc2 = enc3 = enc4 = \"\";\n } while (i < input.length);\n\n return output;\n };\n \n ExifRestorer.restore = function(origFileBase64, resizedFileBase64)\n {\n var expectedBase64Header = \"data:image/jpeg;base64,\";\n\n if (!origFileBase64.match(expectedBase64Header))\n {\n \treturn resizedFileBase64;\n } \n \n var rawImage = this.decode64(origFileBase64.replace(expectedBase64Header, \"\"));\n var segments = this.slice2Segments(rawImage);\n \n var image = this.exifManipulation(resizedFileBase64, segments);\n \n return expectedBase64Header + this.encode64(image);\n \n };\n\n\n ExifRestorer.exifManipulation = function(resizedFileBase64, segments)\n {\n var exifArray = this.getExifArray(segments),\n newImageArray = this.insertExif(resizedFileBase64, exifArray),\n aBuffer = new Uint8Array(newImageArray);\n\n return aBuffer;\n };\n\n\n ExifRestorer.getExifArray = function(segments)\n {\n var seg;\n for (var x = 0; x < segments.length; x++)\n {\n seg = segments[x];\n if (seg[0] == 255 & seg[1] == 225) //(ff e1)\n {\n return seg;\n }\n }\n return [];\n };\n\n\n ExifRestorer.insertExif = function(resizedFileBase64, exifArray)\n {\n var imageData = resizedFileBase64.replace(\"data:image/jpeg;base64,\", \"\"),\n buf = this.decode64(imageData),\n separatePoint = buf.indexOf(255,3),\n mae = buf.slice(0, separatePoint),\n ato = buf.slice(separatePoint),\n array = mae;\n\n array = array.concat(exifArray);\n array = array.concat(ato);\n return array;\n };\n\n\n \n ExifRestorer.slice2Segments = function(rawImageArray)\n {\n var head = 0,\n segments = [];\n\n while (1)\n {\n if (rawImageArray[head] == 255 & rawImageArray[head + 1] == 218){break;}\n if (rawImageArray[head] == 255 & rawImageArray[head + 1] == 216)\n {\n head += 2;\n }\n else\n {\n var length = rawImageArray[head + 2] * 256 + rawImageArray[head + 3],\n endPoint = head + length + 2,\n seg = rawImageArray.slice(head, endPoint);\n segments.push(seg);\n head = endPoint;\n }\n if (head > rawImageArray.length){break;}\n }\n\n return segments;\n };\n\n\n \n ExifRestorer.decode64 = function(input) \n {\n var output = \"\",\n chr1, chr2, chr3 = \"\",\n enc1, enc2, enc3, enc4 = \"\",\n i = 0,\n buf = [];\n\n // remove all characters that are not A-Z, a-z, 0-9, +, /, or =\n var base64test = /[^A-Za-z0-9\\+\\/\\=]/g;\n if (base64test.exec(input)) {\n throw new Error(\"There were invalid base64 characters in the input text. \" +\n \"Valid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='\");\n }\n input = input.replace(/[^A-Za-z0-9\\+\\/\\=]/g, \"\");\n\n do {\n enc1 = this.KEY_STR.indexOf(input.charAt(i++));\n enc2 = this.KEY_STR.indexOf(input.charAt(i++));\n enc3 = this.KEY_STR.indexOf(input.charAt(i++));\n enc4 = this.KEY_STR.indexOf(input.charAt(i++));\n\n chr1 = (enc1 << 2) | (enc2 >> 4);\n chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);\n chr3 = ((enc3 & 3) << 6) | enc4;\n\n buf.push(chr1);\n\n if (enc3 != 64) {\n buf.push(chr2);\n }\n if (enc4 != 64) {\n buf.push(chr3);\n }\n\n chr1 = chr2 = chr3 = \"\";\n enc1 = enc2 = enc3 = enc4 = \"\";\n\n } while (i < input.length);\n\n return buf;\n };\n\n \n return ExifRestorer;\n})();\n","/* globals qq */\n/**\n * Keeps a running tally of total upload progress for a batch of files.\n *\n * @param callback Invoked when total progress changes, passing calculated total loaded & total size values.\n * @param getSize Function that returns the size of a file given its ID\n * @constructor\n */\nqq.TotalProgress = function(callback, getSize) {\n \"use strict\";\n\n var perFileProgress = {},\n totalLoaded = 0,\n totalSize = 0,\n\n lastLoadedSent = -1,\n lastTotalSent = -1,\n callbackProxy = function(loaded, total) {\n if (loaded !== lastLoadedSent || total !== lastTotalSent) {\n callback(loaded, total);\n }\n\n lastLoadedSent = loaded;\n lastTotalSent = total;\n },\n\n /**\n * @param failed Array of file IDs that have failed\n * @param retryable Array of file IDs that are retryable\n * @returns true if none of the failed files are eligible for retry\n */\n noRetryableFiles = function(failed, retryable) {\n var none = true;\n\n qq.each(failed, function(idx, failedId) {\n if (qq.indexOf(retryable, failedId) >= 0) {\n none = false;\n return false;\n }\n });\n\n return none;\n },\n\n onCancel = function(id) {\n updateTotalProgress(id, -1, -1);\n delete perFileProgress[id];\n },\n\n onAllComplete = function(successful, failed, retryable) {\n if (failed.length === 0 || noRetryableFiles(failed, retryable)) {\n callbackProxy(totalSize, totalSize);\n this.reset();\n }\n },\n\n onNew = function(id) {\n var size = getSize(id);\n\n // We might not know the size yet, such as for blob proxies\n if (size > 0) {\n updateTotalProgress(id, 0, size);\n perFileProgress[id] = {loaded: 0, total: size};\n }\n },\n\n /**\n * Invokes the callback with the current total progress of all files in the batch. Called whenever it may\n * be appropriate to re-calculate and disseminate this data.\n *\n * @param id ID of a file that has changed in some important way\n * @param newLoaded New loaded value for this file. -1 if this value should no longer be part of calculations\n * @param newTotal New total size of the file. -1 if this value should no longer be part of calculations\n */\n updateTotalProgress = function(id, newLoaded, newTotal) {\n var oldLoaded = perFileProgress[id] ? perFileProgress[id].loaded : 0,\n oldTotal = perFileProgress[id] ? perFileProgress[id].total : 0;\n\n if (newLoaded === -1 && newTotal === -1) {\n totalLoaded -= oldLoaded;\n totalSize -= oldTotal;\n }\n else {\n if (newLoaded) {\n totalLoaded += newLoaded - oldLoaded;\n }\n if (newTotal) {\n totalSize += newTotal - oldTotal;\n }\n }\n\n callbackProxy(totalLoaded, totalSize);\n };\n\n qq.extend(this, {\n // Called when a batch of files has completed uploading.\n onAllComplete: onAllComplete,\n\n // Called when the status of a file has changed.\n onStatusChange: function(id, oldStatus, newStatus) {\n if (newStatus === qq.status.CANCELED || newStatus === qq.status.REJECTED) {\n onCancel(id);\n }\n else if (newStatus === qq.status.SUBMITTING) {\n onNew(id);\n }\n },\n\n // Called whenever the upload progress of an individual file has changed.\n onIndividualProgress: function(id, loaded, total) {\n updateTotalProgress(id, loaded, total);\n perFileProgress[id] = {loaded: loaded, total: total};\n },\n\n // Called whenever the total size of a file has changed, such as when the size of a generated blob is known.\n onNewSize: function(id) {\n onNew(id);\n },\n\n reset: function() {\n perFileProgress = {};\n totalLoaded = 0;\n totalSize = 0;\n }\n });\n};\n","/*globals qq*/\nqq.PasteSupport = function(o) {\n \"use strict\";\n\n var options, detachPasteHandler;\n\n options = {\n targetElement: null,\n callbacks: {\n log: function(message, level) {},\n pasteReceived: function(blob) {}\n }\n };\n\n function isImage(item) {\n return item.type &&\n item.type.indexOf(\"image/\") === 0;\n }\n\n function registerPasteHandler() {\n detachPasteHandler = qq(options.targetElement).attach(\"paste\", function(event) {\n var clipboardData = event.clipboardData;\n\n if (clipboardData) {\n qq.each(clipboardData.items, function(idx, item) {\n if (isImage(item)) {\n var blob = item.getAsFile();\n options.callbacks.pasteReceived(blob);\n }\n });\n }\n });\n }\n\n function unregisterPasteHandler() {\n if (detachPasteHandler) {\n detachPasteHandler();\n }\n }\n\n qq.extend(options, o);\n registerPasteHandler();\n\n qq.extend(this, {\n reset: function() {\n unregisterPasteHandler();\n }\n });\n};\n","/* globals qq */\n/**\n * Module that handles support for existing forms.\n *\n * @param options Options passed from the integrator-supplied options related to form support.\n * @param startUpload Callback to invoke when files \"stored\" should be uploaded.\n * @param log Proxy for the logger\n * @constructor\n */\nqq.FormSupport = function(options, startUpload, log) {\n \"use strict\";\n var self = this,\n interceptSubmit = options.interceptSubmit,\n formEl = options.element,\n autoUpload = options.autoUpload;\n\n // Available on the public API associated with this module.\n qq.extend(this, {\n // To be used by the caller to determine if the endpoint will be determined by some processing\n // that occurs in this module, such as if the form has an action attribute.\n // Ignore if `attachToForm === false`.\n newEndpoint: null,\n\n // To be used by the caller to determine if auto uploading should be allowed.\n // Ignore if `attachToForm === false`.\n newAutoUpload: autoUpload,\n\n // true if a form was detected and is being tracked by this module\n attachedToForm: false,\n\n // Returns an object with names and values for all valid form elements associated with the attached form.\n getFormInputsAsObject: function() {\n /* jshint eqnull:true */\n if (formEl == null) {\n return null;\n }\n\n return self._form2Obj(formEl);\n }\n });\n\n // If the form contains an action attribute, this should be the new upload endpoint.\n function determineNewEndpoint(formEl) {\n if (formEl.getAttribute(\"action\")) {\n self.newEndpoint = formEl.getAttribute(\"action\");\n }\n }\n\n // Return true only if the form is valid, or if we cannot make this determination.\n // If the form is invalid, ensure invalid field(s) are highlighted in the UI.\n function validateForm(formEl, nativeSubmit) {\n if (formEl.checkValidity && !formEl.checkValidity()) {\n log(\"Form did not pass validation checks - will not upload.\", \"error\");\n nativeSubmit();\n }\n else {\n return true;\n }\n }\n\n // Intercept form submit attempts, unless the integrator has told us not to do this.\n function maybeUploadOnSubmit(formEl) {\n var nativeSubmit = formEl.submit;\n\n // Intercept and squelch submit events.\n qq(formEl).attach(\"submit\", function(event) {\n event = event || window.event;\n\n if (event.preventDefault) {\n event.preventDefault();\n }\n else {\n event.returnValue = false;\n }\n\n validateForm(formEl, nativeSubmit) && startUpload();\n });\n\n // The form's `submit()` function may be called instead (i.e. via jQuery.submit()).\n // Intercept that too.\n formEl.submit = function() {\n validateForm(formEl, nativeSubmit) && startUpload();\n };\n }\n\n // If the element value passed from the uploader is a string, assume it is an element ID - select it.\n // The rest of the code in this module depends on this being an HTMLElement.\n function determineFormEl(formEl) {\n if (formEl) {\n if (qq.isString(formEl)) {\n formEl = document.getElementById(formEl);\n }\n\n if (formEl) {\n log(\"Attaching to form element.\");\n determineNewEndpoint(formEl);\n interceptSubmit && maybeUploadOnSubmit(formEl);\n }\n }\n\n return formEl;\n }\n\n formEl = determineFormEl(formEl);\n this.attachedToForm = !!formEl;\n};\n\nqq.extend(qq.FormSupport.prototype, {\n // Converts all relevant form fields to key/value pairs. This is meant to mimic the data a browser will\n // construct from a given form when the form is submitted.\n _form2Obj: function(form) {\n \"use strict\";\n var obj = {},\n notIrrelevantType = function(type) {\n var irrelevantTypes = [\n \"button\",\n \"image\",\n \"reset\",\n \"submit\"\n ];\n\n return qq.indexOf(irrelevantTypes, type.toLowerCase()) < 0;\n },\n radioOrCheckbox = function(type) {\n return qq.indexOf([\"checkbox\", \"radio\"], type.toLowerCase()) >= 0;\n },\n ignoreValue = function(el) {\n if (radioOrCheckbox(el.type) && !el.checked) {\n return true;\n }\n\n return el.disabled && el.type.toLowerCase() !== \"hidden\";\n },\n selectValue = function(select) {\n var value = null;\n\n qq.each(qq(select).children(), function(idx, child) {\n if (child.tagName.toLowerCase() === \"option\" && child.selected) {\n value = child.value;\n return false;\n }\n });\n\n return value;\n };\n\n qq.each(form.elements, function(idx, el) {\n if ((qq.isInput(el, true) || el.tagName.toLowerCase() === \"textarea\") &&\n notIrrelevantType(el.type) &&\n !ignoreValue(el)) {\n\n obj[el.name] = el.value;\n }\n else if (el.tagName.toLowerCase() === \"select\" && !ignoreValue(el)) {\n var value = selectValue(el);\n\n if (value !== null) {\n obj[el.name] = value;\n }\n }\n });\n\n return obj;\n }\n});\n","/*globals qq*/\n/**\n * Upload handler used that assumes the current user agent does not have any support for the\n * File API, and, therefore, makes use of iframes and forms to submit the files directly to\n * a generic server.\n *\n * @param options Options passed from the base handler\n * @param proxy Callbacks & methods used to query for or push out data/changes\n */\nqq.traditional = qq.traditional || {};\nqq.traditional.FormUploadHandler = function(options, proxy) {\n \"use strict\";\n\n var handler = this,\n getName = proxy.getName,\n getUuid = proxy.getUuid,\n log = proxy.log;\n\n /**\n * Returns json object received by iframe from server.\n */\n function getIframeContentJson(id, iframe) {\n /*jshint evil: true*/\n\n var response, doc, innerHtml;\n\n //IE may throw an \"access is denied\" error when attempting to access contentDocument on the iframe in some cases\n try {\n // iframe.contentWindow.document - for IE<7\n doc = iframe.contentDocument || iframe.contentWindow.document;\n innerHtml = doc.body.innerHTML;\n\n log(\"converting iframe's innerHTML to JSON\");\n log(\"innerHTML = \" + innerHtml);\n //plain text response may be wrapped in tag\n if (innerHtml && innerHtml.match(/^ 1 && !options.allowMultipleItems) {\n options.callbacks.processingDroppedFilesComplete([]);\n options.callbacks.dropError(\"tooManyFilesError\", \"\");\n uploadDropZone.dropDisabled(false);\n handleDataTransferPromise.failure();\n }\n else {\n droppedFiles = [];\n\n if (qq.isFolderDropSupported(dataTransfer)) {\n qq.each(dataTransfer.items, function(idx, item) {\n var entry = item.webkitGetAsEntry();\n\n if (entry) {\n //due to a bug in Chrome's File System API impl - #149735\n if (entry.isFile) {\n droppedFiles.push(item.getAsFile());\n }\n\n else {\n pendingFolderPromises.push(traverseFileTree(entry).done(function() {\n pendingFolderPromises.pop();\n if (pendingFolderPromises.length === 0) {\n handleDataTransferPromise.success();\n }\n }));\n }\n }\n });\n }\n else {\n droppedFiles = dataTransfer.files;\n }\n\n if (pendingFolderPromises.length === 0) {\n handleDataTransferPromise.success();\n }\n }\n\n return handleDataTransferPromise;\n }\n\n function setupDropzone(dropArea) {\n var dropZone = new qq.UploadDropZone({\n HIDE_ZONES_EVENT_NAME: HIDE_ZONES_EVENT_NAME,\n element: dropArea,\n onEnter: function(e) {\n qq(dropArea).addClass(options.classes.dropActive);\n e.stopPropagation();\n },\n onLeaveNotDescendants: function(e) {\n qq(dropArea).removeClass(options.classes.dropActive);\n },\n onDrop: function(e) {\n handleDataTransfer(e.dataTransfer, dropZone).then(\n function() {\n uploadDroppedFiles(droppedFiles, dropZone);\n },\n function() {\n options.callbacks.dropLog(\"Drop event DataTransfer parsing failed. No files will be uploaded.\", \"error\");\n }\n );\n }\n });\n\n disposeSupport.addDisposer(function() {\n dropZone.dispose();\n });\n\n qq(dropArea).hasAttribute(HIDE_BEFORE_ENTER_ATTR) && qq(dropArea).hide();\n\n uploadDropZones.push(dropZone);\n\n return dropZone;\n }\n\n function isFileDrag(dragEvent) {\n var fileDrag;\n\n qq.each(dragEvent.dataTransfer.types, function(key, val) {\n if (val === \"Files\") {\n fileDrag = true;\n return false;\n }\n });\n\n return fileDrag;\n }\n\n // Attempt to determine when the file has left the document. It is not always possible to detect this\n // in all cases, but it is generally possible in all browsers, with a few exceptions.\n //\n // Exceptions:\n // * IE10+ & Safari: We can't detect a file leaving the document if the Explorer window housing the file\n // overlays the browser window.\n // * IE10+: If the file is dragged out of the window too quickly, IE does not set the expected values of the\n // event's X & Y properties.\n function leavingDocumentOut(e) {\n if (qq.firefox()) {\n return !e.relatedTarget;\n }\n\n if (qq.safari()) {\n return e.x < 0 || e.y < 0;\n }\n\n return e.x === 0 && e.y === 0;\n }\n\n function setupDragDrop() {\n var dropZones = options.dropZoneElements,\n\n maybeHideDropZones = function() {\n setTimeout(function() {\n qq.each(dropZones, function(idx, dropZone) {\n qq(dropZone).hasAttribute(HIDE_BEFORE_ENTER_ATTR) && qq(dropZone).hide();\n qq(dropZone).removeClass(options.classes.dropActive);\n });\n }, 10);\n };\n\n qq.each(dropZones, function(idx, dropZone) {\n var uploadDropZone = setupDropzone(dropZone);\n\n // IE <= 9 does not support the File API used for drag+drop uploads\n if (dropZones.length && qq.supportedFeatures.fileDrop) {\n disposeSupport.attach(document, \"dragenter\", function(e) {\n if (!uploadDropZone.dropDisabled() && isFileDrag(e)) {\n qq.each(dropZones, function(idx, dropZone) {\n // We can't apply styles to non-HTMLElements, since they lack the `style` property.\n // Also, if the drop zone isn't initially hidden, let's not mess with `style.display`.\n if (dropZone instanceof HTMLElement &&\n qq(dropZone).hasAttribute(HIDE_BEFORE_ENTER_ATTR)) {\n\n qq(dropZone).css({display: \"block\"});\n }\n });\n }\n });\n }\n });\n\n disposeSupport.attach(document, \"dragleave\", function(e) {\n if (leavingDocumentOut(e)) {\n maybeHideDropZones();\n }\n });\n\n // Just in case we were not able to detect when a dragged file has left the document,\n // hide all relevant drop zones the next time the mouse enters the document.\n // Note that mouse events such as this one are not fired during drag operations.\n disposeSupport.attach(qq(document).children()[0], \"mouseenter\", function(e) {\n maybeHideDropZones();\n });\n\n disposeSupport.attach(document, \"drop\", function(e) {\n e.preventDefault();\n maybeHideDropZones();\n });\n\n disposeSupport.attach(document, HIDE_ZONES_EVENT_NAME, maybeHideDropZones);\n }\n\n setupDragDrop();\n\n qq.extend(this, {\n setupExtraDropzone: function(element) {\n options.dropZoneElements.push(element);\n setupDropzone(element);\n },\n\n removeDropzone: function(element) {\n var i,\n dzs = options.dropZoneElements;\n\n for (i in dzs) {\n if (dzs[i] === element) {\n return dzs.splice(i, 1);\n }\n }\n },\n\n dispose: function() {\n disposeSupport.dispose();\n qq.each(uploadDropZones, function(idx, dropZone) {\n dropZone.dispose();\n });\n }\n });\n};\n\nqq.DragAndDrop.callbacks = function() {\n \"use strict\";\n\n return {\n processingDroppedFiles: function() {},\n processingDroppedFilesComplete: function(files, targetEl) {},\n dropError: function(code, errorSpecifics) {\n qq.log(\"Drag & drop error code '\" + code + \" with these specifics: '\" + errorSpecifics + \"'\", \"error\");\n },\n dropLog: function(message, level) {\n qq.log(message, level);\n }\n };\n};\n\nqq.UploadDropZone = function(o) {\n \"use strict\";\n\n var disposeSupport = new qq.DisposeSupport(),\n options, element, preventDrop, dropOutsideDisabled;\n\n options = {\n element: null,\n onEnter: function(e) {},\n onLeave: function(e) {},\n // is not fired when leaving element by hovering descendants\n onLeaveNotDescendants: function(e) {},\n onDrop: function(e) {}\n };\n\n qq.extend(options, o);\n element = options.element;\n\n function dragoverShouldBeCanceled() {\n return qq.safari() || (qq.firefox() && qq.windows());\n }\n\n function disableDropOutside(e) {\n // run only once for all instances\n if (!dropOutsideDisabled) {\n\n // for these cases we need to catch onDrop to reset dropArea\n if (dragoverShouldBeCanceled) {\n disposeSupport.attach(document, \"dragover\", function(e) {\n e.preventDefault();\n });\n } else {\n disposeSupport.attach(document, \"dragover\", function(e) {\n if (e.dataTransfer) {\n e.dataTransfer.dropEffect = \"none\";\n e.preventDefault();\n }\n });\n }\n\n dropOutsideDisabled = true;\n }\n }\n\n function isValidFileDrag(e) {\n // e.dataTransfer currently causing IE errors\n // IE9 does NOT support file API, so drag-and-drop is not possible\n if (!qq.supportedFeatures.fileDrop) {\n return false;\n }\n\n var effectTest, dt = e.dataTransfer,\n // do not check dt.types.contains in webkit, because it crashes safari 4\n isSafari = qq.safari();\n\n // dt.effectAllowed is none in Safari 5\n // dt.types.contains check is for firefox\n\n // dt.effectAllowed crashes IE 11 & 10 when files have been dragged from\n // the filesystem\n effectTest = qq.ie() && qq.supportedFeatures.fileDrop ? true : dt.effectAllowed !== \"none\";\n return dt && effectTest && (dt.files || (!isSafari && dt.types.contains && dt.types.contains(\"Files\")));\n }\n\n function isOrSetDropDisabled(isDisabled) {\n if (isDisabled !== undefined) {\n preventDrop = isDisabled;\n }\n return preventDrop;\n }\n\n function triggerHidezonesEvent() {\n var hideZonesEvent;\n\n function triggerUsingOldApi() {\n hideZonesEvent = document.createEvent(\"Event\");\n hideZonesEvent.initEvent(options.HIDE_ZONES_EVENT_NAME, true, true);\n }\n\n if (window.CustomEvent) {\n try {\n hideZonesEvent = new CustomEvent(options.HIDE_ZONES_EVENT_NAME);\n }\n catch (err) {\n triggerUsingOldApi();\n }\n }\n else {\n triggerUsingOldApi();\n }\n\n document.dispatchEvent(hideZonesEvent);\n }\n\n function attachEvents() {\n disposeSupport.attach(element, \"dragover\", function(e) {\n if (!isValidFileDrag(e)) {\n return;\n }\n\n // dt.effectAllowed crashes IE 11 & 10 when files have been dragged from\n // the filesystem\n var effect = qq.ie() && qq.supportedFeatures.fileDrop ? null : e.dataTransfer.effectAllowed;\n if (effect === \"move\" || effect === \"linkMove\") {\n e.dataTransfer.dropEffect = \"move\"; // for FF (only move allowed)\n } else {\n e.dataTransfer.dropEffect = \"copy\"; // for Chrome\n }\n\n e.stopPropagation();\n e.preventDefault();\n });\n\n disposeSupport.attach(element, \"dragenter\", function(e) {\n if (!isOrSetDropDisabled()) {\n if (!isValidFileDrag(e)) {\n return;\n }\n options.onEnter(e);\n }\n });\n\n disposeSupport.attach(element, \"dragleave\", function(e) {\n if (!isValidFileDrag(e)) {\n return;\n }\n\n options.onLeave(e);\n\n var relatedTarget = document.elementFromPoint(e.clientX, e.clientY);\n // do not fire when moving a mouse over a descendant\n if (qq(this).contains(relatedTarget)) {\n return;\n }\n\n options.onLeaveNotDescendants(e);\n });\n\n disposeSupport.attach(element, \"drop\", function(e) {\n if (!isOrSetDropDisabled()) {\n if (!isValidFileDrag(e)) {\n return;\n }\n\n e.preventDefault();\n e.stopPropagation();\n options.onDrop(e);\n\n triggerHidezonesEvent();\n }\n });\n }\n\n disableDropOutside();\n attachEvents();\n\n qq.extend(this, {\n dropDisabled: function(isDisabled) {\n return isOrSetDropDisabled(isDisabled);\n },\n\n dispose: function() {\n disposeSupport.dispose();\n },\n\n getElement: function() {\n return element;\n }\n });\n};\n","/*globals qq */\n/**\n * Defines the public API for FineUploader mode.\n */\n(function() {\n \"use strict\";\n\n qq.uiPublicApi = {\n addInitialFiles: function(cannedFileList) {\n this._parent.prototype.addInitialFiles.apply(this, arguments);\n this._templating.addCacheToDom();\n },\n\n clearStoredFiles: function() {\n this._parent.prototype.clearStoredFiles.apply(this, arguments);\n this._templating.clearFiles();\n },\n\n addExtraDropzone: function(element) {\n this._dnd && this._dnd.setupExtraDropzone(element);\n },\n\n removeExtraDropzone: function(element) {\n if (this._dnd) {\n return this._dnd.removeDropzone(element);\n }\n },\n\n getItemByFileId: function(id) {\n if (!this._templating.isHiddenForever(id)) {\n return this._templating.getFileContainer(id);\n }\n },\n\n reset: function() {\n this._parent.prototype.reset.apply(this, arguments);\n this._templating.reset();\n\n if (!this._options.button && this._templating.getButton()) {\n this._defaultButtonId = this._createUploadButton({\n element: this._templating.getButton(),\n title: this._options.text.fileInputTitle\n }).getButtonId();\n }\n\n if (this._dnd) {\n this._dnd.dispose();\n this._dnd = this._setupDragAndDrop();\n }\n\n this._totalFilesInBatch = 0;\n this._filesInBatchAddedToUi = 0;\n\n this._setupClickAndEditEventHandlers();\n },\n\n setName: function(id, newName) {\n var formattedFilename = this._options.formatFileName(newName);\n\n this._parent.prototype.setName.apply(this, arguments);\n this._templating.updateFilename(id, formattedFilename);\n },\n\n pauseUpload: function(id) {\n var paused = this._parent.prototype.pauseUpload.apply(this, arguments);\n\n paused && this._templating.uploadPaused(id);\n return paused;\n },\n\n continueUpload: function(id) {\n var continued = this._parent.prototype.continueUpload.apply(this, arguments);\n\n continued && this._templating.uploadContinued(id);\n return continued;\n },\n\n getId: function(fileContainerOrChildEl) {\n return this._templating.getFileId(fileContainerOrChildEl);\n },\n\n getDropTarget: function(fileId) {\n var file = this.getFile(fileId);\n\n return file.qqDropTarget;\n }\n };\n\n /**\n * Defines the private (internal) API for FineUploader mode.\n */\n qq.uiPrivateApi = {\n _getButton: function(buttonId) {\n var button = this._parent.prototype._getButton.apply(this, arguments);\n\n if (!button) {\n if (buttonId === this._defaultButtonId) {\n button = this._templating.getButton();\n }\n }\n\n return button;\n },\n\n _removeFileItem: function(fileId) {\n this._templating.removeFile(fileId);\n },\n\n _setupClickAndEditEventHandlers: function() {\n this._fileButtonsClickHandler = qq.FileButtonsClickHandler && this._bindFileButtonsClickEvent();\n\n // A better approach would be to check specifically for focusin event support by querying the DOM API,\n // but the DOMFocusIn event is not exposed as a property, so we have to resort to UA string sniffing.\n this._focusinEventSupported = !qq.firefox();\n\n if (this._isEditFilenameEnabled())\n {\n this._filenameClickHandler = this._bindFilenameClickEvent();\n this._filenameInputFocusInHandler = this._bindFilenameInputFocusInEvent();\n this._filenameInputFocusHandler = this._bindFilenameInputFocusEvent();\n }\n },\n\n _setupDragAndDrop: function() {\n var self = this,\n dropZoneElements = this._options.dragAndDrop.extraDropzones,\n templating = this._templating,\n defaultDropZone = templating.getDropZone();\n\n defaultDropZone && dropZoneElements.push(defaultDropZone);\n\n return new qq.DragAndDrop({\n dropZoneElements: dropZoneElements,\n allowMultipleItems: this._options.multiple,\n classes: {\n dropActive: this._options.classes.dropActive\n },\n callbacks: {\n processingDroppedFiles: function() {\n templating.showDropProcessing();\n },\n processingDroppedFilesComplete: function(files, targetEl) {\n templating.hideDropProcessing();\n\n qq.each(files, function(idx, file) {\n file.qqDropTarget = targetEl;\n });\n\n if (files.length) {\n self.addFiles(files, null, null);\n }\n },\n dropError: function(code, errorData) {\n self._itemError(code, errorData);\n },\n dropLog: function(message, level) {\n self.log(message, level);\n }\n }\n });\n },\n\n _bindFileButtonsClickEvent: function() {\n var self = this;\n\n return new qq.FileButtonsClickHandler({\n templating: this._templating,\n\n log: function(message, lvl) {\n self.log(message, lvl);\n },\n\n onDeleteFile: function(fileId) {\n self.deleteFile(fileId);\n },\n\n onCancel: function(fileId) {\n self.cancel(fileId);\n },\n\n onRetry: function(fileId) {\n self.retry(fileId);\n },\n\n onPause: function(fileId) {\n self.pauseUpload(fileId);\n },\n\n onContinue: function(fileId) {\n self.continueUpload(fileId);\n },\n\n onGetName: function(fileId) {\n return self.getName(fileId);\n }\n });\n },\n\n _isEditFilenameEnabled: function() {\n /*jshint -W014 */\n return this._templating.isEditFilenamePossible()\n && !this._options.autoUpload\n && qq.FilenameClickHandler\n && qq.FilenameInputFocusHandler\n && qq.FilenameInputFocusHandler;\n },\n\n _filenameEditHandler: function() {\n var self = this,\n templating = this._templating;\n\n return {\n templating: templating,\n log: function(message, lvl) {\n self.log(message, lvl);\n },\n onGetUploadStatus: function(fileId) {\n return self.getUploads({id: fileId}).status;\n },\n onGetName: function(fileId) {\n return self.getName(fileId);\n },\n onSetName: function(id, newName) {\n self.setName(id, newName);\n },\n onEditingStatusChange: function(id, isEditing) {\n var qqInput = qq(templating.getEditInput(id)),\n qqFileContainer = qq(templating.getFileContainer(id));\n\n if (isEditing) {\n qqInput.addClass(\"qq-editing\");\n templating.hideFilename(id);\n templating.hideEditIcon(id);\n }\n else {\n qqInput.removeClass(\"qq-editing\");\n templating.showFilename(id);\n templating.showEditIcon(id);\n }\n\n // Force IE8 and older to repaint\n qqFileContainer.addClass(\"qq-temp\").removeClass(\"qq-temp\");\n }\n };\n },\n\n _onUploadStatusChange: function(id, oldStatus, newStatus) {\n this._parent.prototype._onUploadStatusChange.apply(this, arguments);\n\n if (this._isEditFilenameEnabled()) {\n // Status for a file exists before it has been added to the DOM, so we must be careful here.\n if (this._templating.getFileContainer(id) && newStatus !== qq.status.SUBMITTED) {\n this._templating.markFilenameEditable(id);\n this._templating.hideEditIcon(id);\n }\n }\n\n if (oldStatus === qq.status.UPLOAD_RETRYING && newStatus === qq.status.UPLOADING) {\n this._templating.hideRetry(id);\n this._templating.setStatusText(id);\n qq(this._templating.getFileContainer(id)).removeClass(this._classes.retrying);\n }\n else if (newStatus === qq.status.UPLOAD_FAILED) {\n this._templating.hidePause(id);\n }\n },\n\n _bindFilenameInputFocusInEvent: function() {\n var spec = qq.extend({}, this._filenameEditHandler());\n\n return new qq.FilenameInputFocusInHandler(spec);\n },\n\n _bindFilenameInputFocusEvent: function() {\n var spec = qq.extend({}, this._filenameEditHandler());\n\n return new qq.FilenameInputFocusHandler(spec);\n },\n\n _bindFilenameClickEvent: function() {\n var spec = qq.extend({}, this._filenameEditHandler());\n\n return new qq.FilenameClickHandler(spec);\n },\n\n _storeForLater: function(id) {\n this._parent.prototype._storeForLater.apply(this, arguments);\n this._templating.hideSpinner(id);\n },\n\n _onAllComplete: function(successful, failed) {\n this._parent.prototype._onAllComplete.apply(this, arguments);\n this._templating.resetTotalProgress();\n },\n\n _onSubmit: function(id, name) {\n var file = this.getFile(id);\n\n if (file && file.qqPath && this._options.dragAndDrop.reportDirectoryPaths) {\n this._paramsStore.addReadOnly(id, {\n qqpath: file.qqPath\n });\n }\n\n this._parent.prototype._onSubmit.apply(this, arguments);\n this._addToList(id, name);\n },\n\n // The file item has been added to the DOM.\n _onSubmitted: function(id) {\n // If the edit filename feature is enabled, mark the filename element as \"editable\" and the associated edit icon\n if (this._isEditFilenameEnabled()) {\n this._templating.markFilenameEditable(id);\n this._templating.showEditIcon(id);\n\n // If the focusin event is not supported, we must add a focus handler to the newly create edit filename text input\n if (!this._focusinEventSupported) {\n this._filenameInputFocusHandler.addHandler(this._templating.getEditInput(id));\n }\n }\n },\n\n // Update the progress bar & percentage as the file is uploaded\n _onProgress: function(id, name, loaded, total) {\n this._parent.prototype._onProgress.apply(this, arguments);\n\n this._templating.updateProgress(id, loaded, total);\n\n if (total === 0 || Math.round(loaded / total * 100) === 100) {\n this._templating.hideCancel(id);\n this._templating.hidePause(id);\n this._templating.hideProgress(id);\n this._templating.setStatusText(id, this._options.text.waitingForResponse);\n\n // If ~last byte was sent, display total file size\n this._displayFileSize(id);\n }\n else {\n // If still uploading, display percentage - total size is actually the total request(s) size\n this._displayFileSize(id, loaded, total);\n }\n },\n\n _onTotalProgress: function(loaded, total) {\n this._parent.prototype._onTotalProgress.apply(this, arguments);\n this._templating.updateTotalProgress(loaded, total);\n },\n\n _onComplete: function(id, name, result, xhr) {\n var parentRetVal = this._parent.prototype._onComplete.apply(this, arguments),\n templating = this._templating,\n fileContainer = templating.getFileContainer(id),\n self = this;\n\n function completeUpload(result) {\n // If this file is not represented in the templating module, perhaps it was hidden intentionally.\n // If so, don't perform any UI-related tasks related to this file.\n if (!fileContainer) {\n return;\n }\n\n templating.setStatusText(id);\n\n qq(fileContainer).removeClass(self._classes.retrying);\n templating.hideProgress(id);\n\n if (self.getUploads({id: id}).status !== qq.status.UPLOAD_FAILED) {\n templating.hideCancel(id);\n }\n templating.hideSpinner(id);\n\n if (result.success) {\n self._markFileAsSuccessful(id);\n }\n else {\n qq(fileContainer).addClass(self._classes.fail);\n templating.showCancel(id);\n\n if (templating.isRetryPossible() && !self._preventRetries[id]) {\n qq(fileContainer).addClass(self._classes.retryable);\n templating.showRetry(id);\n }\n self._controlFailureTextDisplay(id, result);\n }\n }\n\n // The parent may need to perform some async operation before we can accurately determine the status of the upload.\n if (parentRetVal instanceof qq.Promise) {\n parentRetVal.done(function(newResult) {\n completeUpload(newResult);\n });\n\n }\n else {\n completeUpload(result);\n }\n\n return parentRetVal;\n },\n\n _markFileAsSuccessful: function(id) {\n var templating = this._templating;\n\n if (this._isDeletePossible()) {\n templating.showDeleteButton(id);\n }\n\n qq(templating.getFileContainer(id)).addClass(this._classes.success);\n\n this._maybeUpdateThumbnail(id);\n },\n\n _onUploadPrep: function(id) {\n this._parent.prototype._onUploadPrep.apply(this, arguments);\n this._templating.showSpinner(id);\n },\n\n _onUpload: function(id, name) {\n var parentRetVal = this._parent.prototype._onUpload.apply(this, arguments);\n\n this._templating.showSpinner(id);\n\n return parentRetVal;\n },\n\n _onUploadChunk: function(id, chunkData) {\n this._parent.prototype._onUploadChunk.apply(this, arguments);\n\n // Only display the pause button if we have finished uploading at least one chunk\n // & this file can be resumed\n if (chunkData.partIndex > 0 && this._handler.isResumable(id)) {\n this._templating.allowPause(id);\n }\n },\n\n _onCancel: function(id, name) {\n this._parent.prototype._onCancel.apply(this, arguments);\n this._removeFileItem(id);\n\n if (this._getNotFinished() === 0) {\n this._templating.resetTotalProgress();\n }\n },\n\n _onBeforeAutoRetry: function(id) {\n var retryNumForDisplay, maxAuto, retryNote;\n\n this._parent.prototype._onBeforeAutoRetry.apply(this, arguments);\n\n this._showCancelLink(id);\n\n if (this._options.retry.showAutoRetryNote) {\n retryNumForDisplay = this._autoRetries[id];\n maxAuto = this._options.retry.maxAutoAttempts;\n\n retryNote = this._options.retry.autoRetryNote.replace(/\\{retryNum\\}/g, retryNumForDisplay);\n retryNote = retryNote.replace(/\\{maxAuto\\}/g, maxAuto);\n\n this._templating.setStatusText(id, retryNote);\n qq(this._templating.getFileContainer(id)).addClass(this._classes.retrying);\n }\n },\n\n //return false if we should not attempt the requested retry\n _onBeforeManualRetry: function(id) {\n if (this._parent.prototype._onBeforeManualRetry.apply(this, arguments)) {\n this._templating.resetProgress(id);\n qq(this._templating.getFileContainer(id)).removeClass(this._classes.fail);\n this._templating.setStatusText(id);\n this._templating.showSpinner(id);\n this._showCancelLink(id);\n return true;\n }\n else {\n qq(this._templating.getFileContainer(id)).addClass(this._classes.retryable);\n this._templating.showRetry(id);\n return false;\n }\n },\n\n _onSubmitDelete: function(id) {\n var onSuccessCallback = qq.bind(this._onSubmitDeleteSuccess, this);\n\n this._parent.prototype._onSubmitDelete.call(this, id, onSuccessCallback);\n },\n\n _onSubmitDeleteSuccess: function(id, uuid, additionalMandatedParams) {\n if (this._options.deleteFile.forceConfirm) {\n this._showDeleteConfirm.apply(this, arguments);\n }\n else {\n this._sendDeleteRequest.apply(this, arguments);\n }\n },\n\n _onDeleteComplete: function(id, xhr, isError) {\n this._parent.prototype._onDeleteComplete.apply(this, arguments);\n\n this._templating.hideSpinner(id);\n\n if (isError) {\n this._templating.setStatusText(id, this._options.deleteFile.deletingFailedText);\n this._templating.showDeleteButton(id);\n }\n else {\n this._removeFileItem(id);\n }\n },\n\n _sendDeleteRequest: function(id, uuid, additionalMandatedParams) {\n this._templating.hideDeleteButton(id);\n this._templating.showSpinner(id);\n this._templating.setStatusText(id, this._options.deleteFile.deletingStatusText);\n this._deleteHandler.sendDelete.apply(this, arguments);\n },\n\n _showDeleteConfirm: function(id, uuid, mandatedParams) {\n /*jshint -W004 */\n var fileName = this.getName(id),\n confirmMessage = this._options.deleteFile.confirmMessage.replace(/\\{filename\\}/g, fileName),\n uuid = this.getUuid(id),\n deleteRequestArgs = arguments,\n self = this,\n retVal;\n\n retVal = this._options.showConfirm(confirmMessage);\n\n if (qq.isGenericPromise(retVal)) {\n retVal.then(function() {\n self._sendDeleteRequest.apply(self, deleteRequestArgs);\n });\n }\n else if (retVal !== false) {\n self._sendDeleteRequest.apply(self, deleteRequestArgs);\n }\n },\n\n _addToList: function(id, name, canned) {\n var prependData,\n prependIndex = 0,\n dontDisplay = this._handler.isProxied(id) && this._options.scaling.hideScaled,\n record;\n\n if (this._options.display.prependFiles) {\n if (this._totalFilesInBatch > 1 && this._filesInBatchAddedToUi > 0) {\n prependIndex = this._filesInBatchAddedToUi - 1;\n }\n\n prependData = {\n index: prependIndex\n };\n }\n\n if (!canned) {\n if (this._options.disableCancelForFormUploads && !qq.supportedFeatures.ajaxUploading) {\n this._templating.disableCancel();\n }\n\n // Cancel all existing (previous) files and clear the list if this file is not part of\n // a scaled file group that has already been accepted, or if this file is not part of\n // a scaled file group at all.\n if (!this._options.multiple) {\n record = this.getUploads({id: id});\n\n this._handledProxyGroup = this._handledProxyGroup || record.proxyGroupId;\n\n if (record.proxyGroupId !== this._handledProxyGroup || !record.proxyGroupId) {\n this._handler.cancelAll();\n this._clearList();\n this._handledProxyGroup = null;\n }\n }\n }\n\n if (canned) {\n this._templating.addFileToCache(id, this._options.formatFileName(name), prependData, dontDisplay);\n this._templating.updateThumbnail(id, this._thumbnailUrls[id], true, this._options.thumbnails.customResizer);\n }\n else {\n this._templating.addFile(id, this._options.formatFileName(name), prependData, dontDisplay);\n this._templating.generatePreview(id, this.getFile(id), this._options.thumbnails.customResizer);\n }\n\n this._filesInBatchAddedToUi += 1;\n\n if (canned ||\n (this._options.display.fileSizeOnSubmit && qq.supportedFeatures.ajaxUploading)) {\n\n this._displayFileSize(id);\n }\n },\n\n _clearList: function() {\n this._templating.clearFiles();\n this.clearStoredFiles();\n },\n\n _displayFileSize: function(id, loadedSize, totalSize) {\n var size = this.getSize(id),\n sizeForDisplay = this._formatSize(size);\n\n if (size >= 0) {\n if (loadedSize !== undefined && totalSize !== undefined) {\n sizeForDisplay = this._formatProgress(loadedSize, totalSize);\n }\n\n this._templating.updateSize(id, sizeForDisplay);\n }\n },\n\n _formatProgress: function(uploadedSize, totalSize) {\n var message = this._options.text.formatProgress;\n function r(name, replacement) { message = message.replace(name, replacement); }\n\n r(\"{percent}\", Math.round(uploadedSize / totalSize * 100));\n r(\"{total_size}\", this._formatSize(totalSize));\n return message;\n },\n\n _controlFailureTextDisplay: function(id, response) {\n var mode, responseProperty, failureReason;\n\n mode = this._options.failedUploadTextDisplay.mode;\n responseProperty = this._options.failedUploadTextDisplay.responseProperty;\n\n if (mode === \"custom\") {\n failureReason = response[responseProperty];\n if (!failureReason) {\n failureReason = this._options.text.failUpload;\n }\n\n this._templating.setStatusText(id, failureReason);\n\n if (this._options.failedUploadTextDisplay.enableTooltip) {\n this._showTooltip(id, failureReason);\n }\n }\n else if (mode === \"default\") {\n this._templating.setStatusText(id, this._options.text.failUpload);\n }\n else if (mode !== \"none\") {\n this.log(\"failedUploadTextDisplay.mode value of '\" + mode + \"' is not valid\", \"warn\");\n }\n },\n\n _showTooltip: function(id, text) {\n this._templating.getFileContainer(id).title = text;\n },\n\n _showCancelLink: function(id) {\n if (!this._options.disableCancelForFormUploads || qq.supportedFeatures.ajaxUploading) {\n this._templating.showCancel(id);\n }\n },\n\n _itemError: function(code, name, item) {\n var message = this._parent.prototype._itemError.apply(this, arguments);\n this._options.showMessage(message);\n },\n\n _batchError: function(message) {\n this._parent.prototype._batchError.apply(this, arguments);\n this._options.showMessage(message);\n },\n\n _setupPastePrompt: function() {\n var self = this;\n\n this._options.callbacks.onPasteReceived = function() {\n var message = self._options.paste.namePromptMessage,\n defaultVal = self._options.paste.defaultName;\n\n return self._options.showPrompt(message, defaultVal);\n };\n },\n\n _fileOrBlobRejected: function(id, name) {\n this._totalFilesInBatch -= 1;\n this._parent.prototype._fileOrBlobRejected.apply(this, arguments);\n },\n\n _prepareItemsForUpload: function(items, params, endpoint) {\n this._totalFilesInBatch = items.length;\n this._filesInBatchAddedToUi = 0;\n this._parent.prototype._prepareItemsForUpload.apply(this, arguments);\n },\n\n _maybeUpdateThumbnail: function(fileId) {\n var thumbnailUrl = this._thumbnailUrls[fileId],\n fileStatus = this.getUploads({id: fileId}).status;\n\n if (fileStatus !== qq.status.DELETED &&\n (thumbnailUrl ||\n this._options.thumbnails.placeholders.waitUntilResponse ||\n !qq.supportedFeatures.imagePreviews)) {\n\n // This will replace the \"waiting\" placeholder with a \"preview not available\" placeholder\n // if called with a null thumbnailUrl.\n this._templating.updateThumbnail(fileId, thumbnailUrl, this._options.thumbnails.customResizer);\n }\n },\n\n _addCannedFile: function(sessionData) {\n var id = this._parent.prototype._addCannedFile.apply(this, arguments);\n\n this._addToList(id, this.getName(id), true);\n this._templating.hideSpinner(id);\n this._templating.hideCancel(id);\n this._markFileAsSuccessful(id);\n\n return id;\n },\n\n _setSize: function(id, newSize) {\n this._parent.prototype._setSize.apply(this, arguments);\n\n this._templating.updateSize(id, this._formatSize(newSize));\n },\n\n _sessionRequestComplete: function() {\n this._templating.addCacheToDom();\n this._parent.prototype._sessionRequestComplete.apply(this, arguments);\n }\n };\n}());\n","/*globals qq */\n/**\n * This defines FineUploader mode, which is a default UI w/ drag & drop uploading.\n */\nqq.FineUploader = function(o, namespace) {\n \"use strict\";\n\n var self = this;\n\n // By default this should inherit instance data from FineUploaderBasic, but this can be overridden\n // if the (internal) caller defines a different parent. The parent is also used by\n // the private and public API functions that need to delegate to a parent function.\n this._parent = namespace ? qq[namespace].FineUploaderBasic : qq.FineUploaderBasic;\n this._parent.apply(this, arguments);\n\n // Options provided by FineUploader mode\n qq.extend(this._options, {\n element: null,\n\n button: null,\n\n listElement: null,\n\n dragAndDrop: {\n extraDropzones: [],\n reportDirectoryPaths: false\n },\n\n text: {\n formatProgress: \"{percent}% of {total_size}\",\n failUpload: \"Upload failed\",\n waitingForResponse: \"Processing...\",\n paused: \"Paused\"\n },\n\n template: \"qq-template\",\n\n classes: {\n retrying: \"qq-upload-retrying\",\n retryable: \"qq-upload-retryable\",\n success: \"qq-upload-success\",\n fail: \"qq-upload-fail\",\n editable: \"qq-editable\",\n hide: \"qq-hide\",\n dropActive: \"qq-upload-drop-area-active\"\n },\n\n failedUploadTextDisplay: {\n mode: \"default\", //default, custom, or none\n responseProperty: \"error\",\n enableTooltip: true\n },\n\n messages: {\n tooManyFilesError: \"You may only drop one file\",\n unsupportedBrowser: \"Unrecoverable error - this browser does not permit file uploading of any kind.\"\n },\n\n retry: {\n showAutoRetryNote: true,\n autoRetryNote: \"Retrying {retryNum}/{maxAuto}...\"\n },\n\n deleteFile: {\n forceConfirm: false,\n confirmMessage: \"Are you sure you want to delete {filename}?\",\n deletingStatusText: \"Deleting...\",\n deletingFailedText: \"Delete failed\"\n\n },\n\n display: {\n fileSizeOnSubmit: false,\n prependFiles: false\n },\n\n paste: {\n promptForName: false,\n namePromptMessage: \"Please name this image\"\n },\n\n thumbnails: {\n customResizer: null,\n maxCount: 0,\n placeholders: {\n waitUntilResponse: false,\n notAvailablePath: null,\n waitingPath: null\n },\n timeBetweenThumbs: 750\n },\n\n scaling: {\n hideScaled: false\n },\n\n showMessage: function(message) {\n if (self._templating.hasDialog(\"alert\")) {\n return self._templating.showDialog(\"alert\", message);\n }\n else {\n setTimeout(function() {\n window.alert(message);\n }, 0);\n }\n },\n\n showConfirm: function(message) {\n if (self._templating.hasDialog(\"confirm\")) {\n return self._templating.showDialog(\"confirm\", message);\n }\n else {\n return window.confirm(message);\n }\n },\n\n showPrompt: function(message, defaultValue) {\n if (self._templating.hasDialog(\"prompt\")) {\n return self._templating.showDialog(\"prompt\", message, defaultValue);\n }\n else {\n return window.prompt(message, defaultValue);\n }\n }\n }, true);\n\n // Replace any default options with user defined ones\n qq.extend(this._options, o, true);\n\n this._templating = new qq.Templating({\n log: qq.bind(this.log, this),\n templateIdOrEl: this._options.template,\n containerEl: this._options.element,\n fileContainerEl: this._options.listElement,\n button: this._options.button,\n imageGenerator: this._imageGenerator,\n classes: {\n hide: this._options.classes.hide,\n editable: this._options.classes.editable\n },\n limits: {\n maxThumbs: this._options.thumbnails.maxCount,\n timeBetweenThumbs: this._options.thumbnails.timeBetweenThumbs\n },\n placeholders: {\n waitUntilUpdate: this._options.thumbnails.placeholders.waitUntilResponse,\n thumbnailNotAvailable: this._options.thumbnails.placeholders.notAvailablePath,\n waitingForThumbnail: this._options.thumbnails.placeholders.waitingPath\n },\n text: this._options.text\n });\n\n if (this._options.workarounds.ios8SafariUploads && qq.ios800() && qq.iosSafari()) {\n this._templating.renderFailure(this._options.messages.unsupportedBrowserIos8Safari);\n }\n else if (!qq.supportedFeatures.uploading || (this._options.cors.expected && !qq.supportedFeatures.uploadCors)) {\n this._templating.renderFailure(this._options.messages.unsupportedBrowser);\n }\n else {\n this._wrapCallbacks();\n\n this._templating.render();\n\n this._classes = this._options.classes;\n\n if (!this._options.button && this._templating.getButton()) {\n this._defaultButtonId = this._createUploadButton({\n element: this._templating.getButton(),\n title: this._options.text.fileInputTitle\n }).getButtonId();\n }\n\n this._setupClickAndEditEventHandlers();\n\n if (qq.DragAndDrop && qq.supportedFeatures.fileDrop) {\n this._dnd = this._setupDragAndDrop();\n }\n\n if (this._options.paste.targetElement && this._options.paste.promptForName) {\n if (qq.PasteSupport) {\n this._setupPastePrompt();\n }\n else {\n this.log(\"Paste support module not found.\", \"error\");\n }\n }\n\n this._totalFilesInBatch = 0;\n this._filesInBatchAddedToUi = 0;\n }\n};\n\n// Inherit the base public & private API methods\nqq.extend(qq.FineUploader.prototype, qq.basePublicApi);\nqq.extend(qq.FineUploader.prototype, qq.basePrivateApi);\n\n// Add the FineUploader/default UI public & private UI methods, which may override some base methods.\nqq.extend(qq.FineUploader.prototype, qq.uiPublicApi);\nqq.extend(qq.FineUploader.prototype, qq.uiPrivateApi);\n","/* globals qq */\n/* jshint -W065 */\n/**\n * Module responsible for rendering all Fine Uploader UI templates. This module also asserts at least\n * a limited amount of control over the template elements after they are added to the DOM.\n * Wherever possible, this module asserts total control over template elements present in the DOM.\n *\n * @param spec Specification object used to control various templating behaviors\n * @constructor\n */\nqq.Templating = function(spec) {\n \"use strict\";\n\n var FILE_ID_ATTR = \"qq-file-id\",\n FILE_CLASS_PREFIX = \"qq-file-id-\",\n THUMBNAIL_MAX_SIZE_ATTR = \"qq-max-size\",\n THUMBNAIL_SERVER_SCALE_ATTR = \"qq-server-scale\",\n // This variable is duplicated in the DnD module since it can function as a standalone as well\n HIDE_DROPZONE_ATTR = \"qq-hide-dropzone\",\n DROPZPONE_TEXT_ATTR = \"qq-drop-area-text\",\n IN_PROGRESS_CLASS = \"qq-in-progress\",\n HIDDEN_FOREVER_CLASS = \"qq-hidden-forever\",\n fileBatch = {\n content: document.createDocumentFragment(),\n map: {}\n },\n isCancelDisabled = false,\n generatedThumbnails = 0,\n thumbnailQueueMonitorRunning = false,\n thumbGenerationQueue = [],\n thumbnailMaxSize = -1,\n options = {\n log: null,\n limits: {\n maxThumbs: 0,\n timeBetweenThumbs: 750\n },\n templateIdOrEl: \"qq-template\",\n containerEl: null,\n fileContainerEl: null,\n button: null,\n imageGenerator: null,\n classes: {\n hide: \"qq-hide\",\n editable: \"qq-editable\"\n },\n placeholders: {\n waitUntilUpdate: false,\n thumbnailNotAvailable: null,\n waitingForThumbnail: null\n },\n text: {\n paused: \"Paused\"\n }\n },\n selectorClasses = {\n button: \"qq-upload-button-selector\",\n alertDialog: \"qq-alert-dialog-selector\",\n dialogCancelButton: \"qq-cancel-button-selector\",\n confirmDialog: \"qq-confirm-dialog-selector\",\n dialogMessage: \"qq-dialog-message-selector\",\n dialogOkButton: \"qq-ok-button-selector\",\n promptDialog: \"qq-prompt-dialog-selector\",\n uploader: \"qq-uploader-selector\",\n drop: \"qq-upload-drop-area-selector\",\n list: \"qq-upload-list-selector\",\n progressBarContainer: \"qq-progress-bar-container-selector\",\n progressBar: \"qq-progress-bar-selector\",\n totalProgressBarContainer: \"qq-total-progress-bar-container-selector\",\n totalProgressBar: \"qq-total-progress-bar-selector\",\n file: \"qq-upload-file-selector\",\n spinner: \"qq-upload-spinner-selector\",\n size: \"qq-upload-size-selector\",\n cancel: \"qq-upload-cancel-selector\",\n pause: \"qq-upload-pause-selector\",\n continueButton: \"qq-upload-continue-selector\",\n deleteButton: \"qq-upload-delete-selector\",\n retry: \"qq-upload-retry-selector\",\n statusText: \"qq-upload-status-text-selector\",\n editFilenameInput: \"qq-edit-filename-selector\",\n editNameIcon: \"qq-edit-filename-icon-selector\",\n dropText: \"qq-upload-drop-area-text-selector\",\n dropProcessing: \"qq-drop-processing-selector\",\n dropProcessingSpinner: \"qq-drop-processing-spinner-selector\",\n thumbnail: \"qq-thumbnail-selector\"\n },\n previewGeneration = {},\n cachedThumbnailNotAvailableImg = new qq.Promise(),\n cachedWaitingForThumbnailImg = new qq.Promise(),\n log,\n isEditElementsExist,\n isRetryElementExist,\n templateHtml,\n container,\n fileList,\n showThumbnails,\n serverScale,\n\n // During initialization of the templating module we should cache any\n // placeholder images so we can quickly swap them into the file list on demand.\n // Any placeholder images that cannot be loaded/found are simply ignored.\n cacheThumbnailPlaceholders = function() {\n var notAvailableUrl = options.placeholders.thumbnailNotAvailable,\n waitingUrl = options.placeholders.waitingForThumbnail,\n spec = {\n maxSize: thumbnailMaxSize,\n scale: serverScale\n };\n\n if (showThumbnails) {\n if (notAvailableUrl) {\n options.imageGenerator.generate(notAvailableUrl, new Image(), spec).then(\n function(updatedImg) {\n cachedThumbnailNotAvailableImg.success(updatedImg);\n },\n function() {\n cachedThumbnailNotAvailableImg.failure();\n log(\"Problem loading 'not available' placeholder image at \" + notAvailableUrl, \"error\");\n }\n );\n }\n else {\n cachedThumbnailNotAvailableImg.failure();\n }\n\n if (waitingUrl) {\n options.imageGenerator.generate(waitingUrl, new Image(), spec).then(\n function(updatedImg) {\n cachedWaitingForThumbnailImg.success(updatedImg);\n },\n function() {\n cachedWaitingForThumbnailImg.failure();\n log(\"Problem loading 'waiting for thumbnail' placeholder image at \" + waitingUrl, \"error\");\n }\n );\n }\n else {\n cachedWaitingForThumbnailImg.failure();\n }\n }\n },\n\n // Displays a \"waiting for thumbnail\" type placeholder image\n // iff we were able to load it during initialization of the templating module.\n displayWaitingImg = function(thumbnail) {\n var waitingImgPlacement = new qq.Promise();\n\n cachedWaitingForThumbnailImg.then(function(img) {\n maybeScalePlaceholderViaCss(img, thumbnail);\n /* jshint eqnull:true */\n if (!thumbnail.src) {\n thumbnail.src = img.src;\n thumbnail.onload = function() {\n thumbnail.onload = null;\n show(thumbnail);\n waitingImgPlacement.success();\n };\n }\n else {\n waitingImgPlacement.success();\n }\n }, function() {\n // In some browsers (such as IE9 and older) an img w/out a src attribute\n // are displayed as \"broken\" images, so we should just hide the img tag\n // if we aren't going to display the \"waiting\" placeholder.\n hide(thumbnail);\n waitingImgPlacement.success();\n });\n\n return waitingImgPlacement;\n },\n\n generateNewPreview = function(id, blob, spec) {\n var thumbnail = getThumbnail(id);\n\n log(\"Generating new thumbnail for \" + id);\n blob.qqThumbnailId = id;\n\n return options.imageGenerator.generate(blob, thumbnail, spec).then(\n function() {\n generatedThumbnails++;\n show(thumbnail);\n previewGeneration[id].success();\n },\n function() {\n previewGeneration[id].failure();\n\n // Display the \"not available\" placeholder img only if we are\n // not expecting a thumbnail at a later point, such as in a server response.\n if (!options.placeholders.waitUntilUpdate) {\n maybeSetDisplayNotAvailableImg(id, thumbnail);\n }\n });\n },\n\n generateNextQueuedPreview = function() {\n if (thumbGenerationQueue.length) {\n thumbnailQueueMonitorRunning = true;\n\n var queuedThumbRequest = thumbGenerationQueue.shift();\n\n if (queuedThumbRequest.update) {\n processUpdateQueuedPreviewRequest(queuedThumbRequest);\n }\n else {\n processNewQueuedPreviewRequest(queuedThumbRequest);\n }\n }\n else {\n thumbnailQueueMonitorRunning = false;\n }\n },\n\n getCancel = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.cancel);\n },\n\n getContinue = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.continueButton);\n },\n\n getDialog = function(type) {\n return getTemplateEl(container, selectorClasses[type + \"Dialog\"]);\n },\n\n getDelete = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.deleteButton);\n },\n\n getDropProcessing = function() {\n return getTemplateEl(container, selectorClasses.dropProcessing);\n },\n\n getEditIcon = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.editNameIcon);\n },\n\n getFile = function(id) {\n return fileBatch.map[id] || qq(fileList).getFirstByClass(FILE_CLASS_PREFIX + id);\n },\n\n getFilename = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.file);\n },\n\n getPause = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.pause);\n },\n\n getProgress = function(id) {\n /* jshint eqnull:true */\n // Total progress bar\n if (id == null) {\n return getTemplateEl(container, selectorClasses.totalProgressBarContainer) ||\n getTemplateEl(container, selectorClasses.totalProgressBar);\n }\n\n // Per-file progress bar\n return getTemplateEl(getFile(id), selectorClasses.progressBarContainer) ||\n getTemplateEl(getFile(id), selectorClasses.progressBar);\n },\n\n getRetry = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.retry);\n },\n\n getSize = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.size);\n },\n\n getSpinner = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.spinner);\n },\n\n getTemplateEl = function(context, cssClass) {\n return context && qq(context).getFirstByClass(cssClass);\n },\n\n getThumbnail = function(id) {\n return showThumbnails && getTemplateEl(getFile(id), selectorClasses.thumbnail);\n },\n\n hide = function(el) {\n el && qq(el).addClass(options.classes.hide);\n },\n\n // Ensures a placeholder image does not exceed any max size specified\n // via `style` attribute properties iff was not used to scale\n // the placeholder AND the target doesn't already have these `style` attribute properties set.\n maybeScalePlaceholderViaCss = function(placeholder, thumbnail) {\n var maxWidth = placeholder.style.maxWidth,\n maxHeight = placeholder.style.maxHeight;\n\n if (maxHeight && maxWidth && !thumbnail.style.maxWidth && !thumbnail.style.maxHeight) {\n qq(thumbnail).css({\n maxWidth: maxWidth,\n maxHeight: maxHeight\n });\n }\n },\n\n // Displays a \"thumbnail not available\" type placeholder image\n // iff we were able to load this placeholder during initialization\n // of the templating module or after preview generation has failed.\n maybeSetDisplayNotAvailableImg = function(id, thumbnail) {\n var previewing = previewGeneration[id] || new qq.Promise().failure(),\n notAvailableImgPlacement = new qq.Promise();\n\n cachedThumbnailNotAvailableImg.then(function(img) {\n previewing.then(\n function() {\n notAvailableImgPlacement.success();\n },\n function() {\n maybeScalePlaceholderViaCss(img, thumbnail);\n\n thumbnail.onload = function() {\n thumbnail.onload = null;\n notAvailableImgPlacement.success();\n };\n\n thumbnail.src = img.src;\n show(thumbnail);\n }\n );\n });\n\n return notAvailableImgPlacement;\n },\n\n /**\n * Grabs the HTML from the script tag holding the template markup. This function will also adjust\n * some internally-tracked state variables based on the contents of the template.\n * The template is filtered so that irrelevant elements (such as the drop zone if DnD is not supported)\n * are omitted from the DOM. Useful errors will be thrown if the template cannot be parsed.\n *\n * @returns {{template: *, fileTemplate: *}} HTML for the top-level file items templates\n */\n parseAndGetTemplate = function() {\n var scriptEl,\n scriptHtml,\n fileListNode,\n tempTemplateEl,\n fileListHtml,\n defaultButton,\n dropArea,\n thumbnail,\n dropProcessing,\n dropTextEl,\n uploaderEl;\n\n log(\"Parsing template\");\n\n /*jshint -W116*/\n if (options.templateIdOrEl == null) {\n throw new Error(\"You MUST specify either a template element or ID!\");\n }\n\n // Grab the contents of the script tag holding the template.\n if (qq.isString(options.templateIdOrEl)) {\n scriptEl = document.getElementById(options.templateIdOrEl);\n\n if (scriptEl === null) {\n throw new Error(qq.format(\"Cannot find template script at ID '{}'!\", options.templateIdOrEl));\n }\n\n scriptHtml = scriptEl.innerHTML;\n }\n else {\n if (options.templateIdOrEl.innerHTML === undefined) {\n throw new Error(\"You have specified an invalid value for the template option! \" +\n \"It must be an ID or an Element.\");\n }\n\n scriptHtml = options.templateIdOrEl.innerHTML;\n }\n\n scriptHtml = qq.trimStr(scriptHtml);\n tempTemplateEl = document.createElement(\"div\");\n tempTemplateEl.appendChild(qq.toElement(scriptHtml));\n uploaderEl = qq(tempTemplateEl).getFirstByClass(selectorClasses.uploader);\n\n // Don't include the default template button in the DOM\n // if an alternate button container has been specified.\n if (options.button) {\n defaultButton = qq(tempTemplateEl).getFirstByClass(selectorClasses.button);\n if (defaultButton) {\n qq(defaultButton).remove();\n }\n }\n\n // Omit the drop processing element from the DOM if DnD is not supported by the UA,\n // or the drag and drop module is not found.\n // NOTE: We are consciously not removing the drop zone if the UA doesn't support DnD\n // to support layouts where the drop zone is also a container for visible elements,\n // such as the file list.\n if (!qq.DragAndDrop || !qq.supportedFeatures.fileDrop) {\n dropProcessing = qq(tempTemplateEl).getFirstByClass(selectorClasses.dropProcessing);\n if (dropProcessing) {\n qq(dropProcessing).remove();\n }\n }\n\n dropArea = qq(tempTemplateEl).getFirstByClass(selectorClasses.drop);\n\n // If DnD is not available then remove\n // it from the DOM as well.\n if (dropArea && !qq.DragAndDrop) {\n log(\"DnD module unavailable.\", \"info\");\n qq(dropArea).remove();\n }\n\n if (!qq.supportedFeatures.fileDrop) {\n // don't display any \"drop files to upload\" background text\n uploaderEl.removeAttribute(DROPZPONE_TEXT_ATTR);\n\n if (dropArea && qq(dropArea).hasAttribute(HIDE_DROPZONE_ATTR)) {\n // If there is a drop area defined in the template, and the current UA doesn't support DnD,\n // and the drop area is marked as \"hide before enter\", ensure it is hidden as the DnD module\n // will not do this (since we will not be loading the DnD module)\n qq(dropArea).css({\n display: \"none\"\n });\n }\n }\n else if (qq(uploaderEl).hasAttribute(DROPZPONE_TEXT_ATTR) && dropArea) {\n dropTextEl = qq(dropArea).getFirstByClass(selectorClasses.dropText);\n dropTextEl && qq(dropTextEl).remove();\n }\n\n // Ensure the `showThumbnails` flag is only set if the thumbnail element\n // is present in the template AND the current UA is capable of generating client-side previews.\n thumbnail = qq(tempTemplateEl).getFirstByClass(selectorClasses.thumbnail);\n if (!showThumbnails) {\n thumbnail && qq(thumbnail).remove();\n }\n else if (thumbnail) {\n thumbnailMaxSize = parseInt(thumbnail.getAttribute(THUMBNAIL_MAX_SIZE_ATTR));\n // Only enforce max size if the attr value is non-zero\n thumbnailMaxSize = thumbnailMaxSize > 0 ? thumbnailMaxSize : null;\n\n serverScale = qq(thumbnail).hasAttribute(THUMBNAIL_SERVER_SCALE_ATTR);\n }\n showThumbnails = showThumbnails && thumbnail;\n\n isEditElementsExist = qq(tempTemplateEl).getByClass(selectorClasses.editFilenameInput).length > 0;\n isRetryElementExist = qq(tempTemplateEl).getByClass(selectorClasses.retry).length > 0;\n\n fileListNode = qq(tempTemplateEl).getFirstByClass(selectorClasses.list);\n /*jshint -W116*/\n if (fileListNode == null) {\n throw new Error(\"Could not find the file list container in the template!\");\n }\n\n fileListHtml = fileListNode.innerHTML;\n fileListNode.innerHTML = \"\";\n\n // We must call `createElement` in IE8 in order to target and hide any via CSS\n if (tempTemplateEl.getElementsByTagName(\"DIALOG\").length) {\n document.createElement(\"dialog\");\n }\n\n log(\"Template parsing complete\");\n\n return {\n template: qq.trimStr(tempTemplateEl.innerHTML),\n fileTemplate: qq.trimStr(fileListHtml)\n };\n },\n\n prependFile = function(el, index, fileList) {\n var parentEl = fileList,\n beforeEl = parentEl.firstChild;\n\n if (index > 0) {\n beforeEl = qq(parentEl).children()[index].nextSibling;\n\n }\n\n parentEl.insertBefore(el, beforeEl);\n },\n\n processNewQueuedPreviewRequest = function(queuedThumbRequest) {\n var id = queuedThumbRequest.id,\n optFileOrBlob = queuedThumbRequest.optFileOrBlob,\n relatedThumbnailId = optFileOrBlob && optFileOrBlob.qqThumbnailId,\n thumbnail = getThumbnail(id),\n spec = {\n customResizeFunction: queuedThumbRequest.customResizeFunction,\n maxSize: thumbnailMaxSize,\n orient: true,\n scale: true\n };\n\n if (qq.supportedFeatures.imagePreviews) {\n if (thumbnail) {\n if (options.limits.maxThumbs && options.limits.maxThumbs <= generatedThumbnails) {\n maybeSetDisplayNotAvailableImg(id, thumbnail);\n generateNextQueuedPreview();\n }\n else {\n displayWaitingImg(thumbnail).done(function() {\n previewGeneration[id] = new qq.Promise();\n\n previewGeneration[id].done(function() {\n setTimeout(generateNextQueuedPreview, options.limits.timeBetweenThumbs);\n });\n\n /* jshint eqnull: true */\n // If we've already generated an for this file, use the one that exists,\n // don't waste resources generating a new one.\n if (relatedThumbnailId != null) {\n useCachedPreview(id, relatedThumbnailId);\n }\n else {\n generateNewPreview(id, optFileOrBlob, spec);\n }\n });\n }\n }\n // File element in template may have been removed, so move on to next item in queue\n else {\n generateNextQueuedPreview();\n }\n }\n else if (thumbnail) {\n displayWaitingImg(thumbnail);\n generateNextQueuedPreview();\n }\n },\n\n processUpdateQueuedPreviewRequest = function(queuedThumbRequest) {\n var id = queuedThumbRequest.id,\n thumbnailUrl = queuedThumbRequest.thumbnailUrl,\n showWaitingImg = queuedThumbRequest.showWaitingImg,\n thumbnail = getThumbnail(id),\n spec = {\n customResizeFunction: queuedThumbRequest.customResizeFunction,\n scale: serverScale,\n maxSize: thumbnailMaxSize\n };\n\n if (thumbnail) {\n if (thumbnailUrl) {\n if (options.limits.maxThumbs && options.limits.maxThumbs <= generatedThumbnails) {\n maybeSetDisplayNotAvailableImg(id, thumbnail);\n generateNextQueuedPreview();\n }\n else {\n if (showWaitingImg) {\n displayWaitingImg(thumbnail);\n }\n\n return options.imageGenerator.generate(thumbnailUrl, thumbnail, spec).then(\n function() {\n show(thumbnail);\n generatedThumbnails++;\n setTimeout(generateNextQueuedPreview, options.limits.timeBetweenThumbs);\n },\n\n function() {\n maybeSetDisplayNotAvailableImg(id, thumbnail);\n setTimeout(generateNextQueuedPreview, options.limits.timeBetweenThumbs);\n }\n );\n }\n }\n else {\n maybeSetDisplayNotAvailableImg(id, thumbnail);\n generateNextQueuedPreview();\n }\n }\n },\n\n setProgressBarWidth = function(id, percent) {\n var bar = getProgress(id),\n /* jshint eqnull:true */\n progressBarSelector = id == null ? selectorClasses.totalProgressBar : selectorClasses.progressBar;\n\n if (bar && !qq(bar).hasClass(progressBarSelector)) {\n bar = qq(bar).getFirstByClass(progressBarSelector);\n }\n\n if (bar) {\n qq(bar).css({width: percent + \"%\"});\n bar.setAttribute(\"aria-valuenow\", percent);\n }\n },\n\n show = function(el) {\n el && qq(el).removeClass(options.classes.hide);\n },\n\n useCachedPreview = function(targetThumbnailId, cachedThumbnailId) {\n var targetThumbnail = getThumbnail(targetThumbnailId),\n cachedThumbnail = getThumbnail(cachedThumbnailId);\n\n log(qq.format(\"ID {} is the same file as ID {}. Will use generated thumbnail from ID {} instead.\", targetThumbnailId, cachedThumbnailId, cachedThumbnailId));\n\n // Generation of the related thumbnail may still be in progress, so, wait until it is done.\n previewGeneration[cachedThumbnailId].then(function() {\n generatedThumbnails++;\n previewGeneration[targetThumbnailId].success();\n log(qq.format(\"Now using previously generated thumbnail created for ID {} on ID {}.\", cachedThumbnailId, targetThumbnailId));\n targetThumbnail.src = cachedThumbnail.src;\n show(targetThumbnail);\n },\n function() {\n previewGeneration[targetThumbnailId].failure();\n if (!options.placeholders.waitUntilUpdate) {\n maybeSetDisplayNotAvailableImg(targetThumbnailId, targetThumbnail);\n }\n });\n };\n\n qq.extend(options, spec);\n log = options.log;\n\n // No need to worry about conserving CPU or memory on older browsers,\n // since there is no ability to preview, and thumbnail display is primitive and quick.\n if (!qq.supportedFeatures.imagePreviews) {\n options.limits.timeBetweenThumbs = 0;\n options.limits.maxThumbs = 0;\n }\n\n container = options.containerEl;\n showThumbnails = options.imageGenerator !== undefined;\n templateHtml = parseAndGetTemplate();\n\n cacheThumbnailPlaceholders();\n\n qq.extend(this, {\n render: function() {\n log(\"Rendering template in DOM.\");\n\n generatedThumbnails = 0;\n\n container.innerHTML = templateHtml.template;\n hide(getDropProcessing());\n this.hideTotalProgress();\n fileList = options.fileContainerEl || getTemplateEl(container, selectorClasses.list);\n\n log(\"Template rendering complete\");\n },\n\n renderFailure: function(message) {\n var cantRenderEl = qq.toElement(message);\n container.innerHTML = \"\";\n container.appendChild(cantRenderEl);\n },\n\n reset: function() {\n this.render();\n },\n\n clearFiles: function() {\n fileList.innerHTML = \"\";\n },\n\n disableCancel: function() {\n isCancelDisabled = true;\n },\n\n addFile: function(id, name, prependInfo, hideForever, batch) {\n var fileEl = qq.toElement(templateHtml.fileTemplate),\n fileNameEl = getTemplateEl(fileEl, selectorClasses.file),\n uploaderEl = getTemplateEl(container, selectorClasses.uploader),\n fileContainer = batch ? fileBatch.content : fileList,\n thumb;\n\n if (batch) {\n fileBatch.map[id] = fileEl;\n }\n\n qq(fileEl).addClass(FILE_CLASS_PREFIX + id);\n uploaderEl.removeAttribute(DROPZPONE_TEXT_ATTR);\n\n if (fileNameEl) {\n qq(fileNameEl).setText(name);\n fileNameEl.setAttribute(\"title\", name);\n }\n\n fileEl.setAttribute(FILE_ID_ATTR, id);\n\n if (prependInfo) {\n prependFile(fileEl, prependInfo.index, fileContainer);\n }\n else {\n fileContainer.appendChild(fileEl);\n }\n\n if (hideForever) {\n fileEl.style.display = \"none\";\n qq(fileEl).addClass(HIDDEN_FOREVER_CLASS);\n }\n else {\n hide(getProgress(id));\n hide(getSize(id));\n hide(getDelete(id));\n hide(getRetry(id));\n hide(getPause(id));\n hide(getContinue(id));\n\n if (isCancelDisabled) {\n this.hideCancel(id);\n }\n\n thumb = getThumbnail(id);\n if (thumb && !thumb.src) {\n cachedWaitingForThumbnailImg.then(function(waitingImg) {\n thumb.src = waitingImg.src;\n if (waitingImg.style.maxHeight && waitingImg.style.maxWidth) {\n qq(thumb).css({\n maxHeight: waitingImg.style.maxHeight,\n maxWidth: waitingImg.style.maxWidth\n });\n }\n\n show(thumb);\n });\n }\n }\n },\n\n addFileToCache: function(id, name, prependInfo, hideForever) {\n this.addFile(id, name, prependInfo, hideForever, true);\n },\n\n addCacheToDom: function() {\n fileList.appendChild(fileBatch.content);\n fileBatch.content = document.createDocumentFragment();\n fileBatch.map = {};\n },\n\n removeFile: function(id) {\n qq(getFile(id)).remove();\n },\n\n getFileId: function(el) {\n var currentNode = el;\n\n if (currentNode) {\n /*jshint -W116*/\n while (currentNode.getAttribute(FILE_ID_ATTR) == null) {\n currentNode = currentNode.parentNode;\n }\n\n return parseInt(currentNode.getAttribute(FILE_ID_ATTR));\n }\n },\n\n getFileList: function() {\n return fileList;\n },\n\n markFilenameEditable: function(id) {\n var filename = getFilename(id);\n\n filename && qq(filename).addClass(options.classes.editable);\n },\n\n updateFilename: function(id, name) {\n var filenameEl = getFilename(id);\n\n if (filenameEl) {\n qq(filenameEl).setText(name);\n filenameEl.setAttribute(\"title\", name);\n }\n },\n\n hideFilename: function(id) {\n hide(getFilename(id));\n },\n\n showFilename: function(id) {\n show(getFilename(id));\n },\n\n isFileName: function(el) {\n return qq(el).hasClass(selectorClasses.file);\n },\n\n getButton: function() {\n return options.button || getTemplateEl(container, selectorClasses.button);\n },\n\n hideDropProcessing: function() {\n hide(getDropProcessing());\n },\n\n showDropProcessing: function() {\n show(getDropProcessing());\n },\n\n getDropZone: function() {\n return getTemplateEl(container, selectorClasses.drop);\n },\n\n isEditFilenamePossible: function() {\n return isEditElementsExist;\n },\n\n hideRetry: function(id) {\n hide(getRetry(id));\n },\n\n isRetryPossible: function() {\n return isRetryElementExist;\n },\n\n showRetry: function(id) {\n show(getRetry(id));\n },\n\n getFileContainer: function(id) {\n return getFile(id);\n },\n\n showEditIcon: function(id) {\n var icon = getEditIcon(id);\n\n icon && qq(icon).addClass(options.classes.editable);\n },\n\n isHiddenForever: function(id) {\n return qq(getFile(id)).hasClass(HIDDEN_FOREVER_CLASS);\n },\n\n hideEditIcon: function(id) {\n var icon = getEditIcon(id);\n\n icon && qq(icon).removeClass(options.classes.editable);\n },\n\n isEditIcon: function(el) {\n return qq(el).hasClass(selectorClasses.editNameIcon, true);\n },\n\n getEditInput: function(id) {\n return getTemplateEl(getFile(id), selectorClasses.editFilenameInput);\n },\n\n isEditInput: function(el) {\n return qq(el).hasClass(selectorClasses.editFilenameInput, true);\n },\n\n updateProgress: function(id, loaded, total) {\n var bar = getProgress(id),\n percent;\n\n if (bar && total > 0) {\n percent = Math.round(loaded / total * 100);\n\n if (percent === 100) {\n hide(bar);\n }\n else {\n show(bar);\n }\n\n setProgressBarWidth(id, percent);\n }\n },\n\n updateTotalProgress: function(loaded, total) {\n this.updateProgress(null, loaded, total);\n },\n\n hideProgress: function(id) {\n var bar = getProgress(id);\n\n bar && hide(bar);\n },\n\n hideTotalProgress: function() {\n this.hideProgress();\n },\n\n resetProgress: function(id) {\n setProgressBarWidth(id, 0);\n this.hideTotalProgress(id);\n },\n\n resetTotalProgress: function() {\n this.resetProgress();\n },\n\n showCancel: function(id) {\n if (!isCancelDisabled) {\n var cancel = getCancel(id);\n\n cancel && qq(cancel).removeClass(options.classes.hide);\n }\n },\n\n hideCancel: function(id) {\n hide(getCancel(id));\n },\n\n isCancel: function(el) {\n return qq(el).hasClass(selectorClasses.cancel, true);\n },\n\n allowPause: function(id) {\n show(getPause(id));\n hide(getContinue(id));\n },\n\n uploadPaused: function(id) {\n this.setStatusText(id, options.text.paused);\n this.allowContinueButton(id);\n hide(getSpinner(id));\n },\n\n hidePause: function(id) {\n hide(getPause(id));\n },\n\n isPause: function(el) {\n return qq(el).hasClass(selectorClasses.pause, true);\n },\n\n isContinueButton: function(el) {\n return qq(el).hasClass(selectorClasses.continueButton, true);\n },\n\n allowContinueButton: function(id) {\n show(getContinue(id));\n hide(getPause(id));\n },\n\n uploadContinued: function(id) {\n this.setStatusText(id, \"\");\n this.allowPause(id);\n show(getSpinner(id));\n },\n\n showDeleteButton: function(id) {\n show(getDelete(id));\n },\n\n hideDeleteButton: function(id) {\n hide(getDelete(id));\n },\n\n isDeleteButton: function(el) {\n return qq(el).hasClass(selectorClasses.deleteButton, true);\n },\n\n isRetry: function(el) {\n return qq(el).hasClass(selectorClasses.retry, true);\n },\n\n updateSize: function(id, text) {\n var size = getSize(id);\n\n if (size) {\n show(size);\n qq(size).setText(text);\n }\n },\n\n setStatusText: function(id, text) {\n var textEl = getTemplateEl(getFile(id), selectorClasses.statusText);\n\n if (textEl) {\n /*jshint -W116*/\n if (text == null) {\n qq(textEl).clearText();\n }\n else {\n qq(textEl).setText(text);\n }\n }\n },\n\n hideSpinner: function(id) {\n qq(getFile(id)).removeClass(IN_PROGRESS_CLASS);\n hide(getSpinner(id));\n },\n\n showSpinner: function(id) {\n qq(getFile(id)).addClass(IN_PROGRESS_CLASS);\n show(getSpinner(id));\n },\n\n generatePreview: function(id, optFileOrBlob, customResizeFunction) {\n if (!this.isHiddenForever(id)) {\n thumbGenerationQueue.push({id: id, customResizeFunction: customResizeFunction, optFileOrBlob: optFileOrBlob});\n !thumbnailQueueMonitorRunning && generateNextQueuedPreview();\n }\n },\n\n updateThumbnail: function(id, thumbnailUrl, showWaitingImg, customResizeFunction) {\n if (!this.isHiddenForever(id)) {\n thumbGenerationQueue.push({customResizeFunction: customResizeFunction, update: true, id: id, thumbnailUrl: thumbnailUrl, showWaitingImg: showWaitingImg});\n !thumbnailQueueMonitorRunning && generateNextQueuedPreview();\n }\n },\n\n hasDialog: function(type) {\n return qq.supportedFeatures.dialogElement && !!getDialog(type);\n },\n\n showDialog: function(type, message, defaultValue) {\n var dialog = getDialog(type),\n messageEl = getTemplateEl(dialog, selectorClasses.dialogMessage),\n inputEl = dialog.getElementsByTagName(\"INPUT\")[0],\n cancelBtn = getTemplateEl(dialog, selectorClasses.dialogCancelButton),\n okBtn = getTemplateEl(dialog, selectorClasses.dialogOkButton),\n promise = new qq.Promise(),\n\n closeHandler = function() {\n cancelBtn.removeEventListener(\"click\", cancelClickHandler);\n okBtn && okBtn.removeEventListener(\"click\", okClickHandler);\n promise.failure();\n },\n\n cancelClickHandler = function() {\n cancelBtn.removeEventListener(\"click\", cancelClickHandler);\n dialog.close();\n },\n\n okClickHandler = function() {\n dialog.removeEventListener(\"close\", closeHandler);\n okBtn.removeEventListener(\"click\", okClickHandler);\n dialog.close();\n\n promise.success(inputEl && inputEl.value);\n };\n\n dialog.addEventListener(\"close\", closeHandler);\n cancelBtn.addEventListener(\"click\", cancelClickHandler);\n okBtn && okBtn.addEventListener(\"click\", okClickHandler);\n\n if (inputEl) {\n inputEl.value = defaultValue;\n }\n messageEl.textContent = message;\n\n dialog.showModal();\n\n return promise;\n }\n });\n};\n","/*globals qq */\n// Base handler for UI (FineUploader mode) events.\n// Some more specific handlers inherit from this one.\nqq.UiEventHandler = function(s, protectedApi) {\n \"use strict\";\n\n var disposer = new qq.DisposeSupport(),\n spec = {\n eventType: \"click\",\n attachTo: null,\n onHandled: function(target, event) {}\n };\n\n // This makes up the \"public\" API methods that will be accessible\n // to instances constructing a base or child handler\n qq.extend(this, {\n addHandler: function(element) {\n addHandler(element);\n },\n\n dispose: function() {\n disposer.dispose();\n }\n });\n\n function addHandler(element) {\n disposer.attach(element, spec.eventType, function(event) {\n // Only in IE: the `event` is a property of the `window`.\n event = event || window.event;\n\n // On older browsers, we must check the `srcElement` instead of the `target`.\n var target = event.target || event.srcElement;\n\n spec.onHandled(target, event);\n });\n }\n\n // These make up the \"protected\" API methods that children of this base handler will utilize.\n qq.extend(protectedApi, {\n getFileIdFromItem: function(item) {\n return item.qqFileId;\n },\n\n getDisposeSupport: function() {\n return disposer;\n }\n });\n\n qq.extend(spec, s);\n\n if (spec.attachTo) {\n addHandler(spec.attachTo);\n }\n};\n","/* global qq */\nqq.FileButtonsClickHandler = function(s) {\n \"use strict\";\n\n var inheritedInternalApi = {},\n spec = {\n templating: null,\n log: function(message, lvl) {},\n onDeleteFile: function(fileId) {},\n onCancel: function(fileId) {},\n onRetry: function(fileId) {},\n onPause: function(fileId) {},\n onContinue: function(fileId) {},\n onGetName: function(fileId) {}\n },\n buttonHandlers = {\n cancel: function(id) { spec.onCancel(id); },\n retry: function(id) { spec.onRetry(id); },\n deleteButton: function(id) { spec.onDeleteFile(id); },\n pause: function(id) { spec.onPause(id); },\n continueButton: function(id) { spec.onContinue(id); }\n };\n\n function examineEvent(target, event) {\n qq.each(buttonHandlers, function(buttonType, handler) {\n var firstLetterCapButtonType = buttonType.charAt(0).toUpperCase() + buttonType.slice(1),\n fileId;\n\n if (spec.templating[\"is\" + firstLetterCapButtonType](target)) {\n fileId = spec.templating.getFileId(target);\n qq.preventDefault(event);\n spec.log(qq.format(\"Detected valid file button click event on file '{}', ID: {}.\", spec.onGetName(fileId), fileId));\n handler(fileId);\n return false;\n }\n });\n }\n\n qq.extend(spec, s);\n\n spec.eventType = \"click\";\n spec.onHandled = examineEvent;\n spec.attachTo = spec.templating.getFileList();\n\n qq.extend(this, new qq.UiEventHandler(spec, inheritedInternalApi));\n};\n","/*globals qq */\n// Child of FilenameEditHandler. Used to detect click events on filename display elements.\nqq.FilenameClickHandler = function(s) {\n \"use strict\";\n\n var inheritedInternalApi = {},\n spec = {\n templating: null,\n log: function(message, lvl) {},\n classes: {\n file: \"qq-upload-file\",\n editNameIcon: \"qq-edit-filename-icon\"\n },\n onGetUploadStatus: function(fileId) {},\n onGetName: function(fileId) {}\n };\n\n qq.extend(spec, s);\n\n // This will be called by the parent handler when a `click` event is received on the list element.\n function examineEvent(target, event) {\n if (spec.templating.isFileName(target) || spec.templating.isEditIcon(target)) {\n var fileId = spec.templating.getFileId(target),\n status = spec.onGetUploadStatus(fileId);\n\n // We only allow users to change filenames of files that have been submitted but not yet uploaded.\n if (status === qq.status.SUBMITTED) {\n spec.log(qq.format(\"Detected valid filename click event on file '{}', ID: {}.\", spec.onGetName(fileId), fileId));\n qq.preventDefault(event);\n\n inheritedInternalApi.handleFilenameEdit(fileId, target, true);\n }\n }\n }\n\n spec.eventType = \"click\";\n spec.onHandled = examineEvent;\n\n qq.extend(this, new qq.FilenameEditHandler(spec, inheritedInternalApi));\n};\n","/*globals qq */\n// Child of FilenameEditHandler. Used to detect focusin events on file edit input elements.\nqq.FilenameInputFocusInHandler = function(s, inheritedInternalApi) {\n \"use strict\";\n\n var spec = {\n templating: null,\n onGetUploadStatus: function(fileId) {},\n log: function(message, lvl) {}\n };\n\n if (!inheritedInternalApi) {\n inheritedInternalApi = {};\n }\n\n // This will be called by the parent handler when a `focusin` event is received on the list element.\n function handleInputFocus(target, event) {\n if (spec.templating.isEditInput(target)) {\n var fileId = spec.templating.getFileId(target),\n status = spec.onGetUploadStatus(fileId);\n\n if (status === qq.status.SUBMITTED) {\n spec.log(qq.format(\"Detected valid filename input focus event on file '{}', ID: {}.\", spec.onGetName(fileId), fileId));\n inheritedInternalApi.handleFilenameEdit(fileId, target);\n }\n }\n }\n\n spec.eventType = \"focusin\";\n spec.onHandled = handleInputFocus;\n\n qq.extend(spec, s);\n qq.extend(this, new qq.FilenameEditHandler(spec, inheritedInternalApi));\n};\n","/*globals qq */\n/**\n * Child of FilenameInputFocusInHandler. Used to detect focus events on file edit input elements. This child module is only\n * needed for UAs that do not support the focusin event. Currently, only Firefox lacks this event.\n *\n * @param spec Overrides for default specifications\n */\nqq.FilenameInputFocusHandler = function(spec) {\n \"use strict\";\n\n spec.eventType = \"focus\";\n spec.attachTo = null;\n\n qq.extend(this, new qq.FilenameInputFocusInHandler(spec, {}));\n};\n","/*globals qq */\n// Handles edit-related events on a file item (FineUploader mode). This is meant to be a parent handler.\n// Children will delegate to this handler when specific edit-related actions are detected.\nqq.FilenameEditHandler = function(s, inheritedInternalApi) {\n \"use strict\";\n\n var spec = {\n templating: null,\n log: function(message, lvl) {},\n onGetUploadStatus: function(fileId) {},\n onGetName: function(fileId) {},\n onSetName: function(fileId, newName) {},\n onEditingStatusChange: function(fileId, isEditing) {}\n };\n\n function getFilenameSansExtension(fileId) {\n var filenameSansExt = spec.onGetName(fileId),\n extIdx = filenameSansExt.lastIndexOf(\".\");\n\n if (extIdx > 0) {\n filenameSansExt = filenameSansExt.substr(0, extIdx);\n }\n\n return filenameSansExt;\n }\n\n function getOriginalExtension(fileId) {\n var origName = spec.onGetName(fileId);\n return qq.getExtension(origName);\n }\n\n // Callback iff the name has been changed\n function handleNameUpdate(newFilenameInputEl, fileId) {\n var newName = newFilenameInputEl.value,\n origExtension;\n\n if (newName !== undefined && qq.trimStr(newName).length > 0) {\n origExtension = getOriginalExtension(fileId);\n\n if (origExtension !== undefined) {\n newName = newName + \".\" + origExtension;\n }\n\n spec.onSetName(fileId, newName);\n }\n\n spec.onEditingStatusChange(fileId, false);\n }\n\n // The name has been updated if the filename edit input loses focus.\n function registerInputBlurHandler(inputEl, fileId) {\n inheritedInternalApi.getDisposeSupport().attach(inputEl, \"blur\", function() {\n handleNameUpdate(inputEl, fileId);\n });\n }\n\n // The name has been updated if the user presses enter.\n function registerInputEnterKeyHandler(inputEl, fileId) {\n inheritedInternalApi.getDisposeSupport().attach(inputEl, \"keyup\", function(event) {\n\n var code = event.keyCode || event.which;\n\n if (code === 13) {\n handleNameUpdate(inputEl, fileId);\n }\n });\n }\n\n qq.extend(spec, s);\n\n spec.attachTo = spec.templating.getFileList();\n\n qq.extend(this, new qq.UiEventHandler(spec, inheritedInternalApi));\n\n qq.extend(inheritedInternalApi, {\n handleFilenameEdit: function(id, target, focusInput) {\n var newFilenameInputEl = spec.templating.getEditInput(id);\n\n spec.onEditingStatusChange(id, true);\n\n newFilenameInputEl.value = getFilenameSansExtension(id);\n\n if (focusInput) {\n newFilenameInputEl.focus();\n }\n\n registerInputBlurHandler(newFilenameInputEl, id);\n registerInputEnterKeyHandler(newFilenameInputEl, id);\n }\n });\n};\n"]}
\ No newline at end of file
+{"version":3,"sources":["?","../client/js/util.js","../client/js/export.js","../client/js/error/error.js","../client/js/version.js","../client/js/features.js","../client/js/promise.js","../client/js/blob-proxy.js","../client/js/button.js","../client/js/upload-data.js","../client/js/uploader.basic.api.js","../client/js/uploader.basic.js","../client/js/ajax.requester.js","../client/js/upload-handler/upload.handler.js","../client/js/upload-handler/upload.handler.controller.js","../client/js/window.receive.message.js","../client/js/upload-handler/form.upload.handler.js","../client/js/upload-handler/xhr.upload.handler.js","../client/js/deletefile.ajax.requester.js","../client/js/image-support/megapix-image.js","../client/js/image-support/image.js","../client/js/image-support/exif.js","../client/js/identify.js","../client/js/image-support/validation.image.js","../client/js/session.js","../client/js/session.ajax.requester.js","../client/js/image-support/scaler.js","../client/js/third-party/ExifRestorer.js","../client/js/total-progress.js","../client/js/paste.js","../client/js/form-support.js","../client/js/traditional/traditional.form.upload.handler.js","../client/js/traditional/traditional.xhr.upload.handler.js","../client/js/traditional/all-chunks-done.ajax.requester.js","../client/js/dnd.js","../client/js/uploader.api.js","../client/js/uploader.js","../client/js/templating.js","../client/js/ui.handler.events.js","../client/js/ui.handler.click.filebuttons.js","../client/js/ui.handler.click.filename.js","../client/js/ui.handler.focusin.filenameinput.js","../client/js/ui.handler.focus.filenameinput.js","../client/js/ui.handler.edit.filename.js"],"names":["global","qq","element","hide","style","display","this","attach","type","fn","addEventListener","attachEvent","detach","removeEventListener","detachEvent","contains","descendant","compareDocumentPosition","insertBefore","elementB","parentNode","remove","removeChild","css","styles","Error","opacity","filter","Math","round","extend","hasClass","name","considerParent","re","RegExp","test","className","addClass","removeClass","replace","getByClass","first","candidates","result","querySelector","querySelectorAll","getElementsByTagName","each","idx","val","push","getFirstByClass","children","child","firstChild","nodeType","nextSibling","setText","text","innerText","textContent","clearText","hasAttribute","attrName","attrVal","exec","getAttribute","undefined","canvasToBlob","canvas","mime","quality","dataUriToBlob","toDataURL","dataUri","arrayBuffer","byteString","intArray","mimeString","createBlob","data","BlobBuilder","window","WebKitBlobBuilder","MozBlobBuilder","MSBlobBuilder","blobBuilder","append","getBlob","Blob","split","indexOf","atob","decodeURI","ArrayBuffer","length","Uint8Array","character","charCodeAt","log","message","level","console","isObject","variable","Object","prototype","toString","call","isFunction","isArray","value","buffer","constructor","isItemList","maybeItemList","isNodeList","maybeNodeList","item","namedItem","isString","maybeString","trimStr","string","String","trim","format","str","args","Array","slice","arguments","newStr","nextIdxToReplace","substring","isFile","maybeFile","File","isFileList","maybeFileList","FileList","isFileOrInput","maybeFileOrInput","isInput","maybeInput","notFile","evaluateType","normalizedType","toLowerCase","HTMLInputElement","tagName","isBlob","maybeBlob","isXhrUploadSupported","input","document","createElement","multiple","FormData","createXhrInstance","upload","XMLHttpRequest","ActiveXObject","error","isFolderDropSupported","dataTransfer","items","webkitGetAsEntry","isFileChunkingSupported","androidStock","webkitSlice","mozSlice","sliceBlob","fileOrBlob","start","end","arrayBufferToHex","bytesAsHex","bytes","byt","byteAsHexStr","readBlobToHex","blob","startOffset","initialBlob","fileReader","FileReader","promise","Promise","onload","success","onerror","failure","readAsArrayBuffer","second","extendNested","prop","override","target","sourceFn","super_","source","srcPropName","srcPropVal","arr","elt","from","len","hasOwnProperty","getUniqueId","c","r","random","ie","navigator","userAgent","ie7","ie8","ie10","ie11","edge","safari","vendor","chrome","opera","firefox","windows","platform","android","ios6","ios","ios7","ios8","ios800","iosChrome","iosSafari","iosSafariWebView","preventDefault","e","returnValue","toElement","div","html","innerHTML","iterableItem","callback","keyOrIndex","retVal","Storage","key","getItem","charAt","bind","oldFunc","context","newArgs","concat","apply","obj2url","obj","temp","prefixDone","uristrings","prefix","add","nextObj","i","nextTemp","encodeURIComponent","join","obj2FormData","formData","arrayKeyName","obj2Inputs","form","setAttribute","appendChild","parseJson","json","JSON","parse","eval","getExtension","filename","extIdx","lastIndexOf","substr","getFilename","blobOrFileInput","fileName","DisposeSupport","disposers","dispose","disposer","shift","addDisposer","disposeFunction","define","amd","module","exports","version","supportedFeatures","testSupportsFileInputElement","tempInput","supported","disabled","ex","isChrome14OrHigher","match","isCrossOriginXhrSupported","withCredentials","isXdrSupported","XDomainRequest","isCrossOriginAjaxSupported","isFolderSelectionSupported","webkitdirectory","isLocalStorageSupported","localStorage","setItem","isDragAndDropSupported","span","supportsUploading","supportsUploadingBlobs","supportsFileDrop","supportsAjaxFileUploading","supportsFolderDrop","supportsChunking","supportsResume","supportsUploadViaPaste","supportsUploadCors","supportsDeleteFileXdr","supportsDeleteFileCorsXhr","supportsDeleteFileCors","supportsFolderSelection","supportsImagePreviews","supportsUploadProgress","postMessage","ajaxUploading","blobUploading","canDetermineSize","chunking","deleteFileCors","deleteFileCorsXdr","deleteFileCorsXhr","dialogElement","HTMLDialogElement","fileDrop","folderDrop","folderSelection","imagePreviews","imageValidation","itemSizeValidation","pause","progressBar","resume","scaling","tiffPreviews","unlimitedScaledImageSize","uploading","uploadCors","uploadCustomHeaders","uploadNonMultipart","uploadViaPaste","isGenericPromise","maybePromise","then","successArgs","failureArgs","successCallbacks","failureCallbacks","doneCallbacks","state","onSuccess","onFailure","done","BlobProxy","referenceBlob","onCreate","create","UploadButton","o","createInput","BUTTON_ID_ATTR_NAME","buttonId","options","title","self","setMultiple","folders","acceptFiles","position","right","top","fontFamily","fontSize","margin","padding","cursor","height","disposeSupport","onChange","hoverClass","focusClass","ios8BrowserCrashWorkaround","overflow","direction","getInput","getButtonId","isMultiple","optInput","removeAttribute","setAcceptFiles","reset","UploadData","uploaderProxy","getDataByIds","idOrIds","entries","id","getDataByUuids","uuids","uuid","byUuid","getDataByStatus","status","statusResults","statuses","index","statusEnum","statusResultIndexes","byStatus","dataIndex","byProxyGroupId","byBatchId","addFile","spec","SUBMITTING","originalName","size","file","batchId","proxyGroupId","onBeforeStatusChange","onStatusChange","retrieve","optionalFilter","removeFileRef","record","setStatus","newStatus","oldStatus","byStatusOldStatusIndex","splice","uuidChanged","newUuid","oldUuid","updateName","newName","updateSize","newSize","setParentId","targetId","parentId","getIdsInProxyGroup","getIdsInBatch","SUBMITTED","REJECTED","QUEUED","CANCELED","PAUSED","UPLOADING","UPLOAD_FINALIZING","UPLOAD_RETRYING","UPLOAD_SUCCESSFUL","UPLOAD_FAILED","DELETE_FAILED","DELETING","DELETED","basePublicApi","addBlobs","blobDataOrArray","params","endpoint","addFiles","addInitialFiles","cannedFileList","cannedFile","_addCannedFile","_maybeHandleIos8SafariWorkaround","_storedIds","_currentBatchId","processBlob","_handleNewFile","_options","blobs","defaultName","verifiedFiles","processBlobData","blobData","processCanvas","processCanvasData","canvasData","normalizedQuality","processFileOrInput","fileOrInput","files","normalizeData","fileContainer","_prepareItemsForUpload","cancel","uploadData","_uploadData","getName","_handler","cancelAll","storedIdsCopy","storedFileId","clearStoredFiles","continueUpload","enabled","_uploadFile","deleteFile","_onSubmitDelete","doesExist","fileOrBlobId","isValid","drawThumbnail","fileId","imgOrCanvas","maxSize","fromServer","customResizeFunction","fileOrUrl","promiseToReturn","_imageGenerator","_thumbnailUrls","scale","getFile","container","generate","modifiedContainer","reason","getButton","_getButton","_buttonIdsForFileIds","getEndpoint","_endpointStore","get","uploadDataRecord","getInProgress","getParentId","uploadDataEntry","getUploads","getResumableFilesData","getSize","getNetUploads","_netUploaded","getRemainingAllowedItems","allowedItems","_currentItemLimit","_netUploadedOrQueued","getUuid","isResumable","hasResumeRecord","debug","pauseUpload","expunge","_autoRetries","_retryTimeouts","_preventRetries","_buttons","button","_paramsStore","_pasteHandler","session","refreshOnReset","_refreshSessionData","_succeededSinceLastAllComplete","_failedSinceLastAllComplete","_totalProgress","_customResumeDataStore","retry","_manualRetry","scaleImage","specs","Scaler","setCustomHeaders","headers","_customHeadersStore","set","setCustomResumeData","setDeleteFileCustomHeaders","_deleteFileCustomHeadersStore","setDeleteFileEndpoint","_deleteFileEndpointStore","setDeleteFileParams","_deleteFileParamsStore","setEndpoint","setForm","elementOrId","_updateFormSupportAndParams","setItemLimit","newItemLimit","setName","setParams","setUuid","_onDeleteComplete","errorMessage","uploadStoredFiles","_itemError","_uploadStoredFiles","basePrivateApi","sessionData","deleteFileEndpoint","deleteFileParams","thumbnailUrl","_annotateWithButtonId","associatedInput","qqButtonId","_getButtonId","_batchError","callbacks","onError","_createDeleteHandler","DeleteFileAjaxRequester","method","toUpperCase","maxConnections","uuidParamName","request","uuidName","customHeaders","paramsStore","endpointStore","cors","onDelete","_onDelete","onDeleteComplete","xhrOrXdr","isError","_createPasteHandler","PasteSupport","targetElement","paste","pasteReceived","_handleCheckedCallback","onPasteReceived","_handlePasteSuccess","identifier","_createStore","initialValue","_readOnlyValues_","store","catchall","perIdReadOnlyValues","readOnlyValues","copy","orig","getReadOnlyValues","includeReadOnlyValues","existing","values","addReadOnly","_createUploadDataTracker","_onUploadStatusChange","_maybeAllComplete","setTimeout","_createUploadButton","allowMultiple","workarounds","iosEmptyVideos","_isAllowedExtension","allowedExtensions","accept","validation","classes","buttonFocus","buttonHover","ios8BrowserCrash","inputName","_onInputChange","fileInputTitle","_disposeSupport","_createUploadHandler","additionalOptions","namespace","lastOnProgress","preventRetryParam","preventRetryResponseProperty","onProgress","loaded","total","_onProgress","onComplete","xhr","_onComplete","onCancel","cancelFinalizationEffort","_onCancel","onUploadPrep","_onUploadPrep","onUpload","_onUpload","onUploadResult","onUploadChunk","chunkData","_onUploadChunk","onUploadChunkResult","partIndex","onUploadChunkSuccess","_onUploadChunkSuccess","onResume","customResumeData","onAutoRetry","responseJSON","_onAutoRetry","onUuidChanged","setSize","_setSize","getDataByUuid","isQueued","isInProgress","getCustomResumeData","_getCustomResumeData","UploadHandlerController","_fileOrBlobRejected","_formatSize","sizeSymbols","max","toFixed","_generateExtraButtonSpecs","_extraButtonSpecs","extraButtons","extraButtonOptionEntry","extraButtonSpec","_initExtraButton","extraButtonsSpec","_defaultButtonId","buttonOrFileInputOrFile","inputs","fileInput","fileBlobOrInput","_getNotFinished","_getValidationBase","_getValidationDescriptor","fileWrapper","_getValidationDescriptors","fileWrappers","fileDescriptors","_handleCameraAccess","camera","optionRoot","details","callbackRetVal","successParam","newFileWrapperList","actualFile","handler","_customNewFileHandler","_handleNewFileGeneric","addFileToHandler","_trackButton","fileList","extSuppliedName","extension","_handleDeleteSuccess","_handleDeleteFailed","_initFormSupportAndParams","_formSupport","FormSupport","attachedToForm","getFormInputsAsObject","autoUpload","newAutoUpload","newEndpoint","_isDeletePossible","expected","allowXdr","allowed","valid","allowedExt","extRegex","code","maybeNameOrNames","replacement","extensionsForMessage","placeholderMatch","messages","names","validationBase","allowedExtension","formatFileName","sizeLimit","minSizeLimit","placeholder","_onBeforeManualRetry","notFinished","_onAllComplete","ios8SafariUploads","alert","unsupportedBrowserIos8Safari","_maybeParseAndSendUploadError","response","errorReason","defaultResponseError","_maybeProcessNextItemAfterOnValidateCallback","validItem","stopOnFirstInvalidFile","validationDescriptor","onValidate","_onValidateCallbackSuccess","_onValidateCallbackFailure","successful","failed","onAllComplete","_shouldAutoRetry","retryWaitPeriod","autoAttemptDelay","_onBeforeAutoRetry","itemLimit","onManualRetry","clearTimeout","storedItemIndex","fileIndex","onIndividualProgress","_onSubmit","_onSubmitCallbackSuccess","_onSubmitted","onSubmitted","_storeForLater","onSuccessCallback","additionalMandatedParams","adjustedOnSuccessCallback","onSubmitDelete","_deleteHandler","sendDelete","_onTotalProgress","onTotalProgress","enableAuto","_onValidateBatchCallbackFailure","_onValidateBatchCallbackSuccess","validationDescriptors","proposedNetFilesUploadedOrQueued","tooManyItemsError","nextIndex","_validateFileOrBlobData","_upload","onValidateBatch","_preventLeaveInProgress","event","onLeave","Session","_session","addFileRecord","refresh","_sessionRequestComplete","onSessionRequestComplete","onNewSize","maxAutoAttempts","formElementOrId","onSubmit","idToUpload","stillSubmitting","validityChecker","allowEmpty","ImageValidation","validate","image","errorCode","_wrapCallbacks","safeCallback","errorMsg","exception","callbackName","callbackFunc","FineUploaderBasic","disableCancelForFormUploads","warnBeforeUnload","filenameParam","forceMultipart","omitDefaultParams","paramsInBody","requireSuccessJson","totalFileSizeName","maxHeight","maxWidth","minHeight","minWidth","maybeXhr","maybeXhrOrXdr","attemptNumber","fileOrBlobData","typeError","sizeError","minSizeError","emptyError","noFilesError","maxHeightImageError","maxWidthImageError","minHeightImageError","minWidthImageError","retryFailTooManyItems","concurrent","mandatory","paramNames","partByteOffset","chunkSize","totalFileSize","totalParts","partSize","jsonPayload","resetOnStatus","recordsExpireIn","resuming","customKeys","fileOrBlobName","sendCredentials","interceptSubmit","customResizer","sendOriginal","orient","defaultType","defaultQuality","failureText","includeExif","sizes","ImageGenerator","_scaler","handleNewFile","TotalProgress","entry","AjaxRequester","isSimpleMethod","containsNonSimpleHeaders","containsNonSimple","header","isXdr","getCorsAjaxTransport","ontimeout","onprogress","getXhrOrXdr","suppliedXhr","requestData","dequeue","nextId","queue","sendRequest","xdrError","isResponseSuccessful","getParams","onDemandParams","additionalParams","mandatedParams","optXhr","url","payload","onSend","createUrl","additionalQueryParams","getXdrLoadHandler","getXdrErrorHandler","onreadystatechange","getXhrReadyStateChangeHandler","registerForUploadProgress","open","setHeaders","send","shouldParamsBeInQueryString","contentType","stringify","addToPath","readyState","lengthComputable","onDemandHeaders","additionalHeaders","allHeaders","acceptHeader","setRequestHeader","allowXRequestedWithAndCacheControl","responseCode","successfulResponseCodes","prepareToSend","validMethods","DELETE","PATCH","POST","PUT","GET","initTransport","path","cacheBuster","withPath","appendToPath","withParams","withQueryParams","_additionalQueryParams_","withHeaders","withPayload","thePayload","withCacheBuster","qqtimestamp","Date","getTime","canceled","UploadHandler","proxy","fileState","fileItem","getThirdPartyFileId","_getFileState","_setThirdPartyFileId","thirdPartyFileId","_wasCanceled","preventRetryResponse","controller","chunkingPossible","concurrentChunkingPossible","chunked","chunkIdx","_getChunkData","attemptingResume","chunkProgress","_getChunkDataForCallback","finalize","finalizeChunks","normaizedResponse","normalizeResponse","_maybeDeletePersistedChunkData","cleanup","normalizedResponse","handleFailure","clearCachedChunk","inProgressIdx","responseToReport","inProgressChunksArray","inProgress","remaining","unshift","ignoreFailure","keys","_getXhrs","ckid","ckXhr","abort","_cancelled","moveInProgressToRemaining","connectionManager","free","hasMoreParts","nextPart","nextIdx","_getTotalChunks","reevaluateChunking","sendNext","inProgressChunks","available","requestOverrides","uploadChunkData","overrides","uploadChunk","inProgressChunkIdx","_maybePersistChunkedState","clearXhr","_open","_openChunks","_waiting","openChunkEntriesCount","openChunksCount","openChunkIndexes","dontAllowNext","allowNext","waitingIndex","connectionsIndex","getProxyOrBlob","getWaitingOrConnected","waitingOrConnected","chunks","parseInt","isUsingConnection","pop","openChunksEntry","simple","uploadFile","maybeNewUuid","_clearXhrs","getProxy","initHandler","traditional","onFinalizing","_removeExpiredChunkingRecords","isDeferredEligibleForUpload","maybeDefer","generatedBlob","updateBlob","maybeSendDeferredFiles","errorResponse","idsInGroup","uploadedThisId","idInGroup","now","originalResponse","_shouldChunkThisFile","blobToUpload","cancelRetVal","isProxied","_getLocalStorageId","isAttemptingResume","WindowReceiveMessage","callbackWrapperDetachers","receiveMessage","onMessageCallbackWrapper","stopReceivingMessages","detacher","FormUploadHandler","expungeFile","detachLoadEvents","isCors","postMessageCallbackTimers","corsMessageReceiver","iframe","getElementById","_getIframeName","getFileIdForIframeName","iframeName","initIframeForUpload","body","registerPostMessageCallback","onloadCallbacks","onloadCallback","_parseJsonResponse","_detachLoadEvent","formHandlerInstanceId","_attachLoadEvent","responseDescriptor","contentDocument","_createIframe","_initFormForUpload","targetName","innerHtmlOrMessage","XhrUploadHandler","xhrId","ajaxRequester","_getAjaxRequester","getChunkSize","chunkFiles","resumeEnabled","blobOrProxy","_initTempState","_maybePrepareForResume","cachedChunks","tempState","xhrs","ajaxRequesters","responseParser","lastChunkIdx","_getXhr","resumableFilesData","_iterateResumeRecords","notResumable","optInProgress","optRemaining","chunkingState","reverse","paused","totalChunks","parts","newBlob","chunkId","_createXhr","optChunkIdx","_registerXhr","chunkIndex","fileSize","startBytes","endBytes","part","count","startByte","endByte","localStorageId","forEach","_getMimeType","_getPersistableData","ceil","_markNotResumable","removeItem","persistedData","lastUpdated","_registerProgressHandler","progressCalculator","totalSuccessfullyLoadedForFile","loadedForRequest","totalForRequest","estActualChunkLoaded","totalLoadedForFile","chunkLoaded","optAjaxRequester","xhrsId","expirationDays","expirationDate","setDate","getDate","getMandatedParams","_method","requester","detectSubsampling","img","ctx","iw","naturalWidth","ih","naturalHeight","width","getContext","drawImage","getImageData","detectVerticalSquash","alpha","ratio","sy","ey","py","renderImageToDataURL","doSquash","renderImageToCanvas","maybeCalculateDownsampledDimensions","origHeight","origWidth","newHeight","sqrt","newWidth","modifiedDimensions","save","resize","renderImageToCanvasWithCustomResizer","imageHeight","imageWidth","orientation","targetHeight","targetWidth","transformCoordinate","tmpCtx","sx","dx","d","tmpCanvas","vertSquashRatio","dw","dh","dy","clearRect","restore","qqImageRendered","resizeInfo","sourceCanvas","sourceCanvasContext","targetCanvas","translate","rotate","PI","MegaPixImage","srcImage","errorCallback","Image","URL","createObjectURL","webkitURL","src","listeners","imageLoadListeners","render","opt","imgWidth","imgHeight","optionsKey","optionsValue","oldTargetSrc","onrender","isImg","el","isCanvas","isImgCorsSupported","crossOrigin","isCanvasSupported","determineMimeOfFileName","nameWithPath","pathSegments","isCrossOrigin","targetProtocol","targetHostname","targetPort","targetAnchor","href","protocol","port","hostname","location","registerImgLoadListeners","registerCanvasDrawImageListener","registerThumbnailRenderedListener","registered","draw","drawPreview","Identify","megapixErrorHandler","isPreviewable","dummyExif","exif","Exif","mpImg","Orientation","failureMsg","drawOnCanvasOrImgFromUrl","canvasOrImg","tempImg","tempImgRender","drawOnImgFromUrlWithCssScaling","drawFromUrl","fileBlobOrUrl","_testing","parseLittleEndian","hex","pow","seekToApp1","offset","theOffset","thePromise","segmentLength","getApp1Offset","isLittleEndian","app1Start","getDirEntryCount","littleEndian","getIfd","dirEntries","getDirEntries","ifdHex","getTagValues","tagsToFind","TAG_IDS","vals","tagValHex","tagValLength","idHex","tagsToFindIdx","TAG_INFO","274","parser","onParseFailure","app1Offset","dirEntryCount","tagValues","isIdentifiable","magicBytes","questionableBytes","identifiable","magicBytesEntries","magicBytesArrayEntry","previewable","isPreviewableSync","PREVIEWABLE_MIME_TYPES","fileMime","isRecognizedImage","image/jpeg","image/gif","image/png","image/bmp","image/tiff","hasNonZeroLimits","limits","atLeastOne","limit","getWidthHeight","sizeDetermination","getFailingLimit","dimensions","failingLimit","limitName","limitValue","limitMatcher","dimensionPropName","actualValue","validationEffort","isJsonResponseValid","handleFileItems","fileItems","someItemsIgnored","err","refreshEffort","refreshCompleteCallback","requesterOptions","SessionAjaxRequester","queryServer","responseText","includeOriginal","failedToScaleText","_getSortedSizes","getFileRecords","originalFileUuid","originalFileName","originalBlobOrBlobData","records","originalBlob","sizeRecord","outputType","_determineOutputType","requestedType","refType","_getName","_generateScaledImage","failedText","api","scaledIds","originalId","blobSize","scaledId","qqparentuuid","qqparentsize","param","scalingEffort","scalingOptions","scaler","referenceType","scaledVersionProperties","startOfExt","versionType","scaledName","scaledExt","nameAppendage","sort","a","b","sourceFile","imageGenerator","scaledImageDataUri","signalSuccess","_insertExifHeader","scaledImageDataUriWithExif","originalImage","reader","insertionEffort","originalImageDataUri","ExifRestorer","readAsDataURL","_dataUriToBlob","_createBlob","KEY_STR","encode64","chr1","chr2","enc1","enc2","enc3","output","chr3","enc4","isNaN","origFileBase64","resizedFileBase64","rawImage","decode64","segments","slice2Segments","exifManipulation","exifArray","getExifArray","newImageArray","insertExif","seg","x","imageData","buf","separatePoint","mae","ato","array","rawImageArray","head","endPoint","perFileProgress","totalLoaded","totalSize","lastLoadedSent","lastTotalSent","callbackProxy","noRetryableFiles","retryable","none","failedId","updateTotalProgress","onNew","newLoaded","newTotal","oldLoaded","oldTotal","isImage","registerPasteHandler","detachPasteHandler","clipboardData","getAsFile","unregisterPasteHandler","startUpload","determineNewEndpoint","formEl","validateForm","nativeSubmit","checkValidity","maybeUploadOnSubmit","submit","determineFormEl","_form2Obj","notIrrelevantType","irrelevantTypes","radioOrCheckbox","ignoreValue","checked","selectValue","select","selected","elements","getIframeContentJson","doc","innerHtml","contentWindow","nodeValue","createForm","responseFromMessage","multipart","addChunkingSpecificParams","allChunksDoneRequester","AllChunksDoneAjaxRequester","createReadyStateChangedHandler","onUploadOrChunkComplete","getChunksCompleteParams","isErrorUploadResponse","parseResponse","sendChunksCompleteRequest","complete","setParamsAndGetEntityToSend","entityToSendParams","xhrOverrides","customParams","defaultParams","xhrOverrideParams","setUploadHeaders","headersOptions","headerOverrides","headerName","headerValue","extraHeaders","uploadChunkParams","toSend","promises","endpointHandler","DragAndDrop","uploadDroppedFiles","uploadDropZone","filesAsArray","dropLog","dropDisabled","processingDroppedFilesComplete","getElement","traverseFileTree","parseEntryPromise","qqPath","extractDirectoryPath","droppedFiles","fileError","fullPath","isDirectory","getFilesInDirectory","entriesLeft","indexOfNameInFullPath","accumEntries","existingPromise","dirReader","createReader","readEntries","newEntries","handleDataTransfer","pendingFolderPromises","handleDataTransferPromise","processingDroppedFiles","allowMultipleItems","dropError","setupDropzone","dropArea","dropZone","UploadDropZone","HIDE_ZONES_EVENT_NAME","onEnter","dropActive","stopPropagation","onLeaveNotDescendants","onDrop","uploadDropZones","isFileDrag","dragEvent","fileDrag","types","leavingDocumentOut","y","setupDragDrop","dropZones","dropZoneElements","maybeHideDropZones","HTMLElement","setupExtraDropzone","removeDropzone","dzs","targetEl","errorSpecifics","dragoverShouldBeCanceled","disableDropOutside","dropOutsideDisabled","dropEffect","isValidFileDrag","effectTest","dt","isSafari","effectAllowed","includes","isOrSetDropDisabled","isDisabled","preventDrop","triggerHidezonesEvent","triggerUsingOldApi","hideZonesEvent","createEvent","initEvent","CustomEvent","dispatchEvent","attachEvents","effect","relatedTarget","elementFromPoint","clientX","clientY","uiPublicApi","_parent","_templating","addCacheToDom","clearFiles","addExtraDropzone","_dnd","removeExtraDropzone","getItemByFileId","isHiddenForever","getFileContainer","_setupDragAndDrop","_totalFilesInBatch","_filesInBatchAddedToUi","_setupClickAndEditEventHandlers","formattedFilename","updateFilename","uploadPaused","continued","uploadContinued","getId","fileContainerOrChildEl","getFileId","getDropTarget","qqDropTarget","uiPrivateApi","_removeFileItem","removeFile","_fileButtonsClickHandler","FileButtonsClickHandler","_bindFileButtonsClickEvent","_focusinEventSupported","_isEditFilenameEnabled","_filenameClickHandler","_bindFilenameClickEvent","_filenameInputFocusInHandler","_bindFilenameInputFocusInEvent","_filenameInputFocusHandler","_bindFilenameInputFocusEvent","dragAndDrop","extraDropzones","templating","defaultDropZone","getDropZone","showDropProcessing","hideDropProcessing","errorData","lvl","onDeleteFile","onRetry","onPause","onContinue","onGetName","isEditFilenamePossible","FilenameClickHandler","FilenameInputFocusHandler","_filenameEditHandler","onGetUploadStatus","onSetName","onEditingStatusChange","isEditing","qqInput","getEditInput","qqFileContainer","hideFilename","hideEditIcon","showFilename","showEditIcon","markFilenameEditable","hideRetry","setStatusText","_classes","retrying","hidePause","FilenameInputFocusInHandler","hideSpinner","resetTotalProgress","reportDirectoryPaths","qqpath","_addToList","addHandler","updateProgress","hideCancel","hideProgress","waitingForResponse","_displayFileSize","completeUpload","_markFileAsSuccessful","fail","showCancel","isRetryPossible","showRetry","_controlFailureTextDisplay","parentRetVal","newResult","showDeleteButton","_maybeUpdateThumbnail","showSpinner","allowPause","retryNumForDisplay","maxAuto","retryNote","_showCancelLink","showAutoRetryNote","autoRetryNote","resetProgress","_onSubmitDeleteSuccess","forceConfirm","_showDeleteConfirm","_sendDeleteRequest","deletingFailedText","hideDeleteButton","deletingStatusText","confirmMessage","deleteRequestArgs","showConfirm","canned","prependData","prependIndex","dontDisplay","hideScaled","prependFiles","disableCancel","_handledProxyGroup","_clearList","addFileToCache","updateThumbnail","thumbnails","generatePreview","fileSizeOnSubmit","loadedSize","sizeForDisplay","_formatProgress","uploadedSize","formatProgress","mode","responseProperty","failureReason","failedUploadTextDisplay","failUpload","enableTooltip","_showTooltip","showMessage","_setupPastePrompt","namePromptMessage","defaultVal","showPrompt","placeholders","waitUntilResponse","FineUploader","listElement","template","editable","tooManyFilesError","unsupportedBrowser","promptForName","maxCount","notAvailablePath","waitingPath","timeBetweenThumbs","hasDialog","showDialog","confirm","defaultValue","prompt","Templating","templateIdOrEl","containerEl","fileContainerEl","maxThumbs","waitUntilUpdate","thumbnailNotAvailable","waitingForThumbnail","renderFailure","isEditElementsExist","isRetryElementExist","templateDom","showThumbnails","serverScale","fileBatch","content","createDocumentFragment","map","isCancelDisabled","generatedThumbnails","thumbnailQueueMonitorRunning","thumbGenerationQueue","thumbnailMaxSize","selectorClasses","alertDialog","dialogCancelButton","confirmDialog","dialogMessage","dialogOkButton","promptDialog","uploader","drop","list","progressBarContainer","totalProgressBarContainer","totalProgressBar","spinner","continueButton","deleteButton","statusText","editFilenameInput","editNameIcon","dropText","dropProcessing","dropProcessingSpinner","thumbnail","previewGeneration","cachedThumbnailNotAvailableImg","cachedWaitingForThumbnailImg","cacheThumbnailPlaceholders","notAvailableUrl","waitingUrl","updatedImg","displayWaitingImg","waitingImgPlacement","maybeScalePlaceholderViaCss","show","generateNewPreview","getThumbnail","qqThumbnailId","maybeSetDisplayNotAvailableImg","generateNextQueuedPreview","queuedThumbRequest","update","processUpdateQueuedPreviewRequest","processNewQueuedPreviewRequest","getCancel","getTemplateEl","getContinue","getDialog","getDelete","getDropProcessing","getEditIcon","getPause","getProgress","getRetry","getSpinner","cssClass","previewing","notAvailableImgPlacement","parseAndGetTemplate","scriptEl","scriptHtml","fileListNode","tempTemplateEl","fileListEl","defaultButton","dropTextEl","uploaderEl","cloneNode","fileTemplate","prependFile","parentEl","beforeEl","optFileOrBlob","relatedThumbnailId","useCachedPreview","showWaitingImg","setProgressBarWidth","percent","bar","progressBarSelector","targetThumbnailId","cachedThumbnailId","targetThumbnail","cachedThumbnail","hideTotalProgress","cantRenderEl","prependInfo","hideForever","batch","thumb","fileEl","fileNameEl","waitingImg","currentNode","getFileList","filenameEl","isFileName","icon","isEditIcon","isEditInput","isCancel","allowContinueButton","isPause","isContinueButton","isDeleteButton","isRetry","textEl","dialog","messageEl","inputEl","cancelBtn","okBtn","closeHandler","cancelClickHandler","okClickHandler","close","showModal","UiEventHandler","s","protectedApi","eventType","srcElement","onHandled","attachTo","getFileIdFromItem","qqFileId","getDisposeSupport","examineEvent","buttonHandlers","buttonType","firstLetterCapButtonType","inheritedInternalApi","handleFilenameEdit","FilenameEditHandler","handleInputFocus","getFilenameSansExtension","filenameSansExt","getOriginalExtension","origName","handleNameUpdate","newFilenameInputEl","origExtension","registerInputBlurHandler","registerInputEnterKeyHandler","keyCode","which","focusInput","focus"],"mappings":"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","file":"fine-uploader.min.js","sourcesContent":[null,"/*globals window, navigator, document, FormData, File, HTMLInputElement, XMLHttpRequest, Blob, Storage, ActiveXObject */\n/* jshint -W079 */\nvar qq = function(element) {\n \"use strict\";\n\n return {\n hide: function() {\n element.style.display = \"none\";\n return this;\n },\n\n /** Returns the function which detaches attached event */\n attach: function(type, fn) {\n if (element.addEventListener) {\n element.addEventListener(type, fn, false);\n } else if (element.attachEvent) {\n element.attachEvent(\"on\" + type, fn);\n }\n return function() {\n qq(element).detach(type, fn);\n };\n },\n\n detach: function(type, fn) {\n if (element.removeEventListener) {\n element.removeEventListener(type, fn, false);\n } else if (element.attachEvent) {\n element.detachEvent(\"on\" + type, fn);\n }\n return this;\n },\n\n contains: function(descendant) {\n // The [W3C spec](http://www.w3.org/TR/domcore/#dom-node-contains)\n // says a `null` (or ostensibly `undefined`) parameter\n // passed into `Node.contains` should result in a false return value.\n // IE7 throws an exception if the parameter is `undefined` though.\n if (!descendant) {\n return false;\n }\n\n // compareposition returns false in this case\n if (element === descendant) {\n return true;\n }\n\n if (element.contains) {\n return element.contains(descendant);\n } else {\n /*jslint bitwise: true*/\n return !!(descendant.compareDocumentPosition(element) & 8);\n }\n },\n\n /**\n * Insert this element before elementB.\n */\n insertBefore: function(elementB) {\n elementB.parentNode.insertBefore(element, elementB);\n return this;\n },\n\n remove: function() {\n element.parentNode.removeChild(element);\n return this;\n },\n\n /**\n * Sets styles for an element.\n * Fixes opacity in IE6-8.\n */\n css: function(styles) {\n /*jshint eqnull: true*/\n if (element.style == null) {\n throw new qq.Error(\"Can't apply style to node as it is not on the HTMLElement prototype chain!\");\n }\n\n /*jshint -W116*/\n if (styles.opacity != null) {\n if (typeof element.style.opacity !== \"string\" && typeof (element.filters) !== \"undefined\") {\n styles.filter = \"alpha(opacity=\" + Math.round(100 * styles.opacity) + \")\";\n }\n }\n qq.extend(element.style, styles);\n\n return this;\n },\n\n hasClass: function(name, considerParent) {\n var re = new RegExp(\"(^| )\" + name + \"( |$)\");\n return re.test(element.className) || !!(considerParent && re.test(element.parentNode.className));\n },\n\n addClass: function(name) {\n if (!qq(element).hasClass(name)) {\n element.className += \" \" + name;\n }\n return this;\n },\n\n removeClass: function(name) {\n var re = new RegExp(\"(^| )\" + name + \"( |$)\");\n element.className = element.className.replace(re, \" \").replace(/^\\s+|\\s+$/g, \"\");\n return this;\n },\n\n getByClass: function(className, first) {\n var candidates,\n result = [];\n\n if (first && element.querySelector) {\n return element.querySelector(\".\" + className);\n }\n else if (element.querySelectorAll) {\n return element.querySelectorAll(\".\" + className);\n }\n\n candidates = element.getElementsByTagName(\"*\");\n\n qq.each(candidates, function(idx, val) {\n if (qq(val).hasClass(className)) {\n result.push(val);\n }\n });\n return first ? result[0] : result;\n },\n\n getFirstByClass: function(className) {\n return qq(element).getByClass(className, true);\n },\n\n children: function() {\n var children = [],\n child = element.firstChild;\n\n while (child) {\n if (child.nodeType === 1) {\n children.push(child);\n }\n child = child.nextSibling;\n }\n\n return children;\n },\n\n setText: function(text) {\n element.innerText = text;\n element.textContent = text;\n return this;\n },\n\n clearText: function() {\n return qq(element).setText(\"\");\n },\n\n // Returns true if the attribute exists on the element\n // AND the value of the attribute is NOT \"false\" (case-insensitive)\n hasAttribute: function(attrName) {\n var attrVal;\n\n if (element.hasAttribute) {\n\n if (!element.hasAttribute(attrName)) {\n return false;\n }\n\n /*jshint -W116*/\n return (/^false$/i).exec(element.getAttribute(attrName)) == null;\n }\n else {\n attrVal = element[attrName];\n\n if (attrVal === undefined) {\n return false;\n }\n\n /*jshint -W116*/\n return (/^false$/i).exec(attrVal) == null;\n }\n }\n };\n};\n\n(function() {\n \"use strict\";\n\n qq.canvasToBlob = function(canvas, mime, quality) {\n return qq.dataUriToBlob(canvas.toDataURL(mime, quality));\n };\n\n qq.dataUriToBlob = function(dataUri) {\n var arrayBuffer, byteString,\n createBlob = function(data, mime) {\n var BlobBuilder = window.BlobBuilder ||\n window.WebKitBlobBuilder ||\n window.MozBlobBuilder ||\n window.MSBlobBuilder,\n blobBuilder = BlobBuilder && new BlobBuilder();\n\n if (blobBuilder) {\n blobBuilder.append(data);\n return blobBuilder.getBlob(mime);\n }\n else {\n return new Blob([data], {type: mime});\n }\n },\n intArray, mimeString;\n\n // convert base64 to raw binary data held in a string\n if (dataUri.split(\",\")[0].indexOf(\"base64\") >= 0) {\n byteString = atob(dataUri.split(\",\")[1]);\n }\n else {\n byteString = decodeURI(dataUri.split(\",\")[1]);\n }\n\n // extract the MIME\n mimeString = dataUri.split(\",\")[0]\n .split(\":\")[1]\n .split(\";\")[0];\n\n // write the bytes of the binary string to an ArrayBuffer\n arrayBuffer = new ArrayBuffer(byteString.length);\n intArray = new Uint8Array(arrayBuffer);\n qq.each(byteString, function(idx, character) {\n intArray[idx] = character.charCodeAt(0);\n });\n\n return createBlob(arrayBuffer, mimeString);\n };\n\n qq.log = function(message, level) {\n if (window.console) {\n if (!level || level === \"info\") {\n window.console.log(message);\n }\n else\n {\n if (window.console[level]) {\n window.console[level](message);\n }\n else {\n window.console.log(\"<\" + level + \"> \" + message);\n }\n }\n }\n };\n\n qq.isObject = function(variable) {\n return variable && !variable.nodeType && Object.prototype.toString.call(variable) === \"[object Object]\";\n };\n\n qq.isFunction = function(variable) {\n return typeof (variable) === \"function\";\n };\n\n /**\n * Check the type of a value. Is it an \"array\"?\n *\n * @param value value to test.\n * @returns true if the value is an array or associated with an `ArrayBuffer`\n */\n qq.isArray = function(value) {\n return Object.prototype.toString.call(value) === \"[object Array]\" ||\n (value && window.ArrayBuffer && value.buffer && value.buffer.constructor === ArrayBuffer);\n };\n\n // Looks for an object on a `DataTransfer` object that is associated with drop events when utilizing the Filesystem API.\n qq.isItemList = function(maybeItemList) {\n return Object.prototype.toString.call(maybeItemList) === \"[object DataTransferItemList]\";\n };\n\n // Looks for an object on a `NodeList` or an `HTMLCollection`|`HTMLFormElement`|`HTMLSelectElement`\n // object that is associated with collections of Nodes.\n qq.isNodeList = function(maybeNodeList) {\n return Object.prototype.toString.call(maybeNodeList) === \"[object NodeList]\" ||\n // If `HTMLCollection` is the actual type of the object, we must determine this\n // by checking for expected properties/methods on the object\n (maybeNodeList.item && maybeNodeList.namedItem);\n };\n\n qq.isString = function(maybeString) {\n return Object.prototype.toString.call(maybeString) === \"[object String]\";\n };\n\n qq.trimStr = function(string) {\n if (String.prototype.trim) {\n return string.trim();\n }\n\n return string.replace(/^\\s+|\\s+$/g, \"\");\n };\n\n /**\n * @param str String to format.\n * @returns {string} A string, swapping argument values with the associated occurrence of {} in the passed string.\n */\n qq.format = function(str) {\n\n var args = Array.prototype.slice.call(arguments, 1),\n newStr = str,\n nextIdxToReplace = newStr.indexOf(\"{}\");\n\n qq.each(args, function(idx, val) {\n var strBefore = newStr.substring(0, nextIdxToReplace),\n strAfter = newStr.substring(nextIdxToReplace + 2);\n\n newStr = strBefore + val + strAfter;\n nextIdxToReplace = newStr.indexOf(\"{}\", nextIdxToReplace + val.length);\n\n // End the loop if we have run out of tokens (when the arguments exceed the # of tokens)\n if (nextIdxToReplace < 0) {\n return false;\n }\n });\n\n return newStr;\n };\n\n qq.isFile = function(maybeFile) {\n return window.File && Object.prototype.toString.call(maybeFile) === \"[object File]\";\n };\n\n qq.isFileList = function(maybeFileList) {\n return window.FileList && Object.prototype.toString.call(maybeFileList) === \"[object FileList]\";\n };\n\n qq.isFileOrInput = function(maybeFileOrInput) {\n return qq.isFile(maybeFileOrInput) || qq.isInput(maybeFileOrInput);\n };\n\n qq.isInput = function(maybeInput, notFile) {\n var evaluateType = function(type) {\n var normalizedType = type.toLowerCase();\n\n if (notFile) {\n return normalizedType !== \"file\";\n }\n\n return normalizedType === \"file\";\n };\n\n if (window.HTMLInputElement) {\n if (Object.prototype.toString.call(maybeInput) === \"[object HTMLInputElement]\") {\n if (maybeInput.type && evaluateType(maybeInput.type)) {\n return true;\n }\n }\n }\n if (maybeInput.tagName) {\n if (maybeInput.tagName.toLowerCase() === \"input\") {\n if (maybeInput.type && evaluateType(maybeInput.type)) {\n return true;\n }\n }\n }\n\n return false;\n };\n\n qq.isBlob = function(maybeBlob) {\n if (window.Blob && Object.prototype.toString.call(maybeBlob) === \"[object Blob]\") {\n return true;\n }\n };\n\n qq.isXhrUploadSupported = function() {\n var input = document.createElement(\"input\");\n input.type = \"file\";\n\n return (\n input.multiple !== undefined &&\n typeof File !== \"undefined\" &&\n typeof FormData !== \"undefined\" &&\n typeof (qq.createXhrInstance()).upload !== \"undefined\");\n };\n\n // Fall back to ActiveX is native XHR is disabled (possible in any version of IE).\n qq.createXhrInstance = function() {\n if (window.XMLHttpRequest) {\n return new XMLHttpRequest();\n }\n\n try {\n return new ActiveXObject(\"MSXML2.XMLHTTP.3.0\");\n }\n catch (error) {\n qq.log(\"Neither XHR or ActiveX are supported!\", \"error\");\n return null;\n }\n };\n\n qq.isFolderDropSupported = function(dataTransfer) {\n return dataTransfer.items &&\n dataTransfer.items.length > 0 &&\n dataTransfer.items[0].webkitGetAsEntry;\n };\n\n qq.isFileChunkingSupported = function() {\n return !qq.androidStock() && //Android's stock browser cannot upload Blobs correctly\n qq.isXhrUploadSupported() &&\n (File.prototype.slice !== undefined || File.prototype.webkitSlice !== undefined || File.prototype.mozSlice !== undefined);\n };\n\n qq.sliceBlob = function(fileOrBlob, start, end) {\n var slicer = fileOrBlob.slice || fileOrBlob.mozSlice || fileOrBlob.webkitSlice;\n\n return slicer.call(fileOrBlob, start, end);\n };\n\n qq.arrayBufferToHex = function(buffer) {\n var bytesAsHex = \"\",\n bytes = new Uint8Array(buffer);\n\n qq.each(bytes, function(idx, byt) {\n var byteAsHexStr = byt.toString(16);\n\n if (byteAsHexStr.length < 2) {\n byteAsHexStr = \"0\" + byteAsHexStr;\n }\n\n bytesAsHex += byteAsHexStr;\n });\n\n return bytesAsHex;\n };\n\n qq.readBlobToHex = function(blob, startOffset, length) {\n var initialBlob = qq.sliceBlob(blob, startOffset, startOffset + length),\n fileReader = new FileReader(),\n promise = new qq.Promise();\n\n fileReader.onload = function() {\n promise.success(qq.arrayBufferToHex(fileReader.result));\n };\n\n fileReader.onerror = promise.failure;\n\n fileReader.readAsArrayBuffer(initialBlob);\n\n return promise;\n };\n\n qq.extend = function(first, second, extendNested) {\n qq.each(second, function(prop, val) {\n if (extendNested && qq.isObject(val)) {\n if (first[prop] === undefined) {\n first[prop] = {};\n }\n qq.extend(first[prop], val, true);\n }\n else {\n first[prop] = val;\n }\n });\n\n return first;\n };\n\n /**\n * Allow properties in one object to override properties in another,\n * keeping track of the original values from the target object.\n *\n * Note that the pre-overriden properties to be overriden by the source will be passed into the `sourceFn` when it is invoked.\n *\n * @param target Update properties in this object from some source\n * @param sourceFn A function that, when invoked, will return properties that will replace properties with the same name in the target.\n * @returns {object} The target object\n */\n qq.override = function(target, sourceFn) {\n var super_ = {},\n source = sourceFn(super_);\n\n qq.each(source, function(srcPropName, srcPropVal) {\n if (target[srcPropName] !== undefined) {\n super_[srcPropName] = target[srcPropName];\n }\n\n target[srcPropName] = srcPropVal;\n });\n\n return target;\n };\n\n /**\n * Searches for a given element (elt) in the array, returns -1 if it is not present.\n */\n qq.indexOf = function(arr, elt, from) {\n if (arr.indexOf) {\n return arr.indexOf(elt, from);\n }\n\n from = from || 0;\n var len = arr.length;\n\n if (from < 0) {\n from += len;\n }\n\n for (; from < len; from += 1) {\n if (arr.hasOwnProperty(from) && arr[from] === elt) {\n return from;\n }\n }\n return -1;\n };\n\n //this is a version 4 UUID\n qq.getUniqueId = function() {\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, function(c) {\n /*jslint eqeq: true, bitwise: true*/\n var r = Math.random() * 16 | 0, v = c == \"x\" ? r : (r & 0x3 | 0x8);\n return v.toString(16);\n });\n };\n\n //\n // Browsers and platforms detection\n qq.ie = function() {\n return navigator.userAgent.indexOf(\"MSIE\") !== -1 ||\n navigator.userAgent.indexOf(\"Trident\") !== -1;\n };\n\n qq.ie7 = function() {\n return navigator.userAgent.indexOf(\"MSIE 7\") !== -1;\n };\n\n qq.ie8 = function() {\n return navigator.userAgent.indexOf(\"MSIE 8\") !== -1;\n };\n\n qq.ie10 = function() {\n return navigator.userAgent.indexOf(\"MSIE 10\") !== -1;\n };\n\n qq.ie11 = function() {\n return qq.ie() && navigator.userAgent.indexOf(\"rv:11\") !== -1;\n };\n\n qq.edge = function() {\n return navigator.userAgent.indexOf(\"Edge\") >= 0;\n };\n\n qq.safari = function() {\n return navigator.vendor !== undefined && navigator.vendor.indexOf(\"Apple\") !== -1;\n };\n\n qq.chrome = function() {\n return navigator.vendor !== undefined && navigator.vendor.indexOf(\"Google\") !== -1;\n };\n\n qq.opera = function() {\n return navigator.vendor !== undefined && navigator.vendor.indexOf(\"Opera\") !== -1;\n };\n\n qq.firefox = function() {\n return (!qq.edge() && !qq.ie11() && navigator.userAgent.indexOf(\"Mozilla\") !== -1 && navigator.vendor !== undefined && navigator.vendor === \"\");\n };\n\n qq.windows = function() {\n return navigator.platform === \"Win32\";\n };\n\n qq.android = function() {\n return navigator.userAgent.toLowerCase().indexOf(\"android\") !== -1;\n };\n\n // We need to identify the Android stock browser via the UA string to work around various bugs in this browser,\n // such as the one that prevents a `Blob` from being uploaded.\n qq.androidStock = function() {\n return qq.android() && navigator.userAgent.toLowerCase().indexOf(\"chrome\") < 0;\n };\n\n qq.ios6 = function() {\n return qq.ios() && navigator.userAgent.indexOf(\" OS 6_\") !== -1;\n };\n\n qq.ios7 = function() {\n return qq.ios() && navigator.userAgent.indexOf(\" OS 7_\") !== -1;\n };\n\n qq.ios8 = function() {\n return qq.ios() && navigator.userAgent.indexOf(\" OS 8_\") !== -1;\n };\n\n // iOS 8.0.0\n qq.ios800 = function() {\n return qq.ios() && navigator.userAgent.indexOf(\" OS 8_0 \") !== -1;\n };\n\n qq.ios = function() {\n /*jshint -W014 */\n return navigator.userAgent.indexOf(\"iPad\") !== -1\n || navigator.userAgent.indexOf(\"iPod\") !== -1\n || navigator.userAgent.indexOf(\"iPhone\") !== -1;\n };\n\n qq.iosChrome = function() {\n return qq.ios() && navigator.userAgent.indexOf(\"CriOS\") !== -1;\n };\n\n qq.iosSafari = function() {\n return qq.ios() && !qq.iosChrome() && navigator.userAgent.indexOf(\"Safari\") !== -1;\n };\n\n qq.iosSafariWebView = function() {\n return qq.ios() && !qq.iosChrome() && !qq.iosSafari();\n };\n\n //\n // Events\n\n qq.preventDefault = function(e) {\n if (e.preventDefault) {\n e.preventDefault();\n } else {\n e.returnValue = false;\n }\n };\n\n /**\n * Creates and returns element from html string\n * Uses innerHTML to create an element\n */\n qq.toElement = (function() {\n var div = document.createElement(\"div\");\n return function(html) {\n div.innerHTML = html;\n var element = div.firstChild;\n div.removeChild(element);\n return element;\n };\n }());\n\n //key and value are passed to callback for each entry in the iterable item\n qq.each = function(iterableItem, callback) {\n var keyOrIndex, retVal;\n\n if (iterableItem) {\n // Iterate through [`Storage`](http://www.w3.org/TR/webstorage/#the-storage-interface) items\n if (window.Storage && iterableItem.constructor === window.Storage) {\n for (keyOrIndex = 0; keyOrIndex < iterableItem.length; keyOrIndex++) {\n retVal = callback(iterableItem.key(keyOrIndex), iterableItem.getItem(iterableItem.key(keyOrIndex)));\n if (retVal === false) {\n break;\n }\n }\n }\n // `DataTransferItemList` & `NodeList` objects are array-like and should be treated as arrays\n // when iterating over items inside the object.\n else if (qq.isArray(iterableItem) || qq.isItemList(iterableItem) || qq.isNodeList(iterableItem)) {\n for (keyOrIndex = 0; keyOrIndex < iterableItem.length; keyOrIndex++) {\n retVal = callback(keyOrIndex, iterableItem[keyOrIndex]);\n if (retVal === false) {\n break;\n }\n }\n }\n else if (qq.isString(iterableItem)) {\n for (keyOrIndex = 0; keyOrIndex < iterableItem.length; keyOrIndex++) {\n retVal = callback(keyOrIndex, iterableItem.charAt(keyOrIndex));\n if (retVal === false) {\n break;\n }\n }\n }\n else {\n for (keyOrIndex in iterableItem) {\n if (Object.prototype.hasOwnProperty.call(iterableItem, keyOrIndex)) {\n retVal = callback(keyOrIndex, iterableItem[keyOrIndex]);\n if (retVal === false) {\n break;\n }\n }\n }\n }\n }\n };\n\n //include any args that should be passed to the new function after the context arg\n qq.bind = function(oldFunc, context) {\n if (qq.isFunction(oldFunc)) {\n var args = Array.prototype.slice.call(arguments, 2);\n\n return function() {\n var newArgs = qq.extend([], args);\n if (arguments.length) {\n newArgs = newArgs.concat(Array.prototype.slice.call(arguments));\n }\n return oldFunc.apply(context, newArgs);\n };\n }\n\n throw new Error(\"first parameter must be a function!\");\n };\n\n /**\n * obj2url() takes a json-object as argument and generates\n * a querystring. pretty much like jQuery.param()\n *\n * how to use:\n *\n * `qq.obj2url({a:'b',c:'d'},'http://any.url/upload?otherParam=value');`\n *\n * will result in:\n *\n * `http://any.url/upload?otherParam=value&a=b&c=d`\n *\n * @param Object JSON-Object\n * @param String current querystring-part\n * @return String encoded querystring\n */\n qq.obj2url = function(obj, temp, prefixDone) {\n /*jshint laxbreak: true*/\n var uristrings = [],\n prefix = \"&\",\n add = function(nextObj, i) {\n var nextTemp = temp\n ? (/\\[\\]$/.test(temp)) // prevent double-encoding\n ? temp\n : temp + \"[\" + i + \"]\"\n : i;\n if ((nextTemp !== \"undefined\") && (i !== \"undefined\")) {\n uristrings.push(\n (typeof nextObj === \"object\")\n ? qq.obj2url(nextObj, nextTemp, true)\n : (Object.prototype.toString.call(nextObj) === \"[object Function]\")\n ? encodeURIComponent(nextTemp) + \"=\" + encodeURIComponent(nextObj())\n : encodeURIComponent(nextTemp) + \"=\" + encodeURIComponent(nextObj)\n );\n }\n };\n\n if (!prefixDone && temp) {\n prefix = (/\\?/.test(temp)) ? (/\\?$/.test(temp)) ? \"\" : \"&\" : \"?\";\n uristrings.push(temp);\n uristrings.push(qq.obj2url(obj));\n } else if ((Object.prototype.toString.call(obj) === \"[object Array]\") && (typeof obj !== \"undefined\")) {\n qq.each(obj, function(idx, val) {\n add(val, idx);\n });\n } else if ((typeof obj !== \"undefined\") && (obj !== null) && (typeof obj === \"object\")) {\n qq.each(obj, function(prop, val) {\n add(val, prop);\n });\n } else {\n uristrings.push(encodeURIComponent(temp) + \"=\" + encodeURIComponent(obj));\n }\n\n if (temp) {\n return uristrings.join(prefix);\n } else {\n return uristrings.join(prefix)\n .replace(/^&/, \"\")\n .replace(/%20/g, \"+\");\n }\n };\n\n qq.obj2FormData = function(obj, formData, arrayKeyName) {\n if (!formData) {\n formData = new FormData();\n }\n\n qq.each(obj, function(key, val) {\n key = arrayKeyName ? arrayKeyName + \"[\" + key + \"]\" : key;\n\n if (qq.isObject(val)) {\n qq.obj2FormData(val, formData, key);\n }\n else if (qq.isFunction(val)) {\n formData.append(key, val());\n }\n else {\n formData.append(key, val);\n }\n });\n\n return formData;\n };\n\n qq.obj2Inputs = function(obj, form) {\n var input;\n\n if (!form) {\n form = document.createElement(\"form\");\n }\n\n qq.obj2FormData(obj, {\n append: function(key, val) {\n input = document.createElement(\"input\");\n input.setAttribute(\"name\", key);\n input.setAttribute(\"value\", val);\n form.appendChild(input);\n }\n });\n\n return form;\n };\n\n /**\n * Not recommended for use outside of Fine Uploader since this falls back to an unchecked eval if JSON.parse is not\n * implemented. For a more secure JSON.parse polyfill, use Douglas Crockford's json2.js.\n */\n qq.parseJson = function(json) {\n /*jshint evil: true*/\n if (window.JSON && qq.isFunction(JSON.parse)) {\n return JSON.parse(json);\n } else {\n return eval(\"(\" + json + \")\");\n }\n };\n\n /**\n * Retrieve the extension of a file, if it exists.\n *\n * @param filename\n * @returns {string || undefined}\n */\n qq.getExtension = function(filename) {\n var extIdx = filename.lastIndexOf(\".\") + 1;\n\n if (extIdx > 0) {\n return filename.substr(extIdx, filename.length - extIdx);\n }\n };\n\n qq.getFilename = function(blobOrFileInput) {\n /*jslint regexp: true*/\n\n if (qq.isInput(blobOrFileInput)) {\n // get input value and remove path to normalize\n return blobOrFileInput.value.replace(/.*(\\/|\\\\)/, \"\");\n }\n else if (qq.isFile(blobOrFileInput)) {\n if (blobOrFileInput.fileName !== null && blobOrFileInput.fileName !== undefined) {\n return blobOrFileInput.fileName;\n }\n }\n\n return blobOrFileInput.name;\n };\n\n /**\n * A generic module which supports object disposing in dispose() method.\n * */\n qq.DisposeSupport = function() {\n var disposers = [];\n\n return {\n /** Run all registered disposers */\n dispose: function() {\n var disposer;\n do {\n disposer = disposers.shift();\n if (disposer) {\n disposer();\n }\n }\n while (disposer);\n },\n\n /** Attach event handler and register de-attacher as a disposer */\n attach: function() {\n var args = arguments;\n /*jslint undef:true*/\n this.addDisposer(qq(args[0]).attach.apply(this, Array.prototype.slice.call(arguments, 1)));\n },\n\n /** Add disposer to the collection */\n addDisposer: function(disposeFunction) {\n disposers.push(disposeFunction);\n }\n };\n };\n}());\n","/* globals define, module, global, qq */\n(function() {\n \"use strict\";\n if (typeof define === \"function\" && define.amd) {\n define(function() {\n return qq;\n });\n }\n else if (typeof module !== \"undefined\" && module.exports) {\n module.exports = qq;\n }\n else {\n global.qq = qq;\n }\n}());\n","/* globals qq */\n/**\n * Fine Uploader top-level Error container. Inherits from `Error`.\n */\n(function() {\n \"use strict\";\n\n qq.Error = function(message) {\n this.message = \"[Fine Uploader \" + qq.version + \"] \" + message;\n };\n\n qq.Error.prototype = new Error();\n}());\n","/*global qq */\nqq.version = \"5.16.2\";\n","/* globals qq */\nqq.supportedFeatures = (function() {\n \"use strict\";\n\n var supportsUploading,\n supportsUploadingBlobs,\n supportsFileDrop,\n supportsAjaxFileUploading,\n supportsFolderDrop,\n supportsChunking,\n supportsResume,\n supportsUploadViaPaste,\n supportsUploadCors,\n supportsDeleteFileXdr,\n supportsDeleteFileCorsXhr,\n supportsDeleteFileCors,\n supportsFolderSelection,\n supportsImagePreviews,\n supportsUploadProgress;\n\n function testSupportsFileInputElement() {\n var supported = true,\n tempInput;\n\n try {\n tempInput = document.createElement(\"input\");\n tempInput.type = \"file\";\n qq(tempInput).hide();\n\n if (tempInput.disabled) {\n supported = false;\n }\n }\n catch (ex) {\n supported = false;\n }\n\n return supported;\n }\n\n //only way to test for complete Clipboard API support at this time\n function isChrome14OrHigher() {\n return (qq.chrome() || qq.opera()) &&\n navigator.userAgent.match(/Chrome\\/[1][4-9]|Chrome\\/[2-9][0-9]/) !== undefined;\n }\n\n //Ensure we can send cross-origin `XMLHttpRequest`s\n function isCrossOriginXhrSupported() {\n if (window.XMLHttpRequest) {\n var xhr = qq.createXhrInstance();\n\n //Commonly accepted test for XHR CORS support.\n return xhr.withCredentials !== undefined;\n }\n\n return false;\n }\n\n //Test for (terrible) cross-origin ajax transport fallback for IE9 and IE8\n function isXdrSupported() {\n return window.XDomainRequest !== undefined;\n }\n\n // CORS Ajax requests are supported if it is either possible to send credentialed `XMLHttpRequest`s,\n // or if `XDomainRequest` is an available alternative.\n function isCrossOriginAjaxSupported() {\n if (isCrossOriginXhrSupported()) {\n return true;\n }\n\n return isXdrSupported();\n }\n\n function isFolderSelectionSupported() {\n // We know that folder selection is only supported in Chrome via this proprietary attribute for now\n return document.createElement(\"input\").webkitdirectory !== undefined;\n }\n\n function isLocalStorageSupported() {\n try {\n return !!window.localStorage &&\n // unpatched versions of IE10/11 have buggy impls of localStorage where setItem is a string\n qq.isFunction(window.localStorage.setItem);\n }\n catch (error) {\n // probably caught a security exception, so no localStorage for you\n return false;\n }\n }\n\n function isDragAndDropSupported() {\n var span = document.createElement(\"span\");\n\n return (\"draggable\" in span || (\"ondragstart\" in span && \"ondrop\" in span)) &&\n !qq.android() && !qq.ios();\n }\n\n supportsUploading = testSupportsFileInputElement();\n\n supportsAjaxFileUploading = supportsUploading && qq.isXhrUploadSupported();\n\n supportsUploadingBlobs = supportsAjaxFileUploading && !qq.androidStock();\n\n supportsFileDrop = supportsAjaxFileUploading && isDragAndDropSupported();\n\n // adapted from https://stackoverflow.com/a/23278460/486979\n supportsFolderDrop = supportsFileDrop && (function() {\n var input = document.createElement(\"input\");\n\n input.type = \"file\";\n return !!(\"webkitdirectory\" in (input || document.querySelectorAll(\"input[type=file]\")[0]));\n }());\n\n supportsChunking = supportsAjaxFileUploading && qq.isFileChunkingSupported();\n\n supportsResume = supportsAjaxFileUploading && supportsChunking && isLocalStorageSupported();\n\n supportsUploadViaPaste = supportsAjaxFileUploading && isChrome14OrHigher();\n\n supportsUploadCors = supportsUploading && (window.postMessage !== undefined || supportsAjaxFileUploading);\n\n supportsDeleteFileCorsXhr = isCrossOriginXhrSupported();\n\n supportsDeleteFileXdr = isXdrSupported();\n\n supportsDeleteFileCors = isCrossOriginAjaxSupported();\n\n supportsFolderSelection = isFolderSelectionSupported();\n\n supportsImagePreviews = supportsAjaxFileUploading && window.FileReader !== undefined;\n\n supportsUploadProgress = (function() {\n if (supportsAjaxFileUploading) {\n return !qq.androidStock() && !qq.iosChrome();\n }\n return false;\n }());\n\n return {\n ajaxUploading: supportsAjaxFileUploading,\n blobUploading: supportsUploadingBlobs,\n canDetermineSize: supportsAjaxFileUploading,\n chunking: supportsChunking,\n deleteFileCors: supportsDeleteFileCors,\n deleteFileCorsXdr: supportsDeleteFileXdr, //NOTE: will also return true in IE10, where XDR is also supported\n deleteFileCorsXhr: supportsDeleteFileCorsXhr,\n dialogElement: !!window.HTMLDialogElement,\n fileDrop: supportsFileDrop,\n folderDrop: supportsFolderDrop,\n folderSelection: supportsFolderSelection,\n imagePreviews: supportsImagePreviews,\n imageValidation: supportsImagePreviews,\n itemSizeValidation: supportsAjaxFileUploading,\n pause: supportsChunking,\n progressBar: supportsUploadProgress,\n resume: supportsResume,\n scaling: supportsImagePreviews && supportsUploadingBlobs,\n tiffPreviews: qq.safari(), // Not the best solution, but simple and probably accurate enough (for now)\n unlimitedScaledImageSize: !qq.ios(), // false simply indicates that there is some known limit\n uploading: supportsUploading,\n uploadCors: supportsUploadCors,\n uploadCustomHeaders: supportsAjaxFileUploading,\n uploadNonMultipart: supportsAjaxFileUploading,\n uploadViaPaste: supportsUploadViaPaste\n };\n\n}());\n","/*globals qq*/\n\n// Is the passed object a promise instance?\nqq.isGenericPromise = function(maybePromise) {\n \"use strict\";\n return !!(maybePromise && maybePromise.then && qq.isFunction(maybePromise.then));\n};\n\nqq.Promise = function() {\n \"use strict\";\n\n var successArgs, failureArgs,\n successCallbacks = [],\n failureCallbacks = [],\n doneCallbacks = [],\n state = 0;\n\n qq.extend(this, {\n then: function(onSuccess, onFailure) {\n if (state === 0) {\n if (onSuccess) {\n successCallbacks.push(onSuccess);\n }\n if (onFailure) {\n failureCallbacks.push(onFailure);\n }\n }\n else if (state === -1) {\n onFailure && onFailure.apply(null, failureArgs);\n }\n else if (onSuccess) {\n onSuccess.apply(null, successArgs);\n }\n\n return this;\n },\n\n done: function(callback) {\n if (state === 0) {\n doneCallbacks.push(callback);\n }\n else {\n callback.apply(null, failureArgs === undefined ? successArgs : failureArgs);\n }\n\n return this;\n },\n\n success: function() {\n state = 1;\n successArgs = arguments;\n\n if (successCallbacks.length) {\n qq.each(successCallbacks, function(idx, callback) {\n callback.apply(null, successArgs);\n });\n }\n\n if (doneCallbacks.length) {\n qq.each(doneCallbacks, function(idx, callback) {\n callback.apply(null, successArgs);\n });\n }\n\n return this;\n },\n\n failure: function() {\n state = -1;\n failureArgs = arguments;\n\n if (failureCallbacks.length) {\n qq.each(failureCallbacks, function(idx, callback) {\n callback.apply(null, failureArgs);\n });\n }\n\n if (doneCallbacks.length) {\n qq.each(doneCallbacks, function(idx, callback) {\n callback.apply(null, failureArgs);\n });\n }\n\n return this;\n }\n });\n};\n","/* globals qq */\n/**\n * Placeholder for a Blob that will be generated on-demand.\n *\n * @param referenceBlob Parent of the generated blob\n * @param onCreate Function to invoke when the blob must be created. Must be promissory.\n * @constructor\n */\nqq.BlobProxy = function(referenceBlob, onCreate) {\n \"use strict\";\n\n qq.extend(this, {\n referenceBlob: referenceBlob,\n\n create: function() {\n return onCreate(referenceBlob);\n }\n });\n};\n","/*globals qq*/\n\n/**\n * This module represents an upload or \"Select File(s)\" button. It's job is to embed an opaque ` `\n * element as a child of a provided \"container\" element. This \"container\" element (`options.element`) is used to provide\n * a custom style for the ` ` element. The ability to change the style of the container element is also\n * provided here by adding CSS classes to the container on hover/focus.\n *\n * TODO Eliminate the mouseover and mouseout event handlers since the :hover CSS pseudo-class should now be\n * available on all supported browsers.\n *\n * @param o Options to override the default values\n */\nqq.UploadButton = function(o) {\n \"use strict\";\n\n var self = this,\n\n disposeSupport = new qq.DisposeSupport(),\n\n options = {\n // Corresponds to the `accept` attribute on the associated ` `\n acceptFiles: null,\n\n // \"Container\" element\n element: null,\n\n focusClass: \"qq-upload-button-focus\",\n\n // A true value allows folders to be selected, if supported by the UA\n folders: false,\n\n // **This option will be removed** in the future as the :hover CSS pseudo-class is available on all supported browsers\n hoverClass: \"qq-upload-button-hover\",\n\n ios8BrowserCrashWorkaround: false,\n\n // If true adds `multiple` attribute to ` `\n multiple: false,\n\n // `name` attribute of ` `\n name: \"qqfile\",\n\n // Called when the browser invokes the onchange handler on the ` `\n onChange: function(input) {},\n\n title: null\n },\n input, buttonId;\n\n // Overrides any of the default option values with any option values passed in during construction.\n qq.extend(options, o);\n\n buttonId = qq.getUniqueId();\n\n // Embed an opaque ` ` element as a child of `options.element`.\n function createInput() {\n var input = document.createElement(\"input\");\n\n input.setAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME, buttonId);\n input.setAttribute(\"title\", options.title);\n\n self.setMultiple(options.multiple, input);\n\n if (options.folders && qq.supportedFeatures.folderSelection) {\n // selecting directories is only possible in Chrome now, via a vendor-specific prefixed attribute\n input.setAttribute(\"webkitdirectory\", \"\");\n }\n\n if (options.acceptFiles) {\n input.setAttribute(\"accept\", options.acceptFiles);\n }\n\n input.setAttribute(\"type\", \"file\");\n input.setAttribute(\"name\", options.name);\n\n qq(input).css({\n position: \"absolute\",\n // in Opera only 'browse' button\n // is clickable and it is located at\n // the right side of the input\n right: 0,\n top: 0,\n fontFamily: \"Arial\",\n // It's especially important to make this an arbitrarily large value\n // to ensure the rendered input button in IE takes up the entire\n // space of the container element. Otherwise, the left side of the\n // button will require a double-click to invoke the file chooser.\n // In other browsers, this might cause other issues, so a large font-size\n // is only used in IE. There is a bug in IE8 where the opacity style is ignored\n // in some cases when the font-size is large. So, this workaround is not applied\n // to IE8.\n fontSize: qq.ie() && !qq.ie8() ? \"3500px\" : \"118px\",\n margin: 0,\n padding: 0,\n cursor: \"pointer\",\n opacity: 0\n });\n\n // Setting the file input's height to 100% in IE7 causes\n // most of the visible button to be unclickable.\n !qq.ie7() && qq(input).css({height: \"100%\"});\n\n options.element.appendChild(input);\n\n disposeSupport.attach(input, \"change\", function() {\n options.onChange(input);\n });\n\n // **These event handlers will be removed** in the future as the :hover CSS pseudo-class is available on all supported browsers\n disposeSupport.attach(input, \"mouseover\", function() {\n qq(options.element).addClass(options.hoverClass);\n });\n disposeSupport.attach(input, \"mouseout\", function() {\n qq(options.element).removeClass(options.hoverClass);\n });\n\n disposeSupport.attach(input, \"focus\", function() {\n qq(options.element).addClass(options.focusClass);\n });\n disposeSupport.attach(input, \"blur\", function() {\n qq(options.element).removeClass(options.focusClass);\n });\n\n return input;\n }\n\n // Make button suitable container for input\n qq(options.element).css({\n position: \"relative\",\n overflow: \"hidden\",\n // Make sure browse button is in the right side in Internet Explorer\n direction: \"ltr\"\n });\n\n // Exposed API\n qq.extend(this, {\n getInput: function() {\n return input;\n },\n\n getButtonId: function() {\n return buttonId;\n },\n\n setMultiple: function(isMultiple, optInput) {\n var input = optInput || this.getInput();\n\n // Temporary workaround for bug in in iOS8 UIWebView that causes the browser to crash\n // before the file chooser appears if the file input doesn't contain a multiple attribute.\n // See #1283.\n if (options.ios8BrowserCrashWorkaround && qq.ios8() && (qq.iosChrome() || qq.iosSafariWebView())) {\n input.setAttribute(\"multiple\", \"\");\n }\n\n else {\n if (isMultiple) {\n input.setAttribute(\"multiple\", \"\");\n }\n else {\n input.removeAttribute(\"multiple\");\n }\n }\n },\n\n setAcceptFiles: function(acceptFiles) {\n if (acceptFiles !== options.acceptFiles) {\n input.setAttribute(\"accept\", acceptFiles);\n }\n },\n\n reset: function() {\n if (input.parentNode) {\n qq(input).remove();\n }\n\n qq(options.element).removeClass(options.focusClass);\n input = null;\n input = createInput();\n }\n });\n\n input = createInput();\n};\n\nqq.UploadButton.BUTTON_ID_ATTR_NAME = \"qq-button-id\";\n","/*globals qq */\nqq.UploadData = function(uploaderProxy) {\n \"use strict\";\n\n var data = [],\n byUuid = {},\n byStatus = {},\n byProxyGroupId = {},\n byBatchId = {};\n\n function getDataByIds(idOrIds) {\n if (qq.isArray(idOrIds)) {\n var entries = [];\n\n qq.each(idOrIds, function(idx, id) {\n entries.push(data[id]);\n });\n\n return entries;\n }\n\n return data[idOrIds];\n }\n\n function getDataByUuids(uuids) {\n if (qq.isArray(uuids)) {\n var entries = [];\n\n qq.each(uuids, function(idx, uuid) {\n entries.push(data[byUuid[uuid]]);\n });\n\n return entries;\n }\n\n return data[byUuid[uuids]];\n }\n\n function getDataByStatus(status) {\n var statusResults = [],\n statuses = [].concat(status);\n\n qq.each(statuses, function(index, statusEnum) {\n var statusResultIndexes = byStatus[statusEnum];\n\n if (statusResultIndexes !== undefined) {\n qq.each(statusResultIndexes, function(i, dataIndex) {\n statusResults.push(data[dataIndex]);\n });\n }\n });\n\n return statusResults;\n }\n\n qq.extend(this, {\n /**\n * Adds a new file to the data cache for tracking purposes.\n *\n * @param spec Data that describes this file. Possible properties are:\n *\n * - uuid: Initial UUID for this file.\n * - name: Initial name of this file.\n * - size: Size of this file, omit if this cannot be determined\n * - status: Initial `qq.status` for this file. Omit for `qq.status.SUBMITTING`.\n * - batchId: ID of the batch this file belongs to\n * - proxyGroupId: ID of the proxy group associated with this file\n * - onBeforeStatusChange(fileId): callback that is executed before the status change is broadcast\n *\n * @returns {number} Internal ID for this file.\n */\n addFile: function(spec) {\n var status = spec.status || qq.status.SUBMITTING,\n id = data.push({\n name: spec.name,\n originalName: spec.name,\n uuid: spec.uuid,\n size: spec.size == null ? -1 : spec.size,\n status: status,\n file: spec.file\n }) - 1;\n\n if (spec.batchId) {\n data[id].batchId = spec.batchId;\n\n if (byBatchId[spec.batchId] === undefined) {\n byBatchId[spec.batchId] = [];\n }\n byBatchId[spec.batchId].push(id);\n }\n\n if (spec.proxyGroupId) {\n data[id].proxyGroupId = spec.proxyGroupId;\n\n if (byProxyGroupId[spec.proxyGroupId] === undefined) {\n byProxyGroupId[spec.proxyGroupId] = [];\n }\n byProxyGroupId[spec.proxyGroupId].push(id);\n }\n\n data[id].id = id;\n byUuid[spec.uuid] = id;\n\n if (byStatus[status] === undefined) {\n byStatus[status] = [];\n }\n byStatus[status].push(id);\n\n spec.onBeforeStatusChange && spec.onBeforeStatusChange(id);\n uploaderProxy.onStatusChange(id, null, status);\n\n return id;\n },\n\n retrieve: function(optionalFilter) {\n if (qq.isObject(optionalFilter) && data.length) {\n if (optionalFilter.id !== undefined) {\n return getDataByIds(optionalFilter.id);\n }\n\n else if (optionalFilter.uuid !== undefined) {\n return getDataByUuids(optionalFilter.uuid);\n }\n\n else if (optionalFilter.status) {\n return getDataByStatus(optionalFilter.status);\n }\n }\n else {\n return qq.extend([], data, true);\n }\n },\n\n removeFileRef: function(id) {\n var record = getDataByIds(id);\n\n if (record) {\n delete record.file;\n }\n },\n\n reset: function() {\n data = [];\n byUuid = {};\n byStatus = {};\n byBatchId = {};\n },\n\n setStatus: function(id, newStatus) {\n var oldStatus = data[id].status,\n byStatusOldStatusIndex = qq.indexOf(byStatus[oldStatus], id);\n\n byStatus[oldStatus].splice(byStatusOldStatusIndex, 1);\n\n data[id].status = newStatus;\n\n if (byStatus[newStatus] === undefined) {\n byStatus[newStatus] = [];\n }\n byStatus[newStatus].push(id);\n\n uploaderProxy.onStatusChange(id, oldStatus, newStatus);\n },\n\n uuidChanged: function(id, newUuid) {\n var oldUuid = data[id].uuid;\n\n data[id].uuid = newUuid;\n byUuid[newUuid] = id;\n delete byUuid[oldUuid];\n },\n\n updateName: function(id, newName) {\n data[id].name = newName;\n },\n\n updateSize: function(id, newSize) {\n data[id].size = newSize;\n },\n\n // Only applicable if this file has a parent that we may want to reference later.\n setParentId: function(targetId, parentId) {\n data[targetId].parentId = parentId;\n },\n\n getIdsInProxyGroup: function(id) {\n var proxyGroupId = data[id].proxyGroupId;\n\n if (proxyGroupId) {\n return byProxyGroupId[proxyGroupId];\n }\n return [];\n },\n\n getIdsInBatch: function(id) {\n var batchId = data[id].batchId;\n\n return byBatchId[batchId];\n }\n });\n};\n\nqq.status = {\n SUBMITTING: \"submitting\",\n SUBMITTED: \"submitted\",\n REJECTED: \"rejected\",\n QUEUED: \"queued\",\n CANCELED: \"canceled\",\n PAUSED: \"paused\",\n UPLOADING: \"uploading\",\n UPLOAD_FINALIZING: \"upload finalizing\",\n UPLOAD_RETRYING: \"retrying upload\",\n UPLOAD_SUCCESSFUL: \"upload successful\",\n UPLOAD_FAILED: \"upload failed\",\n DELETE_FAILED: \"delete failed\",\n DELETING: \"deleting\",\n DELETED: \"deleted\"\n};\n","/*globals qq*/\n/**\n * Defines the public API for FineUploaderBasic mode.\n */\n(function() {\n \"use strict\";\n\n qq.basePublicApi = {\n // DEPRECATED - TODO REMOVE IN NEXT MAJOR RELEASE (replaced by addFiles)\n addBlobs: function(blobDataOrArray, params, endpoint) {\n this.addFiles(blobDataOrArray, params, endpoint);\n },\n\n addInitialFiles: function(cannedFileList) {\n var self = this;\n\n qq.each(cannedFileList, function(index, cannedFile) {\n self._addCannedFile(cannedFile);\n });\n },\n\n addFiles: function(data, params, endpoint) {\n this._maybeHandleIos8SafariWorkaround();\n\n var batchId = this._storedIds.length === 0 ? qq.getUniqueId() : this._currentBatchId,\n\n processBlob = qq.bind(function(blob) {\n this._handleNewFile({\n blob: blob,\n name: this._options.blobs.defaultName\n }, batchId, verifiedFiles);\n }, this),\n\n processBlobData = qq.bind(function(blobData) {\n this._handleNewFile(blobData, batchId, verifiedFiles);\n }, this),\n\n processCanvas = qq.bind(function(canvas) {\n var blob = qq.canvasToBlob(canvas);\n\n this._handleNewFile({\n blob: blob,\n name: this._options.blobs.defaultName + \".png\"\n }, batchId, verifiedFiles);\n }, this),\n\n processCanvasData = qq.bind(function(canvasData) {\n var normalizedQuality = canvasData.quality && canvasData.quality / 100,\n blob = qq.canvasToBlob(canvasData.canvas, canvasData.type, normalizedQuality);\n\n this._handleNewFile({\n blob: blob,\n name: canvasData.name\n }, batchId, verifiedFiles);\n }, this),\n\n processFileOrInput = qq.bind(function(fileOrInput) {\n if (qq.isInput(fileOrInput) && qq.supportedFeatures.ajaxUploading) {\n var files = Array.prototype.slice.call(fileOrInput.files),\n self = this;\n\n qq.each(files, function(idx, file) {\n self._handleNewFile(file, batchId, verifiedFiles);\n });\n }\n else {\n this._handleNewFile(fileOrInput, batchId, verifiedFiles);\n }\n }, this),\n\n normalizeData = function() {\n if (qq.isFileList(data)) {\n data = Array.prototype.slice.call(data);\n }\n data = [].concat(data);\n },\n\n self = this,\n verifiedFiles = [];\n\n this._currentBatchId = batchId;\n\n if (data) {\n normalizeData();\n\n qq.each(data, function(idx, fileContainer) {\n if (qq.isFileOrInput(fileContainer)) {\n processFileOrInput(fileContainer);\n }\n else if (qq.isBlob(fileContainer)) {\n processBlob(fileContainer);\n }\n else if (qq.isObject(fileContainer)) {\n if (fileContainer.blob && fileContainer.name) {\n processBlobData(fileContainer);\n }\n else if (fileContainer.canvas && fileContainer.name) {\n processCanvasData(fileContainer);\n }\n }\n else if (fileContainer.tagName && fileContainer.tagName.toLowerCase() === \"canvas\") {\n processCanvas(fileContainer);\n }\n else {\n self.log(fileContainer + \" is not a valid file container! Ignoring!\", \"warn\");\n }\n });\n\n this.log(\"Received \" + verifiedFiles.length + \" files.\");\n this._prepareItemsForUpload(verifiedFiles, params, endpoint);\n }\n },\n\n cancel: function(id) {\n var uploadData = this._uploadData.retrieve({id: id});\n\n if (uploadData && uploadData.status === qq.status.UPLOAD_FINALIZING) {\n this.log(qq.format(\"Ignoring cancel for file ID {} ({}). Finalizing upload.\", id, this.getName(id)), \"error\");\n }\n else {\n this._handler.cancel(id);\n }\n },\n\n cancelAll: function() {\n var storedIdsCopy = [],\n self = this;\n\n qq.extend(storedIdsCopy, this._storedIds);\n qq.each(storedIdsCopy, function(idx, storedFileId) {\n self.cancel(storedFileId);\n });\n\n this._handler.cancelAll();\n },\n\n clearStoredFiles: function() {\n this._storedIds = [];\n },\n\n continueUpload: function(id) {\n var uploadData = this._uploadData.retrieve({id: id});\n\n if (!qq.supportedFeatures.pause || !this._options.chunking.enabled) {\n return false;\n }\n\n if (uploadData.status === qq.status.PAUSED) {\n this.log(qq.format(\"Paused file ID {} ({}) will be continued. Not paused.\", id, this.getName(id)));\n this._uploadFile(id);\n return true;\n }\n else {\n this.log(qq.format(\"Ignoring continue for file ID {} ({}). Not paused.\", id, this.getName(id)), \"error\");\n }\n\n return false;\n },\n\n deleteFile: function(id) {\n return this._onSubmitDelete(id);\n },\n\n // TODO document?\n doesExist: function(fileOrBlobId) {\n return this._handler.isValid(fileOrBlobId);\n },\n\n // Generate a variable size thumbnail on an img or canvas,\n // returning a promise that is fulfilled when the attempt completes.\n // Thumbnail can either be based off of a URL for an image returned\n // by the server in the upload response, or the associated `Blob`.\n drawThumbnail: function(fileId, imgOrCanvas, maxSize, fromServer, customResizeFunction) {\n var promiseToReturn = new qq.Promise(),\n fileOrUrl, options;\n\n if (this._imageGenerator) {\n fileOrUrl = this._thumbnailUrls[fileId];\n options = {\n customResizeFunction: customResizeFunction,\n maxSize: maxSize > 0 ? maxSize : null,\n scale: maxSize > 0\n };\n\n // If client-side preview generation is possible\n // and we are not specifically looking for the image URl returned by the server...\n if (!fromServer && qq.supportedFeatures.imagePreviews) {\n fileOrUrl = this.getFile(fileId);\n }\n\n /* jshint eqeqeq:false,eqnull:true */\n if (fileOrUrl == null) {\n promiseToReturn.failure({container: imgOrCanvas, error: \"File or URL not found.\"});\n }\n else {\n this._imageGenerator.generate(fileOrUrl, imgOrCanvas, options).then(\n function success(modifiedContainer) {\n promiseToReturn.success(modifiedContainer);\n },\n\n function failure(container, reason) {\n promiseToReturn.failure({container: container, error: reason || \"Problem generating thumbnail\"});\n }\n );\n }\n }\n else {\n promiseToReturn.failure({container: imgOrCanvas, error: \"Missing image generator module\"});\n }\n\n return promiseToReturn;\n },\n\n getButton: function(fileId) {\n return this._getButton(this._buttonIdsForFileIds[fileId]);\n },\n\n getEndpoint: function(fileId) {\n return this._endpointStore.get(fileId);\n },\n\n getFile: function(fileOrBlobId) {\n var file = this._handler.getFile(fileOrBlobId);\n var uploadDataRecord;\n\n if (!file) {\n uploadDataRecord = this._uploadData.retrieve({id: fileOrBlobId});\n\n if (uploadDataRecord) {\n file = uploadDataRecord.file;\n }\n }\n\n return file || null;\n },\n\n getInProgress: function() {\n return this._uploadData.retrieve({\n status: [\n qq.status.UPLOADING,\n qq.status.UPLOAD_RETRYING,\n qq.status.QUEUED\n ]\n }).length;\n },\n\n getName: function(id) {\n return this._uploadData.retrieve({id: id}).name;\n },\n\n // Parent ID for a specific file, or null if this is the parent, or if it has no parent.\n getParentId: function(id) {\n var uploadDataEntry = this.getUploads({id: id}),\n parentId = null;\n\n if (uploadDataEntry) {\n if (uploadDataEntry.parentId !== undefined) {\n parentId = uploadDataEntry.parentId;\n }\n }\n\n return parentId;\n },\n\n getResumableFilesData: function() {\n return this._handler.getResumableFilesData();\n },\n\n getSize: function(id) {\n return this._uploadData.retrieve({id: id}).size;\n },\n\n getNetUploads: function() {\n return this._netUploaded;\n },\n\n getRemainingAllowedItems: function() {\n var allowedItems = this._currentItemLimit;\n\n if (allowedItems > 0) {\n return allowedItems - this._netUploadedOrQueued;\n }\n\n return null;\n },\n\n getUploads: function(optionalFilter) {\n return this._uploadData.retrieve(optionalFilter);\n },\n\n getUuid: function(id) {\n return this._uploadData.retrieve({id: id}).uuid;\n },\n\n isResumable: function(id) {\n return this._handler.hasResumeRecord(id);\n },\n\n log: function(str, level) {\n if (this._options.debug && (!level || level === \"info\")) {\n qq.log(\"[Fine Uploader \" + qq.version + \"] \" + str);\n }\n else if (level && level !== \"info\") {\n qq.log(\"[Fine Uploader \" + qq.version + \"] \" + str, level);\n\n }\n },\n\n pauseUpload: function(id) {\n var uploadData = this._uploadData.retrieve({id: id});\n\n if (!qq.supportedFeatures.pause || !this._options.chunking.enabled) {\n return false;\n }\n\n // Pause only really makes sense if the file is uploading or retrying\n if (qq.indexOf([qq.status.UPLOADING, qq.status.UPLOAD_RETRYING], uploadData.status) >= 0) {\n if (this._handler.pause(id)) {\n this._uploadData.setStatus(id, qq.status.PAUSED);\n return true;\n }\n else {\n this.log(qq.format(\"Unable to pause file ID {} ({}).\", id, this.getName(id)), \"error\");\n }\n }\n else {\n this.log(qq.format(\"Ignoring pause for file ID {} ({}). Not in progress.\", id, this.getName(id)), \"error\");\n }\n\n return false;\n },\n\n removeFileRef: function(id) {\n this._handler.expunge(id);\n this._uploadData.removeFileRef(id);\n },\n\n reset: function() {\n this.log(\"Resetting uploader...\");\n\n this._handler.reset();\n this._storedIds = [];\n this._autoRetries = [];\n this._retryTimeouts = [];\n this._preventRetries = [];\n this._thumbnailUrls = [];\n\n qq.each(this._buttons, function(idx, button) {\n button.reset();\n });\n\n this._paramsStore.reset();\n this._endpointStore.reset();\n this._netUploadedOrQueued = 0;\n this._netUploaded = 0;\n this._uploadData.reset();\n this._buttonIdsForFileIds = [];\n\n this._pasteHandler && this._pasteHandler.reset();\n this._options.session.refreshOnReset && this._refreshSessionData();\n\n this._succeededSinceLastAllComplete = [];\n this._failedSinceLastAllComplete = [];\n\n this._totalProgress && this._totalProgress.reset();\n\n this._customResumeDataStore.reset();\n },\n\n retry: function(id) {\n return this._manualRetry(id);\n },\n\n scaleImage: function(id, specs) {\n var self = this;\n\n return qq.Scaler.prototype.scaleImage(id, specs, {\n log: qq.bind(self.log, self),\n getFile: qq.bind(self.getFile, self),\n uploadData: self._uploadData\n });\n },\n\n setCustomHeaders: function(headers, id) {\n this._customHeadersStore.set(headers, id);\n },\n\n setCustomResumeData: function(id, data) {\n this._customResumeDataStore.set(data, id);\n },\n\n setDeleteFileCustomHeaders: function(headers, id) {\n this._deleteFileCustomHeadersStore.set(headers, id);\n },\n\n setDeleteFileEndpoint: function(endpoint, id) {\n this._deleteFileEndpointStore.set(endpoint, id);\n },\n\n setDeleteFileParams: function(params, id) {\n this._deleteFileParamsStore.set(params, id);\n },\n\n // Re-sets the default endpoint, an endpoint for a specific file, or an endpoint for a specific button\n setEndpoint: function(endpoint, id) {\n this._endpointStore.set(endpoint, id);\n },\n\n setForm: function(elementOrId) {\n this._updateFormSupportAndParams(elementOrId);\n },\n\n setItemLimit: function(newItemLimit) {\n this._currentItemLimit = newItemLimit;\n },\n\n setName: function(id, newName) {\n this._uploadData.updateName(id, newName);\n },\n\n setParams: function(params, id) {\n this._paramsStore.set(params, id);\n },\n\n setUuid: function(id, newUuid) {\n return this._uploadData.uuidChanged(id, newUuid);\n },\n\n /**\n * Expose the internal status of a file id to the public api for manual state changes\n * @public\n *\n * @param {Number} id,\n * @param {String} newStatus\n *\n * @todo Implement the remaining methods\n */\n setStatus: function(id, newStatus) {\n var fileRecord = this.getUploads({id: id});\n if (!fileRecord) {\n throw new qq.Error(id + \" is not a valid file ID.\");\n }\n\n switch (newStatus) {\n case qq.status.DELETED:\n this._onDeleteComplete(id, null, false);\n break;\n case qq.status.DELETE_FAILED:\n this._onDeleteComplete(id, null, true);\n break;\n default:\n var errorMessage = \"Method setStatus called on '\" + name + \"' not implemented yet for \" + newStatus;\n this.log(errorMessage);\n throw new qq.Error(errorMessage);\n }\n },\n\n uploadStoredFiles: function() {\n if (this._storedIds.length === 0) {\n this._itemError(\"noFilesError\");\n }\n else {\n this._uploadStoredFiles();\n }\n }\n };\n\n /**\n * Defines the private (internal) API for FineUploaderBasic mode.\n */\n qq.basePrivateApi = {\n // Updates internal state with a file record (not backed by a live file). Returns the assigned ID.\n _addCannedFile: function(sessionData) {\n var self = this;\n\n return this._uploadData.addFile({\n uuid: sessionData.uuid,\n name: sessionData.name,\n size: sessionData.size,\n status: qq.status.UPLOAD_SUCCESSFUL,\n onBeforeStatusChange: function(id) {\n sessionData.deleteFileEndpoint && self.setDeleteFileEndpoint(sessionData.deleteFileEndpoint, id);\n sessionData.deleteFileParams && self.setDeleteFileParams(sessionData.deleteFileParams, id);\n\n if (sessionData.thumbnailUrl) {\n self._thumbnailUrls[id] = sessionData.thumbnailUrl;\n }\n\n self._netUploaded++;\n self._netUploadedOrQueued++;\n }\n });\n },\n\n _annotateWithButtonId: function(file, associatedInput) {\n if (qq.isFile(file)) {\n file.qqButtonId = this._getButtonId(associatedInput);\n }\n },\n\n _batchError: function(message) {\n this._options.callbacks.onError(null, null, message, undefined);\n },\n\n _createDeleteHandler: function() {\n var self = this;\n\n return new qq.DeleteFileAjaxRequester({\n method: this._options.deleteFile.method.toUpperCase(),\n maxConnections: this._options.maxConnections,\n uuidParamName: this._options.request.uuidName,\n customHeaders: this._deleteFileCustomHeadersStore,\n paramsStore: this._deleteFileParamsStore,\n endpointStore: this._deleteFileEndpointStore,\n cors: this._options.cors,\n log: qq.bind(self.log, self),\n onDelete: function(id) {\n self._onDelete(id);\n self._options.callbacks.onDelete(id);\n },\n onDeleteComplete: function(id, xhrOrXdr, isError) {\n self._onDeleteComplete(id, xhrOrXdr, isError);\n self._options.callbacks.onDeleteComplete(id, xhrOrXdr, isError);\n }\n\n });\n },\n\n _createPasteHandler: function() {\n var self = this;\n\n return new qq.PasteSupport({\n targetElement: this._options.paste.targetElement,\n callbacks: {\n log: qq.bind(self.log, self),\n pasteReceived: function(blob) {\n self._handleCheckedCallback({\n name: \"onPasteReceived\",\n callback: qq.bind(self._options.callbacks.onPasteReceived, self, blob),\n onSuccess: qq.bind(self._handlePasteSuccess, self, blob),\n identifier: \"pasted image\"\n });\n }\n }\n });\n },\n\n _createStore: function(initialValue, _readOnlyValues_) {\n var store = {},\n catchall = initialValue,\n perIdReadOnlyValues = {},\n readOnlyValues = _readOnlyValues_,\n copy = function(orig) {\n if (qq.isObject(orig)) {\n return qq.extend({}, orig);\n }\n return orig;\n },\n getReadOnlyValues = function() {\n if (qq.isFunction(readOnlyValues)) {\n return readOnlyValues();\n }\n return readOnlyValues;\n },\n includeReadOnlyValues = function(id, existing) {\n if (readOnlyValues && qq.isObject(existing)) {\n qq.extend(existing, getReadOnlyValues());\n }\n\n if (perIdReadOnlyValues[id]) {\n qq.extend(existing, perIdReadOnlyValues[id]);\n }\n };\n\n return {\n set: function(val, id) {\n /*jshint eqeqeq: true, eqnull: true*/\n if (id == null) {\n store = {};\n catchall = copy(val);\n }\n else {\n store[id] = copy(val);\n }\n },\n\n get: function(id) {\n var values;\n\n /*jshint eqeqeq: true, eqnull: true*/\n if (id != null && store[id]) {\n values = store[id];\n }\n else {\n values = copy(catchall);\n }\n\n includeReadOnlyValues(id, values);\n\n return copy(values);\n },\n\n addReadOnly: function(id, values) {\n // Only applicable to Object stores\n if (qq.isObject(store)) {\n // If null ID, apply readonly values to all files\n if (id === null) {\n if (qq.isFunction(values)) {\n readOnlyValues = values;\n }\n else {\n readOnlyValues = readOnlyValues || {};\n qq.extend(readOnlyValues, values);\n }\n }\n else {\n perIdReadOnlyValues[id] = perIdReadOnlyValues[id] || {};\n qq.extend(perIdReadOnlyValues[id], values);\n }\n }\n },\n\n remove: function(fileId) {\n return delete store[fileId];\n },\n\n reset: function() {\n store = {};\n perIdReadOnlyValues = {};\n catchall = initialValue;\n }\n };\n },\n\n _createUploadDataTracker: function() {\n var self = this;\n\n return new qq.UploadData({\n getName: function(id) {\n return self.getName(id);\n },\n getUuid: function(id) {\n return self.getUuid(id);\n },\n getSize: function(id) {\n return self.getSize(id);\n },\n onStatusChange: function(id, oldStatus, newStatus) {\n self._onUploadStatusChange(id, oldStatus, newStatus);\n self._options.callbacks.onStatusChange(id, oldStatus, newStatus);\n self._maybeAllComplete(id, newStatus);\n\n if (self._totalProgress) {\n setTimeout(function() {\n self._totalProgress.onStatusChange(id, oldStatus, newStatus);\n }, 0);\n }\n }\n });\n },\n\n /**\n * Generate a tracked upload button.\n *\n * @param spec Object containing a required `element` property\n * along with optional `multiple`, `accept`, and `folders`.\n * @returns {qq.UploadButton}\n * @private\n */\n _createUploadButton: function(spec) {\n var self = this,\n acceptFiles = spec.accept || this._options.validation.acceptFiles,\n allowedExtensions = spec.allowedExtensions || this._options.validation.allowedExtensions,\n button;\n\n function allowMultiple() {\n if (qq.supportedFeatures.ajaxUploading) {\n // Workaround for bug in iOS7+ (see #1039)\n if (self._options.workarounds.iosEmptyVideos &&\n qq.ios() &&\n !qq.ios6() &&\n self._isAllowedExtension(allowedExtensions, \".mov\")) {\n\n return false;\n }\n\n if (spec.multiple === undefined) {\n return self._options.multiple;\n }\n\n return spec.multiple;\n }\n\n return false;\n }\n\n button = new qq.UploadButton({\n acceptFiles: acceptFiles,\n element: spec.element,\n focusClass: this._options.classes.buttonFocus,\n folders: spec.folders,\n hoverClass: this._options.classes.buttonHover,\n ios8BrowserCrashWorkaround: this._options.workarounds.ios8BrowserCrash,\n multiple: allowMultiple(),\n name: this._options.request.inputName,\n onChange: function(input) {\n self._onInputChange(input);\n },\n title: spec.title == null ? this._options.text.fileInputTitle : spec.title\n });\n\n this._disposeSupport.addDisposer(function() {\n button.dispose();\n });\n\n self._buttons.push(button);\n\n return button;\n },\n\n _createUploadHandler: function(additionalOptions, namespace) {\n var self = this,\n lastOnProgress = {},\n options = {\n debug: this._options.debug,\n maxConnections: this._options.maxConnections,\n cors: this._options.cors,\n paramsStore: this._paramsStore,\n endpointStore: this._endpointStore,\n chunking: this._options.chunking,\n resume: this._options.resume,\n blobs: this._options.blobs,\n log: qq.bind(self.log, self),\n preventRetryParam: this._options.retry.preventRetryResponseProperty,\n onProgress: function(id, name, loaded, total) {\n if (loaded < 0 || total < 0) {\n return;\n }\n\n if (lastOnProgress[id]) {\n if (lastOnProgress[id].loaded !== loaded || lastOnProgress[id].total !== total) {\n self._onProgress(id, name, loaded, total);\n self._options.callbacks.onProgress(id, name, loaded, total);\n }\n }\n else {\n self._onProgress(id, name, loaded, total);\n self._options.callbacks.onProgress(id, name, loaded, total);\n }\n\n lastOnProgress[id] = {loaded: loaded, total: total};\n\n },\n onComplete: function(id, name, result, xhr) {\n delete lastOnProgress[id];\n\n var status = self.getUploads({id: id}).status,\n retVal;\n\n // This is to deal with some observed cases where the XHR readyStateChange handler is\n // invoked by the browser multiple times for the same XHR instance with the same state\n // readyState value. Higher level: don't invoke complete-related code if we've already\n // done this.\n if (status === qq.status.UPLOAD_SUCCESSFUL || status === qq.status.UPLOAD_FAILED) {\n return;\n }\n\n retVal = self._onComplete(id, name, result, xhr);\n\n // If the internal `_onComplete` handler returns a promise, don't invoke the `onComplete` callback\n // until the promise has been fulfilled.\n if (retVal instanceof qq.Promise) {\n retVal.done(function() {\n self._options.callbacks.onComplete(id, name, result, xhr);\n });\n }\n else {\n self._options.callbacks.onComplete(id, name, result, xhr);\n }\n },\n onCancel: function(id, name, cancelFinalizationEffort) {\n var promise = new qq.Promise();\n\n self._handleCheckedCallback({\n name: \"onCancel\",\n callback: qq.bind(self._options.callbacks.onCancel, self, id, name),\n onFailure: promise.failure,\n onSuccess: function() {\n cancelFinalizationEffort.then(function() {\n self._onCancel(id, name);\n });\n\n promise.success();\n },\n identifier: id\n });\n\n return promise;\n },\n onUploadPrep: qq.bind(this._onUploadPrep, this),\n onUpload: function(id, name) {\n self._onUpload(id, name);\n var onUploadResult = self._options.callbacks.onUpload(id, name);\n\n if (qq.isGenericPromise(onUploadResult)) {\n self.log(qq.format(\"onUpload for {} returned a Promise - waiting for resolution.\", id));\n return onUploadResult;\n }\n\n return new qq.Promise().success();\n },\n onUploadChunk: function(id, name, chunkData) {\n self._onUploadChunk(id, chunkData);\n var onUploadChunkResult = self._options.callbacks.onUploadChunk(id, name, chunkData);\n\n if (qq.isGenericPromise(onUploadChunkResult)) {\n self.log(qq.format(\"onUploadChunk for {}.{} returned a Promise - waiting for resolution.\", id, chunkData.partIndex));\n return onUploadChunkResult;\n }\n\n return new qq.Promise().success();\n },\n onUploadChunkSuccess: function(id, chunkData, result, xhr) {\n self._onUploadChunkSuccess(id, chunkData);\n self._options.callbacks.onUploadChunkSuccess.apply(self, arguments);\n },\n onResume: function(id, name, chunkData, customResumeData) {\n return self._options.callbacks.onResume(id, name, chunkData, customResumeData);\n },\n onAutoRetry: function(id, name, responseJSON, xhr) {\n return self._onAutoRetry.apply(self, arguments);\n },\n onUuidChanged: function(id, newUuid) {\n self.log(\"Server requested UUID change from '\" + self.getUuid(id) + \"' to '\" + newUuid + \"'\");\n self.setUuid(id, newUuid);\n },\n getName: qq.bind(self.getName, self),\n getUuid: qq.bind(self.getUuid, self),\n getSize: qq.bind(self.getSize, self),\n setSize: qq.bind(self._setSize, self),\n getDataByUuid: function(uuid) {\n return self.getUploads({uuid: uuid});\n },\n isQueued: function(id) {\n var status = self.getUploads({id: id}).status;\n return status === qq.status.QUEUED ||\n status === qq.status.SUBMITTED ||\n status === qq.status.UPLOAD_RETRYING ||\n status === qq.status.PAUSED;\n },\n getIdsInProxyGroup: self._uploadData.getIdsInProxyGroup,\n getIdsInBatch: self._uploadData.getIdsInBatch,\n isInProgress: function(id) {\n return self.getUploads({id: id}).status === qq.status.UPLOADING;\n },\n getCustomResumeData: qq.bind(self._getCustomResumeData, self),\n setStatus: function(id, status) {\n self._uploadData.setStatus(id, status);\n }\n };\n\n qq.each(this._options.request, function(prop, val) {\n options[prop] = val;\n });\n\n options.customHeaders = this._customHeadersStore;\n\n if (additionalOptions) {\n qq.each(additionalOptions, function(key, val) {\n options[key] = val;\n });\n }\n\n return new qq.UploadHandlerController(options, namespace);\n },\n\n _fileOrBlobRejected: function(id) {\n this._netUploadedOrQueued--;\n this._uploadData.setStatus(id, qq.status.REJECTED);\n },\n\n _formatSize: function(bytes) {\n if (bytes === 0) {\n return bytes + this._options.text.sizeSymbols[0];\n }\n var i = -1;\n do {\n bytes = bytes / 1000;\n i++;\n } while (bytes > 999);\n\n return Math.max(bytes, 0.1).toFixed(1) + this._options.text.sizeSymbols[i];\n },\n\n // Creates an internal object that tracks various properties of each extra button,\n // and then actually creates the extra button.\n _generateExtraButtonSpecs: function() {\n var self = this;\n\n this._extraButtonSpecs = {};\n\n qq.each(this._options.extraButtons, function(idx, extraButtonOptionEntry) {\n var multiple = extraButtonOptionEntry.multiple,\n validation = qq.extend({}, self._options.validation, true),\n extraButtonSpec = qq.extend({}, extraButtonOptionEntry);\n\n if (multiple === undefined) {\n multiple = self._options.multiple;\n }\n\n if (extraButtonSpec.validation) {\n qq.extend(validation, extraButtonOptionEntry.validation, true);\n }\n\n qq.extend(extraButtonSpec, {\n multiple: multiple,\n validation: validation\n }, true);\n\n self._initExtraButton(extraButtonSpec);\n });\n },\n\n _getButton: function(buttonId) {\n var extraButtonsSpec = this._extraButtonSpecs[buttonId];\n\n if (extraButtonsSpec) {\n return extraButtonsSpec.element;\n }\n else if (buttonId === this._defaultButtonId) {\n return this._options.button;\n }\n },\n\n /**\n * Gets the internally used tracking ID for a button.\n *\n * @param buttonOrFileInputOrFile `File`, ` `, or a button container element\n * @returns {*} The button's ID, or undefined if no ID is recoverable\n * @private\n */\n _getButtonId: function(buttonOrFileInputOrFile) {\n var inputs, fileInput,\n fileBlobOrInput = buttonOrFileInputOrFile;\n\n // We want the reference file/blob here if this is a proxy (a file that will be generated on-demand later)\n if (fileBlobOrInput instanceof qq.BlobProxy) {\n fileBlobOrInput = fileBlobOrInput.referenceBlob;\n }\n\n // If the item is a `Blob` it will never be associated with a button or drop zone.\n if (fileBlobOrInput && !qq.isBlob(fileBlobOrInput)) {\n if (qq.isFile(fileBlobOrInput)) {\n return fileBlobOrInput.qqButtonId;\n }\n else if (fileBlobOrInput.tagName.toLowerCase() === \"input\" &&\n fileBlobOrInput.type.toLowerCase() === \"file\") {\n\n return fileBlobOrInput.getAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME);\n }\n\n inputs = fileBlobOrInput.getElementsByTagName(\"input\");\n\n qq.each(inputs, function(idx, input) {\n if (input.getAttribute(\"type\") === \"file\") {\n fileInput = input;\n return false;\n }\n });\n\n if (fileInput) {\n return fileInput.getAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME);\n }\n }\n },\n\n _getCustomResumeData: function(fileId) {\n return this._customResumeDataStore.get(fileId);\n },\n\n _getNotFinished: function() {\n return this._uploadData.retrieve({\n status: [\n qq.status.UPLOADING,\n qq.status.UPLOAD_RETRYING,\n qq.status.QUEUED,\n qq.status.SUBMITTING,\n qq.status.SUBMITTED,\n qq.status.PAUSED\n ]\n }).length;\n },\n\n // Get the validation options for this button. Could be the default validation option\n // or a specific one assigned to this particular button.\n _getValidationBase: function(buttonId) {\n var extraButtonSpec = this._extraButtonSpecs[buttonId];\n\n return extraButtonSpec ? extraButtonSpec.validation : this._options.validation;\n },\n\n _getValidationDescriptor: function(fileWrapper) {\n if (fileWrapper.file instanceof qq.BlobProxy) {\n return {\n name: qq.getFilename(fileWrapper.file.referenceBlob),\n size: fileWrapper.file.referenceBlob.size\n };\n }\n\n return {\n name: this.getUploads({id: fileWrapper.id}).name,\n size: this.getUploads({id: fileWrapper.id}).size\n };\n },\n\n _getValidationDescriptors: function(fileWrappers) {\n var self = this,\n fileDescriptors = [];\n\n qq.each(fileWrappers, function(idx, fileWrapper) {\n fileDescriptors.push(self._getValidationDescriptor(fileWrapper));\n });\n\n return fileDescriptors;\n },\n\n // Allows camera access on either the default or an extra button for iOS devices.\n _handleCameraAccess: function() {\n if (this._options.camera.ios && qq.ios()) {\n var acceptIosCamera = \"image/*;capture=camera\",\n button = this._options.camera.button,\n buttonId = button ? this._getButtonId(button) : this._defaultButtonId,\n optionRoot = this._options;\n\n // If we are not targeting the default button, it is an \"extra\" button\n if (buttonId && buttonId !== this._defaultButtonId) {\n optionRoot = this._extraButtonSpecs[buttonId];\n }\n\n // Camera access won't work in iOS if the `multiple` attribute is present on the file input\n optionRoot.multiple = false;\n\n // update the options\n if (optionRoot.validation.acceptFiles === null) {\n optionRoot.validation.acceptFiles = acceptIosCamera;\n }\n else {\n optionRoot.validation.acceptFiles += \",\" + acceptIosCamera;\n }\n\n // update the already-created button\n qq.each(this._buttons, function(idx, button) {\n if (button.getButtonId() === buttonId) {\n button.setMultiple(optionRoot.multiple);\n button.setAcceptFiles(optionRoot.acceptFiles);\n\n return false;\n }\n });\n }\n },\n\n _handleCheckedCallback: function(details) {\n var self = this,\n callbackRetVal = details.callback();\n\n if (qq.isGenericPromise(callbackRetVal)) {\n this.log(details.name + \" - waiting for \" + details.name + \" promise to be fulfilled for \" + details.identifier);\n return callbackRetVal.then(\n function(successParam) {\n self.log(details.name + \" promise success for \" + details.identifier);\n details.onSuccess(successParam);\n },\n function() {\n if (details.onFailure) {\n self.log(details.name + \" promise failure for \" + details.identifier);\n details.onFailure();\n }\n else {\n self.log(details.name + \" promise failure for \" + details.identifier);\n }\n });\n }\n\n if (callbackRetVal !== false) {\n details.onSuccess(callbackRetVal);\n }\n else {\n if (details.onFailure) {\n this.log(details.name + \" - return value was 'false' for \" + details.identifier + \". Invoking failure callback.\");\n details.onFailure();\n }\n else {\n this.log(details.name + \" - return value was 'false' for \" + details.identifier + \". Will not proceed.\");\n }\n }\n\n return callbackRetVal;\n },\n\n // Updates internal state when a new file has been received, and adds it along with its ID to a passed array.\n _handleNewFile: function(file, batchId, newFileWrapperList) {\n var self = this,\n uuid = qq.getUniqueId(),\n size = -1,\n name = qq.getFilename(file),\n actualFile = file.blob || file,\n handler = this._customNewFileHandler ?\n this._customNewFileHandler :\n qq.bind(self._handleNewFileGeneric, self);\n\n if (!qq.isInput(actualFile) && actualFile.size >= 0) {\n size = actualFile.size;\n }\n\n handler(actualFile, name, uuid, size, newFileWrapperList, batchId, this._options.request.uuidName, {\n uploadData: self._uploadData,\n paramsStore: self._paramsStore,\n addFileToHandler: function(id, file) {\n self._handler.add(id, file);\n self._netUploadedOrQueued++;\n self._trackButton(id);\n }\n });\n },\n\n _handleNewFileGeneric: function(file, name, uuid, size, fileList, batchId) {\n var id = this._uploadData.addFile({\n uuid: uuid,\n name: name,\n size: size,\n batchId: batchId,\n file: file\n });\n\n this._handler.add(id, file);\n\n this._trackButton(id);\n\n this._netUploadedOrQueued++;\n\n fileList.push({id: id, file: file});\n },\n\n _handlePasteSuccess: function(blob, extSuppliedName) {\n var extension = blob.type.split(\"/\")[1],\n name = extSuppliedName;\n\n /*jshint eqeqeq: true, eqnull: true*/\n if (name == null) {\n name = this._options.paste.defaultName;\n }\n\n name += \".\" + extension;\n\n this.addFiles({\n name: name,\n blob: blob\n });\n },\n\n _handleDeleteSuccess: function(id) {\n if (this.getUploads({id: id}).status !== qq.status.DELETED) {\n var name = this.getName(id);\n\n this._netUploadedOrQueued--;\n this._netUploaded--;\n this._handler.expunge(id);\n this._uploadData.setStatus(id, qq.status.DELETED);\n this.log(\"Delete request for '\" + name + \"' has succeeded.\");\n }\n },\n\n _handleDeleteFailed: function(id, xhrOrXdr) {\n var name = this.getName(id);\n\n this._uploadData.setStatus(id, qq.status.DELETE_FAILED);\n this.log(\"Delete request for '\" + name + \"' has failed.\", \"error\");\n\n // Check first if xhrOrXdr is actually passed or valid\n // For error reporting, we only have access to the response status if this is not\n // an `XDomainRequest`.\n if (!xhrOrXdr || xhrOrXdr.withCredentials === undefined) {\n this._options.callbacks.onError(id, name, \"Delete request failed\", xhrOrXdr);\n }\n else {\n this._options.callbacks.onError(id, name, \"Delete request failed with response code \" + xhrOrXdr.status, xhrOrXdr);\n }\n },\n\n // Creates an extra button element\n _initExtraButton: function(spec) {\n var button = this._createUploadButton({\n accept: spec.validation.acceptFiles,\n allowedExtensions: spec.validation.allowedExtensions,\n element: spec.element,\n folders: spec.folders,\n multiple: spec.multiple,\n title: spec.fileInputTitle\n });\n\n this._extraButtonSpecs[button.getButtonId()] = spec;\n },\n\n _initFormSupportAndParams: function() {\n this._formSupport = qq.FormSupport && new qq.FormSupport(\n this._options.form, qq.bind(this.uploadStoredFiles, this), qq.bind(this.log, this)\n );\n\n if (this._formSupport && this._formSupport.attachedToForm) {\n this._paramsStore = this._createStore(\n this._options.request.params, this._formSupport.getFormInputsAsObject\n );\n\n this._options.autoUpload = this._formSupport.newAutoUpload;\n if (this._formSupport.newEndpoint) {\n this._options.request.endpoint = this._formSupport.newEndpoint;\n }\n }\n else {\n this._paramsStore = this._createStore(this._options.request.params);\n }\n },\n\n _isDeletePossible: function() {\n if (!qq.DeleteFileAjaxRequester || !this._options.deleteFile.enabled) {\n return false;\n }\n\n if (this._options.cors.expected) {\n if (qq.supportedFeatures.deleteFileCorsXhr) {\n return true;\n }\n\n if (qq.supportedFeatures.deleteFileCorsXdr && this._options.cors.allowXdr) {\n return true;\n }\n\n return false;\n }\n\n return true;\n },\n\n _isAllowedExtension: function(allowed, fileName) {\n var valid = false;\n\n if (!allowed.length) {\n return true;\n }\n\n qq.each(allowed, function(idx, allowedExt) {\n /**\n * If an argument is not a string, ignore it. Added when a possible issue with MooTools hijacking the\n * `allowedExtensions` array was discovered. See case #735 in the issue tracker for more details.\n */\n if (qq.isString(allowedExt)) {\n /*jshint eqeqeq: true, eqnull: true*/\n var extRegex = new RegExp(\"\\\\.\" + allowedExt + \"$\", \"i\");\n\n if (fileName.match(extRegex) != null) {\n valid = true;\n return false;\n }\n }\n });\n\n return valid;\n },\n\n /**\n * Constructs and returns a message that describes an item/file error. Also calls `onError` callback.\n *\n * @param code REQUIRED - a code that corresponds to a stock message describing this type of error\n * @param maybeNameOrNames names of the items that have failed, if applicable\n * @param item `File`, `Blob`, or ` `\n * @private\n */\n _itemError: function(code, maybeNameOrNames, item) {\n var message = this._options.messages[code],\n allowedExtensions = [],\n names = [].concat(maybeNameOrNames),\n name = names[0],\n buttonId = this._getButtonId(item),\n validationBase = this._getValidationBase(buttonId),\n extensionsForMessage, placeholderMatch;\n\n function r(name, replacement) { message = message.replace(name, replacement); }\n\n qq.each(validationBase.allowedExtensions, function(idx, allowedExtension) {\n /**\n * If an argument is not a string, ignore it. Added when a possible issue with MooTools hijacking the\n * `allowedExtensions` array was discovered. See case #735 in the issue tracker for more details.\n */\n if (qq.isString(allowedExtension)) {\n allowedExtensions.push(allowedExtension);\n }\n });\n\n extensionsForMessage = allowedExtensions.join(\", \").toLowerCase();\n\n r(\"{file}\", this._options.formatFileName(name));\n r(\"{extensions}\", extensionsForMessage);\n r(\"{sizeLimit}\", this._formatSize(validationBase.sizeLimit));\n r(\"{minSizeLimit}\", this._formatSize(validationBase.minSizeLimit));\n\n placeholderMatch = message.match(/(\\{\\w+\\})/g);\n if (placeholderMatch !== null) {\n qq.each(placeholderMatch, function(idx, placeholder) {\n r(placeholder, names[idx]);\n });\n }\n\n this._options.callbacks.onError(null, name, message, undefined);\n\n return message;\n },\n\n /**\n * Conditionally orders a manual retry of a failed upload.\n *\n * @param id File ID of the failed upload\n * @param callback Optional callback to invoke if a retry is prudent.\n * In lieu of asking the upload handler to retry.\n * @returns {boolean} true if a manual retry will occur\n * @private\n */\n _manualRetry: function(id, callback) {\n if (this._onBeforeManualRetry(id)) {\n this._netUploadedOrQueued++;\n this._uploadData.setStatus(id, qq.status.UPLOAD_RETRYING);\n\n if (callback) {\n callback(id);\n }\n else {\n this._handler.retry(id);\n }\n\n return true;\n }\n },\n\n _maybeAllComplete: function(id, status) {\n var self = this,\n notFinished = this._getNotFinished();\n\n if (status === qq.status.UPLOAD_SUCCESSFUL) {\n this._succeededSinceLastAllComplete.push(id);\n }\n else if (status === qq.status.UPLOAD_FAILED) {\n this._failedSinceLastAllComplete.push(id);\n }\n\n if (notFinished === 0 &&\n (this._succeededSinceLastAllComplete.length || this._failedSinceLastAllComplete.length)) {\n // Attempt to ensure onAllComplete is not invoked before other callbacks, such as onCancel & onComplete\n setTimeout(function() {\n self._onAllComplete(self._succeededSinceLastAllComplete, self._failedSinceLastAllComplete);\n }, 0);\n }\n },\n\n _maybeHandleIos8SafariWorkaround: function() {\n var self = this;\n\n if (this._options.workarounds.ios8SafariUploads && qq.ios800() && qq.iosSafari()) {\n setTimeout(function() {\n window.alert(self._options.messages.unsupportedBrowserIos8Safari);\n }, 0);\n throw new qq.Error(this._options.messages.unsupportedBrowserIos8Safari);\n }\n },\n\n _maybeParseAndSendUploadError: function(id, name, response, xhr) {\n // Assuming no one will actually set the response code to something other than 200\n // and still set 'success' to true...\n if (!response.success) {\n if (xhr && xhr.status !== 200 && !response.error) {\n this._options.callbacks.onError(id, name, \"XHR returned response code \" + xhr.status, xhr);\n }\n else {\n var errorReason = response.error ? response.error : this._options.text.defaultResponseError;\n this._options.callbacks.onError(id, name, errorReason, xhr);\n }\n }\n },\n\n _maybeProcessNextItemAfterOnValidateCallback: function(validItem, items, index, params, endpoint) {\n var self = this;\n\n if (items.length > index) {\n if (validItem || !this._options.validation.stopOnFirstInvalidFile) {\n //use setTimeout to prevent a stack overflow with a large number of files in the batch & non-promissory callbacks\n setTimeout(function() {\n var validationDescriptor = self._getValidationDescriptor(items[index]),\n buttonId = self._getButtonId(items[index].file),\n button = self._getButton(buttonId);\n\n self._handleCheckedCallback({\n name: \"onValidate\",\n callback: qq.bind(self._options.callbacks.onValidate, self, validationDescriptor, button),\n onSuccess: qq.bind(self._onValidateCallbackSuccess, self, items, index, params, endpoint),\n onFailure: qq.bind(self._onValidateCallbackFailure, self, items, index, params, endpoint),\n identifier: \"Item '\" + validationDescriptor.name + \"', size: \" + validationDescriptor.size\n });\n }, 0);\n }\n else if (!validItem) {\n for (; index < items.length; index++) {\n self._fileOrBlobRejected(items[index].id);\n }\n }\n }\n },\n\n _onAllComplete: function(successful, failed) {\n this._totalProgress && this._totalProgress.onAllComplete(successful, failed, this._preventRetries);\n\n this._options.callbacks.onAllComplete(qq.extend([], successful), qq.extend([], failed));\n\n this._succeededSinceLastAllComplete = [];\n this._failedSinceLastAllComplete = [];\n },\n\n /**\n * Attempt to automatically retry a failed upload.\n *\n * @param id The file ID of the failed upload\n * @param name The name of the file associated with the failed upload\n * @param responseJSON Response from the server, parsed into a javascript object\n * @param xhr Ajax transport used to send the failed request\n * @param callback Optional callback to be invoked if a retry is prudent.\n * Invoked in lieu of asking the upload handler to retry.\n * @returns {boolean} true if an auto-retry will occur\n * @private\n */\n _onAutoRetry: function(id, name, responseJSON, xhr, callback) {\n var self = this;\n\n self._preventRetries[id] = responseJSON[self._options.retry.preventRetryResponseProperty];\n\n if (self._shouldAutoRetry(id)) {\n var retryWaitPeriod = self._options.retry.autoAttemptDelay * 1000;\n\n self._maybeParseAndSendUploadError.apply(self, arguments);\n self._options.callbacks.onAutoRetry(id, name, self._autoRetries[id]);\n self._onBeforeAutoRetry(id, name);\n\n self._uploadData.setStatus(id, qq.status.UPLOAD_RETRYING);\n self._retryTimeouts[id] = setTimeout(function() {\n self.log(\"Starting retry for \" + name + \"...\");\n\n if (callback) {\n callback(id);\n }\n else {\n self._handler.retry(id);\n }\n }, retryWaitPeriod);\n\n return true;\n }\n },\n\n _onBeforeAutoRetry: function(id, name) {\n this.log(\"Waiting \" + this._options.retry.autoAttemptDelay + \" seconds before retrying \" + name + \"...\");\n },\n\n //return false if we should not attempt the requested retry\n _onBeforeManualRetry: function(id) {\n var itemLimit = this._currentItemLimit,\n fileName;\n\n if (this._preventRetries[id]) {\n this.log(\"Retries are forbidden for id \" + id, \"warn\");\n return false;\n }\n else if (this._handler.isValid(id)) {\n fileName = this.getName(id);\n\n if (this._options.callbacks.onManualRetry(id, fileName) === false) {\n return false;\n }\n\n if (itemLimit > 0 && this._netUploadedOrQueued + 1 > itemLimit) {\n this._itemError(\"retryFailTooManyItems\");\n return false;\n }\n\n this.log(\"Retrying upload for '\" + fileName + \"' (id: \" + id + \")...\");\n return true;\n }\n else {\n this.log(\"'\" + id + \"' is not a valid file ID\", \"error\");\n return false;\n }\n },\n\n _onCancel: function(id, name) {\n this._netUploadedOrQueued--;\n\n clearTimeout(this._retryTimeouts[id]);\n\n var storedItemIndex = qq.indexOf(this._storedIds, id);\n if (!this._options.autoUpload && storedItemIndex >= 0) {\n this._storedIds.splice(storedItemIndex, 1);\n }\n\n this._uploadData.setStatus(id, qq.status.CANCELED);\n },\n\n _onComplete: function(id, name, result, xhr) {\n if (!result.success) {\n this._netUploadedOrQueued--;\n this._uploadData.setStatus(id, qq.status.UPLOAD_FAILED);\n\n if (result[this._options.retry.preventRetryResponseProperty] === true) {\n this._preventRetries[id] = true;\n }\n }\n else {\n if (result.thumbnailUrl) {\n this._thumbnailUrls[id] = result.thumbnailUrl;\n }\n\n this._netUploaded++;\n this._uploadData.setStatus(id, qq.status.UPLOAD_SUCCESSFUL);\n }\n\n this._maybeParseAndSendUploadError(id, name, result, xhr);\n\n return result.success ? true : false;\n },\n\n _onDelete: function(id) {\n this._uploadData.setStatus(id, qq.status.DELETING);\n },\n\n _onDeleteComplete: function(id, xhrOrXdr, isError) {\n var name = this.getName(id);\n\n if (isError) {\n this._handleDeleteFailed(id, xhrOrXdr);\n }\n else {\n this._handleDeleteSuccess(id);\n }\n },\n\n _onInputChange: function(input) {\n var fileIndex;\n\n if (qq.supportedFeatures.ajaxUploading) {\n for (fileIndex = 0; fileIndex < input.files.length; fileIndex++) {\n this._annotateWithButtonId(input.files[fileIndex], input);\n }\n\n this.addFiles(input.files);\n }\n // Android 2.3.x will fire `onchange` even if no file has been selected\n else if (input.value.length > 0) {\n this.addFiles(input);\n }\n\n qq.each(this._buttons, function(idx, button) {\n button.reset();\n });\n },\n\n _onProgress: function(id, name, loaded, total) {\n this._totalProgress && this._totalProgress.onIndividualProgress(id, loaded, total);\n },\n\n _onSubmit: function(id, name) {\n //nothing to do yet in core uploader\n },\n\n _onSubmitCallbackSuccess: function(id, name) {\n this._onSubmit.apply(this, arguments);\n this._uploadData.setStatus(id, qq.status.SUBMITTED);\n this._onSubmitted.apply(this, arguments);\n\n if (this._options.autoUpload) {\n this._options.callbacks.onSubmitted.apply(this, arguments);\n this._uploadFile(id);\n }\n else {\n this._storeForLater(id);\n this._options.callbacks.onSubmitted.apply(this, arguments);\n }\n },\n\n _onSubmitDelete: function(id, onSuccessCallback, additionalMandatedParams) {\n var uuid = this.getUuid(id),\n adjustedOnSuccessCallback;\n\n if (onSuccessCallback) {\n adjustedOnSuccessCallback = qq.bind(onSuccessCallback, this, id, uuid, additionalMandatedParams);\n }\n\n if (this._isDeletePossible()) {\n this._handleCheckedCallback({\n name: \"onSubmitDelete\",\n callback: qq.bind(this._options.callbacks.onSubmitDelete, this, id),\n onSuccess: adjustedOnSuccessCallback ||\n qq.bind(this._deleteHandler.sendDelete, this, id, uuid, additionalMandatedParams),\n identifier: id\n });\n return true;\n }\n else {\n this.log(\"Delete request ignored for ID \" + id + \", delete feature is disabled or request not possible \" +\n \"due to CORS on a user agent that does not support pre-flighting.\", \"warn\");\n return false;\n }\n },\n\n _onSubmitted: function(id) {\n //nothing to do in the base uploader\n },\n\n _onTotalProgress: function(loaded, total) {\n this._options.callbacks.onTotalProgress(loaded, total);\n },\n\n _onUploadPrep: function(id) {\n // nothing to do in the core uploader for now\n },\n\n _onUpload: function(id, name) {\n this._uploadData.setStatus(id, qq.status.UPLOADING);\n },\n\n _onUploadChunk: function(id, chunkData) {\n //nothing to do in the base uploader\n },\n\n _onUploadChunkSuccess: function(id, chunkData) {\n if (!this._preventRetries[id] && this._options.retry.enableAuto) {\n this._autoRetries[id] = 0;\n }\n },\n\n _onUploadStatusChange: function(id, oldStatus, newStatus) {\n // Make sure a \"queued\" retry attempt is canceled if the upload has been paused\n if (newStatus === qq.status.PAUSED) {\n clearTimeout(this._retryTimeouts[id]);\n }\n },\n\n _onValidateBatchCallbackFailure: function(fileWrappers) {\n var self = this;\n\n qq.each(fileWrappers, function(idx, fileWrapper) {\n self._fileOrBlobRejected(fileWrapper.id);\n });\n },\n\n _onValidateBatchCallbackSuccess: function(validationDescriptors, items, params, endpoint, button) {\n var errorMessage,\n itemLimit = this._currentItemLimit,\n proposedNetFilesUploadedOrQueued = this._netUploadedOrQueued;\n\n if (itemLimit === 0 || proposedNetFilesUploadedOrQueued <= itemLimit) {\n if (items.length > 0) {\n this._handleCheckedCallback({\n name: \"onValidate\",\n callback: qq.bind(this._options.callbacks.onValidate, this, validationDescriptors[0], button),\n onSuccess: qq.bind(this._onValidateCallbackSuccess, this, items, 0, params, endpoint),\n onFailure: qq.bind(this._onValidateCallbackFailure, this, items, 0, params, endpoint),\n identifier: \"Item '\" + items[0].file.name + \"', size: \" + items[0].file.size\n });\n }\n else {\n this._itemError(\"noFilesError\");\n }\n }\n else {\n this._onValidateBatchCallbackFailure(items);\n errorMessage = this._options.messages.tooManyItemsError\n .replace(/\\{netItems\\}/g, proposedNetFilesUploadedOrQueued)\n .replace(/\\{itemLimit\\}/g, itemLimit);\n this._batchError(errorMessage);\n }\n },\n\n _onValidateCallbackFailure: function(items, index, params, endpoint) {\n var nextIndex = index + 1;\n\n this._fileOrBlobRejected(items[index].id, items[index].file.name);\n\n this._maybeProcessNextItemAfterOnValidateCallback(false, items, nextIndex, params, endpoint);\n },\n\n _onValidateCallbackSuccess: function(items, index, params, endpoint) {\n var self = this,\n nextIndex = index + 1,\n validationDescriptor = this._getValidationDescriptor(items[index]);\n\n this._validateFileOrBlobData(items[index], validationDescriptor)\n .then(\n function() {\n self._upload(items[index].id, params, endpoint);\n self._maybeProcessNextItemAfterOnValidateCallback(true, items, nextIndex, params, endpoint);\n },\n function() {\n self._maybeProcessNextItemAfterOnValidateCallback(false, items, nextIndex, params, endpoint);\n }\n );\n },\n\n _prepareItemsForUpload: function(items, params, endpoint) {\n if (items.length === 0) {\n this._itemError(\"noFilesError\");\n return;\n }\n\n var validationDescriptors = this._getValidationDescriptors(items),\n buttonId = this._getButtonId(items[0].file),\n button = this._getButton(buttonId);\n\n this._handleCheckedCallback({\n name: \"onValidateBatch\",\n callback: qq.bind(this._options.callbacks.onValidateBatch, this, validationDescriptors, button),\n onSuccess: qq.bind(this._onValidateBatchCallbackSuccess, this, validationDescriptors, items, params, endpoint, button),\n onFailure: qq.bind(this._onValidateBatchCallbackFailure, this, items),\n identifier: \"batch validation\"\n });\n },\n\n _preventLeaveInProgress: function() {\n var self = this;\n\n this._disposeSupport.attach(window, \"beforeunload\", function(e) {\n if (self.getInProgress()) {\n e = e || window.event;\n // for ie, ff\n e.returnValue = self._options.messages.onLeave;\n // for webkit\n return self._options.messages.onLeave;\n }\n });\n },\n\n // Attempts to refresh session data only if the `qq.Session` module exists\n // and a session endpoint has been specified. The `onSessionRequestComplete`\n // callback will be invoked once the refresh is complete.\n _refreshSessionData: function() {\n var self = this,\n options = this._options.session;\n\n /* jshint eqnull:true */\n if (qq.Session && this._options.session.endpoint != null) {\n if (!this._session) {\n qq.extend(options, {cors: this._options.cors});\n\n options.log = qq.bind(this.log, this);\n options.addFileRecord = qq.bind(this._addCannedFile, this);\n\n this._session = new qq.Session(options);\n }\n\n setTimeout(function() {\n self._session.refresh().then(function(response, xhrOrXdr) {\n self._sessionRequestComplete();\n self._options.callbacks.onSessionRequestComplete(response, true, xhrOrXdr);\n\n }, function(response, xhrOrXdr) {\n\n self._options.callbacks.onSessionRequestComplete(response, false, xhrOrXdr);\n });\n }, 0);\n }\n },\n\n _sessionRequestComplete: function() {},\n\n _setSize: function(id, newSize) {\n this._uploadData.updateSize(id, newSize);\n this._totalProgress && this._totalProgress.onNewSize(id);\n },\n\n _shouldAutoRetry: function(id) {\n var uploadData = this._uploadData.retrieve({id: id});\n\n /*jshint laxbreak: true */\n if (!this._preventRetries[id]\n && this._options.retry.enableAuto\n && uploadData.status !== qq.status.PAUSED) {\n\n if (this._autoRetries[id] === undefined) {\n this._autoRetries[id] = 0;\n }\n\n if (this._autoRetries[id] < this._options.retry.maxAutoAttempts) {\n this._autoRetries[id] += 1;\n return true;\n }\n }\n\n return false;\n },\n\n _storeForLater: function(id) {\n this._storedIds.push(id);\n },\n\n // Maps a file with the button that was used to select it.\n _trackButton: function(id) {\n var buttonId;\n\n if (qq.supportedFeatures.ajaxUploading) {\n buttonId = this._handler.getFile(id).qqButtonId;\n }\n else {\n buttonId = this._getButtonId(this._handler.getInput(id));\n }\n\n if (buttonId) {\n this._buttonIdsForFileIds[id] = buttonId;\n }\n },\n\n _updateFormSupportAndParams: function(formElementOrId) {\n this._options.form.element = formElementOrId;\n\n this._formSupport = qq.FormSupport && new qq.FormSupport(\n this._options.form, qq.bind(this.uploadStoredFiles, this), qq.bind(this.log, this)\n );\n\n if (this._formSupport && this._formSupport.attachedToForm) {\n this._paramsStore.addReadOnly(null, this._formSupport.getFormInputsAsObject);\n\n this._options.autoUpload = this._formSupport.newAutoUpload;\n if (this._formSupport.newEndpoint) {\n this.setEndpoint(this._formSupport.newEndpoint);\n }\n }\n },\n\n _upload: function(id, params, endpoint) {\n var name = this.getName(id);\n\n if (params) {\n this.setParams(params, id);\n }\n\n if (endpoint) {\n this.setEndpoint(endpoint, id);\n }\n\n this._handleCheckedCallback({\n name: \"onSubmit\",\n callback: qq.bind(this._options.callbacks.onSubmit, this, id, name),\n onSuccess: qq.bind(this._onSubmitCallbackSuccess, this, id, name),\n onFailure: qq.bind(this._fileOrBlobRejected, this, id, name),\n identifier: id\n });\n },\n\n _uploadFile: function(id) {\n if (!this._handler.upload(id)) {\n this._uploadData.setStatus(id, qq.status.QUEUED);\n }\n },\n\n _uploadStoredFiles: function() {\n var idToUpload, stillSubmitting,\n self = this;\n\n while (this._storedIds.length) {\n idToUpload = this._storedIds.shift();\n this._uploadFile(idToUpload);\n }\n\n // If we are still waiting for some files to clear validation, attempt to upload these again in a bit\n stillSubmitting = this.getUploads({status: qq.status.SUBMITTING}).length;\n if (stillSubmitting) {\n qq.log(\"Still waiting for \" + stillSubmitting + \" files to clear submit queue. Will re-parse stored IDs array shortly.\");\n setTimeout(function() {\n self._uploadStoredFiles();\n }, 1000);\n }\n },\n\n /**\n * Performs some internal validation checks on an item, defined in the `validation` option.\n *\n * @param fileWrapper Wrapper containing a `file` along with an `id`\n * @param validationDescriptor Normalized information about the item (`size`, `name`).\n * @returns qq.Promise with appropriate callbacks invoked depending on the validity of the file\n * @private\n */\n _validateFileOrBlobData: function(fileWrapper, validationDescriptor) {\n var self = this,\n file = (function() {\n if (fileWrapper.file instanceof qq.BlobProxy) {\n return fileWrapper.file.referenceBlob;\n }\n return fileWrapper.file;\n }()),\n name = validationDescriptor.name,\n size = validationDescriptor.size,\n buttonId = this._getButtonId(fileWrapper.file),\n validationBase = this._getValidationBase(buttonId),\n validityChecker = new qq.Promise();\n\n validityChecker.then(\n function() {},\n function() {\n self._fileOrBlobRejected(fileWrapper.id, name);\n });\n\n if (qq.isFileOrInput(file) && !this._isAllowedExtension(validationBase.allowedExtensions, name)) {\n this._itemError(\"typeError\", name, file);\n return validityChecker.failure();\n }\n\n if (!this._options.validation.allowEmpty && size === 0) {\n this._itemError(\"emptyError\", name, file);\n return validityChecker.failure();\n }\n\n if (size > 0 && validationBase.sizeLimit && size > validationBase.sizeLimit) {\n this._itemError(\"sizeError\", name, file);\n return validityChecker.failure();\n }\n\n if (size > 0 && size < validationBase.minSizeLimit) {\n this._itemError(\"minSizeError\", name, file);\n return validityChecker.failure();\n }\n\n if (qq.ImageValidation && qq.supportedFeatures.imagePreviews && qq.isFile(file)) {\n new qq.ImageValidation(file, qq.bind(self.log, self)).validate(validationBase.image).then(\n validityChecker.success,\n function(errorCode) {\n self._itemError(errorCode + \"ImageError\", name, file);\n validityChecker.failure();\n }\n );\n }\n else {\n validityChecker.success();\n }\n\n return validityChecker;\n },\n\n _wrapCallbacks: function() {\n var self, safeCallback, prop;\n\n self = this;\n\n safeCallback = function(name, callback, args) {\n var errorMsg;\n\n try {\n return callback.apply(self, args);\n }\n catch (exception) {\n errorMsg = exception.message || exception.toString();\n self.log(\"Caught exception in '\" + name + \"' callback - \" + errorMsg, \"error\");\n }\n };\n\n /* jshint forin: false, loopfunc: true */\n for (prop in this._options.callbacks) {\n (function() {\n var callbackName, callbackFunc;\n callbackName = prop;\n callbackFunc = self._options.callbacks[callbackName];\n self._options.callbacks[callbackName] = function() {\n return safeCallback(callbackName, callbackFunc, arguments);\n };\n }());\n }\n }\n };\n}());\n","/*globals qq*/\n(function() {\n \"use strict\";\n\n qq.FineUploaderBasic = function(o) {\n var self = this;\n\n // These options define FineUploaderBasic mode.\n this._options = {\n debug: false,\n button: null,\n multiple: true,\n maxConnections: 3,\n disableCancelForFormUploads: false,\n autoUpload: true,\n warnBeforeUnload: true,\n\n request: {\n customHeaders: {},\n endpoint: \"/server/upload\",\n filenameParam: \"qqfilename\",\n forceMultipart: true,\n inputName: \"qqfile\",\n method: \"POST\",\n omitDefaultParams: false,\n params: {},\n paramsInBody: true,\n requireSuccessJson: true,\n totalFileSizeName: \"qqtotalfilesize\",\n uuidName: \"qquuid\"\n },\n\n validation: {\n allowedExtensions: [],\n sizeLimit: 0,\n minSizeLimit: 0,\n itemLimit: 0,\n stopOnFirstInvalidFile: true,\n acceptFiles: null,\n image: {\n maxHeight: 0,\n maxWidth: 0,\n minHeight: 0,\n minWidth: 0\n },\n allowEmpty: false\n },\n\n callbacks: {\n onSubmit: function(id, name) {},\n onSubmitted: function(id, name) {},\n onComplete: function(id, name, responseJSON, maybeXhr) {},\n onAllComplete: function(successful, failed) {},\n onCancel: function(id, name) {},\n onUpload: function(id, name) {},\n onUploadChunk: function(id, name, chunkData) {},\n onUploadChunkSuccess: function(id, chunkData, responseJSON, xhr) {},\n onResume: function(id, fileName, chunkData, customResumeData) {},\n onProgress: function(id, name, loaded, total) {},\n onTotalProgress: function(loaded, total) {},\n onError: function(id, name, reason, maybeXhrOrXdr) {},\n onAutoRetry: function(id, name, attemptNumber) {},\n onManualRetry: function(id, name) {},\n onValidateBatch: function(fileOrBlobData) {},\n onValidate: function(fileOrBlobData) {},\n onSubmitDelete: function(id) {},\n onDelete: function(id) {},\n onDeleteComplete: function(id, xhrOrXdr, isError) {},\n onPasteReceived: function(blob) {},\n onStatusChange: function(id, oldStatus, newStatus) {},\n onSessionRequestComplete: function(response, success, xhrOrXdr) {}\n },\n\n messages: {\n typeError: \"{file} has an invalid extension. Valid extension(s): {extensions}.\",\n sizeError: \"{file} is too large, maximum file size is {sizeLimit}.\",\n minSizeError: \"{file} is too small, minimum file size is {minSizeLimit}.\",\n emptyError: \"{file} is empty, please select files again without it.\",\n noFilesError: \"No files to upload.\",\n tooManyItemsError: \"Too many items ({netItems}) would be uploaded. Item limit is {itemLimit}.\",\n maxHeightImageError: \"Image is too tall.\",\n maxWidthImageError: \"Image is too wide.\",\n minHeightImageError: \"Image is not tall enough.\",\n minWidthImageError: \"Image is not wide enough.\",\n retryFailTooManyItems: \"Retry failed - you have reached your file limit.\",\n onLeave: \"The files are being uploaded, if you leave now the upload will be canceled.\",\n unsupportedBrowserIos8Safari: \"Unrecoverable error - this browser does not permit file uploading of any kind due to serious bugs in iOS8 Safari. Please use iOS8 Chrome until Apple fixes these issues.\"\n },\n\n retry: {\n enableAuto: false,\n maxAutoAttempts: 3,\n autoAttemptDelay: 5,\n preventRetryResponseProperty: \"preventRetry\"\n },\n\n classes: {\n buttonHover: \"qq-upload-button-hover\",\n buttonFocus: \"qq-upload-button-focus\"\n },\n\n chunking: {\n enabled: false,\n concurrent: {\n enabled: false\n },\n mandatory: false,\n paramNames: {\n partIndex: \"qqpartindex\",\n partByteOffset: \"qqpartbyteoffset\",\n chunkSize: \"qqchunksize\",\n totalFileSize: \"qqtotalfilesize\",\n totalParts: \"qqtotalparts\"\n },\n partSize: function(id) {\n return 2000000;\n },\n // only relevant for traditional endpoints, only required when concurrent.enabled === true\n success: {\n endpoint: null,\n\n headers: function(id) {\n return null;\n },\n\n jsonPayload: false,\n\n method: \"POST\",\n\n params: function(id) {\n return null;\n },\n\n resetOnStatus: []\n }\n },\n\n resume: {\n enabled: false,\n recordsExpireIn: 7, //days\n paramNames: {\n resuming: \"qqresume\"\n },\n customKeys: function(fileId) {\n return [];\n }\n },\n\n formatFileName: function(fileOrBlobName) {\n return fileOrBlobName;\n },\n\n text: {\n defaultResponseError: \"Upload failure reason unknown\",\n fileInputTitle: \"file input\",\n sizeSymbols: [\"kB\", \"MB\", \"GB\", \"TB\", \"PB\", \"EB\"]\n },\n\n deleteFile: {\n enabled: false,\n method: \"DELETE\",\n endpoint: \"/server/upload\",\n customHeaders: {},\n params: {}\n },\n\n cors: {\n expected: false,\n sendCredentials: false,\n allowXdr: false\n },\n\n blobs: {\n defaultName: \"misc_data\"\n },\n\n paste: {\n targetElement: null,\n defaultName: \"pasted_image\"\n },\n\n camera: {\n ios: false,\n\n // if ios is true: button is null means target the default button, otherwise target the button specified\n button: null\n },\n\n // This refers to additional upload buttons to be handled by Fine Uploader.\n // Each element is an object, containing `element` as the only required\n // property. The `element` must be a container that will ultimately\n // contain an invisible ` ` created by Fine Uploader.\n // Optional properties of each object include `multiple`, `validation`,\n // and `folders`.\n extraButtons: [],\n\n // Depends on the session module. Used to query the server for an initial file list\n // during initialization and optionally after a `reset`.\n session: {\n endpoint: null,\n params: {},\n customHeaders: {},\n refreshOnReset: true\n },\n\n // Send parameters associated with an existing form along with the files\n form: {\n // Element ID, HTMLElement, or null\n element: \"qq-form\",\n\n // Overrides the base `autoUpload`, unless `element` is null.\n autoUpload: false,\n\n // true = upload files on form submission (and squelch submit event)\n interceptSubmit: true\n },\n\n // scale images client side, upload a new file for each scaled version\n scaling: {\n customResizer: null,\n\n // send the original file as well\n sendOriginal: true,\n\n // fox orientation for scaled images\n orient: true,\n\n // If null, scaled image type will match reference image type. This value will be referred to\n // for any size record that does not specific a type.\n defaultType: null,\n\n defaultQuality: 80,\n\n failureText: \"Failed to scale\",\n\n includeExif: false,\n\n // metadata about each requested scaled version\n sizes: []\n },\n\n workarounds: {\n iosEmptyVideos: true,\n ios8SafariUploads: true,\n ios8BrowserCrash: false\n }\n };\n\n // Replace any default options with user defined ones\n qq.extend(this._options, o, true);\n\n this._buttons = [];\n this._extraButtonSpecs = {};\n this._buttonIdsForFileIds = [];\n\n this._wrapCallbacks();\n this._disposeSupport = new qq.DisposeSupport();\n\n this._storedIds = [];\n this._autoRetries = [];\n this._retryTimeouts = [];\n this._preventRetries = [];\n this._thumbnailUrls = [];\n\n this._netUploadedOrQueued = 0;\n this._netUploaded = 0;\n this._uploadData = this._createUploadDataTracker();\n\n this._initFormSupportAndParams();\n\n this._customHeadersStore = this._createStore(this._options.request.customHeaders);\n this._deleteFileCustomHeadersStore = this._createStore(this._options.deleteFile.customHeaders);\n\n this._deleteFileParamsStore = this._createStore(this._options.deleteFile.params);\n\n this._endpointStore = this._createStore(this._options.request.endpoint);\n this._deleteFileEndpointStore = this._createStore(this._options.deleteFile.endpoint);\n\n this._handler = this._createUploadHandler();\n\n this._deleteHandler = qq.DeleteFileAjaxRequester && this._createDeleteHandler();\n\n if (this._options.button) {\n this._defaultButtonId = this._createUploadButton({\n element: this._options.button,\n title: this._options.text.fileInputTitle\n }).getButtonId();\n }\n\n this._generateExtraButtonSpecs();\n\n this._handleCameraAccess();\n\n if (this._options.paste.targetElement) {\n if (qq.PasteSupport) {\n this._pasteHandler = this._createPasteHandler();\n }\n else {\n this.log(\"Paste support module not found\", \"error\");\n }\n }\n\n this._options.warnBeforeUnload && this._preventLeaveInProgress();\n\n this._imageGenerator = qq.ImageGenerator && new qq.ImageGenerator(qq.bind(this.log, this));\n this._refreshSessionData();\n\n this._succeededSinceLastAllComplete = [];\n this._failedSinceLastAllComplete = [];\n\n this._scaler = (qq.Scaler && new qq.Scaler(this._options.scaling, qq.bind(this.log, this))) || {};\n if (this._scaler.enabled) {\n this._customNewFileHandler = qq.bind(this._scaler.handleNewFile, this._scaler);\n }\n\n if (qq.TotalProgress && qq.supportedFeatures.progressBar) {\n this._totalProgress = new qq.TotalProgress(\n qq.bind(this._onTotalProgress, this),\n\n function(id) {\n var entry = self._uploadData.retrieve({id: id});\n return (entry && entry.size) || 0;\n }\n );\n }\n\n this._currentItemLimit = this._options.validation.itemLimit;\n\n this._customResumeDataStore = this._createStore();\n };\n\n // Define the private & public API methods.\n qq.FineUploaderBasic.prototype = qq.basePublicApi;\n qq.extend(qq.FineUploaderBasic.prototype, qq.basePrivateApi);\n}());\n","/*globals qq, XDomainRequest*/\n/** Generic class for sending non-upload ajax requests and handling the associated responses **/\nqq.AjaxRequester = function(o) {\n \"use strict\";\n\n var log, shouldParamsBeInQueryString,\n queue = [],\n requestData = {},\n options = {\n acceptHeader: null,\n validMethods: [\"PATCH\", \"POST\", \"PUT\"],\n method: \"POST\",\n contentType: \"application/x-www-form-urlencoded\",\n maxConnections: 3,\n customHeaders: {},\n endpointStore: {},\n paramsStore: {},\n mandatedParams: {},\n allowXRequestedWithAndCacheControl: true,\n successfulResponseCodes: {\n DELETE: [200, 202, 204],\n PATCH: [200, 201, 202, 203, 204],\n POST: [200, 201, 202, 203, 204],\n PUT: [200, 201, 202, 203, 204],\n GET: [200]\n },\n cors: {\n expected: false,\n sendCredentials: false\n },\n log: function(str, level) {},\n onSend: function(id) {},\n onComplete: function(id, xhrOrXdr, isError) {},\n onProgress: null\n };\n\n qq.extend(options, o);\n log = options.log;\n\n if (qq.indexOf(options.validMethods, options.method) < 0) {\n throw new Error(\"'\" + options.method + \"' is not a supported method for this type of request!\");\n }\n\n // [Simple methods](http://www.w3.org/TR/cors/#simple-method)\n // are defined by the W3C in the CORS spec as a list of methods that, in part,\n // make a CORS request eligible to be exempt from preflighting.\n function isSimpleMethod() {\n return qq.indexOf([\"GET\", \"POST\", \"HEAD\"], options.method) >= 0;\n }\n\n // [Simple headers](http://www.w3.org/TR/cors/#simple-header)\n // are defined by the W3C in the CORS spec as a list of headers that, in part,\n // make a CORS request eligible to be exempt from preflighting.\n function containsNonSimpleHeaders(headers) {\n var containsNonSimple = false;\n\n qq.each(containsNonSimple, function(idx, header) {\n if (qq.indexOf([\"Accept\", \"Accept-Language\", \"Content-Language\", \"Content-Type\"], header) < 0) {\n containsNonSimple = true;\n return false;\n }\n });\n\n return containsNonSimple;\n }\n\n function isXdr(xhr) {\n //The `withCredentials` test is a commonly accepted way to determine if XHR supports CORS.\n return options.cors.expected && xhr.withCredentials === undefined;\n }\n\n // Returns either a new `XMLHttpRequest` or `XDomainRequest` instance.\n function getCorsAjaxTransport() {\n var xhrOrXdr;\n\n if (window.XMLHttpRequest || window.ActiveXObject) {\n xhrOrXdr = qq.createXhrInstance();\n\n if (xhrOrXdr.withCredentials === undefined) {\n xhrOrXdr = new XDomainRequest();\n // Workaround for XDR bug in IE9 - https://social.msdn.microsoft.com/Forums/ie/en-US/30ef3add-767c-4436-b8a9-f1ca19b4812e/ie9-rtm-xdomainrequest-issued-requests-may-abort-if-all-event-handlers-not-specified?forum=iewebdevelopment\n xhrOrXdr.onload = function() {};\n xhrOrXdr.onerror = function() {};\n xhrOrXdr.ontimeout = function() {};\n xhrOrXdr.onprogress = function() {};\n }\n }\n\n return xhrOrXdr;\n }\n\n // Returns either a new XHR/XDR instance, or an existing one for the associated `File` or `Blob`.\n function getXhrOrXdr(id, suppliedXhr) {\n var xhrOrXdr = requestData[id] && requestData[id].xhr;\n\n if (!xhrOrXdr) {\n if (suppliedXhr) {\n xhrOrXdr = suppliedXhr;\n }\n else {\n if (options.cors.expected) {\n xhrOrXdr = getCorsAjaxTransport();\n }\n else {\n xhrOrXdr = qq.createXhrInstance();\n }\n }\n\n requestData[id].xhr = xhrOrXdr;\n }\n\n return xhrOrXdr;\n }\n\n // Removes element from queue, sends next request\n function dequeue(id) {\n var i = qq.indexOf(queue, id),\n max = options.maxConnections,\n nextId;\n\n delete requestData[id];\n queue.splice(i, 1);\n\n if (queue.length >= max && i < max) {\n nextId = queue[max - 1];\n sendRequest(nextId);\n }\n }\n\n function onComplete(id, xdrError) {\n var xhr = getXhrOrXdr(id),\n method = options.method,\n isError = xdrError === true;\n\n dequeue(id);\n\n if (isError) {\n log(method + \" request for \" + id + \" has failed\", \"error\");\n }\n else if (!isXdr(xhr) && !isResponseSuccessful(xhr.status)) {\n isError = true;\n log(method + \" request for \" + id + \" has failed - response code \" + xhr.status, \"error\");\n }\n\n options.onComplete(id, xhr, isError);\n }\n\n function getParams(id) {\n var onDemandParams = requestData[id].additionalParams,\n mandatedParams = options.mandatedParams,\n params;\n\n if (options.paramsStore.get) {\n params = options.paramsStore.get(id);\n }\n\n if (onDemandParams) {\n qq.each(onDemandParams, function(name, val) {\n params = params || {};\n params[name] = val;\n });\n }\n\n if (mandatedParams) {\n qq.each(mandatedParams, function(name, val) {\n params = params || {};\n params[name] = val;\n });\n }\n\n return params;\n }\n\n function sendRequest(id, optXhr) {\n var xhr = getXhrOrXdr(id, optXhr),\n method = options.method,\n params = getParams(id),\n payload = requestData[id].payload,\n url;\n\n options.onSend(id);\n\n url = createUrl(id, params, requestData[id].additionalQueryParams);\n\n // XDR and XHR status detection APIs differ a bit.\n if (isXdr(xhr)) {\n xhr.onload = getXdrLoadHandler(id);\n xhr.onerror = getXdrErrorHandler(id);\n }\n else {\n xhr.onreadystatechange = getXhrReadyStateChangeHandler(id);\n }\n\n registerForUploadProgress(id);\n\n // The last parameter is assumed to be ignored if we are actually using `XDomainRequest`.\n xhr.open(method, url, true);\n\n // Instruct the transport to send cookies along with the CORS request,\n // unless we are using `XDomainRequest`, which is not capable of this.\n if (options.cors.expected && options.cors.sendCredentials && !isXdr(xhr)) {\n xhr.withCredentials = true;\n }\n\n setHeaders(id);\n\n log(\"Sending \" + method + \" request for \" + id);\n\n if (payload) {\n xhr.send(payload);\n }\n else if (shouldParamsBeInQueryString || !params) {\n xhr.send();\n }\n else if (params && options.contentType && options.contentType.toLowerCase().indexOf(\"application/x-www-form-urlencoded\") >= 0) {\n xhr.send(qq.obj2url(params, \"\"));\n }\n else if (params && options.contentType && options.contentType.toLowerCase().indexOf(\"application/json\") >= 0) {\n xhr.send(JSON.stringify(params));\n }\n else {\n xhr.send(params);\n }\n\n return xhr;\n }\n\n function createUrl(id, params, additionalQueryParams) {\n var endpoint = options.endpointStore.get(id),\n addToPath = requestData[id].addToPath;\n\n /*jshint -W116,-W041 */\n if (addToPath != undefined) {\n endpoint += \"/\" + addToPath;\n }\n\n if (shouldParamsBeInQueryString && params) {\n endpoint = qq.obj2url(params, endpoint);\n }\n\n if (additionalQueryParams) {\n endpoint = qq.obj2url(additionalQueryParams, endpoint);\n }\n\n return endpoint;\n }\n\n // Invoked by the UA to indicate a number of possible states that describe\n // a live `XMLHttpRequest` transport.\n function getXhrReadyStateChangeHandler(id) {\n return function() {\n if (getXhrOrXdr(id).readyState === 4) {\n onComplete(id);\n }\n };\n }\n\n function registerForUploadProgress(id) {\n var onProgress = options.onProgress;\n\n if (onProgress) {\n getXhrOrXdr(id).upload.onprogress = function(e) {\n if (e.lengthComputable) {\n onProgress(id, e.loaded, e.total);\n }\n };\n }\n }\n\n // This will be called by IE to indicate **success** for an associated\n // `XDomainRequest` transported request.\n function getXdrLoadHandler(id) {\n return function() {\n onComplete(id);\n };\n }\n\n // This will be called by IE to indicate **failure** for an associated\n // `XDomainRequest` transported request.\n function getXdrErrorHandler(id) {\n return function() {\n onComplete(id, true);\n };\n }\n\n function setHeaders(id) {\n var xhr = getXhrOrXdr(id),\n customHeaders = options.customHeaders,\n onDemandHeaders = requestData[id].additionalHeaders || {},\n method = options.method,\n allHeaders = {};\n\n // If XDomainRequest is being used, we can't set headers, so just ignore this block.\n if (!isXdr(xhr)) {\n options.acceptHeader && xhr.setRequestHeader(\"Accept\", options.acceptHeader);\n\n // Only attempt to add X-Requested-With & Cache-Control if permitted\n if (options.allowXRequestedWithAndCacheControl) {\n // Do not add X-Requested-With & Cache-Control if this is a cross-origin request\n // OR the cross-origin request contains a non-simple method or header.\n // This is done to ensure a preflight is not triggered exclusively based on the\n // addition of these 2 non-simple headers.\n if (!options.cors.expected || (!isSimpleMethod() || containsNonSimpleHeaders(customHeaders))) {\n xhr.setRequestHeader(\"X-Requested-With\", \"XMLHttpRequest\");\n xhr.setRequestHeader(\"Cache-Control\", \"no-cache\");\n }\n }\n\n if (options.contentType && (method === \"POST\" || method === \"PUT\")) {\n xhr.setRequestHeader(\"Content-Type\", options.contentType);\n }\n\n qq.extend(allHeaders, qq.isFunction(customHeaders) ? customHeaders(id) : customHeaders);\n qq.extend(allHeaders, onDemandHeaders);\n\n qq.each(allHeaders, function(name, val) {\n xhr.setRequestHeader(name, val);\n });\n }\n }\n\n function isResponseSuccessful(responseCode) {\n return qq.indexOf(options.successfulResponseCodes[options.method], responseCode) >= 0;\n }\n\n function prepareToSend(id, optXhr, addToPath, additionalParams, additionalQueryParams, additionalHeaders, payload) {\n requestData[id] = {\n addToPath: addToPath,\n additionalParams: additionalParams,\n additionalQueryParams: additionalQueryParams,\n additionalHeaders: additionalHeaders,\n payload: payload\n };\n\n var len = queue.push(id);\n\n // if too many active connections, wait...\n if (len <= options.maxConnections) {\n return sendRequest(id, optXhr);\n }\n }\n\n shouldParamsBeInQueryString = options.method === \"GET\" || options.method === \"DELETE\";\n\n qq.extend(this, {\n // Start the process of sending the request. The ID refers to the file associated with the request.\n initTransport: function(id) {\n var path, params, headers, payload, cacheBuster, additionalQueryParams;\n\n return {\n // Optionally specify the end of the endpoint path for the request.\n withPath: function(appendToPath) {\n path = appendToPath;\n return this;\n },\n\n // Optionally specify additional parameters to send along with the request.\n // These will be added to the query string for GET/DELETE requests or the payload\n // for POST/PUT requests. The Content-Type of the request will be used to determine\n // how these parameters should be formatted as well.\n withParams: function(additionalParams) {\n params = additionalParams;\n return this;\n },\n\n withQueryParams: function(_additionalQueryParams_) {\n additionalQueryParams = _additionalQueryParams_;\n return this;\n },\n\n // Optionally specify additional headers to send along with the request.\n withHeaders: function(additionalHeaders) {\n headers = additionalHeaders;\n return this;\n },\n\n // Optionally specify a payload/body for the request.\n withPayload: function(thePayload) {\n payload = thePayload;\n return this;\n },\n\n // Appends a cache buster (timestamp) to the request URL as a query parameter (only if GET or DELETE)\n withCacheBuster: function() {\n cacheBuster = true;\n return this;\n },\n\n // Send the constructed request.\n send: function(optXhr) {\n if (cacheBuster && qq.indexOf([\"GET\", \"DELETE\"], options.method) >= 0) {\n params.qqtimestamp = new Date().getTime();\n }\n\n return prepareToSend(id, optXhr, path, params, additionalQueryParams, headers, payload);\n }\n };\n },\n\n canceled: function(id) {\n dequeue(id);\n }\n });\n};\n","/* globals qq */\n/**\n * Common upload handler functions.\n *\n * @constructor\n */\nqq.UploadHandler = function(spec) {\n \"use strict\";\n\n var proxy = spec.proxy,\n fileState = {},\n onCancel = proxy.onCancel,\n getName = proxy.getName;\n\n qq.extend(this, {\n add: function(id, fileItem) {\n fileState[id] = fileItem;\n fileState[id].temp = {};\n },\n\n cancel: function(id) {\n var self = this,\n cancelFinalizationEffort = new qq.Promise(),\n onCancelRetVal = onCancel(id, getName(id), cancelFinalizationEffort);\n\n onCancelRetVal.then(function() {\n if (self.isValid(id)) {\n fileState[id].canceled = true;\n self.expunge(id);\n }\n cancelFinalizationEffort.success();\n });\n },\n\n expunge: function(id) {\n delete fileState[id];\n },\n\n getThirdPartyFileId: function(id) {\n return fileState[id].key;\n },\n\n isValid: function(id) {\n return fileState[id] !== undefined;\n },\n\n reset: function() {\n fileState = {};\n },\n\n _getFileState: function(id) {\n return fileState[id];\n },\n\n _setThirdPartyFileId: function(id, thirdPartyFileId) {\n fileState[id].key = thirdPartyFileId;\n },\n\n _wasCanceled: function(id) {\n return !!fileState[id].canceled;\n }\n });\n};\n","/*globals qq*/\n/**\n * Base upload handler module. Controls more specific handlers.\n *\n * @param o Options. Passed along to the specific handler submodule as well.\n * @param namespace [optional] Namespace for the specific handler.\n */\nqq.UploadHandlerController = function(o, namespace) {\n \"use strict\";\n\n var controller = this,\n chunkingPossible = false,\n concurrentChunkingPossible = false,\n chunking, preventRetryResponse, log, handler,\n\n options = {\n paramsStore: {},\n maxConnections: 3, // maximum number of concurrent uploads\n chunking: {\n enabled: false,\n multiple: {\n enabled: false\n }\n },\n log: function(str, level) {},\n onProgress: function(id, fileName, loaded, total) {},\n onComplete: function(id, fileName, response, xhr) {},\n onCancel: function(id, fileName) {},\n onUploadPrep: function(id) {}, // Called if non-trivial operations will be performed before onUpload\n onUpload: function(id, fileName) {},\n onUploadChunk: function(id, fileName, chunkData) {},\n onUploadChunkSuccess: function(id, chunkData, response, xhr) {},\n onAutoRetry: function(id, fileName, response, xhr) {},\n onResume: function(id, fileName, chunkData, customResumeData) {},\n onUuidChanged: function(id, newUuid) {},\n getName: function(id) {},\n setSize: function(id, newSize) {},\n isQueued: function(id) {},\n getIdsInProxyGroup: function(id) {},\n getIdsInBatch: function(id) {},\n isInProgress: function(id) {}\n },\n\n chunked = {\n // Called when each chunk has uploaded successfully\n done: function(id, chunkIdx, response, xhr) {\n var chunkData = handler._getChunkData(id, chunkIdx);\n\n handler._getFileState(id).attemptingResume = false;\n\n delete handler._getFileState(id).temp.chunkProgress[chunkIdx];\n handler._getFileState(id).loaded += chunkData.size;\n\n options.onUploadChunkSuccess(id, handler._getChunkDataForCallback(chunkData), response, xhr);\n },\n\n // Called when all chunks have been successfully uploaded and we want to ask the handler to perform any\n // logic associated with closing out the file, such as combining the chunks.\n finalize: function(id) {\n var size = options.getSize(id),\n name = options.getName(id);\n\n log(\"All chunks have been uploaded for \" + id + \" - finalizing....\");\n handler.finalizeChunks(id).then(\n function(response, xhr) {\n log(\"Finalize successful for \" + id);\n\n var normaizedResponse = upload.normalizeResponse(response, true);\n\n options.onProgress(id, name, size, size);\n handler._maybeDeletePersistedChunkData(id);\n upload.cleanup(id, normaizedResponse, xhr);\n },\n function(response, xhr) {\n var normalizedResponse = upload.normalizeResponse(response, false);\n\n log(\"Problem finalizing chunks for file ID \" + id + \" - \" + normalizedResponse.error, \"error\");\n\n if (\n normalizedResponse.reset ||\n (xhr && options.chunking.success.resetOnStatus.indexOf(xhr.status) >= 0)\n ) {\n chunked.reset(id);\n }\n\n if (!options.onAutoRetry(id, name, normalizedResponse, xhr)) {\n upload.cleanup(id, normalizedResponse, xhr);\n }\n }\n );\n },\n\n handleFailure: function(chunkIdx, id, response, xhr) {\n var name = options.getName(id);\n\n log(\"Chunked upload request failed for \" + id + \", chunk \" + chunkIdx);\n\n handler.clearCachedChunk(id, chunkIdx);\n\n var responseToReport = upload.normalizeResponse(response, false),\n inProgressIdx;\n\n if (responseToReport.reset) {\n chunked.reset(id);\n }\n else {\n var inProgressChunksArray = handler._getFileState(id).chunking.inProgress;\n\n inProgressIdx = inProgressChunksArray ? qq.indexOf(inProgressChunksArray, chunkIdx) : -1;\n if (inProgressIdx >= 0) {\n handler._getFileState(id).chunking.inProgress.splice(inProgressIdx, 1);\n handler._getFileState(id).chunking.remaining.unshift(chunkIdx);\n }\n }\n\n // We may have aborted all other in-progress chunks for this file due to a failure.\n // If so, ignore the failures associated with those aborts.\n if (!handler._getFileState(id).temp.ignoreFailure) {\n // If this chunk has failed, we want to ignore all other failures of currently in-progress\n // chunks since they will be explicitly aborted\n if (concurrentChunkingPossible) {\n handler._getFileState(id).temp.ignoreFailure = true;\n\n log(qq.format(\"Going to attempt to abort these chunks: {}. These are currently in-progress: {}.\", JSON.stringify(Object.keys(handler._getXhrs(id))), JSON.stringify(handler._getFileState(id).chunking.inProgress)));\n qq.each(handler._getXhrs(id), function(ckid, ckXhr) {\n log(qq.format(\"Attempting to abort file {}.{}. XHR readyState {}. \", id, ckid, ckXhr.readyState));\n ckXhr.abort();\n // Flag the transport, in case we are waiting for some other async operation\n // to complete before attempting to upload the chunk\n ckXhr._cancelled = true;\n });\n\n // We must indicate that all aborted chunks are no longer in progress\n handler.moveInProgressToRemaining(id);\n\n // Free up any connections used by these chunks, but don't allow any\n // other files to take up the connections (until we have exhausted all auto-retries)\n connectionManager.free(id, true);\n }\n\n if (!options.onAutoRetry(id, name, responseToReport, xhr)) {\n // If one chunk fails, abort all of the others to avoid odd race conditions that occur\n // if a chunk succeeds immediately after one fails before we have determined if the upload\n // is a failure or not.\n upload.cleanup(id, responseToReport, xhr);\n }\n }\n },\n\n hasMoreParts: function(id) {\n return !!handler._getFileState(id).chunking.remaining.length;\n },\n\n nextPart: function(id) {\n var nextIdx = handler._getFileState(id).chunking.remaining.shift();\n\n if (nextIdx >= handler._getTotalChunks(id)) {\n nextIdx = null;\n }\n\n return nextIdx;\n },\n\n reset: function(id) {\n log(\"Server or callback has ordered chunking effort to be restarted on next attempt for item ID \" + id, \"error\");\n\n handler._maybeDeletePersistedChunkData(id);\n handler.reevaluateChunking(id);\n handler._getFileState(id).loaded = 0;\n handler._getFileState(id).attemptingResume = false;\n },\n\n sendNext: function(id) {\n var size = options.getSize(id),\n name = options.getName(id),\n chunkIdx = chunked.nextPart(id),\n chunkData = handler._getChunkData(id, chunkIdx),\n fileState = handler._getFileState(id),\n resuming = fileState.attemptingResume,\n inProgressChunks = fileState.chunking.inProgress || [];\n\n if (fileState.loaded == null) {\n fileState.loaded = 0;\n }\n\n // Don't follow-through with the resume attempt if the integrator returns false from onResume\n if (resuming && options.onResume(id, name, chunkData, fileState.customResumeData) === false) {\n chunked.reset(id);\n chunkIdx = chunked.nextPart(id);\n chunkData = handler._getChunkData(id, chunkIdx);\n resuming = false;\n }\n\n // If all chunks have already uploaded successfully, we must be re-attempting the finalize step.\n if (chunkIdx == null && inProgressChunks.length === 0) {\n chunked.finalize(id);\n }\n\n // Send the next chunk\n else {\n inProgressChunks.push(chunkIdx);\n handler._getFileState(id).chunking.inProgress = inProgressChunks;\n\n if (concurrentChunkingPossible) {\n connectionManager.open(id, chunkIdx);\n }\n\n if (concurrentChunkingPossible && connectionManager.available() && handler._getFileState(id).chunking.remaining.length) {\n chunked.sendNext(id);\n }\n\n if (chunkData.blob.size === 0) {\n log(qq.format(\"Chunk {} for file {} will not be uploaded, zero sized chunk.\", chunkIdx, id), \"error\");\n chunked.handleFailure(chunkIdx, id, \"File is no longer available\", null);\n }\n\n var onUploadChunkPromise = options.onUploadChunk(id, name, handler._getChunkDataForCallback(chunkData));\n\n onUploadChunkPromise.then(\n function(requestOverrides) {\n if (!options.isInProgress(id)) {\n log(qq.format(\"Not sending chunked upload request for item {}.{} - no longer in progress.\", id, chunkIdx));\n }\n else {\n log(qq.format(\"Sending chunked upload request for item {}.{}, bytes {}-{} of {}.\", id, chunkIdx, chunkData.start + 1, chunkData.end, size));\n\n var uploadChunkData = {\n chunkIdx: chunkIdx,\n id: id,\n overrides: requestOverrides,\n resuming: resuming\n };\n\n handler.uploadChunk(uploadChunkData).then(\n // upload chunk success\n function success(response, xhr) {\n log(\"Chunked upload request succeeded for \" + id + \", chunk \" + chunkIdx);\n\n handler.clearCachedChunk(id, chunkIdx);\n\n var inProgressChunks = handler._getFileState(id).chunking.inProgress || [],\n responseToReport = upload.normalizeResponse(response, true),\n inProgressChunkIdx = qq.indexOf(inProgressChunks, chunkIdx);\n\n log(qq.format(\"Chunk {} for file {} uploaded successfully.\", chunkIdx, id));\n\n chunked.done(id, chunkIdx, responseToReport, xhr);\n\n if (inProgressChunkIdx >= 0) {\n inProgressChunks.splice(inProgressChunkIdx, 1);\n }\n\n handler._maybePersistChunkedState(id);\n\n if (!chunked.hasMoreParts(id) && inProgressChunks.length === 0) {\n chunked.finalize(id);\n }\n else if (chunked.hasMoreParts(id)) {\n chunked.sendNext(id);\n }\n else {\n log(qq.format(\"File ID {} has no more chunks to send and these chunk indexes are still marked as in-progress: {}\", id, JSON.stringify(inProgressChunks)));\n }\n },\n\n // upload chunk failure\n function failure(response, xhr) {\n chunked.handleFailure(chunkIdx, id, response, xhr);\n }\n )\n .done(function () {\n handler.clearXhr(id, chunkIdx);\n });\n }\n },\n\n function(error) {\n chunked.handleFailure(chunkIdx, id, error, null);\n }\n );\n }\n }\n },\n\n connectionManager = {\n _open: [],\n _openChunks: {},\n _waiting: [],\n\n available: function() {\n var max = options.maxConnections,\n openChunkEntriesCount = 0,\n openChunksCount = 0;\n\n qq.each(connectionManager._openChunks, function(fileId, openChunkIndexes) {\n openChunkEntriesCount++;\n openChunksCount += openChunkIndexes.length;\n });\n\n return max - (connectionManager._open.length - openChunkEntriesCount + openChunksCount);\n },\n\n /**\n * Removes element from queue, starts upload of next\n */\n free: function(id, dontAllowNext) {\n var allowNext = !dontAllowNext,\n waitingIndex = qq.indexOf(connectionManager._waiting, id),\n connectionsIndex = qq.indexOf(connectionManager._open, id),\n nextId;\n\n delete connectionManager._openChunks[id];\n\n if (upload.getProxyOrBlob(id) instanceof qq.BlobProxy) {\n log(\"Generated blob upload has ended for \" + id + \", disposing generated blob.\");\n delete handler._getFileState(id).file;\n }\n\n // If this file was not consuming a connection, it was just waiting, so remove it from the waiting array\n if (waitingIndex >= 0) {\n connectionManager._waiting.splice(waitingIndex, 1);\n }\n // If this file was consuming a connection, allow the next file to be uploaded\n else if (allowNext && connectionsIndex >= 0) {\n connectionManager._open.splice(connectionsIndex, 1);\n\n nextId = connectionManager._waiting.shift();\n if (nextId >= 0) {\n connectionManager._open.push(nextId);\n upload.start(nextId);\n }\n }\n },\n\n getWaitingOrConnected: function() {\n var waitingOrConnected = [];\n\n // Chunked files may have multiple connections open per chunk (if concurrent chunking is enabled)\n // We need to grab the file ID of any file that has at least one chunk consuming a connection.\n qq.each(connectionManager._openChunks, function(fileId, chunks) {\n if (chunks && chunks.length) {\n waitingOrConnected.push(parseInt(fileId));\n }\n });\n\n // For non-chunked files, only one connection will be consumed per file.\n // This is where we aggregate those file IDs.\n qq.each(connectionManager._open, function(idx, fileId) {\n if (!connectionManager._openChunks[fileId]) {\n waitingOrConnected.push(parseInt(fileId));\n }\n });\n\n // There may be files waiting for a connection.\n waitingOrConnected = waitingOrConnected.concat(connectionManager._waiting);\n\n return waitingOrConnected;\n },\n\n isUsingConnection: function(id) {\n return qq.indexOf(connectionManager._open, id) >= 0;\n },\n\n open: function(id, chunkIdx) {\n if (chunkIdx == null) {\n connectionManager._waiting.push(id);\n }\n\n if (connectionManager.available()) {\n if (chunkIdx == null) {\n connectionManager._waiting.pop();\n connectionManager._open.push(id);\n }\n else {\n (function() {\n var openChunksEntry = connectionManager._openChunks[id] || [];\n openChunksEntry.push(chunkIdx);\n connectionManager._openChunks[id] = openChunksEntry;\n }());\n }\n\n return true;\n }\n\n return false;\n },\n\n reset: function() {\n connectionManager._waiting = [];\n connectionManager._open = [];\n }\n },\n\n simple = {\n send: function(id, name) {\n var fileState = handler._getFileState(id);\n\n if (!fileState) {\n log(\"Ignoring send request as this upload may have been cancelled, File ID \" + id, \"warn\");\n return;\n }\n\n fileState.loaded = 0;\n\n log(\"Sending simple upload request for \" + id);\n handler.uploadFile(id).then(\n function(response, optXhr) {\n log(\"Simple upload request succeeded for \" + id);\n\n var responseToReport = upload.normalizeResponse(response, true),\n size = options.getSize(id);\n\n options.onProgress(id, name, size, size);\n upload.maybeNewUuid(id, responseToReport);\n upload.cleanup(id, responseToReport, optXhr);\n },\n\n function(response, optXhr) {\n log(\"Simple upload request failed for \" + id);\n\n var responseToReport = upload.normalizeResponse(response, false);\n\n if (!options.onAutoRetry(id, name, responseToReport, optXhr)) {\n upload.cleanup(id, responseToReport, optXhr);\n }\n }\n );\n }\n },\n\n upload = {\n cancel: function(id) {\n log(\"Cancelling \" + id);\n options.paramsStore.remove(id);\n connectionManager.free(id);\n },\n\n cleanup: function(id, response, optXhr) {\n var name = options.getName(id);\n\n options.onComplete(id, name, response, optXhr);\n\n if (handler._getFileState(id)) {\n handler._clearXhrs && handler._clearXhrs(id);\n }\n\n connectionManager.free(id);\n },\n\n // Returns a qq.BlobProxy, or an actual File/Blob if no proxy is involved, or undefined\n // if none of these are available for the ID\n getProxyOrBlob: function(id) {\n return (handler.getProxy && handler.getProxy(id)) ||\n (handler.getFile && handler.getFile(id));\n },\n\n initHandler: function() {\n var handlerType = namespace ? qq[namespace] : qq.traditional,\n handlerModuleSubtype = qq.supportedFeatures.ajaxUploading ? \"Xhr\" : \"Form\";\n\n handler = new handlerType[handlerModuleSubtype + \"UploadHandler\"](\n options,\n {\n getCustomResumeData: options.getCustomResumeData,\n getDataByUuid: options.getDataByUuid,\n getName: options.getName,\n getSize: options.getSize,\n getUuid: options.getUuid,\n log: log,\n onCancel: options.onCancel,\n onProgress: options.onProgress,\n onUuidChanged: options.onUuidChanged,\n onFinalizing: function(id) {\n options.setStatus(id, qq.status.UPLOAD_FINALIZING);\n }\n }\n );\n\n if (handler._removeExpiredChunkingRecords) {\n handler._removeExpiredChunkingRecords();\n }\n },\n\n isDeferredEligibleForUpload: function(id) {\n return options.isQueued(id);\n },\n\n // For Blobs that are part of a group of generated images, along with a reference image,\n // this will ensure the blobs in the group are uploaded in the order they were triggered,\n // even if some async processing must be completed on one or more Blobs first.\n maybeDefer: function(id, blob) {\n // If we don't have a file/blob yet & no file/blob exists for this item, request it,\n // and then submit the upload to the specific handler once the blob is available.\n // ASSUMPTION: This condition will only ever be true if XHR uploading is supported.\n if (blob && !handler.getFile(id) && blob instanceof qq.BlobProxy) {\n\n // Blob creation may take some time, so the caller may want to update the\n // UI to indicate that an operation is in progress, even before the actual\n // upload begins and an onUpload callback is invoked.\n options.onUploadPrep(id);\n\n log(\"Attempting to generate a blob on-demand for \" + id);\n blob.create().then(function(generatedBlob) {\n log(\"Generated an on-demand blob for \" + id);\n\n // Update record associated with this file by providing the generated Blob\n handler.updateBlob(id, generatedBlob);\n\n // Propagate the size for this generated Blob\n options.setSize(id, generatedBlob.size);\n\n // Order handler to recalculate chunking possibility, if applicable\n handler.reevaluateChunking(id);\n\n upload.maybeSendDeferredFiles(id);\n },\n\n // Blob could not be generated. Fail the upload & attempt to prevent retries. Also bubble error message.\n function(errorMessage) {\n var errorResponse = {};\n\n if (errorMessage) {\n errorResponse.error = errorMessage;\n }\n\n log(qq.format(\"Failed to generate blob for ID {}. Error message: {}.\", id, errorMessage), \"error\");\n\n options.onComplete(id, options.getName(id), qq.extend(errorResponse, preventRetryResponse), null);\n upload.maybeSendDeferredFiles(id);\n connectionManager.free(id);\n });\n }\n else {\n return upload.maybeSendDeferredFiles(id);\n }\n\n return false;\n },\n\n // Upload any grouped blobs, in the proper order, that are ready to be uploaded\n maybeSendDeferredFiles: function(id) {\n var idsInGroup = options.getIdsInProxyGroup(id),\n uploadedThisId = false;\n\n if (idsInGroup && idsInGroup.length) {\n log(\"Maybe ready to upload proxy group file \" + id);\n\n qq.each(idsInGroup, function(idx, idInGroup) {\n if (upload.isDeferredEligibleForUpload(idInGroup) && !!handler.getFile(idInGroup)) {\n uploadedThisId = idInGroup === id;\n upload.now(idInGroup);\n }\n else if (upload.isDeferredEligibleForUpload(idInGroup)) {\n return false;\n }\n });\n }\n else {\n uploadedThisId = true;\n upload.now(id);\n }\n\n return uploadedThisId;\n },\n\n maybeNewUuid: function(id, response) {\n if (response.newUuid !== undefined) {\n options.onUuidChanged(id, response.newUuid);\n }\n },\n\n // The response coming from handler implementations may be in various formats.\n // Instead of hoping a promise nested 5 levels deep will always return an object\n // as its first param, let's just normalize the response here.\n normalizeResponse: function(originalResponse, successful) {\n var response = originalResponse;\n\n // The passed \"response\" param may not be a response at all.\n // It could be a string, detailing the error, for example.\n if (!qq.isObject(originalResponse)) {\n response = {};\n\n if (qq.isString(originalResponse) && !successful) {\n response.error = originalResponse;\n }\n }\n\n response.success = successful;\n\n return response;\n },\n\n now: function(id) {\n var name = options.getName(id);\n\n if (!controller.isValid(id)) {\n throw new qq.Error(id + \" is not a valid file ID to upload!\");\n }\n\n options.onUpload(id, name).then(\n function(response) {\n if (response && response.pause) {\n options.setStatus(id, qq.status.PAUSED);\n handler.pause(id);\n connectionManager.free(id);\n }\n else {\n if (chunkingPossible && handler._shouldChunkThisFile(id)) {\n chunked.sendNext(id);\n }\n else {\n simple.send(id, name);\n }\n }\n },\n\n function(error) {\n error = error || {};\n\n log(id + \" upload start aborted due to rejected onUpload Promise - details: \" + error, \"error\");\n\n if (!options.onAutoRetry(id, name, error.responseJSON || {})) {\n var response = upload.normalizeResponse(error.responseJSON, false);\n upload.cleanup(id, response);\n }\n }\n );\n },\n\n start: function(id) {\n var blobToUpload = upload.getProxyOrBlob(id);\n\n if (blobToUpload) {\n return upload.maybeDefer(id, blobToUpload);\n }\n else {\n upload.now(id);\n return true;\n }\n }\n };\n\n qq.extend(this, {\n /**\n * Adds file or file input to the queue\n **/\n add: function(id, file) {\n handler.add.apply(this, arguments);\n },\n\n /**\n * Sends the file identified by id\n */\n upload: function(id) {\n if (connectionManager.open(id)) {\n return upload.start(id);\n }\n return false;\n },\n\n retry: function(id) {\n // On retry, if concurrent chunking has been enabled, we may have aborted all other in-progress chunks\n // for a file when encountering a failed chunk upload. We then signaled the controller to ignore\n // all failures associated with these aborts. We are now retrying, so we don't want to ignore\n // any more failures at this point.\n if (concurrentChunkingPossible) {\n handler._getFileState(id).temp.ignoreFailure = false;\n }\n\n // If we are attempting to retry a file that is already consuming a connection, this is likely an auto-retry.\n // Just go ahead and ask the handler to upload again.\n if (connectionManager.isUsingConnection(id)) {\n return upload.start(id);\n }\n\n // If we are attempting to retry a file that is not currently consuming a connection,\n // this is likely a manual retry attempt. We will need to ensure a connection is available\n // before the retry commences.\n else {\n return controller.upload(id);\n }\n },\n\n /**\n * Cancels file upload by id\n */\n cancel: function(id) {\n var cancelRetVal = handler.cancel(id);\n\n if (qq.isGenericPromise(cancelRetVal)) {\n cancelRetVal.then(function() {\n upload.cancel(id);\n });\n }\n else if (cancelRetVal !== false) {\n upload.cancel(id);\n }\n },\n\n /**\n * Cancels all queued or in-progress uploads\n */\n cancelAll: function() {\n var waitingOrConnected = connectionManager.getWaitingOrConnected(),\n i;\n\n // ensure files are cancelled in reverse order which they were added\n // to avoid a flash of time where a queued file begins to upload before it is canceled\n if (waitingOrConnected.length) {\n for (i = waitingOrConnected.length - 1; i >= 0; i--) {\n controller.cancel(waitingOrConnected[i]);\n }\n }\n\n connectionManager.reset();\n },\n\n // Returns a File, Blob, or the Blob/File for the reference/parent file if the targeted blob is a proxy.\n // Undefined if no file record is available.\n getFile: function(id) {\n if (handler.getProxy && handler.getProxy(id)) {\n return handler.getProxy(id).referenceBlob;\n }\n\n return handler.getFile && handler.getFile(id);\n },\n\n // Returns true if the Blob associated with the ID is related to a proxy s\n isProxied: function(id) {\n return !!(handler.getProxy && handler.getProxy(id));\n },\n\n getInput: function(id) {\n if (handler.getInput) {\n return handler.getInput(id);\n }\n },\n\n reset: function() {\n log(\"Resetting upload handler\");\n controller.cancelAll();\n connectionManager.reset();\n handler.reset();\n },\n\n expunge: function(id) {\n if (controller.isValid(id)) {\n return handler.expunge(id);\n }\n },\n\n /**\n * Determine if the file exists.\n */\n isValid: function(id) {\n return handler.isValid(id);\n },\n\n hasResumeRecord: function(id) {\n var key = handler.isValid(id) &&\n handler._getLocalStorageId &&\n handler._getLocalStorageId(id);\n\n if (key) {\n return !!localStorage.getItem(key);\n }\n\n return false;\n },\n\n getResumableFilesData: function() {\n if (handler.getResumableFilesData) {\n return handler.getResumableFilesData();\n }\n return [];\n },\n\n /**\n * This may or may not be implemented, depending on the handler. For handlers where a third-party ID is\n * available (such as the \"key\" for Amazon S3), this will return that value. Otherwise, the return value\n * will be undefined.\n *\n * @param id Internal file ID\n * @returns {*} Some identifier used by a 3rd-party service involved in the upload process\n */\n getThirdPartyFileId: function(id) {\n if (controller.isValid(id)) {\n return handler.getThirdPartyFileId(id);\n }\n },\n\n /**\n * Attempts to pause the associated upload if the specific handler supports this and the file is \"valid\".\n * @param id ID of the upload/file to pause\n * @returns {boolean} true if the upload was paused\n */\n pause: function(id) {\n if (controller.isResumable(id) && handler.pause && controller.isValid(id) && handler.pause(id)) {\n connectionManager.free(id);\n handler.moveInProgressToRemaining(id);\n return true;\n }\n return false;\n },\n\n isAttemptingResume: function(id) {\n return !!handler.isAttemptingResume && handler.isAttemptingResume(id);\n },\n\n // True if the file is eligible for pause/resume.\n isResumable: function(id) {\n return !!handler.isResumable && handler.isResumable(id);\n }\n });\n\n qq.extend(options, o);\n log = options.log;\n chunkingPossible = options.chunking.enabled && qq.supportedFeatures.chunking;\n concurrentChunkingPossible = chunkingPossible && options.chunking.concurrent.enabled;\n\n preventRetryResponse = (function() {\n var response = {};\n\n response[options.preventRetryParam] = true;\n\n return response;\n }());\n\n upload.initHandler();\n};\n","/*globals qq */\n/*jshint -W117 */\nqq.WindowReceiveMessage = function(o) {\n \"use strict\";\n\n var options = {\n log: function(message, level) {}\n },\n callbackWrapperDetachers = {};\n\n qq.extend(options, o);\n\n qq.extend(this, {\n receiveMessage: function(id, callback) {\n var onMessageCallbackWrapper = function(event) {\n callback(event.data);\n };\n\n if (window.postMessage) {\n callbackWrapperDetachers[id] = qq(window).attach(\"message\", onMessageCallbackWrapper);\n }\n else {\n log(\"iframe message passing not supported in this browser!\", \"error\");\n }\n },\n\n stopReceivingMessages: function(id) {\n if (window.postMessage) {\n var detacher = callbackWrapperDetachers[id];\n if (detacher) {\n detacher();\n }\n }\n }\n });\n};\n","/* globals qq */\n/**\n * Common APIs exposed to creators of upload via form/iframe handlers. This is reused and possibly overridden\n * in some cases by specific form upload handlers.\n *\n * @constructor\n */\nqq.FormUploadHandler = function(spec) {\n \"use strict\";\n\n var options = spec.options,\n handler = this,\n proxy = spec.proxy,\n formHandlerInstanceId = qq.getUniqueId(),\n onloadCallbacks = {},\n detachLoadEvents = {},\n postMessageCallbackTimers = {},\n isCors = options.isCors,\n inputName = options.inputName,\n getUuid = proxy.getUuid,\n log = proxy.log,\n corsMessageReceiver = new qq.WindowReceiveMessage({log: log});\n\n /**\n * Remove any trace of the file from the handler.\n *\n * @param id ID of the associated file\n */\n function expungeFile(id) {\n delete detachLoadEvents[id];\n\n // If we are dealing with CORS, we might still be waiting for a response from a loaded iframe.\n // In that case, terminate the timer waiting for a message from the loaded iframe\n // and stop listening for any more messages coming from this iframe.\n if (isCors) {\n clearTimeout(postMessageCallbackTimers[id]);\n delete postMessageCallbackTimers[id];\n corsMessageReceiver.stopReceivingMessages(id);\n }\n\n var iframe = document.getElementById(handler._getIframeName(id));\n if (iframe) {\n // To cancel request set src to something else. We use src=\"javascript:false;\"\n // because it doesn't trigger ie6 prompt on https\n /* jshint scripturl:true */\n iframe.setAttribute(\"src\", \"javascript:false;\");\n\n qq(iframe).remove();\n }\n }\n\n /**\n * @param iframeName `document`-unique Name of the associated iframe\n * @returns {*} ID of the associated file\n */\n function getFileIdForIframeName(iframeName) {\n return iframeName.split(\"_\")[0];\n }\n\n /**\n * Generates an iframe to be used as a target for upload-related form submits. This also adds the iframe\n * to the current `document`. Note that the iframe is hidden from view.\n *\n * @param name Name of the iframe.\n * @returns {HTMLIFrameElement} The created iframe\n */\n function initIframeForUpload(name) {\n var iframe = qq.toElement(\"\");\n\n iframe.setAttribute(\"id\", name);\n\n iframe.style.display = \"none\";\n document.body.appendChild(iframe);\n\n return iframe;\n }\n\n /**\n * If we are in CORS mode, we must listen for messages (containing the server response) from the associated\n * iframe, since we cannot directly parse the content of the iframe due to cross-origin restrictions.\n *\n * @param iframe Listen for messages on this iframe.\n * @param callback Invoke this callback with the message from the iframe.\n */\n function registerPostMessageCallback(iframe, callback) {\n var iframeName = iframe.id,\n fileId = getFileIdForIframeName(iframeName),\n uuid = getUuid(fileId);\n\n onloadCallbacks[uuid] = callback;\n\n // When the iframe has loaded (after the server responds to an upload request)\n // declare the attempt a failure if we don't receive a valid message shortly after the response comes in.\n detachLoadEvents[fileId] = qq(iframe).attach(\"load\", function() {\n if (handler.getInput(fileId)) {\n log(\"Received iframe load event for CORS upload request (iframe name \" + iframeName + \")\");\n\n postMessageCallbackTimers[iframeName] = setTimeout(function() {\n var errorMessage = \"No valid message received from loaded iframe for iframe name \" + iframeName;\n log(errorMessage, \"error\");\n callback({\n error: errorMessage\n });\n }, 1000);\n }\n });\n\n // Listen for messages coming from this iframe. When a message has been received, cancel the timer\n // that declares the upload a failure if a message is not received within a reasonable amount of time.\n corsMessageReceiver.receiveMessage(iframeName, function(message) {\n log(\"Received the following window message: '\" + message + \"'\");\n var fileId = getFileIdForIframeName(iframeName),\n response = handler._parseJsonResponse(message),\n uuid = response.uuid,\n onloadCallback;\n\n if (uuid && onloadCallbacks[uuid]) {\n log(\"Handling response for iframe name \" + iframeName);\n clearTimeout(postMessageCallbackTimers[iframeName]);\n delete postMessageCallbackTimers[iframeName];\n\n handler._detachLoadEvent(iframeName);\n\n onloadCallback = onloadCallbacks[uuid];\n\n delete onloadCallbacks[uuid];\n corsMessageReceiver.stopReceivingMessages(iframeName);\n onloadCallback(response);\n }\n else if (!uuid) {\n log(\"'\" + message + \"' does not contain a UUID - ignoring.\");\n }\n });\n }\n\n qq.extend(this, new qq.UploadHandler(spec));\n\n qq.override(this, function(super_) {\n return {\n /**\n * Adds File or Blob to the queue\n **/\n add: function(id, fileInput) {\n super_.add(id, {input: fileInput});\n\n fileInput.setAttribute(\"name\", inputName);\n\n // remove file input from DOM\n if (fileInput.parentNode) {\n qq(fileInput).remove();\n }\n },\n\n expunge: function(id) {\n expungeFile(id);\n super_.expunge(id);\n },\n\n isValid: function(id) {\n return super_.isValid(id) &&\n handler._getFileState(id).input !== undefined;\n }\n };\n });\n\n qq.extend(this, {\n getInput: function(id) {\n return handler._getFileState(id).input;\n },\n\n /**\n * This function either delegates to a more specific message handler if CORS is involved,\n * or simply registers a callback when the iframe has been loaded that invokes the passed callback\n * after determining if the content of the iframe is accessible.\n *\n * @param iframe Associated iframe\n * @param callback Callback to invoke after we have determined if the iframe content is accessible.\n */\n _attachLoadEvent: function(iframe, callback) {\n /*jslint eqeq: true*/\n var responseDescriptor;\n\n if (isCors) {\n registerPostMessageCallback(iframe, callback);\n }\n else {\n detachLoadEvents[iframe.id] = qq(iframe).attach(\"load\", function() {\n log(\"Received response for \" + iframe.id);\n\n // when we remove iframe from dom\n // the request stops, but in IE load\n // event fires\n if (!iframe.parentNode) {\n return;\n }\n\n try {\n // fixing Opera 10.53\n if (iframe.contentDocument &&\n iframe.contentDocument.body &&\n iframe.contentDocument.body.innerHTML == \"false\") {\n // In Opera event is fired second time\n // when body.innerHTML changed from false\n // to server response approx. after 1 sec\n // when we upload file with iframe\n return;\n }\n }\n catch (error) {\n //IE may throw an \"access is denied\" error when attempting to access contentDocument on the iframe in some cases\n log(\"Error when attempting to access iframe during handling of upload response (\" + error.message + \")\", \"error\");\n responseDescriptor = {success: false};\n }\n\n callback(responseDescriptor);\n });\n }\n },\n\n /**\n * Creates an iframe with a specific document-unique name.\n *\n * @param id ID of the associated file\n * @returns {HTMLIFrameElement}\n */\n _createIframe: function(id) {\n var iframeName = handler._getIframeName(id);\n\n return initIframeForUpload(iframeName);\n },\n\n /**\n * Called when we are no longer interested in being notified when an iframe has loaded.\n *\n * @param id Associated file ID\n */\n _detachLoadEvent: function(id) {\n if (detachLoadEvents[id] !== undefined) {\n detachLoadEvents[id]();\n delete detachLoadEvents[id];\n }\n },\n\n /**\n * @param fileId ID of the associated file\n * @returns {string} The `document`-unique name of the iframe\n */\n _getIframeName: function(fileId) {\n return fileId + \"_\" + formHandlerInstanceId;\n },\n\n /**\n * Generates a form element and appends it to the `document`. When the form is submitted, a specific iframe is targeted.\n * The name of the iframe is passed in as a property of the spec parameter, and must be unique in the `document`. Note\n * that the form is hidden from view.\n *\n * @param spec An object containing various properties to be used when constructing the form. Required properties are\n * currently: `method`, `endpoint`, `params`, `paramsInBody`, and `targetName`.\n * @returns {HTMLFormElement} The created form\n */\n _initFormForUpload: function(spec) {\n var method = spec.method,\n endpoint = spec.endpoint,\n params = spec.params,\n paramsInBody = spec.paramsInBody,\n targetName = spec.targetName,\n form = qq.toElement(\"\"),\n url = endpoint;\n\n if (paramsInBody) {\n qq.obj2Inputs(params, form);\n }\n else {\n url = qq.obj2url(params, endpoint);\n }\n\n form.setAttribute(\"action\", url);\n form.setAttribute(\"target\", targetName);\n form.style.display = \"none\";\n document.body.appendChild(form);\n\n return form;\n },\n\n /**\n * @param innerHtmlOrMessage JSON message\n * @returns {*} The parsed response, or an empty object if the response could not be parsed\n */\n _parseJsonResponse: function(innerHtmlOrMessage) {\n var response = {};\n\n try {\n response = qq.parseJson(innerHtmlOrMessage);\n }\n catch (error) {\n log(\"Error when attempting to parse iframe upload response (\" + error.message + \")\", \"error\");\n }\n\n return response;\n }\n });\n};\n","/* globals qq */\n/**\n * Common API exposed to creators of XHR handlers. This is reused and possibly overriding in some cases by specific\n * XHR upload handlers.\n *\n * @constructor\n */\nqq.XhrUploadHandler = function(spec) {\n \"use strict\";\n\n var handler = this,\n namespace = spec.options.namespace,\n proxy = spec.proxy,\n chunking = spec.options.chunking,\n getChunkSize = function(id) {\n var fileState = handler._getFileState(id);\n\n if (fileState.chunkSize) {\n return fileState.chunkSize;\n }\n\n else {\n var chunkSize = chunking.partSize;\n\n if (qq.isFunction(chunkSize)) {\n chunkSize = chunkSize(id, getSize(id));\n }\n\n fileState.chunkSize = chunkSize;\n return chunkSize;\n }\n },\n resume = spec.options.resume,\n chunkFiles = chunking && spec.options.chunking.enabled && qq.supportedFeatures.chunking,\n resumeEnabled = resume && spec.options.resume.enabled && chunkFiles && qq.supportedFeatures.resume,\n getName = proxy.getName,\n getSize = proxy.getSize,\n getUuid = proxy.getUuid,\n getEndpoint = proxy.getEndpoint,\n getDataByUuid = proxy.getDataByUuid,\n onUuidChanged = proxy.onUuidChanged,\n onProgress = proxy.onProgress,\n log = proxy.log,\n getCustomResumeData = proxy.getCustomResumeData;\n\n function abort(id) {\n qq.each(handler._getXhrs(id), function(xhrId, xhr) {\n var ajaxRequester = handler._getAjaxRequester(id, xhrId);\n\n xhr.onreadystatechange = null;\n xhr.upload.onprogress = null;\n xhr.abort();\n ajaxRequester && ajaxRequester.canceled && ajaxRequester.canceled(id);\n });\n }\n\n qq.extend(this, new qq.UploadHandler(spec));\n\n qq.override(this, function(super_) {\n return {\n /**\n * Adds File or Blob to the queue\n **/\n add: function(id, blobOrProxy) {\n if (qq.isFile(blobOrProxy) || qq.isBlob(blobOrProxy)) {\n super_.add(id, {file: blobOrProxy});\n }\n else if (blobOrProxy instanceof qq.BlobProxy) {\n super_.add(id, {proxy: blobOrProxy});\n }\n else {\n throw new Error(\"Passed obj is not a File, Blob, or proxy\");\n }\n\n handler._initTempState(id);\n resumeEnabled && handler._maybePrepareForResume(id);\n },\n\n expunge: function(id) {\n abort(id);\n handler._maybeDeletePersistedChunkData(id);\n handler._clearXhrs(id);\n super_.expunge(id);\n }\n };\n });\n\n qq.extend(this, {\n // Clear the cached chunk `Blob` after we are done with it, just in case the `Blob` bytes are stored in memory.\n clearCachedChunk: function(id, chunkIdx) {\n var fileState = handler._getFileState(id);\n\n if (fileState) {\n delete fileState.temp.cachedChunks[chunkIdx];\n }\n },\n\n clearXhr: function(id, chunkIdx) {\n var tempState = handler._getFileState(id).temp;\n\n if (tempState.xhrs) {\n delete tempState.xhrs[chunkIdx];\n }\n if (tempState.ajaxRequesters) {\n delete tempState.ajaxRequesters[chunkIdx];\n }\n },\n\n // Called when all chunks have been successfully uploaded. Expected promissory return type.\n // This defines the default behavior if nothing further is required when all chunks have been uploaded.\n finalizeChunks: function(id, responseParser) {\n var lastChunkIdx = handler._getTotalChunks(id) - 1,\n xhr = handler._getXhr(id, lastChunkIdx);\n\n if (responseParser) {\n return new qq.Promise().success(responseParser(xhr), xhr);\n }\n\n return new qq.Promise().success({}, xhr);\n },\n\n getFile: function(id) {\n return handler.isValid(id) && handler._getFileState(id).file;\n },\n\n getProxy: function(id) {\n return handler.isValid(id) && handler._getFileState(id).proxy;\n },\n\n /**\n * @returns {Array} Array of objects containing properties useful to integrators\n * when it is important to determine which files are potentially resumable.\n */\n getResumableFilesData: function() {\n var resumableFilesData = [];\n\n handler._iterateResumeRecords(function(key, uploadData) {\n handler.moveInProgressToRemaining(null, uploadData.chunking.inProgress, uploadData.chunking.remaining);\n\n var data = {\n name: uploadData.name,\n remaining: uploadData.chunking.remaining,\n size: uploadData.size,\n uuid: uploadData.uuid\n };\n\n if (uploadData.key) {\n data.key = uploadData.key;\n }\n\n if (uploadData.customResumeData) {\n data.customResumeData = uploadData.customResumeData;\n }\n\n resumableFilesData.push(data);\n });\n\n return resumableFilesData;\n },\n\n isAttemptingResume: function(id) {\n return handler._getFileState(id).attemptingResume;\n },\n\n isResumable: function(id) {\n return !!chunking && handler.isValid(id) &&\n !handler._getFileState(id).notResumable;\n },\n\n moveInProgressToRemaining: function(id, optInProgress, optRemaining) {\n var fileState = handler._getFileState(id) || {},\n chunkingState = fileState.chunking || {},\n inProgress = optInProgress || chunkingState.inProgress,\n remaining = optRemaining || chunkingState.remaining;\n\n if (inProgress) {\n log(qq.format(\"Moving these chunks from in-progress {}, to remaining.\", JSON.stringify(inProgress)));\n inProgress.reverse();\n qq.each(inProgress, function(idx, chunkIdx) {\n remaining.unshift(chunkIdx);\n });\n inProgress.length = 0;\n }\n },\n\n pause: function(id) {\n if (handler.isValid(id)) {\n log(qq.format(\"Aborting XHR upload for {} '{}' due to pause instruction.\", id, getName(id)));\n handler._getFileState(id).paused = true;\n abort(id);\n return true;\n }\n },\n\n reevaluateChunking: function(id) {\n if (chunking && handler.isValid(id)) {\n var state = handler._getFileState(id),\n totalChunks,\n i;\n\n delete state.chunking;\n\n state.chunking = {};\n totalChunks = handler._getTotalChunks(id);\n if (totalChunks > 1 || chunking.mandatory) {\n state.chunking.enabled = true;\n state.chunking.parts = totalChunks;\n state.chunking.remaining = [];\n\n for (i = 0; i < totalChunks; i++) {\n state.chunking.remaining.push(i);\n }\n\n handler._initTempState(id);\n }\n else {\n state.chunking.enabled = false;\n }\n }\n },\n\n updateBlob: function(id, newBlob) {\n if (handler.isValid(id)) {\n handler._getFileState(id).file = newBlob;\n }\n },\n\n _clearXhrs: function(id) {\n var tempState = handler._getFileState(id).temp;\n\n qq.each(tempState.ajaxRequesters, function(chunkId) {\n delete tempState.ajaxRequesters[chunkId];\n });\n\n qq.each(tempState.xhrs, function(chunkId) {\n delete tempState.xhrs[chunkId];\n });\n },\n\n /**\n * Creates an XHR instance for this file and stores it in the fileState.\n *\n * @param id File ID\n * @param optChunkIdx The chunk index associated with this XHR, if applicable\n * @returns {XMLHttpRequest}\n */\n _createXhr: function(id, optChunkIdx) {\n return handler._registerXhr(id, optChunkIdx, qq.createXhrInstance());\n },\n\n _getAjaxRequester: function(id, optChunkIdx) {\n var chunkIdx = optChunkIdx == null ? -1 : optChunkIdx;\n return handler._getFileState(id).temp.ajaxRequesters[chunkIdx];\n },\n\n _getChunkData: function(id, chunkIndex) {\n var chunkSize = getChunkSize(id),\n fileSize = getSize(id),\n fileOrBlob = handler.getFile(id),\n startBytes = chunkSize * chunkIndex,\n endBytes = startBytes + chunkSize >= fileSize ? fileSize : startBytes + chunkSize,\n totalChunks = handler._getTotalChunks(id),\n cachedChunks = this._getFileState(id).temp.cachedChunks,\n\n // To work around a Webkit GC bug, we must keep each chunk `Blob` in scope until we are done with it.\n // See https://github.com/FineUploader/fine-uploader/issues/937#issuecomment-41418760\n blob = cachedChunks[chunkIndex] || qq.sliceBlob(fileOrBlob, startBytes, endBytes);\n\n cachedChunks[chunkIndex] = blob;\n\n return {\n part: chunkIndex,\n start: startBytes,\n end: endBytes,\n count: totalChunks,\n blob: blob,\n size: endBytes - startBytes\n };\n },\n\n _getChunkDataForCallback: function(chunkData) {\n return {\n partIndex: chunkData.part,\n startByte: chunkData.start + 1,\n endByte: chunkData.end,\n totalParts: chunkData.count\n };\n },\n\n /**\n * @param id File ID\n * @returns {string} Identifier for this item that may appear in the browser's local storage\n */\n _getLocalStorageId: function(id) {\n var formatVersion = \"5.0\",\n name = getName(id),\n size = getSize(id),\n chunkSize = getChunkSize(id),\n endpoint = getEndpoint(id),\n customKeys = resume.customKeys(id),\n localStorageId = qq.format(\"qq{}resume{}-{}-{}-{}-{}\", namespace, formatVersion, name, size, chunkSize, endpoint);\n\n customKeys.forEach(function(key) {\n localStorageId += \"-\" + key;\n });\n\n return localStorageId;\n },\n\n _getMimeType: function(id) {\n return handler.getFile(id).type;\n },\n\n _getPersistableData: function(id) {\n return handler._getFileState(id).chunking;\n },\n\n /**\n * @param id ID of the associated file\n * @returns {number} Number of parts this file can be divided into, or undefined if chunking is not supported in this UA\n */\n _getTotalChunks: function(id) {\n if (chunking) {\n var fileSize = getSize(id),\n chunkSize = getChunkSize(id);\n\n return Math.ceil(fileSize / chunkSize);\n }\n },\n\n _getXhr: function(id, optChunkIdx) {\n var chunkIdx = optChunkIdx == null ? -1 : optChunkIdx;\n return handler._getFileState(id).temp.xhrs[chunkIdx];\n },\n\n _getXhrs: function(id) {\n return handler._getFileState(id).temp.xhrs;\n },\n\n // Iterates through all XHR handler-created resume records (in local storage),\n // invoking the passed callback and passing in the key and value of each local storage record.\n _iterateResumeRecords: function(callback) {\n if (resumeEnabled) {\n qq.each(localStorage, function(key, item) {\n if (key.indexOf(qq.format(\"qq{}resume\", namespace)) === 0) {\n var uploadData = JSON.parse(item);\n callback(key, uploadData);\n }\n });\n }\n },\n\n _initTempState: function(id) {\n handler._getFileState(id).temp = {\n ajaxRequesters: {},\n chunkProgress: {},\n xhrs: {},\n cachedChunks: {}\n };\n },\n\n _markNotResumable: function(id) {\n handler._getFileState(id).notResumable = true;\n },\n\n // Removes a chunked upload record from local storage, if possible.\n // Returns true if the item was removed, false otherwise.\n _maybeDeletePersistedChunkData: function(id) {\n var localStorageId;\n\n if (resumeEnabled && handler.isResumable(id)) {\n localStorageId = handler._getLocalStorageId(id);\n\n if (localStorageId && localStorage.getItem(localStorageId)) {\n localStorage.removeItem(localStorageId);\n return true;\n }\n }\n\n return false;\n },\n\n // If this is a resumable upload, grab the relevant data from storage and items in memory that track this upload\n // so we can pick up from where we left off.\n _maybePrepareForResume: function(id) {\n var state = handler._getFileState(id),\n localStorageId, persistedData;\n\n // Resume is enabled and possible and this is the first time we've tried to upload this file in this session,\n // so prepare for a resume attempt.\n if (resumeEnabled && state.key === undefined) {\n localStorageId = handler._getLocalStorageId(id);\n persistedData = localStorage.getItem(localStorageId);\n\n // If we found this item in local storage, maybe we should resume it.\n if (persistedData) {\n persistedData = JSON.parse(persistedData);\n\n // If we found a resume record but we have already handled this file in this session,\n // don't try to resume it & ensure we don't persist future check data\n if (getDataByUuid(persistedData.uuid)) {\n handler._markNotResumable(id);\n }\n else {\n log(qq.format(\"Identified file with ID {} and name of {} as resumable.\", id, getName(id)));\n\n onUuidChanged(id, persistedData.uuid);\n\n state.key = persistedData.key;\n state.chunking = persistedData.chunking;\n state.loaded = persistedData.loaded;\n state.customResumeData = persistedData.customResumeData;\n state.attemptingResume = true;\n\n handler.moveInProgressToRemaining(id);\n }\n }\n }\n },\n\n // Persist any data needed to resume this upload in a new session.\n _maybePersistChunkedState: function(id) {\n var state = handler._getFileState(id),\n localStorageId, persistedData;\n\n // If local storage isn't supported by the browser, or if resume isn't enabled or possible, give up\n if (resumeEnabled && handler.isResumable(id)) {\n var customResumeData = getCustomResumeData(id);\n\n localStorageId = handler._getLocalStorageId(id);\n\n persistedData = {\n name: getName(id),\n size: getSize(id),\n uuid: getUuid(id),\n key: state.key,\n chunking: state.chunking,\n loaded: state.loaded,\n lastUpdated: Date.now(),\n };\n\n if (customResumeData) {\n persistedData.customResumeData = customResumeData;\n }\n\n try {\n localStorage.setItem(localStorageId, JSON.stringify(persistedData));\n }\n catch (error) {\n log(qq.format(\"Unable to save resume data for '{}' due to error: '{}'.\", id, error.toString()), \"warn\");\n }\n }\n },\n\n _registerProgressHandler: function(id, chunkIdx, chunkSize) {\n var xhr = handler._getXhr(id, chunkIdx),\n name = getName(id),\n progressCalculator = {\n simple: function(loaded, total) {\n var fileSize = getSize(id);\n\n if (loaded === total) {\n onProgress(id, name, fileSize, fileSize);\n }\n else {\n onProgress(id, name, (loaded >= fileSize ? fileSize - 1 : loaded), fileSize);\n }\n },\n\n chunked: function(loaded, total) {\n var chunkProgress = handler._getFileState(id).temp.chunkProgress,\n totalSuccessfullyLoadedForFile = handler._getFileState(id).loaded,\n loadedForRequest = loaded,\n totalForRequest = total,\n totalFileSize = getSize(id),\n estActualChunkLoaded = loadedForRequest - (totalForRequest - chunkSize),\n totalLoadedForFile = totalSuccessfullyLoadedForFile;\n\n chunkProgress[chunkIdx] = estActualChunkLoaded;\n\n qq.each(chunkProgress, function(chunkIdx, chunkLoaded) {\n totalLoadedForFile += chunkLoaded;\n });\n\n onProgress(id, name, totalLoadedForFile, totalFileSize);\n }\n };\n\n xhr.upload.onprogress = function(e) {\n if (e.lengthComputable) {\n /* jshint eqnull: true */\n var type = chunkSize == null ? \"simple\" : \"chunked\";\n progressCalculator[type](e.loaded, e.total);\n }\n };\n },\n\n /**\n * Registers an XHR transport instance created elsewhere.\n *\n * @param id ID of the associated file\n * @param optChunkIdx The chunk index associated with this XHR, if applicable\n * @param xhr XMLHttpRequest object instance\n * @param optAjaxRequester `qq.AjaxRequester` associated with this request, if applicable.\n * @returns {XMLHttpRequest}\n */\n _registerXhr: function(id, optChunkIdx, xhr, optAjaxRequester) {\n var xhrsId = optChunkIdx == null ? -1 : optChunkIdx,\n tempState = handler._getFileState(id).temp;\n\n tempState.xhrs = tempState.xhrs || {};\n tempState.ajaxRequesters = tempState.ajaxRequesters || {};\n\n tempState.xhrs[xhrsId] = xhr;\n\n if (optAjaxRequester) {\n tempState.ajaxRequesters[xhrsId] = optAjaxRequester;\n }\n\n return xhr;\n },\n\n // Deletes any local storage records that are \"expired\".\n _removeExpiredChunkingRecords: function() {\n var expirationDays = resume.recordsExpireIn;\n\n handler._iterateResumeRecords(function(key, uploadData) {\n var expirationDate = new Date(uploadData.lastUpdated);\n\n // transform updated date into expiration date\n expirationDate.setDate(expirationDate.getDate() + expirationDays);\n\n if (expirationDate.getTime() <= Date.now()) {\n log(\"Removing expired resume record with key \" + key);\n localStorage.removeItem(key);\n }\n });\n },\n\n /**\n * Determine if the associated file should be chunked.\n *\n * @param id ID of the associated file\n * @returns {*} true if chunking is enabled, possible, and the file can be split into more than 1 part\n */\n _shouldChunkThisFile: function(id) {\n var state = handler._getFileState(id);\n\n // file may no longer be available if it was recently cancelled\n if (state) {\n if (!state.chunking) {\n handler.reevaluateChunking(id);\n }\n\n return state.chunking.enabled;\n }\n }\n });\n};\n","/*globals qq, XMLHttpRequest*/\nqq.DeleteFileAjaxRequester = function(o) {\n \"use strict\";\n\n var requester,\n options = {\n method: \"DELETE\",\n uuidParamName: \"qquuid\",\n endpointStore: {},\n maxConnections: 3,\n customHeaders: function(id) {return {};},\n paramsStore: {},\n cors: {\n expected: false,\n sendCredentials: false\n },\n log: function(str, level) {},\n onDelete: function(id) {},\n onDeleteComplete: function(id, xhrOrXdr, isError) {}\n };\n\n qq.extend(options, o);\n\n function getMandatedParams() {\n if (options.method.toUpperCase() === \"POST\") {\n return {\n _method: \"DELETE\"\n };\n }\n\n return {};\n }\n\n requester = qq.extend(this, new qq.AjaxRequester({\n acceptHeader: \"application/json\",\n validMethods: [\"POST\", \"DELETE\"],\n method: options.method,\n endpointStore: options.endpointStore,\n paramsStore: options.paramsStore,\n mandatedParams: getMandatedParams(),\n maxConnections: options.maxConnections,\n customHeaders: function(id) {\n return options.customHeaders.get(id);\n },\n log: options.log,\n onSend: options.onDelete,\n onComplete: options.onDeleteComplete,\n cors: options.cors\n }));\n\n qq.extend(this, {\n sendDelete: function(id, uuid, additionalMandatedParams) {\n var additionalOptions = additionalMandatedParams || {};\n\n options.log(\"Submitting delete file request for \" + id);\n\n if (options.method === \"DELETE\") {\n requester.initTransport(id)\n .withPath(uuid)\n .withParams(additionalOptions)\n .send();\n }\n else {\n additionalOptions[options.uuidParamName] = uuid;\n requester.initTransport(id)\n .withParams(additionalOptions)\n .send();\n }\n }\n });\n};\n","/*global qq, define */\n/*jshint strict:false,bitwise:false,nonew:false,asi:true,-W064,-W116,-W089 */\n/**\n * Mega pixel image rendering library for iOS6+\n *\n * Fixes iOS6+'s image file rendering issue for large size image (over mega-pixel),\n * which causes unexpected subsampling when drawing it in canvas.\n * By using this library, you can safely render the image with proper stretching.\n *\n * Copyright (c) 2012 Shinichi Tomita \n * Released under the MIT license\n *\n * Heavily modified by Widen for Fine Uploader\n */\n(function() {\n\n /**\n * Detect subsampling in loaded image.\n * In iOS, larger images than 2M pixels may be subsampled in rendering.\n */\n function detectSubsampling(img) {\n var iw = img.naturalWidth,\n ih = img.naturalHeight,\n canvas = document.createElement(\"canvas\"),\n ctx;\n\n if (iw * ih > 1024 * 1024) { // subsampling may happen over megapixel image\n canvas.width = canvas.height = 1;\n ctx = canvas.getContext(\"2d\");\n ctx.drawImage(img, -iw + 1, 0);\n // subsampled image becomes half smaller in rendering size.\n // check alpha channel value to confirm image is covering edge pixel or not.\n // if alpha value is 0 image is not covering, hence subsampled.\n return ctx.getImageData(0, 0, 1, 1).data[3] === 0;\n } else {\n return false;\n }\n }\n\n /**\n * Detecting vertical squash in loaded image.\n * Fixes a bug which squash image vertically while drawing into canvas for some images.\n */\n function detectVerticalSquash(img, iw, ih) {\n var canvas = document.createElement(\"canvas\"),\n sy = 0,\n ey = ih,\n py = ih,\n ctx, data, alpha, ratio;\n\n canvas.width = 1;\n canvas.height = ih;\n ctx = canvas.getContext(\"2d\");\n ctx.drawImage(img, 0, 0);\n data = ctx.getImageData(0, 0, 1, ih).data;\n\n // search image edge pixel position in case it is squashed vertically.\n while (py > sy) {\n alpha = data[(py - 1) * 4 + 3];\n if (alpha === 0) {\n ey = py;\n } else {\n sy = py;\n }\n py = (ey + sy) >> 1;\n }\n\n ratio = (py / ih);\n return (ratio === 0) ? 1 : ratio;\n }\n\n /**\n * Rendering image element (with resizing) and get its data URL\n */\n function renderImageToDataURL(img, blob, options, doSquash) {\n var canvas = document.createElement(\"canvas\"),\n mime = options.mime || \"image/jpeg\",\n promise = new qq.Promise();\n\n renderImageToCanvas(img, blob, canvas, options, doSquash)\n .then(function() {\n promise.success(\n canvas.toDataURL(mime, options.quality || 0.8)\n );\n });\n\n return promise;\n }\n\n function maybeCalculateDownsampledDimensions(spec) {\n var maxPixels = 5241000; //iOS specific value\n\n if (!qq.ios()) {\n throw new qq.Error(\"Downsampled dimensions can only be reliably calculated for iOS!\");\n }\n\n if (spec.origHeight * spec.origWidth > maxPixels) {\n return {\n newHeight: Math.round(Math.sqrt(maxPixels * (spec.origHeight / spec.origWidth))),\n newWidth: Math.round(Math.sqrt(maxPixels * (spec.origWidth / spec.origHeight)))\n };\n }\n }\n\n /**\n * Rendering image element (with resizing) into the canvas element\n */\n function renderImageToCanvas(img, blob, canvas, options, doSquash) {\n var iw = img.naturalWidth,\n ih = img.naturalHeight,\n width = options.width,\n height = options.height,\n ctx = canvas.getContext(\"2d\"),\n promise = new qq.Promise(),\n modifiedDimensions;\n\n ctx.save();\n\n if (options.resize) {\n return renderImageToCanvasWithCustomResizer({\n blob: blob,\n canvas: canvas,\n image: img,\n imageHeight: ih,\n imageWidth: iw,\n orientation: options.orientation,\n resize: options.resize,\n targetHeight: height,\n targetWidth: width\n });\n }\n\n if (!qq.supportedFeatures.unlimitedScaledImageSize) {\n modifiedDimensions = maybeCalculateDownsampledDimensions({\n origWidth: width,\n origHeight: height\n });\n\n if (modifiedDimensions) {\n qq.log(qq.format(\"Had to reduce dimensions due to device limitations from {}w / {}h to {}w / {}h\",\n width, height, modifiedDimensions.newWidth, modifiedDimensions.newHeight),\n \"warn\");\n\n width = modifiedDimensions.newWidth;\n height = modifiedDimensions.newHeight;\n }\n }\n\n transformCoordinate(canvas, width, height, options.orientation);\n\n // Fine Uploader specific: Save some CPU cycles if not using iOS\n // Assumption: This logic is only needed to overcome iOS image sampling issues\n if (qq.ios()) {\n (function() {\n if (detectSubsampling(img)) {\n iw /= 2;\n ih /= 2;\n }\n\n var d = 1024, // size of tiling canvas\n tmpCanvas = document.createElement(\"canvas\"),\n vertSquashRatio = doSquash ? detectVerticalSquash(img, iw, ih) : 1,\n dw = Math.ceil(d * width / iw),\n dh = Math.ceil(d * height / ih / vertSquashRatio),\n sy = 0,\n dy = 0,\n tmpCtx, sx, dx;\n\n tmpCanvas.width = tmpCanvas.height = d;\n tmpCtx = tmpCanvas.getContext(\"2d\");\n\n while (sy < ih) {\n sx = 0;\n dx = 0;\n while (sx < iw) {\n tmpCtx.clearRect(0, 0, d, d);\n tmpCtx.drawImage(img, -sx, -sy);\n ctx.drawImage(tmpCanvas, 0, 0, d, d, dx, dy, dw, dh);\n sx += d;\n dx += dw;\n }\n sy += d;\n dy += dh;\n }\n ctx.restore();\n tmpCanvas = tmpCtx = null;\n }());\n }\n else {\n ctx.drawImage(img, 0, 0, width, height);\n }\n\n canvas.qqImageRendered && canvas.qqImageRendered();\n promise.success();\n\n return promise;\n }\n\n function renderImageToCanvasWithCustomResizer(resizeInfo) {\n var blob = resizeInfo.blob,\n image = resizeInfo.image,\n imageHeight = resizeInfo.imageHeight,\n imageWidth = resizeInfo.imageWidth,\n orientation = resizeInfo.orientation,\n promise = new qq.Promise(),\n resize = resizeInfo.resize,\n sourceCanvas = document.createElement(\"canvas\"),\n sourceCanvasContext = sourceCanvas.getContext(\"2d\"),\n targetCanvas = resizeInfo.canvas,\n targetHeight = resizeInfo.targetHeight,\n targetWidth = resizeInfo.targetWidth;\n\n transformCoordinate(sourceCanvas, imageWidth, imageHeight, orientation);\n\n targetCanvas.height = targetHeight;\n targetCanvas.width = targetWidth;\n\n sourceCanvasContext.drawImage(image, 0, 0);\n\n resize({\n blob: blob,\n height: targetHeight,\n image: image,\n sourceCanvas: sourceCanvas,\n targetCanvas: targetCanvas,\n width: targetWidth\n })\n .then(\n function success() {\n targetCanvas.qqImageRendered && targetCanvas.qqImageRendered();\n promise.success();\n },\n promise.failure\n );\n\n return promise;\n }\n\n /**\n * Transform canvas coordination according to specified frame size and orientation\n * Orientation value is from EXIF tag\n */\n function transformCoordinate(canvas, width, height, orientation) {\n switch (orientation) {\n case 5:\n case 6:\n case 7:\n case 8:\n canvas.width = height;\n canvas.height = width;\n break;\n default:\n canvas.width = width;\n canvas.height = height;\n }\n var ctx = canvas.getContext(\"2d\");\n switch (orientation) {\n case 2:\n // horizontal flip\n ctx.translate(width, 0);\n ctx.scale(-1, 1);\n break;\n case 3:\n // 180 rotate left\n ctx.translate(width, height);\n ctx.rotate(Math.PI);\n break;\n case 4:\n // vertical flip\n ctx.translate(0, height);\n ctx.scale(1, -1);\n break;\n case 5:\n // vertical flip + 90 rotate right\n ctx.rotate(0.5 * Math.PI);\n ctx.scale(1, -1);\n break;\n case 6:\n // 90 rotate right\n ctx.rotate(0.5 * Math.PI);\n ctx.translate(0, -height);\n break;\n case 7:\n // horizontal flip + 90 rotate right\n ctx.rotate(0.5 * Math.PI);\n ctx.translate(width, -height);\n ctx.scale(-1, 1);\n break;\n case 8:\n // 90 rotate left\n ctx.rotate(-0.5 * Math.PI);\n ctx.translate(-width, 0);\n break;\n default:\n break;\n }\n }\n\n /**\n * MegaPixImage class\n */\n function MegaPixImage(srcImage, errorCallback) {\n var self = this;\n\n if (window.Blob && srcImage instanceof Blob) {\n (function() {\n var img = new Image(),\n URL = window.URL && window.URL.createObjectURL ? window.URL :\n window.webkitURL && window.webkitURL.createObjectURL ? window.webkitURL : null;\n if (!URL) { throw Error(\"No createObjectURL function found to create blob url\"); }\n img.src = URL.createObjectURL(srcImage);\n self.blob = srcImage;\n srcImage = img;\n }());\n }\n if (!srcImage.naturalWidth && !srcImage.naturalHeight) {\n srcImage.onload = function() {\n var listeners = self.imageLoadListeners;\n if (listeners) {\n self.imageLoadListeners = null;\n // IE11 doesn't reliably report actual image dimensions immediately after onload for small files,\n // so let's push this to the end of the UI thread queue.\n setTimeout(function() {\n for (var i = 0, len = listeners.length; i < len; i++) {\n listeners[i]();\n }\n }, 0);\n }\n };\n srcImage.onerror = errorCallback;\n this.imageLoadListeners = [];\n }\n this.srcImage = srcImage;\n }\n\n /**\n * Rendering megapix image into specified target element\n */\n MegaPixImage.prototype.render = function(target, options) {\n options = options || {};\n\n var self = this,\n imgWidth = this.srcImage.naturalWidth,\n imgHeight = this.srcImage.naturalHeight,\n width = options.width,\n height = options.height,\n maxWidth = options.maxWidth,\n maxHeight = options.maxHeight,\n doSquash = !this.blob || this.blob.type === \"image/jpeg\",\n tagName = target.tagName.toLowerCase(),\n opt;\n\n if (this.imageLoadListeners) {\n this.imageLoadListeners.push(function() { self.render(target, options); });\n return;\n }\n\n if (width && !height) {\n height = (imgHeight * width / imgWidth) << 0;\n } else if (height && !width) {\n width = (imgWidth * height / imgHeight) << 0;\n } else {\n width = imgWidth;\n height = imgHeight;\n }\n if (maxWidth && width > maxWidth) {\n width = maxWidth;\n height = (imgHeight * width / imgWidth) << 0;\n }\n if (maxHeight && height > maxHeight) {\n height = maxHeight;\n width = (imgWidth * height / imgHeight) << 0;\n }\n\n opt = { width: width, height: height },\n qq.each(options, function(optionsKey, optionsValue) {\n opt[optionsKey] = optionsValue;\n });\n\n if (tagName === \"img\") {\n (function() {\n var oldTargetSrc = target.src;\n renderImageToDataURL(self.srcImage, self.blob, opt, doSquash)\n .then(function(dataUri) {\n target.src = dataUri;\n oldTargetSrc === target.src && target.onload();\n });\n }());\n } else if (tagName === \"canvas\") {\n renderImageToCanvas(this.srcImage, this.blob, target, opt, doSquash);\n }\n if (typeof this.onrender === \"function\") {\n this.onrender(target);\n }\n };\n\n qq.MegaPixImage = MegaPixImage;\n})();\n","/*globals qq */\n/**\n * Draws a thumbnail of a Blob/File/URL onto an or .\n *\n * @constructor\n */\nqq.ImageGenerator = function(log) {\n \"use strict\";\n\n function isImg(el) {\n return el.tagName.toLowerCase() === \"img\";\n }\n\n function isCanvas(el) {\n return el.tagName.toLowerCase() === \"canvas\";\n }\n\n function isImgCorsSupported() {\n return new Image().crossOrigin !== undefined;\n }\n\n function isCanvasSupported() {\n var canvas = document.createElement(\"canvas\");\n\n return canvas.getContext && canvas.getContext(\"2d\");\n }\n\n // This is only meant to determine the MIME type of a renderable image file.\n // It is used to ensure images drawn from a URL that have transparent backgrounds\n // are rendered correctly, among other things.\n function determineMimeOfFileName(nameWithPath) {\n /*jshint -W015 */\n var pathSegments = nameWithPath.split(\"/\"),\n name = pathSegments[pathSegments.length - 1].split(\"?\")[0],\n extension = qq.getExtension(name);\n\n extension = extension && extension.toLowerCase();\n\n switch (extension) {\n case \"jpeg\":\n case \"jpg\":\n return \"image/jpeg\";\n case \"png\":\n return \"image/png\";\n case \"bmp\":\n return \"image/bmp\";\n case \"gif\":\n return \"image/gif\";\n case \"tiff\":\n case \"tif\":\n return \"image/tiff\";\n }\n }\n\n // This will likely not work correctly in IE8 and older.\n // It's only used as part of a formula to determine\n // if a canvas can be used to scale a server-hosted thumbnail.\n // If canvas isn't supported by the UA (IE8 and older)\n // this method should not even be called.\n function isCrossOrigin(url) {\n var targetAnchor = document.createElement(\"a\"),\n targetProtocol, targetHostname, targetPort;\n\n targetAnchor.href = url;\n\n targetProtocol = targetAnchor.protocol;\n targetPort = targetAnchor.port;\n targetHostname = targetAnchor.hostname;\n\n if (targetProtocol.toLowerCase() !== window.location.protocol.toLowerCase()) {\n return true;\n }\n\n if (targetHostname.toLowerCase() !== window.location.hostname.toLowerCase()) {\n return true;\n }\n\n // IE doesn't take ports into consideration when determining if two endpoints are same origin.\n if (targetPort !== window.location.port && !qq.ie()) {\n return true;\n }\n\n return false;\n }\n\n function registerImgLoadListeners(img, promise) {\n img.onload = function() {\n img.onload = null;\n img.onerror = null;\n promise.success(img);\n };\n\n img.onerror = function() {\n img.onload = null;\n img.onerror = null;\n log(\"Problem drawing thumbnail!\", \"error\");\n promise.failure(img, \"Problem drawing thumbnail!\");\n };\n }\n\n function registerCanvasDrawImageListener(canvas, promise) {\n // The image is drawn on the canvas by a third-party library,\n // and we want to know when this is completed. Since the library\n // may invoke drawImage many times in a loop, we need to be called\n // back when the image is fully rendered. So, we are expecting the\n // code that draws this image to follow a convention that involves a\n // function attached to the canvas instance be invoked when it is done.\n canvas.qqImageRendered = function() {\n promise.success(canvas);\n };\n }\n\n // Fulfills a `qq.Promise` when an image has been drawn onto the target,\n // whether that is a or an . The attempt is considered a\n // failure if the target is not an or a , or if the drawing\n // attempt was not successful.\n function registerThumbnailRenderedListener(imgOrCanvas, promise) {\n var registered = isImg(imgOrCanvas) || isCanvas(imgOrCanvas);\n\n if (isImg(imgOrCanvas)) {\n registerImgLoadListeners(imgOrCanvas, promise);\n }\n else if (isCanvas(imgOrCanvas)) {\n registerCanvasDrawImageListener(imgOrCanvas, promise);\n }\n else {\n promise.failure(imgOrCanvas);\n log(qq.format(\"Element container of type {} is not supported!\", imgOrCanvas.tagName), \"error\");\n }\n\n return registered;\n }\n\n // Draw a preview iff the current UA can natively display it.\n // Also rotate the image if necessary.\n function draw(fileOrBlob, container, options) {\n var drawPreview = new qq.Promise(),\n identifier = new qq.Identify(fileOrBlob, log),\n maxSize = options.maxSize,\n // jshint eqnull:true\n orient = options.orient == null ? true : options.orient,\n megapixErrorHandler = function() {\n container.onerror = null;\n container.onload = null;\n log(\"Could not render preview, file may be too large!\", \"error\");\n drawPreview.failure(container, \"Browser cannot render image!\");\n };\n\n identifier.isPreviewable().then(\n function(mime) {\n // If options explicitly specify that Orientation is not desired,\n // replace the orient task with a dummy promise that \"succeeds\" immediately.\n var dummyExif = {\n parse: function() {\n return new qq.Promise().success();\n }\n },\n exif = orient ? new qq.Exif(fileOrBlob, log) : dummyExif,\n mpImg = new qq.MegaPixImage(fileOrBlob, megapixErrorHandler);\n\n if (registerThumbnailRenderedListener(container, drawPreview)) {\n exif.parse().then(\n function(exif) {\n var orientation = exif && exif.Orientation;\n\n mpImg.render(container, {\n maxWidth: maxSize,\n maxHeight: maxSize,\n orientation: orientation,\n mime: mime,\n resize: options.customResizeFunction\n });\n },\n\n function(failureMsg) {\n log(qq.format(\"EXIF data could not be parsed ({}). Assuming orientation = 1.\", failureMsg));\n\n mpImg.render(container, {\n maxWidth: maxSize,\n maxHeight: maxSize,\n mime: mime,\n resize: options.customResizeFunction\n });\n }\n );\n }\n },\n\n function() {\n log(\"Not previewable\");\n drawPreview.failure(container, \"Not previewable\");\n }\n );\n\n return drawPreview;\n }\n\n function drawOnCanvasOrImgFromUrl(url, canvasOrImg, draw, maxSize, customResizeFunction) {\n var tempImg = new Image(),\n tempImgRender = new qq.Promise();\n\n registerThumbnailRenderedListener(tempImg, tempImgRender);\n\n if (isCrossOrigin(url)) {\n tempImg.crossOrigin = \"anonymous\";\n }\n\n tempImg.src = url;\n\n tempImgRender.then(\n function rendered() {\n registerThumbnailRenderedListener(canvasOrImg, draw);\n\n var mpImg = new qq.MegaPixImage(tempImg);\n mpImg.render(canvasOrImg, {\n maxWidth: maxSize,\n maxHeight: maxSize,\n mime: determineMimeOfFileName(url),\n resize: customResizeFunction\n });\n },\n\n draw.failure\n );\n }\n\n function drawOnImgFromUrlWithCssScaling(url, img, draw, maxSize) {\n registerThumbnailRenderedListener(img, draw);\n // NOTE: The fact that maxWidth/height is set on the thumbnail for scaled images\n // that must drop back to CSS is known and exploited by the templating module.\n // In this module, we pre-render \"waiting\" thumbs for all files immediately after they\n // are submitted, and we must be sure to pass any style associated with the \"waiting\" preview.\n qq(img).css({\n maxWidth: maxSize + \"px\",\n maxHeight: maxSize + \"px\"\n });\n\n img.src = url;\n }\n\n // Draw a (server-hosted) thumbnail given a URL.\n // This will optionally scale the thumbnail as well.\n // It attempts to use to scale, but will fall back\n // to max-width and max-height style properties if the UA\n // doesn't support canvas or if the images is cross-domain and\n // the UA doesn't support the crossorigin attribute on img tags,\n // which is required to scale a cross-origin image using &\n // then export it back to an .\n function drawFromUrl(url, container, options) {\n var draw = new qq.Promise(),\n scale = options.scale,\n maxSize = scale ? options.maxSize : null;\n\n // container is an img, scaling needed\n if (scale && isImg(container)) {\n // Iff canvas is available in this UA, try to use it for scaling.\n // Otherwise, fall back to CSS scaling\n if (isCanvasSupported()) {\n // Attempt to use for image scaling,\n // but we must fall back to scaling via CSS/styles\n // if this is a cross-origin image and the UA doesn't support CORS.\n if (isCrossOrigin(url) && !isImgCorsSupported()) {\n drawOnImgFromUrlWithCssScaling(url, container, draw, maxSize);\n }\n else {\n drawOnCanvasOrImgFromUrl(url, container, draw, maxSize);\n }\n }\n else {\n drawOnImgFromUrlWithCssScaling(url, container, draw, maxSize);\n }\n }\n // container is a canvas, scaling optional\n else if (isCanvas(container)) {\n drawOnCanvasOrImgFromUrl(url, container, draw, maxSize);\n }\n // container is an img & no scaling: just set the src attr to the passed url\n else if (registerThumbnailRenderedListener(container, draw)) {\n container.src = url;\n }\n\n return draw;\n }\n\n qq.extend(this, {\n /**\n * Generate a thumbnail. Depending on the arguments, this may either result in\n * a client-side rendering of an image (if a `Blob` is supplied) or a server-generated\n * image that may optionally be scaled client-side using or CSS/styles (as a fallback).\n *\n * @param fileBlobOrUrl a `File`, `Blob`, or a URL pointing to the image\n * @param container or to contain the preview\n * @param options possible properties include `maxSize` (int), `orient` (bool - default true), resize` (bool - default true), and `customResizeFunction`.\n * @returns qq.Promise fulfilled when the preview has been drawn, or the attempt has failed\n */\n generate: function(fileBlobOrUrl, container, options) {\n if (qq.isString(fileBlobOrUrl)) {\n log(\"Attempting to update thumbnail based on server response.\");\n return drawFromUrl(fileBlobOrUrl, container, options || {});\n }\n else {\n log(\"Attempting to draw client-side image preview.\");\n return draw(fileBlobOrUrl, container, options || {});\n }\n }\n });\n\n /**/\n this._testing = {};\n this._testing.isImg = isImg;\n this._testing.isCanvas = isCanvas;\n this._testing.isCrossOrigin = isCrossOrigin;\n this._testing.determineMimeOfFileName = determineMimeOfFileName;\n /* */\n};\n","/*globals qq */\n/**\n * EXIF image data parser. Currently only parses the Orientation tag value,\n * but this may be expanded to other tags in the future.\n *\n * @param fileOrBlob Attempt to parse EXIF data in this `Blob`\n * @constructor\n */\nqq.Exif = function(fileOrBlob, log) {\n \"use strict\";\n\n // Orientation is the only tag parsed here at this time.\n var TAG_IDS = [274],\n TAG_INFO = {\n 274: {\n name: \"Orientation\",\n bytes: 2\n }\n };\n\n // Convert a little endian (hex string) to big endian (decimal).\n function parseLittleEndian(hex) {\n var result = 0,\n pow = 0;\n\n while (hex.length > 0) {\n result += parseInt(hex.substring(0, 2), 16) * Math.pow(2, pow);\n hex = hex.substring(2, hex.length);\n pow += 8;\n }\n\n return result;\n }\n\n // Find the byte offset, of Application Segment 1 (EXIF).\n // External callers need not supply any arguments.\n function seekToApp1(offset, promise) {\n var theOffset = offset,\n thePromise = promise;\n if (theOffset === undefined) {\n theOffset = 2;\n thePromise = new qq.Promise();\n }\n\n qq.readBlobToHex(fileOrBlob, theOffset, 4).then(function(hex) {\n var match = /^ffe([0-9])/.exec(hex),\n segmentLength;\n\n if (match) {\n if (match[1] !== \"1\") {\n segmentLength = parseInt(hex.slice(4, 8), 16);\n seekToApp1(theOffset + segmentLength + 2, thePromise);\n }\n else {\n thePromise.success(theOffset);\n }\n }\n else {\n thePromise.failure(\"No EXIF header to be found!\");\n }\n });\n\n return thePromise;\n }\n\n // Find the byte offset of Application Segment 1 (EXIF) for valid JPEGs only.\n function getApp1Offset() {\n var promise = new qq.Promise();\n\n qq.readBlobToHex(fileOrBlob, 0, 6).then(function(hex) {\n if (hex.indexOf(\"ffd8\") !== 0) {\n promise.failure(\"Not a valid JPEG!\");\n }\n else {\n seekToApp1().then(function(offset) {\n promise.success(offset);\n },\n function(error) {\n promise.failure(error);\n });\n }\n });\n\n return promise;\n }\n\n // Determine the byte ordering of the EXIF header.\n function isLittleEndian(app1Start) {\n var promise = new qq.Promise();\n\n qq.readBlobToHex(fileOrBlob, app1Start + 10, 2).then(function(hex) {\n promise.success(hex === \"4949\");\n });\n\n return promise;\n }\n\n // Determine the number of directory entries in the EXIF header.\n function getDirEntryCount(app1Start, littleEndian) {\n var promise = new qq.Promise();\n\n qq.readBlobToHex(fileOrBlob, app1Start + 18, 2).then(function(hex) {\n if (littleEndian) {\n return promise.success(parseLittleEndian(hex));\n }\n else {\n promise.success(parseInt(hex, 16));\n }\n });\n\n return promise;\n }\n\n // Get the IFD portion of the EXIF header as a hex string.\n function getIfd(app1Start, dirEntries) {\n var offset = app1Start + 20,\n bytes = dirEntries * 12;\n\n return qq.readBlobToHex(fileOrBlob, offset, bytes);\n }\n\n // Obtain an array of all directory entries (as hex strings) in the EXIF header.\n function getDirEntries(ifdHex) {\n var entries = [],\n offset = 0;\n\n while (offset + 24 <= ifdHex.length) {\n entries.push(ifdHex.slice(offset, offset + 24));\n offset += 24;\n }\n\n return entries;\n }\n\n // Obtain values for all relevant tags and return them.\n function getTagValues(littleEndian, dirEntries) {\n var TAG_VAL_OFFSET = 16,\n tagsToFind = qq.extend([], TAG_IDS),\n vals = {};\n\n qq.each(dirEntries, function(idx, entry) {\n var idHex = entry.slice(0, 4),\n id = littleEndian ? parseLittleEndian(idHex) : parseInt(idHex, 16),\n tagsToFindIdx = tagsToFind.indexOf(id),\n tagValHex, tagName, tagValLength;\n\n if (tagsToFindIdx >= 0) {\n tagName = TAG_INFO[id].name;\n tagValLength = TAG_INFO[id].bytes;\n tagValHex = entry.slice(TAG_VAL_OFFSET, TAG_VAL_OFFSET + (tagValLength * 2));\n vals[tagName] = littleEndian ? parseLittleEndian(tagValHex) : parseInt(tagValHex, 16);\n\n tagsToFind.splice(tagsToFindIdx, 1);\n }\n\n if (tagsToFind.length === 0) {\n return false;\n }\n });\n\n return vals;\n }\n\n qq.extend(this, {\n /**\n * Attempt to parse the EXIF header for the `Blob` associated with this instance.\n *\n * @returns {qq.Promise} To be fulfilled when the parsing is complete.\n * If successful, the parsed EXIF header as an object will be included.\n */\n parse: function() {\n var parser = new qq.Promise(),\n onParseFailure = function(message) {\n log(qq.format(\"EXIF header parse failed: '{}' \", message));\n parser.failure(message);\n };\n\n getApp1Offset().then(function(app1Offset) {\n log(qq.format(\"Moving forward with EXIF header parsing for '{}'\", fileOrBlob.name === undefined ? \"blob\" : fileOrBlob.name));\n\n isLittleEndian(app1Offset).then(function(littleEndian) {\n\n log(qq.format(\"EXIF Byte order is {} endian\", littleEndian ? \"little\" : \"big\"));\n\n getDirEntryCount(app1Offset, littleEndian).then(function(dirEntryCount) {\n\n log(qq.format(\"Found {} APP1 directory entries\", dirEntryCount));\n\n getIfd(app1Offset, dirEntryCount).then(function(ifdHex) {\n var dirEntries = getDirEntries(ifdHex),\n tagValues = getTagValues(littleEndian, dirEntries);\n\n log(\"Successfully parsed some EXIF tags\");\n\n parser.success(tagValues);\n }, onParseFailure);\n }, onParseFailure);\n }, onParseFailure);\n }, onParseFailure);\n\n return parser;\n }\n });\n\n /**/\n this._testing = {};\n this._testing.parseLittleEndian = parseLittleEndian;\n /* */\n};\n","/*globals qq */\nqq.Identify = function(fileOrBlob, log) {\n \"use strict\";\n\n function isIdentifiable(magicBytes, questionableBytes) {\n var identifiable = false,\n magicBytesEntries = [].concat(magicBytes);\n\n qq.each(magicBytesEntries, function(idx, magicBytesArrayEntry) {\n if (questionableBytes.indexOf(magicBytesArrayEntry) === 0) {\n identifiable = true;\n return false;\n }\n });\n\n return identifiable;\n }\n\n qq.extend(this, {\n /**\n * Determines if a Blob can be displayed natively in the current browser. This is done by reading magic\n * bytes in the beginning of the file, so this is an asynchronous operation. Before we attempt to read the\n * file, we will examine the blob's type attribute to save CPU cycles.\n *\n * @returns {qq.Promise} Promise that is fulfilled when identification is complete.\n * If successful, the MIME string is passed to the success handler.\n */\n isPreviewable: function() {\n var self = this,\n identifier = new qq.Promise(),\n previewable = false,\n name = fileOrBlob.name === undefined ? \"blob\" : fileOrBlob.name;\n\n log(qq.format(\"Attempting to determine if {} can be rendered in this browser\", name));\n\n log(\"First pass: check type attribute of blob object.\");\n\n if (this.isPreviewableSync()) {\n log(\"Second pass: check for magic bytes in file header.\");\n\n qq.readBlobToHex(fileOrBlob, 0, 4).then(function(hex) {\n qq.each(self.PREVIEWABLE_MIME_TYPES, function(mime, bytes) {\n if (isIdentifiable(bytes, hex)) {\n // Safari is the only supported browser that can deal with TIFFs natively,\n // so, if this is a TIFF and the UA isn't Safari, declare this file \"non-previewable\".\n if (mime !== \"image/tiff\" || qq.supportedFeatures.tiffPreviews) {\n previewable = true;\n identifier.success(mime);\n }\n\n return false;\n }\n });\n\n log(qq.format(\"'{}' is {} able to be rendered in this browser\", name, previewable ? \"\" : \"NOT\"));\n\n if (!previewable) {\n identifier.failure();\n }\n },\n function() {\n log(\"Error reading file w/ name '\" + name + \"'. Not able to be rendered in this browser.\");\n identifier.failure();\n });\n }\n else {\n identifier.failure();\n }\n\n return identifier;\n },\n\n /**\n * Determines if a Blob can be displayed natively in the current browser. This is done by checking the\n * blob's type attribute. This is a synchronous operation, useful for situations where an asynchronous operation\n * would be challenging to support. Note that the blob's type property is not as accurate as reading the\n * file's magic bytes.\n *\n * @returns {Boolean} true if the blob can be rendered in the current browser\n */\n isPreviewableSync: function() {\n var fileMime = fileOrBlob.type,\n // Assumption: This will only ever be executed in browsers that support `Object.keys`.\n isRecognizedImage = qq.indexOf(Object.keys(this.PREVIEWABLE_MIME_TYPES), fileMime) >= 0,\n previewable = false,\n name = fileOrBlob.name === undefined ? \"blob\" : fileOrBlob.name;\n\n if (isRecognizedImage) {\n if (fileMime === \"image/tiff\") {\n previewable = qq.supportedFeatures.tiffPreviews;\n }\n else {\n previewable = true;\n }\n }\n\n !previewable && log(name + \" is not previewable in this browser per the blob's type attr\");\n\n return previewable;\n }\n });\n};\n\nqq.Identify.prototype.PREVIEWABLE_MIME_TYPES = {\n \"image/jpeg\": \"ffd8ff\",\n \"image/gif\": \"474946\",\n \"image/png\": \"89504e\",\n \"image/bmp\": \"424d\",\n \"image/tiff\": [\"49492a00\", \"4d4d002a\"]\n};\n","/*globals qq*/\n/**\n * Attempts to validate an image, wherever possible.\n *\n * @param blob File or Blob representing a user-selecting image.\n * @param log Uses this to post log messages to the console.\n * @constructor\n */\nqq.ImageValidation = function(blob, log) {\n \"use strict\";\n\n /**\n * @param limits Object with possible image-related limits to enforce.\n * @returns {boolean} true if at least one of the limits has a non-zero value\n */\n function hasNonZeroLimits(limits) {\n var atLeastOne = false;\n\n qq.each(limits, function(limit, value) {\n if (value > 0) {\n atLeastOne = true;\n return false;\n }\n });\n\n return atLeastOne;\n }\n\n /**\n * @returns {qq.Promise} The promise is a failure if we can't obtain the width & height.\n * Otherwise, `success` is called on the returned promise with an object containing\n * `width` and `height` properties.\n */\n function getWidthHeight() {\n var sizeDetermination = new qq.Promise();\n\n new qq.Identify(blob, log).isPreviewable().then(function() {\n var image = new Image(),\n url = window.URL && window.URL.createObjectURL ? window.URL :\n window.webkitURL && window.webkitURL.createObjectURL ? window.webkitURL :\n null;\n\n if (url) {\n image.onerror = function() {\n log(\"Cannot determine dimensions for image. May be too large.\", \"error\");\n sizeDetermination.failure();\n };\n\n image.onload = function() {\n sizeDetermination.success({\n width: this.width,\n height: this.height\n });\n };\n\n image.src = url.createObjectURL(blob);\n }\n else {\n log(\"No createObjectURL function available to generate image URL!\", \"error\");\n sizeDetermination.failure();\n }\n }, sizeDetermination.failure);\n\n return sizeDetermination;\n }\n\n /**\n *\n * @param limits Object with possible image-related limits to enforce.\n * @param dimensions Object containing `width` & `height` properties for the image to test.\n * @returns {String || undefined} The name of the failing limit. Undefined if no failing limits.\n */\n function getFailingLimit(limits, dimensions) {\n var failingLimit;\n\n qq.each(limits, function(limitName, limitValue) {\n if (limitValue > 0) {\n var limitMatcher = /(max|min)(Width|Height)/.exec(limitName),\n dimensionPropName = limitMatcher[2].charAt(0).toLowerCase() + limitMatcher[2].slice(1),\n actualValue = dimensions[dimensionPropName];\n\n /*jshint -W015*/\n switch (limitMatcher[1]) {\n case \"min\":\n if (actualValue < limitValue) {\n failingLimit = limitName;\n return false;\n }\n break;\n case \"max\":\n if (actualValue > limitValue) {\n failingLimit = limitName;\n return false;\n }\n break;\n }\n }\n });\n\n return failingLimit;\n }\n\n /**\n * Validate the associated blob.\n *\n * @param limits\n * @returns {qq.Promise} `success` is called on the promise is the image is valid or\n * if the blob is not an image, or if the image is not verifiable.\n * Otherwise, `failure` with the name of the failing limit.\n */\n this.validate = function(limits) {\n var validationEffort = new qq.Promise();\n\n log(\"Attempting to validate image.\");\n\n if (hasNonZeroLimits(limits)) {\n getWidthHeight().then(function(dimensions) {\n var failingLimit = getFailingLimit(limits, dimensions);\n\n if (failingLimit) {\n validationEffort.failure(failingLimit);\n }\n else {\n validationEffort.success();\n }\n }, validationEffort.success);\n }\n else {\n validationEffort.success();\n }\n\n return validationEffort;\n };\n};\n","/* globals qq */\n/**\n * Module used to control populating the initial list of files.\n *\n * @constructor\n */\nqq.Session = function(spec) {\n \"use strict\";\n\n var options = {\n endpoint: null,\n params: {},\n customHeaders: {},\n cors: {},\n addFileRecord: function(sessionData) {},\n log: function(message, level) {}\n };\n\n qq.extend(options, spec, true);\n\n function isJsonResponseValid(response) {\n if (qq.isArray(response)) {\n return true;\n }\n\n options.log(\"Session response is not an array.\", \"error\");\n }\n\n function handleFileItems(fileItems, success, xhrOrXdr, promise) {\n var someItemsIgnored = false;\n\n success = success && isJsonResponseValid(fileItems);\n\n if (success) {\n qq.each(fileItems, function(idx, fileItem) {\n /* jshint eqnull:true */\n if (fileItem.uuid == null) {\n someItemsIgnored = true;\n options.log(qq.format(\"Session response item {} did not include a valid UUID - ignoring.\", idx), \"error\");\n }\n else if (fileItem.name == null) {\n someItemsIgnored = true;\n options.log(qq.format(\"Session response item {} did not include a valid name - ignoring.\", idx), \"error\");\n }\n else {\n try {\n options.addFileRecord(fileItem);\n return true;\n }\n catch (err) {\n someItemsIgnored = true;\n options.log(err.message, \"error\");\n }\n }\n\n return false;\n });\n }\n\n promise[success && !someItemsIgnored ? \"success\" : \"failure\"](fileItems, xhrOrXdr);\n }\n\n // Initiate a call to the server that will be used to populate the initial file list.\n // Returns a `qq.Promise`.\n this.refresh = function() {\n /*jshint indent:false */\n var refreshEffort = new qq.Promise(),\n refreshCompleteCallback = function(response, success, xhrOrXdr) {\n handleFileItems(response, success, xhrOrXdr, refreshEffort);\n },\n requesterOptions = qq.extend({}, options),\n requester = new qq.SessionAjaxRequester(\n qq.extend(requesterOptions, {onComplete: refreshCompleteCallback})\n );\n\n requester.queryServer();\n\n return refreshEffort;\n };\n};\n","/*globals qq, XMLHttpRequest*/\n/**\n * Thin module used to send GET requests to the server, expecting information about session\n * data used to initialize an uploader instance.\n *\n * @param spec Various options used to influence the associated request.\n * @constructor\n */\nqq.SessionAjaxRequester = function(spec) {\n \"use strict\";\n\n var requester,\n options = {\n endpoint: null,\n customHeaders: {},\n params: {},\n cors: {\n expected: false,\n sendCredentials: false\n },\n onComplete: function(response, success, xhrOrXdr) {},\n log: function(str, level) {}\n };\n\n qq.extend(options, spec);\n\n function onComplete(id, xhrOrXdr, isError) {\n var response = null;\n\n /* jshint eqnull:true */\n if (xhrOrXdr.responseText != null) {\n try {\n response = qq.parseJson(xhrOrXdr.responseText);\n }\n catch (err) {\n options.log(\"Problem parsing session response: \" + err.message, \"error\");\n isError = true;\n }\n }\n\n options.onComplete(response, !isError, xhrOrXdr);\n }\n\n requester = qq.extend(this, new qq.AjaxRequester({\n acceptHeader: \"application/json\",\n validMethods: [\"GET\"],\n method: \"GET\",\n endpointStore: {\n get: function() {\n return options.endpoint;\n }\n },\n customHeaders: options.customHeaders,\n log: options.log,\n onComplete: onComplete,\n cors: options.cors\n }));\n\n qq.extend(this, {\n queryServer: function() {\n var params = qq.extend({}, options.params);\n\n options.log(\"Session query request.\");\n\n requester.initTransport(\"sessionRefresh\")\n .withParams(params)\n .withCacheBuster()\n .send();\n }\n });\n};\n","/* globals qq, ExifRestorer */\n/**\n * Controls generation of scaled images based on a reference image encapsulated in a `File` or `Blob`.\n * Scaled images are generated and converted to blobs on-demand.\n * Multiple scaled images per reference image with varying sizes and other properties are supported.\n *\n * @param spec Information about the scaled images to generate.\n * @param log Logger instance\n * @constructor\n */\nqq.Scaler = function(spec, log) {\n \"use strict\";\n\n var self = this,\n customResizeFunction = spec.customResizer,\n includeOriginal = spec.sendOriginal,\n orient = spec.orient,\n defaultType = spec.defaultType,\n defaultQuality = spec.defaultQuality / 100,\n failedToScaleText = spec.failureText,\n includeExif = spec.includeExif,\n sizes = this._getSortedSizes(spec.sizes);\n\n // Revealed API for instances of this module\n qq.extend(this, {\n // If no targeted sizes have been declared or if this browser doesn't support\n // client-side image preview generation, there is no scaling to do.\n enabled: qq.supportedFeatures.scaling && sizes.length > 0,\n\n getFileRecords: function(originalFileUuid, originalFileName, originalBlobOrBlobData) {\n var self = this,\n records = [],\n originalBlob = originalBlobOrBlobData.blob ? originalBlobOrBlobData.blob : originalBlobOrBlobData,\n identifier = new qq.Identify(originalBlob, log);\n\n // If the reference file cannot be rendered natively, we can't create scaled versions.\n if (identifier.isPreviewableSync()) {\n // Create records for each scaled version & add them to the records array, smallest first.\n qq.each(sizes, function(idx, sizeRecord) {\n var outputType = self._determineOutputType({\n defaultType: defaultType,\n requestedType: sizeRecord.type,\n refType: originalBlob.type\n });\n\n records.push({\n uuid: qq.getUniqueId(),\n name: self._getName(originalFileName, {\n name: sizeRecord.name,\n type: outputType,\n refType: originalBlob.type\n }),\n blob: new qq.BlobProxy(originalBlob,\n qq.bind(self._generateScaledImage, self, {\n customResizeFunction: customResizeFunction,\n maxSize: sizeRecord.maxSize,\n orient: orient,\n type: outputType,\n quality: defaultQuality,\n failedText: failedToScaleText,\n includeExif: includeExif,\n log: log\n }))\n });\n });\n\n records.push({\n uuid: originalFileUuid,\n name: originalFileName,\n size: originalBlob.size,\n blob: includeOriginal ? originalBlob : null\n });\n }\n else {\n records.push({\n uuid: originalFileUuid,\n name: originalFileName,\n size: originalBlob.size,\n blob: originalBlob\n });\n }\n\n return records;\n },\n\n handleNewFile: function(file, name, uuid, size, fileList, batchId, uuidParamName, api) {\n var self = this,\n buttonId = file.qqButtonId || (file.blob && file.blob.qqButtonId),\n scaledIds = [],\n originalId = null,\n addFileToHandler = api.addFileToHandler,\n uploadData = api.uploadData,\n paramsStore = api.paramsStore,\n proxyGroupId = qq.getUniqueId();\n\n qq.each(self.getFileRecords(uuid, name, file), function(idx, record) {\n var blobSize = record.size,\n id;\n\n if (record.blob instanceof qq.BlobProxy) {\n blobSize = -1;\n }\n\n id = uploadData.addFile({\n uuid: record.uuid,\n name: record.name,\n size: blobSize,\n batchId: batchId,\n proxyGroupId: proxyGroupId\n });\n\n if (record.blob instanceof qq.BlobProxy) {\n scaledIds.push(id);\n }\n else {\n originalId = id;\n }\n\n if (record.blob) {\n addFileToHandler(id, record.blob);\n fileList.push({id: id, file: record.blob});\n }\n else {\n uploadData.setStatus(id, qq.status.REJECTED);\n }\n });\n\n // If we are potentially uploading an original file and some scaled versions,\n // ensure the scaled versions include reference's to the parent's UUID and size\n // in their associated upload requests.\n if (originalId !== null) {\n qq.each(scaledIds, function(idx, scaledId) {\n var params = {\n qqparentuuid: uploadData.retrieve({id: originalId}).uuid,\n qqparentsize: uploadData.retrieve({id: originalId}).size\n };\n\n // Make sure the UUID for each scaled image is sent with the upload request,\n // to be consistent (since we may need to ensure it is sent for the original file as well).\n params[uuidParamName] = uploadData.retrieve({id: scaledId}).uuid;\n\n uploadData.setParentId(scaledId, originalId);\n paramsStore.addReadOnly(scaledId, params);\n });\n\n // If any scaled images are tied to this parent image, be SURE we send its UUID as an upload request\n // parameter as well.\n if (scaledIds.length) {\n (function() {\n var param = {};\n param[uuidParamName] = uploadData.retrieve({id: originalId}).uuid;\n paramsStore.addReadOnly(originalId, param);\n }());\n }\n }\n }\n });\n};\n\nqq.extend(qq.Scaler.prototype, {\n scaleImage: function(id, specs, api) {\n \"use strict\";\n\n if (!qq.supportedFeatures.scaling) {\n throw new qq.Error(\"Scaling is not supported in this browser!\");\n }\n\n var scalingEffort = new qq.Promise(),\n log = api.log,\n file = api.getFile(id),\n uploadData = api.uploadData.retrieve({id: id}),\n name = uploadData && uploadData.name,\n uuid = uploadData && uploadData.uuid,\n scalingOptions = {\n customResizer: specs.customResizer,\n sendOriginal: false,\n orient: specs.orient,\n defaultType: specs.type || null,\n defaultQuality: specs.quality,\n failedToScaleText: \"Unable to scale\",\n sizes: [{name: \"\", maxSize: specs.maxSize}]\n },\n scaler = new qq.Scaler(scalingOptions, log);\n\n if (!qq.Scaler || !qq.supportedFeatures.imagePreviews || !file) {\n scalingEffort.failure();\n\n log(\"Could not generate requested scaled image for \" + id + \". \" +\n \"Scaling is either not possible in this browser, or the file could not be located.\", \"error\");\n }\n else {\n (qq.bind(function() {\n // Assumption: There will never be more than one record\n var record = scaler.getFileRecords(uuid, name, file)[0];\n\n if (record && record.blob instanceof qq.BlobProxy) {\n record.blob.create().then(scalingEffort.success, scalingEffort.failure);\n }\n else {\n log(id + \" is not a scalable image!\", \"error\");\n scalingEffort.failure();\n }\n }, this)());\n }\n\n return scalingEffort;\n },\n\n // NOTE: We cannot reliably determine at this time if the UA supports a specific MIME type for the target format.\n // image/jpeg and image/png are the only safe choices at this time.\n _determineOutputType: function(spec) {\n \"use strict\";\n\n var requestedType = spec.requestedType,\n defaultType = spec.defaultType,\n referenceType = spec.refType;\n\n // If a default type and requested type have not been specified, this should be a\n // JPEG if the original type is a JPEG, otherwise, a PNG.\n if (!defaultType && !requestedType) {\n if (referenceType !== \"image/jpeg\") {\n return \"image/png\";\n }\n return referenceType;\n }\n\n // A specified default type is used when a requested type is not specified.\n if (!requestedType) {\n return defaultType;\n }\n\n // If requested type is specified, use it, as long as this recognized type is supported by the current UA\n if (qq.indexOf(Object.keys(qq.Identify.prototype.PREVIEWABLE_MIME_TYPES), requestedType) >= 0) {\n if (requestedType === \"image/tiff\") {\n return qq.supportedFeatures.tiffPreviews ? requestedType : defaultType;\n }\n\n return requestedType;\n }\n\n return defaultType;\n },\n\n // Get a file name for a generated scaled file record, based on the provided scaled image description\n _getName: function(originalName, scaledVersionProperties) {\n \"use strict\";\n\n var startOfExt = originalName.lastIndexOf(\".\"),\n versionType = scaledVersionProperties.type || \"image/png\",\n referenceType = scaledVersionProperties.refType,\n scaledName = \"\",\n scaledExt = qq.getExtension(originalName),\n nameAppendage = \"\";\n\n if (scaledVersionProperties.name && scaledVersionProperties.name.trim().length) {\n nameAppendage = \" (\" + scaledVersionProperties.name + \")\";\n }\n\n if (startOfExt >= 0) {\n scaledName = originalName.substr(0, startOfExt);\n\n if (referenceType !== versionType) {\n scaledExt = versionType.split(\"/\")[1];\n }\n\n scaledName += nameAppendage + \".\" + scaledExt;\n }\n else {\n scaledName = originalName + nameAppendage;\n }\n\n return scaledName;\n },\n\n // We want the smallest scaled file to be uploaded first\n _getSortedSizes: function(sizes) {\n \"use strict\";\n\n sizes = qq.extend([], sizes);\n\n return sizes.sort(function(a, b) {\n if (a.maxSize > b.maxSize) {\n return 1;\n }\n if (a.maxSize < b.maxSize) {\n return -1;\n }\n return 0;\n });\n },\n\n _generateScaledImage: function(spec, sourceFile) {\n \"use strict\";\n\n var self = this,\n customResizeFunction = spec.customResizeFunction,\n log = spec.log,\n maxSize = spec.maxSize,\n orient = spec.orient,\n type = spec.type,\n quality = spec.quality,\n failedText = spec.failedText,\n includeExif = spec.includeExif && sourceFile.type === \"image/jpeg\" && type === \"image/jpeg\",\n scalingEffort = new qq.Promise(),\n imageGenerator = new qq.ImageGenerator(log),\n canvas = document.createElement(\"canvas\");\n\n log(\"Attempting to generate scaled version for \" + sourceFile.name);\n\n imageGenerator.generate(sourceFile, canvas, {maxSize: maxSize, orient: orient, customResizeFunction: customResizeFunction}).then(function() {\n var scaledImageDataUri = canvas.toDataURL(type, quality),\n signalSuccess = function() {\n log(\"Success generating scaled version for \" + sourceFile.name);\n var blob = qq.dataUriToBlob(scaledImageDataUri);\n scalingEffort.success(blob);\n };\n\n if (includeExif) {\n self._insertExifHeader(sourceFile, scaledImageDataUri, log).then(function(scaledImageDataUriWithExif) {\n scaledImageDataUri = scaledImageDataUriWithExif;\n signalSuccess();\n },\n function() {\n log(\"Problem inserting EXIF header into scaled image. Using scaled image w/out EXIF data.\", \"error\");\n signalSuccess();\n });\n }\n else {\n signalSuccess();\n }\n }, function() {\n log(\"Failed attempt to generate scaled version for \" + sourceFile.name, \"error\");\n scalingEffort.failure(failedText);\n });\n\n return scalingEffort;\n },\n\n // Attempt to insert the original image's EXIF header into a scaled version.\n _insertExifHeader: function(originalImage, scaledImageDataUri, log) {\n \"use strict\";\n\n var reader = new FileReader(),\n insertionEffort = new qq.Promise(),\n originalImageDataUri = \"\";\n\n reader.onload = function() {\n originalImageDataUri = reader.result;\n insertionEffort.success(qq.ExifRestorer.restore(originalImageDataUri, scaledImageDataUri));\n };\n\n reader.onerror = function() {\n log(\"Problem reading \" + originalImage.name + \" during attempt to transfer EXIF data to scaled version.\", \"error\");\n insertionEffort.failure();\n };\n\n reader.readAsDataURL(originalImage);\n\n return insertionEffort;\n },\n\n _dataUriToBlob: function(dataUri) {\n \"use strict\";\n\n var byteString, mimeString, arrayBuffer, intArray;\n\n // convert base64 to raw binary data held in a string\n if (dataUri.split(\",\")[0].indexOf(\"base64\") >= 0) {\n byteString = atob(dataUri.split(\",\")[1]);\n }\n else {\n byteString = decodeURI(dataUri.split(\",\")[1]);\n }\n\n // extract the MIME\n mimeString = dataUri.split(\",\")[0]\n .split(\":\")[1]\n .split(\";\")[0];\n\n // write the bytes of the binary string to an ArrayBuffer\n arrayBuffer = new ArrayBuffer(byteString.length);\n intArray = new Uint8Array(arrayBuffer);\n qq.each(byteString, function(idx, character) {\n intArray[idx] = character.charCodeAt(0);\n });\n\n return this._createBlob(arrayBuffer, mimeString);\n },\n\n _createBlob: function(data, mime) {\n \"use strict\";\n\n var BlobBuilder = window.BlobBuilder ||\n window.WebKitBlobBuilder ||\n window.MozBlobBuilder ||\n window.MSBlobBuilder,\n blobBuilder = BlobBuilder && new BlobBuilder();\n\n if (blobBuilder) {\n blobBuilder.append(data);\n return blobBuilder.getBlob(mime);\n }\n else {\n return new Blob([data], {type: mime});\n }\n }\n});\n","//Based on MinifyJpeg\n//http://elicon.blog57.fc2.com/blog-entry-206.html\n\nqq.ExifRestorer = (function()\n{\n \n\tvar ExifRestorer = {};\n\t \n ExifRestorer.KEY_STR = \"ABCDEFGHIJKLMNOP\" +\n \"QRSTUVWXYZabcdef\" +\n \"ghijklmnopqrstuv\" +\n \"wxyz0123456789+/\" +\n \"=\";\n\n ExifRestorer.encode64 = function(input)\n {\n var output = \"\",\n chr1, chr2, chr3 = \"\",\n enc1, enc2, enc3, enc4 = \"\",\n i = 0;\n\n do {\n chr1 = input[i++];\n chr2 = input[i++];\n chr3 = input[i++];\n\n enc1 = chr1 >> 2;\n enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);\n enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);\n enc4 = chr3 & 63;\n\n if (isNaN(chr2)) {\n enc3 = enc4 = 64;\n } else if (isNaN(chr3)) {\n enc4 = 64;\n }\n\n output = output +\n this.KEY_STR.charAt(enc1) +\n this.KEY_STR.charAt(enc2) +\n this.KEY_STR.charAt(enc3) +\n this.KEY_STR.charAt(enc4);\n chr1 = chr2 = chr3 = \"\";\n enc1 = enc2 = enc3 = enc4 = \"\";\n } while (i < input.length);\n\n return output;\n };\n \n ExifRestorer.restore = function(origFileBase64, resizedFileBase64)\n {\n var expectedBase64Header = \"data:image/jpeg;base64,\";\n\n if (!origFileBase64.match(expectedBase64Header))\n {\n \treturn resizedFileBase64;\n } \n \n var rawImage = this.decode64(origFileBase64.replace(expectedBase64Header, \"\"));\n var segments = this.slice2Segments(rawImage);\n \n var image = this.exifManipulation(resizedFileBase64, segments);\n \n return expectedBase64Header + this.encode64(image);\n \n };\n\n\n ExifRestorer.exifManipulation = function(resizedFileBase64, segments)\n {\n var exifArray = this.getExifArray(segments),\n newImageArray = this.insertExif(resizedFileBase64, exifArray),\n aBuffer = new Uint8Array(newImageArray);\n\n return aBuffer;\n };\n\n\n ExifRestorer.getExifArray = function(segments)\n {\n var seg;\n for (var x = 0; x < segments.length; x++)\n {\n seg = segments[x];\n if (seg[0] == 255 & seg[1] == 225) //(ff e1)\n {\n return seg;\n }\n }\n return [];\n };\n\n\n ExifRestorer.insertExif = function(resizedFileBase64, exifArray)\n {\n var imageData = resizedFileBase64.replace(\"data:image/jpeg;base64,\", \"\"),\n buf = this.decode64(imageData),\n separatePoint = buf.indexOf(255,3),\n mae = buf.slice(0, separatePoint),\n ato = buf.slice(separatePoint),\n array = mae;\n\n array = array.concat(exifArray);\n array = array.concat(ato);\n return array;\n };\n\n\n \n ExifRestorer.slice2Segments = function(rawImageArray)\n {\n var head = 0,\n segments = [];\n\n while (1)\n {\n if (rawImageArray[head] == 255 & rawImageArray[head + 1] == 218){break;}\n if (rawImageArray[head] == 255 & rawImageArray[head + 1] == 216)\n {\n head += 2;\n }\n else\n {\n var length = rawImageArray[head + 2] * 256 + rawImageArray[head + 3],\n endPoint = head + length + 2,\n seg = rawImageArray.slice(head, endPoint);\n segments.push(seg);\n head = endPoint;\n }\n if (head > rawImageArray.length){break;}\n }\n\n return segments;\n };\n\n\n \n ExifRestorer.decode64 = function(input) \n {\n var output = \"\",\n chr1, chr2, chr3 = \"\",\n enc1, enc2, enc3, enc4 = \"\",\n i = 0,\n buf = [];\n\n // remove all characters that are not A-Z, a-z, 0-9, +, /, or =\n var base64test = /[^A-Za-z0-9\\+\\/\\=]/g;\n if (base64test.exec(input)) {\n throw new Error(\"There were invalid base64 characters in the input text. \" +\n \"Valid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='\");\n }\n input = input.replace(/[^A-Za-z0-9\\+\\/\\=]/g, \"\");\n\n do {\n enc1 = this.KEY_STR.indexOf(input.charAt(i++));\n enc2 = this.KEY_STR.indexOf(input.charAt(i++));\n enc3 = this.KEY_STR.indexOf(input.charAt(i++));\n enc4 = this.KEY_STR.indexOf(input.charAt(i++));\n\n chr1 = (enc1 << 2) | (enc2 >> 4);\n chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);\n chr3 = ((enc3 & 3) << 6) | enc4;\n\n buf.push(chr1);\n\n if (enc3 != 64) {\n buf.push(chr2);\n }\n if (enc4 != 64) {\n buf.push(chr3);\n }\n\n chr1 = chr2 = chr3 = \"\";\n enc1 = enc2 = enc3 = enc4 = \"\";\n\n } while (i < input.length);\n\n return buf;\n };\n\n \n return ExifRestorer;\n})();\n","/* globals qq */\n/**\n * Keeps a running tally of total upload progress for a batch of files.\n *\n * @param callback Invoked when total progress changes, passing calculated total loaded & total size values.\n * @param getSize Function that returns the size of a file given its ID\n * @constructor\n */\nqq.TotalProgress = function(callback, getSize) {\n \"use strict\";\n\n var perFileProgress = {},\n totalLoaded = 0,\n totalSize = 0,\n\n lastLoadedSent = -1,\n lastTotalSent = -1,\n callbackProxy = function(loaded, total) {\n if (loaded !== lastLoadedSent || total !== lastTotalSent) {\n callback(loaded, total);\n }\n\n lastLoadedSent = loaded;\n lastTotalSent = total;\n },\n\n /**\n * @param failed Array of file IDs that have failed\n * @param retryable Array of file IDs that are retryable\n * @returns true if none of the failed files are eligible for retry\n */\n noRetryableFiles = function(failed, retryable) {\n var none = true;\n\n qq.each(failed, function(idx, failedId) {\n if (qq.indexOf(retryable, failedId) >= 0) {\n none = false;\n return false;\n }\n });\n\n return none;\n },\n\n onCancel = function(id) {\n updateTotalProgress(id, -1, -1);\n delete perFileProgress[id];\n },\n\n onAllComplete = function(successful, failed, retryable) {\n if (failed.length === 0 || noRetryableFiles(failed, retryable)) {\n callbackProxy(totalSize, totalSize);\n this.reset();\n }\n },\n\n onNew = function(id) {\n var size = getSize(id);\n\n // We might not know the size yet, such as for blob proxies\n if (size > 0) {\n updateTotalProgress(id, 0, size);\n perFileProgress[id] = {loaded: 0, total: size};\n }\n },\n\n /**\n * Invokes the callback with the current total progress of all files in the batch. Called whenever it may\n * be appropriate to re-calculate and disseminate this data.\n *\n * @param id ID of a file that has changed in some important way\n * @param newLoaded New loaded value for this file. -1 if this value should no longer be part of calculations\n * @param newTotal New total size of the file. -1 if this value should no longer be part of calculations\n */\n updateTotalProgress = function(id, newLoaded, newTotal) {\n var oldLoaded = perFileProgress[id] ? perFileProgress[id].loaded : 0,\n oldTotal = perFileProgress[id] ? perFileProgress[id].total : 0;\n\n if (newLoaded === -1 && newTotal === -1) {\n totalLoaded -= oldLoaded;\n totalSize -= oldTotal;\n }\n else {\n if (newLoaded) {\n totalLoaded += newLoaded - oldLoaded;\n }\n if (newTotal) {\n totalSize += newTotal - oldTotal;\n }\n }\n\n callbackProxy(totalLoaded, totalSize);\n };\n\n qq.extend(this, {\n // Called when a batch of files has completed uploading.\n onAllComplete: onAllComplete,\n\n // Called when the status of a file has changed.\n onStatusChange: function(id, oldStatus, newStatus) {\n if (newStatus === qq.status.CANCELED || newStatus === qq.status.REJECTED) {\n onCancel(id);\n }\n else if (newStatus === qq.status.SUBMITTING) {\n onNew(id);\n }\n },\n\n // Called whenever the upload progress of an individual file has changed.\n onIndividualProgress: function(id, loaded, total) {\n updateTotalProgress(id, loaded, total);\n perFileProgress[id] = {loaded: loaded, total: total};\n },\n\n // Called whenever the total size of a file has changed, such as when the size of a generated blob is known.\n onNewSize: function(id) {\n onNew(id);\n },\n\n reset: function() {\n perFileProgress = {};\n totalLoaded = 0;\n totalSize = 0;\n }\n });\n};\n","/*globals qq*/\nqq.PasteSupport = function(o) {\n \"use strict\";\n\n var options, detachPasteHandler;\n\n options = {\n targetElement: null,\n callbacks: {\n log: function(message, level) {},\n pasteReceived: function(blob) {}\n }\n };\n\n function isImage(item) {\n return item.type &&\n item.type.indexOf(\"image/\") === 0;\n }\n\n function registerPasteHandler() {\n detachPasteHandler = qq(options.targetElement).attach(\"paste\", function(event) {\n var clipboardData = event.clipboardData;\n\n if (clipboardData) {\n qq.each(clipboardData.items, function(idx, item) {\n if (isImage(item)) {\n var blob = item.getAsFile();\n options.callbacks.pasteReceived(blob);\n }\n });\n }\n });\n }\n\n function unregisterPasteHandler() {\n if (detachPasteHandler) {\n detachPasteHandler();\n }\n }\n\n qq.extend(options, o);\n registerPasteHandler();\n\n qq.extend(this, {\n reset: function() {\n unregisterPasteHandler();\n }\n });\n};\n","/* globals qq */\n/**\n * Module that handles support for existing forms.\n *\n * @param options Options passed from the integrator-supplied options related to form support.\n * @param startUpload Callback to invoke when files \"stored\" should be uploaded.\n * @param log Proxy for the logger\n * @constructor\n */\nqq.FormSupport = function(options, startUpload, log) {\n \"use strict\";\n var self = this,\n interceptSubmit = options.interceptSubmit,\n formEl = options.element,\n autoUpload = options.autoUpload;\n\n // Available on the public API associated with this module.\n qq.extend(this, {\n // To be used by the caller to determine if the endpoint will be determined by some processing\n // that occurs in this module, such as if the form has an action attribute.\n // Ignore if `attachToForm === false`.\n newEndpoint: null,\n\n // To be used by the caller to determine if auto uploading should be allowed.\n // Ignore if `attachToForm === false`.\n newAutoUpload: autoUpload,\n\n // true if a form was detected and is being tracked by this module\n attachedToForm: false,\n\n // Returns an object with names and values for all valid form elements associated with the attached form.\n getFormInputsAsObject: function() {\n /* jshint eqnull:true */\n if (formEl == null) {\n return null;\n }\n\n return self._form2Obj(formEl);\n }\n });\n\n // If the form contains an action attribute, this should be the new upload endpoint.\n function determineNewEndpoint(formEl) {\n if (formEl.getAttribute(\"action\")) {\n self.newEndpoint = formEl.getAttribute(\"action\");\n }\n }\n\n // Return true only if the form is valid, or if we cannot make this determination.\n // If the form is invalid, ensure invalid field(s) are highlighted in the UI.\n function validateForm(formEl, nativeSubmit) {\n if (formEl.checkValidity && !formEl.checkValidity()) {\n log(\"Form did not pass validation checks - will not upload.\", \"error\");\n nativeSubmit();\n }\n else {\n return true;\n }\n }\n\n // Intercept form submit attempts, unless the integrator has told us not to do this.\n function maybeUploadOnSubmit(formEl) {\n var nativeSubmit = formEl.submit;\n\n // Intercept and squelch submit events.\n qq(formEl).attach(\"submit\", function(event) {\n event = event || window.event;\n\n if (event.preventDefault) {\n event.preventDefault();\n }\n else {\n event.returnValue = false;\n }\n\n validateForm(formEl, nativeSubmit) && startUpload();\n });\n\n // The form's `submit()` function may be called instead (i.e. via jQuery.submit()).\n // Intercept that too.\n formEl.submit = function() {\n validateForm(formEl, nativeSubmit) && startUpload();\n };\n }\n\n // If the element value passed from the uploader is a string, assume it is an element ID - select it.\n // The rest of the code in this module depends on this being an HTMLElement.\n function determineFormEl(formEl) {\n if (formEl) {\n if (qq.isString(formEl)) {\n formEl = document.getElementById(formEl);\n }\n\n if (formEl) {\n log(\"Attaching to form element.\");\n determineNewEndpoint(formEl);\n interceptSubmit && maybeUploadOnSubmit(formEl);\n }\n }\n\n return formEl;\n }\n\n formEl = determineFormEl(formEl);\n this.attachedToForm = !!formEl;\n};\n\nqq.extend(qq.FormSupport.prototype, {\n // Converts all relevant form fields to key/value pairs. This is meant to mimic the data a browser will\n // construct from a given form when the form is submitted.\n _form2Obj: function(form) {\n \"use strict\";\n var obj = {},\n notIrrelevantType = function(type) {\n var irrelevantTypes = [\n \"button\",\n \"image\",\n \"reset\",\n \"submit\"\n ];\n\n return qq.indexOf(irrelevantTypes, type.toLowerCase()) < 0;\n },\n radioOrCheckbox = function(type) {\n return qq.indexOf([\"checkbox\", \"radio\"], type.toLowerCase()) >= 0;\n },\n ignoreValue = function(el) {\n if (radioOrCheckbox(el.type) && !el.checked) {\n return true;\n }\n\n return el.disabled && el.type.toLowerCase() !== \"hidden\";\n },\n selectValue = function(select) {\n var value = null;\n\n qq.each(qq(select).children(), function(idx, child) {\n if (child.tagName.toLowerCase() === \"option\" && child.selected) {\n value = child.value;\n return false;\n }\n });\n\n return value;\n };\n\n qq.each(form.elements, function(idx, el) {\n if ((qq.isInput(el, true) || el.tagName.toLowerCase() === \"textarea\") &&\n notIrrelevantType(el.type) &&\n !ignoreValue(el)) {\n\n obj[el.name] = el.value;\n }\n else if (el.tagName.toLowerCase() === \"select\" && !ignoreValue(el)) {\n var value = selectValue(el);\n\n if (value !== null) {\n obj[el.name] = value;\n }\n }\n });\n\n return obj;\n }\n});\n","/*globals qq*/\n/**\n * Upload handler used that assumes the current user agent does not have any support for the\n * File API, and, therefore, makes use of iframes and forms to submit the files directly to\n * a generic server.\n *\n * @param options Options passed from the base handler\n * @param proxy Callbacks & methods used to query for or push out data/changes\n */\nqq.traditional = qq.traditional || {};\nqq.traditional.FormUploadHandler = function(options, proxy) {\n \"use strict\";\n\n var handler = this,\n getName = proxy.getName,\n getUuid = proxy.getUuid,\n log = proxy.log;\n\n /**\n * Returns json object received by iframe from server.\n */\n function getIframeContentJson(id, iframe) {\n /*jshint evil: true*/\n\n var response, doc, innerHtml;\n\n //IE may throw an \"access is denied\" error when attempting to access contentDocument on the iframe in some cases\n try {\n // iframe.contentWindow.document - for IE<7\n doc = iframe.contentDocument || iframe.contentWindow.document;\n innerHtml = doc.body.innerHTML;\n\n log(\"converting iframe's innerHTML to JSON\");\n log(\"innerHTML = \" + innerHtml);\n //plain text response may be wrapped in tag\n if (innerHtml && innerHtml.match(/^ 1 && !options.allowMultipleItems) {\n options.callbacks.processingDroppedFilesComplete([]);\n options.callbacks.dropError(\"tooManyFilesError\", \"\");\n uploadDropZone.dropDisabled(false);\n handleDataTransferPromise.failure();\n }\n else {\n droppedFiles = [];\n\n if (qq.isFolderDropSupported(dataTransfer)) {\n qq.each(dataTransfer.items, function(idx, item) {\n var entry = item.webkitGetAsEntry();\n\n if (entry) {\n //due to a bug in Chrome's File System API impl - #149735\n if (entry.isFile) {\n droppedFiles.push(item.getAsFile());\n }\n\n else {\n pendingFolderPromises.push(traverseFileTree(entry).done(function() {\n pendingFolderPromises.pop();\n if (pendingFolderPromises.length === 0) {\n handleDataTransferPromise.success();\n }\n }));\n }\n }\n });\n }\n else {\n droppedFiles = dataTransfer.files;\n }\n\n if (pendingFolderPromises.length === 0) {\n handleDataTransferPromise.success();\n }\n }\n\n return handleDataTransferPromise;\n }\n\n function setupDropzone(dropArea) {\n var dropZone = new qq.UploadDropZone({\n HIDE_ZONES_EVENT_NAME: HIDE_ZONES_EVENT_NAME,\n element: dropArea,\n onEnter: function(e) {\n qq(dropArea).addClass(options.classes.dropActive);\n e.stopPropagation();\n },\n onLeaveNotDescendants: function(e) {\n qq(dropArea).removeClass(options.classes.dropActive);\n },\n onDrop: function(e) {\n handleDataTransfer(e.dataTransfer, dropZone).then(\n function() {\n uploadDroppedFiles(droppedFiles, dropZone);\n },\n function() {\n options.callbacks.dropLog(\"Drop event DataTransfer parsing failed. No files will be uploaded.\", \"error\");\n }\n );\n }\n });\n\n disposeSupport.addDisposer(function() {\n dropZone.dispose();\n });\n\n qq(dropArea).hasAttribute(HIDE_BEFORE_ENTER_ATTR) && qq(dropArea).hide();\n\n uploadDropZones.push(dropZone);\n\n return dropZone;\n }\n\n function isFileDrag(dragEvent) {\n var fileDrag;\n\n qq.each(dragEvent.dataTransfer.types, function(key, val) {\n if (val === \"Files\") {\n fileDrag = true;\n return false;\n }\n });\n\n return fileDrag;\n }\n\n // Attempt to determine when the file has left the document. It is not always possible to detect this\n // in all cases, but it is generally possible in all browsers, with a few exceptions.\n //\n // Exceptions:\n // * IE10+ & Safari: We can't detect a file leaving the document if the Explorer window housing the file\n // overlays the browser window.\n // * IE10+: If the file is dragged out of the window too quickly, IE does not set the expected values of the\n // event's X & Y properties.\n function leavingDocumentOut(e) {\n if (qq.safari()) {\n return e.x < 0 || e.y < 0;\n }\n\n return e.x === 0 && e.y === 0;\n }\n\n function setupDragDrop() {\n var dropZones = options.dropZoneElements,\n\n maybeHideDropZones = function() {\n setTimeout(function() {\n qq.each(dropZones, function(idx, dropZone) {\n qq(dropZone).hasAttribute(HIDE_BEFORE_ENTER_ATTR) && qq(dropZone).hide();\n qq(dropZone).removeClass(options.classes.dropActive);\n });\n }, 10);\n };\n\n qq.each(dropZones, function(idx, dropZone) {\n var uploadDropZone = setupDropzone(dropZone);\n\n // IE <= 9 does not support the File API used for drag+drop uploads\n if (dropZones.length && qq.supportedFeatures.fileDrop) {\n disposeSupport.attach(document, \"dragenter\", function(e) {\n if (!uploadDropZone.dropDisabled() && isFileDrag(e)) {\n qq.each(dropZones, function(idx, dropZone) {\n // We can't apply styles to non-HTMLElements, since they lack the `style` property.\n // Also, if the drop zone isn't initially hidden, let's not mess with `style.display`.\n if (dropZone instanceof HTMLElement &&\n qq(dropZone).hasAttribute(HIDE_BEFORE_ENTER_ATTR)) {\n\n qq(dropZone).css({display: \"block\"});\n }\n });\n }\n });\n }\n });\n\n disposeSupport.attach(document, \"dragleave\", function(e) {\n if (leavingDocumentOut(e)) {\n maybeHideDropZones();\n }\n });\n\n // Just in case we were not able to detect when a dragged file has left the document,\n // hide all relevant drop zones the next time the mouse enters the document.\n // Note that mouse events such as this one are not fired during drag operations.\n disposeSupport.attach(qq(document).children()[0], \"mouseenter\", function(e) {\n maybeHideDropZones();\n });\n\n disposeSupport.attach(document, \"drop\", function(e) {\n if (isFileDrag(e)) {\n e.preventDefault();\n maybeHideDropZones();\n }\n });\n\n disposeSupport.attach(document, HIDE_ZONES_EVENT_NAME, maybeHideDropZones);\n }\n\n setupDragDrop();\n\n qq.extend(this, {\n setupExtraDropzone: function(element) {\n options.dropZoneElements.push(element);\n setupDropzone(element);\n },\n\n removeDropzone: function(element) {\n var i,\n dzs = options.dropZoneElements;\n\n for (i in dzs) {\n if (dzs[i] === element) {\n return dzs.splice(i, 1);\n }\n }\n },\n\n dispose: function() {\n disposeSupport.dispose();\n qq.each(uploadDropZones, function(idx, dropZone) {\n dropZone.dispose();\n });\n }\n });\n\n this._testing = {};\n this._testing.extractDirectoryPath = extractDirectoryPath;\n};\n\nqq.DragAndDrop.callbacks = function() {\n \"use strict\";\n\n return {\n processingDroppedFiles: function() {},\n processingDroppedFilesComplete: function(files, targetEl) {},\n dropError: function(code, errorSpecifics) {\n qq.log(\"Drag & drop error code '\" + code + \" with these specifics: '\" + errorSpecifics + \"'\", \"error\");\n },\n dropLog: function(message, level) {\n qq.log(message, level);\n }\n };\n};\n\nqq.UploadDropZone = function(o) {\n \"use strict\";\n\n var disposeSupport = new qq.DisposeSupport(),\n options, element, preventDrop, dropOutsideDisabled;\n\n options = {\n element: null,\n onEnter: function(e) {},\n onLeave: function(e) {},\n // is not fired when leaving element by hovering descendants\n onLeaveNotDescendants: function(e) {},\n onDrop: function(e) {}\n };\n\n qq.extend(options, o);\n element = options.element;\n\n function dragoverShouldBeCanceled() {\n return qq.safari() || (qq.firefox() && qq.windows());\n }\n\n function disableDropOutside(e) {\n // run only once for all instances\n if (!dropOutsideDisabled) {\n\n // for these cases we need to catch onDrop to reset dropArea\n if (dragoverShouldBeCanceled) {\n disposeSupport.attach(document, \"dragover\", function(e) {\n e.preventDefault();\n });\n } else {\n disposeSupport.attach(document, \"dragover\", function(e) {\n if (e.dataTransfer) {\n e.dataTransfer.dropEffect = \"none\";\n e.preventDefault();\n }\n });\n }\n\n dropOutsideDisabled = true;\n }\n }\n\n function isValidFileDrag(e) {\n // e.dataTransfer currently causing IE errors\n // IE9 does NOT support file API, so drag-and-drop is not possible\n if (!qq.supportedFeatures.fileDrop) {\n return false;\n }\n\n var effectTest, dt = e.dataTransfer,\n // do not check dt.types.contains in webkit, because it crashes safari 4\n isSafari = qq.safari();\n\n // dt.effectAllowed is none in Safari 5\n\n // dt.effectAllowed crashes IE 11 & 10 when files have been dragged from\n // the filesystem\n effectTest = qq.ie() && qq.supportedFeatures.fileDrop ? true : dt.effectAllowed !== \"none\";\n return dt && effectTest &&\n (\n (dt.files && dt.files.length) || // Valid for drop events with files\n (!isSafari && dt.types.contains && dt.types.contains(\"Files\")) || // Valid in Chrome/Firefox\n (dt.types.includes && dt.types.includes(\"Files\")) // Valid in IE\n );\n }\n\n function isOrSetDropDisabled(isDisabled) {\n if (isDisabled !== undefined) {\n preventDrop = isDisabled;\n }\n return preventDrop;\n }\n\n function triggerHidezonesEvent() {\n var hideZonesEvent;\n\n function triggerUsingOldApi() {\n hideZonesEvent = document.createEvent(\"Event\");\n hideZonesEvent.initEvent(options.HIDE_ZONES_EVENT_NAME, true, true);\n }\n\n if (window.CustomEvent) {\n try {\n hideZonesEvent = new CustomEvent(options.HIDE_ZONES_EVENT_NAME);\n }\n catch (err) {\n triggerUsingOldApi();\n }\n }\n else {\n triggerUsingOldApi();\n }\n\n document.dispatchEvent(hideZonesEvent);\n }\n\n function attachEvents() {\n disposeSupport.attach(element, \"dragover\", function(e) {\n if (!isValidFileDrag(e)) {\n return;\n }\n\n // dt.effectAllowed crashes IE 11 & 10 when files have been dragged from\n // the filesystem\n var effect = qq.ie() && qq.supportedFeatures.fileDrop ? null : e.dataTransfer.effectAllowed;\n if (effect === \"move\" || effect === \"linkMove\") {\n e.dataTransfer.dropEffect = \"move\"; // for FF (only move allowed)\n } else {\n e.dataTransfer.dropEffect = \"copy\"; // for Chrome\n }\n\n e.stopPropagation();\n e.preventDefault();\n });\n\n disposeSupport.attach(element, \"dragenter\", function(e) {\n if (!isOrSetDropDisabled()) {\n if (!isValidFileDrag(e)) {\n return;\n }\n options.onEnter(e);\n }\n });\n\n disposeSupport.attach(element, \"dragleave\", function(e) {\n if (!isValidFileDrag(e)) {\n return;\n }\n\n options.onLeave(e);\n\n var relatedTarget = document.elementFromPoint(e.clientX, e.clientY);\n // do not fire when moving a mouse over a descendant\n if (qq(this).contains(relatedTarget)) {\n return;\n }\n\n options.onLeaveNotDescendants(e);\n });\n\n disposeSupport.attach(element, \"drop\", function(e) {\n if (!isOrSetDropDisabled()) {\n if (!isValidFileDrag(e)) {\n return;\n }\n\n e.preventDefault();\n e.stopPropagation();\n options.onDrop(e);\n\n triggerHidezonesEvent();\n }\n });\n }\n\n disableDropOutside();\n attachEvents();\n\n qq.extend(this, {\n dropDisabled: function(isDisabled) {\n return isOrSetDropDisabled(isDisabled);\n },\n\n dispose: function() {\n disposeSupport.dispose();\n },\n\n getElement: function() {\n return element;\n }\n });\n\n this._testing = {};\n this._testing.isValidFileDrag = isValidFileDrag;\n};\n","/*globals qq */\n/**\n * Defines the public API for FineUploader mode.\n */\n(function() {\n \"use strict\";\n\n qq.uiPublicApi = {\n addInitialFiles: function(cannedFileList) {\n this._parent.prototype.addInitialFiles.apply(this, arguments);\n this._templating.addCacheToDom();\n },\n\n clearStoredFiles: function() {\n this._parent.prototype.clearStoredFiles.apply(this, arguments);\n this._templating.clearFiles();\n },\n\n addExtraDropzone: function(element) {\n this._dnd && this._dnd.setupExtraDropzone(element);\n },\n\n removeExtraDropzone: function(element) {\n if (this._dnd) {\n return this._dnd.removeDropzone(element);\n }\n },\n\n getItemByFileId: function(id) {\n if (!this._templating.isHiddenForever(id)) {\n return this._templating.getFileContainer(id);\n }\n },\n\n reset: function() {\n this._parent.prototype.reset.apply(this, arguments);\n this._templating.reset();\n\n if (!this._options.button && this._templating.getButton()) {\n this._defaultButtonId = this._createUploadButton({\n element: this._templating.getButton(),\n title: this._options.text.fileInputTitle\n }).getButtonId();\n }\n\n if (this._dnd) {\n this._dnd.dispose();\n this._dnd = this._setupDragAndDrop();\n }\n\n this._totalFilesInBatch = 0;\n this._filesInBatchAddedToUi = 0;\n\n this._setupClickAndEditEventHandlers();\n },\n\n setName: function(id, newName) {\n var formattedFilename = this._options.formatFileName(newName);\n\n this._parent.prototype.setName.apply(this, arguments);\n this._templating.updateFilename(id, formattedFilename);\n },\n\n pauseUpload: function(id) {\n var paused = this._parent.prototype.pauseUpload.apply(this, arguments);\n\n paused && this._templating.uploadPaused(id);\n return paused;\n },\n\n continueUpload: function(id) {\n var continued = this._parent.prototype.continueUpload.apply(this, arguments);\n\n continued && this._templating.uploadContinued(id);\n return continued;\n },\n\n getId: function(fileContainerOrChildEl) {\n return this._templating.getFileId(fileContainerOrChildEl);\n },\n\n getDropTarget: function(fileId) {\n var file = this.getFile(fileId);\n\n return file.qqDropTarget;\n }\n };\n\n /**\n * Defines the private (internal) API for FineUploader mode.\n */\n qq.uiPrivateApi = {\n _getButton: function(buttonId) {\n var button = this._parent.prototype._getButton.apply(this, arguments);\n\n if (!button) {\n if (buttonId === this._defaultButtonId) {\n button = this._templating.getButton();\n }\n }\n\n return button;\n },\n\n _removeFileItem: function(fileId) {\n this._templating.removeFile(fileId);\n },\n\n _setupClickAndEditEventHandlers: function() {\n this._fileButtonsClickHandler = qq.FileButtonsClickHandler && this._bindFileButtonsClickEvent();\n\n // A better approach would be to check specifically for focusin event support by querying the DOM API,\n // but the DOMFocusIn event is not exposed as a property, so we have to resort to UA string sniffing.\n this._focusinEventSupported = !qq.firefox();\n\n if (this._isEditFilenameEnabled())\n {\n this._filenameClickHandler = this._bindFilenameClickEvent();\n this._filenameInputFocusInHandler = this._bindFilenameInputFocusInEvent();\n this._filenameInputFocusHandler = this._bindFilenameInputFocusEvent();\n }\n },\n\n _setupDragAndDrop: function() {\n var self = this,\n dropZoneElements = this._options.dragAndDrop.extraDropzones,\n templating = this._templating,\n defaultDropZone = templating.getDropZone();\n\n defaultDropZone && dropZoneElements.push(defaultDropZone);\n\n return new qq.DragAndDrop({\n dropZoneElements: dropZoneElements,\n allowMultipleItems: this._options.multiple,\n classes: {\n dropActive: this._options.classes.dropActive\n },\n callbacks: {\n processingDroppedFiles: function() {\n templating.showDropProcessing();\n },\n processingDroppedFilesComplete: function(files, targetEl) {\n templating.hideDropProcessing();\n\n qq.each(files, function(idx, file) {\n file.qqDropTarget = targetEl;\n });\n\n if (files.length) {\n self.addFiles(files, null, null);\n }\n },\n dropError: function(code, errorData) {\n self._itemError(code, errorData);\n },\n dropLog: function(message, level) {\n self.log(message, level);\n }\n }\n });\n },\n\n _bindFileButtonsClickEvent: function() {\n var self = this;\n\n return new qq.FileButtonsClickHandler({\n templating: this._templating,\n\n log: function(message, lvl) {\n self.log(message, lvl);\n },\n\n onDeleteFile: function(fileId) {\n self.deleteFile(fileId);\n },\n\n onCancel: function(fileId) {\n self.cancel(fileId);\n },\n\n onRetry: function(fileId) {\n self.retry(fileId);\n },\n\n onPause: function(fileId) {\n self.pauseUpload(fileId);\n },\n\n onContinue: function(fileId) {\n self.continueUpload(fileId);\n },\n\n onGetName: function(fileId) {\n return self.getName(fileId);\n }\n });\n },\n\n _isEditFilenameEnabled: function() {\n /*jshint -W014 */\n return this._templating.isEditFilenamePossible()\n && !this._options.autoUpload\n && qq.FilenameClickHandler\n && qq.FilenameInputFocusHandler\n && qq.FilenameInputFocusHandler;\n },\n\n _filenameEditHandler: function() {\n var self = this,\n templating = this._templating;\n\n return {\n templating: templating,\n log: function(message, lvl) {\n self.log(message, lvl);\n },\n onGetUploadStatus: function(fileId) {\n return self.getUploads({id: fileId}).status;\n },\n onGetName: function(fileId) {\n return self.getName(fileId);\n },\n onSetName: function(id, newName) {\n self.setName(id, newName);\n },\n onEditingStatusChange: function(id, isEditing) {\n var qqInput = qq(templating.getEditInput(id)),\n qqFileContainer = qq(templating.getFileContainer(id));\n\n if (isEditing) {\n qqInput.addClass(\"qq-editing\");\n templating.hideFilename(id);\n templating.hideEditIcon(id);\n }\n else {\n qqInput.removeClass(\"qq-editing\");\n templating.showFilename(id);\n templating.showEditIcon(id);\n }\n\n // Force IE8 and older to repaint\n qqFileContainer.addClass(\"qq-temp\").removeClass(\"qq-temp\");\n }\n };\n },\n\n _onUploadStatusChange: function(id, oldStatus, newStatus) {\n this._parent.prototype._onUploadStatusChange.apply(this, arguments);\n\n if (this._isEditFilenameEnabled()) {\n // Status for a file exists before it has been added to the DOM, so we must be careful here.\n if (this._templating.getFileContainer(id) && newStatus !== qq.status.SUBMITTED) {\n this._templating.markFilenameEditable(id);\n this._templating.hideEditIcon(id);\n }\n }\n\n if (oldStatus === qq.status.UPLOAD_RETRYING && newStatus === qq.status.UPLOADING) {\n this._templating.hideRetry(id);\n this._templating.setStatusText(id);\n qq(this._templating.getFileContainer(id)).removeClass(this._classes.retrying);\n }\n else if (newStatus === qq.status.UPLOAD_FAILED) {\n this._templating.hidePause(id);\n }\n },\n\n _bindFilenameInputFocusInEvent: function() {\n var spec = qq.extend({}, this._filenameEditHandler());\n\n return new qq.FilenameInputFocusInHandler(spec);\n },\n\n _bindFilenameInputFocusEvent: function() {\n var spec = qq.extend({}, this._filenameEditHandler());\n\n return new qq.FilenameInputFocusHandler(spec);\n },\n\n _bindFilenameClickEvent: function() {\n var spec = qq.extend({}, this._filenameEditHandler());\n\n return new qq.FilenameClickHandler(spec);\n },\n\n _storeForLater: function(id) {\n this._parent.prototype._storeForLater.apply(this, arguments);\n this._templating.hideSpinner(id);\n },\n\n _onAllComplete: function(successful, failed) {\n this._parent.prototype._onAllComplete.apply(this, arguments);\n this._templating.resetTotalProgress();\n },\n\n _onSubmit: function(id, name) {\n var file = this.getFile(id);\n\n if (file && file.qqPath && this._options.dragAndDrop.reportDirectoryPaths) {\n this._paramsStore.addReadOnly(id, {\n qqpath: file.qqPath\n });\n }\n\n this._parent.prototype._onSubmit.apply(this, arguments);\n this._addToList(id, name);\n },\n\n // The file item has been added to the DOM.\n _onSubmitted: function(id) {\n // If the edit filename feature is enabled, mark the filename element as \"editable\" and the associated edit icon\n if (this._isEditFilenameEnabled()) {\n this._templating.markFilenameEditable(id);\n this._templating.showEditIcon(id);\n\n // If the focusin event is not supported, we must add a focus handler to the newly create edit filename text input\n if (!this._focusinEventSupported) {\n this._filenameInputFocusHandler.addHandler(this._templating.getEditInput(id));\n }\n }\n },\n\n // Update the progress bar & percentage as the file is uploaded\n _onProgress: function(id, name, loaded, total) {\n this._parent.prototype._onProgress.apply(this, arguments);\n\n this._templating.updateProgress(id, loaded, total);\n\n if (total === 0 || Math.round(loaded / total * 100) === 100) {\n this._templating.hideCancel(id);\n this._templating.hidePause(id);\n this._templating.hideProgress(id);\n this._templating.setStatusText(id, this._options.text.waitingForResponse);\n\n // If ~last byte was sent, display total file size\n this._displayFileSize(id);\n }\n else {\n // If still uploading, display percentage - total size is actually the total request(s) size\n this._displayFileSize(id, loaded, total);\n }\n },\n\n _onTotalProgress: function(loaded, total) {\n this._parent.prototype._onTotalProgress.apply(this, arguments);\n this._templating.updateTotalProgress(loaded, total);\n },\n\n _onComplete: function(id, name, result, xhr) {\n var parentRetVal = this._parent.prototype._onComplete.apply(this, arguments),\n templating = this._templating,\n fileContainer = templating.getFileContainer(id),\n self = this;\n\n function completeUpload(result) {\n // If this file is not represented in the templating module, perhaps it was hidden intentionally.\n // If so, don't perform any UI-related tasks related to this file.\n if (!fileContainer) {\n return;\n }\n\n templating.setStatusText(id);\n\n qq(fileContainer).removeClass(self._classes.retrying);\n templating.hideProgress(id);\n\n if (self.getUploads({id: id}).status !== qq.status.UPLOAD_FAILED) {\n templating.hideCancel(id);\n }\n templating.hideSpinner(id);\n\n if (result.success) {\n self._markFileAsSuccessful(id);\n }\n else {\n qq(fileContainer).addClass(self._classes.fail);\n templating.showCancel(id);\n\n if (templating.isRetryPossible() && !self._preventRetries[id]) {\n qq(fileContainer).addClass(self._classes.retryable);\n templating.showRetry(id);\n }\n self._controlFailureTextDisplay(id, result);\n }\n }\n\n // The parent may need to perform some async operation before we can accurately determine the status of the upload.\n if (parentRetVal instanceof qq.Promise) {\n parentRetVal.done(function(newResult) {\n completeUpload(newResult);\n });\n\n }\n else {\n completeUpload(result);\n }\n\n return parentRetVal;\n },\n\n _markFileAsSuccessful: function(id) {\n var templating = this._templating;\n\n if (this._isDeletePossible()) {\n templating.showDeleteButton(id);\n }\n\n qq(templating.getFileContainer(id)).addClass(this._classes.success);\n\n this._maybeUpdateThumbnail(id);\n },\n\n _onUploadPrep: function(id) {\n this._parent.prototype._onUploadPrep.apply(this, arguments);\n this._templating.showSpinner(id);\n },\n\n _onUpload: function(id, name) {\n var parentRetVal = this._parent.prototype._onUpload.apply(this, arguments);\n\n this._templating.showSpinner(id);\n\n return parentRetVal;\n },\n\n _onUploadChunk: function(id, chunkData) {\n this._parent.prototype._onUploadChunk.apply(this, arguments);\n\n // Only display the pause button if we have finished uploading at least one chunk\n // & this file can be resumed\n if (chunkData.partIndex > 0 && this._handler.isResumable(id)) {\n this._templating.allowPause(id);\n }\n },\n\n _onCancel: function(id, name) {\n this._parent.prototype._onCancel.apply(this, arguments);\n this._removeFileItem(id);\n\n if (this._getNotFinished() === 0) {\n this._templating.resetTotalProgress();\n }\n },\n\n _onBeforeAutoRetry: function(id) {\n var retryNumForDisplay, maxAuto, retryNote;\n\n this._parent.prototype._onBeforeAutoRetry.apply(this, arguments);\n\n this._showCancelLink(id);\n\n if (this._options.retry.showAutoRetryNote) {\n retryNumForDisplay = this._autoRetries[id];\n maxAuto = this._options.retry.maxAutoAttempts;\n\n retryNote = this._options.retry.autoRetryNote.replace(/\\{retryNum\\}/g, retryNumForDisplay);\n retryNote = retryNote.replace(/\\{maxAuto\\}/g, maxAuto);\n\n this._templating.setStatusText(id, retryNote);\n qq(this._templating.getFileContainer(id)).addClass(this._classes.retrying);\n }\n },\n\n //return false if we should not attempt the requested retry\n _onBeforeManualRetry: function(id) {\n if (this._parent.prototype._onBeforeManualRetry.apply(this, arguments)) {\n this._templating.resetProgress(id);\n qq(this._templating.getFileContainer(id)).removeClass(this._classes.fail);\n this._templating.setStatusText(id);\n this._templating.showSpinner(id);\n this._showCancelLink(id);\n return true;\n }\n else {\n qq(this._templating.getFileContainer(id)).addClass(this._classes.retryable);\n this._templating.showRetry(id);\n return false;\n }\n },\n\n _onSubmitDelete: function(id) {\n var onSuccessCallback = qq.bind(this._onSubmitDeleteSuccess, this);\n\n this._parent.prototype._onSubmitDelete.call(this, id, onSuccessCallback);\n },\n\n _onSubmitDeleteSuccess: function(id, uuid, additionalMandatedParams) {\n if (this._options.deleteFile.forceConfirm) {\n this._showDeleteConfirm.apply(this, arguments);\n }\n else {\n this._sendDeleteRequest.apply(this, arguments);\n }\n },\n\n _onDeleteComplete: function(id, xhr, isError) {\n this._parent.prototype._onDeleteComplete.apply(this, arguments);\n\n this._templating.hideSpinner(id);\n\n if (isError) {\n this._templating.setStatusText(id, this._options.deleteFile.deletingFailedText);\n this._templating.showDeleteButton(id);\n }\n else {\n this._removeFileItem(id);\n }\n },\n\n _sendDeleteRequest: function(id, uuid, additionalMandatedParams) {\n this._templating.hideDeleteButton(id);\n this._templating.showSpinner(id);\n this._templating.setStatusText(id, this._options.deleteFile.deletingStatusText);\n this._deleteHandler.sendDelete.apply(this, arguments);\n },\n\n _showDeleteConfirm: function(id, uuid, mandatedParams) {\n /*jshint -W004 */\n var fileName = this.getName(id),\n confirmMessage = this._options.deleteFile.confirmMessage.replace(/\\{filename\\}/g, fileName),\n uuid = this.getUuid(id),\n deleteRequestArgs = arguments,\n self = this,\n retVal;\n\n retVal = this._options.showConfirm(confirmMessage);\n\n if (qq.isGenericPromise(retVal)) {\n retVal.then(function() {\n self._sendDeleteRequest.apply(self, deleteRequestArgs);\n });\n }\n else if (retVal !== false) {\n self._sendDeleteRequest.apply(self, deleteRequestArgs);\n }\n },\n\n _addToList: function(id, name, canned) {\n var prependData,\n prependIndex = 0,\n dontDisplay = this._handler.isProxied(id) && this._options.scaling.hideScaled,\n record;\n\n if (this._options.display.prependFiles) {\n if (this._totalFilesInBatch > 1 && this._filesInBatchAddedToUi > 0) {\n prependIndex = this._filesInBatchAddedToUi - 1;\n }\n\n prependData = {\n index: prependIndex\n };\n }\n\n if (!canned) {\n if (this._options.disableCancelForFormUploads && !qq.supportedFeatures.ajaxUploading) {\n this._templating.disableCancel();\n }\n\n // Cancel all existing (previous) files and clear the list if this file is not part of\n // a scaled file group that has already been accepted, or if this file is not part of\n // a scaled file group at all.\n if (!this._options.multiple) {\n record = this.getUploads({id: id});\n\n this._handledProxyGroup = this._handledProxyGroup || record.proxyGroupId;\n\n if (record.proxyGroupId !== this._handledProxyGroup || !record.proxyGroupId) {\n this._handler.cancelAll();\n this._clearList();\n this._handledProxyGroup = null;\n }\n }\n }\n\n if (canned) {\n this._templating.addFileToCache(id, this._options.formatFileName(name), prependData, dontDisplay);\n this._templating.updateThumbnail(id, this._thumbnailUrls[id], true, this._options.thumbnails.customResizer);\n }\n else {\n this._templating.addFile(id, this._options.formatFileName(name), prependData, dontDisplay);\n this._templating.generatePreview(id, this.getFile(id), this._options.thumbnails.customResizer);\n }\n\n this._filesInBatchAddedToUi += 1;\n\n if (canned ||\n (this._options.display.fileSizeOnSubmit && qq.supportedFeatures.ajaxUploading)) {\n\n this._displayFileSize(id);\n }\n },\n\n _clearList: function() {\n this._templating.clearFiles();\n this.clearStoredFiles();\n },\n\n _displayFileSize: function(id, loadedSize, totalSize) {\n var size = this.getSize(id),\n sizeForDisplay = this._formatSize(size);\n\n if (size >= 0) {\n if (loadedSize !== undefined && totalSize !== undefined) {\n sizeForDisplay = this._formatProgress(loadedSize, totalSize);\n }\n\n this._templating.updateSize(id, sizeForDisplay);\n }\n },\n\n _formatProgress: function(uploadedSize, totalSize) {\n var message = this._options.text.formatProgress;\n function r(name, replacement) { message = message.replace(name, replacement); }\n\n r(\"{percent}\", Math.round(uploadedSize / totalSize * 100));\n r(\"{total_size}\", this._formatSize(totalSize));\n return message;\n },\n\n _controlFailureTextDisplay: function(id, response) {\n var mode, responseProperty, failureReason;\n\n mode = this._options.failedUploadTextDisplay.mode;\n responseProperty = this._options.failedUploadTextDisplay.responseProperty;\n\n if (mode === \"custom\") {\n failureReason = response[responseProperty];\n if (!failureReason) {\n failureReason = this._options.text.failUpload;\n }\n\n this._templating.setStatusText(id, failureReason);\n\n if (this._options.failedUploadTextDisplay.enableTooltip) {\n this._showTooltip(id, failureReason);\n }\n }\n else if (mode === \"default\") {\n this._templating.setStatusText(id, this._options.text.failUpload);\n }\n else if (mode !== \"none\") {\n this.log(\"failedUploadTextDisplay.mode value of '\" + mode + \"' is not valid\", \"warn\");\n }\n },\n\n _showTooltip: function(id, text) {\n this._templating.getFileContainer(id).title = text;\n },\n\n _showCancelLink: function(id) {\n if (!this._options.disableCancelForFormUploads || qq.supportedFeatures.ajaxUploading) {\n this._templating.showCancel(id);\n }\n },\n\n _itemError: function(code, name, item) {\n var message = this._parent.prototype._itemError.apply(this, arguments);\n this._options.showMessage(message);\n },\n\n _batchError: function(message) {\n this._parent.prototype._batchError.apply(this, arguments);\n this._options.showMessage(message);\n },\n\n _setupPastePrompt: function() {\n var self = this;\n\n this._options.callbacks.onPasteReceived = function() {\n var message = self._options.paste.namePromptMessage,\n defaultVal = self._options.paste.defaultName;\n\n return self._options.showPrompt(message, defaultVal);\n };\n },\n\n _fileOrBlobRejected: function(id, name) {\n this._totalFilesInBatch -= 1;\n this._parent.prototype._fileOrBlobRejected.apply(this, arguments);\n },\n\n _prepareItemsForUpload: function(items, params, endpoint) {\n this._totalFilesInBatch = items.length;\n this._filesInBatchAddedToUi = 0;\n this._parent.prototype._prepareItemsForUpload.apply(this, arguments);\n },\n\n _maybeUpdateThumbnail: function(fileId) {\n var thumbnailUrl = this._thumbnailUrls[fileId],\n fileStatus = this.getUploads({id: fileId}).status;\n\n if (fileStatus !== qq.status.DELETED &&\n (thumbnailUrl ||\n this._options.thumbnails.placeholders.waitUntilResponse ||\n !qq.supportedFeatures.imagePreviews)) {\n\n // This will replace the \"waiting\" placeholder with a \"preview not available\" placeholder\n // if called with a null thumbnailUrl.\n this._templating.updateThumbnail(fileId, thumbnailUrl, this._options.thumbnails.customResizer);\n }\n },\n\n _addCannedFile: function(sessionData) {\n var id = this._parent.prototype._addCannedFile.apply(this, arguments);\n\n this._addToList(id, this.getName(id), true);\n this._templating.hideSpinner(id);\n this._templating.hideCancel(id);\n this._markFileAsSuccessful(id);\n\n return id;\n },\n\n _setSize: function(id, newSize) {\n this._parent.prototype._setSize.apply(this, arguments);\n\n this._templating.updateSize(id, this._formatSize(newSize));\n },\n\n _sessionRequestComplete: function() {\n this._templating.addCacheToDom();\n this._parent.prototype._sessionRequestComplete.apply(this, arguments);\n }\n };\n}());\n","/*globals qq */\n/**\n * This defines FineUploader mode, which is a default UI w/ drag & drop uploading.\n */\nqq.FineUploader = function(o, namespace) {\n \"use strict\";\n\n var self = this;\n\n // By default this should inherit instance data from FineUploaderBasic, but this can be overridden\n // if the (internal) caller defines a different parent. The parent is also used by\n // the private and public API functions that need to delegate to a parent function.\n this._parent = namespace ? qq[namespace].FineUploaderBasic : qq.FineUploaderBasic;\n this._parent.apply(this, arguments);\n\n // Options provided by FineUploader mode\n qq.extend(this._options, {\n element: null,\n\n button: null,\n\n listElement: null,\n\n dragAndDrop: {\n extraDropzones: [],\n reportDirectoryPaths: false\n },\n\n text: {\n formatProgress: \"{percent}% of {total_size}\",\n failUpload: \"Upload failed\",\n waitingForResponse: \"Processing...\",\n paused: \"Paused\"\n },\n\n template: \"qq-template\",\n\n classes: {\n retrying: \"qq-upload-retrying\",\n retryable: \"qq-upload-retryable\",\n success: \"qq-upload-success\",\n fail: \"qq-upload-fail\",\n editable: \"qq-editable\",\n hide: \"qq-hide\",\n dropActive: \"qq-upload-drop-area-active\"\n },\n\n failedUploadTextDisplay: {\n mode: \"default\", //default, custom, or none\n responseProperty: \"error\",\n enableTooltip: true\n },\n\n messages: {\n tooManyFilesError: \"You may only drop one file\",\n unsupportedBrowser: \"Unrecoverable error - this browser does not permit file uploading of any kind.\"\n },\n\n retry: {\n showAutoRetryNote: true,\n autoRetryNote: \"Retrying {retryNum}/{maxAuto}...\"\n },\n\n deleteFile: {\n forceConfirm: false,\n confirmMessage: \"Are you sure you want to delete {filename}?\",\n deletingStatusText: \"Deleting...\",\n deletingFailedText: \"Delete failed\"\n\n },\n\n display: {\n fileSizeOnSubmit: false,\n prependFiles: false\n },\n\n paste: {\n promptForName: false,\n namePromptMessage: \"Please name this image\"\n },\n\n thumbnails: {\n customResizer: null,\n maxCount: 0,\n placeholders: {\n waitUntilResponse: false,\n notAvailablePath: null,\n waitingPath: null\n },\n timeBetweenThumbs: 750\n },\n\n scaling: {\n hideScaled: false\n },\n\n showMessage: function(message) {\n if (self._templating.hasDialog(\"alert\")) {\n return self._templating.showDialog(\"alert\", message);\n }\n else {\n setTimeout(function() {\n window.alert(message);\n }, 0);\n }\n },\n\n showConfirm: function(message) {\n if (self._templating.hasDialog(\"confirm\")) {\n return self._templating.showDialog(\"confirm\", message);\n }\n else {\n return window.confirm(message);\n }\n },\n\n showPrompt: function(message, defaultValue) {\n if (self._templating.hasDialog(\"prompt\")) {\n return self._templating.showDialog(\"prompt\", message, defaultValue);\n }\n else {\n return window.prompt(message, defaultValue);\n }\n }\n }, true);\n\n // Replace any default options with user defined ones\n qq.extend(this._options, o, true);\n\n this._templating = new qq.Templating({\n log: qq.bind(this.log, this),\n templateIdOrEl: this._options.template,\n containerEl: this._options.element,\n fileContainerEl: this._options.listElement,\n button: this._options.button,\n imageGenerator: this._imageGenerator,\n classes: {\n hide: this._options.classes.hide,\n editable: this._options.classes.editable\n },\n limits: {\n maxThumbs: this._options.thumbnails.maxCount,\n timeBetweenThumbs: this._options.thumbnails.timeBetweenThumbs\n },\n placeholders: {\n waitUntilUpdate: this._options.thumbnails.placeholders.waitUntilResponse,\n thumbnailNotAvailable: this._options.thumbnails.placeholders.notAvailablePath,\n waitingForThumbnail: this._options.thumbnails.placeholders.waitingPath\n },\n text: this._options.text\n });\n\n if (this._options.workarounds.ios8SafariUploads && qq.ios800() && qq.iosSafari()) {\n this._templating.renderFailure(this._options.messages.unsupportedBrowserIos8Safari);\n }\n else if (!qq.supportedFeatures.uploading || (this._options.cors.expected && !qq.supportedFeatures.uploadCors)) {\n this._templating.renderFailure(this._options.messages.unsupportedBrowser);\n }\n else {\n this._wrapCallbacks();\n\n this._templating.render();\n\n this._classes = this._options.classes;\n\n if (!this._options.button && this._templating.getButton()) {\n this._defaultButtonId = this._createUploadButton({\n element: this._templating.getButton(),\n title: this._options.text.fileInputTitle\n }).getButtonId();\n }\n\n this._setupClickAndEditEventHandlers();\n\n if (qq.DragAndDrop && qq.supportedFeatures.fileDrop) {\n this._dnd = this._setupDragAndDrop();\n }\n\n if (this._options.paste.targetElement && this._options.paste.promptForName) {\n if (qq.PasteSupport) {\n this._setupPastePrompt();\n }\n else {\n this.log(\"Paste support module not found.\", \"error\");\n }\n }\n\n this._totalFilesInBatch = 0;\n this._filesInBatchAddedToUi = 0;\n }\n};\n\n// Inherit the base public & private API methods\nqq.extend(qq.FineUploader.prototype, qq.basePublicApi);\nqq.extend(qq.FineUploader.prototype, qq.basePrivateApi);\n\n// Add the FineUploader/default UI public & private UI methods, which may override some base methods.\nqq.extend(qq.FineUploader.prototype, qq.uiPublicApi);\nqq.extend(qq.FineUploader.prototype, qq.uiPrivateApi);\n","/* globals qq */\n/* jshint -W065 */\n/**\n * Module responsible for rendering all Fine Uploader UI templates. This module also asserts at least\n * a limited amount of control over the template elements after they are added to the DOM.\n * Wherever possible, this module asserts total control over template elements present in the DOM.\n *\n * @param spec Specification object used to control various templating behaviors\n * @constructor\n */\nqq.Templating = function(spec) {\n \"use strict\";\n\n var FILE_ID_ATTR = \"qq-file-id\",\n FILE_CLASS_PREFIX = \"qq-file-id-\",\n THUMBNAIL_MAX_SIZE_ATTR = \"qq-max-size\",\n THUMBNAIL_SERVER_SCALE_ATTR = \"qq-server-scale\",\n // This variable is duplicated in the DnD module since it can function as a standalone as well\n HIDE_DROPZONE_ATTR = \"qq-hide-dropzone\",\n DROPZPONE_TEXT_ATTR = \"qq-drop-area-text\",\n IN_PROGRESS_CLASS = \"qq-in-progress\",\n HIDDEN_FOREVER_CLASS = \"qq-hidden-forever\",\n fileBatch = {\n content: document.createDocumentFragment(),\n map: {}\n },\n isCancelDisabled = false,\n generatedThumbnails = 0,\n thumbnailQueueMonitorRunning = false,\n thumbGenerationQueue = [],\n thumbnailMaxSize = -1,\n options = {\n log: null,\n limits: {\n maxThumbs: 0,\n timeBetweenThumbs: 750\n },\n templateIdOrEl: \"qq-template\",\n containerEl: null,\n fileContainerEl: null,\n button: null,\n imageGenerator: null,\n classes: {\n hide: \"qq-hide\",\n editable: \"qq-editable\"\n },\n placeholders: {\n waitUntilUpdate: false,\n thumbnailNotAvailable: null,\n waitingForThumbnail: null\n },\n text: {\n paused: \"Paused\"\n }\n },\n selectorClasses = {\n button: \"qq-upload-button-selector\",\n alertDialog: \"qq-alert-dialog-selector\",\n dialogCancelButton: \"qq-cancel-button-selector\",\n confirmDialog: \"qq-confirm-dialog-selector\",\n dialogMessage: \"qq-dialog-message-selector\",\n dialogOkButton: \"qq-ok-button-selector\",\n promptDialog: \"qq-prompt-dialog-selector\",\n uploader: \"qq-uploader-selector\",\n drop: \"qq-upload-drop-area-selector\",\n list: \"qq-upload-list-selector\",\n progressBarContainer: \"qq-progress-bar-container-selector\",\n progressBar: \"qq-progress-bar-selector\",\n totalProgressBarContainer: \"qq-total-progress-bar-container-selector\",\n totalProgressBar: \"qq-total-progress-bar-selector\",\n file: \"qq-upload-file-selector\",\n spinner: \"qq-upload-spinner-selector\",\n size: \"qq-upload-size-selector\",\n cancel: \"qq-upload-cancel-selector\",\n pause: \"qq-upload-pause-selector\",\n continueButton: \"qq-upload-continue-selector\",\n deleteButton: \"qq-upload-delete-selector\",\n retry: \"qq-upload-retry-selector\",\n statusText: \"qq-upload-status-text-selector\",\n editFilenameInput: \"qq-edit-filename-selector\",\n editNameIcon: \"qq-edit-filename-icon-selector\",\n dropText: \"qq-upload-drop-area-text-selector\",\n dropProcessing: \"qq-drop-processing-selector\",\n dropProcessingSpinner: \"qq-drop-processing-spinner-selector\",\n thumbnail: \"qq-thumbnail-selector\"\n },\n previewGeneration = {},\n cachedThumbnailNotAvailableImg = new qq.Promise(),\n cachedWaitingForThumbnailImg = new qq.Promise(),\n log,\n isEditElementsExist,\n isRetryElementExist,\n templateDom,\n container,\n fileList,\n showThumbnails,\n serverScale,\n\n // During initialization of the templating module we should cache any\n // placeholder images so we can quickly swap them into the file list on demand.\n // Any placeholder images that cannot be loaded/found are simply ignored.\n cacheThumbnailPlaceholders = function() {\n var notAvailableUrl = options.placeholders.thumbnailNotAvailable,\n waitingUrl = options.placeholders.waitingForThumbnail,\n spec = {\n maxSize: thumbnailMaxSize,\n scale: serverScale\n };\n\n if (showThumbnails) {\n if (notAvailableUrl) {\n options.imageGenerator.generate(notAvailableUrl, new Image(), spec).then(\n function(updatedImg) {\n cachedThumbnailNotAvailableImg.success(updatedImg);\n },\n function() {\n cachedThumbnailNotAvailableImg.failure();\n log(\"Problem loading 'not available' placeholder image at \" + notAvailableUrl, \"error\");\n }\n );\n }\n else {\n cachedThumbnailNotAvailableImg.failure();\n }\n\n if (waitingUrl) {\n options.imageGenerator.generate(waitingUrl, new Image(), spec).then(\n function(updatedImg) {\n cachedWaitingForThumbnailImg.success(updatedImg);\n },\n function() {\n cachedWaitingForThumbnailImg.failure();\n log(\"Problem loading 'waiting for thumbnail' placeholder image at \" + waitingUrl, \"error\");\n }\n );\n }\n else {\n cachedWaitingForThumbnailImg.failure();\n }\n }\n },\n\n // Displays a \"waiting for thumbnail\" type placeholder image\n // iff we were able to load it during initialization of the templating module.\n displayWaitingImg = function(thumbnail) {\n var waitingImgPlacement = new qq.Promise();\n\n cachedWaitingForThumbnailImg.then(function(img) {\n maybeScalePlaceholderViaCss(img, thumbnail);\n /* jshint eqnull:true */\n if (!thumbnail.src) {\n thumbnail.src = img.src;\n thumbnail.onload = function() {\n thumbnail.onload = null;\n show(thumbnail);\n waitingImgPlacement.success();\n };\n }\n else {\n waitingImgPlacement.success();\n }\n }, function() {\n // In some browsers (such as IE9 and older) an img w/out a src attribute\n // are displayed as \"broken\" images, so we should just hide the img tag\n // if we aren't going to display the \"waiting\" placeholder.\n hide(thumbnail);\n waitingImgPlacement.success();\n });\n\n return waitingImgPlacement;\n },\n\n generateNewPreview = function(id, blob, spec) {\n var thumbnail = getThumbnail(id);\n\n log(\"Generating new thumbnail for \" + id);\n blob.qqThumbnailId = id;\n\n return options.imageGenerator.generate(blob, thumbnail, spec).then(\n function() {\n generatedThumbnails++;\n show(thumbnail);\n previewGeneration[id].success();\n },\n function() {\n previewGeneration[id].failure();\n\n // Display the \"not available\" placeholder img only if we are\n // not expecting a thumbnail at a later point, such as in a server response.\n if (!options.placeholders.waitUntilUpdate) {\n maybeSetDisplayNotAvailableImg(id, thumbnail);\n }\n });\n },\n\n generateNextQueuedPreview = function() {\n if (thumbGenerationQueue.length) {\n thumbnailQueueMonitorRunning = true;\n\n var queuedThumbRequest = thumbGenerationQueue.shift();\n\n if (queuedThumbRequest.update) {\n processUpdateQueuedPreviewRequest(queuedThumbRequest);\n }\n else {\n processNewQueuedPreviewRequest(queuedThumbRequest);\n }\n }\n else {\n thumbnailQueueMonitorRunning = false;\n }\n },\n\n getCancel = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.cancel);\n },\n\n getContinue = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.continueButton);\n },\n\n getDialog = function(type) {\n return getTemplateEl(container, selectorClasses[type + \"Dialog\"]);\n },\n\n getDelete = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.deleteButton);\n },\n\n getDropProcessing = function() {\n return getTemplateEl(container, selectorClasses.dropProcessing);\n },\n\n getEditIcon = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.editNameIcon);\n },\n\n getFile = function(id) {\n return fileBatch.map[id] || qq(fileList).getFirstByClass(FILE_CLASS_PREFIX + id);\n },\n\n getFilename = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.file);\n },\n\n getPause = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.pause);\n },\n\n getProgress = function(id) {\n /* jshint eqnull:true */\n // Total progress bar\n if (id == null) {\n return getTemplateEl(container, selectorClasses.totalProgressBarContainer) ||\n getTemplateEl(container, selectorClasses.totalProgressBar);\n }\n\n // Per-file progress bar\n return getTemplateEl(getFile(id), selectorClasses.progressBarContainer) ||\n getTemplateEl(getFile(id), selectorClasses.progressBar);\n },\n\n getRetry = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.retry);\n },\n\n getSize = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.size);\n },\n\n getSpinner = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.spinner);\n },\n\n getTemplateEl = function(context, cssClass) {\n return context && qq(context).getFirstByClass(cssClass);\n },\n\n getThumbnail = function(id) {\n return showThumbnails && getTemplateEl(getFile(id), selectorClasses.thumbnail);\n },\n\n hide = function(el) {\n el && qq(el).addClass(options.classes.hide);\n },\n\n // Ensures a placeholder image does not exceed any max size specified\n // via `style` attribute properties iff was not used to scale\n // the placeholder AND the target doesn't already have these `style` attribute properties set.\n maybeScalePlaceholderViaCss = function(placeholder, thumbnail) {\n var maxWidth = placeholder.style.maxWidth,\n maxHeight = placeholder.style.maxHeight;\n\n if (maxHeight && maxWidth && !thumbnail.style.maxWidth && !thumbnail.style.maxHeight) {\n qq(thumbnail).css({\n maxWidth: maxWidth,\n maxHeight: maxHeight\n });\n }\n },\n\n // Displays a \"thumbnail not available\" type placeholder image\n // iff we were able to load this placeholder during initialization\n // of the templating module or after preview generation has failed.\n maybeSetDisplayNotAvailableImg = function(id, thumbnail) {\n var previewing = previewGeneration[id] || new qq.Promise().failure(),\n notAvailableImgPlacement = new qq.Promise();\n\n cachedThumbnailNotAvailableImg.then(function(img) {\n previewing.then(\n function() {\n notAvailableImgPlacement.success();\n },\n function() {\n maybeScalePlaceholderViaCss(img, thumbnail);\n\n thumbnail.onload = function() {\n thumbnail.onload = null;\n notAvailableImgPlacement.success();\n };\n\n thumbnail.src = img.src;\n show(thumbnail);\n }\n );\n });\n\n return notAvailableImgPlacement;\n },\n\n /**\n * Grabs the HTML from the script tag holding the template markup. This function will also adjust\n * some internally-tracked state variables based on the contents of the template.\n * The template is filtered so that irrelevant elements (such as the drop zone if DnD is not supported)\n * are omitted from the DOM. Useful errors will be thrown if the template cannot be parsed.\n *\n * @returns {{template: *, fileTemplate: *}} HTML for the top-level file items templates\n */\n parseAndGetTemplate = function() {\n var scriptEl,\n scriptHtml,\n fileListNode,\n tempTemplateEl,\n fileListEl,\n defaultButton,\n dropArea,\n thumbnail,\n dropProcessing,\n dropTextEl,\n uploaderEl;\n\n log(\"Parsing template\");\n\n /*jshint -W116*/\n if (options.templateIdOrEl == null) {\n throw new Error(\"You MUST specify either a template element or ID!\");\n }\n\n // Grab the contents of the script tag holding the template.\n if (qq.isString(options.templateIdOrEl)) {\n scriptEl = document.getElementById(options.templateIdOrEl);\n\n if (scriptEl === null) {\n throw new Error(qq.format(\"Cannot find template script at ID '{}'!\", options.templateIdOrEl));\n }\n\n scriptHtml = scriptEl.innerHTML;\n }\n else {\n if (options.templateIdOrEl.innerHTML === undefined) {\n throw new Error(\"You have specified an invalid value for the template option! \" +\n \"It must be an ID or an Element.\");\n }\n\n scriptHtml = options.templateIdOrEl.innerHTML;\n }\n\n scriptHtml = qq.trimStr(scriptHtml);\n tempTemplateEl = document.createElement(\"div\");\n tempTemplateEl.appendChild(qq.toElement(scriptHtml));\n uploaderEl = qq(tempTemplateEl).getFirstByClass(selectorClasses.uploader);\n\n // Don't include the default template button in the DOM\n // if an alternate button container has been specified.\n if (options.button) {\n defaultButton = qq(tempTemplateEl).getFirstByClass(selectorClasses.button);\n if (defaultButton) {\n qq(defaultButton).remove();\n }\n }\n\n // Omit the drop processing element from the DOM if DnD is not supported by the UA,\n // or the drag and drop module is not found.\n // NOTE: We are consciously not removing the drop zone if the UA doesn't support DnD\n // to support layouts where the drop zone is also a container for visible elements,\n // such as the file list.\n if (!qq.DragAndDrop || !qq.supportedFeatures.fileDrop) {\n dropProcessing = qq(tempTemplateEl).getFirstByClass(selectorClasses.dropProcessing);\n if (dropProcessing) {\n qq(dropProcessing).remove();\n }\n }\n\n dropArea = qq(tempTemplateEl).getFirstByClass(selectorClasses.drop);\n\n // If DnD is not available then remove\n // it from the DOM as well.\n if (dropArea && !qq.DragAndDrop) {\n log(\"DnD module unavailable.\", \"info\");\n qq(dropArea).remove();\n }\n\n if (!qq.supportedFeatures.fileDrop) {\n // don't display any \"drop files to upload\" background text\n uploaderEl.removeAttribute(DROPZPONE_TEXT_ATTR);\n\n if (dropArea && qq(dropArea).hasAttribute(HIDE_DROPZONE_ATTR)) {\n // If there is a drop area defined in the template, and the current UA doesn't support DnD,\n // and the drop area is marked as \"hide before enter\", ensure it is hidden as the DnD module\n // will not do this (since we will not be loading the DnD module)\n qq(dropArea).css({\n display: \"none\"\n });\n }\n }\n else if (qq(uploaderEl).hasAttribute(DROPZPONE_TEXT_ATTR) && dropArea) {\n dropTextEl = qq(dropArea).getFirstByClass(selectorClasses.dropText);\n dropTextEl && qq(dropTextEl).remove();\n }\n\n // Ensure the `showThumbnails` flag is only set if the thumbnail element\n // is present in the template AND the current UA is capable of generating client-side previews.\n thumbnail = qq(tempTemplateEl).getFirstByClass(selectorClasses.thumbnail);\n if (!showThumbnails) {\n thumbnail && qq(thumbnail).remove();\n }\n else if (thumbnail) {\n thumbnailMaxSize = parseInt(thumbnail.getAttribute(THUMBNAIL_MAX_SIZE_ATTR));\n // Only enforce max size if the attr value is non-zero\n thumbnailMaxSize = thumbnailMaxSize > 0 ? thumbnailMaxSize : null;\n\n serverScale = qq(thumbnail).hasAttribute(THUMBNAIL_SERVER_SCALE_ATTR);\n }\n showThumbnails = showThumbnails && thumbnail;\n\n isEditElementsExist = qq(tempTemplateEl).getByClass(selectorClasses.editFilenameInput).length > 0;\n isRetryElementExist = qq(tempTemplateEl).getByClass(selectorClasses.retry).length > 0;\n\n fileListNode = qq(tempTemplateEl).getFirstByClass(selectorClasses.list);\n /*jshint -W116*/\n if (fileListNode == null) {\n throw new Error(\"Could not find the file list container in the template!\");\n }\n\n fileListEl = fileListNode.children[0].cloneNode(true);\n fileListNode.innerHTML = \"\";\n\n // We must call `createElement` in IE8 in order to target and hide any via CSS\n if (tempTemplateEl.getElementsByTagName(\"DIALOG\").length) {\n document.createElement(\"dialog\");\n }\n\n log(\"Template parsing complete\");\n\n return {\n template: tempTemplateEl,\n fileTemplate: fileListEl\n };\n },\n\n prependFile = function(el, index, fileList) {\n var parentEl = fileList,\n beforeEl = parentEl.firstChild;\n\n if (index > 0) {\n beforeEl = qq(parentEl).children()[index].nextSibling;\n\n }\n\n parentEl.insertBefore(el, beforeEl);\n },\n\n processNewQueuedPreviewRequest = function(queuedThumbRequest) {\n var id = queuedThumbRequest.id,\n optFileOrBlob = queuedThumbRequest.optFileOrBlob,\n relatedThumbnailId = optFileOrBlob && optFileOrBlob.qqThumbnailId,\n thumbnail = getThumbnail(id),\n spec = {\n customResizeFunction: queuedThumbRequest.customResizeFunction,\n maxSize: thumbnailMaxSize,\n orient: true,\n scale: true\n };\n\n if (qq.supportedFeatures.imagePreviews) {\n if (thumbnail) {\n if (options.limits.maxThumbs && options.limits.maxThumbs <= generatedThumbnails) {\n maybeSetDisplayNotAvailableImg(id, thumbnail);\n generateNextQueuedPreview();\n }\n else {\n displayWaitingImg(thumbnail).done(function() {\n previewGeneration[id] = new qq.Promise();\n\n previewGeneration[id].done(function() {\n setTimeout(generateNextQueuedPreview, options.limits.timeBetweenThumbs);\n });\n\n /* jshint eqnull: true */\n // If we've already generated an for this file, use the one that exists,\n // don't waste resources generating a new one.\n if (relatedThumbnailId != null) {\n useCachedPreview(id, relatedThumbnailId);\n }\n else {\n generateNewPreview(id, optFileOrBlob, spec);\n }\n });\n }\n }\n // File element in template may have been removed, so move on to next item in queue\n else {\n generateNextQueuedPreview();\n }\n }\n else if (thumbnail) {\n displayWaitingImg(thumbnail);\n generateNextQueuedPreview();\n }\n },\n\n processUpdateQueuedPreviewRequest = function(queuedThumbRequest) {\n var id = queuedThumbRequest.id,\n thumbnailUrl = queuedThumbRequest.thumbnailUrl,\n showWaitingImg = queuedThumbRequest.showWaitingImg,\n thumbnail = getThumbnail(id),\n spec = {\n customResizeFunction: queuedThumbRequest.customResizeFunction,\n scale: serverScale,\n maxSize: thumbnailMaxSize\n };\n\n if (thumbnail) {\n if (thumbnailUrl) {\n if (options.limits.maxThumbs && options.limits.maxThumbs <= generatedThumbnails) {\n maybeSetDisplayNotAvailableImg(id, thumbnail);\n generateNextQueuedPreview();\n }\n else {\n if (showWaitingImg) {\n displayWaitingImg(thumbnail);\n }\n\n return options.imageGenerator.generate(thumbnailUrl, thumbnail, spec).then(\n function() {\n show(thumbnail);\n generatedThumbnails++;\n setTimeout(generateNextQueuedPreview, options.limits.timeBetweenThumbs);\n },\n\n function() {\n maybeSetDisplayNotAvailableImg(id, thumbnail);\n setTimeout(generateNextQueuedPreview, options.limits.timeBetweenThumbs);\n }\n );\n }\n }\n else {\n maybeSetDisplayNotAvailableImg(id, thumbnail);\n generateNextQueuedPreview();\n }\n }\n },\n\n setProgressBarWidth = function(id, percent) {\n var bar = getProgress(id),\n /* jshint eqnull:true */\n progressBarSelector = id == null ? selectorClasses.totalProgressBar : selectorClasses.progressBar;\n\n if (bar && !qq(bar).hasClass(progressBarSelector)) {\n bar = qq(bar).getFirstByClass(progressBarSelector);\n }\n\n if (bar) {\n qq(bar).css({width: percent + \"%\"});\n bar.setAttribute(\"aria-valuenow\", percent);\n }\n },\n\n show = function(el) {\n el && qq(el).removeClass(options.classes.hide);\n },\n\n useCachedPreview = function(targetThumbnailId, cachedThumbnailId) {\n var targetThumbnail = getThumbnail(targetThumbnailId),\n cachedThumbnail = getThumbnail(cachedThumbnailId);\n\n log(qq.format(\"ID {} is the same file as ID {}. Will use generated thumbnail from ID {} instead.\", targetThumbnailId, cachedThumbnailId, cachedThumbnailId));\n\n // Generation of the related thumbnail may still be in progress, so, wait until it is done.\n previewGeneration[cachedThumbnailId].then(function() {\n generatedThumbnails++;\n previewGeneration[targetThumbnailId].success();\n log(qq.format(\"Now using previously generated thumbnail created for ID {} on ID {}.\", cachedThumbnailId, targetThumbnailId));\n targetThumbnail.src = cachedThumbnail.src;\n show(targetThumbnail);\n },\n function() {\n previewGeneration[targetThumbnailId].failure();\n if (!options.placeholders.waitUntilUpdate) {\n maybeSetDisplayNotAvailableImg(targetThumbnailId, targetThumbnail);\n }\n });\n };\n\n qq.extend(options, spec);\n log = options.log;\n\n // No need to worry about conserving CPU or memory on older browsers,\n // since there is no ability to preview, and thumbnail display is primitive and quick.\n if (!qq.supportedFeatures.imagePreviews) {\n options.limits.timeBetweenThumbs = 0;\n options.limits.maxThumbs = 0;\n }\n\n container = options.containerEl;\n showThumbnails = options.imageGenerator !== undefined;\n templateDom = parseAndGetTemplate();\n\n cacheThumbnailPlaceholders();\n\n qq.extend(this, {\n render: function() {\n log(\"Rendering template in DOM.\");\n\n generatedThumbnails = 0;\n\n container.appendChild(templateDom.template.cloneNode(true));\n hide(getDropProcessing());\n this.hideTotalProgress();\n fileList = options.fileContainerEl || getTemplateEl(container, selectorClasses.list);\n\n log(\"Template rendering complete\");\n },\n\n renderFailure: function(message) {\n var cantRenderEl = qq.toElement(message);\n container.innerHTML = \"\";\n container.appendChild(cantRenderEl);\n },\n\n reset: function() {\n container.innerHTML = \"\";\n this.render();\n },\n\n clearFiles: function() {\n fileList.innerHTML = \"\";\n },\n\n disableCancel: function() {\n isCancelDisabled = true;\n },\n\n addFile: function(id, name, prependInfo, hideForever, batch) {\n var fileEl = templateDom.fileTemplate.cloneNode(true),\n fileNameEl = getTemplateEl(fileEl, selectorClasses.file),\n uploaderEl = getTemplateEl(container, selectorClasses.uploader),\n fileContainer = batch ? fileBatch.content : fileList,\n thumb;\n\n if (batch) {\n fileBatch.map[id] = fileEl;\n }\n\n qq(fileEl).addClass(FILE_CLASS_PREFIX + id);\n uploaderEl.removeAttribute(DROPZPONE_TEXT_ATTR);\n\n if (fileNameEl) {\n qq(fileNameEl).setText(name);\n fileNameEl.setAttribute(\"title\", name);\n }\n\n fileEl.setAttribute(FILE_ID_ATTR, id);\n\n if (prependInfo) {\n prependFile(fileEl, prependInfo.index, fileContainer);\n }\n else {\n fileContainer.appendChild(fileEl);\n }\n\n if (hideForever) {\n fileEl.style.display = \"none\";\n qq(fileEl).addClass(HIDDEN_FOREVER_CLASS);\n }\n else {\n hide(getProgress(id));\n hide(getSize(id));\n hide(getDelete(id));\n hide(getRetry(id));\n hide(getPause(id));\n hide(getContinue(id));\n\n if (isCancelDisabled) {\n this.hideCancel(id);\n }\n\n thumb = getThumbnail(id);\n if (thumb && !thumb.src) {\n cachedWaitingForThumbnailImg.then(function(waitingImg) {\n thumb.src = waitingImg.src;\n if (waitingImg.style.maxHeight && waitingImg.style.maxWidth) {\n qq(thumb).css({\n maxHeight: waitingImg.style.maxHeight,\n maxWidth: waitingImg.style.maxWidth\n });\n }\n\n show(thumb);\n });\n }\n }\n },\n\n addFileToCache: function(id, name, prependInfo, hideForever) {\n this.addFile(id, name, prependInfo, hideForever, true);\n },\n\n addCacheToDom: function() {\n fileList.appendChild(fileBatch.content);\n fileBatch.content = document.createDocumentFragment();\n fileBatch.map = {};\n },\n\n removeFile: function(id) {\n qq(getFile(id)).remove();\n },\n\n getFileId: function(el) {\n var currentNode = el;\n\n if (currentNode) {\n /*jshint -W116*/\n while (currentNode.getAttribute(FILE_ID_ATTR) == null) {\n currentNode = currentNode.parentNode;\n }\n\n return parseInt(currentNode.getAttribute(FILE_ID_ATTR));\n }\n },\n\n getFileList: function() {\n return fileList;\n },\n\n markFilenameEditable: function(id) {\n var filename = getFilename(id);\n\n filename && qq(filename).addClass(options.classes.editable);\n },\n\n updateFilename: function(id, name) {\n var filenameEl = getFilename(id);\n\n if (filenameEl) {\n qq(filenameEl).setText(name);\n filenameEl.setAttribute(\"title\", name);\n }\n },\n\n hideFilename: function(id) {\n hide(getFilename(id));\n },\n\n showFilename: function(id) {\n show(getFilename(id));\n },\n\n isFileName: function(el) {\n return qq(el).hasClass(selectorClasses.file);\n },\n\n getButton: function() {\n return options.button || getTemplateEl(container, selectorClasses.button);\n },\n\n hideDropProcessing: function() {\n hide(getDropProcessing());\n },\n\n showDropProcessing: function() {\n show(getDropProcessing());\n },\n\n getDropZone: function() {\n return getTemplateEl(container, selectorClasses.drop);\n },\n\n isEditFilenamePossible: function() {\n return isEditElementsExist;\n },\n\n hideRetry: function(id) {\n hide(getRetry(id));\n },\n\n isRetryPossible: function() {\n return isRetryElementExist;\n },\n\n showRetry: function(id) {\n show(getRetry(id));\n },\n\n getFileContainer: function(id) {\n return getFile(id);\n },\n\n showEditIcon: function(id) {\n var icon = getEditIcon(id);\n\n icon && qq(icon).addClass(options.classes.editable);\n },\n\n isHiddenForever: function(id) {\n return qq(getFile(id)).hasClass(HIDDEN_FOREVER_CLASS);\n },\n\n hideEditIcon: function(id) {\n var icon = getEditIcon(id);\n\n icon && qq(icon).removeClass(options.classes.editable);\n },\n\n isEditIcon: function(el) {\n return qq(el).hasClass(selectorClasses.editNameIcon, true);\n },\n\n getEditInput: function(id) {\n return getTemplateEl(getFile(id), selectorClasses.editFilenameInput);\n },\n\n isEditInput: function(el) {\n return qq(el).hasClass(selectorClasses.editFilenameInput, true);\n },\n\n updateProgress: function(id, loaded, total) {\n var bar = getProgress(id),\n percent;\n\n if (bar && total > 0) {\n percent = Math.round(loaded / total * 100);\n\n if (percent === 100) {\n hide(bar);\n }\n else {\n show(bar);\n }\n\n setProgressBarWidth(id, percent);\n }\n },\n\n updateTotalProgress: function(loaded, total) {\n this.updateProgress(null, loaded, total);\n },\n\n hideProgress: function(id) {\n var bar = getProgress(id);\n\n bar && hide(bar);\n },\n\n hideTotalProgress: function() {\n this.hideProgress();\n },\n\n resetProgress: function(id) {\n setProgressBarWidth(id, 0);\n this.hideTotalProgress(id);\n },\n\n resetTotalProgress: function() {\n this.resetProgress();\n },\n\n showCancel: function(id) {\n if (!isCancelDisabled) {\n var cancel = getCancel(id);\n\n cancel && qq(cancel).removeClass(options.classes.hide);\n }\n },\n\n hideCancel: function(id) {\n hide(getCancel(id));\n },\n\n isCancel: function(el) {\n return qq(el).hasClass(selectorClasses.cancel, true);\n },\n\n allowPause: function(id) {\n show(getPause(id));\n hide(getContinue(id));\n },\n\n uploadPaused: function(id) {\n this.setStatusText(id, options.text.paused);\n this.allowContinueButton(id);\n hide(getSpinner(id));\n },\n\n hidePause: function(id) {\n hide(getPause(id));\n },\n\n isPause: function(el) {\n return qq(el).hasClass(selectorClasses.pause, true);\n },\n\n isContinueButton: function(el) {\n return qq(el).hasClass(selectorClasses.continueButton, true);\n },\n\n allowContinueButton: function(id) {\n show(getContinue(id));\n hide(getPause(id));\n },\n\n uploadContinued: function(id) {\n this.setStatusText(id, \"\");\n this.allowPause(id);\n show(getSpinner(id));\n },\n\n showDeleteButton: function(id) {\n show(getDelete(id));\n },\n\n hideDeleteButton: function(id) {\n hide(getDelete(id));\n },\n\n isDeleteButton: function(el) {\n return qq(el).hasClass(selectorClasses.deleteButton, true);\n },\n\n isRetry: function(el) {\n return qq(el).hasClass(selectorClasses.retry, true);\n },\n\n updateSize: function(id, text) {\n var size = getSize(id);\n\n if (size) {\n show(size);\n qq(size).setText(text);\n }\n },\n\n setStatusText: function(id, text) {\n var textEl = getTemplateEl(getFile(id), selectorClasses.statusText);\n\n if (textEl) {\n /*jshint -W116*/\n if (text == null) {\n qq(textEl).clearText();\n }\n else {\n qq(textEl).setText(text);\n }\n }\n },\n\n hideSpinner: function(id) {\n qq(getFile(id)).removeClass(IN_PROGRESS_CLASS);\n hide(getSpinner(id));\n },\n\n showSpinner: function(id) {\n qq(getFile(id)).addClass(IN_PROGRESS_CLASS);\n show(getSpinner(id));\n },\n\n generatePreview: function(id, optFileOrBlob, customResizeFunction) {\n if (!this.isHiddenForever(id)) {\n thumbGenerationQueue.push({id: id, customResizeFunction: customResizeFunction, optFileOrBlob: optFileOrBlob});\n !thumbnailQueueMonitorRunning && generateNextQueuedPreview();\n }\n },\n\n updateThumbnail: function(id, thumbnailUrl, showWaitingImg, customResizeFunction) {\n if (!this.isHiddenForever(id)) {\n thumbGenerationQueue.push({customResizeFunction: customResizeFunction, update: true, id: id, thumbnailUrl: thumbnailUrl, showWaitingImg: showWaitingImg});\n !thumbnailQueueMonitorRunning && generateNextQueuedPreview();\n }\n },\n\n hasDialog: function(type) {\n return qq.supportedFeatures.dialogElement && !!getDialog(type);\n },\n\n showDialog: function(type, message, defaultValue) {\n var dialog = getDialog(type),\n messageEl = getTemplateEl(dialog, selectorClasses.dialogMessage),\n inputEl = dialog.getElementsByTagName(\"INPUT\")[0],\n cancelBtn = getTemplateEl(dialog, selectorClasses.dialogCancelButton),\n okBtn = getTemplateEl(dialog, selectorClasses.dialogOkButton),\n promise = new qq.Promise(),\n\n closeHandler = function() {\n cancelBtn.removeEventListener(\"click\", cancelClickHandler);\n okBtn && okBtn.removeEventListener(\"click\", okClickHandler);\n promise.failure();\n },\n\n cancelClickHandler = function() {\n cancelBtn.removeEventListener(\"click\", cancelClickHandler);\n dialog.close();\n },\n\n okClickHandler = function() {\n dialog.removeEventListener(\"close\", closeHandler);\n okBtn.removeEventListener(\"click\", okClickHandler);\n dialog.close();\n\n promise.success(inputEl && inputEl.value);\n };\n\n dialog.addEventListener(\"close\", closeHandler);\n cancelBtn.addEventListener(\"click\", cancelClickHandler);\n okBtn && okBtn.addEventListener(\"click\", okClickHandler);\n\n if (inputEl) {\n inputEl.value = defaultValue;\n }\n messageEl.textContent = message;\n\n dialog.showModal();\n\n return promise;\n }\n });\n};\n","/*globals qq */\n// Base handler for UI (FineUploader mode) events.\n// Some more specific handlers inherit from this one.\nqq.UiEventHandler = function(s, protectedApi) {\n \"use strict\";\n\n var disposer = new qq.DisposeSupport(),\n spec = {\n eventType: \"click\",\n attachTo: null,\n onHandled: function(target, event) {}\n };\n\n // This makes up the \"public\" API methods that will be accessible\n // to instances constructing a base or child handler\n qq.extend(this, {\n addHandler: function(element) {\n addHandler(element);\n },\n\n dispose: function() {\n disposer.dispose();\n }\n });\n\n function addHandler(element) {\n disposer.attach(element, spec.eventType, function(event) {\n // Only in IE: the `event` is a property of the `window`.\n event = event || window.event;\n\n // On older browsers, we must check the `srcElement` instead of the `target`.\n var target = event.target || event.srcElement;\n\n spec.onHandled(target, event);\n });\n }\n\n // These make up the \"protected\" API methods that children of this base handler will utilize.\n qq.extend(protectedApi, {\n getFileIdFromItem: function(item) {\n return item.qqFileId;\n },\n\n getDisposeSupport: function() {\n return disposer;\n }\n });\n\n qq.extend(spec, s);\n\n if (spec.attachTo) {\n addHandler(spec.attachTo);\n }\n};\n","/* global qq */\nqq.FileButtonsClickHandler = function(s) {\n \"use strict\";\n\n var inheritedInternalApi = {},\n spec = {\n templating: null,\n log: function(message, lvl) {},\n onDeleteFile: function(fileId) {},\n onCancel: function(fileId) {},\n onRetry: function(fileId) {},\n onPause: function(fileId) {},\n onContinue: function(fileId) {},\n onGetName: function(fileId) {}\n },\n buttonHandlers = {\n cancel: function(id) { spec.onCancel(id); },\n retry: function(id) { spec.onRetry(id); },\n deleteButton: function(id) { spec.onDeleteFile(id); },\n pause: function(id) { spec.onPause(id); },\n continueButton: function(id) { spec.onContinue(id); }\n };\n\n function examineEvent(target, event) {\n qq.each(buttonHandlers, function(buttonType, handler) {\n var firstLetterCapButtonType = buttonType.charAt(0).toUpperCase() + buttonType.slice(1),\n fileId;\n\n if (spec.templating[\"is\" + firstLetterCapButtonType](target)) {\n fileId = spec.templating.getFileId(target);\n qq.preventDefault(event);\n spec.log(qq.format(\"Detected valid file button click event on file '{}', ID: {}.\", spec.onGetName(fileId), fileId));\n handler(fileId);\n return false;\n }\n });\n }\n\n qq.extend(spec, s);\n\n spec.eventType = \"click\";\n spec.onHandled = examineEvent;\n spec.attachTo = spec.templating.getFileList();\n\n qq.extend(this, new qq.UiEventHandler(spec, inheritedInternalApi));\n};\n","/*globals qq */\n// Child of FilenameEditHandler. Used to detect click events on filename display elements.\nqq.FilenameClickHandler = function(s) {\n \"use strict\";\n\n var inheritedInternalApi = {},\n spec = {\n templating: null,\n log: function(message, lvl) {},\n classes: {\n file: \"qq-upload-file\",\n editNameIcon: \"qq-edit-filename-icon\"\n },\n onGetUploadStatus: function(fileId) {},\n onGetName: function(fileId) {}\n };\n\n qq.extend(spec, s);\n\n // This will be called by the parent handler when a `click` event is received on the list element.\n function examineEvent(target, event) {\n if (spec.templating.isFileName(target) || spec.templating.isEditIcon(target)) {\n var fileId = spec.templating.getFileId(target),\n status = spec.onGetUploadStatus(fileId);\n\n // We only allow users to change filenames of files that have been submitted but not yet uploaded.\n if (status === qq.status.SUBMITTED) {\n spec.log(qq.format(\"Detected valid filename click event on file '{}', ID: {}.\", spec.onGetName(fileId), fileId));\n qq.preventDefault(event);\n\n inheritedInternalApi.handleFilenameEdit(fileId, target, true);\n }\n }\n }\n\n spec.eventType = \"click\";\n spec.onHandled = examineEvent;\n\n qq.extend(this, new qq.FilenameEditHandler(spec, inheritedInternalApi));\n};\n","/*globals qq */\n// Child of FilenameEditHandler. Used to detect focusin events on file edit input elements.\nqq.FilenameInputFocusInHandler = function(s, inheritedInternalApi) {\n \"use strict\";\n\n var spec = {\n templating: null,\n onGetUploadStatus: function(fileId) {},\n log: function(message, lvl) {}\n };\n\n if (!inheritedInternalApi) {\n inheritedInternalApi = {};\n }\n\n // This will be called by the parent handler when a `focusin` event is received on the list element.\n function handleInputFocus(target, event) {\n if (spec.templating.isEditInput(target)) {\n var fileId = spec.templating.getFileId(target),\n status = spec.onGetUploadStatus(fileId);\n\n if (status === qq.status.SUBMITTED) {\n spec.log(qq.format(\"Detected valid filename input focus event on file '{}', ID: {}.\", spec.onGetName(fileId), fileId));\n inheritedInternalApi.handleFilenameEdit(fileId, target);\n }\n }\n }\n\n spec.eventType = \"focusin\";\n spec.onHandled = handleInputFocus;\n\n qq.extend(spec, s);\n qq.extend(this, new qq.FilenameEditHandler(spec, inheritedInternalApi));\n};\n","/*globals qq */\n/**\n * Child of FilenameInputFocusInHandler. Used to detect focus events on file edit input elements. This child module is only\n * needed for UAs that do not support the focusin event. Currently, only Firefox lacks this event.\n *\n * @param spec Overrides for default specifications\n */\nqq.FilenameInputFocusHandler = function(spec) {\n \"use strict\";\n\n spec.eventType = \"focus\";\n spec.attachTo = null;\n\n qq.extend(this, new qq.FilenameInputFocusInHandler(spec, {}));\n};\n","/*globals qq */\n// Handles edit-related events on a file item (FineUploader mode). This is meant to be a parent handler.\n// Children will delegate to this handler when specific edit-related actions are detected.\nqq.FilenameEditHandler = function(s, inheritedInternalApi) {\n \"use strict\";\n\n var spec = {\n templating: null,\n log: function(message, lvl) {},\n onGetUploadStatus: function(fileId) {},\n onGetName: function(fileId) {},\n onSetName: function(fileId, newName) {},\n onEditingStatusChange: function(fileId, isEditing) {}\n };\n\n function getFilenameSansExtension(fileId) {\n var filenameSansExt = spec.onGetName(fileId),\n extIdx = filenameSansExt.lastIndexOf(\".\");\n\n if (extIdx > 0) {\n filenameSansExt = filenameSansExt.substr(0, extIdx);\n }\n\n return filenameSansExt;\n }\n\n function getOriginalExtension(fileId) {\n var origName = spec.onGetName(fileId);\n return qq.getExtension(origName);\n }\n\n // Callback iff the name has been changed\n function handleNameUpdate(newFilenameInputEl, fileId) {\n var newName = newFilenameInputEl.value,\n origExtension;\n\n if (newName !== undefined && qq.trimStr(newName).length > 0) {\n origExtension = getOriginalExtension(fileId);\n\n if (origExtension !== undefined) {\n newName = newName + \".\" + origExtension;\n }\n\n spec.onSetName(fileId, newName);\n }\n\n spec.onEditingStatusChange(fileId, false);\n }\n\n // The name has been updated if the filename edit input loses focus.\n function registerInputBlurHandler(inputEl, fileId) {\n inheritedInternalApi.getDisposeSupport().attach(inputEl, \"blur\", function() {\n handleNameUpdate(inputEl, fileId);\n });\n }\n\n // The name has been updated if the user presses enter.\n function registerInputEnterKeyHandler(inputEl, fileId) {\n inheritedInternalApi.getDisposeSupport().attach(inputEl, \"keyup\", function(event) {\n\n var code = event.keyCode || event.which;\n\n if (code === 13) {\n handleNameUpdate(inputEl, fileId);\n }\n });\n }\n\n qq.extend(spec, s);\n\n spec.attachTo = spec.templating.getFileList();\n\n qq.extend(this, new qq.UiEventHandler(spec, inheritedInternalApi));\n\n qq.extend(inheritedInternalApi, {\n handleFilenameEdit: function(id, target, focusInput) {\n var newFilenameInputEl = spec.templating.getEditInput(id);\n\n spec.onEditingStatusChange(id, true);\n\n newFilenameInputEl.value = getFilenameSansExtension(id);\n\n if (focusInput) {\n newFilenameInputEl.focus();\n }\n\n registerInputBlurHandler(newFilenameInputEl, id);\n registerInputEnterKeyHandler(newFilenameInputEl, id);\n }\n });\n};\n"]}
\ No newline at end of file
diff --git a/styles/bootstrap/fine-uploader/jquery.fine-uploader.js b/styles/bootstrap/fine-uploader/jquery.fine-uploader.js
index f635b4d0e..00152c02b 100644
--- a/styles/bootstrap/fine-uploader/jquery.fine-uploader.js
+++ b/styles/bootstrap/fine-uploader/jquery.fine-uploader.js
@@ -1,4 +1,4 @@
-// Fine Uploader 5.12.0 - (c) 2013-present Widen Enterprises, Inc. MIT licensed. http://fineuploader.com
+// Fine Uploader 5.16.2 - MIT licensed. http://fineuploader.com
(function(global) {
(function($) {
"use strict";
@@ -842,7 +842,7 @@
};
qq.Error.prototype = new Error();
})();
- qq.version = "5.12.0";
+ qq.version = "5.16.2";
qq.supportedFeatures = function() {
"use strict";
var supportsUploading, supportsUploadingBlobs, supportsFileDrop, supportsAjaxFileUploading, supportsFolderDrop, supportsChunking, supportsResume, supportsUploadViaPaste, supportsUploadCors, supportsDeleteFileXdr, supportsDeleteFileCorsXhr, supportsDeleteFileCors, supportsFolderSelection, supportsImagePreviews, supportsUploadProgress;
@@ -860,9 +860,6 @@
}
return supported;
}
- function isChrome21OrHigher() {
- return (qq.chrome() || qq.opera()) && navigator.userAgent.match(/Chrome\/[2][1-9]|Chrome\/[3-9][0-9]/) !== undefined;
- }
function isChrome14OrHigher() {
return (qq.chrome() || qq.opera()) && navigator.userAgent.match(/Chrome\/[1][4-9]|Chrome\/[2-9][0-9]/) !== undefined;
}
@@ -900,7 +897,11 @@
supportsAjaxFileUploading = supportsUploading && qq.isXhrUploadSupported();
supportsUploadingBlobs = supportsAjaxFileUploading && !qq.androidStock();
supportsFileDrop = supportsAjaxFileUploading && isDragAndDropSupported();
- supportsFolderDrop = supportsFileDrop && isChrome21OrHigher();
+ supportsFolderDrop = supportsFileDrop && function() {
+ var input = document.createElement("input");
+ input.type = "file";
+ return !!("webkitdirectory" in (input || document.querySelectorAll("input[type=file]")[0]));
+ }();
supportsChunking = supportsAjaxFileUploading && qq.isFileChunkingSupported();
supportsResume = supportsAjaxFileUploading && supportsChunking && isLocalStorageSupported();
supportsUploadViaPaste = supportsAjaxFileUploading && isChrome14OrHigher();
@@ -1160,7 +1161,8 @@
originalName: spec.name,
uuid: spec.uuid,
size: spec.size == null ? -1 : spec.size,
- status: status
+ status: status,
+ file: spec.file
}) - 1;
if (spec.batchId) {
data[id].batchId = spec.batchId;
@@ -1182,6 +1184,7 @@
byStatus[status] = [];
}
byStatus[status].push(id);
+ spec.onBeforeStatusChange && spec.onBeforeStatusChange(id);
uploaderProxy.onStatusChange(id, null, status);
return id;
},
@@ -1198,6 +1201,12 @@
return qq.extend([], data, true);
}
},
+ removeFileRef: function(id) {
+ var record = getDataByIds(id);
+ if (record) {
+ delete record.file;
+ }
+ },
reset: function() {
data = [];
byUuid = {};
@@ -1250,6 +1259,7 @@
CANCELED: "canceled",
PAUSED: "paused",
UPLOADING: "uploading",
+ UPLOAD_FINALIZING: "upload finalizing",
UPLOAD_RETRYING: "retrying upload",
UPLOAD_SUCCESSFUL: "upload successful",
UPLOAD_FAILED: "upload failed",
@@ -1330,7 +1340,14 @@
}
},
cancel: function(id) {
- this._handler.cancel(id);
+ var uploadData = this._uploadData.retrieve({
+ id: id
+ });
+ if (uploadData && uploadData.status === qq.status.UPLOAD_FINALIZING) {
+ this.log(qq.format("Ignoring cancel for file ID {} ({}). Finalizing upload.", id, this.getName(id)), "error");
+ } else {
+ this._handler.cancel(id);
+ }
},
cancelAll: function() {
var storedIdsCopy = [], self = this;
@@ -1407,7 +1424,17 @@
return this._endpointStore.get(fileId);
},
getFile: function(fileOrBlobId) {
- return this._handler.getFile(fileOrBlobId) || null;
+ var file = this._handler.getFile(fileOrBlobId);
+ var uploadDataRecord;
+ if (!file) {
+ uploadDataRecord = this._uploadData.retrieve({
+ id: fileOrBlobId
+ });
+ if (uploadDataRecord) {
+ file = uploadDataRecord.file;
+ }
+ }
+ return file || null;
},
getInProgress: function() {
return this._uploadData.retrieve({
@@ -1456,6 +1483,9 @@
id: id
}).uuid;
},
+ isResumable: function(id) {
+ return this._handler.hasResumeRecord(id);
+ },
log: function(str, level) {
if (this._options.debug && (!level || level === "info")) {
qq.log("[Fine Uploader " + qq.version + "] " + str);
@@ -1482,6 +1512,10 @@
}
return false;
},
+ removeFileRef: function(id) {
+ this._handler.expunge(id);
+ this._uploadData.removeFileRef(id);
+ },
reset: function() {
this.log("Resetting uploader...");
this._handler.reset();
@@ -1504,6 +1538,7 @@
this._succeededSinceLastAllComplete = [];
this._failedSinceLastAllComplete = [];
this._totalProgress && this._totalProgress.reset();
+ this._customResumeDataStore.reset();
},
retry: function(id) {
return this._manualRetry(id);
@@ -1519,6 +1554,9 @@
setCustomHeaders: function(headers, id) {
this._customHeadersStore.set(headers, id);
},
+ setCustomResumeData: function(id, data) {
+ this._customResumeDataStore.set(data, id);
+ },
setDeleteFileCustomHeaders: function(headers, id) {
this._deleteFileCustomHeadersStore.set(headers, id);
},
@@ -1546,6 +1584,28 @@
setUuid: function(id, newUuid) {
return this._uploadData.uuidChanged(id, newUuid);
},
+ setStatus: function(id, newStatus) {
+ var fileRecord = this.getUploads({
+ id: id
+ });
+ if (!fileRecord) {
+ throw new qq.Error(id + " is not a valid file ID.");
+ }
+ switch (newStatus) {
+ case qq.status.DELETED:
+ this._onDeleteComplete(id, null, false);
+ break;
+
+ case qq.status.DELETE_FAILED:
+ this._onDeleteComplete(id, null, true);
+ break;
+
+ default:
+ var errorMessage = "Method setStatus called on '" + name + "' not implemented yet for " + newStatus;
+ this.log(errorMessage);
+ throw new qq.Error(errorMessage);
+ }
+ },
uploadStoredFiles: function() {
if (this._storedIds.length === 0) {
this._itemError("noFilesError");
@@ -1556,20 +1616,22 @@
};
qq.basePrivateApi = {
_addCannedFile: function(sessionData) {
- var id = this._uploadData.addFile({
+ var self = this;
+ return this._uploadData.addFile({
uuid: sessionData.uuid,
name: sessionData.name,
size: sessionData.size,
- status: qq.status.UPLOAD_SUCCESSFUL
+ status: qq.status.UPLOAD_SUCCESSFUL,
+ onBeforeStatusChange: function(id) {
+ sessionData.deleteFileEndpoint && self.setDeleteFileEndpoint(sessionData.deleteFileEndpoint, id);
+ sessionData.deleteFileParams && self.setDeleteFileParams(sessionData.deleteFileParams, id);
+ if (sessionData.thumbnailUrl) {
+ self._thumbnailUrls[id] = sessionData.thumbnailUrl;
+ }
+ self._netUploaded++;
+ self._netUploadedOrQueued++;
+ }
});
- sessionData.deleteFileEndpoint && this.setDeleteFileEndpoint(sessionData.deleteFileEndpoint, id);
- sessionData.deleteFileParams && this.setDeleteFileParams(sessionData.deleteFileParams, id);
- if (sessionData.thumbnailUrl) {
- this._thumbnailUrls[id] = sessionData.thumbnailUrl;
- }
- this._netUploaded++;
- this._netUploadedOrQueued++;
- return id;
},
_annotateWithButtonId: function(file, associatedInput) {
if (qq.isFile(file)) {
@@ -1804,17 +1866,28 @@
onUploadPrep: qq.bind(this._onUploadPrep, this),
onUpload: function(id, name) {
self._onUpload(id, name);
- self._options.callbacks.onUpload(id, name);
+ var onUploadResult = self._options.callbacks.onUpload(id, name);
+ if (qq.isGenericPromise(onUploadResult)) {
+ self.log(qq.format("onUpload for {} returned a Promise - waiting for resolution.", id));
+ return onUploadResult;
+ }
+ return new qq.Promise().success();
},
onUploadChunk: function(id, name, chunkData) {
self._onUploadChunk(id, chunkData);
- self._options.callbacks.onUploadChunk(id, name, chunkData);
+ var onUploadChunkResult = self._options.callbacks.onUploadChunk(id, name, chunkData);
+ if (qq.isGenericPromise(onUploadChunkResult)) {
+ self.log(qq.format("onUploadChunk for {}.{} returned a Promise - waiting for resolution.", id, chunkData.partIndex));
+ return onUploadChunkResult;
+ }
+ return new qq.Promise().success();
},
onUploadChunkSuccess: function(id, chunkData, result, xhr) {
+ self._onUploadChunkSuccess(id, chunkData);
self._options.callbacks.onUploadChunkSuccess.apply(self, arguments);
},
- onResume: function(id, name, chunkData) {
- return self._options.callbacks.onResume(id, name, chunkData);
+ onResume: function(id, name, chunkData, customResumeData) {
+ return self._options.callbacks.onResume(id, name, chunkData, customResumeData);
},
onAutoRetry: function(id, name, responseJSON, xhr) {
return self._onAutoRetry.apply(self, arguments);
@@ -1839,7 +1912,16 @@
return status === qq.status.QUEUED || status === qq.status.SUBMITTED || status === qq.status.UPLOAD_RETRYING || status === qq.status.PAUSED;
},
getIdsInProxyGroup: self._uploadData.getIdsInProxyGroup,
- getIdsInBatch: self._uploadData.getIdsInBatch
+ getIdsInBatch: self._uploadData.getIdsInBatch,
+ isInProgress: function(id) {
+ return self.getUploads({
+ id: id
+ }).status === qq.status.UPLOADING;
+ },
+ getCustomResumeData: qq.bind(self._getCustomResumeData, self),
+ setStatus: function(id, status) {
+ self._uploadData.setStatus(id, status);
+ }
};
qq.each(this._options.request, function(prop, val) {
options[prop] = val;
@@ -1916,6 +1998,9 @@
}
}
},
+ _getCustomResumeData: function(fileId) {
+ return this._customResumeDataStore.get(fileId);
+ },
_getNotFinished: function() {
return this._uploadData.retrieve({
status: [ qq.status.UPLOADING, qq.status.UPLOAD_RETRYING, qq.status.QUEUED, qq.status.SUBMITTING, qq.status.SUBMITTED, qq.status.PAUSED ]
@@ -2017,7 +2102,8 @@
uuid: uuid,
name: name,
size: size,
- batchId: batchId
+ batchId: batchId,
+ file: file
});
this._handler.add(id, file);
this._trackButton(id);
@@ -2038,6 +2124,28 @@
blob: blob
});
},
+ _handleDeleteSuccess: function(id) {
+ if (this.getUploads({
+ id: id
+ }).status !== qq.status.DELETED) {
+ var name = this.getName(id);
+ this._netUploadedOrQueued--;
+ this._netUploaded--;
+ this._handler.expunge(id);
+ this._uploadData.setStatus(id, qq.status.DELETED);
+ this.log("Delete request for '" + name + "' has succeeded.");
+ }
+ },
+ _handleDeleteFailed: function(id, xhrOrXdr) {
+ var name = this.getName(id);
+ this._uploadData.setStatus(id, qq.status.DELETE_FAILED);
+ this.log("Delete request for '" + name + "' has failed.", "error");
+ if (!xhrOrXdr || xhrOrXdr.withCredentials === undefined) {
+ this._options.callbacks.onError(id, name, "Delete request failed", xhrOrXdr);
+ } else {
+ this._options.callbacks.onError(id, name, "Delete request failed with response code " + xhrOrXdr.status, xhrOrXdr);
+ }
+ },
_initExtraButton: function(spec) {
var button = this._createUploadButton({
accept: spec.validation.acceptFiles,
@@ -2190,7 +2298,7 @@
_onAutoRetry: function(id, name, responseJSON, xhr, callback) {
var self = this;
self._preventRetries[id] = responseJSON[self._options.retry.preventRetryResponseProperty];
- if (self._shouldAutoRetry(id, name, responseJSON)) {
+ if (self._shouldAutoRetry(id)) {
var retryWaitPeriod = self._options.retry.autoAttemptDelay * 1e3;
self._maybeParseAndSendUploadError.apply(self, arguments);
self._options.callbacks.onAutoRetry(id, name, self._autoRetries[id]);
@@ -2263,19 +2371,9 @@
_onDeleteComplete: function(id, xhrOrXdr, isError) {
var name = this.getName(id);
if (isError) {
- this._uploadData.setStatus(id, qq.status.DELETE_FAILED);
- this.log("Delete request for '" + name + "' has failed.", "error");
- if (xhrOrXdr.withCredentials === undefined) {
- this._options.callbacks.onError(id, name, "Delete request failed", xhrOrXdr);
- } else {
- this._options.callbacks.onError(id, name, "Delete request failed with response code " + xhrOrXdr.status, xhrOrXdr);
- }
+ this._handleDeleteFailed(id, xhrOrXdr);
} else {
- this._netUploadedOrQueued--;
- this._netUploaded--;
- this._handler.expunge(id);
- this._uploadData.setStatus(id, qq.status.DELETED);
- this.log("Delete request for '" + name + "' has succeeded.");
+ this._handleDeleteSuccess(id);
}
},
_onInputChange: function(input) {
@@ -2335,6 +2433,11 @@
this._uploadData.setStatus(id, qq.status.UPLOADING);
},
_onUploadChunk: function(id, chunkData) {},
+ _onUploadChunkSuccess: function(id, chunkData) {
+ if (!this._preventRetries[id] && this._options.retry.enableAuto) {
+ this._autoRetries[id] = 0;
+ }
+ },
_onUploadStatusChange: function(id, oldStatus, newStatus) {
if (newStatus === qq.status.PAUSED) {
clearTimeout(this._retryTimeouts[id]);
@@ -2430,7 +2533,7 @@
this._uploadData.updateSize(id, newSize);
this._totalProgress && this._totalProgress.onNewSize(id);
},
- _shouldAutoRetry: function(id, name, responseJSON) {
+ _shouldAutoRetry: function(id) {
var uploadData = this._uploadData.retrieve({
id: id
});
@@ -2579,6 +2682,7 @@
maxConnections: 3,
disableCancelForFormUploads: false,
autoUpload: true,
+ warnBeforeUnload: true,
request: {
customHeaders: {},
endpoint: "/server/upload",
@@ -2586,8 +2690,10 @@
forceMultipart: true,
inputName: "qqfile",
method: "POST",
+ omitDefaultParams: false,
params: {},
paramsInBody: true,
+ requireSuccessJson: true,
totalFileSizeName: "qqtotalfilesize",
uuidName: "qquuid"
},
@@ -2615,7 +2721,7 @@
onUpload: function(id, name) {},
onUploadChunk: function(id, name, chunkData) {},
onUploadChunkSuccess: function(id, chunkData, responseJSON, xhr) {},
- onResume: function(id, fileName, chunkData) {},
+ onResume: function(id, fileName, chunkData, customResumeData) {},
onProgress: function(id, name, loaded, total) {},
onTotalProgress: function(loaded, total) {},
onError: function(id, name, reason, maybeXhrOrXdr) {},
@@ -2668,9 +2774,20 @@
totalFileSize: "qqtotalfilesize",
totalParts: "qqtotalparts"
},
- partSize: 2e6,
+ partSize: function(id) {
+ return 2e6;
+ },
success: {
- endpoint: null
+ endpoint: null,
+ headers: function(id) {
+ return null;
+ },
+ jsonPayload: false,
+ method: "POST",
+ params: function(id) {
+ return null;
+ },
+ resetOnStatus: []
}
},
resume: {
@@ -2678,6 +2795,9 @@
recordsExpireIn: 7,
paramNames: {
resuming: "qqresume"
+ },
+ customKeys: function(fileId) {
+ return [];
}
},
formatFileName: function(fileOrBlobName) {
@@ -2776,7 +2896,7 @@
this.log("Paste support module not found", "error");
}
}
- this._preventLeaveInProgress();
+ this._options.warnBeforeUnload && this._preventLeaveInProgress();
this._imageGenerator = qq.ImageGenerator && new qq.ImageGenerator(qq.bind(this.log, this));
this._refreshSessionData();
this._succeededSinceLastAllComplete = [];
@@ -2794,6 +2914,7 @@
});
}
this._currentItemLimit = this._options.validation.itemLimit;
+ this._customResumeDataStore = this._createStore();
};
qq.FineUploaderBasic.prototype = qq.basePublicApi;
qq.extend(qq.FineUploaderBasic.prototype, qq.basePrivateApi);
@@ -2863,7 +2984,7 @@
return xhrOrXdr;
}
function getXhrOrXdr(id, suppliedXhr) {
- var xhrOrXdr = requestData[id].xhr;
+ var xhrOrXdr = requestData[id] && requestData[id].xhr;
if (!xhrOrXdr) {
if (suppliedXhr) {
xhrOrXdr = suppliedXhr;
@@ -3126,13 +3247,14 @@
onUploadChunk: function(id, fileName, chunkData) {},
onUploadChunkSuccess: function(id, chunkData, response, xhr) {},
onAutoRetry: function(id, fileName, response, xhr) {},
- onResume: function(id, fileName, chunkData) {},
+ onResume: function(id, fileName, chunkData, customResumeData) {},
onUuidChanged: function(id, newUuid) {},
getName: function(id) {},
setSize: function(id, newSize) {},
isQueued: function(id) {},
getIdsInProxyGroup: function(id) {},
- getIdsInBatch: function(id) {}
+ getIdsInBatch: function(id) {},
+ isInProgress: function(id) {}
}, chunked = {
done: function(id, chunkIdx, response, xhr) {
var chunkData = handler._getChunkData(id, chunkIdx);
@@ -3151,13 +3273,13 @@
handler._maybeDeletePersistedChunkData(id);
upload.cleanup(id, normaizedResponse, xhr);
}, function(response, xhr) {
- var normaizedResponse = upload.normalizeResponse(response, false);
- log("Problem finalizing chunks for file ID " + id + " - " + normaizedResponse.error, "error");
- if (normaizedResponse.reset) {
+ var normalizedResponse = upload.normalizeResponse(response, false);
+ log("Problem finalizing chunks for file ID " + id + " - " + normalizedResponse.error, "error");
+ if (normalizedResponse.reset || xhr && options.chunking.success.resetOnStatus.indexOf(xhr.status) >= 0) {
chunked.reset(id);
}
- if (!options.onAutoRetry(id, name, normaizedResponse, xhr)) {
- upload.cleanup(id, normaizedResponse, xhr);
+ if (!options.onAutoRetry(id, name, normalizedResponse, xhr)) {
+ upload.cleanup(id, normalizedResponse, xhr);
}
});
},
@@ -3169,7 +3291,8 @@
if (responseToReport.reset) {
chunked.reset(id);
} else {
- inProgressIdx = qq.indexOf(handler._getFileState(id).chunking.inProgress, chunkIdx);
+ var inProgressChunksArray = handler._getFileState(id).chunking.inProgress;
+ inProgressIdx = inProgressChunksArray ? qq.indexOf(inProgressChunksArray, chunkIdx) : -1;
if (inProgressIdx >= 0) {
handler._getFileState(id).chunking.inProgress.splice(inProgressIdx, 1);
handler._getFileState(id).chunking.remaining.unshift(chunkIdx);
@@ -3207,13 +3330,14 @@
handler._maybeDeletePersistedChunkData(id);
handler.reevaluateChunking(id);
handler._getFileState(id).loaded = 0;
+ handler._getFileState(id).attemptingResume = false;
},
sendNext: function(id) {
- var size = options.getSize(id), name = options.getName(id), chunkIdx = chunked.nextPart(id), chunkData = handler._getChunkData(id, chunkIdx), resuming = handler._getFileState(id).attemptingResume, inProgressChunks = handler._getFileState(id).chunking.inProgress || [];
- if (handler._getFileState(id).loaded == null) {
- handler._getFileState(id).loaded = 0;
+ var size = options.getSize(id), name = options.getName(id), chunkIdx = chunked.nextPart(id), chunkData = handler._getChunkData(id, chunkIdx), fileState = handler._getFileState(id), resuming = fileState.attemptingResume, inProgressChunks = fileState.chunking.inProgress || [];
+ if (fileState.loaded == null) {
+ fileState.loaded = 0;
}
- if (resuming && options.onResume(id, name, chunkData) === false) {
+ if (resuming && options.onResume(id, name, chunkData, fileState.customResumeData) === false) {
chunked.reset(id);
chunkIdx = chunked.nextPart(id);
chunkData = handler._getChunkData(id, chunkIdx);
@@ -3222,8 +3346,6 @@
if (chunkIdx == null && inProgressChunks.length === 0) {
chunked.finalize(id);
} else {
- log(qq.format("Sending chunked upload request for item {}.{}, bytes {}-{} of {}.", id, chunkIdx, chunkData.start + 1, chunkData.end, size));
- options.onUploadChunk(id, name, handler._getChunkDataForCallback(chunkData));
inProgressChunks.push(chunkIdx);
handler._getFileState(id).chunking.inProgress = inProgressChunks;
if (concurrentChunkingPossible) {
@@ -3235,30 +3357,45 @@
if (chunkData.blob.size === 0) {
log(qq.format("Chunk {} for file {} will not be uploaded, zero sized chunk.", chunkIdx, id), "error");
chunked.handleFailure(chunkIdx, id, "File is no longer available", null);
- } else {
- handler.uploadChunk(id, chunkIdx, resuming).then(function success(response, xhr) {
- log("Chunked upload request succeeded for " + id + ", chunk " + chunkIdx);
- handler.clearCachedChunk(id, chunkIdx);
- var inProgressChunks = handler._getFileState(id).chunking.inProgress || [], responseToReport = upload.normalizeResponse(response, true), inProgressChunkIdx = qq.indexOf(inProgressChunks, chunkIdx);
- log(qq.format("Chunk {} for file {} uploaded successfully.", chunkIdx, id));
- chunked.done(id, chunkIdx, responseToReport, xhr);
- if (inProgressChunkIdx >= 0) {
- inProgressChunks.splice(inProgressChunkIdx, 1);
- }
- handler._maybePersistChunkedState(id);
- if (!chunked.hasMoreParts(id) && inProgressChunks.length === 0) {
- chunked.finalize(id);
- } else if (chunked.hasMoreParts(id)) {
- chunked.sendNext(id);
- } else {
- log(qq.format("File ID {} has no more chunks to send and these chunk indexes are still marked as in-progress: {}", id, JSON.stringify(inProgressChunks)));
- }
- }, function failure(response, xhr) {
- chunked.handleFailure(chunkIdx, id, response, xhr);
- }).done(function() {
- handler.clearXhr(id, chunkIdx);
- });
}
+ var onUploadChunkPromise = options.onUploadChunk(id, name, handler._getChunkDataForCallback(chunkData));
+ onUploadChunkPromise.then(function(requestOverrides) {
+ if (!options.isInProgress(id)) {
+ log(qq.format("Not sending chunked upload request for item {}.{} - no longer in progress.", id, chunkIdx));
+ } else {
+ log(qq.format("Sending chunked upload request for item {}.{}, bytes {}-{} of {}.", id, chunkIdx, chunkData.start + 1, chunkData.end, size));
+ var uploadChunkData = {
+ chunkIdx: chunkIdx,
+ id: id,
+ overrides: requestOverrides,
+ resuming: resuming
+ };
+ handler.uploadChunk(uploadChunkData).then(function success(response, xhr) {
+ log("Chunked upload request succeeded for " + id + ", chunk " + chunkIdx);
+ handler.clearCachedChunk(id, chunkIdx);
+ var inProgressChunks = handler._getFileState(id).chunking.inProgress || [], responseToReport = upload.normalizeResponse(response, true), inProgressChunkIdx = qq.indexOf(inProgressChunks, chunkIdx);
+ log(qq.format("Chunk {} for file {} uploaded successfully.", chunkIdx, id));
+ chunked.done(id, chunkIdx, responseToReport, xhr);
+ if (inProgressChunkIdx >= 0) {
+ inProgressChunks.splice(inProgressChunkIdx, 1);
+ }
+ handler._maybePersistChunkedState(id);
+ if (!chunked.hasMoreParts(id) && inProgressChunks.length === 0) {
+ chunked.finalize(id);
+ } else if (chunked.hasMoreParts(id)) {
+ chunked.sendNext(id);
+ } else {
+ log(qq.format("File ID {} has no more chunks to send and these chunk indexes are still marked as in-progress: {}", id, JSON.stringify(inProgressChunks)));
+ }
+ }, function failure(response, xhr) {
+ chunked.handleFailure(chunkIdx, id, response, xhr);
+ }).done(function() {
+ handler.clearXhr(id, chunkIdx);
+ });
+ }
+ }, function(error) {
+ chunked.handleFailure(chunkIdx, id, error, null);
+ });
}
}
}, connectionManager = {
@@ -3334,7 +3471,12 @@
}
}, simple = {
send: function(id, name) {
- handler._getFileState(id).loaded = 0;
+ var fileState = handler._getFileState(id);
+ if (!fileState) {
+ log("Ignoring send request as this upload may have been cancelled, File ID " + id, "warn");
+ return;
+ }
+ fileState.loaded = 0;
log("Sending simple upload request for " + id);
handler.uploadFile(id).then(function(response, optXhr) {
log("Simple upload request succeeded for " + id);
@@ -3370,6 +3512,7 @@
initHandler: function() {
var handlerType = namespace ? qq[namespace] : qq.traditional, handlerModuleSubtype = qq.supportedFeatures.ajaxUploading ? "Xhr" : "Form";
handler = new handlerType[handlerModuleSubtype + "UploadHandler"](options, {
+ getCustomResumeData: options.getCustomResumeData,
getDataByUuid: options.getDataByUuid,
getName: options.getName,
getSize: options.getSize,
@@ -3377,7 +3520,10 @@
log: log,
onCancel: options.onCancel,
onProgress: options.onProgress,
- onUuidChanged: options.onUuidChanged
+ onUuidChanged: options.onUuidChanged,
+ onFinalizing: function(id) {
+ options.setStatus(id, qq.status.UPLOAD_FINALIZING);
+ }
});
if (handler._removeExpiredChunkingRecords) {
handler._removeExpiredChunkingRecords();
@@ -3450,12 +3596,26 @@
if (!controller.isValid(id)) {
throw new qq.Error(id + " is not a valid file ID to upload!");
}
- options.onUpload(id, name);
- if (chunkingPossible && handler._shouldChunkThisFile(id)) {
- chunked.sendNext(id);
- } else {
- simple.send(id, name);
- }
+ options.onUpload(id, name).then(function(response) {
+ if (response && response.pause) {
+ options.setStatus(id, qq.status.PAUSED);
+ handler.pause(id);
+ connectionManager.free(id);
+ } else {
+ if (chunkingPossible && handler._shouldChunkThisFile(id)) {
+ chunked.sendNext(id);
+ } else {
+ simple.send(id, name);
+ }
+ }
+ }, function(error) {
+ error = error || {};
+ log(id + " upload start aborted due to rejected onUpload Promise - details: " + error, "error");
+ if (!options.onAutoRetry(id, name, error.responseJSON || {})) {
+ var response = upload.normalizeResponse(error.responseJSON, false);
+ upload.cleanup(id, response);
+ }
+ });
},
start: function(id) {
var blobToUpload = upload.getProxyOrBlob(id);
@@ -3534,6 +3694,13 @@
isValid: function(id) {
return handler.isValid(id);
},
+ hasResumeRecord: function(id) {
+ var key = handler.isValid(id) && handler._getLocalStorageId && handler._getLocalStorageId(id);
+ if (key) {
+ return !!localStorage.getItem(key);
+ }
+ return false;
+ },
getResumableFilesData: function() {
if (handler.getResumableFilesData) {
return handler.getResumableFilesData();
@@ -3553,6 +3720,9 @@
}
return false;
},
+ isAttemptingResume: function(id) {
+ return !!handler.isAttemptingResume && handler.isAttemptingResume(id);
+ },
isResumable: function(id) {
return !!handler.isResumable && handler.isResumable(id);
}
@@ -3743,7 +3913,19 @@
};
qq.XhrUploadHandler = function(spec) {
"use strict";
- var handler = this, namespace = spec.options.namespace, proxy = spec.proxy, chunking = spec.options.chunking, resume = spec.options.resume, chunkFiles = chunking && spec.options.chunking.enabled && qq.supportedFeatures.chunking, resumeEnabled = resume && spec.options.resume.enabled && chunkFiles && qq.supportedFeatures.resume, getName = proxy.getName, getSize = proxy.getSize, getUuid = proxy.getUuid, getEndpoint = proxy.getEndpoint, getDataByUuid = proxy.getDataByUuid, onUuidChanged = proxy.onUuidChanged, onProgress = proxy.onProgress, log = proxy.log;
+ var handler = this, namespace = spec.options.namespace, proxy = spec.proxy, chunking = spec.options.chunking, getChunkSize = function(id) {
+ var fileState = handler._getFileState(id);
+ if (fileState.chunkSize) {
+ return fileState.chunkSize;
+ } else {
+ var chunkSize = chunking.partSize;
+ if (qq.isFunction(chunkSize)) {
+ chunkSize = chunkSize(id, getSize(id));
+ }
+ fileState.chunkSize = chunkSize;
+ return chunkSize;
+ }
+ }, resume = spec.options.resume, chunkFiles = chunking && spec.options.chunking.enabled && qq.supportedFeatures.chunking, resumeEnabled = resume && spec.options.resume.enabled && chunkFiles && qq.supportedFeatures.resume, getName = proxy.getName, getSize = proxy.getSize, getUuid = proxy.getUuid, getEndpoint = proxy.getEndpoint, getDataByUuid = proxy.getDataByUuid, onUuidChanged = proxy.onUuidChanged, onProgress = proxy.onProgress, log = proxy.log, getCustomResumeData = proxy.getCustomResumeData;
function abort(id) {
qq.each(handler._getXhrs(id), function(xhrId, xhr) {
var ajaxRequester = handler._getAjaxRequester(id, xhrId);
@@ -3781,7 +3963,10 @@
});
qq.extend(this, {
clearCachedChunk: function(id, chunkIdx) {
- delete handler._getFileState(id).temp.cachedChunks[chunkIdx];
+ var fileState = handler._getFileState(id);
+ if (fileState) {
+ delete fileState.temp.cachedChunks[chunkIdx];
+ }
},
clearXhr: function(id, chunkIdx) {
var tempState = handler._getFileState(id).temp;
@@ -3818,15 +4003,21 @@
if (uploadData.key) {
data.key = uploadData.key;
}
+ if (uploadData.customResumeData) {
+ data.customResumeData = uploadData.customResumeData;
+ }
resumableFilesData.push(data);
});
return resumableFilesData;
},
+ isAttemptingResume: function(id) {
+ return handler._getFileState(id).attemptingResume;
+ },
isResumable: function(id) {
return !!chunking && handler.isValid(id) && !handler._getFileState(id).notResumable;
},
moveInProgressToRemaining: function(id, optInProgress, optRemaining) {
- var inProgress = optInProgress || handler._getFileState(id).chunking.inProgress, remaining = optRemaining || handler._getFileState(id).chunking.remaining;
+ var fileState = handler._getFileState(id) || {}, chunkingState = fileState.chunking || {}, inProgress = optInProgress || chunkingState.inProgress, remaining = optRemaining || chunkingState.remaining;
if (inProgress) {
log(qq.format("Moving these chunks from in-progress {}, to remaining.", JSON.stringify(inProgress)));
inProgress.reverse();
@@ -3885,7 +4076,7 @@
return handler._getFileState(id).temp.ajaxRequesters[chunkIdx];
},
_getChunkData: function(id, chunkIndex) {
- var chunkSize = chunking.partSize, fileSize = getSize(id), fileOrBlob = handler.getFile(id), startBytes = chunkSize * chunkIndex, endBytes = startBytes + chunkSize >= fileSize ? fileSize : startBytes + chunkSize, totalChunks = handler._getTotalChunks(id), cachedChunks = this._getFileState(id).temp.cachedChunks, blob = cachedChunks[chunkIndex] || qq.sliceBlob(fileOrBlob, startBytes, endBytes);
+ var chunkSize = getChunkSize(id), fileSize = getSize(id), fileOrBlob = handler.getFile(id), startBytes = chunkSize * chunkIndex, endBytes = startBytes + chunkSize >= fileSize ? fileSize : startBytes + chunkSize, totalChunks = handler._getTotalChunks(id), cachedChunks = this._getFileState(id).temp.cachedChunks, blob = cachedChunks[chunkIndex] || qq.sliceBlob(fileOrBlob, startBytes, endBytes);
cachedChunks[chunkIndex] = blob;
return {
part: chunkIndex,
@@ -3905,8 +4096,11 @@
};
},
_getLocalStorageId: function(id) {
- var formatVersion = "5.0", name = getName(id), size = getSize(id), chunkSize = chunking.partSize, endpoint = getEndpoint(id);
- return qq.format("qq{}resume{}-{}-{}-{}-{}", namespace, formatVersion, name, size, chunkSize, endpoint);
+ var formatVersion = "5.0", name = getName(id), size = getSize(id), chunkSize = getChunkSize(id), endpoint = getEndpoint(id), customKeys = resume.customKeys(id), localStorageId = qq.format("qq{}resume{}-{}-{}-{}-{}", namespace, formatVersion, name, size, chunkSize, endpoint);
+ customKeys.forEach(function(key) {
+ localStorageId += "-" + key;
+ });
+ return localStorageId;
},
_getMimeType: function(id) {
return handler.getFile(id).type;
@@ -3916,7 +4110,7 @@
},
_getTotalChunks: function(id) {
if (chunking) {
- var fileSize = getSize(id), chunkSize = chunking.partSize;
+ var fileSize = getSize(id), chunkSize = getChunkSize(id);
return Math.ceil(fileSize / chunkSize);
}
},
@@ -3974,6 +4168,7 @@
state.key = persistedData.key;
state.chunking = persistedData.chunking;
state.loaded = persistedData.loaded;
+ state.customResumeData = persistedData.customResumeData;
state.attemptingResume = true;
handler.moveInProgressToRemaining(id);
}
@@ -3983,6 +4178,7 @@
_maybePersistChunkedState: function(id) {
var state = handler._getFileState(id), localStorageId, persistedData;
if (resumeEnabled && handler.isResumable(id)) {
+ var customResumeData = getCustomResumeData(id);
localStorageId = handler._getLocalStorageId(id);
persistedData = {
name: getName(id),
@@ -3993,6 +4189,9 @@
loaded: state.loaded,
lastUpdated: Date.now()
};
+ if (customResumeData) {
+ persistedData.customResumeData = customResumeData;
+ }
try {
localStorage.setItem(localStorageId, JSON.stringify(persistedData));
} catch (error) {
@@ -4049,10 +4248,12 @@
},
_shouldChunkThisFile: function(id) {
var state = handler._getFileState(id);
- if (!state.chunking) {
- handler.reevaluateChunking(id);
+ if (state) {
+ if (!state.chunking) {
+ handler.reevaluateChunking(id);
+ }
+ return state.chunking.enabled;
}
- return state.chunking.enabled;
}
});
};
@@ -5579,18 +5780,24 @@
"use strict";
var handler = this, getName = proxy.getName, getSize = proxy.getSize, getUuid = proxy.getUuid, log = proxy.log, multipart = spec.forceMultipart || spec.paramsInBody, addChunkingSpecificParams = function(id, params, chunkData) {
var size = getSize(id), name = getName(id);
- params[spec.chunking.paramNames.partIndex] = chunkData.part;
- params[spec.chunking.paramNames.partByteOffset] = chunkData.start;
- params[spec.chunking.paramNames.chunkSize] = chunkData.size;
- params[spec.chunking.paramNames.totalParts] = chunkData.count;
- params[spec.totalFileSizeName] = size;
- if (multipart) {
+ if (!spec.omitDefaultParams) {
+ params[spec.chunking.paramNames.partIndex] = chunkData.part;
+ params[spec.chunking.paramNames.partByteOffset] = chunkData.start;
+ params[spec.chunking.paramNames.chunkSize] = chunkData.size;
+ params[spec.chunking.paramNames.totalParts] = chunkData.count;
+ params[spec.totalFileSizeName] = size;
+ }
+ if (multipart && !spec.omitDefaultParams) {
params[spec.filenameParam] = name;
}
}, allChunksDoneRequester = new qq.traditional.AllChunksDoneAjaxRequester({
cors: spec.cors,
endpoint: spec.chunking.success.endpoint,
- log: log
+ headers: spec.chunking.success.headers,
+ jsonPayload: spec.chunking.success.jsonPayload,
+ log: log,
+ method: spec.chunking.success.method,
+ params: spec.chunking.success.params
}), createReadyStateChangedHandler = function(id, xhr) {
var promise = new qq.Promise();
xhr.onreadystatechange = function() {
@@ -5612,7 +5819,7 @@
params[spec.chunking.paramNames.totalParts] = handler._getTotalChunks(id);
return params;
}, isErrorUploadResponse = function(xhr, response) {
- return qq.indexOf([ 200, 201, 202, 203, 204 ], xhr.status) < 0 || !response.success || response.reset;
+ return qq.indexOf([ 200, 201, 202, 203, 204 ], xhr.status) < 0 || spec.requireSuccessJson && !response.success || response.reset;
}, onUploadOrChunkComplete = function(id, xhr) {
var response;
log("xhr - server response received for " + id);
@@ -5628,7 +5835,7 @@
log(qq.format("Received response status {} with body: {}", xhr.status, xhr.responseText));
response = qq.parseJson(xhr.responseText);
} catch (error) {
- upload && log("Error when attempting to parse xhr response text (" + error.message + ")", "error");
+ upload && spec.requireSuccessJson && log("Error when attempting to parse xhr response text (" + error.message + ")", "error");
}
return response;
}, sendChunksCompleteRequest = function(id) {
@@ -5639,17 +5846,32 @@
promise.failure(parseResponse(false, xhr), xhr);
});
return promise;
- }, setParamsAndGetEntityToSend = function(params, xhr, fileOrBlob, id) {
- var formData = new FormData(), method = spec.method, endpoint = spec.endpointStore.get(id), name = getName(id), size = getSize(id);
- params[spec.uuidName] = getUuid(id);
- params[spec.filenameParam] = name;
- if (multipart) {
- params[spec.totalFileSizeName] = size;
- }
- if (!spec.paramsInBody) {
- if (!multipart) {
+ }, setParamsAndGetEntityToSend = function(entityToSendParams) {
+ var fileOrBlob = entityToSendParams.fileOrBlob;
+ var id = entityToSendParams.id;
+ var xhr = entityToSendParams.xhr;
+ var xhrOverrides = entityToSendParams.xhrOverrides || {};
+ var customParams = entityToSendParams.customParams || {};
+ var defaultParams = entityToSendParams.params || {};
+ var xhrOverrideParams = xhrOverrides.params || {};
+ var params;
+ var formData = multipart ? new FormData() : null, method = xhrOverrides.method || spec.method, endpoint = xhrOverrides.endpoint || spec.endpointStore.get(id), name = getName(id), size = getSize(id);
+ if (spec.omitDefaultParams) {
+ params = qq.extend({}, customParams);
+ qq.extend(params, xhrOverrideParams);
+ } else {
+ params = qq.extend({}, customParams);
+ qq.extend(params, xhrOverrideParams);
+ qq.extend(params, defaultParams);
+ params[spec.uuidName] = getUuid(id);
+ params[spec.filenameParam] = name;
+ if (multipart) {
+ params[spec.totalFileSizeName] = size;
+ } else if (!spec.paramsInBody) {
params[spec.inputName] = name;
}
+ }
+ if (!spec.paramsInBody) {
endpoint = qq.obj2url(params, endpoint);
}
xhr.open(method, endpoint, true);
@@ -5664,42 +5886,74 @@
return formData;
}
return fileOrBlob;
- }, setUploadHeaders = function(id, xhr) {
- var extraHeaders = spec.customHeaders.get(id), fileOrBlob = handler.getFile(id);
- xhr.setRequestHeader("Accept", "application/json");
- xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
- xhr.setRequestHeader("Cache-Control", "no-cache");
- if (!multipart) {
- xhr.setRequestHeader("Content-Type", "application/octet-stream");
- xhr.setRequestHeader("X-Mime-Type", fileOrBlob.type);
+ }, setUploadHeaders = function(headersOptions) {
+ var headerOverrides = headersOptions.headerOverrides;
+ var id = headersOptions.id;
+ var xhr = headersOptions.xhr;
+ if (headerOverrides) {
+ qq.each(headerOverrides, function(headerName, headerValue) {
+ xhr.setRequestHeader(headerName, headerValue);
+ });
+ } else {
+ var extraHeaders = spec.customHeaders.get(id), fileOrBlob = handler.getFile(id);
+ xhr.setRequestHeader("Accept", "application/json");
+ xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
+ xhr.setRequestHeader("Cache-Control", "no-cache");
+ if (!multipart) {
+ xhr.setRequestHeader("Content-Type", "application/octet-stream");
+ xhr.setRequestHeader("X-Mime-Type", fileOrBlob.type);
+ }
+ qq.each(extraHeaders, function(name, val) {
+ xhr.setRequestHeader(name, val);
+ });
}
- qq.each(extraHeaders, function(name, val) {
- xhr.setRequestHeader(name, val);
- });
};
qq.extend(this, {
- uploadChunk: function(id, chunkIdx, resuming) {
- var chunkData = handler._getChunkData(id, chunkIdx), xhr = handler._createXhr(id, chunkIdx), size = getSize(id), promise, toSend, params;
+ uploadChunk: function(uploadChunkParams) {
+ var id = uploadChunkParams.id;
+ var chunkIdx = uploadChunkParams.chunkIdx;
+ var overrides = uploadChunkParams.overrides || {};
+ var resuming = uploadChunkParams.resuming;
+ var chunkData = handler._getChunkData(id, chunkIdx), xhr = handler._createXhr(id, chunkIdx), promise, toSend, customParams, params = {};
promise = createReadyStateChangedHandler(id, xhr);
handler._registerProgressHandler(id, chunkIdx, chunkData.size);
- params = spec.paramsStore.get(id);
+ customParams = spec.paramsStore.get(id);
addChunkingSpecificParams(id, params, chunkData);
if (resuming) {
params[spec.resume.paramNames.resuming] = true;
}
- toSend = setParamsAndGetEntityToSend(params, xhr, chunkData.blob, id);
- setUploadHeaders(id, xhr);
+ toSend = setParamsAndGetEntityToSend({
+ fileOrBlob: chunkData.blob,
+ id: id,
+ customParams: customParams,
+ params: params,
+ xhr: xhr,
+ xhrOverrides: overrides
+ });
+ setUploadHeaders({
+ headerOverrides: overrides.headers,
+ id: id,
+ xhr: xhr
+ });
xhr.send(toSend);
return promise;
},
uploadFile: function(id) {
- var fileOrBlob = handler.getFile(id), promise, xhr, params, toSend;
+ var fileOrBlob = handler.getFile(id), promise, xhr, customParams, toSend;
xhr = handler._createXhr(id);
handler._registerProgressHandler(id);
promise = createReadyStateChangedHandler(id, xhr);
- params = spec.paramsStore.get(id);
- toSend = setParamsAndGetEntityToSend(params, xhr, fileOrBlob, id);
- setUploadHeaders(id, xhr);
+ customParams = spec.paramsStore.get(id);
+ toSend = setParamsAndGetEntityToSend({
+ fileOrBlob: fileOrBlob,
+ id: id,
+ customParams: customParams,
+ xhr: xhr
+ });
+ setUploadHeaders({
+ id: id,
+ xhr: xhr
+ });
xhr.send(toSend);
return promise;
}
@@ -5715,6 +5969,7 @@
qq.override(this, function(super_) {
return {
finalizeChunks: function(id) {
+ proxy.onFinalizing(id);
if (spec.chunking.success.endpoint) {
return sendChunksCompleteRequest(id);
} else {
@@ -5726,24 +5981,29 @@
};
qq.traditional.AllChunksDoneAjaxRequester = function(o) {
"use strict";
- var requester, method = "POST", options = {
+ var requester, options = {
cors: {
allowXdr: false,
expected: false,
sendCredentials: false
},
endpoint: null,
- log: function(str, level) {}
+ log: function(str, level) {},
+ method: "POST"
}, promises = {}, endpointHandler = {
get: function(id) {
+ if (qq.isFunction(options.endpoint)) {
+ return options.endpoint(id);
+ }
return options.endpoint;
}
};
qq.extend(options, o);
requester = qq.extend(this, new qq.AjaxRequester({
acceptHeader: "application/json",
- validMethods: [ method ],
- method: method,
+ contentType: options.jsonPayload ? "application/json" : "application/x-www-form-urlencoded",
+ validMethods: [ options.method ],
+ method: options.method,
endpointStore: endpointHandler,
allowXRequestedWithAndCacheControl: false,
cors: options.cors,
@@ -5763,7 +6023,7 @@
var promise = new qq.Promise();
options.log("Submitting All Chunks Done request for " + id);
promises[id] = promise;
- requester.initTransport(id).withParams(params).withHeaders(headers).send(xhr);
+ requester.initTransport(id).withParams(options.params(id) || params).withHeaders(options.headers(id) || headers).send(xhr);
return promise;
}
});
@@ -5790,12 +6050,7 @@
var parseEntryPromise = new qq.Promise();
if (entry.isFile) {
entry.file(function(file) {
- var name = entry.name, fullPath = entry.fullPath, indexOfNameInFullPath = fullPath.indexOf(name);
- fullPath = fullPath.substr(0, indexOfNameInFullPath);
- if (fullPath.charAt(0) === "/") {
- fullPath = fullPath.substr(1);
- }
- file.qqPath = fullPath;
+ file.qqPath = extractDirectoryPath(entry);
droppedFiles.push(file);
parseEntryPromise.success();
}, function(fileError) {
@@ -5823,6 +6078,14 @@
}
return parseEntryPromise;
}
+ function extractDirectoryPath(entry) {
+ var name = entry.name, fullPath = entry.fullPath, indexOfNameInFullPath = fullPath.lastIndexOf(name);
+ fullPath = fullPath.substr(0, indexOfNameInFullPath);
+ if (fullPath.charAt(0) === "/") {
+ fullPath = fullPath.substr(1);
+ }
+ return fullPath;
+ }
function getFilesInDirectory(entry, reader, accumEntries, existingPromise) {
var promise = existingPromise || new qq.Promise(), dirReader = reader || entry.createReader();
dirReader.readEntries(function readSuccess(entries) {
@@ -5910,9 +6173,6 @@
return fileDrag;
}
function leavingDocumentOut(e) {
- if (qq.firefox()) {
- return !e.relatedTarget;
- }
if (qq.safari()) {
return e.x < 0 || e.y < 0;
}
@@ -5952,8 +6212,10 @@
maybeHideDropZones();
});
disposeSupport.attach(document, "drop", function(e) {
- e.preventDefault();
- maybeHideDropZones();
+ if (isFileDrag(e)) {
+ e.preventDefault();
+ maybeHideDropZones();
+ }
});
disposeSupport.attach(document, HIDE_ZONES_EVENT_NAME, maybeHideDropZones);
}
@@ -5978,6 +6240,8 @@
});
}
});
+ this._testing = {};
+ this._testing.extractDirectoryPath = extractDirectoryPath;
};
qq.DragAndDrop.callbacks = function() {
"use strict";
@@ -6030,7 +6294,7 @@
}
var effectTest, dt = e.dataTransfer, isSafari = qq.safari();
effectTest = qq.ie() && qq.supportedFeatures.fileDrop ? true : dt.effectAllowed !== "none";
- return dt && effectTest && (dt.files || !isSafari && dt.types.contains && dt.types.contains("Files"));
+ return dt && effectTest && (dt.files && dt.files.length || !isSafari && dt.types.contains && dt.types.contains("Files") || dt.types.includes && dt.types.includes("Files"));
}
function isOrSetDropDisabled(isDisabled) {
if (isDisabled !== undefined) {
@@ -6113,6 +6377,8 @@
return element;
}
});
+ this._testing = {};
+ this._testing.isValidFileDrag = isValidFileDrag;
};
(function() {
"use strict";
@@ -6841,7 +7107,7 @@
dropProcessing: "qq-drop-processing-selector",
dropProcessingSpinner: "qq-drop-processing-spinner-selector",
thumbnail: "qq-thumbnail-selector"
- }, previewGeneration = {}, cachedThumbnailNotAvailableImg = new qq.Promise(), cachedWaitingForThumbnailImg = new qq.Promise(), log, isEditElementsExist, isRetryElementExist, templateHtml, container, fileList, showThumbnails, serverScale, cacheThumbnailPlaceholders = function() {
+ }, previewGeneration = {}, cachedThumbnailNotAvailableImg = new qq.Promise(), cachedWaitingForThumbnailImg = new qq.Promise(), log, isEditElementsExist, isRetryElementExist, templateDom, container, fileList, showThumbnails, serverScale, cacheThumbnailPlaceholders = function() {
var notAvailableUrl = options.placeholders.thumbnailNotAvailable, waitingUrl = options.placeholders.waitingForThumbnail, spec = {
maxSize: thumbnailMaxSize,
scale: serverScale
@@ -6973,7 +7239,7 @@
});
return notAvailableImgPlacement;
}, parseAndGetTemplate = function() {
- var scriptEl, scriptHtml, fileListNode, tempTemplateEl, fileListHtml, defaultButton, dropArea, thumbnail, dropProcessing, dropTextEl, uploaderEl;
+ var scriptEl, scriptHtml, fileListNode, tempTemplateEl, fileListEl, defaultButton, dropArea, thumbnail, dropProcessing, dropTextEl, uploaderEl;
log("Parsing template");
if (options.templateIdOrEl == null) {
throw new Error("You MUST specify either a template element or ID!");
@@ -7037,15 +7303,15 @@
if (fileListNode == null) {
throw new Error("Could not find the file list container in the template!");
}
- fileListHtml = fileListNode.innerHTML;
+ fileListEl = fileListNode.children[0].cloneNode(true);
fileListNode.innerHTML = "";
if (tempTemplateEl.getElementsByTagName("DIALOG").length) {
document.createElement("dialog");
}
log("Template parsing complete");
return {
- template: qq.trimStr(tempTemplateEl.innerHTML),
- fileTemplate: qq.trimStr(fileListHtml)
+ template: tempTemplateEl,
+ fileTemplate: fileListEl
};
}, prependFile = function(el, index, fileList) {
var parentEl = fileList, beforeEl = parentEl.firstChild;
@@ -7151,13 +7417,13 @@
}
container = options.containerEl;
showThumbnails = options.imageGenerator !== undefined;
- templateHtml = parseAndGetTemplate();
+ templateDom = parseAndGetTemplate();
cacheThumbnailPlaceholders();
qq.extend(this, {
render: function() {
log("Rendering template in DOM.");
generatedThumbnails = 0;
- container.innerHTML = templateHtml.template;
+ container.appendChild(templateDom.template.cloneNode(true));
hide(getDropProcessing());
this.hideTotalProgress();
fileList = options.fileContainerEl || getTemplateEl(container, selectorClasses.list);
@@ -7169,6 +7435,7 @@
container.appendChild(cantRenderEl);
},
reset: function() {
+ container.innerHTML = "";
this.render();
},
clearFiles: function() {
@@ -7178,7 +7445,7 @@
isCancelDisabled = true;
},
addFile: function(id, name, prependInfo, hideForever, batch) {
- var fileEl = qq.toElement(templateHtml.fileTemplate), fileNameEl = getTemplateEl(fileEl, selectorClasses.file), uploaderEl = getTemplateEl(container, selectorClasses.uploader), fileContainer = batch ? fileBatch.content : fileList, thumb;
+ var fileEl = templateDom.fileTemplate.cloneNode(true), fileNameEl = getTemplateEl(fileEl, selectorClasses.file), uploaderEl = getTemplateEl(container, selectorClasses.uploader), fileContainer = batch ? fileBatch.content : fileList, thumb;
if (batch) {
fileBatch.map[id] = fileEl;
}
diff --git a/styles/bootstrap/fine-uploader/jquery.fine-uploader.js.map b/styles/bootstrap/fine-uploader/jquery.fine-uploader.js.map
index d573d8f94..4ab51c04f 100644
--- a/styles/bootstrap/fine-uploader/jquery.fine-uploader.js.map
+++ b/styles/bootstrap/fine-uploader/jquery.fine-uploader.js.map
@@ -1 +1 @@
-{"version":3,"sources":["?","../client/js/jquery-plugin.js","../client/js/jquery-dnd.js","../client/js/util.js","../client/js/export.js","../client/js/error/error.js","../client/js/version.js","../client/js/features.js","../client/js/promise.js","../client/js/blob-proxy.js","../client/js/button.js","../client/js/upload-data.js","../client/js/uploader.basic.api.js","../client/js/uploader.basic.js","../client/js/ajax.requester.js","../client/js/upload-handler/upload.handler.js","../client/js/upload-handler/upload.handler.controller.js","../client/js/window.receive.message.js","../client/js/upload-handler/form.upload.handler.js","../client/js/upload-handler/xhr.upload.handler.js","../client/js/deletefile.ajax.requester.js","../client/js/image-support/megapix-image.js","../client/js/image-support/image.js","../client/js/image-support/exif.js","../client/js/identify.js","../client/js/image-support/validation.image.js","../client/js/session.js","../client/js/session.ajax.requester.js","../client/js/image-support/scaler.js","../client/js/third-party/ExifRestorer.js","../client/js/total-progress.js","../client/js/paste.js","../client/js/form-support.js","../client/js/traditional/traditional.form.upload.handler.js","../client/js/traditional/traditional.xhr.upload.handler.js","../client/js/traditional/all-chunks-done.ajax.requester.js","../client/js/dnd.js","../client/js/uploader.api.js","../client/js/uploader.js","../client/js/templating.js","../client/js/ui.handler.events.js","../client/js/ui.handler.click.filebuttons.js","../client/js/ui.handler.click.filename.js","../client/js/ui.handler.focusin.filenameinput.js","../client/js/ui.handler.focus.filenameinput.js","../client/js/ui.handler.edit.filename.js"],"names":["global","$","$el","pluginOptions","init","options","xformedOpts","transformVariables","newUploaderInstance","getNewUploaderInstance","uploader","addCallbacks","params","uploaderType","pluginOption","namespace","charAt","toUpperCase","slice","toLowerCase","qq","FineUploader","dataStore","key","val","data","undefined","instanceToStore","option","optionVal","transformedOpts","callbacks","each","_options","prop","nonJqueryCallback","name","callbackEventTarget","exec","substring","originalArgs","Array","prototype","call","arguments","transformedArgs","nonJqueryCallbackRetVal","jqueryEventCallbackRetVal","idx","arg","push","maybeWrapInJquery","apply","this","triggerHandler","error","log","message","source","dest","xformed","arrayVals","element","inArray","isPlainObject","isArray","arrayVal","arrayObjDest","merge","isValidCommand","command","type","match","delegateCommand","xformedArgs","origArgs","retVal","transformedVal","nodeType","cloneNode","fn","fineUploader","optionsOrCommand","self","selfArgs","retVals","index","el","length","jQuery","rootDataKey","dropZoneElements","dnd","DragAndDrop","func","$callbackEl","args","jqueryHandlerResult","fineUploaderDnd","hide","style","display","attach","addEventListener","attachEvent","detach","removeEventListener","detachEvent","contains","descendant","compareDocumentPosition","insertBefore","elementB","parentNode","remove","removeChild","css","styles","Error","opacity","filter","Math","round","extend","hasClass","considerParent","re","RegExp","test","className","addClass","removeClass","replace","getByClass","first","candidates","result","querySelector","querySelectorAll","getElementsByTagName","getFirstByClass","children","child","firstChild","nextSibling","setText","text","innerText","textContent","clearText","hasAttribute","attrName","attrVal","getAttribute","canvasToBlob","canvas","mime","quality","dataUriToBlob","toDataURL","dataUri","arrayBuffer","byteString","createBlob","BlobBuilder","window","WebKitBlobBuilder","MozBlobBuilder","MSBlobBuilder","blobBuilder","append","getBlob","Blob","intArray","mimeString","split","indexOf","atob","decodeURI","ArrayBuffer","Uint8Array","character","charCodeAt","level","console","isObject","variable","Object","toString","isFunction","value","buffer","constructor","isItemList","maybeItemList","isNodeList","maybeNodeList","item","namedItem","isString","maybeString","trimStr","string","String","trim","format","str","newStr","nextIdxToReplace","strBefore","strAfter","isFile","maybeFile","File","isFileList","maybeFileList","FileList","isFileOrInput","maybeFileOrInput","isInput","maybeInput","notFile","evaluateType","normalizedType","HTMLInputElement","tagName","isBlob","maybeBlob","isXhrUploadSupported","input","document","createElement","multiple","FormData","createXhrInstance","upload","XMLHttpRequest","ActiveXObject","isFolderDropSupported","dataTransfer","items","webkitGetAsEntry","isFileChunkingSupported","androidStock","webkitSlice","mozSlice","sliceBlob","fileOrBlob","start","end","slicer","arrayBufferToHex","bytesAsHex","bytes","byt","byteAsHexStr","readBlobToHex","blob","startOffset","initialBlob","fileReader","FileReader","promise","Promise","onload","success","onerror","failure","readAsArrayBuffer","second","extendNested","override","target","sourceFn","super_","srcPropName","srcPropVal","arr","elt","from","len","hasOwnProperty","getUniqueId","c","r","random","v","ie","navigator","userAgent","ie7","ie8","ie10","ie11","edge","safari","vendor","chrome","opera","firefox","windows","platform","android","ios6","ios","ios7","ios8","ios800","iosChrome","iosSafari","iosSafariWebView","preventDefault","e","returnValue","toElement","div","html","innerHTML","iterableItem","callback","keyOrIndex","Storage","getItem","bind","oldFunc","context","newArgs","concat","obj2url","obj","temp","prefixDone","uristrings","prefix","add","nextObj","i","nextTemp","encodeURIComponent","join","obj2FormData","formData","arrayKeyName","obj2Inputs","form","setAttribute","appendChild","parseJson","json","JSON","parse","eval","getExtension","filename","extIdx","lastIndexOf","substr","getFilename","blobOrFileInput","fileName","DisposeSupport","disposers","dispose","disposer","shift","addDisposer","disposeFunction","define","amd","module","exports","version","supportedFeatures","supportsUploading","supportsUploadingBlobs","supportsFileDrop","supportsAjaxFileUploading","supportsFolderDrop","supportsChunking","supportsResume","supportsUploadViaPaste","supportsUploadCors","supportsDeleteFileXdr","supportsDeleteFileCorsXhr","supportsDeleteFileCors","supportsFolderSelection","supportsImagePreviews","supportsUploadProgress","testSupportsFileInputElement","supported","tempInput","disabled","ex","isChrome21OrHigher","isChrome14OrHigher","isCrossOriginXhrSupported","xhr","withCredentials","isXdrSupported","XDomainRequest","isCrossOriginAjaxSupported","isFolderSelectionSupported","webkitdirectory","isLocalStorageSupported","localStorage","setItem","isDragAndDropSupported","span","postMessage","ajaxUploading","blobUploading","canDetermineSize","chunking","deleteFileCors","deleteFileCorsXdr","deleteFileCorsXhr","dialogElement","HTMLDialogElement","fileDrop","folderDrop","folderSelection","imagePreviews","imageValidation","itemSizeValidation","pause","progressBar","resume","scaling","tiffPreviews","unlimitedScaledImageSize","uploading","uploadCors","uploadCustomHeaders","uploadNonMultipart","uploadViaPaste","isGenericPromise","maybePromise","then","successArgs","failureArgs","successCallbacks","failureCallbacks","doneCallbacks","state","onSuccess","onFailure","done","BlobProxy","referenceBlob","onCreate","create","UploadButton","o","disposeSupport","acceptFiles","focusClass","folders","hoverClass","ios8BrowserCrashWorkaround","onChange","title","buttonId","createInput","BUTTON_ID_ATTR_NAME","setMultiple","position","right","top","fontFamily","fontSize","margin","padding","cursor","height","overflow","direction","getInput","getButtonId","isMultiple","optInput","removeAttribute","setAcceptFiles","reset","UploadData","uploaderProxy","byUuid","byStatus","byProxyGroupId","byBatchId","getDataByIds","idOrIds","entries","id","getDataByUuids","uuids","uuid","getDataByStatus","status","statusResults","statuses","statusEnum","statusResultIndexes","dataIndex","addFile","spec","SUBMITTING","originalName","size","batchId","proxyGroupId","onStatusChange","retrieve","optionalFilter","setStatus","newStatus","oldStatus","byStatusOldStatusIndex","splice","uuidChanged","newUuid","oldUuid","updateName","newName","updateSize","newSize","setParentId","targetId","parentId","getIdsInProxyGroup","getIdsInBatch","SUBMITTED","REJECTED","QUEUED","CANCELED","PAUSED","UPLOADING","UPLOAD_RETRYING","UPLOAD_SUCCESSFUL","UPLOAD_FAILED","DELETE_FAILED","DELETING","DELETED","basePublicApi","addBlobs","blobDataOrArray","endpoint","addFiles","addInitialFiles","cannedFileList","cannedFile","_addCannedFile","_maybeHandleIos8SafariWorkaround","_storedIds","_currentBatchId","processBlob","_handleNewFile","blobs","defaultName","verifiedFiles","processBlobData","blobData","processCanvas","processCanvasData","canvasData","normalizedQuality","processFileOrInput","fileOrInput","files","file","normalizeData","fileContainer","_prepareItemsForUpload","cancel","_handler","cancelAll","storedIdsCopy","storedFileId","clearStoredFiles","continueUpload","uploadData","_uploadData","enabled","getName","_uploadFile","deleteFile","_onSubmitDelete","doesExist","fileOrBlobId","isValid","drawThumbnail","fileId","imgOrCanvas","maxSize","fromServer","customResizeFunction","promiseToReturn","fileOrUrl","_imageGenerator","_thumbnailUrls","scale","getFile","container","generate","modifiedContainer","reason","getButton","_getButton","_buttonIdsForFileIds","getEndpoint","_endpointStore","get","getInProgress","getParentId","uploadDataEntry","getUploads","getResumableFilesData","getSize","getNetUploads","_netUploaded","getRemainingAllowedItems","allowedItems","_currentItemLimit","_netUploadedOrQueued","getUuid","debug","pauseUpload","_autoRetries","_retryTimeouts","_preventRetries","_buttons","button","_paramsStore","_pasteHandler","session","refreshOnReset","_refreshSessionData","_succeededSinceLastAllComplete","_failedSinceLastAllComplete","_totalProgress","retry","_manualRetry","scaleImage","specs","Scaler","setCustomHeaders","headers","_customHeadersStore","set","setDeleteFileCustomHeaders","_deleteFileCustomHeadersStore","setDeleteFileEndpoint","_deleteFileEndpointStore","setDeleteFileParams","_deleteFileParamsStore","setEndpoint","setForm","elementOrId","_updateFormSupportAndParams","setItemLimit","newItemLimit","setName","setParams","setUuid","uploadStoredFiles","_itemError","_uploadStoredFiles","basePrivateApi","sessionData","deleteFileEndpoint","deleteFileParams","thumbnailUrl","_annotateWithButtonId","associatedInput","qqButtonId","_getButtonId","_batchError","onError","_createDeleteHandler","DeleteFileAjaxRequester","method","maxConnections","uuidParamName","request","uuidName","customHeaders","paramsStore","endpointStore","cors","onDelete","_onDelete","onDeleteComplete","xhrOrXdr","isError","_onDeleteComplete","_createPasteHandler","PasteSupport","targetElement","paste","pasteReceived","_handleCheckedCallback","onPasteReceived","_handlePasteSuccess","identifier","_createStore","initialValue","_readOnlyValues_","store","catchall","perIdReadOnlyValues","readOnlyValues","copy","orig","getReadOnlyValues","includeReadOnlyValues","existing","values","addReadOnly","_createUploadDataTracker","_onUploadStatusChange","_maybeAllComplete","setTimeout","_createUploadButton","accept","validation","allowedExtensions","allowMultiple","workarounds","iosEmptyVideos","_isAllowedExtension","classes","buttonFocus","buttonHover","ios8BrowserCrash","inputName","_onInputChange","fileInputTitle","_disposeSupport","_createUploadHandler","additionalOptions","lastOnProgress","preventRetryParam","preventRetryResponseProperty","onProgress","loaded","total","_onProgress","onComplete","_onComplete","onCancel","cancelFinalizationEffort","_onCancel","onUploadPrep","_onUploadPrep","onUpload","_onUpload","onUploadChunk","chunkData","_onUploadChunk","onUploadChunkSuccess","onResume","onAutoRetry","responseJSON","_onAutoRetry","onUuidChanged","setSize","_setSize","getDataByUuid","isQueued","UploadHandlerController","_fileOrBlobRejected","_formatSize","sizeSymbols","max","toFixed","_generateExtraButtonSpecs","_extraButtonSpecs","extraButtons","extraButtonOptionEntry","extraButtonSpec","_initExtraButton","extraButtonsSpec","_defaultButtonId","buttonOrFileInputOrFile","inputs","fileInput","fileBlobOrInput","_getNotFinished","_getValidationBase","_getValidationDescriptor","fileWrapper","_getValidationDescriptors","fileWrappers","fileDescriptors","_handleCameraAccess","camera","acceptIosCamera","optionRoot","details","callbackRetVal","successParam","newFileWrapperList","actualFile","handler","_customNewFileHandler","_handleNewFileGeneric","addFileToHandler","_trackButton","fileList","extSuppliedName","extension","_initFormSupportAndParams","_formSupport","FormSupport","attachedToForm","getFormInputsAsObject","autoUpload","newAutoUpload","newEndpoint","_isDeletePossible","expected","allowXdr","allowed","valid","allowedExt","extRegex","code","maybeNameOrNames","messages","names","validationBase","extensionsForMessage","placeholderMatch","replacement","allowedExtension","formatFileName","sizeLimit","minSizeLimit","placeholder","_onBeforeManualRetry","notFinished","_onAllComplete","ios8SafariUploads","alert","unsupportedBrowserIos8Safari","_maybeParseAndSendUploadError","response","errorReason","defaultResponseError","_maybeProcessNextItemAfterOnValidateCallback","validItem","stopOnFirstInvalidFile","validationDescriptor","onValidate","_onValidateCallbackSuccess","_onValidateCallbackFailure","successful","failed","onAllComplete","_shouldAutoRetry","retryWaitPeriod","autoAttemptDelay","_onBeforeAutoRetry","itemLimit","onManualRetry","clearTimeout","storedItemIndex","expunge","fileIndex","onIndividualProgress","_onSubmit","_onSubmitCallbackSuccess","_onSubmitted","onSubmitted","_storeForLater","onSuccessCallback","additionalMandatedParams","adjustedOnSuccessCallback","onSubmitDelete","_deleteHandler","sendDelete","_onTotalProgress","onTotalProgress","_onValidateBatchCallbackFailure","_onValidateBatchCallbackSuccess","validationDescriptors","errorMessage","proposedNetFilesUploadedOrQueued","tooManyItemsError","nextIndex","_validateFileOrBlobData","_upload","onValidateBatch","_preventLeaveInProgress","event","onLeave","Session","_session","addFileRecord","refresh","_sessionRequestComplete","onSessionRequestComplete","onNewSize","enableAuto","maxAutoAttempts","formElementOrId","onSubmit","idToUpload","stillSubmitting","validityChecker","allowEmpty","ImageValidation","validate","image","errorCode","_wrapCallbacks","safeCallback","errorMsg","exception","callbackName","callbackFunc","FineUploaderBasic","disableCancelForFormUploads","filenameParam","forceMultipart","paramsInBody","totalFileSizeName","maxHeight","maxWidth","minHeight","minWidth","maybeXhr","maybeXhrOrXdr","attemptNumber","fileOrBlobData","typeError","sizeError","minSizeError","emptyError","noFilesError","maxHeightImageError","maxWidthImageError","minHeightImageError","minWidthImageError","retryFailTooManyItems","concurrent","mandatory","paramNames","partIndex","partByteOffset","chunkSize","totalFileSize","totalParts","partSize","recordsExpireIn","resuming","fileOrBlobName","sendCredentials","interceptSubmit","customResizer","sendOriginal","orient","defaultType","defaultQuality","failureText","includeExif","sizes","ImageGenerator","_scaler","handleNewFile","TotalProgress","entry","AjaxRequester","shouldParamsBeInQueryString","queue","requestData","acceptHeader","validMethods","contentType","mandatedParams","allowXRequestedWithAndCacheControl","successfulResponseCodes","DELETE","PATCH","POST","PUT","GET","onSend","isSimpleMethod","containsNonSimpleHeaders","containsNonSimple","header","isXdr","getCorsAjaxTransport","ontimeout","onprogress","getXhrOrXdr","suppliedXhr","dequeue","nextId","sendRequest","xdrError","isResponseSuccessful","getParams","onDemandParams","additionalParams","optXhr","payload","url","createUrl","additionalQueryParams","getXdrLoadHandler","getXdrErrorHandler","onreadystatechange","getXhrReadyStateChangeHandler","registerForUploadProgress","open","setHeaders","send","stringify","addToPath","readyState","lengthComputable","onDemandHeaders","additionalHeaders","allHeaders","setRequestHeader","responseCode","prepareToSend","initTransport","path","cacheBuster","withPath","appendToPath","withParams","withQueryParams","_additionalQueryParams_","withHeaders","withPayload","thePayload","withCacheBuster","qqtimestamp","Date","getTime","canceled","UploadHandler","proxy","fileState","fileItem","onCancelRetVal","getThirdPartyFileId","_getFileState","_setThirdPartyFileId","thirdPartyFileId","_wasCanceled","controller","chunkingPossible","concurrentChunkingPossible","preventRetryResponse","chunked","chunkIdx","_getChunkData","attemptingResume","chunkProgress","_getChunkDataForCallback","finalize","finalizeChunks","normaizedResponse","normalizeResponse","_maybeDeletePersistedChunkData","cleanup","handleFailure","clearCachedChunk","responseToReport","inProgressIdx","inProgress","remaining","unshift","ignoreFailure","keys","_getXhrs","ckid","ckXhr","abort","_cancelled","moveInProgressToRemaining","connectionManager","free","hasMoreParts","nextPart","nextIdx","_getTotalChunks","reevaluateChunking","sendNext","inProgressChunks","available","uploadChunk","inProgressChunkIdx","_maybePersistChunkedState","clearXhr","_open","_openChunks","_waiting","openChunkEntriesCount","openChunksCount","openChunkIndexes","dontAllowNext","allowNext","waitingIndex","connectionsIndex","getProxyOrBlob","getWaitingOrConnected","waitingOrConnected","chunks","parseInt","isUsingConnection","pop","openChunksEntry","simple","uploadFile","maybeNewUuid","_clearXhrs","getProxy","initHandler","handlerType","traditional","handlerModuleSubtype","_removeExpiredChunkingRecords","isDeferredEligibleForUpload","maybeDefer","generatedBlob","updateBlob","maybeSendDeferredFiles","errorResponse","idsInGroup","uploadedThisId","idInGroup","now","originalResponse","_shouldChunkThisFile","blobToUpload","cancelRetVal","isProxied","isResumable","WindowReceiveMessage","callbackWrapperDetachers","receiveMessage","onMessageCallbackWrapper","stopReceivingMessages","detacher","FormUploadHandler","formHandlerInstanceId","onloadCallbacks","detachLoadEvents","postMessageCallbackTimers","isCors","corsMessageReceiver","expungeFile","iframe","getElementById","_getIframeName","getFileIdForIframeName","iframeName","initIframeForUpload","body","registerPostMessageCallback","_parseJsonResponse","onloadCallback","_detachLoadEvent","_attachLoadEvent","responseDescriptor","contentDocument","_createIframe","_initFormForUpload","targetName","innerHtmlOrMessage","XhrUploadHandler","chunkFiles","resumeEnabled","xhrId","ajaxRequester","_getAjaxRequester","blobOrProxy","_initTempState","_maybePrepareForResume","cachedChunks","tempState","xhrs","ajaxRequesters","responseParser","lastChunkIdx","_getXhr","resumableFilesData","_iterateResumeRecords","notResumable","optInProgress","optRemaining","reverse","paused","totalChunks","parts","newBlob","chunkId","_createXhr","optChunkIdx","_registerXhr","chunkIndex","fileSize","startBytes","endBytes","part","count","startByte","endByte","_getLocalStorageId","formatVersion","_getMimeType","_getPersistableData","ceil","_markNotResumable","localStorageId","removeItem","persistedData","lastUpdated","_registerProgressHandler","progressCalculator","totalSuccessfullyLoadedForFile","loadedForRequest","totalForRequest","estActualChunkLoaded","totalLoadedForFile","chunkLoaded","optAjaxRequester","xhrsId","expirationDays","expirationDate","setDate","getDate","requester","getMandatedParams","_method","detectSubsampling","img","iw","naturalWidth","ih","naturalHeight","ctx","width","getContext","drawImage","getImageData","detectVerticalSquash","sy","ey","py","alpha","ratio","renderImageToDataURL","doSquash","renderImageToCanvas","maybeCalculateDownsampledDimensions","maxPixels","origHeight","origWidth","newHeight","sqrt","newWidth","modifiedDimensions","save","resize","renderImageToCanvasWithCustomResizer","imageHeight","imageWidth","orientation","targetHeight","targetWidth","transformCoordinate","d","tmpCanvas","vertSquashRatio","dw","dh","dy","tmpCtx","sx","dx","clearRect","restore","qqImageRendered","resizeInfo","sourceCanvas","sourceCanvasContext","targetCanvas","translate","rotate","PI","MegaPixImage","srcImage","errorCallback","Image","URL","createObjectURL","webkitURL","src","listeners","imageLoadListeners","render","imgWidth","imgHeight","opt","optionsKey","optionsValue","oldTargetSrc","onrender","isImg","isCanvas","isImgCorsSupported","crossOrigin","isCanvasSupported","determineMimeOfFileName","nameWithPath","pathSegments","isCrossOrigin","targetAnchor","targetProtocol","targetHostname","targetPort","href","protocol","port","hostname","location","registerImgLoadListeners","registerCanvasDrawImageListener","registerThumbnailRenderedListener","registered","draw","drawPreview","Identify","megapixErrorHandler","isPreviewable","dummyExif","exif","Exif","mpImg","Orientation","failureMsg","drawOnCanvasOrImgFromUrl","canvasOrImg","tempImg","tempImgRender","rendered","drawOnImgFromUrlWithCssScaling","drawFromUrl","fileBlobOrUrl","_testing","TAG_IDS","TAG_INFO","274","parseLittleEndian","hex","pow","seekToApp1","offset","theOffset","thePromise","segmentLength","getApp1Offset","isLittleEndian","app1Start","getDirEntryCount","littleEndian","getIfd","dirEntries","getDirEntries","ifdHex","getTagValues","TAG_VAL_OFFSET","tagsToFind","vals","idHex","tagsToFindIdx","tagValHex","tagValLength","parser","onParseFailure","app1Offset","dirEntryCount","tagValues","isIdentifiable","magicBytes","questionableBytes","identifiable","magicBytesEntries","magicBytesArrayEntry","previewable","isPreviewableSync","PREVIEWABLE_MIME_TYPES","fileMime","isRecognizedImage","image/jpeg","image/gif","image/png","image/bmp","image/tiff","hasNonZeroLimits","limits","atLeastOne","limit","getWidthHeight","sizeDetermination","getFailingLimit","dimensions","failingLimit","limitName","limitValue","limitMatcher","dimensionPropName","actualValue","validationEffort","isJsonResponseValid","handleFileItems","fileItems","someItemsIgnored","err","refreshEffort","refreshCompleteCallback","requesterOptions","SessionAjaxRequester","queryServer","responseText","includeOriginal","failedToScaleText","_getSortedSizes","getFileRecords","originalFileUuid","originalFileName","originalBlobOrBlobData","records","originalBlob","sizeRecord","outputType","_determineOutputType","requestedType","refType","_getName","_generateScaledImage","failedText","api","scaledIds","originalId","record","blobSize","scaledId","qqparentuuid","qqparentsize","param","scalingEffort","scalingOptions","scaler","referenceType","scaledVersionProperties","startOfExt","versionType","scaledName","scaledExt","nameAppendage","sort","a","b","sourceFile","imageGenerator","scaledImageDataUri","signalSuccess","_insertExifHeader","scaledImageDataUriWithExif","originalImage","reader","insertionEffort","originalImageDataUri","ExifRestorer","readAsDataURL","_dataUriToBlob","_createBlob","KEY_STR","encode64","output","chr1","chr2","chr3","enc1","enc2","enc3","enc4","isNaN","origFileBase64","resizedFileBase64","expectedBase64Header","rawImage","decode64","segments","slice2Segments","exifManipulation","exifArray","getExifArray","newImageArray","insertExif","aBuffer","seg","x","imageData","buf","separatePoint","mae","ato","array","rawImageArray","head","endPoint","base64test","perFileProgress","totalLoaded","totalSize","lastLoadedSent","lastTotalSent","callbackProxy","noRetryableFiles","retryable","none","failedId","updateTotalProgress","onNew","newLoaded","newTotal","oldLoaded","oldTotal","detachPasteHandler","isImage","registerPasteHandler","clipboardData","getAsFile","unregisterPasteHandler","startUpload","formEl","_form2Obj","determineNewEndpoint","validateForm","nativeSubmit","checkValidity","maybeUploadOnSubmit","submit","determineFormEl","notIrrelevantType","irrelevantTypes","radioOrCheckbox","ignoreValue","checked","selectValue","select","selected","elements","getIframeContentJson","doc","innerHtml","contentWindow","nodeValue","createForm","responseFromMessage","multipart","addChunkingSpecificParams","allChunksDoneRequester","AllChunksDoneAjaxRequester","createReadyStateChangedHandler","onUploadOrChunkComplete","getChunksCompleteParams","isErrorUploadResponse","parseResponse","sendChunksCompleteRequest","complete","setParamsAndGetEntityToSend","setUploadHeaders","extraHeaders","toSend","promises","endpointHandler","HIDE_ZONES_EVENT_NAME","HIDE_BEFORE_ENTER_ATTR","uploadDropZones","droppedFiles","allowMultipleItems","dropActive","uploadDroppedFiles","uploadDropZone","filesAsArray","dropLog","dropDisabled","processingDroppedFilesComplete","getElement","traverseFileTree","parseEntryPromise","fullPath","indexOfNameInFullPath","qqPath","fileError","isDirectory","getFilesInDirectory","allEntriesRead","entriesLeft","readFailure","accumEntries","existingPromise","dirReader","createReader","readEntries","readSuccess","newEntries","handleDataTransfer","pendingFolderPromises","handleDataTransferPromise","processingDroppedFiles","dropError","setupDropzone","dropArea","dropZone","UploadDropZone","onEnter","stopPropagation","onLeaveNotDescendants","onDrop","isFileDrag","dragEvent","fileDrag","types","leavingDocumentOut","relatedTarget","y","setupDragDrop","dropZones","maybeHideDropZones","HTMLElement","setupExtraDropzone","removeDropzone","dzs","targetEl","errorSpecifics","preventDrop","dropOutsideDisabled","dragoverShouldBeCanceled","disableDropOutside","dropEffect","isValidFileDrag","effectTest","dt","isSafari","effectAllowed","isOrSetDropDisabled","isDisabled","triggerHidezonesEvent","hideZonesEvent","triggerUsingOldApi","createEvent","initEvent","CustomEvent","dispatchEvent","attachEvents","effect","elementFromPoint","clientX","clientY","uiPublicApi","_parent","_templating","addCacheToDom","clearFiles","addExtraDropzone","_dnd","removeExtraDropzone","getItemByFileId","isHiddenForever","getFileContainer","_setupDragAndDrop","_totalFilesInBatch","_filesInBatchAddedToUi","_setupClickAndEditEventHandlers","formattedFilename","updateFilename","uploadPaused","continued","uploadContinued","getId","fileContainerOrChildEl","getFileId","getDropTarget","qqDropTarget","uiPrivateApi","_removeFileItem","removeFile","_fileButtonsClickHandler","FileButtonsClickHandler","_bindFileButtonsClickEvent","_focusinEventSupported","_isEditFilenameEnabled","_filenameClickHandler","_bindFilenameClickEvent","_filenameInputFocusInHandler","_bindFilenameInputFocusInEvent","_filenameInputFocusHandler","_bindFilenameInputFocusEvent","dragAndDrop","extraDropzones","templating","defaultDropZone","getDropZone","showDropProcessing","hideDropProcessing","errorData","lvl","onDeleteFile","onRetry","onPause","onContinue","onGetName","isEditFilenamePossible","FilenameClickHandler","FilenameInputFocusHandler","_filenameEditHandler","onGetUploadStatus","onSetName","onEditingStatusChange","isEditing","qqInput","getEditInput","qqFileContainer","hideFilename","hideEditIcon","showFilename","showEditIcon","markFilenameEditable","hideRetry","setStatusText","_classes","retrying","hidePause","FilenameInputFocusInHandler","hideSpinner","resetTotalProgress","reportDirectoryPaths","qqpath","_addToList","addHandler","updateProgress","hideCancel","hideProgress","waitingForResponse","_displayFileSize","parentRetVal","completeUpload","_markFileAsSuccessful","fail","showCancel","isRetryPossible","showRetry","_controlFailureTextDisplay","newResult","showDeleteButton","_maybeUpdateThumbnail","showSpinner","allowPause","retryNumForDisplay","maxAuto","retryNote","_showCancelLink","showAutoRetryNote","autoRetryNote","resetProgress","_onSubmitDeleteSuccess","forceConfirm","_showDeleteConfirm","_sendDeleteRequest","deletingFailedText","hideDeleteButton","deletingStatusText","confirmMessage","deleteRequestArgs","showConfirm","canned","prependData","prependIndex","dontDisplay","hideScaled","prependFiles","disableCancel","_handledProxyGroup","_clearList","addFileToCache","updateThumbnail","thumbnails","generatePreview","fileSizeOnSubmit","loadedSize","sizeForDisplay","_formatProgress","uploadedSize","formatProgress","mode","responseProperty","failureReason","failedUploadTextDisplay","failUpload","enableTooltip","_showTooltip","showMessage","_setupPastePrompt","namePromptMessage","defaultVal","showPrompt","fileStatus","placeholders","waitUntilResponse","listElement","template","editable","tooManyFilesError","unsupportedBrowser","promptForName","maxCount","notAvailablePath","waitingPath","timeBetweenThumbs","hasDialog","showDialog","confirm","defaultValue","prompt","Templating","templateIdOrEl","containerEl","fileContainerEl","maxThumbs","waitUntilUpdate","thumbnailNotAvailable","waitingForThumbnail","renderFailure","FILE_ID_ATTR","FILE_CLASS_PREFIX","THUMBNAIL_MAX_SIZE_ATTR","THUMBNAIL_SERVER_SCALE_ATTR","HIDE_DROPZONE_ATTR","DROPZPONE_TEXT_ATTR","IN_PROGRESS_CLASS","HIDDEN_FOREVER_CLASS","fileBatch","content","createDocumentFragment","map","isCancelDisabled","generatedThumbnails","thumbnailQueueMonitorRunning","thumbGenerationQueue","thumbnailMaxSize","selectorClasses","alertDialog","dialogCancelButton","confirmDialog","dialogMessage","dialogOkButton","promptDialog","drop","list","progressBarContainer","totalProgressBarContainer","totalProgressBar","spinner","continueButton","deleteButton","statusText","editFilenameInput","editNameIcon","dropText","dropProcessing","dropProcessingSpinner","thumbnail","previewGeneration","cachedThumbnailNotAvailableImg","cachedWaitingForThumbnailImg","isEditElementsExist","isRetryElementExist","templateHtml","showThumbnails","serverScale","cacheThumbnailPlaceholders","notAvailableUrl","waitingUrl","updatedImg","displayWaitingImg","waitingImgPlacement","maybeScalePlaceholderViaCss","show","generateNewPreview","getThumbnail","qqThumbnailId","maybeSetDisplayNotAvailableImg","generateNextQueuedPreview","queuedThumbRequest","update","processUpdateQueuedPreviewRequest","processNewQueuedPreviewRequest","getCancel","getTemplateEl","getContinue","getDialog","getDelete","getDropProcessing","getEditIcon","getPause","getProgress","getRetry","getSpinner","cssClass","previewing","notAvailableImgPlacement","parseAndGetTemplate","scriptEl","scriptHtml","fileListNode","tempTemplateEl","fileListHtml","defaultButton","dropTextEl","uploaderEl","fileTemplate","prependFile","parentEl","beforeEl","optFileOrBlob","relatedThumbnailId","useCachedPreview","showWaitingImg","setProgressBarWidth","percent","bar","progressBarSelector","targetThumbnailId","cachedThumbnailId","targetThumbnail","cachedThumbnail","hideTotalProgress","cantRenderEl","prependInfo","hideForever","batch","fileEl","fileNameEl","thumb","waitingImg","currentNode","getFileList","filenameEl","isFileName","icon","isEditIcon","isEditInput","isCancel","allowContinueButton","isPause","isContinueButton","isDeleteButton","isRetry","textEl","dialog","messageEl","inputEl","cancelBtn","okBtn","closeHandler","cancelClickHandler","okClickHandler","close","showModal","UiEventHandler","s","protectedApi","eventType","attachTo","onHandled","srcElement","getFileIdFromItem","qqFileId","getDisposeSupport","inheritedInternalApi","buttonHandlers","examineEvent","buttonType","firstLetterCapButtonType","handleFilenameEdit","FilenameEditHandler","handleInputFocus","getFilenameSansExtension","filenameSansExt","getOriginalExtension","origName","handleNameUpdate","newFilenameInputEl","origExtension","registerInputBlurHandler","registerInputEnterKeyHandler","keyCode","which","focusInput","focus"],"mappings":"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","file":"jquery.fine-uploader.js","sourcesContent":[null,"/*globals jQuery, qq*/\n(function($) {\n \"use strict\";\n var $el,\n pluginOptions = [\"uploaderType\", \"endpointType\"];\n\n function init(options) {\n var xformedOpts = transformVariables(options || {}),\n newUploaderInstance = getNewUploaderInstance(xformedOpts);\n\n uploader(newUploaderInstance);\n addCallbacks(xformedOpts, newUploaderInstance);\n\n return $el;\n }\n\n function getNewUploaderInstance(params) {\n var uploaderType = pluginOption(\"uploaderType\"),\n namespace = pluginOption(\"endpointType\");\n\n // If the integrator has defined a specific type of uploader to load, use that, otherwise assume `qq.FineUploader`\n if (uploaderType) {\n // We can determine the correct constructor function to invoke by combining \"FineUploader\"\n // with the upper camel cased `uploaderType` value.\n uploaderType = uploaderType.charAt(0).toUpperCase() + uploaderType.slice(1).toLowerCase();\n\n if (namespace) {\n return new qq[namespace][\"FineUploader\" + uploaderType](params);\n }\n\n return new qq[\"FineUploader\" + uploaderType](params);\n }\n else {\n if (namespace) {\n return new qq[namespace].FineUploader(params);\n }\n\n return new qq.FineUploader(params);\n }\n }\n\n function dataStore(key, val) {\n var data = $el.data(\"fineuploader\");\n\n if (val) {\n if (data === undefined) {\n data = {};\n }\n data[key] = val;\n $el.data(\"fineuploader\", data);\n }\n else {\n if (data === undefined) {\n return null;\n }\n return data[key];\n }\n }\n\n //the underlying Fine Uploader instance is stored in jQuery's data stored, associated with the element\n // tied to this instance of the plug-in\n function uploader(instanceToStore) {\n return dataStore(\"uploader\", instanceToStore);\n }\n\n function pluginOption(option, optionVal) {\n return dataStore(option, optionVal);\n }\n\n // Implement all callbacks defined in Fine Uploader as functions that trigger appropriately names events and\n // return the result of executing the bound handler back to Fine Uploader\n function addCallbacks(transformedOpts, newUploaderInstance) {\n var callbacks = transformedOpts.callbacks = {};\n\n $.each(newUploaderInstance._options.callbacks, function(prop, nonJqueryCallback) {\n var name, callbackEventTarget;\n\n name = /^on(\\w+)/.exec(prop)[1];\n name = name.substring(0, 1).toLowerCase() + name.substring(1);\n callbackEventTarget = $el;\n\n callbacks[prop] = function() {\n var originalArgs = Array.prototype.slice.call(arguments),\n transformedArgs = [],\n nonJqueryCallbackRetVal, jqueryEventCallbackRetVal;\n\n $.each(originalArgs, function(idx, arg) {\n transformedArgs.push(maybeWrapInJquery(arg));\n });\n\n nonJqueryCallbackRetVal = nonJqueryCallback.apply(this, originalArgs);\n\n try {\n jqueryEventCallbackRetVal = callbackEventTarget.triggerHandler(name, transformedArgs);\n }\n catch (error) {\n qq.log(\"Caught error in Fine Uploader jQuery event handler: \" + error.message, \"error\");\n }\n\n /*jshint -W116*/\n if (nonJqueryCallbackRetVal != null) {\n return nonJqueryCallbackRetVal;\n }\n return jqueryEventCallbackRetVal;\n };\n });\n\n newUploaderInstance._options.callbacks = callbacks;\n }\n\n //transform jQuery objects into HTMLElements, and pass along all other option properties\n function transformVariables(source, dest) {\n var xformed, arrayVals;\n\n if (dest === undefined) {\n if (source.uploaderType !== \"basic\") {\n xformed = { element: $el[0] };\n }\n else {\n xformed = {};\n }\n }\n else {\n xformed = dest;\n }\n\n $.each(source, function(prop, val) {\n if ($.inArray(prop, pluginOptions) >= 0) {\n pluginOption(prop, val);\n }\n else if (val instanceof $) {\n xformed[prop] = val[0];\n }\n else if ($.isPlainObject(val)) {\n xformed[prop] = {};\n transformVariables(val, xformed[prop]);\n }\n else if ($.isArray(val)) {\n arrayVals = [];\n $.each(val, function(idx, arrayVal) {\n var arrayObjDest = {};\n\n if (arrayVal instanceof $) {\n $.merge(arrayVals, arrayVal);\n }\n else if ($.isPlainObject(arrayVal)) {\n transformVariables(arrayVal, arrayObjDest);\n arrayVals.push(arrayObjDest);\n }\n else {\n arrayVals.push(arrayVal);\n }\n });\n xformed[prop] = arrayVals;\n }\n else {\n xformed[prop] = val;\n }\n });\n\n if (dest === undefined) {\n return xformed;\n }\n }\n\n function isValidCommand(command) {\n return $.type(command) === \"string\" &&\n !command.match(/^_/) && //enforce private methods convention\n uploader()[command] !== undefined;\n }\n\n // Assuming we have already verified that this is a valid command, call the associated function in the underlying\n // Fine Uploader instance (passing along the arguments from the caller) and return the result of the call back to the caller\n function delegateCommand(command) {\n var xformedArgs = [],\n origArgs = Array.prototype.slice.call(arguments, 1),\n retVal;\n\n transformVariables(origArgs, xformedArgs);\n\n retVal = uploader()[command].apply(uploader(), xformedArgs);\n\n return maybeWrapInJquery(retVal);\n }\n\n // If the value is an `HTMLElement` or `HTMLDocument`, wrap it in a `jQuery` object\n function maybeWrapInJquery(val) {\n var transformedVal = val;\n\n // If the command is returning an `HTMLElement` or `HTMLDocument`, wrap it in a `jQuery` object\n /*jshint -W116*/\n if (val != null && typeof val === \"object\" &&\n (val.nodeType === 1 || val.nodeType === 9) && val.cloneNode) {\n\n transformedVal = $(val);\n }\n\n return transformedVal;\n }\n\n $.fn.fineUploader = function(optionsOrCommand) {\n var self = this, selfArgs = arguments, retVals = [];\n\n this.each(function(index, el) {\n $el = $(el);\n\n if (uploader() && isValidCommand(optionsOrCommand)) {\n retVals.push(delegateCommand.apply(self, selfArgs));\n\n if (self.length === 1) {\n return false;\n }\n }\n else if (typeof optionsOrCommand === \"object\" || !optionsOrCommand) {\n init.apply(self, selfArgs);\n }\n else {\n $.error(\"Method \" + optionsOrCommand + \" does not exist on jQuery.fineUploader\");\n }\n });\n\n if (retVals.length === 1) {\n return retVals[0];\n }\n else if (retVals.length > 1) {\n return retVals;\n }\n\n return this;\n };\n\n}(jQuery));\n","/*globals jQuery, qq*/\n(function($) {\n \"use strict\";\n var rootDataKey = \"fineUploaderDnd\",\n $el;\n\n function init(options) {\n if (!options) {\n options = {};\n }\n\n options.dropZoneElements = [$el];\n var xformedOpts = transformVariables(options);\n addCallbacks(xformedOpts);\n dnd(new qq.DragAndDrop(xformedOpts));\n\n return $el;\n }\n\n function dataStore(key, val) {\n var data = $el.data(rootDataKey);\n\n if (val) {\n if (data === undefined) {\n data = {};\n }\n data[key] = val;\n $el.data(rootDataKey, data);\n }\n else {\n if (data === undefined) {\n return null;\n }\n return data[key];\n }\n }\n\n function dnd(instanceToStore) {\n return dataStore(\"dndInstance\", instanceToStore);\n }\n\n function addCallbacks(transformedOpts) {\n var callbacks = transformedOpts.callbacks = {};\n\n $.each(new qq.DragAndDrop.callbacks(), function(prop, func) {\n var name = prop,\n $callbackEl;\n\n $callbackEl = $el;\n\n callbacks[prop] = function() {\n var args = Array.prototype.slice.call(arguments),\n jqueryHandlerResult = $callbackEl.triggerHandler(name, args);\n\n return jqueryHandlerResult;\n };\n });\n }\n\n //transform jQuery objects into HTMLElements, and pass along all other option properties\n function transformVariables(source, dest) {\n var xformed, arrayVals;\n\n if (dest === undefined) {\n xformed = {};\n }\n else {\n xformed = dest;\n }\n\n $.each(source, function(prop, val) {\n if (val instanceof $) {\n xformed[prop] = val[0];\n }\n else if ($.isPlainObject(val)) {\n xformed[prop] = {};\n transformVariables(val, xformed[prop]);\n }\n else if ($.isArray(val)) {\n arrayVals = [];\n $.each(val, function(idx, arrayVal) {\n if (arrayVal instanceof $) {\n $.merge(arrayVals, arrayVal);\n }\n else {\n arrayVals.push(arrayVal);\n }\n });\n xformed[prop] = arrayVals;\n }\n else {\n xformed[prop] = val;\n }\n });\n\n if (dest === undefined) {\n return xformed;\n }\n }\n\n function isValidCommand(command) {\n return $.type(command) === \"string\" &&\n command === \"dispose\" &&\n dnd()[command] !== undefined;\n }\n\n function delegateCommand(command) {\n var xformedArgs = [], origArgs = Array.prototype.slice.call(arguments, 1);\n transformVariables(origArgs, xformedArgs);\n return dnd()[command].apply(dnd(), xformedArgs);\n }\n\n $.fn.fineUploaderDnd = function(optionsOrCommand) {\n var self = this, selfArgs = arguments, retVals = [];\n\n this.each(function(index, el) {\n $el = $(el);\n\n if (dnd() && isValidCommand(optionsOrCommand)) {\n retVals.push(delegateCommand.apply(self, selfArgs));\n\n if (self.length === 1) {\n return false;\n }\n }\n else if (typeof optionsOrCommand === \"object\" || !optionsOrCommand) {\n init.apply(self, selfArgs);\n }\n else {\n $.error(\"Method \" + optionsOrCommand + \" does not exist in Fine Uploader's DnD module.\");\n }\n });\n\n if (retVals.length === 1) {\n return retVals[0];\n }\n else if (retVals.length > 1) {\n return retVals;\n }\n\n return this;\n };\n\n}(jQuery));\n","/*globals window, navigator, document, FormData, File, HTMLInputElement, XMLHttpRequest, Blob, Storage, ActiveXObject */\n/* jshint -W079 */\nvar qq = function(element) {\n \"use strict\";\n\n return {\n hide: function() {\n element.style.display = \"none\";\n return this;\n },\n\n /** Returns the function which detaches attached event */\n attach: function(type, fn) {\n if (element.addEventListener) {\n element.addEventListener(type, fn, false);\n } else if (element.attachEvent) {\n element.attachEvent(\"on\" + type, fn);\n }\n return function() {\n qq(element).detach(type, fn);\n };\n },\n\n detach: function(type, fn) {\n if (element.removeEventListener) {\n element.removeEventListener(type, fn, false);\n } else if (element.attachEvent) {\n element.detachEvent(\"on\" + type, fn);\n }\n return this;\n },\n\n contains: function(descendant) {\n // The [W3C spec](http://www.w3.org/TR/domcore/#dom-node-contains)\n // says a `null` (or ostensibly `undefined`) parameter\n // passed into `Node.contains` should result in a false return value.\n // IE7 throws an exception if the parameter is `undefined` though.\n if (!descendant) {\n return false;\n }\n\n // compareposition returns false in this case\n if (element === descendant) {\n return true;\n }\n\n if (element.contains) {\n return element.contains(descendant);\n } else {\n /*jslint bitwise: true*/\n return !!(descendant.compareDocumentPosition(element) & 8);\n }\n },\n\n /**\n * Insert this element before elementB.\n */\n insertBefore: function(elementB) {\n elementB.parentNode.insertBefore(element, elementB);\n return this;\n },\n\n remove: function() {\n element.parentNode.removeChild(element);\n return this;\n },\n\n /**\n * Sets styles for an element.\n * Fixes opacity in IE6-8.\n */\n css: function(styles) {\n /*jshint eqnull: true*/\n if (element.style == null) {\n throw new qq.Error(\"Can't apply style to node as it is not on the HTMLElement prototype chain!\");\n }\n\n /*jshint -W116*/\n if (styles.opacity != null) {\n if (typeof element.style.opacity !== \"string\" && typeof (element.filters) !== \"undefined\") {\n styles.filter = \"alpha(opacity=\" + Math.round(100 * styles.opacity) + \")\";\n }\n }\n qq.extend(element.style, styles);\n\n return this;\n },\n\n hasClass: function(name, considerParent) {\n var re = new RegExp(\"(^| )\" + name + \"( |$)\");\n return re.test(element.className) || !!(considerParent && re.test(element.parentNode.className));\n },\n\n addClass: function(name) {\n if (!qq(element).hasClass(name)) {\n element.className += \" \" + name;\n }\n return this;\n },\n\n removeClass: function(name) {\n var re = new RegExp(\"(^| )\" + name + \"( |$)\");\n element.className = element.className.replace(re, \" \").replace(/^\\s+|\\s+$/g, \"\");\n return this;\n },\n\n getByClass: function(className, first) {\n var candidates,\n result = [];\n\n if (first && element.querySelector) {\n return element.querySelector(\".\" + className);\n }\n else if (element.querySelectorAll) {\n return element.querySelectorAll(\".\" + className);\n }\n\n candidates = element.getElementsByTagName(\"*\");\n\n qq.each(candidates, function(idx, val) {\n if (qq(val).hasClass(className)) {\n result.push(val);\n }\n });\n return first ? result[0] : result;\n },\n\n getFirstByClass: function(className) {\n return qq(element).getByClass(className, true);\n },\n\n children: function() {\n var children = [],\n child = element.firstChild;\n\n while (child) {\n if (child.nodeType === 1) {\n children.push(child);\n }\n child = child.nextSibling;\n }\n\n return children;\n },\n\n setText: function(text) {\n element.innerText = text;\n element.textContent = text;\n return this;\n },\n\n clearText: function() {\n return qq(element).setText(\"\");\n },\n\n // Returns true if the attribute exists on the element\n // AND the value of the attribute is NOT \"false\" (case-insensitive)\n hasAttribute: function(attrName) {\n var attrVal;\n\n if (element.hasAttribute) {\n\n if (!element.hasAttribute(attrName)) {\n return false;\n }\n\n /*jshint -W116*/\n return (/^false$/i).exec(element.getAttribute(attrName)) == null;\n }\n else {\n attrVal = element[attrName];\n\n if (attrVal === undefined) {\n return false;\n }\n\n /*jshint -W116*/\n return (/^false$/i).exec(attrVal) == null;\n }\n }\n };\n};\n\n(function() {\n \"use strict\";\n\n qq.canvasToBlob = function(canvas, mime, quality) {\n return qq.dataUriToBlob(canvas.toDataURL(mime, quality));\n };\n\n qq.dataUriToBlob = function(dataUri) {\n var arrayBuffer, byteString,\n createBlob = function(data, mime) {\n var BlobBuilder = window.BlobBuilder ||\n window.WebKitBlobBuilder ||\n window.MozBlobBuilder ||\n window.MSBlobBuilder,\n blobBuilder = BlobBuilder && new BlobBuilder();\n\n if (blobBuilder) {\n blobBuilder.append(data);\n return blobBuilder.getBlob(mime);\n }\n else {\n return new Blob([data], {type: mime});\n }\n },\n intArray, mimeString;\n\n // convert base64 to raw binary data held in a string\n if (dataUri.split(\",\")[0].indexOf(\"base64\") >= 0) {\n byteString = atob(dataUri.split(\",\")[1]);\n }\n else {\n byteString = decodeURI(dataUri.split(\",\")[1]);\n }\n\n // extract the MIME\n mimeString = dataUri.split(\",\")[0]\n .split(\":\")[1]\n .split(\";\")[0];\n\n // write the bytes of the binary string to an ArrayBuffer\n arrayBuffer = new ArrayBuffer(byteString.length);\n intArray = new Uint8Array(arrayBuffer);\n qq.each(byteString, function(idx, character) {\n intArray[idx] = character.charCodeAt(0);\n });\n\n return createBlob(arrayBuffer, mimeString);\n };\n\n qq.log = function(message, level) {\n if (window.console) {\n if (!level || level === \"info\") {\n window.console.log(message);\n }\n else\n {\n if (window.console[level]) {\n window.console[level](message);\n }\n else {\n window.console.log(\"<\" + level + \"> \" + message);\n }\n }\n }\n };\n\n qq.isObject = function(variable) {\n return variable && !variable.nodeType && Object.prototype.toString.call(variable) === \"[object Object]\";\n };\n\n qq.isFunction = function(variable) {\n return typeof (variable) === \"function\";\n };\n\n /**\n * Check the type of a value. Is it an \"array\"?\n *\n * @param value value to test.\n * @returns true if the value is an array or associated with an `ArrayBuffer`\n */\n qq.isArray = function(value) {\n return Object.prototype.toString.call(value) === \"[object Array]\" ||\n (value && window.ArrayBuffer && value.buffer && value.buffer.constructor === ArrayBuffer);\n };\n\n // Looks for an object on a `DataTransfer` object that is associated with drop events when utilizing the Filesystem API.\n qq.isItemList = function(maybeItemList) {\n return Object.prototype.toString.call(maybeItemList) === \"[object DataTransferItemList]\";\n };\n\n // Looks for an object on a `NodeList` or an `HTMLCollection`|`HTMLFormElement`|`HTMLSelectElement`\n // object that is associated with collections of Nodes.\n qq.isNodeList = function(maybeNodeList) {\n return Object.prototype.toString.call(maybeNodeList) === \"[object NodeList]\" ||\n // If `HTMLCollection` is the actual type of the object, we must determine this\n // by checking for expected properties/methods on the object\n (maybeNodeList.item && maybeNodeList.namedItem);\n };\n\n qq.isString = function(maybeString) {\n return Object.prototype.toString.call(maybeString) === \"[object String]\";\n };\n\n qq.trimStr = function(string) {\n if (String.prototype.trim) {\n return string.trim();\n }\n\n return string.replace(/^\\s+|\\s+$/g, \"\");\n };\n\n /**\n * @param str String to format.\n * @returns {string} A string, swapping argument values with the associated occurrence of {} in the passed string.\n */\n qq.format = function(str) {\n\n var args = Array.prototype.slice.call(arguments, 1),\n newStr = str,\n nextIdxToReplace = newStr.indexOf(\"{}\");\n\n qq.each(args, function(idx, val) {\n var strBefore = newStr.substring(0, nextIdxToReplace),\n strAfter = newStr.substring(nextIdxToReplace + 2);\n\n newStr = strBefore + val + strAfter;\n nextIdxToReplace = newStr.indexOf(\"{}\", nextIdxToReplace + val.length);\n\n // End the loop if we have run out of tokens (when the arguments exceed the # of tokens)\n if (nextIdxToReplace < 0) {\n return false;\n }\n });\n\n return newStr;\n };\n\n qq.isFile = function(maybeFile) {\n return window.File && Object.prototype.toString.call(maybeFile) === \"[object File]\";\n };\n\n qq.isFileList = function(maybeFileList) {\n return window.FileList && Object.prototype.toString.call(maybeFileList) === \"[object FileList]\";\n };\n\n qq.isFileOrInput = function(maybeFileOrInput) {\n return qq.isFile(maybeFileOrInput) || qq.isInput(maybeFileOrInput);\n };\n\n qq.isInput = function(maybeInput, notFile) {\n var evaluateType = function(type) {\n var normalizedType = type.toLowerCase();\n\n if (notFile) {\n return normalizedType !== \"file\";\n }\n\n return normalizedType === \"file\";\n };\n\n if (window.HTMLInputElement) {\n if (Object.prototype.toString.call(maybeInput) === \"[object HTMLInputElement]\") {\n if (maybeInput.type && evaluateType(maybeInput.type)) {\n return true;\n }\n }\n }\n if (maybeInput.tagName) {\n if (maybeInput.tagName.toLowerCase() === \"input\") {\n if (maybeInput.type && evaluateType(maybeInput.type)) {\n return true;\n }\n }\n }\n\n return false;\n };\n\n qq.isBlob = function(maybeBlob) {\n if (window.Blob && Object.prototype.toString.call(maybeBlob) === \"[object Blob]\") {\n return true;\n }\n };\n\n qq.isXhrUploadSupported = function() {\n var input = document.createElement(\"input\");\n input.type = \"file\";\n\n return (\n input.multiple !== undefined &&\n typeof File !== \"undefined\" &&\n typeof FormData !== \"undefined\" &&\n typeof (qq.createXhrInstance()).upload !== \"undefined\");\n };\n\n // Fall back to ActiveX is native XHR is disabled (possible in any version of IE).\n qq.createXhrInstance = function() {\n if (window.XMLHttpRequest) {\n return new XMLHttpRequest();\n }\n\n try {\n return new ActiveXObject(\"MSXML2.XMLHTTP.3.0\");\n }\n catch (error) {\n qq.log(\"Neither XHR or ActiveX are supported!\", \"error\");\n return null;\n }\n };\n\n qq.isFolderDropSupported = function(dataTransfer) {\n return dataTransfer.items &&\n dataTransfer.items.length > 0 &&\n dataTransfer.items[0].webkitGetAsEntry;\n };\n\n qq.isFileChunkingSupported = function() {\n return !qq.androidStock() && //Android's stock browser cannot upload Blobs correctly\n qq.isXhrUploadSupported() &&\n (File.prototype.slice !== undefined || File.prototype.webkitSlice !== undefined || File.prototype.mozSlice !== undefined);\n };\n\n qq.sliceBlob = function(fileOrBlob, start, end) {\n var slicer = fileOrBlob.slice || fileOrBlob.mozSlice || fileOrBlob.webkitSlice;\n\n return slicer.call(fileOrBlob, start, end);\n };\n\n qq.arrayBufferToHex = function(buffer) {\n var bytesAsHex = \"\",\n bytes = new Uint8Array(buffer);\n\n qq.each(bytes, function(idx, byt) {\n var byteAsHexStr = byt.toString(16);\n\n if (byteAsHexStr.length < 2) {\n byteAsHexStr = \"0\" + byteAsHexStr;\n }\n\n bytesAsHex += byteAsHexStr;\n });\n\n return bytesAsHex;\n };\n\n qq.readBlobToHex = function(blob, startOffset, length) {\n var initialBlob = qq.sliceBlob(blob, startOffset, startOffset + length),\n fileReader = new FileReader(),\n promise = new qq.Promise();\n\n fileReader.onload = function() {\n promise.success(qq.arrayBufferToHex(fileReader.result));\n };\n\n fileReader.onerror = promise.failure;\n\n fileReader.readAsArrayBuffer(initialBlob);\n\n return promise;\n };\n\n qq.extend = function(first, second, extendNested) {\n qq.each(second, function(prop, val) {\n if (extendNested && qq.isObject(val)) {\n if (first[prop] === undefined) {\n first[prop] = {};\n }\n qq.extend(first[prop], val, true);\n }\n else {\n first[prop] = val;\n }\n });\n\n return first;\n };\n\n /**\n * Allow properties in one object to override properties in another,\n * keeping track of the original values from the target object.\n *\n * Note that the pre-overriden properties to be overriden by the source will be passed into the `sourceFn` when it is invoked.\n *\n * @param target Update properties in this object from some source\n * @param sourceFn A function that, when invoked, will return properties that will replace properties with the same name in the target.\n * @returns {object} The target object\n */\n qq.override = function(target, sourceFn) {\n var super_ = {},\n source = sourceFn(super_);\n\n qq.each(source, function(srcPropName, srcPropVal) {\n if (target[srcPropName] !== undefined) {\n super_[srcPropName] = target[srcPropName];\n }\n\n target[srcPropName] = srcPropVal;\n });\n\n return target;\n };\n\n /**\n * Searches for a given element (elt) in the array, returns -1 if it is not present.\n */\n qq.indexOf = function(arr, elt, from) {\n if (arr.indexOf) {\n return arr.indexOf(elt, from);\n }\n\n from = from || 0;\n var len = arr.length;\n\n if (from < 0) {\n from += len;\n }\n\n for (; from < len; from += 1) {\n if (arr.hasOwnProperty(from) && arr[from] === elt) {\n return from;\n }\n }\n return -1;\n };\n\n //this is a version 4 UUID\n qq.getUniqueId = function() {\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, function(c) {\n /*jslint eqeq: true, bitwise: true*/\n var r = Math.random() * 16 | 0, v = c == \"x\" ? r : (r & 0x3 | 0x8);\n return v.toString(16);\n });\n };\n\n //\n // Browsers and platforms detection\n qq.ie = function() {\n return navigator.userAgent.indexOf(\"MSIE\") !== -1 ||\n navigator.userAgent.indexOf(\"Trident\") !== -1;\n };\n\n qq.ie7 = function() {\n return navigator.userAgent.indexOf(\"MSIE 7\") !== -1;\n };\n\n qq.ie8 = function() {\n return navigator.userAgent.indexOf(\"MSIE 8\") !== -1;\n };\n\n qq.ie10 = function() {\n return navigator.userAgent.indexOf(\"MSIE 10\") !== -1;\n };\n\n qq.ie11 = function() {\n return qq.ie() && navigator.userAgent.indexOf(\"rv:11\") !== -1;\n };\n\n qq.edge = function() {\n return navigator.userAgent.indexOf(\"Edge\") >= 0;\n };\n\n qq.safari = function() {\n return navigator.vendor !== undefined && navigator.vendor.indexOf(\"Apple\") !== -1;\n };\n\n qq.chrome = function() {\n return navigator.vendor !== undefined && navigator.vendor.indexOf(\"Google\") !== -1;\n };\n\n qq.opera = function() {\n return navigator.vendor !== undefined && navigator.vendor.indexOf(\"Opera\") !== -1;\n };\n\n qq.firefox = function() {\n return (!qq.edge() && !qq.ie11() && navigator.userAgent.indexOf(\"Mozilla\") !== -1 && navigator.vendor !== undefined && navigator.vendor === \"\");\n };\n\n qq.windows = function() {\n return navigator.platform === \"Win32\";\n };\n\n qq.android = function() {\n return navigator.userAgent.toLowerCase().indexOf(\"android\") !== -1;\n };\n\n // We need to identify the Android stock browser via the UA string to work around various bugs in this browser,\n // such as the one that prevents a `Blob` from being uploaded.\n qq.androidStock = function() {\n return qq.android() && navigator.userAgent.toLowerCase().indexOf(\"chrome\") < 0;\n };\n\n qq.ios6 = function() {\n return qq.ios() && navigator.userAgent.indexOf(\" OS 6_\") !== -1;\n };\n\n qq.ios7 = function() {\n return qq.ios() && navigator.userAgent.indexOf(\" OS 7_\") !== -1;\n };\n\n qq.ios8 = function() {\n return qq.ios() && navigator.userAgent.indexOf(\" OS 8_\") !== -1;\n };\n\n // iOS 8.0.0\n qq.ios800 = function() {\n return qq.ios() && navigator.userAgent.indexOf(\" OS 8_0 \") !== -1;\n };\n\n qq.ios = function() {\n /*jshint -W014 */\n return navigator.userAgent.indexOf(\"iPad\") !== -1\n || navigator.userAgent.indexOf(\"iPod\") !== -1\n || navigator.userAgent.indexOf(\"iPhone\") !== -1;\n };\n\n qq.iosChrome = function() {\n return qq.ios() && navigator.userAgent.indexOf(\"CriOS\") !== -1;\n };\n\n qq.iosSafari = function() {\n return qq.ios() && !qq.iosChrome() && navigator.userAgent.indexOf(\"Safari\") !== -1;\n };\n\n qq.iosSafariWebView = function() {\n return qq.ios() && !qq.iosChrome() && !qq.iosSafari();\n };\n\n //\n // Events\n\n qq.preventDefault = function(e) {\n if (e.preventDefault) {\n e.preventDefault();\n } else {\n e.returnValue = false;\n }\n };\n\n /**\n * Creates and returns element from html string\n * Uses innerHTML to create an element\n */\n qq.toElement = (function() {\n var div = document.createElement(\"div\");\n return function(html) {\n div.innerHTML = html;\n var element = div.firstChild;\n div.removeChild(element);\n return element;\n };\n }());\n\n //key and value are passed to callback for each entry in the iterable item\n qq.each = function(iterableItem, callback) {\n var keyOrIndex, retVal;\n\n if (iterableItem) {\n // Iterate through [`Storage`](http://www.w3.org/TR/webstorage/#the-storage-interface) items\n if (window.Storage && iterableItem.constructor === window.Storage) {\n for (keyOrIndex = 0; keyOrIndex < iterableItem.length; keyOrIndex++) {\n retVal = callback(iterableItem.key(keyOrIndex), iterableItem.getItem(iterableItem.key(keyOrIndex)));\n if (retVal === false) {\n break;\n }\n }\n }\n // `DataTransferItemList` & `NodeList` objects are array-like and should be treated as arrays\n // when iterating over items inside the object.\n else if (qq.isArray(iterableItem) || qq.isItemList(iterableItem) || qq.isNodeList(iterableItem)) {\n for (keyOrIndex = 0; keyOrIndex < iterableItem.length; keyOrIndex++) {\n retVal = callback(keyOrIndex, iterableItem[keyOrIndex]);\n if (retVal === false) {\n break;\n }\n }\n }\n else if (qq.isString(iterableItem)) {\n for (keyOrIndex = 0; keyOrIndex < iterableItem.length; keyOrIndex++) {\n retVal = callback(keyOrIndex, iterableItem.charAt(keyOrIndex));\n if (retVal === false) {\n break;\n }\n }\n }\n else {\n for (keyOrIndex in iterableItem) {\n if (Object.prototype.hasOwnProperty.call(iterableItem, keyOrIndex)) {\n retVal = callback(keyOrIndex, iterableItem[keyOrIndex]);\n if (retVal === false) {\n break;\n }\n }\n }\n }\n }\n };\n\n //include any args that should be passed to the new function after the context arg\n qq.bind = function(oldFunc, context) {\n if (qq.isFunction(oldFunc)) {\n var args = Array.prototype.slice.call(arguments, 2);\n\n return function() {\n var newArgs = qq.extend([], args);\n if (arguments.length) {\n newArgs = newArgs.concat(Array.prototype.slice.call(arguments));\n }\n return oldFunc.apply(context, newArgs);\n };\n }\n\n throw new Error(\"first parameter must be a function!\");\n };\n\n /**\n * obj2url() takes a json-object as argument and generates\n * a querystring. pretty much like jQuery.param()\n *\n * how to use:\n *\n * `qq.obj2url({a:'b',c:'d'},'http://any.url/upload?otherParam=value');`\n *\n * will result in:\n *\n * `http://any.url/upload?otherParam=value&a=b&c=d`\n *\n * @param Object JSON-Object\n * @param String current querystring-part\n * @return String encoded querystring\n */\n qq.obj2url = function(obj, temp, prefixDone) {\n /*jshint laxbreak: true*/\n var uristrings = [],\n prefix = \"&\",\n add = function(nextObj, i) {\n var nextTemp = temp\n ? (/\\[\\]$/.test(temp)) // prevent double-encoding\n ? temp\n : temp + \"[\" + i + \"]\"\n : i;\n if ((nextTemp !== \"undefined\") && (i !== \"undefined\")) {\n uristrings.push(\n (typeof nextObj === \"object\")\n ? qq.obj2url(nextObj, nextTemp, true)\n : (Object.prototype.toString.call(nextObj) === \"[object Function]\")\n ? encodeURIComponent(nextTemp) + \"=\" + encodeURIComponent(nextObj())\n : encodeURIComponent(nextTemp) + \"=\" + encodeURIComponent(nextObj)\n );\n }\n };\n\n if (!prefixDone && temp) {\n prefix = (/\\?/.test(temp)) ? (/\\?$/.test(temp)) ? \"\" : \"&\" : \"?\";\n uristrings.push(temp);\n uristrings.push(qq.obj2url(obj));\n } else if ((Object.prototype.toString.call(obj) === \"[object Array]\") && (typeof obj !== \"undefined\")) {\n qq.each(obj, function(idx, val) {\n add(val, idx);\n });\n } else if ((typeof obj !== \"undefined\") && (obj !== null) && (typeof obj === \"object\")) {\n qq.each(obj, function(prop, val) {\n add(val, prop);\n });\n } else {\n uristrings.push(encodeURIComponent(temp) + \"=\" + encodeURIComponent(obj));\n }\n\n if (temp) {\n return uristrings.join(prefix);\n } else {\n return uristrings.join(prefix)\n .replace(/^&/, \"\")\n .replace(/%20/g, \"+\");\n }\n };\n\n qq.obj2FormData = function(obj, formData, arrayKeyName) {\n if (!formData) {\n formData = new FormData();\n }\n\n qq.each(obj, function(key, val) {\n key = arrayKeyName ? arrayKeyName + \"[\" + key + \"]\" : key;\n\n if (qq.isObject(val)) {\n qq.obj2FormData(val, formData, key);\n }\n else if (qq.isFunction(val)) {\n formData.append(key, val());\n }\n else {\n formData.append(key, val);\n }\n });\n\n return formData;\n };\n\n qq.obj2Inputs = function(obj, form) {\n var input;\n\n if (!form) {\n form = document.createElement(\"form\");\n }\n\n qq.obj2FormData(obj, {\n append: function(key, val) {\n input = document.createElement(\"input\");\n input.setAttribute(\"name\", key);\n input.setAttribute(\"value\", val);\n form.appendChild(input);\n }\n });\n\n return form;\n };\n\n /**\n * Not recommended for use outside of Fine Uploader since this falls back to an unchecked eval if JSON.parse is not\n * implemented. For a more secure JSON.parse polyfill, use Douglas Crockford's json2.js.\n */\n qq.parseJson = function(json) {\n /*jshint evil: true*/\n if (window.JSON && qq.isFunction(JSON.parse)) {\n return JSON.parse(json);\n } else {\n return eval(\"(\" + json + \")\");\n }\n };\n\n /**\n * Retrieve the extension of a file, if it exists.\n *\n * @param filename\n * @returns {string || undefined}\n */\n qq.getExtension = function(filename) {\n var extIdx = filename.lastIndexOf(\".\") + 1;\n\n if (extIdx > 0) {\n return filename.substr(extIdx, filename.length - extIdx);\n }\n };\n\n qq.getFilename = function(blobOrFileInput) {\n /*jslint regexp: true*/\n\n if (qq.isInput(blobOrFileInput)) {\n // get input value and remove path to normalize\n return blobOrFileInput.value.replace(/.*(\\/|\\\\)/, \"\");\n }\n else if (qq.isFile(blobOrFileInput)) {\n if (blobOrFileInput.fileName !== null && blobOrFileInput.fileName !== undefined) {\n return blobOrFileInput.fileName;\n }\n }\n\n return blobOrFileInput.name;\n };\n\n /**\n * A generic module which supports object disposing in dispose() method.\n * */\n qq.DisposeSupport = function() {\n var disposers = [];\n\n return {\n /** Run all registered disposers */\n dispose: function() {\n var disposer;\n do {\n disposer = disposers.shift();\n if (disposer) {\n disposer();\n }\n }\n while (disposer);\n },\n\n /** Attach event handler and register de-attacher as a disposer */\n attach: function() {\n var args = arguments;\n /*jslint undef:true*/\n this.addDisposer(qq(args[0]).attach.apply(this, Array.prototype.slice.call(arguments, 1)));\n },\n\n /** Add disposer to the collection */\n addDisposer: function(disposeFunction) {\n disposers.push(disposeFunction);\n }\n };\n };\n}());\n","/* globals define, module, global, qq */\n(function() {\n \"use strict\";\n if (typeof define === \"function\" && define.amd) {\n define(function() {\n return qq;\n });\n }\n else if (typeof module !== \"undefined\" && module.exports) {\n module.exports = qq;\n }\n else {\n global.qq = qq;\n }\n}());\n","/* globals qq */\n/**\n * Fine Uploader top-level Error container. Inherits from `Error`.\n */\n(function() {\n \"use strict\";\n\n qq.Error = function(message) {\n this.message = \"[Fine Uploader \" + qq.version + \"] \" + message;\n };\n\n qq.Error.prototype = new Error();\n}());\n","/*global qq */\nqq.version = \"5.12.0\";\n","/* globals qq */\nqq.supportedFeatures = (function() {\n \"use strict\";\n\n var supportsUploading,\n supportsUploadingBlobs,\n supportsFileDrop,\n supportsAjaxFileUploading,\n supportsFolderDrop,\n supportsChunking,\n supportsResume,\n supportsUploadViaPaste,\n supportsUploadCors,\n supportsDeleteFileXdr,\n supportsDeleteFileCorsXhr,\n supportsDeleteFileCors,\n supportsFolderSelection,\n supportsImagePreviews,\n supportsUploadProgress;\n\n function testSupportsFileInputElement() {\n var supported = true,\n tempInput;\n\n try {\n tempInput = document.createElement(\"input\");\n tempInput.type = \"file\";\n qq(tempInput).hide();\n\n if (tempInput.disabled) {\n supported = false;\n }\n }\n catch (ex) {\n supported = false;\n }\n\n return supported;\n }\n\n //only way to test for Filesystem API support since webkit does not expose the DataTransfer interface\n function isChrome21OrHigher() {\n return (qq.chrome() || qq.opera()) &&\n navigator.userAgent.match(/Chrome\\/[2][1-9]|Chrome\\/[3-9][0-9]/) !== undefined;\n }\n\n //only way to test for complete Clipboard API support at this time\n function isChrome14OrHigher() {\n return (qq.chrome() || qq.opera()) &&\n navigator.userAgent.match(/Chrome\\/[1][4-9]|Chrome\\/[2-9][0-9]/) !== undefined;\n }\n\n //Ensure we can send cross-origin `XMLHttpRequest`s\n function isCrossOriginXhrSupported() {\n if (window.XMLHttpRequest) {\n var xhr = qq.createXhrInstance();\n\n //Commonly accepted test for XHR CORS support.\n return xhr.withCredentials !== undefined;\n }\n\n return false;\n }\n\n //Test for (terrible) cross-origin ajax transport fallback for IE9 and IE8\n function isXdrSupported() {\n return window.XDomainRequest !== undefined;\n }\n\n // CORS Ajax requests are supported if it is either possible to send credentialed `XMLHttpRequest`s,\n // or if `XDomainRequest` is an available alternative.\n function isCrossOriginAjaxSupported() {\n if (isCrossOriginXhrSupported()) {\n return true;\n }\n\n return isXdrSupported();\n }\n\n function isFolderSelectionSupported() {\n // We know that folder selection is only supported in Chrome via this proprietary attribute for now\n return document.createElement(\"input\").webkitdirectory !== undefined;\n }\n\n function isLocalStorageSupported() {\n try {\n return !!window.localStorage &&\n // unpatched versions of IE10/11 have buggy impls of localStorage where setItem is a string\n qq.isFunction(window.localStorage.setItem);\n }\n catch (error) {\n // probably caught a security exception, so no localStorage for you\n return false;\n }\n }\n\n function isDragAndDropSupported() {\n var span = document.createElement(\"span\");\n\n return (\"draggable\" in span || (\"ondragstart\" in span && \"ondrop\" in span)) &&\n !qq.android() && !qq.ios();\n }\n\n supportsUploading = testSupportsFileInputElement();\n\n supportsAjaxFileUploading = supportsUploading && qq.isXhrUploadSupported();\n\n supportsUploadingBlobs = supportsAjaxFileUploading && !qq.androidStock();\n\n supportsFileDrop = supportsAjaxFileUploading && isDragAndDropSupported();\n\n supportsFolderDrop = supportsFileDrop && isChrome21OrHigher();\n\n supportsChunking = supportsAjaxFileUploading && qq.isFileChunkingSupported();\n\n supportsResume = supportsAjaxFileUploading && supportsChunking && isLocalStorageSupported();\n\n supportsUploadViaPaste = supportsAjaxFileUploading && isChrome14OrHigher();\n\n supportsUploadCors = supportsUploading && (window.postMessage !== undefined || supportsAjaxFileUploading);\n\n supportsDeleteFileCorsXhr = isCrossOriginXhrSupported();\n\n supportsDeleteFileXdr = isXdrSupported();\n\n supportsDeleteFileCors = isCrossOriginAjaxSupported();\n\n supportsFolderSelection = isFolderSelectionSupported();\n\n supportsImagePreviews = supportsAjaxFileUploading && window.FileReader !== undefined;\n\n supportsUploadProgress = (function() {\n if (supportsAjaxFileUploading) {\n return !qq.androidStock() && !qq.iosChrome();\n }\n return false;\n }());\n\n return {\n ajaxUploading: supportsAjaxFileUploading,\n blobUploading: supportsUploadingBlobs,\n canDetermineSize: supportsAjaxFileUploading,\n chunking: supportsChunking,\n deleteFileCors: supportsDeleteFileCors,\n deleteFileCorsXdr: supportsDeleteFileXdr, //NOTE: will also return true in IE10, where XDR is also supported\n deleteFileCorsXhr: supportsDeleteFileCorsXhr,\n dialogElement: !!window.HTMLDialogElement,\n fileDrop: supportsFileDrop,\n folderDrop: supportsFolderDrop,\n folderSelection: supportsFolderSelection,\n imagePreviews: supportsImagePreviews,\n imageValidation: supportsImagePreviews,\n itemSizeValidation: supportsAjaxFileUploading,\n pause: supportsChunking,\n progressBar: supportsUploadProgress,\n resume: supportsResume,\n scaling: supportsImagePreviews && supportsUploadingBlobs,\n tiffPreviews: qq.safari(), // Not the best solution, but simple and probably accurate enough (for now)\n unlimitedScaledImageSize: !qq.ios(), // false simply indicates that there is some known limit\n uploading: supportsUploading,\n uploadCors: supportsUploadCors,\n uploadCustomHeaders: supportsAjaxFileUploading,\n uploadNonMultipart: supportsAjaxFileUploading,\n uploadViaPaste: supportsUploadViaPaste\n };\n\n}());\n","/*globals qq*/\n\n// Is the passed object a promise instance?\nqq.isGenericPromise = function(maybePromise) {\n \"use strict\";\n return !!(maybePromise && maybePromise.then && qq.isFunction(maybePromise.then));\n};\n\nqq.Promise = function() {\n \"use strict\";\n\n var successArgs, failureArgs,\n successCallbacks = [],\n failureCallbacks = [],\n doneCallbacks = [],\n state = 0;\n\n qq.extend(this, {\n then: function(onSuccess, onFailure) {\n if (state === 0) {\n if (onSuccess) {\n successCallbacks.push(onSuccess);\n }\n if (onFailure) {\n failureCallbacks.push(onFailure);\n }\n }\n else if (state === -1) {\n onFailure && onFailure.apply(null, failureArgs);\n }\n else if (onSuccess) {\n onSuccess.apply(null, successArgs);\n }\n\n return this;\n },\n\n done: function(callback) {\n if (state === 0) {\n doneCallbacks.push(callback);\n }\n else {\n callback.apply(null, failureArgs === undefined ? successArgs : failureArgs);\n }\n\n return this;\n },\n\n success: function() {\n state = 1;\n successArgs = arguments;\n\n if (successCallbacks.length) {\n qq.each(successCallbacks, function(idx, callback) {\n callback.apply(null, successArgs);\n });\n }\n\n if (doneCallbacks.length) {\n qq.each(doneCallbacks, function(idx, callback) {\n callback.apply(null, successArgs);\n });\n }\n\n return this;\n },\n\n failure: function() {\n state = -1;\n failureArgs = arguments;\n\n if (failureCallbacks.length) {\n qq.each(failureCallbacks, function(idx, callback) {\n callback.apply(null, failureArgs);\n });\n }\n\n if (doneCallbacks.length) {\n qq.each(doneCallbacks, function(idx, callback) {\n callback.apply(null, failureArgs);\n });\n }\n\n return this;\n }\n });\n};\n","/* globals qq */\n/**\n * Placeholder for a Blob that will be generated on-demand.\n *\n * @param referenceBlob Parent of the generated blob\n * @param onCreate Function to invoke when the blob must be created. Must be promissory.\n * @constructor\n */\nqq.BlobProxy = function(referenceBlob, onCreate) {\n \"use strict\";\n\n qq.extend(this, {\n referenceBlob: referenceBlob,\n\n create: function() {\n return onCreate(referenceBlob);\n }\n });\n};\n","/*globals qq*/\n\n/**\n * This module represents an upload or \"Select File(s)\" button. It's job is to embed an opaque ` `\n * element as a child of a provided \"container\" element. This \"container\" element (`options.element`) is used to provide\n * a custom style for the ` ` element. The ability to change the style of the container element is also\n * provided here by adding CSS classes to the container on hover/focus.\n *\n * TODO Eliminate the mouseover and mouseout event handlers since the :hover CSS pseudo-class should now be\n * available on all supported browsers.\n *\n * @param o Options to override the default values\n */\nqq.UploadButton = function(o) {\n \"use strict\";\n\n var self = this,\n\n disposeSupport = new qq.DisposeSupport(),\n\n options = {\n // Corresponds to the `accept` attribute on the associated ` `\n acceptFiles: null,\n\n // \"Container\" element\n element: null,\n\n focusClass: \"qq-upload-button-focus\",\n\n // A true value allows folders to be selected, if supported by the UA\n folders: false,\n\n // **This option will be removed** in the future as the :hover CSS pseudo-class is available on all supported browsers\n hoverClass: \"qq-upload-button-hover\",\n\n ios8BrowserCrashWorkaround: false,\n\n // If true adds `multiple` attribute to ` `\n multiple: false,\n\n // `name` attribute of ` `\n name: \"qqfile\",\n\n // Called when the browser invokes the onchange handler on the ` `\n onChange: function(input) {},\n\n title: null\n },\n input, buttonId;\n\n // Overrides any of the default option values with any option values passed in during construction.\n qq.extend(options, o);\n\n buttonId = qq.getUniqueId();\n\n // Embed an opaque ` ` element as a child of `options.element`.\n function createInput() {\n var input = document.createElement(\"input\");\n\n input.setAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME, buttonId);\n input.setAttribute(\"title\", options.title);\n\n self.setMultiple(options.multiple, input);\n\n if (options.folders && qq.supportedFeatures.folderSelection) {\n // selecting directories is only possible in Chrome now, via a vendor-specific prefixed attribute\n input.setAttribute(\"webkitdirectory\", \"\");\n }\n\n if (options.acceptFiles) {\n input.setAttribute(\"accept\", options.acceptFiles);\n }\n\n input.setAttribute(\"type\", \"file\");\n input.setAttribute(\"name\", options.name);\n\n qq(input).css({\n position: \"absolute\",\n // in Opera only 'browse' button\n // is clickable and it is located at\n // the right side of the input\n right: 0,\n top: 0,\n fontFamily: \"Arial\",\n // It's especially important to make this an arbitrarily large value\n // to ensure the rendered input button in IE takes up the entire\n // space of the container element. Otherwise, the left side of the\n // button will require a double-click to invoke the file chooser.\n // In other browsers, this might cause other issues, so a large font-size\n // is only used in IE. There is a bug in IE8 where the opacity style is ignored\n // in some cases when the font-size is large. So, this workaround is not applied\n // to IE8.\n fontSize: qq.ie() && !qq.ie8() ? \"3500px\" : \"118px\",\n margin: 0,\n padding: 0,\n cursor: \"pointer\",\n opacity: 0\n });\n\n // Setting the file input's height to 100% in IE7 causes\n // most of the visible button to be unclickable.\n !qq.ie7() && qq(input).css({height: \"100%\"});\n\n options.element.appendChild(input);\n\n disposeSupport.attach(input, \"change\", function() {\n options.onChange(input);\n });\n\n // **These event handlers will be removed** in the future as the :hover CSS pseudo-class is available on all supported browsers\n disposeSupport.attach(input, \"mouseover\", function() {\n qq(options.element).addClass(options.hoverClass);\n });\n disposeSupport.attach(input, \"mouseout\", function() {\n qq(options.element).removeClass(options.hoverClass);\n });\n\n disposeSupport.attach(input, \"focus\", function() {\n qq(options.element).addClass(options.focusClass);\n });\n disposeSupport.attach(input, \"blur\", function() {\n qq(options.element).removeClass(options.focusClass);\n });\n\n return input;\n }\n\n // Make button suitable container for input\n qq(options.element).css({\n position: \"relative\",\n overflow: \"hidden\",\n // Make sure browse button is in the right side in Internet Explorer\n direction: \"ltr\"\n });\n\n // Exposed API\n qq.extend(this, {\n getInput: function() {\n return input;\n },\n\n getButtonId: function() {\n return buttonId;\n },\n\n setMultiple: function(isMultiple, optInput) {\n var input = optInput || this.getInput();\n\n // Temporary workaround for bug in in iOS8 UIWebView that causes the browser to crash\n // before the file chooser appears if the file input doesn't contain a multiple attribute.\n // See #1283.\n if (options.ios8BrowserCrashWorkaround && qq.ios8() && (qq.iosChrome() || qq.iosSafariWebView())) {\n input.setAttribute(\"multiple\", \"\");\n }\n\n else {\n if (isMultiple) {\n input.setAttribute(\"multiple\", \"\");\n }\n else {\n input.removeAttribute(\"multiple\");\n }\n }\n },\n\n setAcceptFiles: function(acceptFiles) {\n if (acceptFiles !== options.acceptFiles) {\n input.setAttribute(\"accept\", acceptFiles);\n }\n },\n\n reset: function() {\n if (input.parentNode) {\n qq(input).remove();\n }\n\n qq(options.element).removeClass(options.focusClass);\n input = null;\n input = createInput();\n }\n });\n\n input = createInput();\n};\n\nqq.UploadButton.BUTTON_ID_ATTR_NAME = \"qq-button-id\";\n","/*globals qq */\nqq.UploadData = function(uploaderProxy) {\n \"use strict\";\n\n var data = [],\n byUuid = {},\n byStatus = {},\n byProxyGroupId = {},\n byBatchId = {};\n\n function getDataByIds(idOrIds) {\n if (qq.isArray(idOrIds)) {\n var entries = [];\n\n qq.each(idOrIds, function(idx, id) {\n entries.push(data[id]);\n });\n\n return entries;\n }\n\n return data[idOrIds];\n }\n\n function getDataByUuids(uuids) {\n if (qq.isArray(uuids)) {\n var entries = [];\n\n qq.each(uuids, function(idx, uuid) {\n entries.push(data[byUuid[uuid]]);\n });\n\n return entries;\n }\n\n return data[byUuid[uuids]];\n }\n\n function getDataByStatus(status) {\n var statusResults = [],\n statuses = [].concat(status);\n\n qq.each(statuses, function(index, statusEnum) {\n var statusResultIndexes = byStatus[statusEnum];\n\n if (statusResultIndexes !== undefined) {\n qq.each(statusResultIndexes, function(i, dataIndex) {\n statusResults.push(data[dataIndex]);\n });\n }\n });\n\n return statusResults;\n }\n\n qq.extend(this, {\n /**\n * Adds a new file to the data cache for tracking purposes.\n *\n * @param spec Data that describes this file. Possible properties are:\n *\n * - uuid: Initial UUID for this file.\n * - name: Initial name of this file.\n * - size: Size of this file, omit if this cannot be determined\n * - status: Initial `qq.status` for this file. Omit for `qq.status.SUBMITTING`.\n * - batchId: ID of the batch this file belongs to\n * - proxyGroupId: ID of the proxy group associated with this file\n *\n * @returns {number} Internal ID for this file.\n */\n addFile: function(spec) {\n var status = spec.status || qq.status.SUBMITTING,\n id = data.push({\n name: spec.name,\n originalName: spec.name,\n uuid: spec.uuid,\n size: spec.size == null ? -1 : spec.size,\n status: status\n }) - 1;\n\n if (spec.batchId) {\n data[id].batchId = spec.batchId;\n\n if (byBatchId[spec.batchId] === undefined) {\n byBatchId[spec.batchId] = [];\n }\n byBatchId[spec.batchId].push(id);\n }\n\n if (spec.proxyGroupId) {\n data[id].proxyGroupId = spec.proxyGroupId;\n\n if (byProxyGroupId[spec.proxyGroupId] === undefined) {\n byProxyGroupId[spec.proxyGroupId] = [];\n }\n byProxyGroupId[spec.proxyGroupId].push(id);\n }\n\n data[id].id = id;\n byUuid[spec.uuid] = id;\n\n if (byStatus[status] === undefined) {\n byStatus[status] = [];\n }\n byStatus[status].push(id);\n\n uploaderProxy.onStatusChange(id, null, status);\n\n return id;\n },\n\n retrieve: function(optionalFilter) {\n if (qq.isObject(optionalFilter) && data.length) {\n if (optionalFilter.id !== undefined) {\n return getDataByIds(optionalFilter.id);\n }\n\n else if (optionalFilter.uuid !== undefined) {\n return getDataByUuids(optionalFilter.uuid);\n }\n\n else if (optionalFilter.status) {\n return getDataByStatus(optionalFilter.status);\n }\n }\n else {\n return qq.extend([], data, true);\n }\n },\n\n reset: function() {\n data = [];\n byUuid = {};\n byStatus = {};\n byBatchId = {};\n },\n\n setStatus: function(id, newStatus) {\n var oldStatus = data[id].status,\n byStatusOldStatusIndex = qq.indexOf(byStatus[oldStatus], id);\n\n byStatus[oldStatus].splice(byStatusOldStatusIndex, 1);\n\n data[id].status = newStatus;\n\n if (byStatus[newStatus] === undefined) {\n byStatus[newStatus] = [];\n }\n byStatus[newStatus].push(id);\n\n uploaderProxy.onStatusChange(id, oldStatus, newStatus);\n },\n\n uuidChanged: function(id, newUuid) {\n var oldUuid = data[id].uuid;\n\n data[id].uuid = newUuid;\n byUuid[newUuid] = id;\n delete byUuid[oldUuid];\n },\n\n updateName: function(id, newName) {\n data[id].name = newName;\n },\n\n updateSize: function(id, newSize) {\n data[id].size = newSize;\n },\n\n // Only applicable if this file has a parent that we may want to reference later.\n setParentId: function(targetId, parentId) {\n data[targetId].parentId = parentId;\n },\n\n getIdsInProxyGroup: function(id) {\n var proxyGroupId = data[id].proxyGroupId;\n\n if (proxyGroupId) {\n return byProxyGroupId[proxyGroupId];\n }\n return [];\n },\n\n getIdsInBatch: function(id) {\n var batchId = data[id].batchId;\n\n return byBatchId[batchId];\n }\n });\n};\n\nqq.status = {\n SUBMITTING: \"submitting\",\n SUBMITTED: \"submitted\",\n REJECTED: \"rejected\",\n QUEUED: \"queued\",\n CANCELED: \"canceled\",\n PAUSED: \"paused\",\n UPLOADING: \"uploading\",\n UPLOAD_RETRYING: \"retrying upload\",\n UPLOAD_SUCCESSFUL: \"upload successful\",\n UPLOAD_FAILED: \"upload failed\",\n DELETE_FAILED: \"delete failed\",\n DELETING: \"deleting\",\n DELETED: \"deleted\"\n};\n","/*globals qq*/\n/**\n * Defines the public API for FineUploaderBasic mode.\n */\n(function() {\n \"use strict\";\n\n qq.basePublicApi = {\n // DEPRECATED - TODO REMOVE IN NEXT MAJOR RELEASE (replaced by addFiles)\n addBlobs: function(blobDataOrArray, params, endpoint) {\n this.addFiles(blobDataOrArray, params, endpoint);\n },\n\n addInitialFiles: function(cannedFileList) {\n var self = this;\n\n qq.each(cannedFileList, function(index, cannedFile) {\n self._addCannedFile(cannedFile);\n });\n },\n\n addFiles: function(data, params, endpoint) {\n this._maybeHandleIos8SafariWorkaround();\n\n var batchId = this._storedIds.length === 0 ? qq.getUniqueId() : this._currentBatchId,\n\n processBlob = qq.bind(function(blob) {\n this._handleNewFile({\n blob: blob,\n name: this._options.blobs.defaultName\n }, batchId, verifiedFiles);\n }, this),\n\n processBlobData = qq.bind(function(blobData) {\n this._handleNewFile(blobData, batchId, verifiedFiles);\n }, this),\n\n processCanvas = qq.bind(function(canvas) {\n var blob = qq.canvasToBlob(canvas);\n\n this._handleNewFile({\n blob: blob,\n name: this._options.blobs.defaultName + \".png\"\n }, batchId, verifiedFiles);\n }, this),\n\n processCanvasData = qq.bind(function(canvasData) {\n var normalizedQuality = canvasData.quality && canvasData.quality / 100,\n blob = qq.canvasToBlob(canvasData.canvas, canvasData.type, normalizedQuality);\n\n this._handleNewFile({\n blob: blob,\n name: canvasData.name\n }, batchId, verifiedFiles);\n }, this),\n\n processFileOrInput = qq.bind(function(fileOrInput) {\n if (qq.isInput(fileOrInput) && qq.supportedFeatures.ajaxUploading) {\n var files = Array.prototype.slice.call(fileOrInput.files),\n self = this;\n\n qq.each(files, function(idx, file) {\n self._handleNewFile(file, batchId, verifiedFiles);\n });\n }\n else {\n this._handleNewFile(fileOrInput, batchId, verifiedFiles);\n }\n }, this),\n\n normalizeData = function() {\n if (qq.isFileList(data)) {\n data = Array.prototype.slice.call(data);\n }\n data = [].concat(data);\n },\n\n self = this,\n verifiedFiles = [];\n\n this._currentBatchId = batchId;\n\n if (data) {\n normalizeData();\n\n qq.each(data, function(idx, fileContainer) {\n if (qq.isFileOrInput(fileContainer)) {\n processFileOrInput(fileContainer);\n }\n else if (qq.isBlob(fileContainer)) {\n processBlob(fileContainer);\n }\n else if (qq.isObject(fileContainer)) {\n if (fileContainer.blob && fileContainer.name) {\n processBlobData(fileContainer);\n }\n else if (fileContainer.canvas && fileContainer.name) {\n processCanvasData(fileContainer);\n }\n }\n else if (fileContainer.tagName && fileContainer.tagName.toLowerCase() === \"canvas\") {\n processCanvas(fileContainer);\n }\n else {\n self.log(fileContainer + \" is not a valid file container! Ignoring!\", \"warn\");\n }\n });\n\n this.log(\"Received \" + verifiedFiles.length + \" files.\");\n this._prepareItemsForUpload(verifiedFiles, params, endpoint);\n }\n },\n\n cancel: function(id) {\n this._handler.cancel(id);\n },\n\n cancelAll: function() {\n var storedIdsCopy = [],\n self = this;\n\n qq.extend(storedIdsCopy, this._storedIds);\n qq.each(storedIdsCopy, function(idx, storedFileId) {\n self.cancel(storedFileId);\n });\n\n this._handler.cancelAll();\n },\n\n clearStoredFiles: function() {\n this._storedIds = [];\n },\n\n continueUpload: function(id) {\n var uploadData = this._uploadData.retrieve({id: id});\n\n if (!qq.supportedFeatures.pause || !this._options.chunking.enabled) {\n return false;\n }\n\n if (uploadData.status === qq.status.PAUSED) {\n this.log(qq.format(\"Paused file ID {} ({}) will be continued. Not paused.\", id, this.getName(id)));\n this._uploadFile(id);\n return true;\n }\n else {\n this.log(qq.format(\"Ignoring continue for file ID {} ({}). Not paused.\", id, this.getName(id)), \"error\");\n }\n\n return false;\n },\n\n deleteFile: function(id) {\n return this._onSubmitDelete(id);\n },\n\n // TODO document?\n doesExist: function(fileOrBlobId) {\n return this._handler.isValid(fileOrBlobId);\n },\n\n // Generate a variable size thumbnail on an img or canvas,\n // returning a promise that is fulfilled when the attempt completes.\n // Thumbnail can either be based off of a URL for an image returned\n // by the server in the upload response, or the associated `Blob`.\n drawThumbnail: function(fileId, imgOrCanvas, maxSize, fromServer, customResizeFunction) {\n var promiseToReturn = new qq.Promise(),\n fileOrUrl, options;\n\n if (this._imageGenerator) {\n fileOrUrl = this._thumbnailUrls[fileId];\n options = {\n customResizeFunction: customResizeFunction,\n maxSize: maxSize > 0 ? maxSize : null,\n scale: maxSize > 0\n };\n\n // If client-side preview generation is possible\n // and we are not specifically looking for the image URl returned by the server...\n if (!fromServer && qq.supportedFeatures.imagePreviews) {\n fileOrUrl = this.getFile(fileId);\n }\n\n /* jshint eqeqeq:false,eqnull:true */\n if (fileOrUrl == null) {\n promiseToReturn.failure({container: imgOrCanvas, error: \"File or URL not found.\"});\n }\n else {\n this._imageGenerator.generate(fileOrUrl, imgOrCanvas, options).then(\n function success(modifiedContainer) {\n promiseToReturn.success(modifiedContainer);\n },\n\n function failure(container, reason) {\n promiseToReturn.failure({container: container, error: reason || \"Problem generating thumbnail\"});\n }\n );\n }\n }\n else {\n promiseToReturn.failure({container: imgOrCanvas, error: \"Missing image generator module\"});\n }\n\n return promiseToReturn;\n },\n\n getButton: function(fileId) {\n return this._getButton(this._buttonIdsForFileIds[fileId]);\n },\n\n getEndpoint: function(fileId) {\n return this._endpointStore.get(fileId);\n },\n\n getFile: function(fileOrBlobId) {\n return this._handler.getFile(fileOrBlobId) || null;\n },\n\n getInProgress: function() {\n return this._uploadData.retrieve({\n status: [\n qq.status.UPLOADING,\n qq.status.UPLOAD_RETRYING,\n qq.status.QUEUED\n ]\n }).length;\n },\n\n getName: function(id) {\n return this._uploadData.retrieve({id: id}).name;\n },\n\n // Parent ID for a specific file, or null if this is the parent, or if it has no parent.\n getParentId: function(id) {\n var uploadDataEntry = this.getUploads({id: id}),\n parentId = null;\n\n if (uploadDataEntry) {\n if (uploadDataEntry.parentId !== undefined) {\n parentId = uploadDataEntry.parentId;\n }\n }\n\n return parentId;\n },\n\n getResumableFilesData: function() {\n return this._handler.getResumableFilesData();\n },\n\n getSize: function(id) {\n return this._uploadData.retrieve({id: id}).size;\n },\n\n getNetUploads: function() {\n return this._netUploaded;\n },\n\n getRemainingAllowedItems: function() {\n var allowedItems = this._currentItemLimit;\n\n if (allowedItems > 0) {\n return allowedItems - this._netUploadedOrQueued;\n }\n\n return null;\n },\n\n getUploads: function(optionalFilter) {\n return this._uploadData.retrieve(optionalFilter);\n },\n\n getUuid: function(id) {\n return this._uploadData.retrieve({id: id}).uuid;\n },\n\n log: function(str, level) {\n if (this._options.debug && (!level || level === \"info\")) {\n qq.log(\"[Fine Uploader \" + qq.version + \"] \" + str);\n }\n else if (level && level !== \"info\") {\n qq.log(\"[Fine Uploader \" + qq.version + \"] \" + str, level);\n\n }\n },\n\n pauseUpload: function(id) {\n var uploadData = this._uploadData.retrieve({id: id});\n\n if (!qq.supportedFeatures.pause || !this._options.chunking.enabled) {\n return false;\n }\n\n // Pause only really makes sense if the file is uploading or retrying\n if (qq.indexOf([qq.status.UPLOADING, qq.status.UPLOAD_RETRYING], uploadData.status) >= 0) {\n if (this._handler.pause(id)) {\n this._uploadData.setStatus(id, qq.status.PAUSED);\n return true;\n }\n else {\n this.log(qq.format(\"Unable to pause file ID {} ({}).\", id, this.getName(id)), \"error\");\n }\n }\n else {\n this.log(qq.format(\"Ignoring pause for file ID {} ({}). Not in progress.\", id, this.getName(id)), \"error\");\n }\n\n return false;\n },\n\n reset: function() {\n this.log(\"Resetting uploader...\");\n\n this._handler.reset();\n this._storedIds = [];\n this._autoRetries = [];\n this._retryTimeouts = [];\n this._preventRetries = [];\n this._thumbnailUrls = [];\n\n qq.each(this._buttons, function(idx, button) {\n button.reset();\n });\n\n this._paramsStore.reset();\n this._endpointStore.reset();\n this._netUploadedOrQueued = 0;\n this._netUploaded = 0;\n this._uploadData.reset();\n this._buttonIdsForFileIds = [];\n\n this._pasteHandler && this._pasteHandler.reset();\n this._options.session.refreshOnReset && this._refreshSessionData();\n\n this._succeededSinceLastAllComplete = [];\n this._failedSinceLastAllComplete = [];\n\n this._totalProgress && this._totalProgress.reset();\n },\n\n retry: function(id) {\n return this._manualRetry(id);\n },\n\n scaleImage: function(id, specs) {\n var self = this;\n\n return qq.Scaler.prototype.scaleImage(id, specs, {\n log: qq.bind(self.log, self),\n getFile: qq.bind(self.getFile, self),\n uploadData: self._uploadData\n });\n },\n\n setCustomHeaders: function(headers, id) {\n this._customHeadersStore.set(headers, id);\n },\n\n setDeleteFileCustomHeaders: function(headers, id) {\n this._deleteFileCustomHeadersStore.set(headers, id);\n },\n\n setDeleteFileEndpoint: function(endpoint, id) {\n this._deleteFileEndpointStore.set(endpoint, id);\n },\n\n setDeleteFileParams: function(params, id) {\n this._deleteFileParamsStore.set(params, id);\n },\n\n // Re-sets the default endpoint, an endpoint for a specific file, or an endpoint for a specific button\n setEndpoint: function(endpoint, id) {\n this._endpointStore.set(endpoint, id);\n },\n\n setForm: function(elementOrId) {\n this._updateFormSupportAndParams(elementOrId);\n },\n\n setItemLimit: function(newItemLimit) {\n this._currentItemLimit = newItemLimit;\n },\n\n setName: function(id, newName) {\n this._uploadData.updateName(id, newName);\n },\n\n setParams: function(params, id) {\n this._paramsStore.set(params, id);\n },\n\n setUuid: function(id, newUuid) {\n return this._uploadData.uuidChanged(id, newUuid);\n },\n\n uploadStoredFiles: function() {\n if (this._storedIds.length === 0) {\n this._itemError(\"noFilesError\");\n }\n else {\n this._uploadStoredFiles();\n }\n }\n };\n\n /**\n * Defines the private (internal) API for FineUploaderBasic mode.\n */\n qq.basePrivateApi = {\n // Updates internal state with a file record (not backed by a live file). Returns the assigned ID.\n _addCannedFile: function(sessionData) {\n var id = this._uploadData.addFile({\n uuid: sessionData.uuid,\n name: sessionData.name,\n size: sessionData.size,\n status: qq.status.UPLOAD_SUCCESSFUL\n });\n\n sessionData.deleteFileEndpoint && this.setDeleteFileEndpoint(sessionData.deleteFileEndpoint, id);\n sessionData.deleteFileParams && this.setDeleteFileParams(sessionData.deleteFileParams, id);\n\n if (sessionData.thumbnailUrl) {\n this._thumbnailUrls[id] = sessionData.thumbnailUrl;\n }\n\n this._netUploaded++;\n this._netUploadedOrQueued++;\n\n return id;\n },\n\n _annotateWithButtonId: function(file, associatedInput) {\n if (qq.isFile(file)) {\n file.qqButtonId = this._getButtonId(associatedInput);\n }\n },\n\n _batchError: function(message) {\n this._options.callbacks.onError(null, null, message, undefined);\n },\n\n _createDeleteHandler: function() {\n var self = this;\n\n return new qq.DeleteFileAjaxRequester({\n method: this._options.deleteFile.method.toUpperCase(),\n maxConnections: this._options.maxConnections,\n uuidParamName: this._options.request.uuidName,\n customHeaders: this._deleteFileCustomHeadersStore,\n paramsStore: this._deleteFileParamsStore,\n endpointStore: this._deleteFileEndpointStore,\n cors: this._options.cors,\n log: qq.bind(self.log, self),\n onDelete: function(id) {\n self._onDelete(id);\n self._options.callbacks.onDelete(id);\n },\n onDeleteComplete: function(id, xhrOrXdr, isError) {\n self._onDeleteComplete(id, xhrOrXdr, isError);\n self._options.callbacks.onDeleteComplete(id, xhrOrXdr, isError);\n }\n\n });\n },\n\n _createPasteHandler: function() {\n var self = this;\n\n return new qq.PasteSupport({\n targetElement: this._options.paste.targetElement,\n callbacks: {\n log: qq.bind(self.log, self),\n pasteReceived: function(blob) {\n self._handleCheckedCallback({\n name: \"onPasteReceived\",\n callback: qq.bind(self._options.callbacks.onPasteReceived, self, blob),\n onSuccess: qq.bind(self._handlePasteSuccess, self, blob),\n identifier: \"pasted image\"\n });\n }\n }\n });\n },\n\n _createStore: function(initialValue, _readOnlyValues_) {\n var store = {},\n catchall = initialValue,\n perIdReadOnlyValues = {},\n readOnlyValues = _readOnlyValues_,\n copy = function(orig) {\n if (qq.isObject(orig)) {\n return qq.extend({}, orig);\n }\n return orig;\n },\n getReadOnlyValues = function() {\n if (qq.isFunction(readOnlyValues)) {\n return readOnlyValues();\n }\n return readOnlyValues;\n },\n includeReadOnlyValues = function(id, existing) {\n if (readOnlyValues && qq.isObject(existing)) {\n qq.extend(existing, getReadOnlyValues());\n }\n\n if (perIdReadOnlyValues[id]) {\n qq.extend(existing, perIdReadOnlyValues[id]);\n }\n };\n\n return {\n set: function(val, id) {\n /*jshint eqeqeq: true, eqnull: true*/\n if (id == null) {\n store = {};\n catchall = copy(val);\n }\n else {\n store[id] = copy(val);\n }\n },\n\n get: function(id) {\n var values;\n\n /*jshint eqeqeq: true, eqnull: true*/\n if (id != null && store[id]) {\n values = store[id];\n }\n else {\n values = copy(catchall);\n }\n\n includeReadOnlyValues(id, values);\n\n return copy(values);\n },\n\n addReadOnly: function(id, values) {\n // Only applicable to Object stores\n if (qq.isObject(store)) {\n // If null ID, apply readonly values to all files\n if (id === null) {\n if (qq.isFunction(values)) {\n readOnlyValues = values;\n }\n else {\n readOnlyValues = readOnlyValues || {};\n qq.extend(readOnlyValues, values);\n }\n }\n else {\n perIdReadOnlyValues[id] = perIdReadOnlyValues[id] || {};\n qq.extend(perIdReadOnlyValues[id], values);\n }\n }\n },\n\n remove: function(fileId) {\n return delete store[fileId];\n },\n\n reset: function() {\n store = {};\n perIdReadOnlyValues = {};\n catchall = initialValue;\n }\n };\n },\n\n _createUploadDataTracker: function() {\n var self = this;\n\n return new qq.UploadData({\n getName: function(id) {\n return self.getName(id);\n },\n getUuid: function(id) {\n return self.getUuid(id);\n },\n getSize: function(id) {\n return self.getSize(id);\n },\n onStatusChange: function(id, oldStatus, newStatus) {\n self._onUploadStatusChange(id, oldStatus, newStatus);\n self._options.callbacks.onStatusChange(id, oldStatus, newStatus);\n self._maybeAllComplete(id, newStatus);\n\n if (self._totalProgress) {\n setTimeout(function() {\n self._totalProgress.onStatusChange(id, oldStatus, newStatus);\n }, 0);\n }\n }\n });\n },\n\n /**\n * Generate a tracked upload button.\n *\n * @param spec Object containing a required `element` property\n * along with optional `multiple`, `accept`, and `folders`.\n * @returns {qq.UploadButton}\n * @private\n */\n _createUploadButton: function(spec) {\n var self = this,\n acceptFiles = spec.accept || this._options.validation.acceptFiles,\n allowedExtensions = spec.allowedExtensions || this._options.validation.allowedExtensions,\n button;\n\n function allowMultiple() {\n if (qq.supportedFeatures.ajaxUploading) {\n // Workaround for bug in iOS7+ (see #1039)\n if (self._options.workarounds.iosEmptyVideos &&\n qq.ios() &&\n !qq.ios6() &&\n self._isAllowedExtension(allowedExtensions, \".mov\")) {\n\n return false;\n }\n\n if (spec.multiple === undefined) {\n return self._options.multiple;\n }\n\n return spec.multiple;\n }\n\n return false;\n }\n\n button = new qq.UploadButton({\n acceptFiles: acceptFiles,\n element: spec.element,\n focusClass: this._options.classes.buttonFocus,\n folders: spec.folders,\n hoverClass: this._options.classes.buttonHover,\n ios8BrowserCrashWorkaround: this._options.workarounds.ios8BrowserCrash,\n multiple: allowMultiple(),\n name: this._options.request.inputName,\n onChange: function(input) {\n self._onInputChange(input);\n },\n title: spec.title == null ? this._options.text.fileInputTitle : spec.title\n });\n\n this._disposeSupport.addDisposer(function() {\n button.dispose();\n });\n\n self._buttons.push(button);\n\n return button;\n },\n\n _createUploadHandler: function(additionalOptions, namespace) {\n var self = this,\n lastOnProgress = {},\n options = {\n debug: this._options.debug,\n maxConnections: this._options.maxConnections,\n cors: this._options.cors,\n paramsStore: this._paramsStore,\n endpointStore: this._endpointStore,\n chunking: this._options.chunking,\n resume: this._options.resume,\n blobs: this._options.blobs,\n log: qq.bind(self.log, self),\n preventRetryParam: this._options.retry.preventRetryResponseProperty,\n onProgress: function(id, name, loaded, total) {\n if (loaded < 0 || total < 0) {\n return;\n }\n\n if (lastOnProgress[id]) {\n if (lastOnProgress[id].loaded !== loaded || lastOnProgress[id].total !== total) {\n self._onProgress(id, name, loaded, total);\n self._options.callbacks.onProgress(id, name, loaded, total);\n }\n }\n else {\n self._onProgress(id, name, loaded, total);\n self._options.callbacks.onProgress(id, name, loaded, total);\n }\n\n lastOnProgress[id] = {loaded: loaded, total: total};\n\n },\n onComplete: function(id, name, result, xhr) {\n delete lastOnProgress[id];\n\n var status = self.getUploads({id: id}).status,\n retVal;\n\n // This is to deal with some observed cases where the XHR readyStateChange handler is\n // invoked by the browser multiple times for the same XHR instance with the same state\n // readyState value. Higher level: don't invoke complete-related code if we've already\n // done this.\n if (status === qq.status.UPLOAD_SUCCESSFUL || status === qq.status.UPLOAD_FAILED) {\n return;\n }\n\n retVal = self._onComplete(id, name, result, xhr);\n\n // If the internal `_onComplete` handler returns a promise, don't invoke the `onComplete` callback\n // until the promise has been fulfilled.\n if (retVal instanceof qq.Promise) {\n retVal.done(function() {\n self._options.callbacks.onComplete(id, name, result, xhr);\n });\n }\n else {\n self._options.callbacks.onComplete(id, name, result, xhr);\n }\n },\n onCancel: function(id, name, cancelFinalizationEffort) {\n var promise = new qq.Promise();\n\n self._handleCheckedCallback({\n name: \"onCancel\",\n callback: qq.bind(self._options.callbacks.onCancel, self, id, name),\n onFailure: promise.failure,\n onSuccess: function() {\n cancelFinalizationEffort.then(function() {\n self._onCancel(id, name);\n });\n\n promise.success();\n },\n identifier: id\n });\n\n return promise;\n },\n onUploadPrep: qq.bind(this._onUploadPrep, this),\n onUpload: function(id, name) {\n self._onUpload(id, name);\n self._options.callbacks.onUpload(id, name);\n },\n onUploadChunk: function(id, name, chunkData) {\n self._onUploadChunk(id, chunkData);\n self._options.callbacks.onUploadChunk(id, name, chunkData);\n },\n onUploadChunkSuccess: function(id, chunkData, result, xhr) {\n self._options.callbacks.onUploadChunkSuccess.apply(self, arguments);\n },\n onResume: function(id, name, chunkData) {\n return self._options.callbacks.onResume(id, name, chunkData);\n },\n onAutoRetry: function(id, name, responseJSON, xhr) {\n return self._onAutoRetry.apply(self, arguments);\n },\n onUuidChanged: function(id, newUuid) {\n self.log(\"Server requested UUID change from '\" + self.getUuid(id) + \"' to '\" + newUuid + \"'\");\n self.setUuid(id, newUuid);\n },\n getName: qq.bind(self.getName, self),\n getUuid: qq.bind(self.getUuid, self),\n getSize: qq.bind(self.getSize, self),\n setSize: qq.bind(self._setSize, self),\n getDataByUuid: function(uuid) {\n return self.getUploads({uuid: uuid});\n },\n isQueued: function(id) {\n var status = self.getUploads({id: id}).status;\n return status === qq.status.QUEUED ||\n status === qq.status.SUBMITTED ||\n status === qq.status.UPLOAD_RETRYING ||\n status === qq.status.PAUSED;\n },\n getIdsInProxyGroup: self._uploadData.getIdsInProxyGroup,\n getIdsInBatch: self._uploadData.getIdsInBatch\n };\n\n qq.each(this._options.request, function(prop, val) {\n options[prop] = val;\n });\n\n options.customHeaders = this._customHeadersStore;\n\n if (additionalOptions) {\n qq.each(additionalOptions, function(key, val) {\n options[key] = val;\n });\n }\n\n return new qq.UploadHandlerController(options, namespace);\n },\n\n _fileOrBlobRejected: function(id) {\n this._netUploadedOrQueued--;\n this._uploadData.setStatus(id, qq.status.REJECTED);\n },\n\n _formatSize: function(bytes) {\n if (bytes === 0) {\n return bytes + this._options.text.sizeSymbols[0];\n }\n var i = -1;\n do {\n bytes = bytes / 1000;\n i++;\n } while (bytes > 999);\n\n return Math.max(bytes, 0.1).toFixed(1) + this._options.text.sizeSymbols[i];\n },\n\n // Creates an internal object that tracks various properties of each extra button,\n // and then actually creates the extra button.\n _generateExtraButtonSpecs: function() {\n var self = this;\n\n this._extraButtonSpecs = {};\n\n qq.each(this._options.extraButtons, function(idx, extraButtonOptionEntry) {\n var multiple = extraButtonOptionEntry.multiple,\n validation = qq.extend({}, self._options.validation, true),\n extraButtonSpec = qq.extend({}, extraButtonOptionEntry);\n\n if (multiple === undefined) {\n multiple = self._options.multiple;\n }\n\n if (extraButtonSpec.validation) {\n qq.extend(validation, extraButtonOptionEntry.validation, true);\n }\n\n qq.extend(extraButtonSpec, {\n multiple: multiple,\n validation: validation\n }, true);\n\n self._initExtraButton(extraButtonSpec);\n });\n },\n\n _getButton: function(buttonId) {\n var extraButtonsSpec = this._extraButtonSpecs[buttonId];\n\n if (extraButtonsSpec) {\n return extraButtonsSpec.element;\n }\n else if (buttonId === this._defaultButtonId) {\n return this._options.button;\n }\n },\n\n /**\n * Gets the internally used tracking ID for a button.\n *\n * @param buttonOrFileInputOrFile `File`, ` `, or a button container element\n * @returns {*} The button's ID, or undefined if no ID is recoverable\n * @private\n */\n _getButtonId: function(buttonOrFileInputOrFile) {\n var inputs, fileInput,\n fileBlobOrInput = buttonOrFileInputOrFile;\n\n // We want the reference file/blob here if this is a proxy (a file that will be generated on-demand later)\n if (fileBlobOrInput instanceof qq.BlobProxy) {\n fileBlobOrInput = fileBlobOrInput.referenceBlob;\n }\n\n // If the item is a `Blob` it will never be associated with a button or drop zone.\n if (fileBlobOrInput && !qq.isBlob(fileBlobOrInput)) {\n if (qq.isFile(fileBlobOrInput)) {\n return fileBlobOrInput.qqButtonId;\n }\n else if (fileBlobOrInput.tagName.toLowerCase() === \"input\" &&\n fileBlobOrInput.type.toLowerCase() === \"file\") {\n\n return fileBlobOrInput.getAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME);\n }\n\n inputs = fileBlobOrInput.getElementsByTagName(\"input\");\n\n qq.each(inputs, function(idx, input) {\n if (input.getAttribute(\"type\") === \"file\") {\n fileInput = input;\n return false;\n }\n });\n\n if (fileInput) {\n return fileInput.getAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME);\n }\n }\n },\n\n _getNotFinished: function() {\n return this._uploadData.retrieve({\n status: [\n qq.status.UPLOADING,\n qq.status.UPLOAD_RETRYING,\n qq.status.QUEUED,\n qq.status.SUBMITTING,\n qq.status.SUBMITTED,\n qq.status.PAUSED\n ]\n }).length;\n },\n\n // Get the validation options for this button. Could be the default validation option\n // or a specific one assigned to this particular button.\n _getValidationBase: function(buttonId) {\n var extraButtonSpec = this._extraButtonSpecs[buttonId];\n\n return extraButtonSpec ? extraButtonSpec.validation : this._options.validation;\n },\n\n _getValidationDescriptor: function(fileWrapper) {\n if (fileWrapper.file instanceof qq.BlobProxy) {\n return {\n name: qq.getFilename(fileWrapper.file.referenceBlob),\n size: fileWrapper.file.referenceBlob.size\n };\n }\n\n return {\n name: this.getUploads({id: fileWrapper.id}).name,\n size: this.getUploads({id: fileWrapper.id}).size\n };\n },\n\n _getValidationDescriptors: function(fileWrappers) {\n var self = this,\n fileDescriptors = [];\n\n qq.each(fileWrappers, function(idx, fileWrapper) {\n fileDescriptors.push(self._getValidationDescriptor(fileWrapper));\n });\n\n return fileDescriptors;\n },\n\n // Allows camera access on either the default or an extra button for iOS devices.\n _handleCameraAccess: function() {\n if (this._options.camera.ios && qq.ios()) {\n var acceptIosCamera = \"image/*;capture=camera\",\n button = this._options.camera.button,\n buttonId = button ? this._getButtonId(button) : this._defaultButtonId,\n optionRoot = this._options;\n\n // If we are not targeting the default button, it is an \"extra\" button\n if (buttonId && buttonId !== this._defaultButtonId) {\n optionRoot = this._extraButtonSpecs[buttonId];\n }\n\n // Camera access won't work in iOS if the `multiple` attribute is present on the file input\n optionRoot.multiple = false;\n\n // update the options\n if (optionRoot.validation.acceptFiles === null) {\n optionRoot.validation.acceptFiles = acceptIosCamera;\n }\n else {\n optionRoot.validation.acceptFiles += \",\" + acceptIosCamera;\n }\n\n // update the already-created button\n qq.each(this._buttons, function(idx, button) {\n if (button.getButtonId() === buttonId) {\n button.setMultiple(optionRoot.multiple);\n button.setAcceptFiles(optionRoot.acceptFiles);\n\n return false;\n }\n });\n }\n },\n\n _handleCheckedCallback: function(details) {\n var self = this,\n callbackRetVal = details.callback();\n\n if (qq.isGenericPromise(callbackRetVal)) {\n this.log(details.name + \" - waiting for \" + details.name + \" promise to be fulfilled for \" + details.identifier);\n return callbackRetVal.then(\n function(successParam) {\n self.log(details.name + \" promise success for \" + details.identifier);\n details.onSuccess(successParam);\n },\n function() {\n if (details.onFailure) {\n self.log(details.name + \" promise failure for \" + details.identifier);\n details.onFailure();\n }\n else {\n self.log(details.name + \" promise failure for \" + details.identifier);\n }\n });\n }\n\n if (callbackRetVal !== false) {\n details.onSuccess(callbackRetVal);\n }\n else {\n if (details.onFailure) {\n this.log(details.name + \" - return value was 'false' for \" + details.identifier + \". Invoking failure callback.\");\n details.onFailure();\n }\n else {\n this.log(details.name + \" - return value was 'false' for \" + details.identifier + \". Will not proceed.\");\n }\n }\n\n return callbackRetVal;\n },\n\n // Updates internal state when a new file has been received, and adds it along with its ID to a passed array.\n _handleNewFile: function(file, batchId, newFileWrapperList) {\n var self = this,\n uuid = qq.getUniqueId(),\n size = -1,\n name = qq.getFilename(file),\n actualFile = file.blob || file,\n handler = this._customNewFileHandler ?\n this._customNewFileHandler :\n qq.bind(self._handleNewFileGeneric, self);\n\n if (!qq.isInput(actualFile) && actualFile.size >= 0) {\n size = actualFile.size;\n }\n\n handler(actualFile, name, uuid, size, newFileWrapperList, batchId, this._options.request.uuidName, {\n uploadData: self._uploadData,\n paramsStore: self._paramsStore,\n addFileToHandler: function(id, file) {\n self._handler.add(id, file);\n self._netUploadedOrQueued++;\n self._trackButton(id);\n }\n });\n },\n\n _handleNewFileGeneric: function(file, name, uuid, size, fileList, batchId) {\n var id = this._uploadData.addFile({uuid: uuid, name: name, size: size, batchId: batchId});\n\n this._handler.add(id, file);\n this._trackButton(id);\n\n this._netUploadedOrQueued++;\n\n fileList.push({id: id, file: file});\n },\n\n _handlePasteSuccess: function(blob, extSuppliedName) {\n var extension = blob.type.split(\"/\")[1],\n name = extSuppliedName;\n\n /*jshint eqeqeq: true, eqnull: true*/\n if (name == null) {\n name = this._options.paste.defaultName;\n }\n\n name += \".\" + extension;\n\n this.addFiles({\n name: name,\n blob: blob\n });\n },\n\n // Creates an extra button element\n _initExtraButton: function(spec) {\n var button = this._createUploadButton({\n accept: spec.validation.acceptFiles,\n allowedExtensions: spec.validation.allowedExtensions,\n element: spec.element,\n folders: spec.folders,\n multiple: spec.multiple,\n title: spec.fileInputTitle\n });\n\n this._extraButtonSpecs[button.getButtonId()] = spec;\n },\n\n _initFormSupportAndParams: function() {\n this._formSupport = qq.FormSupport && new qq.FormSupport(\n this._options.form, qq.bind(this.uploadStoredFiles, this), qq.bind(this.log, this)\n );\n\n if (this._formSupport && this._formSupport.attachedToForm) {\n this._paramsStore = this._createStore(\n this._options.request.params, this._formSupport.getFormInputsAsObject\n );\n\n this._options.autoUpload = this._formSupport.newAutoUpload;\n if (this._formSupport.newEndpoint) {\n this._options.request.endpoint = this._formSupport.newEndpoint;\n }\n }\n else {\n this._paramsStore = this._createStore(this._options.request.params);\n }\n },\n\n _isDeletePossible: function() {\n if (!qq.DeleteFileAjaxRequester || !this._options.deleteFile.enabled) {\n return false;\n }\n\n if (this._options.cors.expected) {\n if (qq.supportedFeatures.deleteFileCorsXhr) {\n return true;\n }\n\n if (qq.supportedFeatures.deleteFileCorsXdr && this._options.cors.allowXdr) {\n return true;\n }\n\n return false;\n }\n\n return true;\n },\n\n _isAllowedExtension: function(allowed, fileName) {\n var valid = false;\n\n if (!allowed.length) {\n return true;\n }\n\n qq.each(allowed, function(idx, allowedExt) {\n /**\n * If an argument is not a string, ignore it. Added when a possible issue with MooTools hijacking the\n * `allowedExtensions` array was discovered. See case #735 in the issue tracker for more details.\n */\n if (qq.isString(allowedExt)) {\n /*jshint eqeqeq: true, eqnull: true*/\n var extRegex = new RegExp(\"\\\\.\" + allowedExt + \"$\", \"i\");\n\n if (fileName.match(extRegex) != null) {\n valid = true;\n return false;\n }\n }\n });\n\n return valid;\n },\n\n /**\n * Constructs and returns a message that describes an item/file error. Also calls `onError` callback.\n *\n * @param code REQUIRED - a code that corresponds to a stock message describing this type of error\n * @param maybeNameOrNames names of the items that have failed, if applicable\n * @param item `File`, `Blob`, or ` `\n * @private\n */\n _itemError: function(code, maybeNameOrNames, item) {\n var message = this._options.messages[code],\n allowedExtensions = [],\n names = [].concat(maybeNameOrNames),\n name = names[0],\n buttonId = this._getButtonId(item),\n validationBase = this._getValidationBase(buttonId),\n extensionsForMessage, placeholderMatch;\n\n function r(name, replacement) { message = message.replace(name, replacement); }\n\n qq.each(validationBase.allowedExtensions, function(idx, allowedExtension) {\n /**\n * If an argument is not a string, ignore it. Added when a possible issue with MooTools hijacking the\n * `allowedExtensions` array was discovered. See case #735 in the issue tracker for more details.\n */\n if (qq.isString(allowedExtension)) {\n allowedExtensions.push(allowedExtension);\n }\n });\n\n extensionsForMessage = allowedExtensions.join(\", \").toLowerCase();\n\n r(\"{file}\", this._options.formatFileName(name));\n r(\"{extensions}\", extensionsForMessage);\n r(\"{sizeLimit}\", this._formatSize(validationBase.sizeLimit));\n r(\"{minSizeLimit}\", this._formatSize(validationBase.minSizeLimit));\n\n placeholderMatch = message.match(/(\\{\\w+\\})/g);\n if (placeholderMatch !== null) {\n qq.each(placeholderMatch, function(idx, placeholder) {\n r(placeholder, names[idx]);\n });\n }\n\n this._options.callbacks.onError(null, name, message, undefined);\n\n return message;\n },\n\n /**\n * Conditionally orders a manual retry of a failed upload.\n *\n * @param id File ID of the failed upload\n * @param callback Optional callback to invoke if a retry is prudent.\n * In lieu of asking the upload handler to retry.\n * @returns {boolean} true if a manual retry will occur\n * @private\n */\n _manualRetry: function(id, callback) {\n if (this._onBeforeManualRetry(id)) {\n this._netUploadedOrQueued++;\n this._uploadData.setStatus(id, qq.status.UPLOAD_RETRYING);\n\n if (callback) {\n callback(id);\n }\n else {\n this._handler.retry(id);\n }\n\n return true;\n }\n },\n\n _maybeAllComplete: function(id, status) {\n var self = this,\n notFinished = this._getNotFinished();\n\n if (status === qq.status.UPLOAD_SUCCESSFUL) {\n this._succeededSinceLastAllComplete.push(id);\n }\n else if (status === qq.status.UPLOAD_FAILED) {\n this._failedSinceLastAllComplete.push(id);\n }\n\n if (notFinished === 0 &&\n (this._succeededSinceLastAllComplete.length || this._failedSinceLastAllComplete.length)) {\n // Attempt to ensure onAllComplete is not invoked before other callbacks, such as onCancel & onComplete\n setTimeout(function() {\n self._onAllComplete(self._succeededSinceLastAllComplete, self._failedSinceLastAllComplete);\n }, 0);\n }\n },\n\n _maybeHandleIos8SafariWorkaround: function() {\n var self = this;\n\n if (this._options.workarounds.ios8SafariUploads && qq.ios800() && qq.iosSafari()) {\n setTimeout(function() {\n window.alert(self._options.messages.unsupportedBrowserIos8Safari);\n }, 0);\n throw new qq.Error(this._options.messages.unsupportedBrowserIos8Safari);\n }\n },\n\n _maybeParseAndSendUploadError: function(id, name, response, xhr) {\n // Assuming no one will actually set the response code to something other than 200\n // and still set 'success' to true...\n if (!response.success) {\n if (xhr && xhr.status !== 200 && !response.error) {\n this._options.callbacks.onError(id, name, \"XHR returned response code \" + xhr.status, xhr);\n }\n else {\n var errorReason = response.error ? response.error : this._options.text.defaultResponseError;\n this._options.callbacks.onError(id, name, errorReason, xhr);\n }\n }\n },\n\n _maybeProcessNextItemAfterOnValidateCallback: function(validItem, items, index, params, endpoint) {\n var self = this;\n\n if (items.length > index) {\n if (validItem || !this._options.validation.stopOnFirstInvalidFile) {\n //use setTimeout to prevent a stack overflow with a large number of files in the batch & non-promissory callbacks\n setTimeout(function() {\n var validationDescriptor = self._getValidationDescriptor(items[index]),\n buttonId = self._getButtonId(items[index].file),\n button = self._getButton(buttonId);\n\n self._handleCheckedCallback({\n name: \"onValidate\",\n callback: qq.bind(self._options.callbacks.onValidate, self, validationDescriptor, button),\n onSuccess: qq.bind(self._onValidateCallbackSuccess, self, items, index, params, endpoint),\n onFailure: qq.bind(self._onValidateCallbackFailure, self, items, index, params, endpoint),\n identifier: \"Item '\" + validationDescriptor.name + \"', size: \" + validationDescriptor.size\n });\n }, 0);\n }\n else if (!validItem) {\n for (; index < items.length; index++) {\n self._fileOrBlobRejected(items[index].id);\n }\n }\n }\n },\n\n _onAllComplete: function(successful, failed) {\n this._totalProgress && this._totalProgress.onAllComplete(successful, failed, this._preventRetries);\n\n this._options.callbacks.onAllComplete(qq.extend([], successful), qq.extend([], failed));\n\n this._succeededSinceLastAllComplete = [];\n this._failedSinceLastAllComplete = [];\n },\n\n /**\n * Attempt to automatically retry a failed upload.\n *\n * @param id The file ID of the failed upload\n * @param name The name of the file associated with the failed upload\n * @param responseJSON Response from the server, parsed into a javascript object\n * @param xhr Ajax transport used to send the failed request\n * @param callback Optional callback to be invoked if a retry is prudent.\n * Invoked in lieu of asking the upload handler to retry.\n * @returns {boolean} true if an auto-retry will occur\n * @private\n */\n _onAutoRetry: function(id, name, responseJSON, xhr, callback) {\n var self = this;\n\n self._preventRetries[id] = responseJSON[self._options.retry.preventRetryResponseProperty];\n\n if (self._shouldAutoRetry(id, name, responseJSON)) {\n var retryWaitPeriod = self._options.retry.autoAttemptDelay * 1000;\n\n self._maybeParseAndSendUploadError.apply(self, arguments);\n self._options.callbacks.onAutoRetry(id, name, self._autoRetries[id]);\n self._onBeforeAutoRetry(id, name);\n\n self._uploadData.setStatus(id, qq.status.UPLOAD_RETRYING);\n self._retryTimeouts[id] = setTimeout(function() {\n self.log(\"Starting retry for \" + name + \"...\");\n\n if (callback) {\n callback(id);\n }\n else {\n self._handler.retry(id);\n }\n }, retryWaitPeriod);\n\n return true;\n }\n },\n\n _onBeforeAutoRetry: function(id, name) {\n this.log(\"Waiting \" + this._options.retry.autoAttemptDelay + \" seconds before retrying \" + name + \"...\");\n },\n\n //return false if we should not attempt the requested retry\n _onBeforeManualRetry: function(id) {\n var itemLimit = this._currentItemLimit,\n fileName;\n\n if (this._preventRetries[id]) {\n this.log(\"Retries are forbidden for id \" + id, \"warn\");\n return false;\n }\n else if (this._handler.isValid(id)) {\n fileName = this.getName(id);\n\n if (this._options.callbacks.onManualRetry(id, fileName) === false) {\n return false;\n }\n\n if (itemLimit > 0 && this._netUploadedOrQueued + 1 > itemLimit) {\n this._itemError(\"retryFailTooManyItems\");\n return false;\n }\n\n this.log(\"Retrying upload for '\" + fileName + \"' (id: \" + id + \")...\");\n return true;\n }\n else {\n this.log(\"'\" + id + \"' is not a valid file ID\", \"error\");\n return false;\n }\n },\n\n _onCancel: function(id, name) {\n this._netUploadedOrQueued--;\n\n clearTimeout(this._retryTimeouts[id]);\n\n var storedItemIndex = qq.indexOf(this._storedIds, id);\n if (!this._options.autoUpload && storedItemIndex >= 0) {\n this._storedIds.splice(storedItemIndex, 1);\n }\n\n this._uploadData.setStatus(id, qq.status.CANCELED);\n },\n\n _onComplete: function(id, name, result, xhr) {\n if (!result.success) {\n this._netUploadedOrQueued--;\n this._uploadData.setStatus(id, qq.status.UPLOAD_FAILED);\n\n if (result[this._options.retry.preventRetryResponseProperty] === true) {\n this._preventRetries[id] = true;\n }\n }\n else {\n if (result.thumbnailUrl) {\n this._thumbnailUrls[id] = result.thumbnailUrl;\n }\n\n this._netUploaded++;\n this._uploadData.setStatus(id, qq.status.UPLOAD_SUCCESSFUL);\n }\n\n this._maybeParseAndSendUploadError(id, name, result, xhr);\n\n return result.success ? true : false;\n },\n\n _onDelete: function(id) {\n this._uploadData.setStatus(id, qq.status.DELETING);\n },\n\n _onDeleteComplete: function(id, xhrOrXdr, isError) {\n var name = this.getName(id);\n\n if (isError) {\n this._uploadData.setStatus(id, qq.status.DELETE_FAILED);\n this.log(\"Delete request for '\" + name + \"' has failed.\", \"error\");\n\n // For error reporting, we only have access to the response status if this is not\n // an `XDomainRequest`.\n if (xhrOrXdr.withCredentials === undefined) {\n this._options.callbacks.onError(id, name, \"Delete request failed\", xhrOrXdr);\n }\n else {\n this._options.callbacks.onError(id, name, \"Delete request failed with response code \" + xhrOrXdr.status, xhrOrXdr);\n }\n }\n else {\n this._netUploadedOrQueued--;\n this._netUploaded--;\n this._handler.expunge(id);\n this._uploadData.setStatus(id, qq.status.DELETED);\n this.log(\"Delete request for '\" + name + \"' has succeeded.\");\n }\n },\n\n _onInputChange: function(input) {\n var fileIndex;\n\n if (qq.supportedFeatures.ajaxUploading) {\n for (fileIndex = 0; fileIndex < input.files.length; fileIndex++) {\n this._annotateWithButtonId(input.files[fileIndex], input);\n }\n\n this.addFiles(input.files);\n }\n // Android 2.3.x will fire `onchange` even if no file has been selected\n else if (input.value.length > 0) {\n this.addFiles(input);\n }\n\n qq.each(this._buttons, function(idx, button) {\n button.reset();\n });\n },\n\n _onProgress: function(id, name, loaded, total) {\n this._totalProgress && this._totalProgress.onIndividualProgress(id, loaded, total);\n },\n\n _onSubmit: function(id, name) {\n //nothing to do yet in core uploader\n },\n\n _onSubmitCallbackSuccess: function(id, name) {\n this._onSubmit.apply(this, arguments);\n this._uploadData.setStatus(id, qq.status.SUBMITTED);\n this._onSubmitted.apply(this, arguments);\n\n if (this._options.autoUpload) {\n this._options.callbacks.onSubmitted.apply(this, arguments);\n this._uploadFile(id);\n }\n else {\n this._storeForLater(id);\n this._options.callbacks.onSubmitted.apply(this, arguments);\n }\n },\n\n _onSubmitDelete: function(id, onSuccessCallback, additionalMandatedParams) {\n var uuid = this.getUuid(id),\n adjustedOnSuccessCallback;\n\n if (onSuccessCallback) {\n adjustedOnSuccessCallback = qq.bind(onSuccessCallback, this, id, uuid, additionalMandatedParams);\n }\n\n if (this._isDeletePossible()) {\n this._handleCheckedCallback({\n name: \"onSubmitDelete\",\n callback: qq.bind(this._options.callbacks.onSubmitDelete, this, id),\n onSuccess: adjustedOnSuccessCallback ||\n qq.bind(this._deleteHandler.sendDelete, this, id, uuid, additionalMandatedParams),\n identifier: id\n });\n return true;\n }\n else {\n this.log(\"Delete request ignored for ID \" + id + \", delete feature is disabled or request not possible \" +\n \"due to CORS on a user agent that does not support pre-flighting.\", \"warn\");\n return false;\n }\n },\n\n _onSubmitted: function(id) {\n //nothing to do in the base uploader\n },\n\n _onTotalProgress: function(loaded, total) {\n this._options.callbacks.onTotalProgress(loaded, total);\n },\n\n _onUploadPrep: function(id) {\n // nothing to do in the core uploader for now\n },\n\n _onUpload: function(id, name) {\n this._uploadData.setStatus(id, qq.status.UPLOADING);\n },\n\n _onUploadChunk: function(id, chunkData) {\n //nothing to do in the base uploader\n },\n\n _onUploadStatusChange: function(id, oldStatus, newStatus) {\n // Make sure a \"queued\" retry attempt is canceled if the upload has been paused\n if (newStatus === qq.status.PAUSED) {\n clearTimeout(this._retryTimeouts[id]);\n }\n },\n\n _onValidateBatchCallbackFailure: function(fileWrappers) {\n var self = this;\n\n qq.each(fileWrappers, function(idx, fileWrapper) {\n self._fileOrBlobRejected(fileWrapper.id);\n });\n },\n\n _onValidateBatchCallbackSuccess: function(validationDescriptors, items, params, endpoint, button) {\n var errorMessage,\n itemLimit = this._currentItemLimit,\n proposedNetFilesUploadedOrQueued = this._netUploadedOrQueued;\n\n if (itemLimit === 0 || proposedNetFilesUploadedOrQueued <= itemLimit) {\n if (items.length > 0) {\n this._handleCheckedCallback({\n name: \"onValidate\",\n callback: qq.bind(this._options.callbacks.onValidate, this, validationDescriptors[0], button),\n onSuccess: qq.bind(this._onValidateCallbackSuccess, this, items, 0, params, endpoint),\n onFailure: qq.bind(this._onValidateCallbackFailure, this, items, 0, params, endpoint),\n identifier: \"Item '\" + items[0].file.name + \"', size: \" + items[0].file.size\n });\n }\n else {\n this._itemError(\"noFilesError\");\n }\n }\n else {\n this._onValidateBatchCallbackFailure(items);\n errorMessage = this._options.messages.tooManyItemsError\n .replace(/\\{netItems\\}/g, proposedNetFilesUploadedOrQueued)\n .replace(/\\{itemLimit\\}/g, itemLimit);\n this._batchError(errorMessage);\n }\n },\n\n _onValidateCallbackFailure: function(items, index, params, endpoint) {\n var nextIndex = index + 1;\n\n this._fileOrBlobRejected(items[index].id, items[index].file.name);\n\n this._maybeProcessNextItemAfterOnValidateCallback(false, items, nextIndex, params, endpoint);\n },\n\n _onValidateCallbackSuccess: function(items, index, params, endpoint) {\n var self = this,\n nextIndex = index + 1,\n validationDescriptor = this._getValidationDescriptor(items[index]);\n\n this._validateFileOrBlobData(items[index], validationDescriptor)\n .then(\n function() {\n self._upload(items[index].id, params, endpoint);\n self._maybeProcessNextItemAfterOnValidateCallback(true, items, nextIndex, params, endpoint);\n },\n function() {\n self._maybeProcessNextItemAfterOnValidateCallback(false, items, nextIndex, params, endpoint);\n }\n );\n },\n\n _prepareItemsForUpload: function(items, params, endpoint) {\n if (items.length === 0) {\n this._itemError(\"noFilesError\");\n return;\n }\n\n var validationDescriptors = this._getValidationDescriptors(items),\n buttonId = this._getButtonId(items[0].file),\n button = this._getButton(buttonId);\n\n this._handleCheckedCallback({\n name: \"onValidateBatch\",\n callback: qq.bind(this._options.callbacks.onValidateBatch, this, validationDescriptors, button),\n onSuccess: qq.bind(this._onValidateBatchCallbackSuccess, this, validationDescriptors, items, params, endpoint, button),\n onFailure: qq.bind(this._onValidateBatchCallbackFailure, this, items),\n identifier: \"batch validation\"\n });\n },\n\n _preventLeaveInProgress: function() {\n var self = this;\n\n this._disposeSupport.attach(window, \"beforeunload\", function(e) {\n if (self.getInProgress()) {\n e = e || window.event;\n // for ie, ff\n e.returnValue = self._options.messages.onLeave;\n // for webkit\n return self._options.messages.onLeave;\n }\n });\n },\n\n // Attempts to refresh session data only if the `qq.Session` module exists\n // and a session endpoint has been specified. The `onSessionRequestComplete`\n // callback will be invoked once the refresh is complete.\n _refreshSessionData: function() {\n var self = this,\n options = this._options.session;\n\n /* jshint eqnull:true */\n if (qq.Session && this._options.session.endpoint != null) {\n if (!this._session) {\n qq.extend(options, {cors: this._options.cors});\n\n options.log = qq.bind(this.log, this);\n options.addFileRecord = qq.bind(this._addCannedFile, this);\n\n this._session = new qq.Session(options);\n }\n\n setTimeout(function() {\n self._session.refresh().then(function(response, xhrOrXdr) {\n self._sessionRequestComplete();\n self._options.callbacks.onSessionRequestComplete(response, true, xhrOrXdr);\n\n }, function(response, xhrOrXdr) {\n\n self._options.callbacks.onSessionRequestComplete(response, false, xhrOrXdr);\n });\n }, 0);\n }\n },\n\n _sessionRequestComplete: function() {},\n\n _setSize: function(id, newSize) {\n this._uploadData.updateSize(id, newSize);\n this._totalProgress && this._totalProgress.onNewSize(id);\n },\n\n _shouldAutoRetry: function(id, name, responseJSON) {\n var uploadData = this._uploadData.retrieve({id: id});\n\n /*jshint laxbreak: true */\n if (!this._preventRetries[id]\n && this._options.retry.enableAuto\n && uploadData.status !== qq.status.PAUSED) {\n\n if (this._autoRetries[id] === undefined) {\n this._autoRetries[id] = 0;\n }\n\n if (this._autoRetries[id] < this._options.retry.maxAutoAttempts) {\n this._autoRetries[id] += 1;\n return true;\n }\n }\n\n return false;\n },\n\n _storeForLater: function(id) {\n this._storedIds.push(id);\n },\n\n // Maps a file with the button that was used to select it.\n _trackButton: function(id) {\n var buttonId;\n\n if (qq.supportedFeatures.ajaxUploading) {\n buttonId = this._handler.getFile(id).qqButtonId;\n }\n else {\n buttonId = this._getButtonId(this._handler.getInput(id));\n }\n\n if (buttonId) {\n this._buttonIdsForFileIds[id] = buttonId;\n }\n },\n\n _updateFormSupportAndParams: function(formElementOrId) {\n this._options.form.element = formElementOrId;\n\n this._formSupport = qq.FormSupport && new qq.FormSupport(\n this._options.form, qq.bind(this.uploadStoredFiles, this), qq.bind(this.log, this)\n );\n\n if (this._formSupport && this._formSupport.attachedToForm) {\n this._paramsStore.addReadOnly(null, this._formSupport.getFormInputsAsObject);\n\n this._options.autoUpload = this._formSupport.newAutoUpload;\n if (this._formSupport.newEndpoint) {\n this.setEndpoint(this._formSupport.newEndpoint);\n }\n }\n },\n\n _upload: function(id, params, endpoint) {\n var name = this.getName(id);\n\n if (params) {\n this.setParams(params, id);\n }\n\n if (endpoint) {\n this.setEndpoint(endpoint, id);\n }\n\n this._handleCheckedCallback({\n name: \"onSubmit\",\n callback: qq.bind(this._options.callbacks.onSubmit, this, id, name),\n onSuccess: qq.bind(this._onSubmitCallbackSuccess, this, id, name),\n onFailure: qq.bind(this._fileOrBlobRejected, this, id, name),\n identifier: id\n });\n },\n\n _uploadFile: function(id) {\n if (!this._handler.upload(id)) {\n this._uploadData.setStatus(id, qq.status.QUEUED);\n }\n },\n\n _uploadStoredFiles: function() {\n var idToUpload, stillSubmitting,\n self = this;\n\n while (this._storedIds.length) {\n idToUpload = this._storedIds.shift();\n this._uploadFile(idToUpload);\n }\n\n // If we are still waiting for some files to clear validation, attempt to upload these again in a bit\n stillSubmitting = this.getUploads({status: qq.status.SUBMITTING}).length;\n if (stillSubmitting) {\n qq.log(\"Still waiting for \" + stillSubmitting + \" files to clear submit queue. Will re-parse stored IDs array shortly.\");\n setTimeout(function() {\n self._uploadStoredFiles();\n }, 1000);\n }\n },\n\n /**\n * Performs some internal validation checks on an item, defined in the `validation` option.\n *\n * @param fileWrapper Wrapper containing a `file` along with an `id`\n * @param validationDescriptor Normalized information about the item (`size`, `name`).\n * @returns qq.Promise with appropriate callbacks invoked depending on the validity of the file\n * @private\n */\n _validateFileOrBlobData: function(fileWrapper, validationDescriptor) {\n var self = this,\n file = (function() {\n if (fileWrapper.file instanceof qq.BlobProxy) {\n return fileWrapper.file.referenceBlob;\n }\n return fileWrapper.file;\n }()),\n name = validationDescriptor.name,\n size = validationDescriptor.size,\n buttonId = this._getButtonId(fileWrapper.file),\n validationBase = this._getValidationBase(buttonId),\n validityChecker = new qq.Promise();\n\n validityChecker.then(\n function() {},\n function() {\n self._fileOrBlobRejected(fileWrapper.id, name);\n });\n\n if (qq.isFileOrInput(file) && !this._isAllowedExtension(validationBase.allowedExtensions, name)) {\n this._itemError(\"typeError\", name, file);\n return validityChecker.failure();\n }\n\n if (!this._options.validation.allowEmpty && size === 0) {\n this._itemError(\"emptyError\", name, file);\n return validityChecker.failure();\n }\n\n if (size > 0 && validationBase.sizeLimit && size > validationBase.sizeLimit) {\n this._itemError(\"sizeError\", name, file);\n return validityChecker.failure();\n }\n\n if (size > 0 && size < validationBase.minSizeLimit) {\n this._itemError(\"minSizeError\", name, file);\n return validityChecker.failure();\n }\n\n if (qq.ImageValidation && qq.supportedFeatures.imagePreviews && qq.isFile(file)) {\n new qq.ImageValidation(file, qq.bind(self.log, self)).validate(validationBase.image).then(\n validityChecker.success,\n function(errorCode) {\n self._itemError(errorCode + \"ImageError\", name, file);\n validityChecker.failure();\n }\n );\n }\n else {\n validityChecker.success();\n }\n\n return validityChecker;\n },\n\n _wrapCallbacks: function() {\n var self, safeCallback, prop;\n\n self = this;\n\n safeCallback = function(name, callback, args) {\n var errorMsg;\n\n try {\n return callback.apply(self, args);\n }\n catch (exception) {\n errorMsg = exception.message || exception.toString();\n self.log(\"Caught exception in '\" + name + \"' callback - \" + errorMsg, \"error\");\n }\n };\n\n /* jshint forin: false, loopfunc: true */\n for (prop in this._options.callbacks) {\n (function() {\n var callbackName, callbackFunc;\n callbackName = prop;\n callbackFunc = self._options.callbacks[callbackName];\n self._options.callbacks[callbackName] = function() {\n return safeCallback(callbackName, callbackFunc, arguments);\n };\n }());\n }\n }\n };\n}());\n","/*globals qq*/\n(function() {\n \"use strict\";\n\n qq.FineUploaderBasic = function(o) {\n var self = this;\n\n // These options define FineUploaderBasic mode.\n this._options = {\n debug: false,\n button: null,\n multiple: true,\n maxConnections: 3,\n disableCancelForFormUploads: false,\n autoUpload: true,\n\n request: {\n customHeaders: {},\n endpoint: \"/server/upload\",\n filenameParam: \"qqfilename\",\n forceMultipart: true,\n inputName: \"qqfile\",\n method: \"POST\",\n params: {},\n paramsInBody: true,\n totalFileSizeName: \"qqtotalfilesize\",\n uuidName: \"qquuid\"\n },\n\n validation: {\n allowedExtensions: [],\n sizeLimit: 0,\n minSizeLimit: 0,\n itemLimit: 0,\n stopOnFirstInvalidFile: true,\n acceptFiles: null,\n image: {\n maxHeight: 0,\n maxWidth: 0,\n minHeight: 0,\n minWidth: 0\n },\n allowEmpty: false\n },\n\n callbacks: {\n onSubmit: function(id, name) {},\n onSubmitted: function(id, name) {},\n onComplete: function(id, name, responseJSON, maybeXhr) {},\n onAllComplete: function(successful, failed) {},\n onCancel: function(id, name) {},\n onUpload: function(id, name) {},\n onUploadChunk: function(id, name, chunkData) {},\n onUploadChunkSuccess: function(id, chunkData, responseJSON, xhr) {},\n onResume: function(id, fileName, chunkData) {},\n onProgress: function(id, name, loaded, total) {},\n onTotalProgress: function(loaded, total) {},\n onError: function(id, name, reason, maybeXhrOrXdr) {},\n onAutoRetry: function(id, name, attemptNumber) {},\n onManualRetry: function(id, name) {},\n onValidateBatch: function(fileOrBlobData) {},\n onValidate: function(fileOrBlobData) {},\n onSubmitDelete: function(id) {},\n onDelete: function(id) {},\n onDeleteComplete: function(id, xhrOrXdr, isError) {},\n onPasteReceived: function(blob) {},\n onStatusChange: function(id, oldStatus, newStatus) {},\n onSessionRequestComplete: function(response, success, xhrOrXdr) {}\n },\n\n messages: {\n typeError: \"{file} has an invalid extension. Valid extension(s): {extensions}.\",\n sizeError: \"{file} is too large, maximum file size is {sizeLimit}.\",\n minSizeError: \"{file} is too small, minimum file size is {minSizeLimit}.\",\n emptyError: \"{file} is empty, please select files again without it.\",\n noFilesError: \"No files to upload.\",\n tooManyItemsError: \"Too many items ({netItems}) would be uploaded. Item limit is {itemLimit}.\",\n maxHeightImageError: \"Image is too tall.\",\n maxWidthImageError: \"Image is too wide.\",\n minHeightImageError: \"Image is not tall enough.\",\n minWidthImageError: \"Image is not wide enough.\",\n retryFailTooManyItems: \"Retry failed - you have reached your file limit.\",\n onLeave: \"The files are being uploaded, if you leave now the upload will be canceled.\",\n unsupportedBrowserIos8Safari: \"Unrecoverable error - this browser does not permit file uploading of any kind due to serious bugs in iOS8 Safari. Please use iOS8 Chrome until Apple fixes these issues.\"\n },\n\n retry: {\n enableAuto: false,\n maxAutoAttempts: 3,\n autoAttemptDelay: 5,\n preventRetryResponseProperty: \"preventRetry\"\n },\n\n classes: {\n buttonHover: \"qq-upload-button-hover\",\n buttonFocus: \"qq-upload-button-focus\"\n },\n\n chunking: {\n enabled: false,\n concurrent: {\n enabled: false\n },\n mandatory: false,\n paramNames: {\n partIndex: \"qqpartindex\",\n partByteOffset: \"qqpartbyteoffset\",\n chunkSize: \"qqchunksize\",\n totalFileSize: \"qqtotalfilesize\",\n totalParts: \"qqtotalparts\"\n },\n partSize: 2000000,\n // only relevant for traditional endpoints, only required when concurrent.enabled === true\n success: {\n endpoint: null\n }\n },\n\n resume: {\n enabled: false,\n recordsExpireIn: 7, //days\n paramNames: {\n resuming: \"qqresume\"\n }\n },\n\n formatFileName: function(fileOrBlobName) {\n return fileOrBlobName;\n },\n\n text: {\n defaultResponseError: \"Upload failure reason unknown\",\n fileInputTitle: \"file input\",\n sizeSymbols: [\"kB\", \"MB\", \"GB\", \"TB\", \"PB\", \"EB\"]\n },\n\n deleteFile: {\n enabled: false,\n method: \"DELETE\",\n endpoint: \"/server/upload\",\n customHeaders: {},\n params: {}\n },\n\n cors: {\n expected: false,\n sendCredentials: false,\n allowXdr: false\n },\n\n blobs: {\n defaultName: \"misc_data\"\n },\n\n paste: {\n targetElement: null,\n defaultName: \"pasted_image\"\n },\n\n camera: {\n ios: false,\n\n // if ios is true: button is null means target the default button, otherwise target the button specified\n button: null\n },\n\n // This refers to additional upload buttons to be handled by Fine Uploader.\n // Each element is an object, containing `element` as the only required\n // property. The `element` must be a container that will ultimately\n // contain an invisible ` ` created by Fine Uploader.\n // Optional properties of each object include `multiple`, `validation`,\n // and `folders`.\n extraButtons: [],\n\n // Depends on the session module. Used to query the server for an initial file list\n // during initialization and optionally after a `reset`.\n session: {\n endpoint: null,\n params: {},\n customHeaders: {},\n refreshOnReset: true\n },\n\n // Send parameters associated with an existing form along with the files\n form: {\n // Element ID, HTMLElement, or null\n element: \"qq-form\",\n\n // Overrides the base `autoUpload`, unless `element` is null.\n autoUpload: false,\n\n // true = upload files on form submission (and squelch submit event)\n interceptSubmit: true\n },\n\n // scale images client side, upload a new file for each scaled version\n scaling: {\n customResizer: null,\n\n // send the original file as well\n sendOriginal: true,\n\n // fox orientation for scaled images\n orient: true,\n\n // If null, scaled image type will match reference image type. This value will be referred to\n // for any size record that does not specific a type.\n defaultType: null,\n\n defaultQuality: 80,\n\n failureText: \"Failed to scale\",\n\n includeExif: false,\n\n // metadata about each requested scaled version\n sizes: []\n },\n\n workarounds: {\n iosEmptyVideos: true,\n ios8SafariUploads: true,\n ios8BrowserCrash: false\n }\n };\n\n // Replace any default options with user defined ones\n qq.extend(this._options, o, true);\n\n this._buttons = [];\n this._extraButtonSpecs = {};\n this._buttonIdsForFileIds = [];\n\n this._wrapCallbacks();\n this._disposeSupport = new qq.DisposeSupport();\n\n this._storedIds = [];\n this._autoRetries = [];\n this._retryTimeouts = [];\n this._preventRetries = [];\n this._thumbnailUrls = [];\n\n this._netUploadedOrQueued = 0;\n this._netUploaded = 0;\n this._uploadData = this._createUploadDataTracker();\n\n this._initFormSupportAndParams();\n\n this._customHeadersStore = this._createStore(this._options.request.customHeaders);\n this._deleteFileCustomHeadersStore = this._createStore(this._options.deleteFile.customHeaders);\n\n this._deleteFileParamsStore = this._createStore(this._options.deleteFile.params);\n\n this._endpointStore = this._createStore(this._options.request.endpoint);\n this._deleteFileEndpointStore = this._createStore(this._options.deleteFile.endpoint);\n\n this._handler = this._createUploadHandler();\n\n this._deleteHandler = qq.DeleteFileAjaxRequester && this._createDeleteHandler();\n\n if (this._options.button) {\n this._defaultButtonId = this._createUploadButton({\n element: this._options.button,\n title: this._options.text.fileInputTitle\n }).getButtonId();\n }\n\n this._generateExtraButtonSpecs();\n\n this._handleCameraAccess();\n\n if (this._options.paste.targetElement) {\n if (qq.PasteSupport) {\n this._pasteHandler = this._createPasteHandler();\n }\n else {\n this.log(\"Paste support module not found\", \"error\");\n }\n }\n\n this._preventLeaveInProgress();\n\n this._imageGenerator = qq.ImageGenerator && new qq.ImageGenerator(qq.bind(this.log, this));\n this._refreshSessionData();\n\n this._succeededSinceLastAllComplete = [];\n this._failedSinceLastAllComplete = [];\n\n this._scaler = (qq.Scaler && new qq.Scaler(this._options.scaling, qq.bind(this.log, this))) || {};\n if (this._scaler.enabled) {\n this._customNewFileHandler = qq.bind(this._scaler.handleNewFile, this._scaler);\n }\n\n if (qq.TotalProgress && qq.supportedFeatures.progressBar) {\n this._totalProgress = new qq.TotalProgress(\n qq.bind(this._onTotalProgress, this),\n\n function(id) {\n var entry = self._uploadData.retrieve({id: id});\n return (entry && entry.size) || 0;\n }\n );\n }\n\n this._currentItemLimit = this._options.validation.itemLimit;\n };\n\n // Define the private & public API methods.\n qq.FineUploaderBasic.prototype = qq.basePublicApi;\n qq.extend(qq.FineUploaderBasic.prototype, qq.basePrivateApi);\n}());\n","/*globals qq, XDomainRequest*/\n/** Generic class for sending non-upload ajax requests and handling the associated responses **/\nqq.AjaxRequester = function(o) {\n \"use strict\";\n\n var log, shouldParamsBeInQueryString,\n queue = [],\n requestData = {},\n options = {\n acceptHeader: null,\n validMethods: [\"PATCH\", \"POST\", \"PUT\"],\n method: \"POST\",\n contentType: \"application/x-www-form-urlencoded\",\n maxConnections: 3,\n customHeaders: {},\n endpointStore: {},\n paramsStore: {},\n mandatedParams: {},\n allowXRequestedWithAndCacheControl: true,\n successfulResponseCodes: {\n DELETE: [200, 202, 204],\n PATCH: [200, 201, 202, 203, 204],\n POST: [200, 201, 202, 203, 204],\n PUT: [200, 201, 202, 203, 204],\n GET: [200]\n },\n cors: {\n expected: false,\n sendCredentials: false\n },\n log: function(str, level) {},\n onSend: function(id) {},\n onComplete: function(id, xhrOrXdr, isError) {},\n onProgress: null\n };\n\n qq.extend(options, o);\n log = options.log;\n\n if (qq.indexOf(options.validMethods, options.method) < 0) {\n throw new Error(\"'\" + options.method + \"' is not a supported method for this type of request!\");\n }\n\n // [Simple methods](http://www.w3.org/TR/cors/#simple-method)\n // are defined by the W3C in the CORS spec as a list of methods that, in part,\n // make a CORS request eligible to be exempt from preflighting.\n function isSimpleMethod() {\n return qq.indexOf([\"GET\", \"POST\", \"HEAD\"], options.method) >= 0;\n }\n\n // [Simple headers](http://www.w3.org/TR/cors/#simple-header)\n // are defined by the W3C in the CORS spec as a list of headers that, in part,\n // make a CORS request eligible to be exempt from preflighting.\n function containsNonSimpleHeaders(headers) {\n var containsNonSimple = false;\n\n qq.each(containsNonSimple, function(idx, header) {\n if (qq.indexOf([\"Accept\", \"Accept-Language\", \"Content-Language\", \"Content-Type\"], header) < 0) {\n containsNonSimple = true;\n return false;\n }\n });\n\n return containsNonSimple;\n }\n\n function isXdr(xhr) {\n //The `withCredentials` test is a commonly accepted way to determine if XHR supports CORS.\n return options.cors.expected && xhr.withCredentials === undefined;\n }\n\n // Returns either a new `XMLHttpRequest` or `XDomainRequest` instance.\n function getCorsAjaxTransport() {\n var xhrOrXdr;\n\n if (window.XMLHttpRequest || window.ActiveXObject) {\n xhrOrXdr = qq.createXhrInstance();\n\n if (xhrOrXdr.withCredentials === undefined) {\n xhrOrXdr = new XDomainRequest();\n // Workaround for XDR bug in IE9 - https://social.msdn.microsoft.com/Forums/ie/en-US/30ef3add-767c-4436-b8a9-f1ca19b4812e/ie9-rtm-xdomainrequest-issued-requests-may-abort-if-all-event-handlers-not-specified?forum=iewebdevelopment\n xhrOrXdr.onload = function() {};\n xhrOrXdr.onerror = function() {};\n xhrOrXdr.ontimeout = function() {};\n xhrOrXdr.onprogress = function() {};\n }\n }\n\n return xhrOrXdr;\n }\n\n // Returns either a new XHR/XDR instance, or an existing one for the associated `File` or `Blob`.\n function getXhrOrXdr(id, suppliedXhr) {\n var xhrOrXdr = requestData[id].xhr;\n\n if (!xhrOrXdr) {\n if (suppliedXhr) {\n xhrOrXdr = suppliedXhr;\n }\n else {\n if (options.cors.expected) {\n xhrOrXdr = getCorsAjaxTransport();\n }\n else {\n xhrOrXdr = qq.createXhrInstance();\n }\n }\n\n requestData[id].xhr = xhrOrXdr;\n }\n\n return xhrOrXdr;\n }\n\n // Removes element from queue, sends next request\n function dequeue(id) {\n var i = qq.indexOf(queue, id),\n max = options.maxConnections,\n nextId;\n\n delete requestData[id];\n queue.splice(i, 1);\n\n if (queue.length >= max && i < max) {\n nextId = queue[max - 1];\n sendRequest(nextId);\n }\n }\n\n function onComplete(id, xdrError) {\n var xhr = getXhrOrXdr(id),\n method = options.method,\n isError = xdrError === true;\n\n dequeue(id);\n\n if (isError) {\n log(method + \" request for \" + id + \" has failed\", \"error\");\n }\n else if (!isXdr(xhr) && !isResponseSuccessful(xhr.status)) {\n isError = true;\n log(method + \" request for \" + id + \" has failed - response code \" + xhr.status, \"error\");\n }\n\n options.onComplete(id, xhr, isError);\n }\n\n function getParams(id) {\n var onDemandParams = requestData[id].additionalParams,\n mandatedParams = options.mandatedParams,\n params;\n\n if (options.paramsStore.get) {\n params = options.paramsStore.get(id);\n }\n\n if (onDemandParams) {\n qq.each(onDemandParams, function(name, val) {\n params = params || {};\n params[name] = val;\n });\n }\n\n if (mandatedParams) {\n qq.each(mandatedParams, function(name, val) {\n params = params || {};\n params[name] = val;\n });\n }\n\n return params;\n }\n\n function sendRequest(id, optXhr) {\n var xhr = getXhrOrXdr(id, optXhr),\n method = options.method,\n params = getParams(id),\n payload = requestData[id].payload,\n url;\n\n options.onSend(id);\n\n url = createUrl(id, params, requestData[id].additionalQueryParams);\n\n // XDR and XHR status detection APIs differ a bit.\n if (isXdr(xhr)) {\n xhr.onload = getXdrLoadHandler(id);\n xhr.onerror = getXdrErrorHandler(id);\n }\n else {\n xhr.onreadystatechange = getXhrReadyStateChangeHandler(id);\n }\n\n registerForUploadProgress(id);\n\n // The last parameter is assumed to be ignored if we are actually using `XDomainRequest`.\n xhr.open(method, url, true);\n\n // Instruct the transport to send cookies along with the CORS request,\n // unless we are using `XDomainRequest`, which is not capable of this.\n if (options.cors.expected && options.cors.sendCredentials && !isXdr(xhr)) {\n xhr.withCredentials = true;\n }\n\n setHeaders(id);\n\n log(\"Sending \" + method + \" request for \" + id);\n\n if (payload) {\n xhr.send(payload);\n }\n else if (shouldParamsBeInQueryString || !params) {\n xhr.send();\n }\n else if (params && options.contentType && options.contentType.toLowerCase().indexOf(\"application/x-www-form-urlencoded\") >= 0) {\n xhr.send(qq.obj2url(params, \"\"));\n }\n else if (params && options.contentType && options.contentType.toLowerCase().indexOf(\"application/json\") >= 0) {\n xhr.send(JSON.stringify(params));\n }\n else {\n xhr.send(params);\n }\n\n return xhr;\n }\n\n function createUrl(id, params, additionalQueryParams) {\n var endpoint = options.endpointStore.get(id),\n addToPath = requestData[id].addToPath;\n\n /*jshint -W116,-W041 */\n if (addToPath != undefined) {\n endpoint += \"/\" + addToPath;\n }\n\n if (shouldParamsBeInQueryString && params) {\n endpoint = qq.obj2url(params, endpoint);\n }\n\n if (additionalQueryParams) {\n endpoint = qq.obj2url(additionalQueryParams, endpoint);\n }\n\n return endpoint;\n }\n\n // Invoked by the UA to indicate a number of possible states that describe\n // a live `XMLHttpRequest` transport.\n function getXhrReadyStateChangeHandler(id) {\n return function() {\n if (getXhrOrXdr(id).readyState === 4) {\n onComplete(id);\n }\n };\n }\n\n function registerForUploadProgress(id) {\n var onProgress = options.onProgress;\n\n if (onProgress) {\n getXhrOrXdr(id).upload.onprogress = function(e) {\n if (e.lengthComputable) {\n onProgress(id, e.loaded, e.total);\n }\n };\n }\n }\n\n // This will be called by IE to indicate **success** for an associated\n // `XDomainRequest` transported request.\n function getXdrLoadHandler(id) {\n return function() {\n onComplete(id);\n };\n }\n\n // This will be called by IE to indicate **failure** for an associated\n // `XDomainRequest` transported request.\n function getXdrErrorHandler(id) {\n return function() {\n onComplete(id, true);\n };\n }\n\n function setHeaders(id) {\n var xhr = getXhrOrXdr(id),\n customHeaders = options.customHeaders,\n onDemandHeaders = requestData[id].additionalHeaders || {},\n method = options.method,\n allHeaders = {};\n\n // If XDomainRequest is being used, we can't set headers, so just ignore this block.\n if (!isXdr(xhr)) {\n options.acceptHeader && xhr.setRequestHeader(\"Accept\", options.acceptHeader);\n\n // Only attempt to add X-Requested-With & Cache-Control if permitted\n if (options.allowXRequestedWithAndCacheControl) {\n // Do not add X-Requested-With & Cache-Control if this is a cross-origin request\n // OR the cross-origin request contains a non-simple method or header.\n // This is done to ensure a preflight is not triggered exclusively based on the\n // addition of these 2 non-simple headers.\n if (!options.cors.expected || (!isSimpleMethod() || containsNonSimpleHeaders(customHeaders))) {\n xhr.setRequestHeader(\"X-Requested-With\", \"XMLHttpRequest\");\n xhr.setRequestHeader(\"Cache-Control\", \"no-cache\");\n }\n }\n\n if (options.contentType && (method === \"POST\" || method === \"PUT\")) {\n xhr.setRequestHeader(\"Content-Type\", options.contentType);\n }\n\n qq.extend(allHeaders, qq.isFunction(customHeaders) ? customHeaders(id) : customHeaders);\n qq.extend(allHeaders, onDemandHeaders);\n\n qq.each(allHeaders, function(name, val) {\n xhr.setRequestHeader(name, val);\n });\n }\n }\n\n function isResponseSuccessful(responseCode) {\n return qq.indexOf(options.successfulResponseCodes[options.method], responseCode) >= 0;\n }\n\n function prepareToSend(id, optXhr, addToPath, additionalParams, additionalQueryParams, additionalHeaders, payload) {\n requestData[id] = {\n addToPath: addToPath,\n additionalParams: additionalParams,\n additionalQueryParams: additionalQueryParams,\n additionalHeaders: additionalHeaders,\n payload: payload\n };\n\n var len = queue.push(id);\n\n // if too many active connections, wait...\n if (len <= options.maxConnections) {\n return sendRequest(id, optXhr);\n }\n }\n\n shouldParamsBeInQueryString = options.method === \"GET\" || options.method === \"DELETE\";\n\n qq.extend(this, {\n // Start the process of sending the request. The ID refers to the file associated with the request.\n initTransport: function(id) {\n var path, params, headers, payload, cacheBuster, additionalQueryParams;\n\n return {\n // Optionally specify the end of the endpoint path for the request.\n withPath: function(appendToPath) {\n path = appendToPath;\n return this;\n },\n\n // Optionally specify additional parameters to send along with the request.\n // These will be added to the query string for GET/DELETE requests or the payload\n // for POST/PUT requests. The Content-Type of the request will be used to determine\n // how these parameters should be formatted as well.\n withParams: function(additionalParams) {\n params = additionalParams;\n return this;\n },\n\n withQueryParams: function(_additionalQueryParams_) {\n additionalQueryParams = _additionalQueryParams_;\n return this;\n },\n\n // Optionally specify additional headers to send along with the request.\n withHeaders: function(additionalHeaders) {\n headers = additionalHeaders;\n return this;\n },\n\n // Optionally specify a payload/body for the request.\n withPayload: function(thePayload) {\n payload = thePayload;\n return this;\n },\n\n // Appends a cache buster (timestamp) to the request URL as a query parameter (only if GET or DELETE)\n withCacheBuster: function() {\n cacheBuster = true;\n return this;\n },\n\n // Send the constructed request.\n send: function(optXhr) {\n if (cacheBuster && qq.indexOf([\"GET\", \"DELETE\"], options.method) >= 0) {\n params.qqtimestamp = new Date().getTime();\n }\n\n return prepareToSend(id, optXhr, path, params, additionalQueryParams, headers, payload);\n }\n };\n },\n\n canceled: function(id) {\n dequeue(id);\n }\n });\n};\n","/* globals qq */\n/**\n * Common upload handler functions.\n *\n * @constructor\n */\nqq.UploadHandler = function(spec) {\n \"use strict\";\n\n var proxy = spec.proxy,\n fileState = {},\n onCancel = proxy.onCancel,\n getName = proxy.getName;\n\n qq.extend(this, {\n add: function(id, fileItem) {\n fileState[id] = fileItem;\n fileState[id].temp = {};\n },\n\n cancel: function(id) {\n var self = this,\n cancelFinalizationEffort = new qq.Promise(),\n onCancelRetVal = onCancel(id, getName(id), cancelFinalizationEffort);\n\n onCancelRetVal.then(function() {\n if (self.isValid(id)) {\n fileState[id].canceled = true;\n self.expunge(id);\n }\n cancelFinalizationEffort.success();\n });\n },\n\n expunge: function(id) {\n delete fileState[id];\n },\n\n getThirdPartyFileId: function(id) {\n return fileState[id].key;\n },\n\n isValid: function(id) {\n return fileState[id] !== undefined;\n },\n\n reset: function() {\n fileState = {};\n },\n\n _getFileState: function(id) {\n return fileState[id];\n },\n\n _setThirdPartyFileId: function(id, thirdPartyFileId) {\n fileState[id].key = thirdPartyFileId;\n },\n\n _wasCanceled: function(id) {\n return !!fileState[id].canceled;\n }\n });\n};\n","/*globals qq*/\n/**\n * Base upload handler module. Controls more specific handlers.\n *\n * @param o Options. Passed along to the specific handler submodule as well.\n * @param namespace [optional] Namespace for the specific handler.\n */\nqq.UploadHandlerController = function(o, namespace) {\n \"use strict\";\n\n var controller = this,\n chunkingPossible = false,\n concurrentChunkingPossible = false,\n chunking, preventRetryResponse, log, handler,\n\n options = {\n paramsStore: {},\n maxConnections: 3, // maximum number of concurrent uploads\n chunking: {\n enabled: false,\n multiple: {\n enabled: false\n }\n },\n log: function(str, level) {},\n onProgress: function(id, fileName, loaded, total) {},\n onComplete: function(id, fileName, response, xhr) {},\n onCancel: function(id, fileName) {},\n onUploadPrep: function(id) {}, // Called if non-trivial operations will be performed before onUpload\n onUpload: function(id, fileName) {},\n onUploadChunk: function(id, fileName, chunkData) {},\n onUploadChunkSuccess: function(id, chunkData, response, xhr) {},\n onAutoRetry: function(id, fileName, response, xhr) {},\n onResume: function(id, fileName, chunkData) {},\n onUuidChanged: function(id, newUuid) {},\n getName: function(id) {},\n setSize: function(id, newSize) {},\n isQueued: function(id) {},\n getIdsInProxyGroup: function(id) {},\n getIdsInBatch: function(id) {}\n },\n\n chunked = {\n // Called when each chunk has uploaded successfully\n done: function(id, chunkIdx, response, xhr) {\n var chunkData = handler._getChunkData(id, chunkIdx);\n\n handler._getFileState(id).attemptingResume = false;\n\n delete handler._getFileState(id).temp.chunkProgress[chunkIdx];\n handler._getFileState(id).loaded += chunkData.size;\n\n options.onUploadChunkSuccess(id, handler._getChunkDataForCallback(chunkData), response, xhr);\n },\n\n // Called when all chunks have been successfully uploaded and we want to ask the handler to perform any\n // logic associated with closing out the file, such as combining the chunks.\n finalize: function(id) {\n var size = options.getSize(id),\n name = options.getName(id);\n\n log(\"All chunks have been uploaded for \" + id + \" - finalizing....\");\n handler.finalizeChunks(id).then(\n function(response, xhr) {\n log(\"Finalize successful for \" + id);\n\n var normaizedResponse = upload.normalizeResponse(response, true);\n\n options.onProgress(id, name, size, size);\n handler._maybeDeletePersistedChunkData(id);\n upload.cleanup(id, normaizedResponse, xhr);\n },\n function(response, xhr) {\n var normaizedResponse = upload.normalizeResponse(response, false);\n\n log(\"Problem finalizing chunks for file ID \" + id + \" - \" + normaizedResponse.error, \"error\");\n\n if (normaizedResponse.reset) {\n chunked.reset(id);\n }\n\n if (!options.onAutoRetry(id, name, normaizedResponse, xhr)) {\n upload.cleanup(id, normaizedResponse, xhr);\n }\n }\n );\n },\n\n handleFailure: function(chunkIdx, id, response, xhr) {\n var name = options.getName(id);\n\n log(\"Chunked upload request failed for \" + id + \", chunk \" + chunkIdx);\n\n handler.clearCachedChunk(id, chunkIdx);\n\n var responseToReport = upload.normalizeResponse(response, false),\n inProgressIdx;\n\n if (responseToReport.reset) {\n chunked.reset(id);\n }\n else {\n inProgressIdx = qq.indexOf(handler._getFileState(id).chunking.inProgress, chunkIdx);\n if (inProgressIdx >= 0) {\n handler._getFileState(id).chunking.inProgress.splice(inProgressIdx, 1);\n handler._getFileState(id).chunking.remaining.unshift(chunkIdx);\n }\n }\n\n // We may have aborted all other in-progress chunks for this file due to a failure.\n // If so, ignore the failures associated with those aborts.\n if (!handler._getFileState(id).temp.ignoreFailure) {\n // If this chunk has failed, we want to ignore all other failures of currently in-progress\n // chunks since they will be explicitly aborted\n if (concurrentChunkingPossible) {\n handler._getFileState(id).temp.ignoreFailure = true;\n\n log(qq.format(\"Going to attempt to abort these chunks: {}. These are currently in-progress: {}.\", JSON.stringify(Object.keys(handler._getXhrs(id))), JSON.stringify(handler._getFileState(id).chunking.inProgress)));\n qq.each(handler._getXhrs(id), function(ckid, ckXhr) {\n log(qq.format(\"Attempting to abort file {}.{}. XHR readyState {}. \", id, ckid, ckXhr.readyState));\n ckXhr.abort();\n // Flag the transport, in case we are waiting for some other async operation\n // to complete before attempting to upload the chunk\n ckXhr._cancelled = true;\n });\n\n // We must indicate that all aborted chunks are no longer in progress\n handler.moveInProgressToRemaining(id);\n\n // Free up any connections used by these chunks, but don't allow any\n // other files to take up the connections (until we have exhausted all auto-retries)\n connectionManager.free(id, true);\n }\n\n if (!options.onAutoRetry(id, name, responseToReport, xhr)) {\n // If one chunk fails, abort all of the others to avoid odd race conditions that occur\n // if a chunk succeeds immediately after one fails before we have determined if the upload\n // is a failure or not.\n upload.cleanup(id, responseToReport, xhr);\n }\n }\n },\n\n hasMoreParts: function(id) {\n return !!handler._getFileState(id).chunking.remaining.length;\n },\n\n nextPart: function(id) {\n var nextIdx = handler._getFileState(id).chunking.remaining.shift();\n\n if (nextIdx >= handler._getTotalChunks(id)) {\n nextIdx = null;\n }\n\n return nextIdx;\n },\n\n reset: function(id) {\n log(\"Server or callback has ordered chunking effort to be restarted on next attempt for item ID \" + id, \"error\");\n\n handler._maybeDeletePersistedChunkData(id);\n handler.reevaluateChunking(id);\n handler._getFileState(id).loaded = 0;\n },\n\n sendNext: function(id) {\n var size = options.getSize(id),\n name = options.getName(id),\n chunkIdx = chunked.nextPart(id),\n chunkData = handler._getChunkData(id, chunkIdx),\n resuming = handler._getFileState(id).attemptingResume,\n inProgressChunks = handler._getFileState(id).chunking.inProgress || [];\n\n if (handler._getFileState(id).loaded == null) {\n handler._getFileState(id).loaded = 0;\n }\n\n // Don't follow-through with the resume attempt if the integrator returns false from onResume\n if (resuming && options.onResume(id, name, chunkData) === false) {\n chunked.reset(id);\n chunkIdx = chunked.nextPart(id);\n chunkData = handler._getChunkData(id, chunkIdx);\n resuming = false;\n }\n\n // If all chunks have already uploaded successfully, we must be re-attempting the finalize step.\n if (chunkIdx == null && inProgressChunks.length === 0) {\n chunked.finalize(id);\n }\n\n // Send the next chunk\n else {\n log(qq.format(\"Sending chunked upload request for item {}.{}, bytes {}-{} of {}.\", id, chunkIdx, chunkData.start + 1, chunkData.end, size));\n options.onUploadChunk(id, name, handler._getChunkDataForCallback(chunkData));\n inProgressChunks.push(chunkIdx);\n handler._getFileState(id).chunking.inProgress = inProgressChunks;\n\n if (concurrentChunkingPossible) {\n connectionManager.open(id, chunkIdx);\n }\n\n if (concurrentChunkingPossible && connectionManager.available() && handler._getFileState(id).chunking.remaining.length) {\n chunked.sendNext(id);\n }\n\n if (chunkData.blob.size === 0) {\n log(qq.format(\"Chunk {} for file {} will not be uploaded, zero sized chunk.\", chunkIdx, id), \"error\");\n chunked.handleFailure(chunkIdx, id, \"File is no longer available\", null);\n }\n else {\n handler.uploadChunk(id, chunkIdx, resuming).then(\n // upload chunk success\n function success(response, xhr) {\n log(\"Chunked upload request succeeded for \" + id + \", chunk \" + chunkIdx);\n\n handler.clearCachedChunk(id, chunkIdx);\n\n var inProgressChunks = handler._getFileState(id).chunking.inProgress || [],\n responseToReport = upload.normalizeResponse(response, true),\n inProgressChunkIdx = qq.indexOf(inProgressChunks, chunkIdx);\n\n log(qq.format(\"Chunk {} for file {} uploaded successfully.\", chunkIdx, id));\n\n chunked.done(id, chunkIdx, responseToReport, xhr);\n\n if (inProgressChunkIdx >= 0) {\n inProgressChunks.splice(inProgressChunkIdx, 1);\n }\n\n handler._maybePersistChunkedState(id);\n\n if (!chunked.hasMoreParts(id) && inProgressChunks.length === 0) {\n chunked.finalize(id);\n }\n else if (chunked.hasMoreParts(id)) {\n chunked.sendNext(id);\n }\n else {\n log(qq.format(\"File ID {} has no more chunks to send and these chunk indexes are still marked as in-progress: {}\", id, JSON.stringify(inProgressChunks)));\n }\n },\n\n // upload chunk failure\n function failure(response, xhr) {\n chunked.handleFailure(chunkIdx, id, response, xhr);\n }\n )\n .done(function() {\n handler.clearXhr(id, chunkIdx);\n });\n }\n }\n }\n },\n\n connectionManager = {\n _open: [],\n _openChunks: {},\n _waiting: [],\n\n available: function() {\n var max = options.maxConnections,\n openChunkEntriesCount = 0,\n openChunksCount = 0;\n\n qq.each(connectionManager._openChunks, function(fileId, openChunkIndexes) {\n openChunkEntriesCount++;\n openChunksCount += openChunkIndexes.length;\n });\n\n return max - (connectionManager._open.length - openChunkEntriesCount + openChunksCount);\n },\n\n /**\n * Removes element from queue, starts upload of next\n */\n free: function(id, dontAllowNext) {\n var allowNext = !dontAllowNext,\n waitingIndex = qq.indexOf(connectionManager._waiting, id),\n connectionsIndex = qq.indexOf(connectionManager._open, id),\n nextId;\n\n delete connectionManager._openChunks[id];\n\n if (upload.getProxyOrBlob(id) instanceof qq.BlobProxy) {\n log(\"Generated blob upload has ended for \" + id + \", disposing generated blob.\");\n delete handler._getFileState(id).file;\n }\n\n // If this file was not consuming a connection, it was just waiting, so remove it from the waiting array\n if (waitingIndex >= 0) {\n connectionManager._waiting.splice(waitingIndex, 1);\n }\n // If this file was consuming a connection, allow the next file to be uploaded\n else if (allowNext && connectionsIndex >= 0) {\n connectionManager._open.splice(connectionsIndex, 1);\n\n nextId = connectionManager._waiting.shift();\n if (nextId >= 0) {\n connectionManager._open.push(nextId);\n upload.start(nextId);\n }\n }\n },\n\n getWaitingOrConnected: function() {\n var waitingOrConnected = [];\n\n // Chunked files may have multiple connections open per chunk (if concurrent chunking is enabled)\n // We need to grab the file ID of any file that has at least one chunk consuming a connection.\n qq.each(connectionManager._openChunks, function(fileId, chunks) {\n if (chunks && chunks.length) {\n waitingOrConnected.push(parseInt(fileId));\n }\n });\n\n // For non-chunked files, only one connection will be consumed per file.\n // This is where we aggregate those file IDs.\n qq.each(connectionManager._open, function(idx, fileId) {\n if (!connectionManager._openChunks[fileId]) {\n waitingOrConnected.push(parseInt(fileId));\n }\n });\n\n // There may be files waiting for a connection.\n waitingOrConnected = waitingOrConnected.concat(connectionManager._waiting);\n\n return waitingOrConnected;\n },\n\n isUsingConnection: function(id) {\n return qq.indexOf(connectionManager._open, id) >= 0;\n },\n\n open: function(id, chunkIdx) {\n if (chunkIdx == null) {\n connectionManager._waiting.push(id);\n }\n\n if (connectionManager.available()) {\n if (chunkIdx == null) {\n connectionManager._waiting.pop();\n connectionManager._open.push(id);\n }\n else {\n (function() {\n var openChunksEntry = connectionManager._openChunks[id] || [];\n openChunksEntry.push(chunkIdx);\n connectionManager._openChunks[id] = openChunksEntry;\n }());\n }\n\n return true;\n }\n\n return false;\n },\n\n reset: function() {\n connectionManager._waiting = [];\n connectionManager._open = [];\n }\n },\n\n simple = {\n send: function(id, name) {\n handler._getFileState(id).loaded = 0;\n\n log(\"Sending simple upload request for \" + id);\n handler.uploadFile(id).then(\n function(response, optXhr) {\n log(\"Simple upload request succeeded for \" + id);\n\n var responseToReport = upload.normalizeResponse(response, true),\n size = options.getSize(id);\n\n options.onProgress(id, name, size, size);\n upload.maybeNewUuid(id, responseToReport);\n upload.cleanup(id, responseToReport, optXhr);\n },\n\n function(response, optXhr) {\n log(\"Simple upload request failed for \" + id);\n\n var responseToReport = upload.normalizeResponse(response, false);\n\n if (!options.onAutoRetry(id, name, responseToReport, optXhr)) {\n upload.cleanup(id, responseToReport, optXhr);\n }\n }\n );\n }\n },\n\n upload = {\n cancel: function(id) {\n log(\"Cancelling \" + id);\n options.paramsStore.remove(id);\n connectionManager.free(id);\n },\n\n cleanup: function(id, response, optXhr) {\n var name = options.getName(id);\n\n options.onComplete(id, name, response, optXhr);\n\n if (handler._getFileState(id)) {\n handler._clearXhrs && handler._clearXhrs(id);\n }\n\n connectionManager.free(id);\n },\n\n // Returns a qq.BlobProxy, or an actual File/Blob if no proxy is involved, or undefined\n // if none of these are available for the ID\n getProxyOrBlob: function(id) {\n return (handler.getProxy && handler.getProxy(id)) ||\n (handler.getFile && handler.getFile(id));\n },\n\n initHandler: function() {\n var handlerType = namespace ? qq[namespace] : qq.traditional,\n handlerModuleSubtype = qq.supportedFeatures.ajaxUploading ? \"Xhr\" : \"Form\";\n\n handler = new handlerType[handlerModuleSubtype + \"UploadHandler\"](\n options,\n {\n getDataByUuid: options.getDataByUuid,\n getName: options.getName,\n getSize: options.getSize,\n getUuid: options.getUuid,\n log: log,\n onCancel: options.onCancel,\n onProgress: options.onProgress,\n onUuidChanged: options.onUuidChanged\n }\n );\n\n if (handler._removeExpiredChunkingRecords) {\n handler._removeExpiredChunkingRecords();\n }\n },\n\n isDeferredEligibleForUpload: function(id) {\n return options.isQueued(id);\n },\n\n // For Blobs that are part of a group of generated images, along with a reference image,\n // this will ensure the blobs in the group are uploaded in the order they were triggered,\n // even if some async processing must be completed on one or more Blobs first.\n maybeDefer: function(id, blob) {\n // If we don't have a file/blob yet & no file/blob exists for this item, request it,\n // and then submit the upload to the specific handler once the blob is available.\n // ASSUMPTION: This condition will only ever be true if XHR uploading is supported.\n if (blob && !handler.getFile(id) && blob instanceof qq.BlobProxy) {\n\n // Blob creation may take some time, so the caller may want to update the\n // UI to indicate that an operation is in progress, even before the actual\n // upload begins and an onUpload callback is invoked.\n options.onUploadPrep(id);\n\n log(\"Attempting to generate a blob on-demand for \" + id);\n blob.create().then(function(generatedBlob) {\n log(\"Generated an on-demand blob for \" + id);\n\n // Update record associated with this file by providing the generated Blob\n handler.updateBlob(id, generatedBlob);\n\n // Propagate the size for this generated Blob\n options.setSize(id, generatedBlob.size);\n\n // Order handler to recalculate chunking possibility, if applicable\n handler.reevaluateChunking(id);\n\n upload.maybeSendDeferredFiles(id);\n },\n\n // Blob could not be generated. Fail the upload & attempt to prevent retries. Also bubble error message.\n function(errorMessage) {\n var errorResponse = {};\n\n if (errorMessage) {\n errorResponse.error = errorMessage;\n }\n\n log(qq.format(\"Failed to generate blob for ID {}. Error message: {}.\", id, errorMessage), \"error\");\n\n options.onComplete(id, options.getName(id), qq.extend(errorResponse, preventRetryResponse), null);\n upload.maybeSendDeferredFiles(id);\n connectionManager.free(id);\n });\n }\n else {\n return upload.maybeSendDeferredFiles(id);\n }\n\n return false;\n },\n\n // Upload any grouped blobs, in the proper order, that are ready to be uploaded\n maybeSendDeferredFiles: function(id) {\n var idsInGroup = options.getIdsInProxyGroup(id),\n uploadedThisId = false;\n\n if (idsInGroup && idsInGroup.length) {\n log(\"Maybe ready to upload proxy group file \" + id);\n\n qq.each(idsInGroup, function(idx, idInGroup) {\n if (upload.isDeferredEligibleForUpload(idInGroup) && !!handler.getFile(idInGroup)) {\n uploadedThisId = idInGroup === id;\n upload.now(idInGroup);\n }\n else if (upload.isDeferredEligibleForUpload(idInGroup)) {\n return false;\n }\n });\n }\n else {\n uploadedThisId = true;\n upload.now(id);\n }\n\n return uploadedThisId;\n },\n\n maybeNewUuid: function(id, response) {\n if (response.newUuid !== undefined) {\n options.onUuidChanged(id, response.newUuid);\n }\n },\n\n // The response coming from handler implementations may be in various formats.\n // Instead of hoping a promise nested 5 levels deep will always return an object\n // as its first param, let's just normalize the response here.\n normalizeResponse: function(originalResponse, successful) {\n var response = originalResponse;\n\n // The passed \"response\" param may not be a response at all.\n // It could be a string, detailing the error, for example.\n if (!qq.isObject(originalResponse)) {\n response = {};\n\n if (qq.isString(originalResponse) && !successful) {\n response.error = originalResponse;\n }\n }\n\n response.success = successful;\n\n return response;\n },\n\n now: function(id) {\n var name = options.getName(id);\n\n if (!controller.isValid(id)) {\n throw new qq.Error(id + \" is not a valid file ID to upload!\");\n }\n\n options.onUpload(id, name);\n\n if (chunkingPossible && handler._shouldChunkThisFile(id)) {\n chunked.sendNext(id);\n }\n else {\n simple.send(id, name);\n }\n },\n\n start: function(id) {\n var blobToUpload = upload.getProxyOrBlob(id);\n\n if (blobToUpload) {\n return upload.maybeDefer(id, blobToUpload);\n }\n else {\n upload.now(id);\n return true;\n }\n }\n };\n\n qq.extend(this, {\n /**\n * Adds file or file input to the queue\n **/\n add: function(id, file) {\n handler.add.apply(this, arguments);\n },\n\n /**\n * Sends the file identified by id\n */\n upload: function(id) {\n if (connectionManager.open(id)) {\n return upload.start(id);\n }\n return false;\n },\n\n retry: function(id) {\n // On retry, if concurrent chunking has been enabled, we may have aborted all other in-progress chunks\n // for a file when encountering a failed chunk upload. We then signaled the controller to ignore\n // all failures associated with these aborts. We are now retrying, so we don't want to ignore\n // any more failures at this point.\n if (concurrentChunkingPossible) {\n handler._getFileState(id).temp.ignoreFailure = false;\n }\n\n // If we are attempting to retry a file that is already consuming a connection, this is likely an auto-retry.\n // Just go ahead and ask the handler to upload again.\n if (connectionManager.isUsingConnection(id)) {\n return upload.start(id);\n }\n\n // If we are attempting to retry a file that is not currently consuming a connection,\n // this is likely a manual retry attempt. We will need to ensure a connection is available\n // before the retry commences.\n else {\n return controller.upload(id);\n }\n },\n\n /**\n * Cancels file upload by id\n */\n cancel: function(id) {\n var cancelRetVal = handler.cancel(id);\n\n if (qq.isGenericPromise(cancelRetVal)) {\n cancelRetVal.then(function() {\n upload.cancel(id);\n });\n }\n else if (cancelRetVal !== false) {\n upload.cancel(id);\n }\n },\n\n /**\n * Cancels all queued or in-progress uploads\n */\n cancelAll: function() {\n var waitingOrConnected = connectionManager.getWaitingOrConnected(),\n i;\n\n // ensure files are cancelled in reverse order which they were added\n // to avoid a flash of time where a queued file begins to upload before it is canceled\n if (waitingOrConnected.length) {\n for (i = waitingOrConnected.length - 1; i >= 0; i--) {\n controller.cancel(waitingOrConnected[i]);\n }\n }\n\n connectionManager.reset();\n },\n\n // Returns a File, Blob, or the Blob/File for the reference/parent file if the targeted blob is a proxy.\n // Undefined if no file record is available.\n getFile: function(id) {\n if (handler.getProxy && handler.getProxy(id)) {\n return handler.getProxy(id).referenceBlob;\n }\n\n return handler.getFile && handler.getFile(id);\n },\n\n // Returns true if the Blob associated with the ID is related to a proxy s\n isProxied: function(id) {\n return !!(handler.getProxy && handler.getProxy(id));\n },\n\n getInput: function(id) {\n if (handler.getInput) {\n return handler.getInput(id);\n }\n },\n\n reset: function() {\n log(\"Resetting upload handler\");\n controller.cancelAll();\n connectionManager.reset();\n handler.reset();\n },\n\n expunge: function(id) {\n if (controller.isValid(id)) {\n return handler.expunge(id);\n }\n },\n\n /**\n * Determine if the file exists.\n */\n isValid: function(id) {\n return handler.isValid(id);\n },\n\n getResumableFilesData: function() {\n if (handler.getResumableFilesData) {\n return handler.getResumableFilesData();\n }\n return [];\n },\n\n /**\n * This may or may not be implemented, depending on the handler. For handlers where a third-party ID is\n * available (such as the \"key\" for Amazon S3), this will return that value. Otherwise, the return value\n * will be undefined.\n *\n * @param id Internal file ID\n * @returns {*} Some identifier used by a 3rd-party service involved in the upload process\n */\n getThirdPartyFileId: function(id) {\n if (controller.isValid(id)) {\n return handler.getThirdPartyFileId(id);\n }\n },\n\n /**\n * Attempts to pause the associated upload if the specific handler supports this and the file is \"valid\".\n * @param id ID of the upload/file to pause\n * @returns {boolean} true if the upload was paused\n */\n pause: function(id) {\n if (controller.isResumable(id) && handler.pause && controller.isValid(id) && handler.pause(id)) {\n connectionManager.free(id);\n handler.moveInProgressToRemaining(id);\n return true;\n }\n return false;\n },\n\n // True if the file is eligible for pause/resume.\n isResumable: function(id) {\n return !!handler.isResumable && handler.isResumable(id);\n }\n });\n\n qq.extend(options, o);\n log = options.log;\n chunkingPossible = options.chunking.enabled && qq.supportedFeatures.chunking;\n concurrentChunkingPossible = chunkingPossible && options.chunking.concurrent.enabled;\n\n preventRetryResponse = (function() {\n var response = {};\n\n response[options.preventRetryParam] = true;\n\n return response;\n }());\n\n upload.initHandler();\n};\n","/*globals qq */\n/*jshint -W117 */\nqq.WindowReceiveMessage = function(o) {\n \"use strict\";\n\n var options = {\n log: function(message, level) {}\n },\n callbackWrapperDetachers = {};\n\n qq.extend(options, o);\n\n qq.extend(this, {\n receiveMessage: function(id, callback) {\n var onMessageCallbackWrapper = function(event) {\n callback(event.data);\n };\n\n if (window.postMessage) {\n callbackWrapperDetachers[id] = qq(window).attach(\"message\", onMessageCallbackWrapper);\n }\n else {\n log(\"iframe message passing not supported in this browser!\", \"error\");\n }\n },\n\n stopReceivingMessages: function(id) {\n if (window.postMessage) {\n var detacher = callbackWrapperDetachers[id];\n if (detacher) {\n detacher();\n }\n }\n }\n });\n};\n","/* globals qq */\n/**\n * Common APIs exposed to creators of upload via form/iframe handlers. This is reused and possibly overridden\n * in some cases by specific form upload handlers.\n *\n * @constructor\n */\nqq.FormUploadHandler = function(spec) {\n \"use strict\";\n\n var options = spec.options,\n handler = this,\n proxy = spec.proxy,\n formHandlerInstanceId = qq.getUniqueId(),\n onloadCallbacks = {},\n detachLoadEvents = {},\n postMessageCallbackTimers = {},\n isCors = options.isCors,\n inputName = options.inputName,\n getUuid = proxy.getUuid,\n log = proxy.log,\n corsMessageReceiver = new qq.WindowReceiveMessage({log: log});\n\n /**\n * Remove any trace of the file from the handler.\n *\n * @param id ID of the associated file\n */\n function expungeFile(id) {\n delete detachLoadEvents[id];\n\n // If we are dealing with CORS, we might still be waiting for a response from a loaded iframe.\n // In that case, terminate the timer waiting for a message from the loaded iframe\n // and stop listening for any more messages coming from this iframe.\n if (isCors) {\n clearTimeout(postMessageCallbackTimers[id]);\n delete postMessageCallbackTimers[id];\n corsMessageReceiver.stopReceivingMessages(id);\n }\n\n var iframe = document.getElementById(handler._getIframeName(id));\n if (iframe) {\n // To cancel request set src to something else. We use src=\"javascript:false;\"\n // because it doesn't trigger ie6 prompt on https\n /* jshint scripturl:true */\n iframe.setAttribute(\"src\", \"javascript:false;\");\n\n qq(iframe).remove();\n }\n }\n\n /**\n * @param iframeName `document`-unique Name of the associated iframe\n * @returns {*} ID of the associated file\n */\n function getFileIdForIframeName(iframeName) {\n return iframeName.split(\"_\")[0];\n }\n\n /**\n * Generates an iframe to be used as a target for upload-related form submits. This also adds the iframe\n * to the current `document`. Note that the iframe is hidden from view.\n *\n * @param name Name of the iframe.\n * @returns {HTMLIFrameElement} The created iframe\n */\n function initIframeForUpload(name) {\n var iframe = qq.toElement(\"\");\n\n iframe.setAttribute(\"id\", name);\n\n iframe.style.display = \"none\";\n document.body.appendChild(iframe);\n\n return iframe;\n }\n\n /**\n * If we are in CORS mode, we must listen for messages (containing the server response) from the associated\n * iframe, since we cannot directly parse the content of the iframe due to cross-origin restrictions.\n *\n * @param iframe Listen for messages on this iframe.\n * @param callback Invoke this callback with the message from the iframe.\n */\n function registerPostMessageCallback(iframe, callback) {\n var iframeName = iframe.id,\n fileId = getFileIdForIframeName(iframeName),\n uuid = getUuid(fileId);\n\n onloadCallbacks[uuid] = callback;\n\n // When the iframe has loaded (after the server responds to an upload request)\n // declare the attempt a failure if we don't receive a valid message shortly after the response comes in.\n detachLoadEvents[fileId] = qq(iframe).attach(\"load\", function() {\n if (handler.getInput(fileId)) {\n log(\"Received iframe load event for CORS upload request (iframe name \" + iframeName + \")\");\n\n postMessageCallbackTimers[iframeName] = setTimeout(function() {\n var errorMessage = \"No valid message received from loaded iframe for iframe name \" + iframeName;\n log(errorMessage, \"error\");\n callback({\n error: errorMessage\n });\n }, 1000);\n }\n });\n\n // Listen for messages coming from this iframe. When a message has been received, cancel the timer\n // that declares the upload a failure if a message is not received within a reasonable amount of time.\n corsMessageReceiver.receiveMessage(iframeName, function(message) {\n log(\"Received the following window message: '\" + message + \"'\");\n var fileId = getFileIdForIframeName(iframeName),\n response = handler._parseJsonResponse(message),\n uuid = response.uuid,\n onloadCallback;\n\n if (uuid && onloadCallbacks[uuid]) {\n log(\"Handling response for iframe name \" + iframeName);\n clearTimeout(postMessageCallbackTimers[iframeName]);\n delete postMessageCallbackTimers[iframeName];\n\n handler._detachLoadEvent(iframeName);\n\n onloadCallback = onloadCallbacks[uuid];\n\n delete onloadCallbacks[uuid];\n corsMessageReceiver.stopReceivingMessages(iframeName);\n onloadCallback(response);\n }\n else if (!uuid) {\n log(\"'\" + message + \"' does not contain a UUID - ignoring.\");\n }\n });\n }\n\n qq.extend(this, new qq.UploadHandler(spec));\n\n qq.override(this, function(super_) {\n return {\n /**\n * Adds File or Blob to the queue\n **/\n add: function(id, fileInput) {\n super_.add(id, {input: fileInput});\n\n fileInput.setAttribute(\"name\", inputName);\n\n // remove file input from DOM\n if (fileInput.parentNode) {\n qq(fileInput).remove();\n }\n },\n\n expunge: function(id) {\n expungeFile(id);\n super_.expunge(id);\n },\n\n isValid: function(id) {\n return super_.isValid(id) &&\n handler._getFileState(id).input !== undefined;\n }\n };\n });\n\n qq.extend(this, {\n getInput: function(id) {\n return handler._getFileState(id).input;\n },\n\n /**\n * This function either delegates to a more specific message handler if CORS is involved,\n * or simply registers a callback when the iframe has been loaded that invokes the passed callback\n * after determining if the content of the iframe is accessible.\n *\n * @param iframe Associated iframe\n * @param callback Callback to invoke after we have determined if the iframe content is accessible.\n */\n _attachLoadEvent: function(iframe, callback) {\n /*jslint eqeq: true*/\n var responseDescriptor;\n\n if (isCors) {\n registerPostMessageCallback(iframe, callback);\n }\n else {\n detachLoadEvents[iframe.id] = qq(iframe).attach(\"load\", function() {\n log(\"Received response for \" + iframe.id);\n\n // when we remove iframe from dom\n // the request stops, but in IE load\n // event fires\n if (!iframe.parentNode) {\n return;\n }\n\n try {\n // fixing Opera 10.53\n if (iframe.contentDocument &&\n iframe.contentDocument.body &&\n iframe.contentDocument.body.innerHTML == \"false\") {\n // In Opera event is fired second time\n // when body.innerHTML changed from false\n // to server response approx. after 1 sec\n // when we upload file with iframe\n return;\n }\n }\n catch (error) {\n //IE may throw an \"access is denied\" error when attempting to access contentDocument on the iframe in some cases\n log(\"Error when attempting to access iframe during handling of upload response (\" + error.message + \")\", \"error\");\n responseDescriptor = {success: false};\n }\n\n callback(responseDescriptor);\n });\n }\n },\n\n /**\n * Creates an iframe with a specific document-unique name.\n *\n * @param id ID of the associated file\n * @returns {HTMLIFrameElement}\n */\n _createIframe: function(id) {\n var iframeName = handler._getIframeName(id);\n\n return initIframeForUpload(iframeName);\n },\n\n /**\n * Called when we are no longer interested in being notified when an iframe has loaded.\n *\n * @param id Associated file ID\n */\n _detachLoadEvent: function(id) {\n if (detachLoadEvents[id] !== undefined) {\n detachLoadEvents[id]();\n delete detachLoadEvents[id];\n }\n },\n\n /**\n * @param fileId ID of the associated file\n * @returns {string} The `document`-unique name of the iframe\n */\n _getIframeName: function(fileId) {\n return fileId + \"_\" + formHandlerInstanceId;\n },\n\n /**\n * Generates a form element and appends it to the `document`. When the form is submitted, a specific iframe is targeted.\n * The name of the iframe is passed in as a property of the spec parameter, and must be unique in the `document`. Note\n * that the form is hidden from view.\n *\n * @param spec An object containing various properties to be used when constructing the form. Required properties are\n * currently: `method`, `endpoint`, `params`, `paramsInBody`, and `targetName`.\n * @returns {HTMLFormElement} The created form\n */\n _initFormForUpload: function(spec) {\n var method = spec.method,\n endpoint = spec.endpoint,\n params = spec.params,\n paramsInBody = spec.paramsInBody,\n targetName = spec.targetName,\n form = qq.toElement(\"\"),\n url = endpoint;\n\n if (paramsInBody) {\n qq.obj2Inputs(params, form);\n }\n else {\n url = qq.obj2url(params, endpoint);\n }\n\n form.setAttribute(\"action\", url);\n form.setAttribute(\"target\", targetName);\n form.style.display = \"none\";\n document.body.appendChild(form);\n\n return form;\n },\n\n /**\n * @param innerHtmlOrMessage JSON message\n * @returns {*} The parsed response, or an empty object if the response could not be parsed\n */\n _parseJsonResponse: function(innerHtmlOrMessage) {\n var response = {};\n\n try {\n response = qq.parseJson(innerHtmlOrMessage);\n }\n catch (error) {\n log(\"Error when attempting to parse iframe upload response (\" + error.message + \")\", \"error\");\n }\n\n return response;\n }\n });\n};\n","/* globals qq */\n/**\n * Common API exposed to creators of XHR handlers. This is reused and possibly overriding in some cases by specific\n * XHR upload handlers.\n *\n * @constructor\n */\nqq.XhrUploadHandler = function(spec) {\n \"use strict\";\n\n var handler = this,\n namespace = spec.options.namespace,\n proxy = spec.proxy,\n chunking = spec.options.chunking,\n resume = spec.options.resume,\n chunkFiles = chunking && spec.options.chunking.enabled && qq.supportedFeatures.chunking,\n resumeEnabled = resume && spec.options.resume.enabled && chunkFiles && qq.supportedFeatures.resume,\n getName = proxy.getName,\n getSize = proxy.getSize,\n getUuid = proxy.getUuid,\n getEndpoint = proxy.getEndpoint,\n getDataByUuid = proxy.getDataByUuid,\n onUuidChanged = proxy.onUuidChanged,\n onProgress = proxy.onProgress,\n log = proxy.log;\n\n function abort(id) {\n qq.each(handler._getXhrs(id), function(xhrId, xhr) {\n var ajaxRequester = handler._getAjaxRequester(id, xhrId);\n\n xhr.onreadystatechange = null;\n xhr.upload.onprogress = null;\n xhr.abort();\n ajaxRequester && ajaxRequester.canceled && ajaxRequester.canceled(id);\n });\n }\n\n qq.extend(this, new qq.UploadHandler(spec));\n\n qq.override(this, function(super_) {\n return {\n /**\n * Adds File or Blob to the queue\n **/\n add: function(id, blobOrProxy) {\n if (qq.isFile(blobOrProxy) || qq.isBlob(blobOrProxy)) {\n super_.add(id, {file: blobOrProxy});\n }\n else if (blobOrProxy instanceof qq.BlobProxy) {\n super_.add(id, {proxy: blobOrProxy});\n }\n else {\n throw new Error(\"Passed obj is not a File, Blob, or proxy\");\n }\n\n handler._initTempState(id);\n resumeEnabled && handler._maybePrepareForResume(id);\n },\n\n expunge: function(id) {\n abort(id);\n handler._maybeDeletePersistedChunkData(id);\n handler._clearXhrs(id);\n super_.expunge(id);\n }\n };\n });\n\n qq.extend(this, {\n // Clear the cached chunk `Blob` after we are done with it, just in case the `Blob` bytes are stored in memory.\n clearCachedChunk: function(id, chunkIdx) {\n delete handler._getFileState(id).temp.cachedChunks[chunkIdx];\n },\n\n clearXhr: function(id, chunkIdx) {\n var tempState = handler._getFileState(id).temp;\n\n if (tempState.xhrs) {\n delete tempState.xhrs[chunkIdx];\n }\n if (tempState.ajaxRequesters) {\n delete tempState.ajaxRequesters[chunkIdx];\n }\n },\n\n // Called when all chunks have been successfully uploaded. Expected promissory return type.\n // This defines the default behavior if nothing further is required when all chunks have been uploaded.\n finalizeChunks: function(id, responseParser) {\n var lastChunkIdx = handler._getTotalChunks(id) - 1,\n xhr = handler._getXhr(id, lastChunkIdx);\n\n if (responseParser) {\n return new qq.Promise().success(responseParser(xhr), xhr);\n }\n\n return new qq.Promise().success({}, xhr);\n },\n\n getFile: function(id) {\n return handler.isValid(id) && handler._getFileState(id).file;\n },\n\n getProxy: function(id) {\n return handler.isValid(id) && handler._getFileState(id).proxy;\n },\n\n /**\n * @returns {Array} Array of objects containing properties useful to integrators\n * when it is important to determine which files are potentially resumable.\n */\n getResumableFilesData: function() {\n var resumableFilesData = [];\n\n handler._iterateResumeRecords(function(key, uploadData) {\n handler.moveInProgressToRemaining(null, uploadData.chunking.inProgress, uploadData.chunking.remaining);\n\n var data = {\n name: uploadData.name,\n remaining: uploadData.chunking.remaining,\n size: uploadData.size,\n uuid: uploadData.uuid\n };\n\n if (uploadData.key) {\n data.key = uploadData.key;\n }\n\n resumableFilesData.push(data);\n });\n\n return resumableFilesData;\n },\n\n isResumable: function(id) {\n return !!chunking && handler.isValid(id) && !handler._getFileState(id).notResumable;\n },\n\n moveInProgressToRemaining: function(id, optInProgress, optRemaining) {\n var inProgress = optInProgress || handler._getFileState(id).chunking.inProgress,\n remaining = optRemaining || handler._getFileState(id).chunking.remaining;\n\n if (inProgress) {\n log(qq.format(\"Moving these chunks from in-progress {}, to remaining.\", JSON.stringify(inProgress)));\n inProgress.reverse();\n qq.each(inProgress, function(idx, chunkIdx) {\n remaining.unshift(chunkIdx);\n });\n inProgress.length = 0;\n }\n },\n\n pause: function(id) {\n if (handler.isValid(id)) {\n log(qq.format(\"Aborting XHR upload for {} '{}' due to pause instruction.\", id, getName(id)));\n handler._getFileState(id).paused = true;\n abort(id);\n return true;\n }\n },\n\n reevaluateChunking: function(id) {\n if (chunking && handler.isValid(id)) {\n var state = handler._getFileState(id),\n totalChunks,\n i;\n\n delete state.chunking;\n\n state.chunking = {};\n totalChunks = handler._getTotalChunks(id);\n if (totalChunks > 1 || chunking.mandatory) {\n state.chunking.enabled = true;\n state.chunking.parts = totalChunks;\n state.chunking.remaining = [];\n\n for (i = 0; i < totalChunks; i++) {\n state.chunking.remaining.push(i);\n }\n\n handler._initTempState(id);\n }\n else {\n state.chunking.enabled = false;\n }\n }\n },\n\n updateBlob: function(id, newBlob) {\n if (handler.isValid(id)) {\n handler._getFileState(id).file = newBlob;\n }\n },\n\n _clearXhrs: function(id) {\n var tempState = handler._getFileState(id).temp;\n\n qq.each(tempState.ajaxRequesters, function(chunkId) {\n delete tempState.ajaxRequesters[chunkId];\n });\n\n qq.each(tempState.xhrs, function(chunkId) {\n delete tempState.xhrs[chunkId];\n });\n },\n\n /**\n * Creates an XHR instance for this file and stores it in the fileState.\n *\n * @param id File ID\n * @param optChunkIdx The chunk index associated with this XHR, if applicable\n * @returns {XMLHttpRequest}\n */\n _createXhr: function(id, optChunkIdx) {\n return handler._registerXhr(id, optChunkIdx, qq.createXhrInstance());\n },\n\n _getAjaxRequester: function(id, optChunkIdx) {\n var chunkIdx = optChunkIdx == null ? -1 : optChunkIdx;\n return handler._getFileState(id).temp.ajaxRequesters[chunkIdx];\n },\n\n _getChunkData: function(id, chunkIndex) {\n var chunkSize = chunking.partSize,\n fileSize = getSize(id),\n fileOrBlob = handler.getFile(id),\n startBytes = chunkSize * chunkIndex,\n endBytes = startBytes + chunkSize >= fileSize ? fileSize : startBytes + chunkSize,\n totalChunks = handler._getTotalChunks(id),\n cachedChunks = this._getFileState(id).temp.cachedChunks,\n\n // To work around a Webkit GC bug, we must keep each chunk `Blob` in scope until we are done with it.\n // See https://github.com/Widen/fine-uploader/issues/937#issuecomment-41418760\n blob = cachedChunks[chunkIndex] || qq.sliceBlob(fileOrBlob, startBytes, endBytes);\n\n cachedChunks[chunkIndex] = blob;\n\n return {\n part: chunkIndex,\n start: startBytes,\n end: endBytes,\n count: totalChunks,\n blob: blob,\n size: endBytes - startBytes\n };\n },\n\n _getChunkDataForCallback: function(chunkData) {\n return {\n partIndex: chunkData.part,\n startByte: chunkData.start + 1,\n endByte: chunkData.end,\n totalParts: chunkData.count\n };\n },\n\n /**\n * @param id File ID\n * @returns {string} Identifier for this item that may appear in the browser's local storage\n */\n _getLocalStorageId: function(id) {\n var formatVersion = \"5.0\",\n name = getName(id),\n size = getSize(id),\n chunkSize = chunking.partSize,\n endpoint = getEndpoint(id);\n\n return qq.format(\"qq{}resume{}-{}-{}-{}-{}\", namespace, formatVersion, name, size, chunkSize, endpoint);\n },\n\n _getMimeType: function(id) {\n return handler.getFile(id).type;\n },\n\n _getPersistableData: function(id) {\n return handler._getFileState(id).chunking;\n },\n\n /**\n * @param id ID of the associated file\n * @returns {number} Number of parts this file can be divided into, or undefined if chunking is not supported in this UA\n */\n _getTotalChunks: function(id) {\n if (chunking) {\n var fileSize = getSize(id),\n chunkSize = chunking.partSize;\n\n return Math.ceil(fileSize / chunkSize);\n }\n },\n\n _getXhr: function(id, optChunkIdx) {\n var chunkIdx = optChunkIdx == null ? -1 : optChunkIdx;\n return handler._getFileState(id).temp.xhrs[chunkIdx];\n },\n\n _getXhrs: function(id) {\n return handler._getFileState(id).temp.xhrs;\n },\n\n // Iterates through all XHR handler-created resume records (in local storage),\n // invoking the passed callback and passing in the key and value of each local storage record.\n _iterateResumeRecords: function(callback) {\n if (resumeEnabled) {\n qq.each(localStorage, function(key, item) {\n if (key.indexOf(qq.format(\"qq{}resume\", namespace)) === 0) {\n var uploadData = JSON.parse(item);\n callback(key, uploadData);\n }\n });\n }\n },\n\n _initTempState: function(id) {\n handler._getFileState(id).temp = {\n ajaxRequesters: {},\n chunkProgress: {},\n xhrs: {},\n cachedChunks: {}\n };\n },\n\n _markNotResumable: function(id) {\n handler._getFileState(id).notResumable = true;\n },\n\n // Removes a chunked upload record from local storage, if possible.\n // Returns true if the item was removed, false otherwise.\n _maybeDeletePersistedChunkData: function(id) {\n var localStorageId;\n\n if (resumeEnabled && handler.isResumable(id)) {\n localStorageId = handler._getLocalStorageId(id);\n\n if (localStorageId && localStorage.getItem(localStorageId)) {\n localStorage.removeItem(localStorageId);\n return true;\n }\n }\n\n return false;\n },\n\n // If this is a resumable upload, grab the relevant data from storage and items in memory that track this upload\n // so we can pick up from where we left off.\n _maybePrepareForResume: function(id) {\n var state = handler._getFileState(id),\n localStorageId, persistedData;\n\n // Resume is enabled and possible and this is the first time we've tried to upload this file in this session,\n // so prepare for a resume attempt.\n if (resumeEnabled && state.key === undefined) {\n localStorageId = handler._getLocalStorageId(id);\n persistedData = localStorage.getItem(localStorageId);\n\n // If we found this item in local storage, maybe we should resume it.\n if (persistedData) {\n persistedData = JSON.parse(persistedData);\n\n // If we found a resume record but we have already handled this file in this session,\n // don't try to resume it & ensure we don't persist future check data\n if (getDataByUuid(persistedData.uuid)) {\n handler._markNotResumable(id);\n }\n else {\n log(qq.format(\"Identified file with ID {} and name of {} as resumable.\", id, getName(id)));\n\n onUuidChanged(id, persistedData.uuid);\n\n state.key = persistedData.key;\n state.chunking = persistedData.chunking;\n state.loaded = persistedData.loaded;\n state.attemptingResume = true;\n\n handler.moveInProgressToRemaining(id);\n }\n }\n }\n },\n\n // Persist any data needed to resume this upload in a new session.\n _maybePersistChunkedState: function(id) {\n var state = handler._getFileState(id),\n localStorageId, persistedData;\n\n // If local storage isn't supported by the browser, or if resume isn't enabled or possible, give up\n if (resumeEnabled && handler.isResumable(id)) {\n localStorageId = handler._getLocalStorageId(id);\n\n persistedData = {\n name: getName(id),\n size: getSize(id),\n uuid: getUuid(id),\n key: state.key,\n chunking: state.chunking,\n loaded: state.loaded,\n lastUpdated: Date.now()\n };\n\n try {\n localStorage.setItem(localStorageId, JSON.stringify(persistedData));\n }\n catch (error) {\n log(qq.format(\"Unable to save resume data for '{}' due to error: '{}'.\", id, error.toString()), \"warn\");\n }\n }\n },\n\n _registerProgressHandler: function(id, chunkIdx, chunkSize) {\n var xhr = handler._getXhr(id, chunkIdx),\n name = getName(id),\n progressCalculator = {\n simple: function(loaded, total) {\n var fileSize = getSize(id);\n\n if (loaded === total) {\n onProgress(id, name, fileSize, fileSize);\n }\n else {\n onProgress(id, name, (loaded >= fileSize ? fileSize - 1 : loaded), fileSize);\n }\n },\n\n chunked: function(loaded, total) {\n var chunkProgress = handler._getFileState(id).temp.chunkProgress,\n totalSuccessfullyLoadedForFile = handler._getFileState(id).loaded,\n loadedForRequest = loaded,\n totalForRequest = total,\n totalFileSize = getSize(id),\n estActualChunkLoaded = loadedForRequest - (totalForRequest - chunkSize),\n totalLoadedForFile = totalSuccessfullyLoadedForFile;\n\n chunkProgress[chunkIdx] = estActualChunkLoaded;\n\n qq.each(chunkProgress, function(chunkIdx, chunkLoaded) {\n totalLoadedForFile += chunkLoaded;\n });\n\n onProgress(id, name, totalLoadedForFile, totalFileSize);\n }\n };\n\n xhr.upload.onprogress = function(e) {\n if (e.lengthComputable) {\n /* jshint eqnull: true */\n var type = chunkSize == null ? \"simple\" : \"chunked\";\n progressCalculator[type](e.loaded, e.total);\n }\n };\n },\n\n /**\n * Registers an XHR transport instance created elsewhere.\n *\n * @param id ID of the associated file\n * @param optChunkIdx The chunk index associated with this XHR, if applicable\n * @param xhr XMLHttpRequest object instance\n * @param optAjaxRequester `qq.AjaxRequester` associated with this request, if applicable.\n * @returns {XMLHttpRequest}\n */\n _registerXhr: function(id, optChunkIdx, xhr, optAjaxRequester) {\n var xhrsId = optChunkIdx == null ? -1 : optChunkIdx,\n tempState = handler._getFileState(id).temp;\n\n tempState.xhrs = tempState.xhrs || {};\n tempState.ajaxRequesters = tempState.ajaxRequesters || {};\n\n tempState.xhrs[xhrsId] = xhr;\n\n if (optAjaxRequester) {\n tempState.ajaxRequesters[xhrsId] = optAjaxRequester;\n }\n\n return xhr;\n },\n\n // Deletes any local storage records that are \"expired\".\n _removeExpiredChunkingRecords: function() {\n var expirationDays = resume.recordsExpireIn;\n\n handler._iterateResumeRecords(function(key, uploadData) {\n var expirationDate = new Date(uploadData.lastUpdated);\n\n // transform updated date into expiration date\n expirationDate.setDate(expirationDate.getDate() + expirationDays);\n\n if (expirationDate.getTime() <= Date.now()) {\n log(\"Removing expired resume record with key \" + key);\n localStorage.removeItem(key);\n }\n });\n },\n\n /**\n * Determine if the associated file should be chunked.\n *\n * @param id ID of the associated file\n * @returns {*} true if chunking is enabled, possible, and the file can be split into more than 1 part\n */\n _shouldChunkThisFile: function(id) {\n var state = handler._getFileState(id);\n\n if (!state.chunking) {\n handler.reevaluateChunking(id);\n }\n\n return state.chunking.enabled;\n }\n });\n};\n","/*globals qq, XMLHttpRequest*/\nqq.DeleteFileAjaxRequester = function(o) {\n \"use strict\";\n\n var requester,\n options = {\n method: \"DELETE\",\n uuidParamName: \"qquuid\",\n endpointStore: {},\n maxConnections: 3,\n customHeaders: function(id) {return {};},\n paramsStore: {},\n cors: {\n expected: false,\n sendCredentials: false\n },\n log: function(str, level) {},\n onDelete: function(id) {},\n onDeleteComplete: function(id, xhrOrXdr, isError) {}\n };\n\n qq.extend(options, o);\n\n function getMandatedParams() {\n if (options.method.toUpperCase() === \"POST\") {\n return {\n _method: \"DELETE\"\n };\n }\n\n return {};\n }\n\n requester = qq.extend(this, new qq.AjaxRequester({\n acceptHeader: \"application/json\",\n validMethods: [\"POST\", \"DELETE\"],\n method: options.method,\n endpointStore: options.endpointStore,\n paramsStore: options.paramsStore,\n mandatedParams: getMandatedParams(),\n maxConnections: options.maxConnections,\n customHeaders: function(id) {\n return options.customHeaders.get(id);\n },\n log: options.log,\n onSend: options.onDelete,\n onComplete: options.onDeleteComplete,\n cors: options.cors\n }));\n\n qq.extend(this, {\n sendDelete: function(id, uuid, additionalMandatedParams) {\n var additionalOptions = additionalMandatedParams || {};\n\n options.log(\"Submitting delete file request for \" + id);\n\n if (options.method === \"DELETE\") {\n requester.initTransport(id)\n .withPath(uuid)\n .withParams(additionalOptions)\n .send();\n }\n else {\n additionalOptions[options.uuidParamName] = uuid;\n requester.initTransport(id)\n .withParams(additionalOptions)\n .send();\n }\n }\n });\n};\n","/*global qq, define */\n/*jshint strict:false,bitwise:false,nonew:false,asi:true,-W064,-W116,-W089 */\n/**\n * Mega pixel image rendering library for iOS6+\n *\n * Fixes iOS6+'s image file rendering issue for large size image (over mega-pixel),\n * which causes unexpected subsampling when drawing it in canvas.\n * By using this library, you can safely render the image with proper stretching.\n *\n * Copyright (c) 2012 Shinichi Tomita \n * Released under the MIT license\n *\n * Heavily modified by Widen for Fine Uploader\n */\n(function() {\n\n /**\n * Detect subsampling in loaded image.\n * In iOS, larger images than 2M pixels may be subsampled in rendering.\n */\n function detectSubsampling(img) {\n var iw = img.naturalWidth,\n ih = img.naturalHeight,\n canvas = document.createElement(\"canvas\"),\n ctx;\n\n if (iw * ih > 1024 * 1024) { // subsampling may happen over megapixel image\n canvas.width = canvas.height = 1;\n ctx = canvas.getContext(\"2d\");\n ctx.drawImage(img, -iw + 1, 0);\n // subsampled image becomes half smaller in rendering size.\n // check alpha channel value to confirm image is covering edge pixel or not.\n // if alpha value is 0 image is not covering, hence subsampled.\n return ctx.getImageData(0, 0, 1, 1).data[3] === 0;\n } else {\n return false;\n }\n }\n\n /**\n * Detecting vertical squash in loaded image.\n * Fixes a bug which squash image vertically while drawing into canvas for some images.\n */\n function detectVerticalSquash(img, iw, ih) {\n var canvas = document.createElement(\"canvas\"),\n sy = 0,\n ey = ih,\n py = ih,\n ctx, data, alpha, ratio;\n\n canvas.width = 1;\n canvas.height = ih;\n ctx = canvas.getContext(\"2d\");\n ctx.drawImage(img, 0, 0);\n data = ctx.getImageData(0, 0, 1, ih).data;\n\n // search image edge pixel position in case it is squashed vertically.\n while (py > sy) {\n alpha = data[(py - 1) * 4 + 3];\n if (alpha === 0) {\n ey = py;\n } else {\n sy = py;\n }\n py = (ey + sy) >> 1;\n }\n\n ratio = (py / ih);\n return (ratio === 0) ? 1 : ratio;\n }\n\n /**\n * Rendering image element (with resizing) and get its data URL\n */\n function renderImageToDataURL(img, blob, options, doSquash) {\n var canvas = document.createElement(\"canvas\"),\n mime = options.mime || \"image/jpeg\",\n promise = new qq.Promise();\n\n renderImageToCanvas(img, blob, canvas, options, doSquash)\n .then(function() {\n promise.success(\n canvas.toDataURL(mime, options.quality || 0.8)\n );\n });\n\n return promise;\n }\n\n function maybeCalculateDownsampledDimensions(spec) {\n var maxPixels = 5241000; //iOS specific value\n\n if (!qq.ios()) {\n throw new qq.Error(\"Downsampled dimensions can only be reliably calculated for iOS!\");\n }\n\n if (spec.origHeight * spec.origWidth > maxPixels) {\n return {\n newHeight: Math.round(Math.sqrt(maxPixels * (spec.origHeight / spec.origWidth))),\n newWidth: Math.round(Math.sqrt(maxPixels * (spec.origWidth / spec.origHeight)))\n };\n }\n }\n\n /**\n * Rendering image element (with resizing) into the canvas element\n */\n function renderImageToCanvas(img, blob, canvas, options, doSquash) {\n var iw = img.naturalWidth,\n ih = img.naturalHeight,\n width = options.width,\n height = options.height,\n ctx = canvas.getContext(\"2d\"),\n promise = new qq.Promise(),\n modifiedDimensions;\n\n ctx.save();\n\n if (options.resize) {\n return renderImageToCanvasWithCustomResizer({\n blob: blob,\n canvas: canvas,\n image: img,\n imageHeight: ih,\n imageWidth: iw,\n orientation: options.orientation,\n resize: options.resize,\n targetHeight: height,\n targetWidth: width\n });\n }\n\n if (!qq.supportedFeatures.unlimitedScaledImageSize) {\n modifiedDimensions = maybeCalculateDownsampledDimensions({\n origWidth: width,\n origHeight: height\n });\n\n if (modifiedDimensions) {\n qq.log(qq.format(\"Had to reduce dimensions due to device limitations from {}w / {}h to {}w / {}h\",\n width, height, modifiedDimensions.newWidth, modifiedDimensions.newHeight),\n \"warn\");\n\n width = modifiedDimensions.newWidth;\n height = modifiedDimensions.newHeight;\n }\n }\n\n transformCoordinate(canvas, width, height, options.orientation);\n\n // Fine Uploader specific: Save some CPU cycles if not using iOS\n // Assumption: This logic is only needed to overcome iOS image sampling issues\n if (qq.ios()) {\n (function() {\n if (detectSubsampling(img)) {\n iw /= 2;\n ih /= 2;\n }\n\n var d = 1024, // size of tiling canvas\n tmpCanvas = document.createElement(\"canvas\"),\n vertSquashRatio = doSquash ? detectVerticalSquash(img, iw, ih) : 1,\n dw = Math.ceil(d * width / iw),\n dh = Math.ceil(d * height / ih / vertSquashRatio),\n sy = 0,\n dy = 0,\n tmpCtx, sx, dx;\n\n tmpCanvas.width = tmpCanvas.height = d;\n tmpCtx = tmpCanvas.getContext(\"2d\");\n\n while (sy < ih) {\n sx = 0;\n dx = 0;\n while (sx < iw) {\n tmpCtx.clearRect(0, 0, d, d);\n tmpCtx.drawImage(img, -sx, -sy);\n ctx.drawImage(tmpCanvas, 0, 0, d, d, dx, dy, dw, dh);\n sx += d;\n dx += dw;\n }\n sy += d;\n dy += dh;\n }\n ctx.restore();\n tmpCanvas = tmpCtx = null;\n }());\n }\n else {\n ctx.drawImage(img, 0, 0, width, height);\n }\n\n canvas.qqImageRendered && canvas.qqImageRendered();\n promise.success();\n\n return promise;\n }\n\n function renderImageToCanvasWithCustomResizer(resizeInfo) {\n var blob = resizeInfo.blob,\n image = resizeInfo.image,\n imageHeight = resizeInfo.imageHeight,\n imageWidth = resizeInfo.imageWidth,\n orientation = resizeInfo.orientation,\n promise = new qq.Promise(),\n resize = resizeInfo.resize,\n sourceCanvas = document.createElement(\"canvas\"),\n sourceCanvasContext = sourceCanvas.getContext(\"2d\"),\n targetCanvas = resizeInfo.canvas,\n targetHeight = resizeInfo.targetHeight,\n targetWidth = resizeInfo.targetWidth;\n\n transformCoordinate(sourceCanvas, imageWidth, imageHeight, orientation);\n\n targetCanvas.height = targetHeight;\n targetCanvas.width = targetWidth;\n\n sourceCanvasContext.drawImage(image, 0, 0);\n\n resize({\n blob: blob,\n height: targetHeight,\n image: image,\n sourceCanvas: sourceCanvas,\n targetCanvas: targetCanvas,\n width: targetWidth\n })\n .then(\n function success() {\n targetCanvas.qqImageRendered && targetCanvas.qqImageRendered();\n promise.success();\n },\n promise.failure\n );\n\n return promise;\n }\n\n /**\n * Transform canvas coordination according to specified frame size and orientation\n * Orientation value is from EXIF tag\n */\n function transformCoordinate(canvas, width, height, orientation) {\n switch (orientation) {\n case 5:\n case 6:\n case 7:\n case 8:\n canvas.width = height;\n canvas.height = width;\n break;\n default:\n canvas.width = width;\n canvas.height = height;\n }\n var ctx = canvas.getContext(\"2d\");\n switch (orientation) {\n case 2:\n // horizontal flip\n ctx.translate(width, 0);\n ctx.scale(-1, 1);\n break;\n case 3:\n // 180 rotate left\n ctx.translate(width, height);\n ctx.rotate(Math.PI);\n break;\n case 4:\n // vertical flip\n ctx.translate(0, height);\n ctx.scale(1, -1);\n break;\n case 5:\n // vertical flip + 90 rotate right\n ctx.rotate(0.5 * Math.PI);\n ctx.scale(1, -1);\n break;\n case 6:\n // 90 rotate right\n ctx.rotate(0.5 * Math.PI);\n ctx.translate(0, -height);\n break;\n case 7:\n // horizontal flip + 90 rotate right\n ctx.rotate(0.5 * Math.PI);\n ctx.translate(width, -height);\n ctx.scale(-1, 1);\n break;\n case 8:\n // 90 rotate left\n ctx.rotate(-0.5 * Math.PI);\n ctx.translate(-width, 0);\n break;\n default:\n break;\n }\n }\n\n /**\n * MegaPixImage class\n */\n function MegaPixImage(srcImage, errorCallback) {\n var self = this;\n\n if (window.Blob && srcImage instanceof Blob) {\n (function() {\n var img = new Image(),\n URL = window.URL && window.URL.createObjectURL ? window.URL :\n window.webkitURL && window.webkitURL.createObjectURL ? window.webkitURL : null;\n if (!URL) { throw Error(\"No createObjectURL function found to create blob url\"); }\n img.src = URL.createObjectURL(srcImage);\n self.blob = srcImage;\n srcImage = img;\n }());\n }\n if (!srcImage.naturalWidth && !srcImage.naturalHeight) {\n srcImage.onload = function() {\n var listeners = self.imageLoadListeners;\n if (listeners) {\n self.imageLoadListeners = null;\n // IE11 doesn't reliably report actual image dimensions immediately after onload for small files,\n // so let's push this to the end of the UI thread queue.\n setTimeout(function() {\n for (var i = 0, len = listeners.length; i < len; i++) {\n listeners[i]();\n }\n }, 0);\n }\n };\n srcImage.onerror = errorCallback;\n this.imageLoadListeners = [];\n }\n this.srcImage = srcImage;\n }\n\n /**\n * Rendering megapix image into specified target element\n */\n MegaPixImage.prototype.render = function(target, options) {\n options = options || {};\n\n var self = this,\n imgWidth = this.srcImage.naturalWidth,\n imgHeight = this.srcImage.naturalHeight,\n width = options.width,\n height = options.height,\n maxWidth = options.maxWidth,\n maxHeight = options.maxHeight,\n doSquash = !this.blob || this.blob.type === \"image/jpeg\",\n tagName = target.tagName.toLowerCase(),\n opt;\n\n if (this.imageLoadListeners) {\n this.imageLoadListeners.push(function() { self.render(target, options); });\n return;\n }\n\n if (width && !height) {\n height = (imgHeight * width / imgWidth) << 0;\n } else if (height && !width) {\n width = (imgWidth * height / imgHeight) << 0;\n } else {\n width = imgWidth;\n height = imgHeight;\n }\n if (maxWidth && width > maxWidth) {\n width = maxWidth;\n height = (imgHeight * width / imgWidth) << 0;\n }\n if (maxHeight && height > maxHeight) {\n height = maxHeight;\n width = (imgWidth * height / imgHeight) << 0;\n }\n\n opt = { width: width, height: height },\n qq.each(options, function(optionsKey, optionsValue) {\n opt[optionsKey] = optionsValue;\n });\n\n if (tagName === \"img\") {\n (function() {\n var oldTargetSrc = target.src;\n renderImageToDataURL(self.srcImage, self.blob, opt, doSquash)\n .then(function(dataUri) {\n target.src = dataUri;\n oldTargetSrc === target.src && target.onload();\n });\n }());\n } else if (tagName === \"canvas\") {\n renderImageToCanvas(this.srcImage, this.blob, target, opt, doSquash);\n }\n if (typeof this.onrender === \"function\") {\n this.onrender(target);\n }\n };\n\n qq.MegaPixImage = MegaPixImage;\n})();\n","/*globals qq */\n/**\n * Draws a thumbnail of a Blob/File/URL onto an or .\n *\n * @constructor\n */\nqq.ImageGenerator = function(log) {\n \"use strict\";\n\n function isImg(el) {\n return el.tagName.toLowerCase() === \"img\";\n }\n\n function isCanvas(el) {\n return el.tagName.toLowerCase() === \"canvas\";\n }\n\n function isImgCorsSupported() {\n return new Image().crossOrigin !== undefined;\n }\n\n function isCanvasSupported() {\n var canvas = document.createElement(\"canvas\");\n\n return canvas.getContext && canvas.getContext(\"2d\");\n }\n\n // This is only meant to determine the MIME type of a renderable image file.\n // It is used to ensure images drawn from a URL that have transparent backgrounds\n // are rendered correctly, among other things.\n function determineMimeOfFileName(nameWithPath) {\n /*jshint -W015 */\n var pathSegments = nameWithPath.split(\"/\"),\n name = pathSegments[pathSegments.length - 1].split(\"?\")[0],\n extension = qq.getExtension(name);\n\n extension = extension && extension.toLowerCase();\n\n switch (extension) {\n case \"jpeg\":\n case \"jpg\":\n return \"image/jpeg\";\n case \"png\":\n return \"image/png\";\n case \"bmp\":\n return \"image/bmp\";\n case \"gif\":\n return \"image/gif\";\n case \"tiff\":\n case \"tif\":\n return \"image/tiff\";\n }\n }\n\n // This will likely not work correctly in IE8 and older.\n // It's only used as part of a formula to determine\n // if a canvas can be used to scale a server-hosted thumbnail.\n // If canvas isn't supported by the UA (IE8 and older)\n // this method should not even be called.\n function isCrossOrigin(url) {\n var targetAnchor = document.createElement(\"a\"),\n targetProtocol, targetHostname, targetPort;\n\n targetAnchor.href = url;\n\n targetProtocol = targetAnchor.protocol;\n targetPort = targetAnchor.port;\n targetHostname = targetAnchor.hostname;\n\n if (targetProtocol.toLowerCase() !== window.location.protocol.toLowerCase()) {\n return true;\n }\n\n if (targetHostname.toLowerCase() !== window.location.hostname.toLowerCase()) {\n return true;\n }\n\n // IE doesn't take ports into consideration when determining if two endpoints are same origin.\n if (targetPort !== window.location.port && !qq.ie()) {\n return true;\n }\n\n return false;\n }\n\n function registerImgLoadListeners(img, promise) {\n img.onload = function() {\n img.onload = null;\n img.onerror = null;\n promise.success(img);\n };\n\n img.onerror = function() {\n img.onload = null;\n img.onerror = null;\n log(\"Problem drawing thumbnail!\", \"error\");\n promise.failure(img, \"Problem drawing thumbnail!\");\n };\n }\n\n function registerCanvasDrawImageListener(canvas, promise) {\n // The image is drawn on the canvas by a third-party library,\n // and we want to know when this is completed. Since the library\n // may invoke drawImage many times in a loop, we need to be called\n // back when the image is fully rendered. So, we are expecting the\n // code that draws this image to follow a convention that involves a\n // function attached to the canvas instance be invoked when it is done.\n canvas.qqImageRendered = function() {\n promise.success(canvas);\n };\n }\n\n // Fulfills a `qq.Promise` when an image has been drawn onto the target,\n // whether that is a or an . The attempt is considered a\n // failure if the target is not an or a , or if the drawing\n // attempt was not successful.\n function registerThumbnailRenderedListener(imgOrCanvas, promise) {\n var registered = isImg(imgOrCanvas) || isCanvas(imgOrCanvas);\n\n if (isImg(imgOrCanvas)) {\n registerImgLoadListeners(imgOrCanvas, promise);\n }\n else if (isCanvas(imgOrCanvas)) {\n registerCanvasDrawImageListener(imgOrCanvas, promise);\n }\n else {\n promise.failure(imgOrCanvas);\n log(qq.format(\"Element container of type {} is not supported!\", imgOrCanvas.tagName), \"error\");\n }\n\n return registered;\n }\n\n // Draw a preview iff the current UA can natively display it.\n // Also rotate the image if necessary.\n function draw(fileOrBlob, container, options) {\n var drawPreview = new qq.Promise(),\n identifier = new qq.Identify(fileOrBlob, log),\n maxSize = options.maxSize,\n // jshint eqnull:true\n orient = options.orient == null ? true : options.orient,\n megapixErrorHandler = function() {\n container.onerror = null;\n container.onload = null;\n log(\"Could not render preview, file may be too large!\", \"error\");\n drawPreview.failure(container, \"Browser cannot render image!\");\n };\n\n identifier.isPreviewable().then(\n function(mime) {\n // If options explicitly specify that Orientation is not desired,\n // replace the orient task with a dummy promise that \"succeeds\" immediately.\n var dummyExif = {\n parse: function() {\n return new qq.Promise().success();\n }\n },\n exif = orient ? new qq.Exif(fileOrBlob, log) : dummyExif,\n mpImg = new qq.MegaPixImage(fileOrBlob, megapixErrorHandler);\n\n if (registerThumbnailRenderedListener(container, drawPreview)) {\n exif.parse().then(\n function(exif) {\n var orientation = exif && exif.Orientation;\n\n mpImg.render(container, {\n maxWidth: maxSize,\n maxHeight: maxSize,\n orientation: orientation,\n mime: mime,\n resize: options.customResizeFunction\n });\n },\n\n function(failureMsg) {\n log(qq.format(\"EXIF data could not be parsed ({}). Assuming orientation = 1.\", failureMsg));\n\n mpImg.render(container, {\n maxWidth: maxSize,\n maxHeight: maxSize,\n mime: mime,\n resize: options.customResizeFunction\n });\n }\n );\n }\n },\n\n function() {\n log(\"Not previewable\");\n drawPreview.failure(container, \"Not previewable\");\n }\n );\n\n return drawPreview;\n }\n\n function drawOnCanvasOrImgFromUrl(url, canvasOrImg, draw, maxSize, customResizeFunction) {\n var tempImg = new Image(),\n tempImgRender = new qq.Promise();\n\n registerThumbnailRenderedListener(tempImg, tempImgRender);\n\n if (isCrossOrigin(url)) {\n tempImg.crossOrigin = \"anonymous\";\n }\n\n tempImg.src = url;\n\n tempImgRender.then(\n function rendered() {\n registerThumbnailRenderedListener(canvasOrImg, draw);\n\n var mpImg = new qq.MegaPixImage(tempImg);\n mpImg.render(canvasOrImg, {\n maxWidth: maxSize,\n maxHeight: maxSize,\n mime: determineMimeOfFileName(url),\n resize: customResizeFunction\n });\n },\n\n draw.failure\n );\n }\n\n function drawOnImgFromUrlWithCssScaling(url, img, draw, maxSize) {\n registerThumbnailRenderedListener(img, draw);\n // NOTE: The fact that maxWidth/height is set on the thumbnail for scaled images\n // that must drop back to CSS is known and exploited by the templating module.\n // In this module, we pre-render \"waiting\" thumbs for all files immediately after they\n // are submitted, and we must be sure to pass any style associated with the \"waiting\" preview.\n qq(img).css({\n maxWidth: maxSize + \"px\",\n maxHeight: maxSize + \"px\"\n });\n\n img.src = url;\n }\n\n // Draw a (server-hosted) thumbnail given a URL.\n // This will optionally scale the thumbnail as well.\n // It attempts to use to scale, but will fall back\n // to max-width and max-height style properties if the UA\n // doesn't support canvas or if the images is cross-domain and\n // the UA doesn't support the crossorigin attribute on img tags,\n // which is required to scale a cross-origin image using &\n // then export it back to an .\n function drawFromUrl(url, container, options) {\n var draw = new qq.Promise(),\n scale = options.scale,\n maxSize = scale ? options.maxSize : null;\n\n // container is an img, scaling needed\n if (scale && isImg(container)) {\n // Iff canvas is available in this UA, try to use it for scaling.\n // Otherwise, fall back to CSS scaling\n if (isCanvasSupported()) {\n // Attempt to use for image scaling,\n // but we must fall back to scaling via CSS/styles\n // if this is a cross-origin image and the UA doesn't support CORS.\n if (isCrossOrigin(url) && !isImgCorsSupported()) {\n drawOnImgFromUrlWithCssScaling(url, container, draw, maxSize);\n }\n else {\n drawOnCanvasOrImgFromUrl(url, container, draw, maxSize);\n }\n }\n else {\n drawOnImgFromUrlWithCssScaling(url, container, draw, maxSize);\n }\n }\n // container is a canvas, scaling optional\n else if (isCanvas(container)) {\n drawOnCanvasOrImgFromUrl(url, container, draw, maxSize);\n }\n // container is an img & no scaling: just set the src attr to the passed url\n else if (registerThumbnailRenderedListener(container, draw)) {\n container.src = url;\n }\n\n return draw;\n }\n\n qq.extend(this, {\n /**\n * Generate a thumbnail. Depending on the arguments, this may either result in\n * a client-side rendering of an image (if a `Blob` is supplied) or a server-generated\n * image that may optionally be scaled client-side using or CSS/styles (as a fallback).\n *\n * @param fileBlobOrUrl a `File`, `Blob`, or a URL pointing to the image\n * @param container or to contain the preview\n * @param options possible properties include `maxSize` (int), `orient` (bool - default true), resize` (bool - default true), and `customResizeFunction`.\n * @returns qq.Promise fulfilled when the preview has been drawn, or the attempt has failed\n */\n generate: function(fileBlobOrUrl, container, options) {\n if (qq.isString(fileBlobOrUrl)) {\n log(\"Attempting to update thumbnail based on server response.\");\n return drawFromUrl(fileBlobOrUrl, container, options || {});\n }\n else {\n log(\"Attempting to draw client-side image preview.\");\n return draw(fileBlobOrUrl, container, options || {});\n }\n }\n });\n\n /**/\n this._testing = {};\n this._testing.isImg = isImg;\n this._testing.isCanvas = isCanvas;\n this._testing.isCrossOrigin = isCrossOrigin;\n this._testing.determineMimeOfFileName = determineMimeOfFileName;\n /* */\n};\n","/*globals qq */\n/**\n * EXIF image data parser. Currently only parses the Orientation tag value,\n * but this may be expanded to other tags in the future.\n *\n * @param fileOrBlob Attempt to parse EXIF data in this `Blob`\n * @constructor\n */\nqq.Exif = function(fileOrBlob, log) {\n \"use strict\";\n\n // Orientation is the only tag parsed here at this time.\n var TAG_IDS = [274],\n TAG_INFO = {\n 274: {\n name: \"Orientation\",\n bytes: 2\n }\n };\n\n // Convert a little endian (hex string) to big endian (decimal).\n function parseLittleEndian(hex) {\n var result = 0,\n pow = 0;\n\n while (hex.length > 0) {\n result += parseInt(hex.substring(0, 2), 16) * Math.pow(2, pow);\n hex = hex.substring(2, hex.length);\n pow += 8;\n }\n\n return result;\n }\n\n // Find the byte offset, of Application Segment 1 (EXIF).\n // External callers need not supply any arguments.\n function seekToApp1(offset, promise) {\n var theOffset = offset,\n thePromise = promise;\n if (theOffset === undefined) {\n theOffset = 2;\n thePromise = new qq.Promise();\n }\n\n qq.readBlobToHex(fileOrBlob, theOffset, 4).then(function(hex) {\n var match = /^ffe([0-9])/.exec(hex),\n segmentLength;\n\n if (match) {\n if (match[1] !== \"1\") {\n segmentLength = parseInt(hex.slice(4, 8), 16);\n seekToApp1(theOffset + segmentLength + 2, thePromise);\n }\n else {\n thePromise.success(theOffset);\n }\n }\n else {\n thePromise.failure(\"No EXIF header to be found!\");\n }\n });\n\n return thePromise;\n }\n\n // Find the byte offset of Application Segment 1 (EXIF) for valid JPEGs only.\n function getApp1Offset() {\n var promise = new qq.Promise();\n\n qq.readBlobToHex(fileOrBlob, 0, 6).then(function(hex) {\n if (hex.indexOf(\"ffd8\") !== 0) {\n promise.failure(\"Not a valid JPEG!\");\n }\n else {\n seekToApp1().then(function(offset) {\n promise.success(offset);\n },\n function(error) {\n promise.failure(error);\n });\n }\n });\n\n return promise;\n }\n\n // Determine the byte ordering of the EXIF header.\n function isLittleEndian(app1Start) {\n var promise = new qq.Promise();\n\n qq.readBlobToHex(fileOrBlob, app1Start + 10, 2).then(function(hex) {\n promise.success(hex === \"4949\");\n });\n\n return promise;\n }\n\n // Determine the number of directory entries in the EXIF header.\n function getDirEntryCount(app1Start, littleEndian) {\n var promise = new qq.Promise();\n\n qq.readBlobToHex(fileOrBlob, app1Start + 18, 2).then(function(hex) {\n if (littleEndian) {\n return promise.success(parseLittleEndian(hex));\n }\n else {\n promise.success(parseInt(hex, 16));\n }\n });\n\n return promise;\n }\n\n // Get the IFD portion of the EXIF header as a hex string.\n function getIfd(app1Start, dirEntries) {\n var offset = app1Start + 20,\n bytes = dirEntries * 12;\n\n return qq.readBlobToHex(fileOrBlob, offset, bytes);\n }\n\n // Obtain an array of all directory entries (as hex strings) in the EXIF header.\n function getDirEntries(ifdHex) {\n var entries = [],\n offset = 0;\n\n while (offset + 24 <= ifdHex.length) {\n entries.push(ifdHex.slice(offset, offset + 24));\n offset += 24;\n }\n\n return entries;\n }\n\n // Obtain values for all relevant tags and return them.\n function getTagValues(littleEndian, dirEntries) {\n var TAG_VAL_OFFSET = 16,\n tagsToFind = qq.extend([], TAG_IDS),\n vals = {};\n\n qq.each(dirEntries, function(idx, entry) {\n var idHex = entry.slice(0, 4),\n id = littleEndian ? parseLittleEndian(idHex) : parseInt(idHex, 16),\n tagsToFindIdx = tagsToFind.indexOf(id),\n tagValHex, tagName, tagValLength;\n\n if (tagsToFindIdx >= 0) {\n tagName = TAG_INFO[id].name;\n tagValLength = TAG_INFO[id].bytes;\n tagValHex = entry.slice(TAG_VAL_OFFSET, TAG_VAL_OFFSET + (tagValLength * 2));\n vals[tagName] = littleEndian ? parseLittleEndian(tagValHex) : parseInt(tagValHex, 16);\n\n tagsToFind.splice(tagsToFindIdx, 1);\n }\n\n if (tagsToFind.length === 0) {\n return false;\n }\n });\n\n return vals;\n }\n\n qq.extend(this, {\n /**\n * Attempt to parse the EXIF header for the `Blob` associated with this instance.\n *\n * @returns {qq.Promise} To be fulfilled when the parsing is complete.\n * If successful, the parsed EXIF header as an object will be included.\n */\n parse: function() {\n var parser = new qq.Promise(),\n onParseFailure = function(message) {\n log(qq.format(\"EXIF header parse failed: '{}' \", message));\n parser.failure(message);\n };\n\n getApp1Offset().then(function(app1Offset) {\n log(qq.format(\"Moving forward with EXIF header parsing for '{}'\", fileOrBlob.name === undefined ? \"blob\" : fileOrBlob.name));\n\n isLittleEndian(app1Offset).then(function(littleEndian) {\n\n log(qq.format(\"EXIF Byte order is {} endian\", littleEndian ? \"little\" : \"big\"));\n\n getDirEntryCount(app1Offset, littleEndian).then(function(dirEntryCount) {\n\n log(qq.format(\"Found {} APP1 directory entries\", dirEntryCount));\n\n getIfd(app1Offset, dirEntryCount).then(function(ifdHex) {\n var dirEntries = getDirEntries(ifdHex),\n tagValues = getTagValues(littleEndian, dirEntries);\n\n log(\"Successfully parsed some EXIF tags\");\n\n parser.success(tagValues);\n }, onParseFailure);\n }, onParseFailure);\n }, onParseFailure);\n }, onParseFailure);\n\n return parser;\n }\n });\n\n /**/\n this._testing = {};\n this._testing.parseLittleEndian = parseLittleEndian;\n /* */\n};\n","/*globals qq */\nqq.Identify = function(fileOrBlob, log) {\n \"use strict\";\n\n function isIdentifiable(magicBytes, questionableBytes) {\n var identifiable = false,\n magicBytesEntries = [].concat(magicBytes);\n\n qq.each(magicBytesEntries, function(idx, magicBytesArrayEntry) {\n if (questionableBytes.indexOf(magicBytesArrayEntry) === 0) {\n identifiable = true;\n return false;\n }\n });\n\n return identifiable;\n }\n\n qq.extend(this, {\n /**\n * Determines if a Blob can be displayed natively in the current browser. This is done by reading magic\n * bytes in the beginning of the file, so this is an asynchronous operation. Before we attempt to read the\n * file, we will examine the blob's type attribute to save CPU cycles.\n *\n * @returns {qq.Promise} Promise that is fulfilled when identification is complete.\n * If successful, the MIME string is passed to the success handler.\n */\n isPreviewable: function() {\n var self = this,\n identifier = new qq.Promise(),\n previewable = false,\n name = fileOrBlob.name === undefined ? \"blob\" : fileOrBlob.name;\n\n log(qq.format(\"Attempting to determine if {} can be rendered in this browser\", name));\n\n log(\"First pass: check type attribute of blob object.\");\n\n if (this.isPreviewableSync()) {\n log(\"Second pass: check for magic bytes in file header.\");\n\n qq.readBlobToHex(fileOrBlob, 0, 4).then(function(hex) {\n qq.each(self.PREVIEWABLE_MIME_TYPES, function(mime, bytes) {\n if (isIdentifiable(bytes, hex)) {\n // Safari is the only supported browser that can deal with TIFFs natively,\n // so, if this is a TIFF and the UA isn't Safari, declare this file \"non-previewable\".\n if (mime !== \"image/tiff\" || qq.supportedFeatures.tiffPreviews) {\n previewable = true;\n identifier.success(mime);\n }\n\n return false;\n }\n });\n\n log(qq.format(\"'{}' is {} able to be rendered in this browser\", name, previewable ? \"\" : \"NOT\"));\n\n if (!previewable) {\n identifier.failure();\n }\n },\n function() {\n log(\"Error reading file w/ name '\" + name + \"'. Not able to be rendered in this browser.\");\n identifier.failure();\n });\n }\n else {\n identifier.failure();\n }\n\n return identifier;\n },\n\n /**\n * Determines if a Blob can be displayed natively in the current browser. This is done by checking the\n * blob's type attribute. This is a synchronous operation, useful for situations where an asynchronous operation\n * would be challenging to support. Note that the blob's type property is not as accurate as reading the\n * file's magic bytes.\n *\n * @returns {Boolean} true if the blob can be rendered in the current browser\n */\n isPreviewableSync: function() {\n var fileMime = fileOrBlob.type,\n // Assumption: This will only ever be executed in browsers that support `Object.keys`.\n isRecognizedImage = qq.indexOf(Object.keys(this.PREVIEWABLE_MIME_TYPES), fileMime) >= 0,\n previewable = false,\n name = fileOrBlob.name === undefined ? \"blob\" : fileOrBlob.name;\n\n if (isRecognizedImage) {\n if (fileMime === \"image/tiff\") {\n previewable = qq.supportedFeatures.tiffPreviews;\n }\n else {\n previewable = true;\n }\n }\n\n !previewable && log(name + \" is not previewable in this browser per the blob's type attr\");\n\n return previewable;\n }\n });\n};\n\nqq.Identify.prototype.PREVIEWABLE_MIME_TYPES = {\n \"image/jpeg\": \"ffd8ff\",\n \"image/gif\": \"474946\",\n \"image/png\": \"89504e\",\n \"image/bmp\": \"424d\",\n \"image/tiff\": [\"49492a00\", \"4d4d002a\"]\n};\n","/*globals qq*/\n/**\n * Attempts to validate an image, wherever possible.\n *\n * @param blob File or Blob representing a user-selecting image.\n * @param log Uses this to post log messages to the console.\n * @constructor\n */\nqq.ImageValidation = function(blob, log) {\n \"use strict\";\n\n /**\n * @param limits Object with possible image-related limits to enforce.\n * @returns {boolean} true if at least one of the limits has a non-zero value\n */\n function hasNonZeroLimits(limits) {\n var atLeastOne = false;\n\n qq.each(limits, function(limit, value) {\n if (value > 0) {\n atLeastOne = true;\n return false;\n }\n });\n\n return atLeastOne;\n }\n\n /**\n * @returns {qq.Promise} The promise is a failure if we can't obtain the width & height.\n * Otherwise, `success` is called on the returned promise with an object containing\n * `width` and `height` properties.\n */\n function getWidthHeight() {\n var sizeDetermination = new qq.Promise();\n\n new qq.Identify(blob, log).isPreviewable().then(function() {\n var image = new Image(),\n url = window.URL && window.URL.createObjectURL ? window.URL :\n window.webkitURL && window.webkitURL.createObjectURL ? window.webkitURL :\n null;\n\n if (url) {\n image.onerror = function() {\n log(\"Cannot determine dimensions for image. May be too large.\", \"error\");\n sizeDetermination.failure();\n };\n\n image.onload = function() {\n sizeDetermination.success({\n width: this.width,\n height: this.height\n });\n };\n\n image.src = url.createObjectURL(blob);\n }\n else {\n log(\"No createObjectURL function available to generate image URL!\", \"error\");\n sizeDetermination.failure();\n }\n }, sizeDetermination.failure);\n\n return sizeDetermination;\n }\n\n /**\n *\n * @param limits Object with possible image-related limits to enforce.\n * @param dimensions Object containing `width` & `height` properties for the image to test.\n * @returns {String || undefined} The name of the failing limit. Undefined if no failing limits.\n */\n function getFailingLimit(limits, dimensions) {\n var failingLimit;\n\n qq.each(limits, function(limitName, limitValue) {\n if (limitValue > 0) {\n var limitMatcher = /(max|min)(Width|Height)/.exec(limitName),\n dimensionPropName = limitMatcher[2].charAt(0).toLowerCase() + limitMatcher[2].slice(1),\n actualValue = dimensions[dimensionPropName];\n\n /*jshint -W015*/\n switch (limitMatcher[1]) {\n case \"min\":\n if (actualValue < limitValue) {\n failingLimit = limitName;\n return false;\n }\n break;\n case \"max\":\n if (actualValue > limitValue) {\n failingLimit = limitName;\n return false;\n }\n break;\n }\n }\n });\n\n return failingLimit;\n }\n\n /**\n * Validate the associated blob.\n *\n * @param limits\n * @returns {qq.Promise} `success` is called on the promise is the image is valid or\n * if the blob is not an image, or if the image is not verifiable.\n * Otherwise, `failure` with the name of the failing limit.\n */\n this.validate = function(limits) {\n var validationEffort = new qq.Promise();\n\n log(\"Attempting to validate image.\");\n\n if (hasNonZeroLimits(limits)) {\n getWidthHeight().then(function(dimensions) {\n var failingLimit = getFailingLimit(limits, dimensions);\n\n if (failingLimit) {\n validationEffort.failure(failingLimit);\n }\n else {\n validationEffort.success();\n }\n }, validationEffort.success);\n }\n else {\n validationEffort.success();\n }\n\n return validationEffort;\n };\n};\n","/* globals qq */\n/**\n * Module used to control populating the initial list of files.\n *\n * @constructor\n */\nqq.Session = function(spec) {\n \"use strict\";\n\n var options = {\n endpoint: null,\n params: {},\n customHeaders: {},\n cors: {},\n addFileRecord: function(sessionData) {},\n log: function(message, level) {}\n };\n\n qq.extend(options, spec, true);\n\n function isJsonResponseValid(response) {\n if (qq.isArray(response)) {\n return true;\n }\n\n options.log(\"Session response is not an array.\", \"error\");\n }\n\n function handleFileItems(fileItems, success, xhrOrXdr, promise) {\n var someItemsIgnored = false;\n\n success = success && isJsonResponseValid(fileItems);\n\n if (success) {\n qq.each(fileItems, function(idx, fileItem) {\n /* jshint eqnull:true */\n if (fileItem.uuid == null) {\n someItemsIgnored = true;\n options.log(qq.format(\"Session response item {} did not include a valid UUID - ignoring.\", idx), \"error\");\n }\n else if (fileItem.name == null) {\n someItemsIgnored = true;\n options.log(qq.format(\"Session response item {} did not include a valid name - ignoring.\", idx), \"error\");\n }\n else {\n try {\n options.addFileRecord(fileItem);\n return true;\n }\n catch (err) {\n someItemsIgnored = true;\n options.log(err.message, \"error\");\n }\n }\n\n return false;\n });\n }\n\n promise[success && !someItemsIgnored ? \"success\" : \"failure\"](fileItems, xhrOrXdr);\n }\n\n // Initiate a call to the server that will be used to populate the initial file list.\n // Returns a `qq.Promise`.\n this.refresh = function() {\n /*jshint indent:false */\n var refreshEffort = new qq.Promise(),\n refreshCompleteCallback = function(response, success, xhrOrXdr) {\n handleFileItems(response, success, xhrOrXdr, refreshEffort);\n },\n requesterOptions = qq.extend({}, options),\n requester = new qq.SessionAjaxRequester(\n qq.extend(requesterOptions, {onComplete: refreshCompleteCallback})\n );\n\n requester.queryServer();\n\n return refreshEffort;\n };\n};\n","/*globals qq, XMLHttpRequest*/\n/**\n * Thin module used to send GET requests to the server, expecting information about session\n * data used to initialize an uploader instance.\n *\n * @param spec Various options used to influence the associated request.\n * @constructor\n */\nqq.SessionAjaxRequester = function(spec) {\n \"use strict\";\n\n var requester,\n options = {\n endpoint: null,\n customHeaders: {},\n params: {},\n cors: {\n expected: false,\n sendCredentials: false\n },\n onComplete: function(response, success, xhrOrXdr) {},\n log: function(str, level) {}\n };\n\n qq.extend(options, spec);\n\n function onComplete(id, xhrOrXdr, isError) {\n var response = null;\n\n /* jshint eqnull:true */\n if (xhrOrXdr.responseText != null) {\n try {\n response = qq.parseJson(xhrOrXdr.responseText);\n }\n catch (err) {\n options.log(\"Problem parsing session response: \" + err.message, \"error\");\n isError = true;\n }\n }\n\n options.onComplete(response, !isError, xhrOrXdr);\n }\n\n requester = qq.extend(this, new qq.AjaxRequester({\n acceptHeader: \"application/json\",\n validMethods: [\"GET\"],\n method: \"GET\",\n endpointStore: {\n get: function() {\n return options.endpoint;\n }\n },\n customHeaders: options.customHeaders,\n log: options.log,\n onComplete: onComplete,\n cors: options.cors\n }));\n\n qq.extend(this, {\n queryServer: function() {\n var params = qq.extend({}, options.params);\n\n options.log(\"Session query request.\");\n\n requester.initTransport(\"sessionRefresh\")\n .withParams(params)\n .withCacheBuster()\n .send();\n }\n });\n};\n","/* globals qq, ExifRestorer */\n/**\n * Controls generation of scaled images based on a reference image encapsulated in a `File` or `Blob`.\n * Scaled images are generated and converted to blobs on-demand.\n * Multiple scaled images per reference image with varying sizes and other properties are supported.\n *\n * @param spec Information about the scaled images to generate.\n * @param log Logger instance\n * @constructor\n */\nqq.Scaler = function(spec, log) {\n \"use strict\";\n\n var self = this,\n customResizeFunction = spec.customResizer,\n includeOriginal = spec.sendOriginal,\n orient = spec.orient,\n defaultType = spec.defaultType,\n defaultQuality = spec.defaultQuality / 100,\n failedToScaleText = spec.failureText,\n includeExif = spec.includeExif,\n sizes = this._getSortedSizes(spec.sizes);\n\n // Revealed API for instances of this module\n qq.extend(this, {\n // If no targeted sizes have been declared or if this browser doesn't support\n // client-side image preview generation, there is no scaling to do.\n enabled: qq.supportedFeatures.scaling && sizes.length > 0,\n\n getFileRecords: function(originalFileUuid, originalFileName, originalBlobOrBlobData) {\n var self = this,\n records = [],\n originalBlob = originalBlobOrBlobData.blob ? originalBlobOrBlobData.blob : originalBlobOrBlobData,\n identifier = new qq.Identify(originalBlob, log);\n\n // If the reference file cannot be rendered natively, we can't create scaled versions.\n if (identifier.isPreviewableSync()) {\n // Create records for each scaled version & add them to the records array, smallest first.\n qq.each(sizes, function(idx, sizeRecord) {\n var outputType = self._determineOutputType({\n defaultType: defaultType,\n requestedType: sizeRecord.type,\n refType: originalBlob.type\n });\n\n records.push({\n uuid: qq.getUniqueId(),\n name: self._getName(originalFileName, {\n name: sizeRecord.name,\n type: outputType,\n refType: originalBlob.type\n }),\n blob: new qq.BlobProxy(originalBlob,\n qq.bind(self._generateScaledImage, self, {\n customResizeFunction: customResizeFunction,\n maxSize: sizeRecord.maxSize,\n orient: orient,\n type: outputType,\n quality: defaultQuality,\n failedText: failedToScaleText,\n includeExif: includeExif,\n log: log\n }))\n });\n });\n\n records.push({\n uuid: originalFileUuid,\n name: originalFileName,\n size: originalBlob.size,\n blob: includeOriginal ? originalBlob : null\n });\n }\n else {\n records.push({\n uuid: originalFileUuid,\n name: originalFileName,\n size: originalBlob.size,\n blob: originalBlob\n });\n }\n\n return records;\n },\n\n handleNewFile: function(file, name, uuid, size, fileList, batchId, uuidParamName, api) {\n var self = this,\n buttonId = file.qqButtonId || (file.blob && file.blob.qqButtonId),\n scaledIds = [],\n originalId = null,\n addFileToHandler = api.addFileToHandler,\n uploadData = api.uploadData,\n paramsStore = api.paramsStore,\n proxyGroupId = qq.getUniqueId();\n\n qq.each(self.getFileRecords(uuid, name, file), function(idx, record) {\n var blobSize = record.size,\n id;\n\n if (record.blob instanceof qq.BlobProxy) {\n blobSize = -1;\n }\n\n id = uploadData.addFile({\n uuid: record.uuid,\n name: record.name,\n size: blobSize,\n batchId: batchId,\n proxyGroupId: proxyGroupId\n });\n\n if (record.blob instanceof qq.BlobProxy) {\n scaledIds.push(id);\n }\n else {\n originalId = id;\n }\n\n if (record.blob) {\n addFileToHandler(id, record.blob);\n fileList.push({id: id, file: record.blob});\n }\n else {\n uploadData.setStatus(id, qq.status.REJECTED);\n }\n });\n\n // If we are potentially uploading an original file and some scaled versions,\n // ensure the scaled versions include reference's to the parent's UUID and size\n // in their associated upload requests.\n if (originalId !== null) {\n qq.each(scaledIds, function(idx, scaledId) {\n var params = {\n qqparentuuid: uploadData.retrieve({id: originalId}).uuid,\n qqparentsize: uploadData.retrieve({id: originalId}).size\n };\n\n // Make sure the UUID for each scaled image is sent with the upload request,\n // to be consistent (since we may need to ensure it is sent for the original file as well).\n params[uuidParamName] = uploadData.retrieve({id: scaledId}).uuid;\n\n uploadData.setParentId(scaledId, originalId);\n paramsStore.addReadOnly(scaledId, params);\n });\n\n // If any scaled images are tied to this parent image, be SURE we send its UUID as an upload request\n // parameter as well.\n if (scaledIds.length) {\n (function() {\n var param = {};\n param[uuidParamName] = uploadData.retrieve({id: originalId}).uuid;\n paramsStore.addReadOnly(originalId, param);\n }());\n }\n }\n }\n });\n};\n\nqq.extend(qq.Scaler.prototype, {\n scaleImage: function(id, specs, api) {\n \"use strict\";\n\n if (!qq.supportedFeatures.scaling) {\n throw new qq.Error(\"Scaling is not supported in this browser!\");\n }\n\n var scalingEffort = new qq.Promise(),\n log = api.log,\n file = api.getFile(id),\n uploadData = api.uploadData.retrieve({id: id}),\n name = uploadData && uploadData.name,\n uuid = uploadData && uploadData.uuid,\n scalingOptions = {\n customResizer: specs.customResizer,\n sendOriginal: false,\n orient: specs.orient,\n defaultType: specs.type || null,\n defaultQuality: specs.quality,\n failedToScaleText: \"Unable to scale\",\n sizes: [{name: \"\", maxSize: specs.maxSize}]\n },\n scaler = new qq.Scaler(scalingOptions, log);\n\n if (!qq.Scaler || !qq.supportedFeatures.imagePreviews || !file) {\n scalingEffort.failure();\n\n log(\"Could not generate requested scaled image for \" + id + \". \" +\n \"Scaling is either not possible in this browser, or the file could not be located.\", \"error\");\n }\n else {\n (qq.bind(function() {\n // Assumption: There will never be more than one record\n var record = scaler.getFileRecords(uuid, name, file)[0];\n\n if (record && record.blob instanceof qq.BlobProxy) {\n record.blob.create().then(scalingEffort.success, scalingEffort.failure);\n }\n else {\n log(id + \" is not a scalable image!\", \"error\");\n scalingEffort.failure();\n }\n }, this)());\n }\n\n return scalingEffort;\n },\n\n // NOTE: We cannot reliably determine at this time if the UA supports a specific MIME type for the target format.\n // image/jpeg and image/png are the only safe choices at this time.\n _determineOutputType: function(spec) {\n \"use strict\";\n\n var requestedType = spec.requestedType,\n defaultType = spec.defaultType,\n referenceType = spec.refType;\n\n // If a default type and requested type have not been specified, this should be a\n // JPEG if the original type is a JPEG, otherwise, a PNG.\n if (!defaultType && !requestedType) {\n if (referenceType !== \"image/jpeg\") {\n return \"image/png\";\n }\n return referenceType;\n }\n\n // A specified default type is used when a requested type is not specified.\n if (!requestedType) {\n return defaultType;\n }\n\n // If requested type is specified, use it, as long as this recognized type is supported by the current UA\n if (qq.indexOf(Object.keys(qq.Identify.prototype.PREVIEWABLE_MIME_TYPES), requestedType) >= 0) {\n if (requestedType === \"image/tiff\") {\n return qq.supportedFeatures.tiffPreviews ? requestedType : defaultType;\n }\n\n return requestedType;\n }\n\n return defaultType;\n },\n\n // Get a file name for a generated scaled file record, based on the provided scaled image description\n _getName: function(originalName, scaledVersionProperties) {\n \"use strict\";\n\n var startOfExt = originalName.lastIndexOf(\".\"),\n versionType = scaledVersionProperties.type || \"image/png\",\n referenceType = scaledVersionProperties.refType,\n scaledName = \"\",\n scaledExt = qq.getExtension(originalName),\n nameAppendage = \"\";\n\n if (scaledVersionProperties.name && scaledVersionProperties.name.trim().length) {\n nameAppendage = \" (\" + scaledVersionProperties.name + \")\";\n }\n\n if (startOfExt >= 0) {\n scaledName = originalName.substr(0, startOfExt);\n\n if (referenceType !== versionType) {\n scaledExt = versionType.split(\"/\")[1];\n }\n\n scaledName += nameAppendage + \".\" + scaledExt;\n }\n else {\n scaledName = originalName + nameAppendage;\n }\n\n return scaledName;\n },\n\n // We want the smallest scaled file to be uploaded first\n _getSortedSizes: function(sizes) {\n \"use strict\";\n\n sizes = qq.extend([], sizes);\n\n return sizes.sort(function(a, b) {\n if (a.maxSize > b.maxSize) {\n return 1;\n }\n if (a.maxSize < b.maxSize) {\n return -1;\n }\n return 0;\n });\n },\n\n _generateScaledImage: function(spec, sourceFile) {\n \"use strict\";\n\n var self = this,\n customResizeFunction = spec.customResizeFunction,\n log = spec.log,\n maxSize = spec.maxSize,\n orient = spec.orient,\n type = spec.type,\n quality = spec.quality,\n failedText = spec.failedText,\n includeExif = spec.includeExif && sourceFile.type === \"image/jpeg\" && type === \"image/jpeg\",\n scalingEffort = new qq.Promise(),\n imageGenerator = new qq.ImageGenerator(log),\n canvas = document.createElement(\"canvas\");\n\n log(\"Attempting to generate scaled version for \" + sourceFile.name);\n\n imageGenerator.generate(sourceFile, canvas, {maxSize: maxSize, orient: orient, customResizeFunction: customResizeFunction}).then(function() {\n var scaledImageDataUri = canvas.toDataURL(type, quality),\n signalSuccess = function() {\n log(\"Success generating scaled version for \" + sourceFile.name);\n var blob = qq.dataUriToBlob(scaledImageDataUri);\n scalingEffort.success(blob);\n };\n\n if (includeExif) {\n self._insertExifHeader(sourceFile, scaledImageDataUri, log).then(function(scaledImageDataUriWithExif) {\n scaledImageDataUri = scaledImageDataUriWithExif;\n signalSuccess();\n },\n function() {\n log(\"Problem inserting EXIF header into scaled image. Using scaled image w/out EXIF data.\", \"error\");\n signalSuccess();\n });\n }\n else {\n signalSuccess();\n }\n }, function() {\n log(\"Failed attempt to generate scaled version for \" + sourceFile.name, \"error\");\n scalingEffort.failure(failedText);\n });\n\n return scalingEffort;\n },\n\n // Attempt to insert the original image's EXIF header into a scaled version.\n _insertExifHeader: function(originalImage, scaledImageDataUri, log) {\n \"use strict\";\n\n var reader = new FileReader(),\n insertionEffort = new qq.Promise(),\n originalImageDataUri = \"\";\n\n reader.onload = function() {\n originalImageDataUri = reader.result;\n insertionEffort.success(qq.ExifRestorer.restore(originalImageDataUri, scaledImageDataUri));\n };\n\n reader.onerror = function() {\n log(\"Problem reading \" + originalImage.name + \" during attempt to transfer EXIF data to scaled version.\", \"error\");\n insertionEffort.failure();\n };\n\n reader.readAsDataURL(originalImage);\n\n return insertionEffort;\n },\n\n _dataUriToBlob: function(dataUri) {\n \"use strict\";\n\n var byteString, mimeString, arrayBuffer, intArray;\n\n // convert base64 to raw binary data held in a string\n if (dataUri.split(\",\")[0].indexOf(\"base64\") >= 0) {\n byteString = atob(dataUri.split(\",\")[1]);\n }\n else {\n byteString = decodeURI(dataUri.split(\",\")[1]);\n }\n\n // extract the MIME\n mimeString = dataUri.split(\",\")[0]\n .split(\":\")[1]\n .split(\";\")[0];\n\n // write the bytes of the binary string to an ArrayBuffer\n arrayBuffer = new ArrayBuffer(byteString.length);\n intArray = new Uint8Array(arrayBuffer);\n qq.each(byteString, function(idx, character) {\n intArray[idx] = character.charCodeAt(0);\n });\n\n return this._createBlob(arrayBuffer, mimeString);\n },\n\n _createBlob: function(data, mime) {\n \"use strict\";\n\n var BlobBuilder = window.BlobBuilder ||\n window.WebKitBlobBuilder ||\n window.MozBlobBuilder ||\n window.MSBlobBuilder,\n blobBuilder = BlobBuilder && new BlobBuilder();\n\n if (blobBuilder) {\n blobBuilder.append(data);\n return blobBuilder.getBlob(mime);\n }\n else {\n return new Blob([data], {type: mime});\n }\n }\n});\n","//Based on MinifyJpeg\n//http://elicon.blog57.fc2.com/blog-entry-206.html\n\nqq.ExifRestorer = (function()\n{\n \n\tvar ExifRestorer = {};\n\t \n ExifRestorer.KEY_STR = \"ABCDEFGHIJKLMNOP\" +\n \"QRSTUVWXYZabcdef\" +\n \"ghijklmnopqrstuv\" +\n \"wxyz0123456789+/\" +\n \"=\";\n\n ExifRestorer.encode64 = function(input)\n {\n var output = \"\",\n chr1, chr2, chr3 = \"\",\n enc1, enc2, enc3, enc4 = \"\",\n i = 0;\n\n do {\n chr1 = input[i++];\n chr2 = input[i++];\n chr3 = input[i++];\n\n enc1 = chr1 >> 2;\n enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);\n enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);\n enc4 = chr3 & 63;\n\n if (isNaN(chr2)) {\n enc3 = enc4 = 64;\n } else if (isNaN(chr3)) {\n enc4 = 64;\n }\n\n output = output +\n this.KEY_STR.charAt(enc1) +\n this.KEY_STR.charAt(enc2) +\n this.KEY_STR.charAt(enc3) +\n this.KEY_STR.charAt(enc4);\n chr1 = chr2 = chr3 = \"\";\n enc1 = enc2 = enc3 = enc4 = \"\";\n } while (i < input.length);\n\n return output;\n };\n \n ExifRestorer.restore = function(origFileBase64, resizedFileBase64)\n {\n var expectedBase64Header = \"data:image/jpeg;base64,\";\n\n if (!origFileBase64.match(expectedBase64Header))\n {\n \treturn resizedFileBase64;\n } \n \n var rawImage = this.decode64(origFileBase64.replace(expectedBase64Header, \"\"));\n var segments = this.slice2Segments(rawImage);\n \n var image = this.exifManipulation(resizedFileBase64, segments);\n \n return expectedBase64Header + this.encode64(image);\n \n };\n\n\n ExifRestorer.exifManipulation = function(resizedFileBase64, segments)\n {\n var exifArray = this.getExifArray(segments),\n newImageArray = this.insertExif(resizedFileBase64, exifArray),\n aBuffer = new Uint8Array(newImageArray);\n\n return aBuffer;\n };\n\n\n ExifRestorer.getExifArray = function(segments)\n {\n var seg;\n for (var x = 0; x < segments.length; x++)\n {\n seg = segments[x];\n if (seg[0] == 255 & seg[1] == 225) //(ff e1)\n {\n return seg;\n }\n }\n return [];\n };\n\n\n ExifRestorer.insertExif = function(resizedFileBase64, exifArray)\n {\n var imageData = resizedFileBase64.replace(\"data:image/jpeg;base64,\", \"\"),\n buf = this.decode64(imageData),\n separatePoint = buf.indexOf(255,3),\n mae = buf.slice(0, separatePoint),\n ato = buf.slice(separatePoint),\n array = mae;\n\n array = array.concat(exifArray);\n array = array.concat(ato);\n return array;\n };\n\n\n \n ExifRestorer.slice2Segments = function(rawImageArray)\n {\n var head = 0,\n segments = [];\n\n while (1)\n {\n if (rawImageArray[head] == 255 & rawImageArray[head + 1] == 218){break;}\n if (rawImageArray[head] == 255 & rawImageArray[head + 1] == 216)\n {\n head += 2;\n }\n else\n {\n var length = rawImageArray[head + 2] * 256 + rawImageArray[head + 3],\n endPoint = head + length + 2,\n seg = rawImageArray.slice(head, endPoint);\n segments.push(seg);\n head = endPoint;\n }\n if (head > rawImageArray.length){break;}\n }\n\n return segments;\n };\n\n\n \n ExifRestorer.decode64 = function(input) \n {\n var output = \"\",\n chr1, chr2, chr3 = \"\",\n enc1, enc2, enc3, enc4 = \"\",\n i = 0,\n buf = [];\n\n // remove all characters that are not A-Z, a-z, 0-9, +, /, or =\n var base64test = /[^A-Za-z0-9\\+\\/\\=]/g;\n if (base64test.exec(input)) {\n throw new Error(\"There were invalid base64 characters in the input text. \" +\n \"Valid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='\");\n }\n input = input.replace(/[^A-Za-z0-9\\+\\/\\=]/g, \"\");\n\n do {\n enc1 = this.KEY_STR.indexOf(input.charAt(i++));\n enc2 = this.KEY_STR.indexOf(input.charAt(i++));\n enc3 = this.KEY_STR.indexOf(input.charAt(i++));\n enc4 = this.KEY_STR.indexOf(input.charAt(i++));\n\n chr1 = (enc1 << 2) | (enc2 >> 4);\n chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);\n chr3 = ((enc3 & 3) << 6) | enc4;\n\n buf.push(chr1);\n\n if (enc3 != 64) {\n buf.push(chr2);\n }\n if (enc4 != 64) {\n buf.push(chr3);\n }\n\n chr1 = chr2 = chr3 = \"\";\n enc1 = enc2 = enc3 = enc4 = \"\";\n\n } while (i < input.length);\n\n return buf;\n };\n\n \n return ExifRestorer;\n})();\n","/* globals qq */\n/**\n * Keeps a running tally of total upload progress for a batch of files.\n *\n * @param callback Invoked when total progress changes, passing calculated total loaded & total size values.\n * @param getSize Function that returns the size of a file given its ID\n * @constructor\n */\nqq.TotalProgress = function(callback, getSize) {\n \"use strict\";\n\n var perFileProgress = {},\n totalLoaded = 0,\n totalSize = 0,\n\n lastLoadedSent = -1,\n lastTotalSent = -1,\n callbackProxy = function(loaded, total) {\n if (loaded !== lastLoadedSent || total !== lastTotalSent) {\n callback(loaded, total);\n }\n\n lastLoadedSent = loaded;\n lastTotalSent = total;\n },\n\n /**\n * @param failed Array of file IDs that have failed\n * @param retryable Array of file IDs that are retryable\n * @returns true if none of the failed files are eligible for retry\n */\n noRetryableFiles = function(failed, retryable) {\n var none = true;\n\n qq.each(failed, function(idx, failedId) {\n if (qq.indexOf(retryable, failedId) >= 0) {\n none = false;\n return false;\n }\n });\n\n return none;\n },\n\n onCancel = function(id) {\n updateTotalProgress(id, -1, -1);\n delete perFileProgress[id];\n },\n\n onAllComplete = function(successful, failed, retryable) {\n if (failed.length === 0 || noRetryableFiles(failed, retryable)) {\n callbackProxy(totalSize, totalSize);\n this.reset();\n }\n },\n\n onNew = function(id) {\n var size = getSize(id);\n\n // We might not know the size yet, such as for blob proxies\n if (size > 0) {\n updateTotalProgress(id, 0, size);\n perFileProgress[id] = {loaded: 0, total: size};\n }\n },\n\n /**\n * Invokes the callback with the current total progress of all files in the batch. Called whenever it may\n * be appropriate to re-calculate and disseminate this data.\n *\n * @param id ID of a file that has changed in some important way\n * @param newLoaded New loaded value for this file. -1 if this value should no longer be part of calculations\n * @param newTotal New total size of the file. -1 if this value should no longer be part of calculations\n */\n updateTotalProgress = function(id, newLoaded, newTotal) {\n var oldLoaded = perFileProgress[id] ? perFileProgress[id].loaded : 0,\n oldTotal = perFileProgress[id] ? perFileProgress[id].total : 0;\n\n if (newLoaded === -1 && newTotal === -1) {\n totalLoaded -= oldLoaded;\n totalSize -= oldTotal;\n }\n else {\n if (newLoaded) {\n totalLoaded += newLoaded - oldLoaded;\n }\n if (newTotal) {\n totalSize += newTotal - oldTotal;\n }\n }\n\n callbackProxy(totalLoaded, totalSize);\n };\n\n qq.extend(this, {\n // Called when a batch of files has completed uploading.\n onAllComplete: onAllComplete,\n\n // Called when the status of a file has changed.\n onStatusChange: function(id, oldStatus, newStatus) {\n if (newStatus === qq.status.CANCELED || newStatus === qq.status.REJECTED) {\n onCancel(id);\n }\n else if (newStatus === qq.status.SUBMITTING) {\n onNew(id);\n }\n },\n\n // Called whenever the upload progress of an individual file has changed.\n onIndividualProgress: function(id, loaded, total) {\n updateTotalProgress(id, loaded, total);\n perFileProgress[id] = {loaded: loaded, total: total};\n },\n\n // Called whenever the total size of a file has changed, such as when the size of a generated blob is known.\n onNewSize: function(id) {\n onNew(id);\n },\n\n reset: function() {\n perFileProgress = {};\n totalLoaded = 0;\n totalSize = 0;\n }\n });\n};\n","/*globals qq*/\nqq.PasteSupport = function(o) {\n \"use strict\";\n\n var options, detachPasteHandler;\n\n options = {\n targetElement: null,\n callbacks: {\n log: function(message, level) {},\n pasteReceived: function(blob) {}\n }\n };\n\n function isImage(item) {\n return item.type &&\n item.type.indexOf(\"image/\") === 0;\n }\n\n function registerPasteHandler() {\n detachPasteHandler = qq(options.targetElement).attach(\"paste\", function(event) {\n var clipboardData = event.clipboardData;\n\n if (clipboardData) {\n qq.each(clipboardData.items, function(idx, item) {\n if (isImage(item)) {\n var blob = item.getAsFile();\n options.callbacks.pasteReceived(blob);\n }\n });\n }\n });\n }\n\n function unregisterPasteHandler() {\n if (detachPasteHandler) {\n detachPasteHandler();\n }\n }\n\n qq.extend(options, o);\n registerPasteHandler();\n\n qq.extend(this, {\n reset: function() {\n unregisterPasteHandler();\n }\n });\n};\n","/* globals qq */\n/**\n * Module that handles support for existing forms.\n *\n * @param options Options passed from the integrator-supplied options related to form support.\n * @param startUpload Callback to invoke when files \"stored\" should be uploaded.\n * @param log Proxy for the logger\n * @constructor\n */\nqq.FormSupport = function(options, startUpload, log) {\n \"use strict\";\n var self = this,\n interceptSubmit = options.interceptSubmit,\n formEl = options.element,\n autoUpload = options.autoUpload;\n\n // Available on the public API associated with this module.\n qq.extend(this, {\n // To be used by the caller to determine if the endpoint will be determined by some processing\n // that occurs in this module, such as if the form has an action attribute.\n // Ignore if `attachToForm === false`.\n newEndpoint: null,\n\n // To be used by the caller to determine if auto uploading should be allowed.\n // Ignore if `attachToForm === false`.\n newAutoUpload: autoUpload,\n\n // true if a form was detected and is being tracked by this module\n attachedToForm: false,\n\n // Returns an object with names and values for all valid form elements associated with the attached form.\n getFormInputsAsObject: function() {\n /* jshint eqnull:true */\n if (formEl == null) {\n return null;\n }\n\n return self._form2Obj(formEl);\n }\n });\n\n // If the form contains an action attribute, this should be the new upload endpoint.\n function determineNewEndpoint(formEl) {\n if (formEl.getAttribute(\"action\")) {\n self.newEndpoint = formEl.getAttribute(\"action\");\n }\n }\n\n // Return true only if the form is valid, or if we cannot make this determination.\n // If the form is invalid, ensure invalid field(s) are highlighted in the UI.\n function validateForm(formEl, nativeSubmit) {\n if (formEl.checkValidity && !formEl.checkValidity()) {\n log(\"Form did not pass validation checks - will not upload.\", \"error\");\n nativeSubmit();\n }\n else {\n return true;\n }\n }\n\n // Intercept form submit attempts, unless the integrator has told us not to do this.\n function maybeUploadOnSubmit(formEl) {\n var nativeSubmit = formEl.submit;\n\n // Intercept and squelch submit events.\n qq(formEl).attach(\"submit\", function(event) {\n event = event || window.event;\n\n if (event.preventDefault) {\n event.preventDefault();\n }\n else {\n event.returnValue = false;\n }\n\n validateForm(formEl, nativeSubmit) && startUpload();\n });\n\n // The form's `submit()` function may be called instead (i.e. via jQuery.submit()).\n // Intercept that too.\n formEl.submit = function() {\n validateForm(formEl, nativeSubmit) && startUpload();\n };\n }\n\n // If the element value passed from the uploader is a string, assume it is an element ID - select it.\n // The rest of the code in this module depends on this being an HTMLElement.\n function determineFormEl(formEl) {\n if (formEl) {\n if (qq.isString(formEl)) {\n formEl = document.getElementById(formEl);\n }\n\n if (formEl) {\n log(\"Attaching to form element.\");\n determineNewEndpoint(formEl);\n interceptSubmit && maybeUploadOnSubmit(formEl);\n }\n }\n\n return formEl;\n }\n\n formEl = determineFormEl(formEl);\n this.attachedToForm = !!formEl;\n};\n\nqq.extend(qq.FormSupport.prototype, {\n // Converts all relevant form fields to key/value pairs. This is meant to mimic the data a browser will\n // construct from a given form when the form is submitted.\n _form2Obj: function(form) {\n \"use strict\";\n var obj = {},\n notIrrelevantType = function(type) {\n var irrelevantTypes = [\n \"button\",\n \"image\",\n \"reset\",\n \"submit\"\n ];\n\n return qq.indexOf(irrelevantTypes, type.toLowerCase()) < 0;\n },\n radioOrCheckbox = function(type) {\n return qq.indexOf([\"checkbox\", \"radio\"], type.toLowerCase()) >= 0;\n },\n ignoreValue = function(el) {\n if (radioOrCheckbox(el.type) && !el.checked) {\n return true;\n }\n\n return el.disabled && el.type.toLowerCase() !== \"hidden\";\n },\n selectValue = function(select) {\n var value = null;\n\n qq.each(qq(select).children(), function(idx, child) {\n if (child.tagName.toLowerCase() === \"option\" && child.selected) {\n value = child.value;\n return false;\n }\n });\n\n return value;\n };\n\n qq.each(form.elements, function(idx, el) {\n if ((qq.isInput(el, true) || el.tagName.toLowerCase() === \"textarea\") &&\n notIrrelevantType(el.type) &&\n !ignoreValue(el)) {\n\n obj[el.name] = el.value;\n }\n else if (el.tagName.toLowerCase() === \"select\" && !ignoreValue(el)) {\n var value = selectValue(el);\n\n if (value !== null) {\n obj[el.name] = value;\n }\n }\n });\n\n return obj;\n }\n});\n","/*globals qq*/\n/**\n * Upload handler used that assumes the current user agent does not have any support for the\n * File API, and, therefore, makes use of iframes and forms to submit the files directly to\n * a generic server.\n *\n * @param options Options passed from the base handler\n * @param proxy Callbacks & methods used to query for or push out data/changes\n */\nqq.traditional = qq.traditional || {};\nqq.traditional.FormUploadHandler = function(options, proxy) {\n \"use strict\";\n\n var handler = this,\n getName = proxy.getName,\n getUuid = proxy.getUuid,\n log = proxy.log;\n\n /**\n * Returns json object received by iframe from server.\n */\n function getIframeContentJson(id, iframe) {\n /*jshint evil: true*/\n\n var response, doc, innerHtml;\n\n //IE may throw an \"access is denied\" error when attempting to access contentDocument on the iframe in some cases\n try {\n // iframe.contentWindow.document - for IE<7\n doc = iframe.contentDocument || iframe.contentWindow.document;\n innerHtml = doc.body.innerHTML;\n\n log(\"converting iframe's innerHTML to JSON\");\n log(\"innerHTML = \" + innerHtml);\n //plain text response may be wrapped in tag\n if (innerHtml && innerHtml.match(/^ 1 && !options.allowMultipleItems) {\n options.callbacks.processingDroppedFilesComplete([]);\n options.callbacks.dropError(\"tooManyFilesError\", \"\");\n uploadDropZone.dropDisabled(false);\n handleDataTransferPromise.failure();\n }\n else {\n droppedFiles = [];\n\n if (qq.isFolderDropSupported(dataTransfer)) {\n qq.each(dataTransfer.items, function(idx, item) {\n var entry = item.webkitGetAsEntry();\n\n if (entry) {\n //due to a bug in Chrome's File System API impl - #149735\n if (entry.isFile) {\n droppedFiles.push(item.getAsFile());\n }\n\n else {\n pendingFolderPromises.push(traverseFileTree(entry).done(function() {\n pendingFolderPromises.pop();\n if (pendingFolderPromises.length === 0) {\n handleDataTransferPromise.success();\n }\n }));\n }\n }\n });\n }\n else {\n droppedFiles = dataTransfer.files;\n }\n\n if (pendingFolderPromises.length === 0) {\n handleDataTransferPromise.success();\n }\n }\n\n return handleDataTransferPromise;\n }\n\n function setupDropzone(dropArea) {\n var dropZone = new qq.UploadDropZone({\n HIDE_ZONES_EVENT_NAME: HIDE_ZONES_EVENT_NAME,\n element: dropArea,\n onEnter: function(e) {\n qq(dropArea).addClass(options.classes.dropActive);\n e.stopPropagation();\n },\n onLeaveNotDescendants: function(e) {\n qq(dropArea).removeClass(options.classes.dropActive);\n },\n onDrop: function(e) {\n handleDataTransfer(e.dataTransfer, dropZone).then(\n function() {\n uploadDroppedFiles(droppedFiles, dropZone);\n },\n function() {\n options.callbacks.dropLog(\"Drop event DataTransfer parsing failed. No files will be uploaded.\", \"error\");\n }\n );\n }\n });\n\n disposeSupport.addDisposer(function() {\n dropZone.dispose();\n });\n\n qq(dropArea).hasAttribute(HIDE_BEFORE_ENTER_ATTR) && qq(dropArea).hide();\n\n uploadDropZones.push(dropZone);\n\n return dropZone;\n }\n\n function isFileDrag(dragEvent) {\n var fileDrag;\n\n qq.each(dragEvent.dataTransfer.types, function(key, val) {\n if (val === \"Files\") {\n fileDrag = true;\n return false;\n }\n });\n\n return fileDrag;\n }\n\n // Attempt to determine when the file has left the document. It is not always possible to detect this\n // in all cases, but it is generally possible in all browsers, with a few exceptions.\n //\n // Exceptions:\n // * IE10+ & Safari: We can't detect a file leaving the document if the Explorer window housing the file\n // overlays the browser window.\n // * IE10+: If the file is dragged out of the window too quickly, IE does not set the expected values of the\n // event's X & Y properties.\n function leavingDocumentOut(e) {\n if (qq.firefox()) {\n return !e.relatedTarget;\n }\n\n if (qq.safari()) {\n return e.x < 0 || e.y < 0;\n }\n\n return e.x === 0 && e.y === 0;\n }\n\n function setupDragDrop() {\n var dropZones = options.dropZoneElements,\n\n maybeHideDropZones = function() {\n setTimeout(function() {\n qq.each(dropZones, function(idx, dropZone) {\n qq(dropZone).hasAttribute(HIDE_BEFORE_ENTER_ATTR) && qq(dropZone).hide();\n qq(dropZone).removeClass(options.classes.dropActive);\n });\n }, 10);\n };\n\n qq.each(dropZones, function(idx, dropZone) {\n var uploadDropZone = setupDropzone(dropZone);\n\n // IE <= 9 does not support the File API used for drag+drop uploads\n if (dropZones.length && qq.supportedFeatures.fileDrop) {\n disposeSupport.attach(document, \"dragenter\", function(e) {\n if (!uploadDropZone.dropDisabled() && isFileDrag(e)) {\n qq.each(dropZones, function(idx, dropZone) {\n // We can't apply styles to non-HTMLElements, since they lack the `style` property.\n // Also, if the drop zone isn't initially hidden, let's not mess with `style.display`.\n if (dropZone instanceof HTMLElement &&\n qq(dropZone).hasAttribute(HIDE_BEFORE_ENTER_ATTR)) {\n\n qq(dropZone).css({display: \"block\"});\n }\n });\n }\n });\n }\n });\n\n disposeSupport.attach(document, \"dragleave\", function(e) {\n if (leavingDocumentOut(e)) {\n maybeHideDropZones();\n }\n });\n\n // Just in case we were not able to detect when a dragged file has left the document,\n // hide all relevant drop zones the next time the mouse enters the document.\n // Note that mouse events such as this one are not fired during drag operations.\n disposeSupport.attach(qq(document).children()[0], \"mouseenter\", function(e) {\n maybeHideDropZones();\n });\n\n disposeSupport.attach(document, \"drop\", function(e) {\n e.preventDefault();\n maybeHideDropZones();\n });\n\n disposeSupport.attach(document, HIDE_ZONES_EVENT_NAME, maybeHideDropZones);\n }\n\n setupDragDrop();\n\n qq.extend(this, {\n setupExtraDropzone: function(element) {\n options.dropZoneElements.push(element);\n setupDropzone(element);\n },\n\n removeDropzone: function(element) {\n var i,\n dzs = options.dropZoneElements;\n\n for (i in dzs) {\n if (dzs[i] === element) {\n return dzs.splice(i, 1);\n }\n }\n },\n\n dispose: function() {\n disposeSupport.dispose();\n qq.each(uploadDropZones, function(idx, dropZone) {\n dropZone.dispose();\n });\n }\n });\n};\n\nqq.DragAndDrop.callbacks = function() {\n \"use strict\";\n\n return {\n processingDroppedFiles: function() {},\n processingDroppedFilesComplete: function(files, targetEl) {},\n dropError: function(code, errorSpecifics) {\n qq.log(\"Drag & drop error code '\" + code + \" with these specifics: '\" + errorSpecifics + \"'\", \"error\");\n },\n dropLog: function(message, level) {\n qq.log(message, level);\n }\n };\n};\n\nqq.UploadDropZone = function(o) {\n \"use strict\";\n\n var disposeSupport = new qq.DisposeSupport(),\n options, element, preventDrop, dropOutsideDisabled;\n\n options = {\n element: null,\n onEnter: function(e) {},\n onLeave: function(e) {},\n // is not fired when leaving element by hovering descendants\n onLeaveNotDescendants: function(e) {},\n onDrop: function(e) {}\n };\n\n qq.extend(options, o);\n element = options.element;\n\n function dragoverShouldBeCanceled() {\n return qq.safari() || (qq.firefox() && qq.windows());\n }\n\n function disableDropOutside(e) {\n // run only once for all instances\n if (!dropOutsideDisabled) {\n\n // for these cases we need to catch onDrop to reset dropArea\n if (dragoverShouldBeCanceled) {\n disposeSupport.attach(document, \"dragover\", function(e) {\n e.preventDefault();\n });\n } else {\n disposeSupport.attach(document, \"dragover\", function(e) {\n if (e.dataTransfer) {\n e.dataTransfer.dropEffect = \"none\";\n e.preventDefault();\n }\n });\n }\n\n dropOutsideDisabled = true;\n }\n }\n\n function isValidFileDrag(e) {\n // e.dataTransfer currently causing IE errors\n // IE9 does NOT support file API, so drag-and-drop is not possible\n if (!qq.supportedFeatures.fileDrop) {\n return false;\n }\n\n var effectTest, dt = e.dataTransfer,\n // do not check dt.types.contains in webkit, because it crashes safari 4\n isSafari = qq.safari();\n\n // dt.effectAllowed is none in Safari 5\n // dt.types.contains check is for firefox\n\n // dt.effectAllowed crashes IE 11 & 10 when files have been dragged from\n // the filesystem\n effectTest = qq.ie() && qq.supportedFeatures.fileDrop ? true : dt.effectAllowed !== \"none\";\n return dt && effectTest && (dt.files || (!isSafari && dt.types.contains && dt.types.contains(\"Files\")));\n }\n\n function isOrSetDropDisabled(isDisabled) {\n if (isDisabled !== undefined) {\n preventDrop = isDisabled;\n }\n return preventDrop;\n }\n\n function triggerHidezonesEvent() {\n var hideZonesEvent;\n\n function triggerUsingOldApi() {\n hideZonesEvent = document.createEvent(\"Event\");\n hideZonesEvent.initEvent(options.HIDE_ZONES_EVENT_NAME, true, true);\n }\n\n if (window.CustomEvent) {\n try {\n hideZonesEvent = new CustomEvent(options.HIDE_ZONES_EVENT_NAME);\n }\n catch (err) {\n triggerUsingOldApi();\n }\n }\n else {\n triggerUsingOldApi();\n }\n\n document.dispatchEvent(hideZonesEvent);\n }\n\n function attachEvents() {\n disposeSupport.attach(element, \"dragover\", function(e) {\n if (!isValidFileDrag(e)) {\n return;\n }\n\n // dt.effectAllowed crashes IE 11 & 10 when files have been dragged from\n // the filesystem\n var effect = qq.ie() && qq.supportedFeatures.fileDrop ? null : e.dataTransfer.effectAllowed;\n if (effect === \"move\" || effect === \"linkMove\") {\n e.dataTransfer.dropEffect = \"move\"; // for FF (only move allowed)\n } else {\n e.dataTransfer.dropEffect = \"copy\"; // for Chrome\n }\n\n e.stopPropagation();\n e.preventDefault();\n });\n\n disposeSupport.attach(element, \"dragenter\", function(e) {\n if (!isOrSetDropDisabled()) {\n if (!isValidFileDrag(e)) {\n return;\n }\n options.onEnter(e);\n }\n });\n\n disposeSupport.attach(element, \"dragleave\", function(e) {\n if (!isValidFileDrag(e)) {\n return;\n }\n\n options.onLeave(e);\n\n var relatedTarget = document.elementFromPoint(e.clientX, e.clientY);\n // do not fire when moving a mouse over a descendant\n if (qq(this).contains(relatedTarget)) {\n return;\n }\n\n options.onLeaveNotDescendants(e);\n });\n\n disposeSupport.attach(element, \"drop\", function(e) {\n if (!isOrSetDropDisabled()) {\n if (!isValidFileDrag(e)) {\n return;\n }\n\n e.preventDefault();\n e.stopPropagation();\n options.onDrop(e);\n\n triggerHidezonesEvent();\n }\n });\n }\n\n disableDropOutside();\n attachEvents();\n\n qq.extend(this, {\n dropDisabled: function(isDisabled) {\n return isOrSetDropDisabled(isDisabled);\n },\n\n dispose: function() {\n disposeSupport.dispose();\n },\n\n getElement: function() {\n return element;\n }\n });\n};\n","/*globals qq */\n/**\n * Defines the public API for FineUploader mode.\n */\n(function() {\n \"use strict\";\n\n qq.uiPublicApi = {\n addInitialFiles: function(cannedFileList) {\n this._parent.prototype.addInitialFiles.apply(this, arguments);\n this._templating.addCacheToDom();\n },\n\n clearStoredFiles: function() {\n this._parent.prototype.clearStoredFiles.apply(this, arguments);\n this._templating.clearFiles();\n },\n\n addExtraDropzone: function(element) {\n this._dnd && this._dnd.setupExtraDropzone(element);\n },\n\n removeExtraDropzone: function(element) {\n if (this._dnd) {\n return this._dnd.removeDropzone(element);\n }\n },\n\n getItemByFileId: function(id) {\n if (!this._templating.isHiddenForever(id)) {\n return this._templating.getFileContainer(id);\n }\n },\n\n reset: function() {\n this._parent.prototype.reset.apply(this, arguments);\n this._templating.reset();\n\n if (!this._options.button && this._templating.getButton()) {\n this._defaultButtonId = this._createUploadButton({\n element: this._templating.getButton(),\n title: this._options.text.fileInputTitle\n }).getButtonId();\n }\n\n if (this._dnd) {\n this._dnd.dispose();\n this._dnd = this._setupDragAndDrop();\n }\n\n this._totalFilesInBatch = 0;\n this._filesInBatchAddedToUi = 0;\n\n this._setupClickAndEditEventHandlers();\n },\n\n setName: function(id, newName) {\n var formattedFilename = this._options.formatFileName(newName);\n\n this._parent.prototype.setName.apply(this, arguments);\n this._templating.updateFilename(id, formattedFilename);\n },\n\n pauseUpload: function(id) {\n var paused = this._parent.prototype.pauseUpload.apply(this, arguments);\n\n paused && this._templating.uploadPaused(id);\n return paused;\n },\n\n continueUpload: function(id) {\n var continued = this._parent.prototype.continueUpload.apply(this, arguments);\n\n continued && this._templating.uploadContinued(id);\n return continued;\n },\n\n getId: function(fileContainerOrChildEl) {\n return this._templating.getFileId(fileContainerOrChildEl);\n },\n\n getDropTarget: function(fileId) {\n var file = this.getFile(fileId);\n\n return file.qqDropTarget;\n }\n };\n\n /**\n * Defines the private (internal) API for FineUploader mode.\n */\n qq.uiPrivateApi = {\n _getButton: function(buttonId) {\n var button = this._parent.prototype._getButton.apply(this, arguments);\n\n if (!button) {\n if (buttonId === this._defaultButtonId) {\n button = this._templating.getButton();\n }\n }\n\n return button;\n },\n\n _removeFileItem: function(fileId) {\n this._templating.removeFile(fileId);\n },\n\n _setupClickAndEditEventHandlers: function() {\n this._fileButtonsClickHandler = qq.FileButtonsClickHandler && this._bindFileButtonsClickEvent();\n\n // A better approach would be to check specifically for focusin event support by querying the DOM API,\n // but the DOMFocusIn event is not exposed as a property, so we have to resort to UA string sniffing.\n this._focusinEventSupported = !qq.firefox();\n\n if (this._isEditFilenameEnabled())\n {\n this._filenameClickHandler = this._bindFilenameClickEvent();\n this._filenameInputFocusInHandler = this._bindFilenameInputFocusInEvent();\n this._filenameInputFocusHandler = this._bindFilenameInputFocusEvent();\n }\n },\n\n _setupDragAndDrop: function() {\n var self = this,\n dropZoneElements = this._options.dragAndDrop.extraDropzones,\n templating = this._templating,\n defaultDropZone = templating.getDropZone();\n\n defaultDropZone && dropZoneElements.push(defaultDropZone);\n\n return new qq.DragAndDrop({\n dropZoneElements: dropZoneElements,\n allowMultipleItems: this._options.multiple,\n classes: {\n dropActive: this._options.classes.dropActive\n },\n callbacks: {\n processingDroppedFiles: function() {\n templating.showDropProcessing();\n },\n processingDroppedFilesComplete: function(files, targetEl) {\n templating.hideDropProcessing();\n\n qq.each(files, function(idx, file) {\n file.qqDropTarget = targetEl;\n });\n\n if (files.length) {\n self.addFiles(files, null, null);\n }\n },\n dropError: function(code, errorData) {\n self._itemError(code, errorData);\n },\n dropLog: function(message, level) {\n self.log(message, level);\n }\n }\n });\n },\n\n _bindFileButtonsClickEvent: function() {\n var self = this;\n\n return new qq.FileButtonsClickHandler({\n templating: this._templating,\n\n log: function(message, lvl) {\n self.log(message, lvl);\n },\n\n onDeleteFile: function(fileId) {\n self.deleteFile(fileId);\n },\n\n onCancel: function(fileId) {\n self.cancel(fileId);\n },\n\n onRetry: function(fileId) {\n self.retry(fileId);\n },\n\n onPause: function(fileId) {\n self.pauseUpload(fileId);\n },\n\n onContinue: function(fileId) {\n self.continueUpload(fileId);\n },\n\n onGetName: function(fileId) {\n return self.getName(fileId);\n }\n });\n },\n\n _isEditFilenameEnabled: function() {\n /*jshint -W014 */\n return this._templating.isEditFilenamePossible()\n && !this._options.autoUpload\n && qq.FilenameClickHandler\n && qq.FilenameInputFocusHandler\n && qq.FilenameInputFocusHandler;\n },\n\n _filenameEditHandler: function() {\n var self = this,\n templating = this._templating;\n\n return {\n templating: templating,\n log: function(message, lvl) {\n self.log(message, lvl);\n },\n onGetUploadStatus: function(fileId) {\n return self.getUploads({id: fileId}).status;\n },\n onGetName: function(fileId) {\n return self.getName(fileId);\n },\n onSetName: function(id, newName) {\n self.setName(id, newName);\n },\n onEditingStatusChange: function(id, isEditing) {\n var qqInput = qq(templating.getEditInput(id)),\n qqFileContainer = qq(templating.getFileContainer(id));\n\n if (isEditing) {\n qqInput.addClass(\"qq-editing\");\n templating.hideFilename(id);\n templating.hideEditIcon(id);\n }\n else {\n qqInput.removeClass(\"qq-editing\");\n templating.showFilename(id);\n templating.showEditIcon(id);\n }\n\n // Force IE8 and older to repaint\n qqFileContainer.addClass(\"qq-temp\").removeClass(\"qq-temp\");\n }\n };\n },\n\n _onUploadStatusChange: function(id, oldStatus, newStatus) {\n this._parent.prototype._onUploadStatusChange.apply(this, arguments);\n\n if (this._isEditFilenameEnabled()) {\n // Status for a file exists before it has been added to the DOM, so we must be careful here.\n if (this._templating.getFileContainer(id) && newStatus !== qq.status.SUBMITTED) {\n this._templating.markFilenameEditable(id);\n this._templating.hideEditIcon(id);\n }\n }\n\n if (oldStatus === qq.status.UPLOAD_RETRYING && newStatus === qq.status.UPLOADING) {\n this._templating.hideRetry(id);\n this._templating.setStatusText(id);\n qq(this._templating.getFileContainer(id)).removeClass(this._classes.retrying);\n }\n else if (newStatus === qq.status.UPLOAD_FAILED) {\n this._templating.hidePause(id);\n }\n },\n\n _bindFilenameInputFocusInEvent: function() {\n var spec = qq.extend({}, this._filenameEditHandler());\n\n return new qq.FilenameInputFocusInHandler(spec);\n },\n\n _bindFilenameInputFocusEvent: function() {\n var spec = qq.extend({}, this._filenameEditHandler());\n\n return new qq.FilenameInputFocusHandler(spec);\n },\n\n _bindFilenameClickEvent: function() {\n var spec = qq.extend({}, this._filenameEditHandler());\n\n return new qq.FilenameClickHandler(spec);\n },\n\n _storeForLater: function(id) {\n this._parent.prototype._storeForLater.apply(this, arguments);\n this._templating.hideSpinner(id);\n },\n\n _onAllComplete: function(successful, failed) {\n this._parent.prototype._onAllComplete.apply(this, arguments);\n this._templating.resetTotalProgress();\n },\n\n _onSubmit: function(id, name) {\n var file = this.getFile(id);\n\n if (file && file.qqPath && this._options.dragAndDrop.reportDirectoryPaths) {\n this._paramsStore.addReadOnly(id, {\n qqpath: file.qqPath\n });\n }\n\n this._parent.prototype._onSubmit.apply(this, arguments);\n this._addToList(id, name);\n },\n\n // The file item has been added to the DOM.\n _onSubmitted: function(id) {\n // If the edit filename feature is enabled, mark the filename element as \"editable\" and the associated edit icon\n if (this._isEditFilenameEnabled()) {\n this._templating.markFilenameEditable(id);\n this._templating.showEditIcon(id);\n\n // If the focusin event is not supported, we must add a focus handler to the newly create edit filename text input\n if (!this._focusinEventSupported) {\n this._filenameInputFocusHandler.addHandler(this._templating.getEditInput(id));\n }\n }\n },\n\n // Update the progress bar & percentage as the file is uploaded\n _onProgress: function(id, name, loaded, total) {\n this._parent.prototype._onProgress.apply(this, arguments);\n\n this._templating.updateProgress(id, loaded, total);\n\n if (total === 0 || Math.round(loaded / total * 100) === 100) {\n this._templating.hideCancel(id);\n this._templating.hidePause(id);\n this._templating.hideProgress(id);\n this._templating.setStatusText(id, this._options.text.waitingForResponse);\n\n // If ~last byte was sent, display total file size\n this._displayFileSize(id);\n }\n else {\n // If still uploading, display percentage - total size is actually the total request(s) size\n this._displayFileSize(id, loaded, total);\n }\n },\n\n _onTotalProgress: function(loaded, total) {\n this._parent.prototype._onTotalProgress.apply(this, arguments);\n this._templating.updateTotalProgress(loaded, total);\n },\n\n _onComplete: function(id, name, result, xhr) {\n var parentRetVal = this._parent.prototype._onComplete.apply(this, arguments),\n templating = this._templating,\n fileContainer = templating.getFileContainer(id),\n self = this;\n\n function completeUpload(result) {\n // If this file is not represented in the templating module, perhaps it was hidden intentionally.\n // If so, don't perform any UI-related tasks related to this file.\n if (!fileContainer) {\n return;\n }\n\n templating.setStatusText(id);\n\n qq(fileContainer).removeClass(self._classes.retrying);\n templating.hideProgress(id);\n\n if (self.getUploads({id: id}).status !== qq.status.UPLOAD_FAILED) {\n templating.hideCancel(id);\n }\n templating.hideSpinner(id);\n\n if (result.success) {\n self._markFileAsSuccessful(id);\n }\n else {\n qq(fileContainer).addClass(self._classes.fail);\n templating.showCancel(id);\n\n if (templating.isRetryPossible() && !self._preventRetries[id]) {\n qq(fileContainer).addClass(self._classes.retryable);\n templating.showRetry(id);\n }\n self._controlFailureTextDisplay(id, result);\n }\n }\n\n // The parent may need to perform some async operation before we can accurately determine the status of the upload.\n if (parentRetVal instanceof qq.Promise) {\n parentRetVal.done(function(newResult) {\n completeUpload(newResult);\n });\n\n }\n else {\n completeUpload(result);\n }\n\n return parentRetVal;\n },\n\n _markFileAsSuccessful: function(id) {\n var templating = this._templating;\n\n if (this._isDeletePossible()) {\n templating.showDeleteButton(id);\n }\n\n qq(templating.getFileContainer(id)).addClass(this._classes.success);\n\n this._maybeUpdateThumbnail(id);\n },\n\n _onUploadPrep: function(id) {\n this._parent.prototype._onUploadPrep.apply(this, arguments);\n this._templating.showSpinner(id);\n },\n\n _onUpload: function(id, name) {\n var parentRetVal = this._parent.prototype._onUpload.apply(this, arguments);\n\n this._templating.showSpinner(id);\n\n return parentRetVal;\n },\n\n _onUploadChunk: function(id, chunkData) {\n this._parent.prototype._onUploadChunk.apply(this, arguments);\n\n // Only display the pause button if we have finished uploading at least one chunk\n // & this file can be resumed\n if (chunkData.partIndex > 0 && this._handler.isResumable(id)) {\n this._templating.allowPause(id);\n }\n },\n\n _onCancel: function(id, name) {\n this._parent.prototype._onCancel.apply(this, arguments);\n this._removeFileItem(id);\n\n if (this._getNotFinished() === 0) {\n this._templating.resetTotalProgress();\n }\n },\n\n _onBeforeAutoRetry: function(id) {\n var retryNumForDisplay, maxAuto, retryNote;\n\n this._parent.prototype._onBeforeAutoRetry.apply(this, arguments);\n\n this._showCancelLink(id);\n\n if (this._options.retry.showAutoRetryNote) {\n retryNumForDisplay = this._autoRetries[id];\n maxAuto = this._options.retry.maxAutoAttempts;\n\n retryNote = this._options.retry.autoRetryNote.replace(/\\{retryNum\\}/g, retryNumForDisplay);\n retryNote = retryNote.replace(/\\{maxAuto\\}/g, maxAuto);\n\n this._templating.setStatusText(id, retryNote);\n qq(this._templating.getFileContainer(id)).addClass(this._classes.retrying);\n }\n },\n\n //return false if we should not attempt the requested retry\n _onBeforeManualRetry: function(id) {\n if (this._parent.prototype._onBeforeManualRetry.apply(this, arguments)) {\n this._templating.resetProgress(id);\n qq(this._templating.getFileContainer(id)).removeClass(this._classes.fail);\n this._templating.setStatusText(id);\n this._templating.showSpinner(id);\n this._showCancelLink(id);\n return true;\n }\n else {\n qq(this._templating.getFileContainer(id)).addClass(this._classes.retryable);\n this._templating.showRetry(id);\n return false;\n }\n },\n\n _onSubmitDelete: function(id) {\n var onSuccessCallback = qq.bind(this._onSubmitDeleteSuccess, this);\n\n this._parent.prototype._onSubmitDelete.call(this, id, onSuccessCallback);\n },\n\n _onSubmitDeleteSuccess: function(id, uuid, additionalMandatedParams) {\n if (this._options.deleteFile.forceConfirm) {\n this._showDeleteConfirm.apply(this, arguments);\n }\n else {\n this._sendDeleteRequest.apply(this, arguments);\n }\n },\n\n _onDeleteComplete: function(id, xhr, isError) {\n this._parent.prototype._onDeleteComplete.apply(this, arguments);\n\n this._templating.hideSpinner(id);\n\n if (isError) {\n this._templating.setStatusText(id, this._options.deleteFile.deletingFailedText);\n this._templating.showDeleteButton(id);\n }\n else {\n this._removeFileItem(id);\n }\n },\n\n _sendDeleteRequest: function(id, uuid, additionalMandatedParams) {\n this._templating.hideDeleteButton(id);\n this._templating.showSpinner(id);\n this._templating.setStatusText(id, this._options.deleteFile.deletingStatusText);\n this._deleteHandler.sendDelete.apply(this, arguments);\n },\n\n _showDeleteConfirm: function(id, uuid, mandatedParams) {\n /*jshint -W004 */\n var fileName = this.getName(id),\n confirmMessage = this._options.deleteFile.confirmMessage.replace(/\\{filename\\}/g, fileName),\n uuid = this.getUuid(id),\n deleteRequestArgs = arguments,\n self = this,\n retVal;\n\n retVal = this._options.showConfirm(confirmMessage);\n\n if (qq.isGenericPromise(retVal)) {\n retVal.then(function() {\n self._sendDeleteRequest.apply(self, deleteRequestArgs);\n });\n }\n else if (retVal !== false) {\n self._sendDeleteRequest.apply(self, deleteRequestArgs);\n }\n },\n\n _addToList: function(id, name, canned) {\n var prependData,\n prependIndex = 0,\n dontDisplay = this._handler.isProxied(id) && this._options.scaling.hideScaled,\n record;\n\n if (this._options.display.prependFiles) {\n if (this._totalFilesInBatch > 1 && this._filesInBatchAddedToUi > 0) {\n prependIndex = this._filesInBatchAddedToUi - 1;\n }\n\n prependData = {\n index: prependIndex\n };\n }\n\n if (!canned) {\n if (this._options.disableCancelForFormUploads && !qq.supportedFeatures.ajaxUploading) {\n this._templating.disableCancel();\n }\n\n // Cancel all existing (previous) files and clear the list if this file is not part of\n // a scaled file group that has already been accepted, or if this file is not part of\n // a scaled file group at all.\n if (!this._options.multiple) {\n record = this.getUploads({id: id});\n\n this._handledProxyGroup = this._handledProxyGroup || record.proxyGroupId;\n\n if (record.proxyGroupId !== this._handledProxyGroup || !record.proxyGroupId) {\n this._handler.cancelAll();\n this._clearList();\n this._handledProxyGroup = null;\n }\n }\n }\n\n if (canned) {\n this._templating.addFileToCache(id, this._options.formatFileName(name), prependData, dontDisplay);\n this._templating.updateThumbnail(id, this._thumbnailUrls[id], true, this._options.thumbnails.customResizer);\n }\n else {\n this._templating.addFile(id, this._options.formatFileName(name), prependData, dontDisplay);\n this._templating.generatePreview(id, this.getFile(id), this._options.thumbnails.customResizer);\n }\n\n this._filesInBatchAddedToUi += 1;\n\n if (canned ||\n (this._options.display.fileSizeOnSubmit && qq.supportedFeatures.ajaxUploading)) {\n\n this._displayFileSize(id);\n }\n },\n\n _clearList: function() {\n this._templating.clearFiles();\n this.clearStoredFiles();\n },\n\n _displayFileSize: function(id, loadedSize, totalSize) {\n var size = this.getSize(id),\n sizeForDisplay = this._formatSize(size);\n\n if (size >= 0) {\n if (loadedSize !== undefined && totalSize !== undefined) {\n sizeForDisplay = this._formatProgress(loadedSize, totalSize);\n }\n\n this._templating.updateSize(id, sizeForDisplay);\n }\n },\n\n _formatProgress: function(uploadedSize, totalSize) {\n var message = this._options.text.formatProgress;\n function r(name, replacement) { message = message.replace(name, replacement); }\n\n r(\"{percent}\", Math.round(uploadedSize / totalSize * 100));\n r(\"{total_size}\", this._formatSize(totalSize));\n return message;\n },\n\n _controlFailureTextDisplay: function(id, response) {\n var mode, responseProperty, failureReason;\n\n mode = this._options.failedUploadTextDisplay.mode;\n responseProperty = this._options.failedUploadTextDisplay.responseProperty;\n\n if (mode === \"custom\") {\n failureReason = response[responseProperty];\n if (!failureReason) {\n failureReason = this._options.text.failUpload;\n }\n\n this._templating.setStatusText(id, failureReason);\n\n if (this._options.failedUploadTextDisplay.enableTooltip) {\n this._showTooltip(id, failureReason);\n }\n }\n else if (mode === \"default\") {\n this._templating.setStatusText(id, this._options.text.failUpload);\n }\n else if (mode !== \"none\") {\n this.log(\"failedUploadTextDisplay.mode value of '\" + mode + \"' is not valid\", \"warn\");\n }\n },\n\n _showTooltip: function(id, text) {\n this._templating.getFileContainer(id).title = text;\n },\n\n _showCancelLink: function(id) {\n if (!this._options.disableCancelForFormUploads || qq.supportedFeatures.ajaxUploading) {\n this._templating.showCancel(id);\n }\n },\n\n _itemError: function(code, name, item) {\n var message = this._parent.prototype._itemError.apply(this, arguments);\n this._options.showMessage(message);\n },\n\n _batchError: function(message) {\n this._parent.prototype._batchError.apply(this, arguments);\n this._options.showMessage(message);\n },\n\n _setupPastePrompt: function() {\n var self = this;\n\n this._options.callbacks.onPasteReceived = function() {\n var message = self._options.paste.namePromptMessage,\n defaultVal = self._options.paste.defaultName;\n\n return self._options.showPrompt(message, defaultVal);\n };\n },\n\n _fileOrBlobRejected: function(id, name) {\n this._totalFilesInBatch -= 1;\n this._parent.prototype._fileOrBlobRejected.apply(this, arguments);\n },\n\n _prepareItemsForUpload: function(items, params, endpoint) {\n this._totalFilesInBatch = items.length;\n this._filesInBatchAddedToUi = 0;\n this._parent.prototype._prepareItemsForUpload.apply(this, arguments);\n },\n\n _maybeUpdateThumbnail: function(fileId) {\n var thumbnailUrl = this._thumbnailUrls[fileId],\n fileStatus = this.getUploads({id: fileId}).status;\n\n if (fileStatus !== qq.status.DELETED &&\n (thumbnailUrl ||\n this._options.thumbnails.placeholders.waitUntilResponse ||\n !qq.supportedFeatures.imagePreviews)) {\n\n // This will replace the \"waiting\" placeholder with a \"preview not available\" placeholder\n // if called with a null thumbnailUrl.\n this._templating.updateThumbnail(fileId, thumbnailUrl, this._options.thumbnails.customResizer);\n }\n },\n\n _addCannedFile: function(sessionData) {\n var id = this._parent.prototype._addCannedFile.apply(this, arguments);\n\n this._addToList(id, this.getName(id), true);\n this._templating.hideSpinner(id);\n this._templating.hideCancel(id);\n this._markFileAsSuccessful(id);\n\n return id;\n },\n\n _setSize: function(id, newSize) {\n this._parent.prototype._setSize.apply(this, arguments);\n\n this._templating.updateSize(id, this._formatSize(newSize));\n },\n\n _sessionRequestComplete: function() {\n this._templating.addCacheToDom();\n this._parent.prototype._sessionRequestComplete.apply(this, arguments);\n }\n };\n}());\n","/*globals qq */\n/**\n * This defines FineUploader mode, which is a default UI w/ drag & drop uploading.\n */\nqq.FineUploader = function(o, namespace) {\n \"use strict\";\n\n var self = this;\n\n // By default this should inherit instance data from FineUploaderBasic, but this can be overridden\n // if the (internal) caller defines a different parent. The parent is also used by\n // the private and public API functions that need to delegate to a parent function.\n this._parent = namespace ? qq[namespace].FineUploaderBasic : qq.FineUploaderBasic;\n this._parent.apply(this, arguments);\n\n // Options provided by FineUploader mode\n qq.extend(this._options, {\n element: null,\n\n button: null,\n\n listElement: null,\n\n dragAndDrop: {\n extraDropzones: [],\n reportDirectoryPaths: false\n },\n\n text: {\n formatProgress: \"{percent}% of {total_size}\",\n failUpload: \"Upload failed\",\n waitingForResponse: \"Processing...\",\n paused: \"Paused\"\n },\n\n template: \"qq-template\",\n\n classes: {\n retrying: \"qq-upload-retrying\",\n retryable: \"qq-upload-retryable\",\n success: \"qq-upload-success\",\n fail: \"qq-upload-fail\",\n editable: \"qq-editable\",\n hide: \"qq-hide\",\n dropActive: \"qq-upload-drop-area-active\"\n },\n\n failedUploadTextDisplay: {\n mode: \"default\", //default, custom, or none\n responseProperty: \"error\",\n enableTooltip: true\n },\n\n messages: {\n tooManyFilesError: \"You may only drop one file\",\n unsupportedBrowser: \"Unrecoverable error - this browser does not permit file uploading of any kind.\"\n },\n\n retry: {\n showAutoRetryNote: true,\n autoRetryNote: \"Retrying {retryNum}/{maxAuto}...\"\n },\n\n deleteFile: {\n forceConfirm: false,\n confirmMessage: \"Are you sure you want to delete {filename}?\",\n deletingStatusText: \"Deleting...\",\n deletingFailedText: \"Delete failed\"\n\n },\n\n display: {\n fileSizeOnSubmit: false,\n prependFiles: false\n },\n\n paste: {\n promptForName: false,\n namePromptMessage: \"Please name this image\"\n },\n\n thumbnails: {\n customResizer: null,\n maxCount: 0,\n placeholders: {\n waitUntilResponse: false,\n notAvailablePath: null,\n waitingPath: null\n },\n timeBetweenThumbs: 750\n },\n\n scaling: {\n hideScaled: false\n },\n\n showMessage: function(message) {\n if (self._templating.hasDialog(\"alert\")) {\n return self._templating.showDialog(\"alert\", message);\n }\n else {\n setTimeout(function() {\n window.alert(message);\n }, 0);\n }\n },\n\n showConfirm: function(message) {\n if (self._templating.hasDialog(\"confirm\")) {\n return self._templating.showDialog(\"confirm\", message);\n }\n else {\n return window.confirm(message);\n }\n },\n\n showPrompt: function(message, defaultValue) {\n if (self._templating.hasDialog(\"prompt\")) {\n return self._templating.showDialog(\"prompt\", message, defaultValue);\n }\n else {\n return window.prompt(message, defaultValue);\n }\n }\n }, true);\n\n // Replace any default options with user defined ones\n qq.extend(this._options, o, true);\n\n this._templating = new qq.Templating({\n log: qq.bind(this.log, this),\n templateIdOrEl: this._options.template,\n containerEl: this._options.element,\n fileContainerEl: this._options.listElement,\n button: this._options.button,\n imageGenerator: this._imageGenerator,\n classes: {\n hide: this._options.classes.hide,\n editable: this._options.classes.editable\n },\n limits: {\n maxThumbs: this._options.thumbnails.maxCount,\n timeBetweenThumbs: this._options.thumbnails.timeBetweenThumbs\n },\n placeholders: {\n waitUntilUpdate: this._options.thumbnails.placeholders.waitUntilResponse,\n thumbnailNotAvailable: this._options.thumbnails.placeholders.notAvailablePath,\n waitingForThumbnail: this._options.thumbnails.placeholders.waitingPath\n },\n text: this._options.text\n });\n\n if (this._options.workarounds.ios8SafariUploads && qq.ios800() && qq.iosSafari()) {\n this._templating.renderFailure(this._options.messages.unsupportedBrowserIos8Safari);\n }\n else if (!qq.supportedFeatures.uploading || (this._options.cors.expected && !qq.supportedFeatures.uploadCors)) {\n this._templating.renderFailure(this._options.messages.unsupportedBrowser);\n }\n else {\n this._wrapCallbacks();\n\n this._templating.render();\n\n this._classes = this._options.classes;\n\n if (!this._options.button && this._templating.getButton()) {\n this._defaultButtonId = this._createUploadButton({\n element: this._templating.getButton(),\n title: this._options.text.fileInputTitle\n }).getButtonId();\n }\n\n this._setupClickAndEditEventHandlers();\n\n if (qq.DragAndDrop && qq.supportedFeatures.fileDrop) {\n this._dnd = this._setupDragAndDrop();\n }\n\n if (this._options.paste.targetElement && this._options.paste.promptForName) {\n if (qq.PasteSupport) {\n this._setupPastePrompt();\n }\n else {\n this.log(\"Paste support module not found.\", \"error\");\n }\n }\n\n this._totalFilesInBatch = 0;\n this._filesInBatchAddedToUi = 0;\n }\n};\n\n// Inherit the base public & private API methods\nqq.extend(qq.FineUploader.prototype, qq.basePublicApi);\nqq.extend(qq.FineUploader.prototype, qq.basePrivateApi);\n\n// Add the FineUploader/default UI public & private UI methods, which may override some base methods.\nqq.extend(qq.FineUploader.prototype, qq.uiPublicApi);\nqq.extend(qq.FineUploader.prototype, qq.uiPrivateApi);\n","/* globals qq */\n/* jshint -W065 */\n/**\n * Module responsible for rendering all Fine Uploader UI templates. This module also asserts at least\n * a limited amount of control over the template elements after they are added to the DOM.\n * Wherever possible, this module asserts total control over template elements present in the DOM.\n *\n * @param spec Specification object used to control various templating behaviors\n * @constructor\n */\nqq.Templating = function(spec) {\n \"use strict\";\n\n var FILE_ID_ATTR = \"qq-file-id\",\n FILE_CLASS_PREFIX = \"qq-file-id-\",\n THUMBNAIL_MAX_SIZE_ATTR = \"qq-max-size\",\n THUMBNAIL_SERVER_SCALE_ATTR = \"qq-server-scale\",\n // This variable is duplicated in the DnD module since it can function as a standalone as well\n HIDE_DROPZONE_ATTR = \"qq-hide-dropzone\",\n DROPZPONE_TEXT_ATTR = \"qq-drop-area-text\",\n IN_PROGRESS_CLASS = \"qq-in-progress\",\n HIDDEN_FOREVER_CLASS = \"qq-hidden-forever\",\n fileBatch = {\n content: document.createDocumentFragment(),\n map: {}\n },\n isCancelDisabled = false,\n generatedThumbnails = 0,\n thumbnailQueueMonitorRunning = false,\n thumbGenerationQueue = [],\n thumbnailMaxSize = -1,\n options = {\n log: null,\n limits: {\n maxThumbs: 0,\n timeBetweenThumbs: 750\n },\n templateIdOrEl: \"qq-template\",\n containerEl: null,\n fileContainerEl: null,\n button: null,\n imageGenerator: null,\n classes: {\n hide: \"qq-hide\",\n editable: \"qq-editable\"\n },\n placeholders: {\n waitUntilUpdate: false,\n thumbnailNotAvailable: null,\n waitingForThumbnail: null\n },\n text: {\n paused: \"Paused\"\n }\n },\n selectorClasses = {\n button: \"qq-upload-button-selector\",\n alertDialog: \"qq-alert-dialog-selector\",\n dialogCancelButton: \"qq-cancel-button-selector\",\n confirmDialog: \"qq-confirm-dialog-selector\",\n dialogMessage: \"qq-dialog-message-selector\",\n dialogOkButton: \"qq-ok-button-selector\",\n promptDialog: \"qq-prompt-dialog-selector\",\n uploader: \"qq-uploader-selector\",\n drop: \"qq-upload-drop-area-selector\",\n list: \"qq-upload-list-selector\",\n progressBarContainer: \"qq-progress-bar-container-selector\",\n progressBar: \"qq-progress-bar-selector\",\n totalProgressBarContainer: \"qq-total-progress-bar-container-selector\",\n totalProgressBar: \"qq-total-progress-bar-selector\",\n file: \"qq-upload-file-selector\",\n spinner: \"qq-upload-spinner-selector\",\n size: \"qq-upload-size-selector\",\n cancel: \"qq-upload-cancel-selector\",\n pause: \"qq-upload-pause-selector\",\n continueButton: \"qq-upload-continue-selector\",\n deleteButton: \"qq-upload-delete-selector\",\n retry: \"qq-upload-retry-selector\",\n statusText: \"qq-upload-status-text-selector\",\n editFilenameInput: \"qq-edit-filename-selector\",\n editNameIcon: \"qq-edit-filename-icon-selector\",\n dropText: \"qq-upload-drop-area-text-selector\",\n dropProcessing: \"qq-drop-processing-selector\",\n dropProcessingSpinner: \"qq-drop-processing-spinner-selector\",\n thumbnail: \"qq-thumbnail-selector\"\n },\n previewGeneration = {},\n cachedThumbnailNotAvailableImg = new qq.Promise(),\n cachedWaitingForThumbnailImg = new qq.Promise(),\n log,\n isEditElementsExist,\n isRetryElementExist,\n templateHtml,\n container,\n fileList,\n showThumbnails,\n serverScale,\n\n // During initialization of the templating module we should cache any\n // placeholder images so we can quickly swap them into the file list on demand.\n // Any placeholder images that cannot be loaded/found are simply ignored.\n cacheThumbnailPlaceholders = function() {\n var notAvailableUrl = options.placeholders.thumbnailNotAvailable,\n waitingUrl = options.placeholders.waitingForThumbnail,\n spec = {\n maxSize: thumbnailMaxSize,\n scale: serverScale\n };\n\n if (showThumbnails) {\n if (notAvailableUrl) {\n options.imageGenerator.generate(notAvailableUrl, new Image(), spec).then(\n function(updatedImg) {\n cachedThumbnailNotAvailableImg.success(updatedImg);\n },\n function() {\n cachedThumbnailNotAvailableImg.failure();\n log(\"Problem loading 'not available' placeholder image at \" + notAvailableUrl, \"error\");\n }\n );\n }\n else {\n cachedThumbnailNotAvailableImg.failure();\n }\n\n if (waitingUrl) {\n options.imageGenerator.generate(waitingUrl, new Image(), spec).then(\n function(updatedImg) {\n cachedWaitingForThumbnailImg.success(updatedImg);\n },\n function() {\n cachedWaitingForThumbnailImg.failure();\n log(\"Problem loading 'waiting for thumbnail' placeholder image at \" + waitingUrl, \"error\");\n }\n );\n }\n else {\n cachedWaitingForThumbnailImg.failure();\n }\n }\n },\n\n // Displays a \"waiting for thumbnail\" type placeholder image\n // iff we were able to load it during initialization of the templating module.\n displayWaitingImg = function(thumbnail) {\n var waitingImgPlacement = new qq.Promise();\n\n cachedWaitingForThumbnailImg.then(function(img) {\n maybeScalePlaceholderViaCss(img, thumbnail);\n /* jshint eqnull:true */\n if (!thumbnail.src) {\n thumbnail.src = img.src;\n thumbnail.onload = function() {\n thumbnail.onload = null;\n show(thumbnail);\n waitingImgPlacement.success();\n };\n }\n else {\n waitingImgPlacement.success();\n }\n }, function() {\n // In some browsers (such as IE9 and older) an img w/out a src attribute\n // are displayed as \"broken\" images, so we should just hide the img tag\n // if we aren't going to display the \"waiting\" placeholder.\n hide(thumbnail);\n waitingImgPlacement.success();\n });\n\n return waitingImgPlacement;\n },\n\n generateNewPreview = function(id, blob, spec) {\n var thumbnail = getThumbnail(id);\n\n log(\"Generating new thumbnail for \" + id);\n blob.qqThumbnailId = id;\n\n return options.imageGenerator.generate(blob, thumbnail, spec).then(\n function() {\n generatedThumbnails++;\n show(thumbnail);\n previewGeneration[id].success();\n },\n function() {\n previewGeneration[id].failure();\n\n // Display the \"not available\" placeholder img only if we are\n // not expecting a thumbnail at a later point, such as in a server response.\n if (!options.placeholders.waitUntilUpdate) {\n maybeSetDisplayNotAvailableImg(id, thumbnail);\n }\n });\n },\n\n generateNextQueuedPreview = function() {\n if (thumbGenerationQueue.length) {\n thumbnailQueueMonitorRunning = true;\n\n var queuedThumbRequest = thumbGenerationQueue.shift();\n\n if (queuedThumbRequest.update) {\n processUpdateQueuedPreviewRequest(queuedThumbRequest);\n }\n else {\n processNewQueuedPreviewRequest(queuedThumbRequest);\n }\n }\n else {\n thumbnailQueueMonitorRunning = false;\n }\n },\n\n getCancel = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.cancel);\n },\n\n getContinue = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.continueButton);\n },\n\n getDialog = function(type) {\n return getTemplateEl(container, selectorClasses[type + \"Dialog\"]);\n },\n\n getDelete = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.deleteButton);\n },\n\n getDropProcessing = function() {\n return getTemplateEl(container, selectorClasses.dropProcessing);\n },\n\n getEditIcon = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.editNameIcon);\n },\n\n getFile = function(id) {\n return fileBatch.map[id] || qq(fileList).getFirstByClass(FILE_CLASS_PREFIX + id);\n },\n\n getFilename = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.file);\n },\n\n getPause = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.pause);\n },\n\n getProgress = function(id) {\n /* jshint eqnull:true */\n // Total progress bar\n if (id == null) {\n return getTemplateEl(container, selectorClasses.totalProgressBarContainer) ||\n getTemplateEl(container, selectorClasses.totalProgressBar);\n }\n\n // Per-file progress bar\n return getTemplateEl(getFile(id), selectorClasses.progressBarContainer) ||\n getTemplateEl(getFile(id), selectorClasses.progressBar);\n },\n\n getRetry = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.retry);\n },\n\n getSize = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.size);\n },\n\n getSpinner = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.spinner);\n },\n\n getTemplateEl = function(context, cssClass) {\n return context && qq(context).getFirstByClass(cssClass);\n },\n\n getThumbnail = function(id) {\n return showThumbnails && getTemplateEl(getFile(id), selectorClasses.thumbnail);\n },\n\n hide = function(el) {\n el && qq(el).addClass(options.classes.hide);\n },\n\n // Ensures a placeholder image does not exceed any max size specified\n // via `style` attribute properties iff was not used to scale\n // the placeholder AND the target doesn't already have these `style` attribute properties set.\n maybeScalePlaceholderViaCss = function(placeholder, thumbnail) {\n var maxWidth = placeholder.style.maxWidth,\n maxHeight = placeholder.style.maxHeight;\n\n if (maxHeight && maxWidth && !thumbnail.style.maxWidth && !thumbnail.style.maxHeight) {\n qq(thumbnail).css({\n maxWidth: maxWidth,\n maxHeight: maxHeight\n });\n }\n },\n\n // Displays a \"thumbnail not available\" type placeholder image\n // iff we were able to load this placeholder during initialization\n // of the templating module or after preview generation has failed.\n maybeSetDisplayNotAvailableImg = function(id, thumbnail) {\n var previewing = previewGeneration[id] || new qq.Promise().failure(),\n notAvailableImgPlacement = new qq.Promise();\n\n cachedThumbnailNotAvailableImg.then(function(img) {\n previewing.then(\n function() {\n notAvailableImgPlacement.success();\n },\n function() {\n maybeScalePlaceholderViaCss(img, thumbnail);\n\n thumbnail.onload = function() {\n thumbnail.onload = null;\n notAvailableImgPlacement.success();\n };\n\n thumbnail.src = img.src;\n show(thumbnail);\n }\n );\n });\n\n return notAvailableImgPlacement;\n },\n\n /**\n * Grabs the HTML from the script tag holding the template markup. This function will also adjust\n * some internally-tracked state variables based on the contents of the template.\n * The template is filtered so that irrelevant elements (such as the drop zone if DnD is not supported)\n * are omitted from the DOM. Useful errors will be thrown if the template cannot be parsed.\n *\n * @returns {{template: *, fileTemplate: *}} HTML for the top-level file items templates\n */\n parseAndGetTemplate = function() {\n var scriptEl,\n scriptHtml,\n fileListNode,\n tempTemplateEl,\n fileListHtml,\n defaultButton,\n dropArea,\n thumbnail,\n dropProcessing,\n dropTextEl,\n uploaderEl;\n\n log(\"Parsing template\");\n\n /*jshint -W116*/\n if (options.templateIdOrEl == null) {\n throw new Error(\"You MUST specify either a template element or ID!\");\n }\n\n // Grab the contents of the script tag holding the template.\n if (qq.isString(options.templateIdOrEl)) {\n scriptEl = document.getElementById(options.templateIdOrEl);\n\n if (scriptEl === null) {\n throw new Error(qq.format(\"Cannot find template script at ID '{}'!\", options.templateIdOrEl));\n }\n\n scriptHtml = scriptEl.innerHTML;\n }\n else {\n if (options.templateIdOrEl.innerHTML === undefined) {\n throw new Error(\"You have specified an invalid value for the template option! \" +\n \"It must be an ID or an Element.\");\n }\n\n scriptHtml = options.templateIdOrEl.innerHTML;\n }\n\n scriptHtml = qq.trimStr(scriptHtml);\n tempTemplateEl = document.createElement(\"div\");\n tempTemplateEl.appendChild(qq.toElement(scriptHtml));\n uploaderEl = qq(tempTemplateEl).getFirstByClass(selectorClasses.uploader);\n\n // Don't include the default template button in the DOM\n // if an alternate button container has been specified.\n if (options.button) {\n defaultButton = qq(tempTemplateEl).getFirstByClass(selectorClasses.button);\n if (defaultButton) {\n qq(defaultButton).remove();\n }\n }\n\n // Omit the drop processing element from the DOM if DnD is not supported by the UA,\n // or the drag and drop module is not found.\n // NOTE: We are consciously not removing the drop zone if the UA doesn't support DnD\n // to support layouts where the drop zone is also a container for visible elements,\n // such as the file list.\n if (!qq.DragAndDrop || !qq.supportedFeatures.fileDrop) {\n dropProcessing = qq(tempTemplateEl).getFirstByClass(selectorClasses.dropProcessing);\n if (dropProcessing) {\n qq(dropProcessing).remove();\n }\n }\n\n dropArea = qq(tempTemplateEl).getFirstByClass(selectorClasses.drop);\n\n // If DnD is not available then remove\n // it from the DOM as well.\n if (dropArea && !qq.DragAndDrop) {\n log(\"DnD module unavailable.\", \"info\");\n qq(dropArea).remove();\n }\n\n if (!qq.supportedFeatures.fileDrop) {\n // don't display any \"drop files to upload\" background text\n uploaderEl.removeAttribute(DROPZPONE_TEXT_ATTR);\n\n if (dropArea && qq(dropArea).hasAttribute(HIDE_DROPZONE_ATTR)) {\n // If there is a drop area defined in the template, and the current UA doesn't support DnD,\n // and the drop area is marked as \"hide before enter\", ensure it is hidden as the DnD module\n // will not do this (since we will not be loading the DnD module)\n qq(dropArea).css({\n display: \"none\"\n });\n }\n }\n else if (qq(uploaderEl).hasAttribute(DROPZPONE_TEXT_ATTR) && dropArea) {\n dropTextEl = qq(dropArea).getFirstByClass(selectorClasses.dropText);\n dropTextEl && qq(dropTextEl).remove();\n }\n\n // Ensure the `showThumbnails` flag is only set if the thumbnail element\n // is present in the template AND the current UA is capable of generating client-side previews.\n thumbnail = qq(tempTemplateEl).getFirstByClass(selectorClasses.thumbnail);\n if (!showThumbnails) {\n thumbnail && qq(thumbnail).remove();\n }\n else if (thumbnail) {\n thumbnailMaxSize = parseInt(thumbnail.getAttribute(THUMBNAIL_MAX_SIZE_ATTR));\n // Only enforce max size if the attr value is non-zero\n thumbnailMaxSize = thumbnailMaxSize > 0 ? thumbnailMaxSize : null;\n\n serverScale = qq(thumbnail).hasAttribute(THUMBNAIL_SERVER_SCALE_ATTR);\n }\n showThumbnails = showThumbnails && thumbnail;\n\n isEditElementsExist = qq(tempTemplateEl).getByClass(selectorClasses.editFilenameInput).length > 0;\n isRetryElementExist = qq(tempTemplateEl).getByClass(selectorClasses.retry).length > 0;\n\n fileListNode = qq(tempTemplateEl).getFirstByClass(selectorClasses.list);\n /*jshint -W116*/\n if (fileListNode == null) {\n throw new Error(\"Could not find the file list container in the template!\");\n }\n\n fileListHtml = fileListNode.innerHTML;\n fileListNode.innerHTML = \"\";\n\n // We must call `createElement` in IE8 in order to target and hide any via CSS\n if (tempTemplateEl.getElementsByTagName(\"DIALOG\").length) {\n document.createElement(\"dialog\");\n }\n\n log(\"Template parsing complete\");\n\n return {\n template: qq.trimStr(tempTemplateEl.innerHTML),\n fileTemplate: qq.trimStr(fileListHtml)\n };\n },\n\n prependFile = function(el, index, fileList) {\n var parentEl = fileList,\n beforeEl = parentEl.firstChild;\n\n if (index > 0) {\n beforeEl = qq(parentEl).children()[index].nextSibling;\n\n }\n\n parentEl.insertBefore(el, beforeEl);\n },\n\n processNewQueuedPreviewRequest = function(queuedThumbRequest) {\n var id = queuedThumbRequest.id,\n optFileOrBlob = queuedThumbRequest.optFileOrBlob,\n relatedThumbnailId = optFileOrBlob && optFileOrBlob.qqThumbnailId,\n thumbnail = getThumbnail(id),\n spec = {\n customResizeFunction: queuedThumbRequest.customResizeFunction,\n maxSize: thumbnailMaxSize,\n orient: true,\n scale: true\n };\n\n if (qq.supportedFeatures.imagePreviews) {\n if (thumbnail) {\n if (options.limits.maxThumbs && options.limits.maxThumbs <= generatedThumbnails) {\n maybeSetDisplayNotAvailableImg(id, thumbnail);\n generateNextQueuedPreview();\n }\n else {\n displayWaitingImg(thumbnail).done(function() {\n previewGeneration[id] = new qq.Promise();\n\n previewGeneration[id].done(function() {\n setTimeout(generateNextQueuedPreview, options.limits.timeBetweenThumbs);\n });\n\n /* jshint eqnull: true */\n // If we've already generated an for this file, use the one that exists,\n // don't waste resources generating a new one.\n if (relatedThumbnailId != null) {\n useCachedPreview(id, relatedThumbnailId);\n }\n else {\n generateNewPreview(id, optFileOrBlob, spec);\n }\n });\n }\n }\n // File element in template may have been removed, so move on to next item in queue\n else {\n generateNextQueuedPreview();\n }\n }\n else if (thumbnail) {\n displayWaitingImg(thumbnail);\n generateNextQueuedPreview();\n }\n },\n\n processUpdateQueuedPreviewRequest = function(queuedThumbRequest) {\n var id = queuedThumbRequest.id,\n thumbnailUrl = queuedThumbRequest.thumbnailUrl,\n showWaitingImg = queuedThumbRequest.showWaitingImg,\n thumbnail = getThumbnail(id),\n spec = {\n customResizeFunction: queuedThumbRequest.customResizeFunction,\n scale: serverScale,\n maxSize: thumbnailMaxSize\n };\n\n if (thumbnail) {\n if (thumbnailUrl) {\n if (options.limits.maxThumbs && options.limits.maxThumbs <= generatedThumbnails) {\n maybeSetDisplayNotAvailableImg(id, thumbnail);\n generateNextQueuedPreview();\n }\n else {\n if (showWaitingImg) {\n displayWaitingImg(thumbnail);\n }\n\n return options.imageGenerator.generate(thumbnailUrl, thumbnail, spec).then(\n function() {\n show(thumbnail);\n generatedThumbnails++;\n setTimeout(generateNextQueuedPreview, options.limits.timeBetweenThumbs);\n },\n\n function() {\n maybeSetDisplayNotAvailableImg(id, thumbnail);\n setTimeout(generateNextQueuedPreview, options.limits.timeBetweenThumbs);\n }\n );\n }\n }\n else {\n maybeSetDisplayNotAvailableImg(id, thumbnail);\n generateNextQueuedPreview();\n }\n }\n },\n\n setProgressBarWidth = function(id, percent) {\n var bar = getProgress(id),\n /* jshint eqnull:true */\n progressBarSelector = id == null ? selectorClasses.totalProgressBar : selectorClasses.progressBar;\n\n if (bar && !qq(bar).hasClass(progressBarSelector)) {\n bar = qq(bar).getFirstByClass(progressBarSelector);\n }\n\n if (bar) {\n qq(bar).css({width: percent + \"%\"});\n bar.setAttribute(\"aria-valuenow\", percent);\n }\n },\n\n show = function(el) {\n el && qq(el).removeClass(options.classes.hide);\n },\n\n useCachedPreview = function(targetThumbnailId, cachedThumbnailId) {\n var targetThumbnail = getThumbnail(targetThumbnailId),\n cachedThumbnail = getThumbnail(cachedThumbnailId);\n\n log(qq.format(\"ID {} is the same file as ID {}. Will use generated thumbnail from ID {} instead.\", targetThumbnailId, cachedThumbnailId, cachedThumbnailId));\n\n // Generation of the related thumbnail may still be in progress, so, wait until it is done.\n previewGeneration[cachedThumbnailId].then(function() {\n generatedThumbnails++;\n previewGeneration[targetThumbnailId].success();\n log(qq.format(\"Now using previously generated thumbnail created for ID {} on ID {}.\", cachedThumbnailId, targetThumbnailId));\n targetThumbnail.src = cachedThumbnail.src;\n show(targetThumbnail);\n },\n function() {\n previewGeneration[targetThumbnailId].failure();\n if (!options.placeholders.waitUntilUpdate) {\n maybeSetDisplayNotAvailableImg(targetThumbnailId, targetThumbnail);\n }\n });\n };\n\n qq.extend(options, spec);\n log = options.log;\n\n // No need to worry about conserving CPU or memory on older browsers,\n // since there is no ability to preview, and thumbnail display is primitive and quick.\n if (!qq.supportedFeatures.imagePreviews) {\n options.limits.timeBetweenThumbs = 0;\n options.limits.maxThumbs = 0;\n }\n\n container = options.containerEl;\n showThumbnails = options.imageGenerator !== undefined;\n templateHtml = parseAndGetTemplate();\n\n cacheThumbnailPlaceholders();\n\n qq.extend(this, {\n render: function() {\n log(\"Rendering template in DOM.\");\n\n generatedThumbnails = 0;\n\n container.innerHTML = templateHtml.template;\n hide(getDropProcessing());\n this.hideTotalProgress();\n fileList = options.fileContainerEl || getTemplateEl(container, selectorClasses.list);\n\n log(\"Template rendering complete\");\n },\n\n renderFailure: function(message) {\n var cantRenderEl = qq.toElement(message);\n container.innerHTML = \"\";\n container.appendChild(cantRenderEl);\n },\n\n reset: function() {\n this.render();\n },\n\n clearFiles: function() {\n fileList.innerHTML = \"\";\n },\n\n disableCancel: function() {\n isCancelDisabled = true;\n },\n\n addFile: function(id, name, prependInfo, hideForever, batch) {\n var fileEl = qq.toElement(templateHtml.fileTemplate),\n fileNameEl = getTemplateEl(fileEl, selectorClasses.file),\n uploaderEl = getTemplateEl(container, selectorClasses.uploader),\n fileContainer = batch ? fileBatch.content : fileList,\n thumb;\n\n if (batch) {\n fileBatch.map[id] = fileEl;\n }\n\n qq(fileEl).addClass(FILE_CLASS_PREFIX + id);\n uploaderEl.removeAttribute(DROPZPONE_TEXT_ATTR);\n\n if (fileNameEl) {\n qq(fileNameEl).setText(name);\n fileNameEl.setAttribute(\"title\", name);\n }\n\n fileEl.setAttribute(FILE_ID_ATTR, id);\n\n if (prependInfo) {\n prependFile(fileEl, prependInfo.index, fileContainer);\n }\n else {\n fileContainer.appendChild(fileEl);\n }\n\n if (hideForever) {\n fileEl.style.display = \"none\";\n qq(fileEl).addClass(HIDDEN_FOREVER_CLASS);\n }\n else {\n hide(getProgress(id));\n hide(getSize(id));\n hide(getDelete(id));\n hide(getRetry(id));\n hide(getPause(id));\n hide(getContinue(id));\n\n if (isCancelDisabled) {\n this.hideCancel(id);\n }\n\n thumb = getThumbnail(id);\n if (thumb && !thumb.src) {\n cachedWaitingForThumbnailImg.then(function(waitingImg) {\n thumb.src = waitingImg.src;\n if (waitingImg.style.maxHeight && waitingImg.style.maxWidth) {\n qq(thumb).css({\n maxHeight: waitingImg.style.maxHeight,\n maxWidth: waitingImg.style.maxWidth\n });\n }\n\n show(thumb);\n });\n }\n }\n },\n\n addFileToCache: function(id, name, prependInfo, hideForever) {\n this.addFile(id, name, prependInfo, hideForever, true);\n },\n\n addCacheToDom: function() {\n fileList.appendChild(fileBatch.content);\n fileBatch.content = document.createDocumentFragment();\n fileBatch.map = {};\n },\n\n removeFile: function(id) {\n qq(getFile(id)).remove();\n },\n\n getFileId: function(el) {\n var currentNode = el;\n\n if (currentNode) {\n /*jshint -W116*/\n while (currentNode.getAttribute(FILE_ID_ATTR) == null) {\n currentNode = currentNode.parentNode;\n }\n\n return parseInt(currentNode.getAttribute(FILE_ID_ATTR));\n }\n },\n\n getFileList: function() {\n return fileList;\n },\n\n markFilenameEditable: function(id) {\n var filename = getFilename(id);\n\n filename && qq(filename).addClass(options.classes.editable);\n },\n\n updateFilename: function(id, name) {\n var filenameEl = getFilename(id);\n\n if (filenameEl) {\n qq(filenameEl).setText(name);\n filenameEl.setAttribute(\"title\", name);\n }\n },\n\n hideFilename: function(id) {\n hide(getFilename(id));\n },\n\n showFilename: function(id) {\n show(getFilename(id));\n },\n\n isFileName: function(el) {\n return qq(el).hasClass(selectorClasses.file);\n },\n\n getButton: function() {\n return options.button || getTemplateEl(container, selectorClasses.button);\n },\n\n hideDropProcessing: function() {\n hide(getDropProcessing());\n },\n\n showDropProcessing: function() {\n show(getDropProcessing());\n },\n\n getDropZone: function() {\n return getTemplateEl(container, selectorClasses.drop);\n },\n\n isEditFilenamePossible: function() {\n return isEditElementsExist;\n },\n\n hideRetry: function(id) {\n hide(getRetry(id));\n },\n\n isRetryPossible: function() {\n return isRetryElementExist;\n },\n\n showRetry: function(id) {\n show(getRetry(id));\n },\n\n getFileContainer: function(id) {\n return getFile(id);\n },\n\n showEditIcon: function(id) {\n var icon = getEditIcon(id);\n\n icon && qq(icon).addClass(options.classes.editable);\n },\n\n isHiddenForever: function(id) {\n return qq(getFile(id)).hasClass(HIDDEN_FOREVER_CLASS);\n },\n\n hideEditIcon: function(id) {\n var icon = getEditIcon(id);\n\n icon && qq(icon).removeClass(options.classes.editable);\n },\n\n isEditIcon: function(el) {\n return qq(el).hasClass(selectorClasses.editNameIcon, true);\n },\n\n getEditInput: function(id) {\n return getTemplateEl(getFile(id), selectorClasses.editFilenameInput);\n },\n\n isEditInput: function(el) {\n return qq(el).hasClass(selectorClasses.editFilenameInput, true);\n },\n\n updateProgress: function(id, loaded, total) {\n var bar = getProgress(id),\n percent;\n\n if (bar && total > 0) {\n percent = Math.round(loaded / total * 100);\n\n if (percent === 100) {\n hide(bar);\n }\n else {\n show(bar);\n }\n\n setProgressBarWidth(id, percent);\n }\n },\n\n updateTotalProgress: function(loaded, total) {\n this.updateProgress(null, loaded, total);\n },\n\n hideProgress: function(id) {\n var bar = getProgress(id);\n\n bar && hide(bar);\n },\n\n hideTotalProgress: function() {\n this.hideProgress();\n },\n\n resetProgress: function(id) {\n setProgressBarWidth(id, 0);\n this.hideTotalProgress(id);\n },\n\n resetTotalProgress: function() {\n this.resetProgress();\n },\n\n showCancel: function(id) {\n if (!isCancelDisabled) {\n var cancel = getCancel(id);\n\n cancel && qq(cancel).removeClass(options.classes.hide);\n }\n },\n\n hideCancel: function(id) {\n hide(getCancel(id));\n },\n\n isCancel: function(el) {\n return qq(el).hasClass(selectorClasses.cancel, true);\n },\n\n allowPause: function(id) {\n show(getPause(id));\n hide(getContinue(id));\n },\n\n uploadPaused: function(id) {\n this.setStatusText(id, options.text.paused);\n this.allowContinueButton(id);\n hide(getSpinner(id));\n },\n\n hidePause: function(id) {\n hide(getPause(id));\n },\n\n isPause: function(el) {\n return qq(el).hasClass(selectorClasses.pause, true);\n },\n\n isContinueButton: function(el) {\n return qq(el).hasClass(selectorClasses.continueButton, true);\n },\n\n allowContinueButton: function(id) {\n show(getContinue(id));\n hide(getPause(id));\n },\n\n uploadContinued: function(id) {\n this.setStatusText(id, \"\");\n this.allowPause(id);\n show(getSpinner(id));\n },\n\n showDeleteButton: function(id) {\n show(getDelete(id));\n },\n\n hideDeleteButton: function(id) {\n hide(getDelete(id));\n },\n\n isDeleteButton: function(el) {\n return qq(el).hasClass(selectorClasses.deleteButton, true);\n },\n\n isRetry: function(el) {\n return qq(el).hasClass(selectorClasses.retry, true);\n },\n\n updateSize: function(id, text) {\n var size = getSize(id);\n\n if (size) {\n show(size);\n qq(size).setText(text);\n }\n },\n\n setStatusText: function(id, text) {\n var textEl = getTemplateEl(getFile(id), selectorClasses.statusText);\n\n if (textEl) {\n /*jshint -W116*/\n if (text == null) {\n qq(textEl).clearText();\n }\n else {\n qq(textEl).setText(text);\n }\n }\n },\n\n hideSpinner: function(id) {\n qq(getFile(id)).removeClass(IN_PROGRESS_CLASS);\n hide(getSpinner(id));\n },\n\n showSpinner: function(id) {\n qq(getFile(id)).addClass(IN_PROGRESS_CLASS);\n show(getSpinner(id));\n },\n\n generatePreview: function(id, optFileOrBlob, customResizeFunction) {\n if (!this.isHiddenForever(id)) {\n thumbGenerationQueue.push({id: id, customResizeFunction: customResizeFunction, optFileOrBlob: optFileOrBlob});\n !thumbnailQueueMonitorRunning && generateNextQueuedPreview();\n }\n },\n\n updateThumbnail: function(id, thumbnailUrl, showWaitingImg, customResizeFunction) {\n if (!this.isHiddenForever(id)) {\n thumbGenerationQueue.push({customResizeFunction: customResizeFunction, update: true, id: id, thumbnailUrl: thumbnailUrl, showWaitingImg: showWaitingImg});\n !thumbnailQueueMonitorRunning && generateNextQueuedPreview();\n }\n },\n\n hasDialog: function(type) {\n return qq.supportedFeatures.dialogElement && !!getDialog(type);\n },\n\n showDialog: function(type, message, defaultValue) {\n var dialog = getDialog(type),\n messageEl = getTemplateEl(dialog, selectorClasses.dialogMessage),\n inputEl = dialog.getElementsByTagName(\"INPUT\")[0],\n cancelBtn = getTemplateEl(dialog, selectorClasses.dialogCancelButton),\n okBtn = getTemplateEl(dialog, selectorClasses.dialogOkButton),\n promise = new qq.Promise(),\n\n closeHandler = function() {\n cancelBtn.removeEventListener(\"click\", cancelClickHandler);\n okBtn && okBtn.removeEventListener(\"click\", okClickHandler);\n promise.failure();\n },\n\n cancelClickHandler = function() {\n cancelBtn.removeEventListener(\"click\", cancelClickHandler);\n dialog.close();\n },\n\n okClickHandler = function() {\n dialog.removeEventListener(\"close\", closeHandler);\n okBtn.removeEventListener(\"click\", okClickHandler);\n dialog.close();\n\n promise.success(inputEl && inputEl.value);\n };\n\n dialog.addEventListener(\"close\", closeHandler);\n cancelBtn.addEventListener(\"click\", cancelClickHandler);\n okBtn && okBtn.addEventListener(\"click\", okClickHandler);\n\n if (inputEl) {\n inputEl.value = defaultValue;\n }\n messageEl.textContent = message;\n\n dialog.showModal();\n\n return promise;\n }\n });\n};\n","/*globals qq */\n// Base handler for UI (FineUploader mode) events.\n// Some more specific handlers inherit from this one.\nqq.UiEventHandler = function(s, protectedApi) {\n \"use strict\";\n\n var disposer = new qq.DisposeSupport(),\n spec = {\n eventType: \"click\",\n attachTo: null,\n onHandled: function(target, event) {}\n };\n\n // This makes up the \"public\" API methods that will be accessible\n // to instances constructing a base or child handler\n qq.extend(this, {\n addHandler: function(element) {\n addHandler(element);\n },\n\n dispose: function() {\n disposer.dispose();\n }\n });\n\n function addHandler(element) {\n disposer.attach(element, spec.eventType, function(event) {\n // Only in IE: the `event` is a property of the `window`.\n event = event || window.event;\n\n // On older browsers, we must check the `srcElement` instead of the `target`.\n var target = event.target || event.srcElement;\n\n spec.onHandled(target, event);\n });\n }\n\n // These make up the \"protected\" API methods that children of this base handler will utilize.\n qq.extend(protectedApi, {\n getFileIdFromItem: function(item) {\n return item.qqFileId;\n },\n\n getDisposeSupport: function() {\n return disposer;\n }\n });\n\n qq.extend(spec, s);\n\n if (spec.attachTo) {\n addHandler(spec.attachTo);\n }\n};\n","/* global qq */\nqq.FileButtonsClickHandler = function(s) {\n \"use strict\";\n\n var inheritedInternalApi = {},\n spec = {\n templating: null,\n log: function(message, lvl) {},\n onDeleteFile: function(fileId) {},\n onCancel: function(fileId) {},\n onRetry: function(fileId) {},\n onPause: function(fileId) {},\n onContinue: function(fileId) {},\n onGetName: function(fileId) {}\n },\n buttonHandlers = {\n cancel: function(id) { spec.onCancel(id); },\n retry: function(id) { spec.onRetry(id); },\n deleteButton: function(id) { spec.onDeleteFile(id); },\n pause: function(id) { spec.onPause(id); },\n continueButton: function(id) { spec.onContinue(id); }\n };\n\n function examineEvent(target, event) {\n qq.each(buttonHandlers, function(buttonType, handler) {\n var firstLetterCapButtonType = buttonType.charAt(0).toUpperCase() + buttonType.slice(1),\n fileId;\n\n if (spec.templating[\"is\" + firstLetterCapButtonType](target)) {\n fileId = spec.templating.getFileId(target);\n qq.preventDefault(event);\n spec.log(qq.format(\"Detected valid file button click event on file '{}', ID: {}.\", spec.onGetName(fileId), fileId));\n handler(fileId);\n return false;\n }\n });\n }\n\n qq.extend(spec, s);\n\n spec.eventType = \"click\";\n spec.onHandled = examineEvent;\n spec.attachTo = spec.templating.getFileList();\n\n qq.extend(this, new qq.UiEventHandler(spec, inheritedInternalApi));\n};\n","/*globals qq */\n// Child of FilenameEditHandler. Used to detect click events on filename display elements.\nqq.FilenameClickHandler = function(s) {\n \"use strict\";\n\n var inheritedInternalApi = {},\n spec = {\n templating: null,\n log: function(message, lvl) {},\n classes: {\n file: \"qq-upload-file\",\n editNameIcon: \"qq-edit-filename-icon\"\n },\n onGetUploadStatus: function(fileId) {},\n onGetName: function(fileId) {}\n };\n\n qq.extend(spec, s);\n\n // This will be called by the parent handler when a `click` event is received on the list element.\n function examineEvent(target, event) {\n if (spec.templating.isFileName(target) || spec.templating.isEditIcon(target)) {\n var fileId = spec.templating.getFileId(target),\n status = spec.onGetUploadStatus(fileId);\n\n // We only allow users to change filenames of files that have been submitted but not yet uploaded.\n if (status === qq.status.SUBMITTED) {\n spec.log(qq.format(\"Detected valid filename click event on file '{}', ID: {}.\", spec.onGetName(fileId), fileId));\n qq.preventDefault(event);\n\n inheritedInternalApi.handleFilenameEdit(fileId, target, true);\n }\n }\n }\n\n spec.eventType = \"click\";\n spec.onHandled = examineEvent;\n\n qq.extend(this, new qq.FilenameEditHandler(spec, inheritedInternalApi));\n};\n","/*globals qq */\n// Child of FilenameEditHandler. Used to detect focusin events on file edit input elements.\nqq.FilenameInputFocusInHandler = function(s, inheritedInternalApi) {\n \"use strict\";\n\n var spec = {\n templating: null,\n onGetUploadStatus: function(fileId) {},\n log: function(message, lvl) {}\n };\n\n if (!inheritedInternalApi) {\n inheritedInternalApi = {};\n }\n\n // This will be called by the parent handler when a `focusin` event is received on the list element.\n function handleInputFocus(target, event) {\n if (spec.templating.isEditInput(target)) {\n var fileId = spec.templating.getFileId(target),\n status = spec.onGetUploadStatus(fileId);\n\n if (status === qq.status.SUBMITTED) {\n spec.log(qq.format(\"Detected valid filename input focus event on file '{}', ID: {}.\", spec.onGetName(fileId), fileId));\n inheritedInternalApi.handleFilenameEdit(fileId, target);\n }\n }\n }\n\n spec.eventType = \"focusin\";\n spec.onHandled = handleInputFocus;\n\n qq.extend(spec, s);\n qq.extend(this, new qq.FilenameEditHandler(spec, inheritedInternalApi));\n};\n","/*globals qq */\n/**\n * Child of FilenameInputFocusInHandler. Used to detect focus events on file edit input elements. This child module is only\n * needed for UAs that do not support the focusin event. Currently, only Firefox lacks this event.\n *\n * @param spec Overrides for default specifications\n */\nqq.FilenameInputFocusHandler = function(spec) {\n \"use strict\";\n\n spec.eventType = \"focus\";\n spec.attachTo = null;\n\n qq.extend(this, new qq.FilenameInputFocusInHandler(spec, {}));\n};\n","/*globals qq */\n// Handles edit-related events on a file item (FineUploader mode). This is meant to be a parent handler.\n// Children will delegate to this handler when specific edit-related actions are detected.\nqq.FilenameEditHandler = function(s, inheritedInternalApi) {\n \"use strict\";\n\n var spec = {\n templating: null,\n log: function(message, lvl) {},\n onGetUploadStatus: function(fileId) {},\n onGetName: function(fileId) {},\n onSetName: function(fileId, newName) {},\n onEditingStatusChange: function(fileId, isEditing) {}\n };\n\n function getFilenameSansExtension(fileId) {\n var filenameSansExt = spec.onGetName(fileId),\n extIdx = filenameSansExt.lastIndexOf(\".\");\n\n if (extIdx > 0) {\n filenameSansExt = filenameSansExt.substr(0, extIdx);\n }\n\n return filenameSansExt;\n }\n\n function getOriginalExtension(fileId) {\n var origName = spec.onGetName(fileId);\n return qq.getExtension(origName);\n }\n\n // Callback iff the name has been changed\n function handleNameUpdate(newFilenameInputEl, fileId) {\n var newName = newFilenameInputEl.value,\n origExtension;\n\n if (newName !== undefined && qq.trimStr(newName).length > 0) {\n origExtension = getOriginalExtension(fileId);\n\n if (origExtension !== undefined) {\n newName = newName + \".\" + origExtension;\n }\n\n spec.onSetName(fileId, newName);\n }\n\n spec.onEditingStatusChange(fileId, false);\n }\n\n // The name has been updated if the filename edit input loses focus.\n function registerInputBlurHandler(inputEl, fileId) {\n inheritedInternalApi.getDisposeSupport().attach(inputEl, \"blur\", function() {\n handleNameUpdate(inputEl, fileId);\n });\n }\n\n // The name has been updated if the user presses enter.\n function registerInputEnterKeyHandler(inputEl, fileId) {\n inheritedInternalApi.getDisposeSupport().attach(inputEl, \"keyup\", function(event) {\n\n var code = event.keyCode || event.which;\n\n if (code === 13) {\n handleNameUpdate(inputEl, fileId);\n }\n });\n }\n\n qq.extend(spec, s);\n\n spec.attachTo = spec.templating.getFileList();\n\n qq.extend(this, new qq.UiEventHandler(spec, inheritedInternalApi));\n\n qq.extend(inheritedInternalApi, {\n handleFilenameEdit: function(id, target, focusInput) {\n var newFilenameInputEl = spec.templating.getEditInput(id);\n\n spec.onEditingStatusChange(id, true);\n\n newFilenameInputEl.value = getFilenameSansExtension(id);\n\n if (focusInput) {\n newFilenameInputEl.focus();\n }\n\n registerInputBlurHandler(newFilenameInputEl, id);\n registerInputEnterKeyHandler(newFilenameInputEl, id);\n }\n });\n};\n"]}
\ No newline at end of file
+{"version":3,"sources":["?","../client/js/jquery-plugin.js","../client/js/jquery-dnd.js","../client/js/util.js","../client/js/export.js","../client/js/error/error.js","../client/js/version.js","../client/js/features.js","../client/js/promise.js","../client/js/blob-proxy.js","../client/js/button.js","../client/js/upload-data.js","../client/js/uploader.basic.api.js","../client/js/uploader.basic.js","../client/js/ajax.requester.js","../client/js/upload-handler/upload.handler.js","../client/js/upload-handler/upload.handler.controller.js","../client/js/window.receive.message.js","../client/js/upload-handler/form.upload.handler.js","../client/js/upload-handler/xhr.upload.handler.js","../client/js/deletefile.ajax.requester.js","../client/js/image-support/megapix-image.js","../client/js/image-support/image.js","../client/js/image-support/exif.js","../client/js/identify.js","../client/js/image-support/validation.image.js","../client/js/session.js","../client/js/session.ajax.requester.js","../client/js/image-support/scaler.js","../client/js/third-party/ExifRestorer.js","../client/js/total-progress.js","../client/js/paste.js","../client/js/form-support.js","../client/js/traditional/traditional.form.upload.handler.js","../client/js/traditional/traditional.xhr.upload.handler.js","../client/js/traditional/all-chunks-done.ajax.requester.js","../client/js/dnd.js","../client/js/uploader.api.js","../client/js/uploader.js","../client/js/templating.js","../client/js/ui.handler.events.js","../client/js/ui.handler.click.filebuttons.js","../client/js/ui.handler.click.filename.js","../client/js/ui.handler.focusin.filenameinput.js","../client/js/ui.handler.focus.filenameinput.js","../client/js/ui.handler.edit.filename.js"],"names":["global","$","$el","pluginOptions","init","options","xformedOpts","transformVariables","newUploaderInstance","getNewUploaderInstance","uploader","addCallbacks","params","uploaderType","pluginOption","namespace","charAt","toUpperCase","slice","toLowerCase","qq","FineUploader","dataStore","key","val","data","undefined","instanceToStore","option","optionVal","transformedOpts","callbacks","each","_options","prop","nonJqueryCallback","name","callbackEventTarget","exec","substring","originalArgs","Array","prototype","call","arguments","transformedArgs","nonJqueryCallbackRetVal","jqueryEventCallbackRetVal","idx","arg","push","maybeWrapInJquery","apply","this","triggerHandler","error","log","message","source","dest","xformed","arrayVals","element","inArray","isPlainObject","isArray","arrayVal","arrayObjDest","merge","isValidCommand","command","type","match","delegateCommand","xformedArgs","origArgs","retVal","transformedVal","nodeType","cloneNode","fn","fineUploader","optionsOrCommand","self","selfArgs","retVals","index","el","length","jQuery","rootDataKey","dropZoneElements","dnd","DragAndDrop","func","$callbackEl","args","jqueryHandlerResult","fineUploaderDnd","hide","style","display","attach","addEventListener","attachEvent","detach","removeEventListener","detachEvent","contains","descendant","compareDocumentPosition","insertBefore","elementB","parentNode","remove","removeChild","css","styles","Error","opacity","filter","Math","round","extend","hasClass","considerParent","re","RegExp","test","className","addClass","removeClass","replace","getByClass","first","candidates","result","querySelector","querySelectorAll","getElementsByTagName","getFirstByClass","children","child","firstChild","nextSibling","setText","text","innerText","textContent","clearText","hasAttribute","attrName","attrVal","getAttribute","canvasToBlob","canvas","mime","quality","dataUriToBlob","toDataURL","dataUri","arrayBuffer","byteString","createBlob","BlobBuilder","window","WebKitBlobBuilder","MozBlobBuilder","MSBlobBuilder","blobBuilder","append","getBlob","Blob","intArray","mimeString","split","indexOf","atob","decodeURI","ArrayBuffer","Uint8Array","character","charCodeAt","level","console","isObject","variable","Object","toString","isFunction","value","buffer","constructor","isItemList","maybeItemList","isNodeList","maybeNodeList","item","namedItem","isString","maybeString","trimStr","string","String","trim","format","str","newStr","nextIdxToReplace","strBefore","strAfter","isFile","maybeFile","File","isFileList","maybeFileList","FileList","isFileOrInput","maybeFileOrInput","isInput","maybeInput","notFile","evaluateType","normalizedType","HTMLInputElement","tagName","isBlob","maybeBlob","isXhrUploadSupported","input","document","createElement","multiple","FormData","createXhrInstance","upload","XMLHttpRequest","ActiveXObject","isFolderDropSupported","dataTransfer","items","webkitGetAsEntry","isFileChunkingSupported","androidStock","webkitSlice","mozSlice","sliceBlob","fileOrBlob","start","end","slicer","arrayBufferToHex","bytesAsHex","bytes","byt","byteAsHexStr","readBlobToHex","blob","startOffset","initialBlob","fileReader","FileReader","promise","Promise","onload","success","onerror","failure","readAsArrayBuffer","second","extendNested","override","target","sourceFn","super_","srcPropName","srcPropVal","arr","elt","from","len","hasOwnProperty","getUniqueId","c","r","random","v","ie","navigator","userAgent","ie7","ie8","ie10","ie11","edge","safari","vendor","chrome","opera","firefox","windows","platform","android","ios6","ios","ios7","ios8","ios800","iosChrome","iosSafari","iosSafariWebView","preventDefault","e","returnValue","toElement","div","html","innerHTML","iterableItem","callback","keyOrIndex","Storage","getItem","bind","oldFunc","context","newArgs","concat","obj2url","obj","temp","prefixDone","uristrings","prefix","add","nextObj","i","nextTemp","encodeURIComponent","join","obj2FormData","formData","arrayKeyName","obj2Inputs","form","setAttribute","appendChild","parseJson","json","JSON","parse","eval","getExtension","filename","extIdx","lastIndexOf","substr","getFilename","blobOrFileInput","fileName","DisposeSupport","disposers","dispose","disposer","shift","addDisposer","disposeFunction","define","amd","module","exports","version","supportedFeatures","supportsUploading","supportsUploadingBlobs","supportsFileDrop","supportsAjaxFileUploading","supportsFolderDrop","supportsChunking","supportsResume","supportsUploadViaPaste","supportsUploadCors","supportsDeleteFileXdr","supportsDeleteFileCorsXhr","supportsDeleteFileCors","supportsFolderSelection","supportsImagePreviews","supportsUploadProgress","testSupportsFileInputElement","supported","tempInput","disabled","ex","isChrome14OrHigher","isCrossOriginXhrSupported","xhr","withCredentials","isXdrSupported","XDomainRequest","isCrossOriginAjaxSupported","isFolderSelectionSupported","webkitdirectory","isLocalStorageSupported","localStorage","setItem","isDragAndDropSupported","span","postMessage","ajaxUploading","blobUploading","canDetermineSize","chunking","deleteFileCors","deleteFileCorsXdr","deleteFileCorsXhr","dialogElement","HTMLDialogElement","fileDrop","folderDrop","folderSelection","imagePreviews","imageValidation","itemSizeValidation","pause","progressBar","resume","scaling","tiffPreviews","unlimitedScaledImageSize","uploading","uploadCors","uploadCustomHeaders","uploadNonMultipart","uploadViaPaste","isGenericPromise","maybePromise","then","successArgs","failureArgs","successCallbacks","failureCallbacks","doneCallbacks","state","onSuccess","onFailure","done","BlobProxy","referenceBlob","onCreate","create","UploadButton","o","disposeSupport","acceptFiles","focusClass","folders","hoverClass","ios8BrowserCrashWorkaround","onChange","title","buttonId","createInput","BUTTON_ID_ATTR_NAME","setMultiple","position","right","top","fontFamily","fontSize","margin","padding","cursor","height","overflow","direction","getInput","getButtonId","isMultiple","optInput","removeAttribute","setAcceptFiles","reset","UploadData","uploaderProxy","byUuid","byStatus","byProxyGroupId","byBatchId","getDataByIds","idOrIds","entries","id","getDataByUuids","uuids","uuid","getDataByStatus","status","statusResults","statuses","statusEnum","statusResultIndexes","dataIndex","addFile","spec","SUBMITTING","originalName","size","file","batchId","proxyGroupId","onBeforeStatusChange","onStatusChange","retrieve","optionalFilter","removeFileRef","record","setStatus","newStatus","oldStatus","byStatusOldStatusIndex","splice","uuidChanged","newUuid","oldUuid","updateName","newName","updateSize","newSize","setParentId","targetId","parentId","getIdsInProxyGroup","getIdsInBatch","SUBMITTED","REJECTED","QUEUED","CANCELED","PAUSED","UPLOADING","UPLOAD_FINALIZING","UPLOAD_RETRYING","UPLOAD_SUCCESSFUL","UPLOAD_FAILED","DELETE_FAILED","DELETING","DELETED","basePublicApi","addBlobs","blobDataOrArray","endpoint","addFiles","addInitialFiles","cannedFileList","cannedFile","_addCannedFile","_maybeHandleIos8SafariWorkaround","_storedIds","_currentBatchId","processBlob","_handleNewFile","blobs","defaultName","verifiedFiles","processBlobData","blobData","processCanvas","processCanvasData","canvasData","normalizedQuality","processFileOrInput","fileOrInput","files","normalizeData","fileContainer","_prepareItemsForUpload","cancel","uploadData","_uploadData","getName","_handler","cancelAll","storedIdsCopy","storedFileId","clearStoredFiles","continueUpload","enabled","_uploadFile","deleteFile","_onSubmitDelete","doesExist","fileOrBlobId","isValid","drawThumbnail","fileId","imgOrCanvas","maxSize","fromServer","customResizeFunction","promiseToReturn","fileOrUrl","_imageGenerator","_thumbnailUrls","scale","getFile","container","generate","modifiedContainer","reason","getButton","_getButton","_buttonIdsForFileIds","getEndpoint","_endpointStore","get","uploadDataRecord","getInProgress","getParentId","uploadDataEntry","getUploads","getResumableFilesData","getSize","getNetUploads","_netUploaded","getRemainingAllowedItems","allowedItems","_currentItemLimit","_netUploadedOrQueued","getUuid","isResumable","hasResumeRecord","debug","pauseUpload","expunge","_autoRetries","_retryTimeouts","_preventRetries","_buttons","button","_paramsStore","_pasteHandler","session","refreshOnReset","_refreshSessionData","_succeededSinceLastAllComplete","_failedSinceLastAllComplete","_totalProgress","_customResumeDataStore","retry","_manualRetry","scaleImage","specs","Scaler","setCustomHeaders","headers","_customHeadersStore","set","setCustomResumeData","setDeleteFileCustomHeaders","_deleteFileCustomHeadersStore","setDeleteFileEndpoint","_deleteFileEndpointStore","setDeleteFileParams","_deleteFileParamsStore","setEndpoint","setForm","elementOrId","_updateFormSupportAndParams","setItemLimit","newItemLimit","setName","setParams","setUuid","fileRecord","_onDeleteComplete","errorMessage","uploadStoredFiles","_itemError","_uploadStoredFiles","basePrivateApi","sessionData","deleteFileEndpoint","deleteFileParams","thumbnailUrl","_annotateWithButtonId","associatedInput","qqButtonId","_getButtonId","_batchError","onError","_createDeleteHandler","DeleteFileAjaxRequester","method","maxConnections","uuidParamName","request","uuidName","customHeaders","paramsStore","endpointStore","cors","onDelete","_onDelete","onDeleteComplete","xhrOrXdr","isError","_createPasteHandler","PasteSupport","targetElement","paste","pasteReceived","_handleCheckedCallback","onPasteReceived","_handlePasteSuccess","identifier","_createStore","initialValue","_readOnlyValues_","store","catchall","perIdReadOnlyValues","readOnlyValues","copy","orig","getReadOnlyValues","includeReadOnlyValues","existing","values","addReadOnly","_createUploadDataTracker","_onUploadStatusChange","_maybeAllComplete","setTimeout","_createUploadButton","accept","validation","allowedExtensions","allowMultiple","workarounds","iosEmptyVideos","_isAllowedExtension","classes","buttonFocus","buttonHover","ios8BrowserCrash","inputName","_onInputChange","fileInputTitle","_disposeSupport","_createUploadHandler","additionalOptions","lastOnProgress","preventRetryParam","preventRetryResponseProperty","onProgress","loaded","total","_onProgress","onComplete","_onComplete","onCancel","cancelFinalizationEffort","_onCancel","onUploadPrep","_onUploadPrep","onUpload","_onUpload","onUploadResult","onUploadChunk","chunkData","_onUploadChunk","onUploadChunkResult","partIndex","onUploadChunkSuccess","_onUploadChunkSuccess","onResume","customResumeData","onAutoRetry","responseJSON","_onAutoRetry","onUuidChanged","setSize","_setSize","getDataByUuid","isQueued","isInProgress","getCustomResumeData","_getCustomResumeData","UploadHandlerController","_fileOrBlobRejected","_formatSize","sizeSymbols","max","toFixed","_generateExtraButtonSpecs","_extraButtonSpecs","extraButtons","extraButtonOptionEntry","extraButtonSpec","_initExtraButton","extraButtonsSpec","_defaultButtonId","buttonOrFileInputOrFile","inputs","fileInput","fileBlobOrInput","_getNotFinished","_getValidationBase","_getValidationDescriptor","fileWrapper","_getValidationDescriptors","fileWrappers","fileDescriptors","_handleCameraAccess","camera","acceptIosCamera","optionRoot","details","callbackRetVal","successParam","newFileWrapperList","actualFile","handler","_customNewFileHandler","_handleNewFileGeneric","addFileToHandler","_trackButton","fileList","extSuppliedName","extension","_handleDeleteSuccess","_handleDeleteFailed","_initFormSupportAndParams","_formSupport","FormSupport","attachedToForm","getFormInputsAsObject","autoUpload","newAutoUpload","newEndpoint","_isDeletePossible","expected","allowXdr","allowed","valid","allowedExt","extRegex","code","maybeNameOrNames","messages","names","validationBase","extensionsForMessage","placeholderMatch","replacement","allowedExtension","formatFileName","sizeLimit","minSizeLimit","placeholder","_onBeforeManualRetry","notFinished","_onAllComplete","ios8SafariUploads","alert","unsupportedBrowserIos8Safari","_maybeParseAndSendUploadError","response","errorReason","defaultResponseError","_maybeProcessNextItemAfterOnValidateCallback","validItem","stopOnFirstInvalidFile","validationDescriptor","onValidate","_onValidateCallbackSuccess","_onValidateCallbackFailure","successful","failed","onAllComplete","_shouldAutoRetry","retryWaitPeriod","autoAttemptDelay","_onBeforeAutoRetry","itemLimit","onManualRetry","clearTimeout","storedItemIndex","fileIndex","onIndividualProgress","_onSubmit","_onSubmitCallbackSuccess","_onSubmitted","onSubmitted","_storeForLater","onSuccessCallback","additionalMandatedParams","adjustedOnSuccessCallback","onSubmitDelete","_deleteHandler","sendDelete","_onTotalProgress","onTotalProgress","enableAuto","_onValidateBatchCallbackFailure","_onValidateBatchCallbackSuccess","validationDescriptors","proposedNetFilesUploadedOrQueued","tooManyItemsError","nextIndex","_validateFileOrBlobData","_upload","onValidateBatch","_preventLeaveInProgress","event","onLeave","Session","_session","addFileRecord","refresh","_sessionRequestComplete","onSessionRequestComplete","onNewSize","maxAutoAttempts","formElementOrId","onSubmit","idToUpload","stillSubmitting","validityChecker","allowEmpty","ImageValidation","validate","image","errorCode","_wrapCallbacks","safeCallback","errorMsg","exception","callbackName","callbackFunc","FineUploaderBasic","disableCancelForFormUploads","warnBeforeUnload","filenameParam","forceMultipart","omitDefaultParams","paramsInBody","requireSuccessJson","totalFileSizeName","maxHeight","maxWidth","minHeight","minWidth","maybeXhr","maybeXhrOrXdr","attemptNumber","fileOrBlobData","typeError","sizeError","minSizeError","emptyError","noFilesError","maxHeightImageError","maxWidthImageError","minHeightImageError","minWidthImageError","retryFailTooManyItems","concurrent","mandatory","paramNames","partByteOffset","chunkSize","totalFileSize","totalParts","partSize","jsonPayload","resetOnStatus","recordsExpireIn","resuming","customKeys","fileOrBlobName","sendCredentials","interceptSubmit","customResizer","sendOriginal","orient","defaultType","defaultQuality","failureText","includeExif","sizes","ImageGenerator","_scaler","handleNewFile","TotalProgress","entry","AjaxRequester","shouldParamsBeInQueryString","queue","requestData","acceptHeader","validMethods","contentType","mandatedParams","allowXRequestedWithAndCacheControl","successfulResponseCodes","DELETE","PATCH","POST","PUT","GET","onSend","isSimpleMethod","containsNonSimpleHeaders","containsNonSimple","header","isXdr","getCorsAjaxTransport","ontimeout","onprogress","getXhrOrXdr","suppliedXhr","dequeue","nextId","sendRequest","xdrError","isResponseSuccessful","getParams","onDemandParams","additionalParams","optXhr","payload","url","createUrl","additionalQueryParams","getXdrLoadHandler","getXdrErrorHandler","onreadystatechange","getXhrReadyStateChangeHandler","registerForUploadProgress","open","setHeaders","send","stringify","addToPath","readyState","lengthComputable","onDemandHeaders","additionalHeaders","allHeaders","setRequestHeader","responseCode","prepareToSend","initTransport","path","cacheBuster","withPath","appendToPath","withParams","withQueryParams","_additionalQueryParams_","withHeaders","withPayload","thePayload","withCacheBuster","qqtimestamp","Date","getTime","canceled","UploadHandler","proxy","fileState","fileItem","onCancelRetVal","getThirdPartyFileId","_getFileState","_setThirdPartyFileId","thirdPartyFileId","_wasCanceled","controller","chunkingPossible","concurrentChunkingPossible","preventRetryResponse","chunked","chunkIdx","_getChunkData","attemptingResume","chunkProgress","_getChunkDataForCallback","finalize","finalizeChunks","normaizedResponse","normalizeResponse","_maybeDeletePersistedChunkData","cleanup","normalizedResponse","handleFailure","clearCachedChunk","responseToReport","inProgressIdx","inProgressChunksArray","inProgress","remaining","unshift","ignoreFailure","keys","_getXhrs","ckid","ckXhr","abort","_cancelled","moveInProgressToRemaining","connectionManager","free","hasMoreParts","nextPart","nextIdx","_getTotalChunks","reevaluateChunking","sendNext","inProgressChunks","available","onUploadChunkPromise","requestOverrides","uploadChunkData","overrides","uploadChunk","inProgressChunkIdx","_maybePersistChunkedState","clearXhr","_open","_openChunks","_waiting","openChunkEntriesCount","openChunksCount","openChunkIndexes","dontAllowNext","allowNext","waitingIndex","connectionsIndex","getProxyOrBlob","getWaitingOrConnected","waitingOrConnected","chunks","parseInt","isUsingConnection","pop","openChunksEntry","simple","uploadFile","maybeNewUuid","_clearXhrs","getProxy","initHandler","handlerType","traditional","handlerModuleSubtype","onFinalizing","_removeExpiredChunkingRecords","isDeferredEligibleForUpload","maybeDefer","generatedBlob","updateBlob","maybeSendDeferredFiles","errorResponse","idsInGroup","uploadedThisId","idInGroup","now","originalResponse","_shouldChunkThisFile","blobToUpload","cancelRetVal","isProxied","_getLocalStorageId","isAttemptingResume","WindowReceiveMessage","callbackWrapperDetachers","receiveMessage","onMessageCallbackWrapper","stopReceivingMessages","detacher","FormUploadHandler","formHandlerInstanceId","onloadCallbacks","detachLoadEvents","postMessageCallbackTimers","isCors","corsMessageReceiver","expungeFile","iframe","getElementById","_getIframeName","getFileIdForIframeName","iframeName","initIframeForUpload","body","registerPostMessageCallback","_parseJsonResponse","onloadCallback","_detachLoadEvent","_attachLoadEvent","responseDescriptor","contentDocument","_createIframe","_initFormForUpload","targetName","innerHtmlOrMessage","XhrUploadHandler","getChunkSize","chunkFiles","resumeEnabled","xhrId","ajaxRequester","_getAjaxRequester","blobOrProxy","_initTempState","_maybePrepareForResume","cachedChunks","tempState","xhrs","ajaxRequesters","responseParser","lastChunkIdx","_getXhr","resumableFilesData","_iterateResumeRecords","notResumable","optInProgress","optRemaining","chunkingState","reverse","paused","totalChunks","parts","newBlob","chunkId","_createXhr","optChunkIdx","_registerXhr","chunkIndex","fileSize","startBytes","endBytes","part","count","startByte","endByte","formatVersion","localStorageId","forEach","_getMimeType","_getPersistableData","ceil","_markNotResumable","removeItem","persistedData","lastUpdated","_registerProgressHandler","progressCalculator","totalSuccessfullyLoadedForFile","loadedForRequest","totalForRequest","estActualChunkLoaded","totalLoadedForFile","chunkLoaded","optAjaxRequester","xhrsId","expirationDays","expirationDate","setDate","getDate","requester","getMandatedParams","_method","detectSubsampling","img","iw","naturalWidth","ih","naturalHeight","ctx","width","getContext","drawImage","getImageData","detectVerticalSquash","sy","ey","py","alpha","ratio","renderImageToDataURL","doSquash","renderImageToCanvas","maybeCalculateDownsampledDimensions","maxPixels","origHeight","origWidth","newHeight","sqrt","newWidth","modifiedDimensions","save","resize","renderImageToCanvasWithCustomResizer","imageHeight","imageWidth","orientation","targetHeight","targetWidth","transformCoordinate","d","tmpCanvas","vertSquashRatio","dw","dh","dy","tmpCtx","sx","dx","clearRect","restore","qqImageRendered","resizeInfo","sourceCanvas","sourceCanvasContext","targetCanvas","translate","rotate","PI","MegaPixImage","srcImage","errorCallback","Image","URL","createObjectURL","webkitURL","src","listeners","imageLoadListeners","render","imgWidth","imgHeight","opt","optionsKey","optionsValue","oldTargetSrc","onrender","isImg","isCanvas","isImgCorsSupported","crossOrigin","isCanvasSupported","determineMimeOfFileName","nameWithPath","pathSegments","isCrossOrigin","targetAnchor","targetProtocol","targetHostname","targetPort","href","protocol","port","hostname","location","registerImgLoadListeners","registerCanvasDrawImageListener","registerThumbnailRenderedListener","registered","draw","drawPreview","Identify","megapixErrorHandler","isPreviewable","dummyExif","exif","Exif","mpImg","Orientation","failureMsg","drawOnCanvasOrImgFromUrl","canvasOrImg","tempImg","tempImgRender","rendered","drawOnImgFromUrlWithCssScaling","drawFromUrl","fileBlobOrUrl","_testing","TAG_IDS","TAG_INFO","274","parseLittleEndian","hex","pow","seekToApp1","offset","theOffset","thePromise","segmentLength","getApp1Offset","isLittleEndian","app1Start","getDirEntryCount","littleEndian","getIfd","dirEntries","getDirEntries","ifdHex","getTagValues","TAG_VAL_OFFSET","tagsToFind","vals","idHex","tagsToFindIdx","tagValHex","tagValLength","parser","onParseFailure","app1Offset","dirEntryCount","tagValues","isIdentifiable","magicBytes","questionableBytes","identifiable","magicBytesEntries","magicBytesArrayEntry","previewable","isPreviewableSync","PREVIEWABLE_MIME_TYPES","fileMime","isRecognizedImage","image/jpeg","image/gif","image/png","image/bmp","image/tiff","hasNonZeroLimits","limits","atLeastOne","limit","getWidthHeight","sizeDetermination","getFailingLimit","dimensions","failingLimit","limitName","limitValue","limitMatcher","dimensionPropName","actualValue","validationEffort","isJsonResponseValid","handleFileItems","fileItems","someItemsIgnored","err","refreshEffort","refreshCompleteCallback","requesterOptions","SessionAjaxRequester","queryServer","responseText","includeOriginal","failedToScaleText","_getSortedSizes","getFileRecords","originalFileUuid","originalFileName","originalBlobOrBlobData","records","originalBlob","sizeRecord","outputType","_determineOutputType","requestedType","refType","_getName","_generateScaledImage","failedText","api","scaledIds","originalId","blobSize","scaledId","qqparentuuid","qqparentsize","param","scalingEffort","scalingOptions","scaler","referenceType","scaledVersionProperties","startOfExt","versionType","scaledName","scaledExt","nameAppendage","sort","a","b","sourceFile","imageGenerator","scaledImageDataUri","signalSuccess","_insertExifHeader","scaledImageDataUriWithExif","originalImage","reader","insertionEffort","originalImageDataUri","ExifRestorer","readAsDataURL","_dataUriToBlob","_createBlob","KEY_STR","encode64","output","chr1","chr2","chr3","enc1","enc2","enc3","enc4","isNaN","origFileBase64","resizedFileBase64","expectedBase64Header","rawImage","decode64","segments","slice2Segments","exifManipulation","exifArray","getExifArray","newImageArray","insertExif","aBuffer","seg","x","imageData","buf","separatePoint","mae","ato","array","rawImageArray","head","endPoint","base64test","perFileProgress","totalLoaded","totalSize","lastLoadedSent","lastTotalSent","callbackProxy","noRetryableFiles","retryable","none","failedId","updateTotalProgress","onNew","newLoaded","newTotal","oldLoaded","oldTotal","detachPasteHandler","isImage","registerPasteHandler","clipboardData","getAsFile","unregisterPasteHandler","startUpload","formEl","_form2Obj","determineNewEndpoint","validateForm","nativeSubmit","checkValidity","maybeUploadOnSubmit","submit","determineFormEl","notIrrelevantType","irrelevantTypes","radioOrCheckbox","ignoreValue","checked","selectValue","select","selected","elements","getIframeContentJson","doc","innerHtml","contentWindow","nodeValue","createForm","responseFromMessage","multipart","addChunkingSpecificParams","allChunksDoneRequester","AllChunksDoneAjaxRequester","createReadyStateChangedHandler","onUploadOrChunkComplete","getChunksCompleteParams","isErrorUploadResponse","parseResponse","sendChunksCompleteRequest","complete","setParamsAndGetEntityToSend","entityToSendParams","xhrOverrides","customParams","defaultParams","xhrOverrideParams","setUploadHeaders","headersOptions","headerOverrides","headerName","headerValue","extraHeaders","uploadChunkParams","toSend","promises","endpointHandler","HIDE_ZONES_EVENT_NAME","HIDE_BEFORE_ENTER_ATTR","uploadDropZones","droppedFiles","allowMultipleItems","dropActive","uploadDroppedFiles","uploadDropZone","filesAsArray","dropLog","dropDisabled","processingDroppedFilesComplete","getElement","traverseFileTree","parseEntryPromise","qqPath","extractDirectoryPath","fileError","fullPath","isDirectory","getFilesInDirectory","allEntriesRead","entriesLeft","readFailure","indexOfNameInFullPath","accumEntries","existingPromise","dirReader","createReader","readEntries","readSuccess","newEntries","handleDataTransfer","pendingFolderPromises","handleDataTransferPromise","processingDroppedFiles","dropError","setupDropzone","dropArea","dropZone","UploadDropZone","onEnter","stopPropagation","onLeaveNotDescendants","onDrop","isFileDrag","dragEvent","fileDrag","types","leavingDocumentOut","y","setupDragDrop","dropZones","maybeHideDropZones","HTMLElement","setupExtraDropzone","removeDropzone","dzs","targetEl","errorSpecifics","preventDrop","dropOutsideDisabled","dragoverShouldBeCanceled","disableDropOutside","dropEffect","isValidFileDrag","effectTest","dt","isSafari","effectAllowed","includes","isOrSetDropDisabled","isDisabled","triggerHidezonesEvent","hideZonesEvent","triggerUsingOldApi","createEvent","initEvent","CustomEvent","dispatchEvent","attachEvents","effect","relatedTarget","elementFromPoint","clientX","clientY","uiPublicApi","_parent","_templating","addCacheToDom","clearFiles","addExtraDropzone","_dnd","removeExtraDropzone","getItemByFileId","isHiddenForever","getFileContainer","_setupDragAndDrop","_totalFilesInBatch","_filesInBatchAddedToUi","_setupClickAndEditEventHandlers","formattedFilename","updateFilename","uploadPaused","continued","uploadContinued","getId","fileContainerOrChildEl","getFileId","getDropTarget","qqDropTarget","uiPrivateApi","_removeFileItem","removeFile","_fileButtonsClickHandler","FileButtonsClickHandler","_bindFileButtonsClickEvent","_focusinEventSupported","_isEditFilenameEnabled","_filenameClickHandler","_bindFilenameClickEvent","_filenameInputFocusInHandler","_bindFilenameInputFocusInEvent","_filenameInputFocusHandler","_bindFilenameInputFocusEvent","dragAndDrop","extraDropzones","templating","defaultDropZone","getDropZone","showDropProcessing","hideDropProcessing","errorData","lvl","onDeleteFile","onRetry","onPause","onContinue","onGetName","isEditFilenamePossible","FilenameClickHandler","FilenameInputFocusHandler","_filenameEditHandler","onGetUploadStatus","onSetName","onEditingStatusChange","isEditing","qqInput","getEditInput","qqFileContainer","hideFilename","hideEditIcon","showFilename","showEditIcon","markFilenameEditable","hideRetry","setStatusText","_classes","retrying","hidePause","FilenameInputFocusInHandler","hideSpinner","resetTotalProgress","reportDirectoryPaths","qqpath","_addToList","addHandler","updateProgress","hideCancel","hideProgress","waitingForResponse","_displayFileSize","parentRetVal","completeUpload","_markFileAsSuccessful","fail","showCancel","isRetryPossible","showRetry","_controlFailureTextDisplay","newResult","showDeleteButton","_maybeUpdateThumbnail","showSpinner","allowPause","retryNumForDisplay","maxAuto","retryNote","_showCancelLink","showAutoRetryNote","autoRetryNote","resetProgress","_onSubmitDeleteSuccess","forceConfirm","_showDeleteConfirm","_sendDeleteRequest","deletingFailedText","hideDeleteButton","deletingStatusText","confirmMessage","deleteRequestArgs","showConfirm","canned","prependData","prependIndex","dontDisplay","hideScaled","prependFiles","disableCancel","_handledProxyGroup","_clearList","addFileToCache","updateThumbnail","thumbnails","generatePreview","fileSizeOnSubmit","loadedSize","sizeForDisplay","_formatProgress","uploadedSize","formatProgress","mode","responseProperty","failureReason","failedUploadTextDisplay","failUpload","enableTooltip","_showTooltip","showMessage","_setupPastePrompt","namePromptMessage","defaultVal","showPrompt","fileStatus","placeholders","waitUntilResponse","listElement","template","editable","tooManyFilesError","unsupportedBrowser","promptForName","maxCount","notAvailablePath","waitingPath","timeBetweenThumbs","hasDialog","showDialog","confirm","defaultValue","prompt","Templating","templateIdOrEl","containerEl","fileContainerEl","maxThumbs","waitUntilUpdate","thumbnailNotAvailable","waitingForThumbnail","renderFailure","FILE_ID_ATTR","FILE_CLASS_PREFIX","THUMBNAIL_MAX_SIZE_ATTR","THUMBNAIL_SERVER_SCALE_ATTR","HIDE_DROPZONE_ATTR","DROPZPONE_TEXT_ATTR","IN_PROGRESS_CLASS","HIDDEN_FOREVER_CLASS","fileBatch","content","createDocumentFragment","map","isCancelDisabled","generatedThumbnails","thumbnailQueueMonitorRunning","thumbGenerationQueue","thumbnailMaxSize","selectorClasses","alertDialog","dialogCancelButton","confirmDialog","dialogMessage","dialogOkButton","promptDialog","drop","list","progressBarContainer","totalProgressBarContainer","totalProgressBar","spinner","continueButton","deleteButton","statusText","editFilenameInput","editNameIcon","dropText","dropProcessing","dropProcessingSpinner","thumbnail","previewGeneration","cachedThumbnailNotAvailableImg","cachedWaitingForThumbnailImg","isEditElementsExist","isRetryElementExist","templateDom","showThumbnails","serverScale","cacheThumbnailPlaceholders","notAvailableUrl","waitingUrl","updatedImg","displayWaitingImg","waitingImgPlacement","maybeScalePlaceholderViaCss","show","generateNewPreview","getThumbnail","qqThumbnailId","maybeSetDisplayNotAvailableImg","generateNextQueuedPreview","queuedThumbRequest","update","processUpdateQueuedPreviewRequest","processNewQueuedPreviewRequest","getCancel","getTemplateEl","getContinue","getDialog","getDelete","getDropProcessing","getEditIcon","getPause","getProgress","getRetry","getSpinner","cssClass","previewing","notAvailableImgPlacement","parseAndGetTemplate","scriptEl","scriptHtml","fileListNode","tempTemplateEl","fileListEl","defaultButton","dropTextEl","uploaderEl","fileTemplate","prependFile","parentEl","beforeEl","optFileOrBlob","relatedThumbnailId","useCachedPreview","showWaitingImg","setProgressBarWidth","percent","bar","progressBarSelector","targetThumbnailId","cachedThumbnailId","targetThumbnail","cachedThumbnail","hideTotalProgress","cantRenderEl","prependInfo","hideForever","batch","fileEl","fileNameEl","thumb","waitingImg","currentNode","getFileList","filenameEl","isFileName","icon","isEditIcon","isEditInput","isCancel","allowContinueButton","isPause","isContinueButton","isDeleteButton","isRetry","textEl","dialog","messageEl","inputEl","cancelBtn","okBtn","closeHandler","cancelClickHandler","okClickHandler","close","showModal","UiEventHandler","s","protectedApi","eventType","attachTo","onHandled","srcElement","getFileIdFromItem","qqFileId","getDisposeSupport","inheritedInternalApi","buttonHandlers","examineEvent","buttonType","firstLetterCapButtonType","handleFilenameEdit","FilenameEditHandler","handleInputFocus","getFilenameSansExtension","filenameSansExt","getOriginalExtension","origName","handleNameUpdate","newFilenameInputEl","origExtension","registerInputBlurHandler","registerInputEnterKeyHandler","keyCode","which","focusInput","focus"],"mappings":"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","file":"jquery.fine-uploader.js","sourcesContent":[null,"/*globals jQuery, qq*/\n(function($) {\n \"use strict\";\n var $el,\n pluginOptions = [\"uploaderType\", \"endpointType\"];\n\n function init(options) {\n var xformedOpts = transformVariables(options || {}),\n newUploaderInstance = getNewUploaderInstance(xformedOpts);\n\n uploader(newUploaderInstance);\n addCallbacks(xformedOpts, newUploaderInstance);\n\n return $el;\n }\n\n function getNewUploaderInstance(params) {\n var uploaderType = pluginOption(\"uploaderType\"),\n namespace = pluginOption(\"endpointType\");\n\n // If the integrator has defined a specific type of uploader to load, use that, otherwise assume `qq.FineUploader`\n if (uploaderType) {\n // We can determine the correct constructor function to invoke by combining \"FineUploader\"\n // with the upper camel cased `uploaderType` value.\n uploaderType = uploaderType.charAt(0).toUpperCase() + uploaderType.slice(1).toLowerCase();\n\n if (namespace) {\n return new qq[namespace][\"FineUploader\" + uploaderType](params);\n }\n\n return new qq[\"FineUploader\" + uploaderType](params);\n }\n else {\n if (namespace) {\n return new qq[namespace].FineUploader(params);\n }\n\n return new qq.FineUploader(params);\n }\n }\n\n function dataStore(key, val) {\n var data = $el.data(\"fineuploader\");\n\n if (val) {\n if (data === undefined) {\n data = {};\n }\n data[key] = val;\n $el.data(\"fineuploader\", data);\n }\n else {\n if (data === undefined) {\n return null;\n }\n return data[key];\n }\n }\n\n //the underlying Fine Uploader instance is stored in jQuery's data stored, associated with the element\n // tied to this instance of the plug-in\n function uploader(instanceToStore) {\n return dataStore(\"uploader\", instanceToStore);\n }\n\n function pluginOption(option, optionVal) {\n return dataStore(option, optionVal);\n }\n\n // Implement all callbacks defined in Fine Uploader as functions that trigger appropriately names events and\n // return the result of executing the bound handler back to Fine Uploader\n function addCallbacks(transformedOpts, newUploaderInstance) {\n var callbacks = transformedOpts.callbacks = {};\n\n $.each(newUploaderInstance._options.callbacks, function(prop, nonJqueryCallback) {\n var name, callbackEventTarget;\n\n name = /^on(\\w+)/.exec(prop)[1];\n name = name.substring(0, 1).toLowerCase() + name.substring(1);\n callbackEventTarget = $el;\n\n callbacks[prop] = function() {\n var originalArgs = Array.prototype.slice.call(arguments),\n transformedArgs = [],\n nonJqueryCallbackRetVal, jqueryEventCallbackRetVal;\n\n $.each(originalArgs, function(idx, arg) {\n transformedArgs.push(maybeWrapInJquery(arg));\n });\n\n nonJqueryCallbackRetVal = nonJqueryCallback.apply(this, originalArgs);\n\n try {\n jqueryEventCallbackRetVal = callbackEventTarget.triggerHandler(name, transformedArgs);\n }\n catch (error) {\n qq.log(\"Caught error in Fine Uploader jQuery event handler: \" + error.message, \"error\");\n }\n\n /*jshint -W116*/\n if (nonJqueryCallbackRetVal != null) {\n return nonJqueryCallbackRetVal;\n }\n return jqueryEventCallbackRetVal;\n };\n });\n\n newUploaderInstance._options.callbacks = callbacks;\n }\n\n //transform jQuery objects into HTMLElements, and pass along all other option properties\n function transformVariables(source, dest) {\n var xformed, arrayVals;\n\n if (dest === undefined) {\n if (source.uploaderType !== \"basic\") {\n xformed = { element: $el[0] };\n }\n else {\n xformed = {};\n }\n }\n else {\n xformed = dest;\n }\n\n $.each(source, function(prop, val) {\n if ($.inArray(prop, pluginOptions) >= 0) {\n pluginOption(prop, val);\n }\n else if (val instanceof $) {\n xformed[prop] = val[0];\n }\n else if ($.isPlainObject(val)) {\n xformed[prop] = {};\n transformVariables(val, xformed[prop]);\n }\n else if ($.isArray(val)) {\n arrayVals = [];\n $.each(val, function(idx, arrayVal) {\n var arrayObjDest = {};\n\n if (arrayVal instanceof $) {\n $.merge(arrayVals, arrayVal);\n }\n else if ($.isPlainObject(arrayVal)) {\n transformVariables(arrayVal, arrayObjDest);\n arrayVals.push(arrayObjDest);\n }\n else {\n arrayVals.push(arrayVal);\n }\n });\n xformed[prop] = arrayVals;\n }\n else {\n xformed[prop] = val;\n }\n });\n\n if (dest === undefined) {\n return xformed;\n }\n }\n\n function isValidCommand(command) {\n return $.type(command) === \"string\" &&\n !command.match(/^_/) && //enforce private methods convention\n uploader()[command] !== undefined;\n }\n\n // Assuming we have already verified that this is a valid command, call the associated function in the underlying\n // Fine Uploader instance (passing along the arguments from the caller) and return the result of the call back to the caller\n function delegateCommand(command) {\n var xformedArgs = [],\n origArgs = Array.prototype.slice.call(arguments, 1),\n retVal;\n\n transformVariables(origArgs, xformedArgs);\n\n retVal = uploader()[command].apply(uploader(), xformedArgs);\n\n return maybeWrapInJquery(retVal);\n }\n\n // If the value is an `HTMLElement` or `HTMLDocument`, wrap it in a `jQuery` object\n function maybeWrapInJquery(val) {\n var transformedVal = val;\n\n // If the command is returning an `HTMLElement` or `HTMLDocument`, wrap it in a `jQuery` object\n /*jshint -W116*/\n if (val != null && typeof val === \"object\" &&\n (val.nodeType === 1 || val.nodeType === 9) && val.cloneNode) {\n\n transformedVal = $(val);\n }\n\n return transformedVal;\n }\n\n $.fn.fineUploader = function(optionsOrCommand) {\n var self = this, selfArgs = arguments, retVals = [];\n\n this.each(function(index, el) {\n $el = $(el);\n\n if (uploader() && isValidCommand(optionsOrCommand)) {\n retVals.push(delegateCommand.apply(self, selfArgs));\n\n if (self.length === 1) {\n return false;\n }\n }\n else if (typeof optionsOrCommand === \"object\" || !optionsOrCommand) {\n init.apply(self, selfArgs);\n }\n else {\n $.error(\"Method \" + optionsOrCommand + \" does not exist on jQuery.fineUploader\");\n }\n });\n\n if (retVals.length === 1) {\n return retVals[0];\n }\n else if (retVals.length > 1) {\n return retVals;\n }\n\n return this;\n };\n\n}(jQuery));\n","/*globals jQuery, qq*/\n(function($) {\n \"use strict\";\n var rootDataKey = \"fineUploaderDnd\",\n $el;\n\n function init(options) {\n if (!options) {\n options = {};\n }\n\n options.dropZoneElements = [$el];\n var xformedOpts = transformVariables(options);\n addCallbacks(xformedOpts);\n dnd(new qq.DragAndDrop(xformedOpts));\n\n return $el;\n }\n\n function dataStore(key, val) {\n var data = $el.data(rootDataKey);\n\n if (val) {\n if (data === undefined) {\n data = {};\n }\n data[key] = val;\n $el.data(rootDataKey, data);\n }\n else {\n if (data === undefined) {\n return null;\n }\n return data[key];\n }\n }\n\n function dnd(instanceToStore) {\n return dataStore(\"dndInstance\", instanceToStore);\n }\n\n function addCallbacks(transformedOpts) {\n var callbacks = transformedOpts.callbacks = {};\n\n $.each(new qq.DragAndDrop.callbacks(), function(prop, func) {\n var name = prop,\n $callbackEl;\n\n $callbackEl = $el;\n\n callbacks[prop] = function() {\n var args = Array.prototype.slice.call(arguments),\n jqueryHandlerResult = $callbackEl.triggerHandler(name, args);\n\n return jqueryHandlerResult;\n };\n });\n }\n\n //transform jQuery objects into HTMLElements, and pass along all other option properties\n function transformVariables(source, dest) {\n var xformed, arrayVals;\n\n if (dest === undefined) {\n xformed = {};\n }\n else {\n xformed = dest;\n }\n\n $.each(source, function(prop, val) {\n if (val instanceof $) {\n xformed[prop] = val[0];\n }\n else if ($.isPlainObject(val)) {\n xformed[prop] = {};\n transformVariables(val, xformed[prop]);\n }\n else if ($.isArray(val)) {\n arrayVals = [];\n $.each(val, function(idx, arrayVal) {\n if (arrayVal instanceof $) {\n $.merge(arrayVals, arrayVal);\n }\n else {\n arrayVals.push(arrayVal);\n }\n });\n xformed[prop] = arrayVals;\n }\n else {\n xformed[prop] = val;\n }\n });\n\n if (dest === undefined) {\n return xformed;\n }\n }\n\n function isValidCommand(command) {\n return $.type(command) === \"string\" &&\n command === \"dispose\" &&\n dnd()[command] !== undefined;\n }\n\n function delegateCommand(command) {\n var xformedArgs = [], origArgs = Array.prototype.slice.call(arguments, 1);\n transformVariables(origArgs, xformedArgs);\n return dnd()[command].apply(dnd(), xformedArgs);\n }\n\n $.fn.fineUploaderDnd = function(optionsOrCommand) {\n var self = this, selfArgs = arguments, retVals = [];\n\n this.each(function(index, el) {\n $el = $(el);\n\n if (dnd() && isValidCommand(optionsOrCommand)) {\n retVals.push(delegateCommand.apply(self, selfArgs));\n\n if (self.length === 1) {\n return false;\n }\n }\n else if (typeof optionsOrCommand === \"object\" || !optionsOrCommand) {\n init.apply(self, selfArgs);\n }\n else {\n $.error(\"Method \" + optionsOrCommand + \" does not exist in Fine Uploader's DnD module.\");\n }\n });\n\n if (retVals.length === 1) {\n return retVals[0];\n }\n else if (retVals.length > 1) {\n return retVals;\n }\n\n return this;\n };\n\n}(jQuery));\n","/*globals window, navigator, document, FormData, File, HTMLInputElement, XMLHttpRequest, Blob, Storage, ActiveXObject */\n/* jshint -W079 */\nvar qq = function(element) {\n \"use strict\";\n\n return {\n hide: function() {\n element.style.display = \"none\";\n return this;\n },\n\n /** Returns the function which detaches attached event */\n attach: function(type, fn) {\n if (element.addEventListener) {\n element.addEventListener(type, fn, false);\n } else if (element.attachEvent) {\n element.attachEvent(\"on\" + type, fn);\n }\n return function() {\n qq(element).detach(type, fn);\n };\n },\n\n detach: function(type, fn) {\n if (element.removeEventListener) {\n element.removeEventListener(type, fn, false);\n } else if (element.attachEvent) {\n element.detachEvent(\"on\" + type, fn);\n }\n return this;\n },\n\n contains: function(descendant) {\n // The [W3C spec](http://www.w3.org/TR/domcore/#dom-node-contains)\n // says a `null` (or ostensibly `undefined`) parameter\n // passed into `Node.contains` should result in a false return value.\n // IE7 throws an exception if the parameter is `undefined` though.\n if (!descendant) {\n return false;\n }\n\n // compareposition returns false in this case\n if (element === descendant) {\n return true;\n }\n\n if (element.contains) {\n return element.contains(descendant);\n } else {\n /*jslint bitwise: true*/\n return !!(descendant.compareDocumentPosition(element) & 8);\n }\n },\n\n /**\n * Insert this element before elementB.\n */\n insertBefore: function(elementB) {\n elementB.parentNode.insertBefore(element, elementB);\n return this;\n },\n\n remove: function() {\n element.parentNode.removeChild(element);\n return this;\n },\n\n /**\n * Sets styles for an element.\n * Fixes opacity in IE6-8.\n */\n css: function(styles) {\n /*jshint eqnull: true*/\n if (element.style == null) {\n throw new qq.Error(\"Can't apply style to node as it is not on the HTMLElement prototype chain!\");\n }\n\n /*jshint -W116*/\n if (styles.opacity != null) {\n if (typeof element.style.opacity !== \"string\" && typeof (element.filters) !== \"undefined\") {\n styles.filter = \"alpha(opacity=\" + Math.round(100 * styles.opacity) + \")\";\n }\n }\n qq.extend(element.style, styles);\n\n return this;\n },\n\n hasClass: function(name, considerParent) {\n var re = new RegExp(\"(^| )\" + name + \"( |$)\");\n return re.test(element.className) || !!(considerParent && re.test(element.parentNode.className));\n },\n\n addClass: function(name) {\n if (!qq(element).hasClass(name)) {\n element.className += \" \" + name;\n }\n return this;\n },\n\n removeClass: function(name) {\n var re = new RegExp(\"(^| )\" + name + \"( |$)\");\n element.className = element.className.replace(re, \" \").replace(/^\\s+|\\s+$/g, \"\");\n return this;\n },\n\n getByClass: function(className, first) {\n var candidates,\n result = [];\n\n if (first && element.querySelector) {\n return element.querySelector(\".\" + className);\n }\n else if (element.querySelectorAll) {\n return element.querySelectorAll(\".\" + className);\n }\n\n candidates = element.getElementsByTagName(\"*\");\n\n qq.each(candidates, function(idx, val) {\n if (qq(val).hasClass(className)) {\n result.push(val);\n }\n });\n return first ? result[0] : result;\n },\n\n getFirstByClass: function(className) {\n return qq(element).getByClass(className, true);\n },\n\n children: function() {\n var children = [],\n child = element.firstChild;\n\n while (child) {\n if (child.nodeType === 1) {\n children.push(child);\n }\n child = child.nextSibling;\n }\n\n return children;\n },\n\n setText: function(text) {\n element.innerText = text;\n element.textContent = text;\n return this;\n },\n\n clearText: function() {\n return qq(element).setText(\"\");\n },\n\n // Returns true if the attribute exists on the element\n // AND the value of the attribute is NOT \"false\" (case-insensitive)\n hasAttribute: function(attrName) {\n var attrVal;\n\n if (element.hasAttribute) {\n\n if (!element.hasAttribute(attrName)) {\n return false;\n }\n\n /*jshint -W116*/\n return (/^false$/i).exec(element.getAttribute(attrName)) == null;\n }\n else {\n attrVal = element[attrName];\n\n if (attrVal === undefined) {\n return false;\n }\n\n /*jshint -W116*/\n return (/^false$/i).exec(attrVal) == null;\n }\n }\n };\n};\n\n(function() {\n \"use strict\";\n\n qq.canvasToBlob = function(canvas, mime, quality) {\n return qq.dataUriToBlob(canvas.toDataURL(mime, quality));\n };\n\n qq.dataUriToBlob = function(dataUri) {\n var arrayBuffer, byteString,\n createBlob = function(data, mime) {\n var BlobBuilder = window.BlobBuilder ||\n window.WebKitBlobBuilder ||\n window.MozBlobBuilder ||\n window.MSBlobBuilder,\n blobBuilder = BlobBuilder && new BlobBuilder();\n\n if (blobBuilder) {\n blobBuilder.append(data);\n return blobBuilder.getBlob(mime);\n }\n else {\n return new Blob([data], {type: mime});\n }\n },\n intArray, mimeString;\n\n // convert base64 to raw binary data held in a string\n if (dataUri.split(\",\")[0].indexOf(\"base64\") >= 0) {\n byteString = atob(dataUri.split(\",\")[1]);\n }\n else {\n byteString = decodeURI(dataUri.split(\",\")[1]);\n }\n\n // extract the MIME\n mimeString = dataUri.split(\",\")[0]\n .split(\":\")[1]\n .split(\";\")[0];\n\n // write the bytes of the binary string to an ArrayBuffer\n arrayBuffer = new ArrayBuffer(byteString.length);\n intArray = new Uint8Array(arrayBuffer);\n qq.each(byteString, function(idx, character) {\n intArray[idx] = character.charCodeAt(0);\n });\n\n return createBlob(arrayBuffer, mimeString);\n };\n\n qq.log = function(message, level) {\n if (window.console) {\n if (!level || level === \"info\") {\n window.console.log(message);\n }\n else\n {\n if (window.console[level]) {\n window.console[level](message);\n }\n else {\n window.console.log(\"<\" + level + \"> \" + message);\n }\n }\n }\n };\n\n qq.isObject = function(variable) {\n return variable && !variable.nodeType && Object.prototype.toString.call(variable) === \"[object Object]\";\n };\n\n qq.isFunction = function(variable) {\n return typeof (variable) === \"function\";\n };\n\n /**\n * Check the type of a value. Is it an \"array\"?\n *\n * @param value value to test.\n * @returns true if the value is an array or associated with an `ArrayBuffer`\n */\n qq.isArray = function(value) {\n return Object.prototype.toString.call(value) === \"[object Array]\" ||\n (value && window.ArrayBuffer && value.buffer && value.buffer.constructor === ArrayBuffer);\n };\n\n // Looks for an object on a `DataTransfer` object that is associated with drop events when utilizing the Filesystem API.\n qq.isItemList = function(maybeItemList) {\n return Object.prototype.toString.call(maybeItemList) === \"[object DataTransferItemList]\";\n };\n\n // Looks for an object on a `NodeList` or an `HTMLCollection`|`HTMLFormElement`|`HTMLSelectElement`\n // object that is associated with collections of Nodes.\n qq.isNodeList = function(maybeNodeList) {\n return Object.prototype.toString.call(maybeNodeList) === \"[object NodeList]\" ||\n // If `HTMLCollection` is the actual type of the object, we must determine this\n // by checking for expected properties/methods on the object\n (maybeNodeList.item && maybeNodeList.namedItem);\n };\n\n qq.isString = function(maybeString) {\n return Object.prototype.toString.call(maybeString) === \"[object String]\";\n };\n\n qq.trimStr = function(string) {\n if (String.prototype.trim) {\n return string.trim();\n }\n\n return string.replace(/^\\s+|\\s+$/g, \"\");\n };\n\n /**\n * @param str String to format.\n * @returns {string} A string, swapping argument values with the associated occurrence of {} in the passed string.\n */\n qq.format = function(str) {\n\n var args = Array.prototype.slice.call(arguments, 1),\n newStr = str,\n nextIdxToReplace = newStr.indexOf(\"{}\");\n\n qq.each(args, function(idx, val) {\n var strBefore = newStr.substring(0, nextIdxToReplace),\n strAfter = newStr.substring(nextIdxToReplace + 2);\n\n newStr = strBefore + val + strAfter;\n nextIdxToReplace = newStr.indexOf(\"{}\", nextIdxToReplace + val.length);\n\n // End the loop if we have run out of tokens (when the arguments exceed the # of tokens)\n if (nextIdxToReplace < 0) {\n return false;\n }\n });\n\n return newStr;\n };\n\n qq.isFile = function(maybeFile) {\n return window.File && Object.prototype.toString.call(maybeFile) === \"[object File]\";\n };\n\n qq.isFileList = function(maybeFileList) {\n return window.FileList && Object.prototype.toString.call(maybeFileList) === \"[object FileList]\";\n };\n\n qq.isFileOrInput = function(maybeFileOrInput) {\n return qq.isFile(maybeFileOrInput) || qq.isInput(maybeFileOrInput);\n };\n\n qq.isInput = function(maybeInput, notFile) {\n var evaluateType = function(type) {\n var normalizedType = type.toLowerCase();\n\n if (notFile) {\n return normalizedType !== \"file\";\n }\n\n return normalizedType === \"file\";\n };\n\n if (window.HTMLInputElement) {\n if (Object.prototype.toString.call(maybeInput) === \"[object HTMLInputElement]\") {\n if (maybeInput.type && evaluateType(maybeInput.type)) {\n return true;\n }\n }\n }\n if (maybeInput.tagName) {\n if (maybeInput.tagName.toLowerCase() === \"input\") {\n if (maybeInput.type && evaluateType(maybeInput.type)) {\n return true;\n }\n }\n }\n\n return false;\n };\n\n qq.isBlob = function(maybeBlob) {\n if (window.Blob && Object.prototype.toString.call(maybeBlob) === \"[object Blob]\") {\n return true;\n }\n };\n\n qq.isXhrUploadSupported = function() {\n var input = document.createElement(\"input\");\n input.type = \"file\";\n\n return (\n input.multiple !== undefined &&\n typeof File !== \"undefined\" &&\n typeof FormData !== \"undefined\" &&\n typeof (qq.createXhrInstance()).upload !== \"undefined\");\n };\n\n // Fall back to ActiveX is native XHR is disabled (possible in any version of IE).\n qq.createXhrInstance = function() {\n if (window.XMLHttpRequest) {\n return new XMLHttpRequest();\n }\n\n try {\n return new ActiveXObject(\"MSXML2.XMLHTTP.3.0\");\n }\n catch (error) {\n qq.log(\"Neither XHR or ActiveX are supported!\", \"error\");\n return null;\n }\n };\n\n qq.isFolderDropSupported = function(dataTransfer) {\n return dataTransfer.items &&\n dataTransfer.items.length > 0 &&\n dataTransfer.items[0].webkitGetAsEntry;\n };\n\n qq.isFileChunkingSupported = function() {\n return !qq.androidStock() && //Android's stock browser cannot upload Blobs correctly\n qq.isXhrUploadSupported() &&\n (File.prototype.slice !== undefined || File.prototype.webkitSlice !== undefined || File.prototype.mozSlice !== undefined);\n };\n\n qq.sliceBlob = function(fileOrBlob, start, end) {\n var slicer = fileOrBlob.slice || fileOrBlob.mozSlice || fileOrBlob.webkitSlice;\n\n return slicer.call(fileOrBlob, start, end);\n };\n\n qq.arrayBufferToHex = function(buffer) {\n var bytesAsHex = \"\",\n bytes = new Uint8Array(buffer);\n\n qq.each(bytes, function(idx, byt) {\n var byteAsHexStr = byt.toString(16);\n\n if (byteAsHexStr.length < 2) {\n byteAsHexStr = \"0\" + byteAsHexStr;\n }\n\n bytesAsHex += byteAsHexStr;\n });\n\n return bytesAsHex;\n };\n\n qq.readBlobToHex = function(blob, startOffset, length) {\n var initialBlob = qq.sliceBlob(blob, startOffset, startOffset + length),\n fileReader = new FileReader(),\n promise = new qq.Promise();\n\n fileReader.onload = function() {\n promise.success(qq.arrayBufferToHex(fileReader.result));\n };\n\n fileReader.onerror = promise.failure;\n\n fileReader.readAsArrayBuffer(initialBlob);\n\n return promise;\n };\n\n qq.extend = function(first, second, extendNested) {\n qq.each(second, function(prop, val) {\n if (extendNested && qq.isObject(val)) {\n if (first[prop] === undefined) {\n first[prop] = {};\n }\n qq.extend(first[prop], val, true);\n }\n else {\n first[prop] = val;\n }\n });\n\n return first;\n };\n\n /**\n * Allow properties in one object to override properties in another,\n * keeping track of the original values from the target object.\n *\n * Note that the pre-overriden properties to be overriden by the source will be passed into the `sourceFn` when it is invoked.\n *\n * @param target Update properties in this object from some source\n * @param sourceFn A function that, when invoked, will return properties that will replace properties with the same name in the target.\n * @returns {object} The target object\n */\n qq.override = function(target, sourceFn) {\n var super_ = {},\n source = sourceFn(super_);\n\n qq.each(source, function(srcPropName, srcPropVal) {\n if (target[srcPropName] !== undefined) {\n super_[srcPropName] = target[srcPropName];\n }\n\n target[srcPropName] = srcPropVal;\n });\n\n return target;\n };\n\n /**\n * Searches for a given element (elt) in the array, returns -1 if it is not present.\n */\n qq.indexOf = function(arr, elt, from) {\n if (arr.indexOf) {\n return arr.indexOf(elt, from);\n }\n\n from = from || 0;\n var len = arr.length;\n\n if (from < 0) {\n from += len;\n }\n\n for (; from < len; from += 1) {\n if (arr.hasOwnProperty(from) && arr[from] === elt) {\n return from;\n }\n }\n return -1;\n };\n\n //this is a version 4 UUID\n qq.getUniqueId = function() {\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, function(c) {\n /*jslint eqeq: true, bitwise: true*/\n var r = Math.random() * 16 | 0, v = c == \"x\" ? r : (r & 0x3 | 0x8);\n return v.toString(16);\n });\n };\n\n //\n // Browsers and platforms detection\n qq.ie = function() {\n return navigator.userAgent.indexOf(\"MSIE\") !== -1 ||\n navigator.userAgent.indexOf(\"Trident\") !== -1;\n };\n\n qq.ie7 = function() {\n return navigator.userAgent.indexOf(\"MSIE 7\") !== -1;\n };\n\n qq.ie8 = function() {\n return navigator.userAgent.indexOf(\"MSIE 8\") !== -1;\n };\n\n qq.ie10 = function() {\n return navigator.userAgent.indexOf(\"MSIE 10\") !== -1;\n };\n\n qq.ie11 = function() {\n return qq.ie() && navigator.userAgent.indexOf(\"rv:11\") !== -1;\n };\n\n qq.edge = function() {\n return navigator.userAgent.indexOf(\"Edge\") >= 0;\n };\n\n qq.safari = function() {\n return navigator.vendor !== undefined && navigator.vendor.indexOf(\"Apple\") !== -1;\n };\n\n qq.chrome = function() {\n return navigator.vendor !== undefined && navigator.vendor.indexOf(\"Google\") !== -1;\n };\n\n qq.opera = function() {\n return navigator.vendor !== undefined && navigator.vendor.indexOf(\"Opera\") !== -1;\n };\n\n qq.firefox = function() {\n return (!qq.edge() && !qq.ie11() && navigator.userAgent.indexOf(\"Mozilla\") !== -1 && navigator.vendor !== undefined && navigator.vendor === \"\");\n };\n\n qq.windows = function() {\n return navigator.platform === \"Win32\";\n };\n\n qq.android = function() {\n return navigator.userAgent.toLowerCase().indexOf(\"android\") !== -1;\n };\n\n // We need to identify the Android stock browser via the UA string to work around various bugs in this browser,\n // such as the one that prevents a `Blob` from being uploaded.\n qq.androidStock = function() {\n return qq.android() && navigator.userAgent.toLowerCase().indexOf(\"chrome\") < 0;\n };\n\n qq.ios6 = function() {\n return qq.ios() && navigator.userAgent.indexOf(\" OS 6_\") !== -1;\n };\n\n qq.ios7 = function() {\n return qq.ios() && navigator.userAgent.indexOf(\" OS 7_\") !== -1;\n };\n\n qq.ios8 = function() {\n return qq.ios() && navigator.userAgent.indexOf(\" OS 8_\") !== -1;\n };\n\n // iOS 8.0.0\n qq.ios800 = function() {\n return qq.ios() && navigator.userAgent.indexOf(\" OS 8_0 \") !== -1;\n };\n\n qq.ios = function() {\n /*jshint -W014 */\n return navigator.userAgent.indexOf(\"iPad\") !== -1\n || navigator.userAgent.indexOf(\"iPod\") !== -1\n || navigator.userAgent.indexOf(\"iPhone\") !== -1;\n };\n\n qq.iosChrome = function() {\n return qq.ios() && navigator.userAgent.indexOf(\"CriOS\") !== -1;\n };\n\n qq.iosSafari = function() {\n return qq.ios() && !qq.iosChrome() && navigator.userAgent.indexOf(\"Safari\") !== -1;\n };\n\n qq.iosSafariWebView = function() {\n return qq.ios() && !qq.iosChrome() && !qq.iosSafari();\n };\n\n //\n // Events\n\n qq.preventDefault = function(e) {\n if (e.preventDefault) {\n e.preventDefault();\n } else {\n e.returnValue = false;\n }\n };\n\n /**\n * Creates and returns element from html string\n * Uses innerHTML to create an element\n */\n qq.toElement = (function() {\n var div = document.createElement(\"div\");\n return function(html) {\n div.innerHTML = html;\n var element = div.firstChild;\n div.removeChild(element);\n return element;\n };\n }());\n\n //key and value are passed to callback for each entry in the iterable item\n qq.each = function(iterableItem, callback) {\n var keyOrIndex, retVal;\n\n if (iterableItem) {\n // Iterate through [`Storage`](http://www.w3.org/TR/webstorage/#the-storage-interface) items\n if (window.Storage && iterableItem.constructor === window.Storage) {\n for (keyOrIndex = 0; keyOrIndex < iterableItem.length; keyOrIndex++) {\n retVal = callback(iterableItem.key(keyOrIndex), iterableItem.getItem(iterableItem.key(keyOrIndex)));\n if (retVal === false) {\n break;\n }\n }\n }\n // `DataTransferItemList` & `NodeList` objects are array-like and should be treated as arrays\n // when iterating over items inside the object.\n else if (qq.isArray(iterableItem) || qq.isItemList(iterableItem) || qq.isNodeList(iterableItem)) {\n for (keyOrIndex = 0; keyOrIndex < iterableItem.length; keyOrIndex++) {\n retVal = callback(keyOrIndex, iterableItem[keyOrIndex]);\n if (retVal === false) {\n break;\n }\n }\n }\n else if (qq.isString(iterableItem)) {\n for (keyOrIndex = 0; keyOrIndex < iterableItem.length; keyOrIndex++) {\n retVal = callback(keyOrIndex, iterableItem.charAt(keyOrIndex));\n if (retVal === false) {\n break;\n }\n }\n }\n else {\n for (keyOrIndex in iterableItem) {\n if (Object.prototype.hasOwnProperty.call(iterableItem, keyOrIndex)) {\n retVal = callback(keyOrIndex, iterableItem[keyOrIndex]);\n if (retVal === false) {\n break;\n }\n }\n }\n }\n }\n };\n\n //include any args that should be passed to the new function after the context arg\n qq.bind = function(oldFunc, context) {\n if (qq.isFunction(oldFunc)) {\n var args = Array.prototype.slice.call(arguments, 2);\n\n return function() {\n var newArgs = qq.extend([], args);\n if (arguments.length) {\n newArgs = newArgs.concat(Array.prototype.slice.call(arguments));\n }\n return oldFunc.apply(context, newArgs);\n };\n }\n\n throw new Error(\"first parameter must be a function!\");\n };\n\n /**\n * obj2url() takes a json-object as argument and generates\n * a querystring. pretty much like jQuery.param()\n *\n * how to use:\n *\n * `qq.obj2url({a:'b',c:'d'},'http://any.url/upload?otherParam=value');`\n *\n * will result in:\n *\n * `http://any.url/upload?otherParam=value&a=b&c=d`\n *\n * @param Object JSON-Object\n * @param String current querystring-part\n * @return String encoded querystring\n */\n qq.obj2url = function(obj, temp, prefixDone) {\n /*jshint laxbreak: true*/\n var uristrings = [],\n prefix = \"&\",\n add = function(nextObj, i) {\n var nextTemp = temp\n ? (/\\[\\]$/.test(temp)) // prevent double-encoding\n ? temp\n : temp + \"[\" + i + \"]\"\n : i;\n if ((nextTemp !== \"undefined\") && (i !== \"undefined\")) {\n uristrings.push(\n (typeof nextObj === \"object\")\n ? qq.obj2url(nextObj, nextTemp, true)\n : (Object.prototype.toString.call(nextObj) === \"[object Function]\")\n ? encodeURIComponent(nextTemp) + \"=\" + encodeURIComponent(nextObj())\n : encodeURIComponent(nextTemp) + \"=\" + encodeURIComponent(nextObj)\n );\n }\n };\n\n if (!prefixDone && temp) {\n prefix = (/\\?/.test(temp)) ? (/\\?$/.test(temp)) ? \"\" : \"&\" : \"?\";\n uristrings.push(temp);\n uristrings.push(qq.obj2url(obj));\n } else if ((Object.prototype.toString.call(obj) === \"[object Array]\") && (typeof obj !== \"undefined\")) {\n qq.each(obj, function(idx, val) {\n add(val, idx);\n });\n } else if ((typeof obj !== \"undefined\") && (obj !== null) && (typeof obj === \"object\")) {\n qq.each(obj, function(prop, val) {\n add(val, prop);\n });\n } else {\n uristrings.push(encodeURIComponent(temp) + \"=\" + encodeURIComponent(obj));\n }\n\n if (temp) {\n return uristrings.join(prefix);\n } else {\n return uristrings.join(prefix)\n .replace(/^&/, \"\")\n .replace(/%20/g, \"+\");\n }\n };\n\n qq.obj2FormData = function(obj, formData, arrayKeyName) {\n if (!formData) {\n formData = new FormData();\n }\n\n qq.each(obj, function(key, val) {\n key = arrayKeyName ? arrayKeyName + \"[\" + key + \"]\" : key;\n\n if (qq.isObject(val)) {\n qq.obj2FormData(val, formData, key);\n }\n else if (qq.isFunction(val)) {\n formData.append(key, val());\n }\n else {\n formData.append(key, val);\n }\n });\n\n return formData;\n };\n\n qq.obj2Inputs = function(obj, form) {\n var input;\n\n if (!form) {\n form = document.createElement(\"form\");\n }\n\n qq.obj2FormData(obj, {\n append: function(key, val) {\n input = document.createElement(\"input\");\n input.setAttribute(\"name\", key);\n input.setAttribute(\"value\", val);\n form.appendChild(input);\n }\n });\n\n return form;\n };\n\n /**\n * Not recommended for use outside of Fine Uploader since this falls back to an unchecked eval if JSON.parse is not\n * implemented. For a more secure JSON.parse polyfill, use Douglas Crockford's json2.js.\n */\n qq.parseJson = function(json) {\n /*jshint evil: true*/\n if (window.JSON && qq.isFunction(JSON.parse)) {\n return JSON.parse(json);\n } else {\n return eval(\"(\" + json + \")\");\n }\n };\n\n /**\n * Retrieve the extension of a file, if it exists.\n *\n * @param filename\n * @returns {string || undefined}\n */\n qq.getExtension = function(filename) {\n var extIdx = filename.lastIndexOf(\".\") + 1;\n\n if (extIdx > 0) {\n return filename.substr(extIdx, filename.length - extIdx);\n }\n };\n\n qq.getFilename = function(blobOrFileInput) {\n /*jslint regexp: true*/\n\n if (qq.isInput(blobOrFileInput)) {\n // get input value and remove path to normalize\n return blobOrFileInput.value.replace(/.*(\\/|\\\\)/, \"\");\n }\n else if (qq.isFile(blobOrFileInput)) {\n if (blobOrFileInput.fileName !== null && blobOrFileInput.fileName !== undefined) {\n return blobOrFileInput.fileName;\n }\n }\n\n return blobOrFileInput.name;\n };\n\n /**\n * A generic module which supports object disposing in dispose() method.\n * */\n qq.DisposeSupport = function() {\n var disposers = [];\n\n return {\n /** Run all registered disposers */\n dispose: function() {\n var disposer;\n do {\n disposer = disposers.shift();\n if (disposer) {\n disposer();\n }\n }\n while (disposer);\n },\n\n /** Attach event handler and register de-attacher as a disposer */\n attach: function() {\n var args = arguments;\n /*jslint undef:true*/\n this.addDisposer(qq(args[0]).attach.apply(this, Array.prototype.slice.call(arguments, 1)));\n },\n\n /** Add disposer to the collection */\n addDisposer: function(disposeFunction) {\n disposers.push(disposeFunction);\n }\n };\n };\n}());\n","/* globals define, module, global, qq */\n(function() {\n \"use strict\";\n if (typeof define === \"function\" && define.amd) {\n define(function() {\n return qq;\n });\n }\n else if (typeof module !== \"undefined\" && module.exports) {\n module.exports = qq;\n }\n else {\n global.qq = qq;\n }\n}());\n","/* globals qq */\n/**\n * Fine Uploader top-level Error container. Inherits from `Error`.\n */\n(function() {\n \"use strict\";\n\n qq.Error = function(message) {\n this.message = \"[Fine Uploader \" + qq.version + \"] \" + message;\n };\n\n qq.Error.prototype = new Error();\n}());\n","/*global qq */\nqq.version = \"5.16.2\";\n","/* globals qq */\nqq.supportedFeatures = (function() {\n \"use strict\";\n\n var supportsUploading,\n supportsUploadingBlobs,\n supportsFileDrop,\n supportsAjaxFileUploading,\n supportsFolderDrop,\n supportsChunking,\n supportsResume,\n supportsUploadViaPaste,\n supportsUploadCors,\n supportsDeleteFileXdr,\n supportsDeleteFileCorsXhr,\n supportsDeleteFileCors,\n supportsFolderSelection,\n supportsImagePreviews,\n supportsUploadProgress;\n\n function testSupportsFileInputElement() {\n var supported = true,\n tempInput;\n\n try {\n tempInput = document.createElement(\"input\");\n tempInput.type = \"file\";\n qq(tempInput).hide();\n\n if (tempInput.disabled) {\n supported = false;\n }\n }\n catch (ex) {\n supported = false;\n }\n\n return supported;\n }\n\n //only way to test for complete Clipboard API support at this time\n function isChrome14OrHigher() {\n return (qq.chrome() || qq.opera()) &&\n navigator.userAgent.match(/Chrome\\/[1][4-9]|Chrome\\/[2-9][0-9]/) !== undefined;\n }\n\n //Ensure we can send cross-origin `XMLHttpRequest`s\n function isCrossOriginXhrSupported() {\n if (window.XMLHttpRequest) {\n var xhr = qq.createXhrInstance();\n\n //Commonly accepted test for XHR CORS support.\n return xhr.withCredentials !== undefined;\n }\n\n return false;\n }\n\n //Test for (terrible) cross-origin ajax transport fallback for IE9 and IE8\n function isXdrSupported() {\n return window.XDomainRequest !== undefined;\n }\n\n // CORS Ajax requests are supported if it is either possible to send credentialed `XMLHttpRequest`s,\n // or if `XDomainRequest` is an available alternative.\n function isCrossOriginAjaxSupported() {\n if (isCrossOriginXhrSupported()) {\n return true;\n }\n\n return isXdrSupported();\n }\n\n function isFolderSelectionSupported() {\n // We know that folder selection is only supported in Chrome via this proprietary attribute for now\n return document.createElement(\"input\").webkitdirectory !== undefined;\n }\n\n function isLocalStorageSupported() {\n try {\n return !!window.localStorage &&\n // unpatched versions of IE10/11 have buggy impls of localStorage where setItem is a string\n qq.isFunction(window.localStorage.setItem);\n }\n catch (error) {\n // probably caught a security exception, so no localStorage for you\n return false;\n }\n }\n\n function isDragAndDropSupported() {\n var span = document.createElement(\"span\");\n\n return (\"draggable\" in span || (\"ondragstart\" in span && \"ondrop\" in span)) &&\n !qq.android() && !qq.ios();\n }\n\n supportsUploading = testSupportsFileInputElement();\n\n supportsAjaxFileUploading = supportsUploading && qq.isXhrUploadSupported();\n\n supportsUploadingBlobs = supportsAjaxFileUploading && !qq.androidStock();\n\n supportsFileDrop = supportsAjaxFileUploading && isDragAndDropSupported();\n\n // adapted from https://stackoverflow.com/a/23278460/486979\n supportsFolderDrop = supportsFileDrop && (function() {\n var input = document.createElement(\"input\");\n\n input.type = \"file\";\n return !!(\"webkitdirectory\" in (input || document.querySelectorAll(\"input[type=file]\")[0]));\n }());\n\n supportsChunking = supportsAjaxFileUploading && qq.isFileChunkingSupported();\n\n supportsResume = supportsAjaxFileUploading && supportsChunking && isLocalStorageSupported();\n\n supportsUploadViaPaste = supportsAjaxFileUploading && isChrome14OrHigher();\n\n supportsUploadCors = supportsUploading && (window.postMessage !== undefined || supportsAjaxFileUploading);\n\n supportsDeleteFileCorsXhr = isCrossOriginXhrSupported();\n\n supportsDeleteFileXdr = isXdrSupported();\n\n supportsDeleteFileCors = isCrossOriginAjaxSupported();\n\n supportsFolderSelection = isFolderSelectionSupported();\n\n supportsImagePreviews = supportsAjaxFileUploading && window.FileReader !== undefined;\n\n supportsUploadProgress = (function() {\n if (supportsAjaxFileUploading) {\n return !qq.androidStock() && !qq.iosChrome();\n }\n return false;\n }());\n\n return {\n ajaxUploading: supportsAjaxFileUploading,\n blobUploading: supportsUploadingBlobs,\n canDetermineSize: supportsAjaxFileUploading,\n chunking: supportsChunking,\n deleteFileCors: supportsDeleteFileCors,\n deleteFileCorsXdr: supportsDeleteFileXdr, //NOTE: will also return true in IE10, where XDR is also supported\n deleteFileCorsXhr: supportsDeleteFileCorsXhr,\n dialogElement: !!window.HTMLDialogElement,\n fileDrop: supportsFileDrop,\n folderDrop: supportsFolderDrop,\n folderSelection: supportsFolderSelection,\n imagePreviews: supportsImagePreviews,\n imageValidation: supportsImagePreviews,\n itemSizeValidation: supportsAjaxFileUploading,\n pause: supportsChunking,\n progressBar: supportsUploadProgress,\n resume: supportsResume,\n scaling: supportsImagePreviews && supportsUploadingBlobs,\n tiffPreviews: qq.safari(), // Not the best solution, but simple and probably accurate enough (for now)\n unlimitedScaledImageSize: !qq.ios(), // false simply indicates that there is some known limit\n uploading: supportsUploading,\n uploadCors: supportsUploadCors,\n uploadCustomHeaders: supportsAjaxFileUploading,\n uploadNonMultipart: supportsAjaxFileUploading,\n uploadViaPaste: supportsUploadViaPaste\n };\n\n}());\n","/*globals qq*/\n\n// Is the passed object a promise instance?\nqq.isGenericPromise = function(maybePromise) {\n \"use strict\";\n return !!(maybePromise && maybePromise.then && qq.isFunction(maybePromise.then));\n};\n\nqq.Promise = function() {\n \"use strict\";\n\n var successArgs, failureArgs,\n successCallbacks = [],\n failureCallbacks = [],\n doneCallbacks = [],\n state = 0;\n\n qq.extend(this, {\n then: function(onSuccess, onFailure) {\n if (state === 0) {\n if (onSuccess) {\n successCallbacks.push(onSuccess);\n }\n if (onFailure) {\n failureCallbacks.push(onFailure);\n }\n }\n else if (state === -1) {\n onFailure && onFailure.apply(null, failureArgs);\n }\n else if (onSuccess) {\n onSuccess.apply(null, successArgs);\n }\n\n return this;\n },\n\n done: function(callback) {\n if (state === 0) {\n doneCallbacks.push(callback);\n }\n else {\n callback.apply(null, failureArgs === undefined ? successArgs : failureArgs);\n }\n\n return this;\n },\n\n success: function() {\n state = 1;\n successArgs = arguments;\n\n if (successCallbacks.length) {\n qq.each(successCallbacks, function(idx, callback) {\n callback.apply(null, successArgs);\n });\n }\n\n if (doneCallbacks.length) {\n qq.each(doneCallbacks, function(idx, callback) {\n callback.apply(null, successArgs);\n });\n }\n\n return this;\n },\n\n failure: function() {\n state = -1;\n failureArgs = arguments;\n\n if (failureCallbacks.length) {\n qq.each(failureCallbacks, function(idx, callback) {\n callback.apply(null, failureArgs);\n });\n }\n\n if (doneCallbacks.length) {\n qq.each(doneCallbacks, function(idx, callback) {\n callback.apply(null, failureArgs);\n });\n }\n\n return this;\n }\n });\n};\n","/* globals qq */\n/**\n * Placeholder for a Blob that will be generated on-demand.\n *\n * @param referenceBlob Parent of the generated blob\n * @param onCreate Function to invoke when the blob must be created. Must be promissory.\n * @constructor\n */\nqq.BlobProxy = function(referenceBlob, onCreate) {\n \"use strict\";\n\n qq.extend(this, {\n referenceBlob: referenceBlob,\n\n create: function() {\n return onCreate(referenceBlob);\n }\n });\n};\n","/*globals qq*/\n\n/**\n * This module represents an upload or \"Select File(s)\" button. It's job is to embed an opaque ` `\n * element as a child of a provided \"container\" element. This \"container\" element (`options.element`) is used to provide\n * a custom style for the ` ` element. The ability to change the style of the container element is also\n * provided here by adding CSS classes to the container on hover/focus.\n *\n * TODO Eliminate the mouseover and mouseout event handlers since the :hover CSS pseudo-class should now be\n * available on all supported browsers.\n *\n * @param o Options to override the default values\n */\nqq.UploadButton = function(o) {\n \"use strict\";\n\n var self = this,\n\n disposeSupport = new qq.DisposeSupport(),\n\n options = {\n // Corresponds to the `accept` attribute on the associated ` `\n acceptFiles: null,\n\n // \"Container\" element\n element: null,\n\n focusClass: \"qq-upload-button-focus\",\n\n // A true value allows folders to be selected, if supported by the UA\n folders: false,\n\n // **This option will be removed** in the future as the :hover CSS pseudo-class is available on all supported browsers\n hoverClass: \"qq-upload-button-hover\",\n\n ios8BrowserCrashWorkaround: false,\n\n // If true adds `multiple` attribute to ` `\n multiple: false,\n\n // `name` attribute of ` `\n name: \"qqfile\",\n\n // Called when the browser invokes the onchange handler on the ` `\n onChange: function(input) {},\n\n title: null\n },\n input, buttonId;\n\n // Overrides any of the default option values with any option values passed in during construction.\n qq.extend(options, o);\n\n buttonId = qq.getUniqueId();\n\n // Embed an opaque ` ` element as a child of `options.element`.\n function createInput() {\n var input = document.createElement(\"input\");\n\n input.setAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME, buttonId);\n input.setAttribute(\"title\", options.title);\n\n self.setMultiple(options.multiple, input);\n\n if (options.folders && qq.supportedFeatures.folderSelection) {\n // selecting directories is only possible in Chrome now, via a vendor-specific prefixed attribute\n input.setAttribute(\"webkitdirectory\", \"\");\n }\n\n if (options.acceptFiles) {\n input.setAttribute(\"accept\", options.acceptFiles);\n }\n\n input.setAttribute(\"type\", \"file\");\n input.setAttribute(\"name\", options.name);\n\n qq(input).css({\n position: \"absolute\",\n // in Opera only 'browse' button\n // is clickable and it is located at\n // the right side of the input\n right: 0,\n top: 0,\n fontFamily: \"Arial\",\n // It's especially important to make this an arbitrarily large value\n // to ensure the rendered input button in IE takes up the entire\n // space of the container element. Otherwise, the left side of the\n // button will require a double-click to invoke the file chooser.\n // In other browsers, this might cause other issues, so a large font-size\n // is only used in IE. There is a bug in IE8 where the opacity style is ignored\n // in some cases when the font-size is large. So, this workaround is not applied\n // to IE8.\n fontSize: qq.ie() && !qq.ie8() ? \"3500px\" : \"118px\",\n margin: 0,\n padding: 0,\n cursor: \"pointer\",\n opacity: 0\n });\n\n // Setting the file input's height to 100% in IE7 causes\n // most of the visible button to be unclickable.\n !qq.ie7() && qq(input).css({height: \"100%\"});\n\n options.element.appendChild(input);\n\n disposeSupport.attach(input, \"change\", function() {\n options.onChange(input);\n });\n\n // **These event handlers will be removed** in the future as the :hover CSS pseudo-class is available on all supported browsers\n disposeSupport.attach(input, \"mouseover\", function() {\n qq(options.element).addClass(options.hoverClass);\n });\n disposeSupport.attach(input, \"mouseout\", function() {\n qq(options.element).removeClass(options.hoverClass);\n });\n\n disposeSupport.attach(input, \"focus\", function() {\n qq(options.element).addClass(options.focusClass);\n });\n disposeSupport.attach(input, \"blur\", function() {\n qq(options.element).removeClass(options.focusClass);\n });\n\n return input;\n }\n\n // Make button suitable container for input\n qq(options.element).css({\n position: \"relative\",\n overflow: \"hidden\",\n // Make sure browse button is in the right side in Internet Explorer\n direction: \"ltr\"\n });\n\n // Exposed API\n qq.extend(this, {\n getInput: function() {\n return input;\n },\n\n getButtonId: function() {\n return buttonId;\n },\n\n setMultiple: function(isMultiple, optInput) {\n var input = optInput || this.getInput();\n\n // Temporary workaround for bug in in iOS8 UIWebView that causes the browser to crash\n // before the file chooser appears if the file input doesn't contain a multiple attribute.\n // See #1283.\n if (options.ios8BrowserCrashWorkaround && qq.ios8() && (qq.iosChrome() || qq.iosSafariWebView())) {\n input.setAttribute(\"multiple\", \"\");\n }\n\n else {\n if (isMultiple) {\n input.setAttribute(\"multiple\", \"\");\n }\n else {\n input.removeAttribute(\"multiple\");\n }\n }\n },\n\n setAcceptFiles: function(acceptFiles) {\n if (acceptFiles !== options.acceptFiles) {\n input.setAttribute(\"accept\", acceptFiles);\n }\n },\n\n reset: function() {\n if (input.parentNode) {\n qq(input).remove();\n }\n\n qq(options.element).removeClass(options.focusClass);\n input = null;\n input = createInput();\n }\n });\n\n input = createInput();\n};\n\nqq.UploadButton.BUTTON_ID_ATTR_NAME = \"qq-button-id\";\n","/*globals qq */\nqq.UploadData = function(uploaderProxy) {\n \"use strict\";\n\n var data = [],\n byUuid = {},\n byStatus = {},\n byProxyGroupId = {},\n byBatchId = {};\n\n function getDataByIds(idOrIds) {\n if (qq.isArray(idOrIds)) {\n var entries = [];\n\n qq.each(idOrIds, function(idx, id) {\n entries.push(data[id]);\n });\n\n return entries;\n }\n\n return data[idOrIds];\n }\n\n function getDataByUuids(uuids) {\n if (qq.isArray(uuids)) {\n var entries = [];\n\n qq.each(uuids, function(idx, uuid) {\n entries.push(data[byUuid[uuid]]);\n });\n\n return entries;\n }\n\n return data[byUuid[uuids]];\n }\n\n function getDataByStatus(status) {\n var statusResults = [],\n statuses = [].concat(status);\n\n qq.each(statuses, function(index, statusEnum) {\n var statusResultIndexes = byStatus[statusEnum];\n\n if (statusResultIndexes !== undefined) {\n qq.each(statusResultIndexes, function(i, dataIndex) {\n statusResults.push(data[dataIndex]);\n });\n }\n });\n\n return statusResults;\n }\n\n qq.extend(this, {\n /**\n * Adds a new file to the data cache for tracking purposes.\n *\n * @param spec Data that describes this file. Possible properties are:\n *\n * - uuid: Initial UUID for this file.\n * - name: Initial name of this file.\n * - size: Size of this file, omit if this cannot be determined\n * - status: Initial `qq.status` for this file. Omit for `qq.status.SUBMITTING`.\n * - batchId: ID of the batch this file belongs to\n * - proxyGroupId: ID of the proxy group associated with this file\n * - onBeforeStatusChange(fileId): callback that is executed before the status change is broadcast\n *\n * @returns {number} Internal ID for this file.\n */\n addFile: function(spec) {\n var status = spec.status || qq.status.SUBMITTING,\n id = data.push({\n name: spec.name,\n originalName: spec.name,\n uuid: spec.uuid,\n size: spec.size == null ? -1 : spec.size,\n status: status,\n file: spec.file\n }) - 1;\n\n if (spec.batchId) {\n data[id].batchId = spec.batchId;\n\n if (byBatchId[spec.batchId] === undefined) {\n byBatchId[spec.batchId] = [];\n }\n byBatchId[spec.batchId].push(id);\n }\n\n if (spec.proxyGroupId) {\n data[id].proxyGroupId = spec.proxyGroupId;\n\n if (byProxyGroupId[spec.proxyGroupId] === undefined) {\n byProxyGroupId[spec.proxyGroupId] = [];\n }\n byProxyGroupId[spec.proxyGroupId].push(id);\n }\n\n data[id].id = id;\n byUuid[spec.uuid] = id;\n\n if (byStatus[status] === undefined) {\n byStatus[status] = [];\n }\n byStatus[status].push(id);\n\n spec.onBeforeStatusChange && spec.onBeforeStatusChange(id);\n uploaderProxy.onStatusChange(id, null, status);\n\n return id;\n },\n\n retrieve: function(optionalFilter) {\n if (qq.isObject(optionalFilter) && data.length) {\n if (optionalFilter.id !== undefined) {\n return getDataByIds(optionalFilter.id);\n }\n\n else if (optionalFilter.uuid !== undefined) {\n return getDataByUuids(optionalFilter.uuid);\n }\n\n else if (optionalFilter.status) {\n return getDataByStatus(optionalFilter.status);\n }\n }\n else {\n return qq.extend([], data, true);\n }\n },\n\n removeFileRef: function(id) {\n var record = getDataByIds(id);\n\n if (record) {\n delete record.file;\n }\n },\n\n reset: function() {\n data = [];\n byUuid = {};\n byStatus = {};\n byBatchId = {};\n },\n\n setStatus: function(id, newStatus) {\n var oldStatus = data[id].status,\n byStatusOldStatusIndex = qq.indexOf(byStatus[oldStatus], id);\n\n byStatus[oldStatus].splice(byStatusOldStatusIndex, 1);\n\n data[id].status = newStatus;\n\n if (byStatus[newStatus] === undefined) {\n byStatus[newStatus] = [];\n }\n byStatus[newStatus].push(id);\n\n uploaderProxy.onStatusChange(id, oldStatus, newStatus);\n },\n\n uuidChanged: function(id, newUuid) {\n var oldUuid = data[id].uuid;\n\n data[id].uuid = newUuid;\n byUuid[newUuid] = id;\n delete byUuid[oldUuid];\n },\n\n updateName: function(id, newName) {\n data[id].name = newName;\n },\n\n updateSize: function(id, newSize) {\n data[id].size = newSize;\n },\n\n // Only applicable if this file has a parent that we may want to reference later.\n setParentId: function(targetId, parentId) {\n data[targetId].parentId = parentId;\n },\n\n getIdsInProxyGroup: function(id) {\n var proxyGroupId = data[id].proxyGroupId;\n\n if (proxyGroupId) {\n return byProxyGroupId[proxyGroupId];\n }\n return [];\n },\n\n getIdsInBatch: function(id) {\n var batchId = data[id].batchId;\n\n return byBatchId[batchId];\n }\n });\n};\n\nqq.status = {\n SUBMITTING: \"submitting\",\n SUBMITTED: \"submitted\",\n REJECTED: \"rejected\",\n QUEUED: \"queued\",\n CANCELED: \"canceled\",\n PAUSED: \"paused\",\n UPLOADING: \"uploading\",\n UPLOAD_FINALIZING: \"upload finalizing\",\n UPLOAD_RETRYING: \"retrying upload\",\n UPLOAD_SUCCESSFUL: \"upload successful\",\n UPLOAD_FAILED: \"upload failed\",\n DELETE_FAILED: \"delete failed\",\n DELETING: \"deleting\",\n DELETED: \"deleted\"\n};\n","/*globals qq*/\n/**\n * Defines the public API for FineUploaderBasic mode.\n */\n(function() {\n \"use strict\";\n\n qq.basePublicApi = {\n // DEPRECATED - TODO REMOVE IN NEXT MAJOR RELEASE (replaced by addFiles)\n addBlobs: function(blobDataOrArray, params, endpoint) {\n this.addFiles(blobDataOrArray, params, endpoint);\n },\n\n addInitialFiles: function(cannedFileList) {\n var self = this;\n\n qq.each(cannedFileList, function(index, cannedFile) {\n self._addCannedFile(cannedFile);\n });\n },\n\n addFiles: function(data, params, endpoint) {\n this._maybeHandleIos8SafariWorkaround();\n\n var batchId = this._storedIds.length === 0 ? qq.getUniqueId() : this._currentBatchId,\n\n processBlob = qq.bind(function(blob) {\n this._handleNewFile({\n blob: blob,\n name: this._options.blobs.defaultName\n }, batchId, verifiedFiles);\n }, this),\n\n processBlobData = qq.bind(function(blobData) {\n this._handleNewFile(blobData, batchId, verifiedFiles);\n }, this),\n\n processCanvas = qq.bind(function(canvas) {\n var blob = qq.canvasToBlob(canvas);\n\n this._handleNewFile({\n blob: blob,\n name: this._options.blobs.defaultName + \".png\"\n }, batchId, verifiedFiles);\n }, this),\n\n processCanvasData = qq.bind(function(canvasData) {\n var normalizedQuality = canvasData.quality && canvasData.quality / 100,\n blob = qq.canvasToBlob(canvasData.canvas, canvasData.type, normalizedQuality);\n\n this._handleNewFile({\n blob: blob,\n name: canvasData.name\n }, batchId, verifiedFiles);\n }, this),\n\n processFileOrInput = qq.bind(function(fileOrInput) {\n if (qq.isInput(fileOrInput) && qq.supportedFeatures.ajaxUploading) {\n var files = Array.prototype.slice.call(fileOrInput.files),\n self = this;\n\n qq.each(files, function(idx, file) {\n self._handleNewFile(file, batchId, verifiedFiles);\n });\n }\n else {\n this._handleNewFile(fileOrInput, batchId, verifiedFiles);\n }\n }, this),\n\n normalizeData = function() {\n if (qq.isFileList(data)) {\n data = Array.prototype.slice.call(data);\n }\n data = [].concat(data);\n },\n\n self = this,\n verifiedFiles = [];\n\n this._currentBatchId = batchId;\n\n if (data) {\n normalizeData();\n\n qq.each(data, function(idx, fileContainer) {\n if (qq.isFileOrInput(fileContainer)) {\n processFileOrInput(fileContainer);\n }\n else if (qq.isBlob(fileContainer)) {\n processBlob(fileContainer);\n }\n else if (qq.isObject(fileContainer)) {\n if (fileContainer.blob && fileContainer.name) {\n processBlobData(fileContainer);\n }\n else if (fileContainer.canvas && fileContainer.name) {\n processCanvasData(fileContainer);\n }\n }\n else if (fileContainer.tagName && fileContainer.tagName.toLowerCase() === \"canvas\") {\n processCanvas(fileContainer);\n }\n else {\n self.log(fileContainer + \" is not a valid file container! Ignoring!\", \"warn\");\n }\n });\n\n this.log(\"Received \" + verifiedFiles.length + \" files.\");\n this._prepareItemsForUpload(verifiedFiles, params, endpoint);\n }\n },\n\n cancel: function(id) {\n var uploadData = this._uploadData.retrieve({id: id});\n\n if (uploadData && uploadData.status === qq.status.UPLOAD_FINALIZING) {\n this.log(qq.format(\"Ignoring cancel for file ID {} ({}). Finalizing upload.\", id, this.getName(id)), \"error\");\n }\n else {\n this._handler.cancel(id);\n }\n },\n\n cancelAll: function() {\n var storedIdsCopy = [],\n self = this;\n\n qq.extend(storedIdsCopy, this._storedIds);\n qq.each(storedIdsCopy, function(idx, storedFileId) {\n self.cancel(storedFileId);\n });\n\n this._handler.cancelAll();\n },\n\n clearStoredFiles: function() {\n this._storedIds = [];\n },\n\n continueUpload: function(id) {\n var uploadData = this._uploadData.retrieve({id: id});\n\n if (!qq.supportedFeatures.pause || !this._options.chunking.enabled) {\n return false;\n }\n\n if (uploadData.status === qq.status.PAUSED) {\n this.log(qq.format(\"Paused file ID {} ({}) will be continued. Not paused.\", id, this.getName(id)));\n this._uploadFile(id);\n return true;\n }\n else {\n this.log(qq.format(\"Ignoring continue for file ID {} ({}). Not paused.\", id, this.getName(id)), \"error\");\n }\n\n return false;\n },\n\n deleteFile: function(id) {\n return this._onSubmitDelete(id);\n },\n\n // TODO document?\n doesExist: function(fileOrBlobId) {\n return this._handler.isValid(fileOrBlobId);\n },\n\n // Generate a variable size thumbnail on an img or canvas,\n // returning a promise that is fulfilled when the attempt completes.\n // Thumbnail can either be based off of a URL for an image returned\n // by the server in the upload response, or the associated `Blob`.\n drawThumbnail: function(fileId, imgOrCanvas, maxSize, fromServer, customResizeFunction) {\n var promiseToReturn = new qq.Promise(),\n fileOrUrl, options;\n\n if (this._imageGenerator) {\n fileOrUrl = this._thumbnailUrls[fileId];\n options = {\n customResizeFunction: customResizeFunction,\n maxSize: maxSize > 0 ? maxSize : null,\n scale: maxSize > 0\n };\n\n // If client-side preview generation is possible\n // and we are not specifically looking for the image URl returned by the server...\n if (!fromServer && qq.supportedFeatures.imagePreviews) {\n fileOrUrl = this.getFile(fileId);\n }\n\n /* jshint eqeqeq:false,eqnull:true */\n if (fileOrUrl == null) {\n promiseToReturn.failure({container: imgOrCanvas, error: \"File or URL not found.\"});\n }\n else {\n this._imageGenerator.generate(fileOrUrl, imgOrCanvas, options).then(\n function success(modifiedContainer) {\n promiseToReturn.success(modifiedContainer);\n },\n\n function failure(container, reason) {\n promiseToReturn.failure({container: container, error: reason || \"Problem generating thumbnail\"});\n }\n );\n }\n }\n else {\n promiseToReturn.failure({container: imgOrCanvas, error: \"Missing image generator module\"});\n }\n\n return promiseToReturn;\n },\n\n getButton: function(fileId) {\n return this._getButton(this._buttonIdsForFileIds[fileId]);\n },\n\n getEndpoint: function(fileId) {\n return this._endpointStore.get(fileId);\n },\n\n getFile: function(fileOrBlobId) {\n var file = this._handler.getFile(fileOrBlobId);\n var uploadDataRecord;\n\n if (!file) {\n uploadDataRecord = this._uploadData.retrieve({id: fileOrBlobId});\n\n if (uploadDataRecord) {\n file = uploadDataRecord.file;\n }\n }\n\n return file || null;\n },\n\n getInProgress: function() {\n return this._uploadData.retrieve({\n status: [\n qq.status.UPLOADING,\n qq.status.UPLOAD_RETRYING,\n qq.status.QUEUED\n ]\n }).length;\n },\n\n getName: function(id) {\n return this._uploadData.retrieve({id: id}).name;\n },\n\n // Parent ID for a specific file, or null if this is the parent, or if it has no parent.\n getParentId: function(id) {\n var uploadDataEntry = this.getUploads({id: id}),\n parentId = null;\n\n if (uploadDataEntry) {\n if (uploadDataEntry.parentId !== undefined) {\n parentId = uploadDataEntry.parentId;\n }\n }\n\n return parentId;\n },\n\n getResumableFilesData: function() {\n return this._handler.getResumableFilesData();\n },\n\n getSize: function(id) {\n return this._uploadData.retrieve({id: id}).size;\n },\n\n getNetUploads: function() {\n return this._netUploaded;\n },\n\n getRemainingAllowedItems: function() {\n var allowedItems = this._currentItemLimit;\n\n if (allowedItems > 0) {\n return allowedItems - this._netUploadedOrQueued;\n }\n\n return null;\n },\n\n getUploads: function(optionalFilter) {\n return this._uploadData.retrieve(optionalFilter);\n },\n\n getUuid: function(id) {\n return this._uploadData.retrieve({id: id}).uuid;\n },\n\n isResumable: function(id) {\n return this._handler.hasResumeRecord(id);\n },\n\n log: function(str, level) {\n if (this._options.debug && (!level || level === \"info\")) {\n qq.log(\"[Fine Uploader \" + qq.version + \"] \" + str);\n }\n else if (level && level !== \"info\") {\n qq.log(\"[Fine Uploader \" + qq.version + \"] \" + str, level);\n\n }\n },\n\n pauseUpload: function(id) {\n var uploadData = this._uploadData.retrieve({id: id});\n\n if (!qq.supportedFeatures.pause || !this._options.chunking.enabled) {\n return false;\n }\n\n // Pause only really makes sense if the file is uploading or retrying\n if (qq.indexOf([qq.status.UPLOADING, qq.status.UPLOAD_RETRYING], uploadData.status) >= 0) {\n if (this._handler.pause(id)) {\n this._uploadData.setStatus(id, qq.status.PAUSED);\n return true;\n }\n else {\n this.log(qq.format(\"Unable to pause file ID {} ({}).\", id, this.getName(id)), \"error\");\n }\n }\n else {\n this.log(qq.format(\"Ignoring pause for file ID {} ({}). Not in progress.\", id, this.getName(id)), \"error\");\n }\n\n return false;\n },\n\n removeFileRef: function(id) {\n this._handler.expunge(id);\n this._uploadData.removeFileRef(id);\n },\n\n reset: function() {\n this.log(\"Resetting uploader...\");\n\n this._handler.reset();\n this._storedIds = [];\n this._autoRetries = [];\n this._retryTimeouts = [];\n this._preventRetries = [];\n this._thumbnailUrls = [];\n\n qq.each(this._buttons, function(idx, button) {\n button.reset();\n });\n\n this._paramsStore.reset();\n this._endpointStore.reset();\n this._netUploadedOrQueued = 0;\n this._netUploaded = 0;\n this._uploadData.reset();\n this._buttonIdsForFileIds = [];\n\n this._pasteHandler && this._pasteHandler.reset();\n this._options.session.refreshOnReset && this._refreshSessionData();\n\n this._succeededSinceLastAllComplete = [];\n this._failedSinceLastAllComplete = [];\n\n this._totalProgress && this._totalProgress.reset();\n\n this._customResumeDataStore.reset();\n },\n\n retry: function(id) {\n return this._manualRetry(id);\n },\n\n scaleImage: function(id, specs) {\n var self = this;\n\n return qq.Scaler.prototype.scaleImage(id, specs, {\n log: qq.bind(self.log, self),\n getFile: qq.bind(self.getFile, self),\n uploadData: self._uploadData\n });\n },\n\n setCustomHeaders: function(headers, id) {\n this._customHeadersStore.set(headers, id);\n },\n\n setCustomResumeData: function(id, data) {\n this._customResumeDataStore.set(data, id);\n },\n\n setDeleteFileCustomHeaders: function(headers, id) {\n this._deleteFileCustomHeadersStore.set(headers, id);\n },\n\n setDeleteFileEndpoint: function(endpoint, id) {\n this._deleteFileEndpointStore.set(endpoint, id);\n },\n\n setDeleteFileParams: function(params, id) {\n this._deleteFileParamsStore.set(params, id);\n },\n\n // Re-sets the default endpoint, an endpoint for a specific file, or an endpoint for a specific button\n setEndpoint: function(endpoint, id) {\n this._endpointStore.set(endpoint, id);\n },\n\n setForm: function(elementOrId) {\n this._updateFormSupportAndParams(elementOrId);\n },\n\n setItemLimit: function(newItemLimit) {\n this._currentItemLimit = newItemLimit;\n },\n\n setName: function(id, newName) {\n this._uploadData.updateName(id, newName);\n },\n\n setParams: function(params, id) {\n this._paramsStore.set(params, id);\n },\n\n setUuid: function(id, newUuid) {\n return this._uploadData.uuidChanged(id, newUuid);\n },\n\n /**\n * Expose the internal status of a file id to the public api for manual state changes\n * @public\n *\n * @param {Number} id,\n * @param {String} newStatus\n *\n * @todo Implement the remaining methods\n */\n setStatus: function(id, newStatus) {\n var fileRecord = this.getUploads({id: id});\n if (!fileRecord) {\n throw new qq.Error(id + \" is not a valid file ID.\");\n }\n\n switch (newStatus) {\n case qq.status.DELETED:\n this._onDeleteComplete(id, null, false);\n break;\n case qq.status.DELETE_FAILED:\n this._onDeleteComplete(id, null, true);\n break;\n default:\n var errorMessage = \"Method setStatus called on '\" + name + \"' not implemented yet for \" + newStatus;\n this.log(errorMessage);\n throw new qq.Error(errorMessage);\n }\n },\n\n uploadStoredFiles: function() {\n if (this._storedIds.length === 0) {\n this._itemError(\"noFilesError\");\n }\n else {\n this._uploadStoredFiles();\n }\n }\n };\n\n /**\n * Defines the private (internal) API for FineUploaderBasic mode.\n */\n qq.basePrivateApi = {\n // Updates internal state with a file record (not backed by a live file). Returns the assigned ID.\n _addCannedFile: function(sessionData) {\n var self = this;\n\n return this._uploadData.addFile({\n uuid: sessionData.uuid,\n name: sessionData.name,\n size: sessionData.size,\n status: qq.status.UPLOAD_SUCCESSFUL,\n onBeforeStatusChange: function(id) {\n sessionData.deleteFileEndpoint && self.setDeleteFileEndpoint(sessionData.deleteFileEndpoint, id);\n sessionData.deleteFileParams && self.setDeleteFileParams(sessionData.deleteFileParams, id);\n\n if (sessionData.thumbnailUrl) {\n self._thumbnailUrls[id] = sessionData.thumbnailUrl;\n }\n\n self._netUploaded++;\n self._netUploadedOrQueued++;\n }\n });\n },\n\n _annotateWithButtonId: function(file, associatedInput) {\n if (qq.isFile(file)) {\n file.qqButtonId = this._getButtonId(associatedInput);\n }\n },\n\n _batchError: function(message) {\n this._options.callbacks.onError(null, null, message, undefined);\n },\n\n _createDeleteHandler: function() {\n var self = this;\n\n return new qq.DeleteFileAjaxRequester({\n method: this._options.deleteFile.method.toUpperCase(),\n maxConnections: this._options.maxConnections,\n uuidParamName: this._options.request.uuidName,\n customHeaders: this._deleteFileCustomHeadersStore,\n paramsStore: this._deleteFileParamsStore,\n endpointStore: this._deleteFileEndpointStore,\n cors: this._options.cors,\n log: qq.bind(self.log, self),\n onDelete: function(id) {\n self._onDelete(id);\n self._options.callbacks.onDelete(id);\n },\n onDeleteComplete: function(id, xhrOrXdr, isError) {\n self._onDeleteComplete(id, xhrOrXdr, isError);\n self._options.callbacks.onDeleteComplete(id, xhrOrXdr, isError);\n }\n\n });\n },\n\n _createPasteHandler: function() {\n var self = this;\n\n return new qq.PasteSupport({\n targetElement: this._options.paste.targetElement,\n callbacks: {\n log: qq.bind(self.log, self),\n pasteReceived: function(blob) {\n self._handleCheckedCallback({\n name: \"onPasteReceived\",\n callback: qq.bind(self._options.callbacks.onPasteReceived, self, blob),\n onSuccess: qq.bind(self._handlePasteSuccess, self, blob),\n identifier: \"pasted image\"\n });\n }\n }\n });\n },\n\n _createStore: function(initialValue, _readOnlyValues_) {\n var store = {},\n catchall = initialValue,\n perIdReadOnlyValues = {},\n readOnlyValues = _readOnlyValues_,\n copy = function(orig) {\n if (qq.isObject(orig)) {\n return qq.extend({}, orig);\n }\n return orig;\n },\n getReadOnlyValues = function() {\n if (qq.isFunction(readOnlyValues)) {\n return readOnlyValues();\n }\n return readOnlyValues;\n },\n includeReadOnlyValues = function(id, existing) {\n if (readOnlyValues && qq.isObject(existing)) {\n qq.extend(existing, getReadOnlyValues());\n }\n\n if (perIdReadOnlyValues[id]) {\n qq.extend(existing, perIdReadOnlyValues[id]);\n }\n };\n\n return {\n set: function(val, id) {\n /*jshint eqeqeq: true, eqnull: true*/\n if (id == null) {\n store = {};\n catchall = copy(val);\n }\n else {\n store[id] = copy(val);\n }\n },\n\n get: function(id) {\n var values;\n\n /*jshint eqeqeq: true, eqnull: true*/\n if (id != null && store[id]) {\n values = store[id];\n }\n else {\n values = copy(catchall);\n }\n\n includeReadOnlyValues(id, values);\n\n return copy(values);\n },\n\n addReadOnly: function(id, values) {\n // Only applicable to Object stores\n if (qq.isObject(store)) {\n // If null ID, apply readonly values to all files\n if (id === null) {\n if (qq.isFunction(values)) {\n readOnlyValues = values;\n }\n else {\n readOnlyValues = readOnlyValues || {};\n qq.extend(readOnlyValues, values);\n }\n }\n else {\n perIdReadOnlyValues[id] = perIdReadOnlyValues[id] || {};\n qq.extend(perIdReadOnlyValues[id], values);\n }\n }\n },\n\n remove: function(fileId) {\n return delete store[fileId];\n },\n\n reset: function() {\n store = {};\n perIdReadOnlyValues = {};\n catchall = initialValue;\n }\n };\n },\n\n _createUploadDataTracker: function() {\n var self = this;\n\n return new qq.UploadData({\n getName: function(id) {\n return self.getName(id);\n },\n getUuid: function(id) {\n return self.getUuid(id);\n },\n getSize: function(id) {\n return self.getSize(id);\n },\n onStatusChange: function(id, oldStatus, newStatus) {\n self._onUploadStatusChange(id, oldStatus, newStatus);\n self._options.callbacks.onStatusChange(id, oldStatus, newStatus);\n self._maybeAllComplete(id, newStatus);\n\n if (self._totalProgress) {\n setTimeout(function() {\n self._totalProgress.onStatusChange(id, oldStatus, newStatus);\n }, 0);\n }\n }\n });\n },\n\n /**\n * Generate a tracked upload button.\n *\n * @param spec Object containing a required `element` property\n * along with optional `multiple`, `accept`, and `folders`.\n * @returns {qq.UploadButton}\n * @private\n */\n _createUploadButton: function(spec) {\n var self = this,\n acceptFiles = spec.accept || this._options.validation.acceptFiles,\n allowedExtensions = spec.allowedExtensions || this._options.validation.allowedExtensions,\n button;\n\n function allowMultiple() {\n if (qq.supportedFeatures.ajaxUploading) {\n // Workaround for bug in iOS7+ (see #1039)\n if (self._options.workarounds.iosEmptyVideos &&\n qq.ios() &&\n !qq.ios6() &&\n self._isAllowedExtension(allowedExtensions, \".mov\")) {\n\n return false;\n }\n\n if (spec.multiple === undefined) {\n return self._options.multiple;\n }\n\n return spec.multiple;\n }\n\n return false;\n }\n\n button = new qq.UploadButton({\n acceptFiles: acceptFiles,\n element: spec.element,\n focusClass: this._options.classes.buttonFocus,\n folders: spec.folders,\n hoverClass: this._options.classes.buttonHover,\n ios8BrowserCrashWorkaround: this._options.workarounds.ios8BrowserCrash,\n multiple: allowMultiple(),\n name: this._options.request.inputName,\n onChange: function(input) {\n self._onInputChange(input);\n },\n title: spec.title == null ? this._options.text.fileInputTitle : spec.title\n });\n\n this._disposeSupport.addDisposer(function() {\n button.dispose();\n });\n\n self._buttons.push(button);\n\n return button;\n },\n\n _createUploadHandler: function(additionalOptions, namespace) {\n var self = this,\n lastOnProgress = {},\n options = {\n debug: this._options.debug,\n maxConnections: this._options.maxConnections,\n cors: this._options.cors,\n paramsStore: this._paramsStore,\n endpointStore: this._endpointStore,\n chunking: this._options.chunking,\n resume: this._options.resume,\n blobs: this._options.blobs,\n log: qq.bind(self.log, self),\n preventRetryParam: this._options.retry.preventRetryResponseProperty,\n onProgress: function(id, name, loaded, total) {\n if (loaded < 0 || total < 0) {\n return;\n }\n\n if (lastOnProgress[id]) {\n if (lastOnProgress[id].loaded !== loaded || lastOnProgress[id].total !== total) {\n self._onProgress(id, name, loaded, total);\n self._options.callbacks.onProgress(id, name, loaded, total);\n }\n }\n else {\n self._onProgress(id, name, loaded, total);\n self._options.callbacks.onProgress(id, name, loaded, total);\n }\n\n lastOnProgress[id] = {loaded: loaded, total: total};\n\n },\n onComplete: function(id, name, result, xhr) {\n delete lastOnProgress[id];\n\n var status = self.getUploads({id: id}).status,\n retVal;\n\n // This is to deal with some observed cases where the XHR readyStateChange handler is\n // invoked by the browser multiple times for the same XHR instance with the same state\n // readyState value. Higher level: don't invoke complete-related code if we've already\n // done this.\n if (status === qq.status.UPLOAD_SUCCESSFUL || status === qq.status.UPLOAD_FAILED) {\n return;\n }\n\n retVal = self._onComplete(id, name, result, xhr);\n\n // If the internal `_onComplete` handler returns a promise, don't invoke the `onComplete` callback\n // until the promise has been fulfilled.\n if (retVal instanceof qq.Promise) {\n retVal.done(function() {\n self._options.callbacks.onComplete(id, name, result, xhr);\n });\n }\n else {\n self._options.callbacks.onComplete(id, name, result, xhr);\n }\n },\n onCancel: function(id, name, cancelFinalizationEffort) {\n var promise = new qq.Promise();\n\n self._handleCheckedCallback({\n name: \"onCancel\",\n callback: qq.bind(self._options.callbacks.onCancel, self, id, name),\n onFailure: promise.failure,\n onSuccess: function() {\n cancelFinalizationEffort.then(function() {\n self._onCancel(id, name);\n });\n\n promise.success();\n },\n identifier: id\n });\n\n return promise;\n },\n onUploadPrep: qq.bind(this._onUploadPrep, this),\n onUpload: function(id, name) {\n self._onUpload(id, name);\n var onUploadResult = self._options.callbacks.onUpload(id, name);\n\n if (qq.isGenericPromise(onUploadResult)) {\n self.log(qq.format(\"onUpload for {} returned a Promise - waiting for resolution.\", id));\n return onUploadResult;\n }\n\n return new qq.Promise().success();\n },\n onUploadChunk: function(id, name, chunkData) {\n self._onUploadChunk(id, chunkData);\n var onUploadChunkResult = self._options.callbacks.onUploadChunk(id, name, chunkData);\n\n if (qq.isGenericPromise(onUploadChunkResult)) {\n self.log(qq.format(\"onUploadChunk for {}.{} returned a Promise - waiting for resolution.\", id, chunkData.partIndex));\n return onUploadChunkResult;\n }\n\n return new qq.Promise().success();\n },\n onUploadChunkSuccess: function(id, chunkData, result, xhr) {\n self._onUploadChunkSuccess(id, chunkData);\n self._options.callbacks.onUploadChunkSuccess.apply(self, arguments);\n },\n onResume: function(id, name, chunkData, customResumeData) {\n return self._options.callbacks.onResume(id, name, chunkData, customResumeData);\n },\n onAutoRetry: function(id, name, responseJSON, xhr) {\n return self._onAutoRetry.apply(self, arguments);\n },\n onUuidChanged: function(id, newUuid) {\n self.log(\"Server requested UUID change from '\" + self.getUuid(id) + \"' to '\" + newUuid + \"'\");\n self.setUuid(id, newUuid);\n },\n getName: qq.bind(self.getName, self),\n getUuid: qq.bind(self.getUuid, self),\n getSize: qq.bind(self.getSize, self),\n setSize: qq.bind(self._setSize, self),\n getDataByUuid: function(uuid) {\n return self.getUploads({uuid: uuid});\n },\n isQueued: function(id) {\n var status = self.getUploads({id: id}).status;\n return status === qq.status.QUEUED ||\n status === qq.status.SUBMITTED ||\n status === qq.status.UPLOAD_RETRYING ||\n status === qq.status.PAUSED;\n },\n getIdsInProxyGroup: self._uploadData.getIdsInProxyGroup,\n getIdsInBatch: self._uploadData.getIdsInBatch,\n isInProgress: function(id) {\n return self.getUploads({id: id}).status === qq.status.UPLOADING;\n },\n getCustomResumeData: qq.bind(self._getCustomResumeData, self),\n setStatus: function(id, status) {\n self._uploadData.setStatus(id, status);\n }\n };\n\n qq.each(this._options.request, function(prop, val) {\n options[prop] = val;\n });\n\n options.customHeaders = this._customHeadersStore;\n\n if (additionalOptions) {\n qq.each(additionalOptions, function(key, val) {\n options[key] = val;\n });\n }\n\n return new qq.UploadHandlerController(options, namespace);\n },\n\n _fileOrBlobRejected: function(id) {\n this._netUploadedOrQueued--;\n this._uploadData.setStatus(id, qq.status.REJECTED);\n },\n\n _formatSize: function(bytes) {\n if (bytes === 0) {\n return bytes + this._options.text.sizeSymbols[0];\n }\n var i = -1;\n do {\n bytes = bytes / 1000;\n i++;\n } while (bytes > 999);\n\n return Math.max(bytes, 0.1).toFixed(1) + this._options.text.sizeSymbols[i];\n },\n\n // Creates an internal object that tracks various properties of each extra button,\n // and then actually creates the extra button.\n _generateExtraButtonSpecs: function() {\n var self = this;\n\n this._extraButtonSpecs = {};\n\n qq.each(this._options.extraButtons, function(idx, extraButtonOptionEntry) {\n var multiple = extraButtonOptionEntry.multiple,\n validation = qq.extend({}, self._options.validation, true),\n extraButtonSpec = qq.extend({}, extraButtonOptionEntry);\n\n if (multiple === undefined) {\n multiple = self._options.multiple;\n }\n\n if (extraButtonSpec.validation) {\n qq.extend(validation, extraButtonOptionEntry.validation, true);\n }\n\n qq.extend(extraButtonSpec, {\n multiple: multiple,\n validation: validation\n }, true);\n\n self._initExtraButton(extraButtonSpec);\n });\n },\n\n _getButton: function(buttonId) {\n var extraButtonsSpec = this._extraButtonSpecs[buttonId];\n\n if (extraButtonsSpec) {\n return extraButtonsSpec.element;\n }\n else if (buttonId === this._defaultButtonId) {\n return this._options.button;\n }\n },\n\n /**\n * Gets the internally used tracking ID for a button.\n *\n * @param buttonOrFileInputOrFile `File`, ` `, or a button container element\n * @returns {*} The button's ID, or undefined if no ID is recoverable\n * @private\n */\n _getButtonId: function(buttonOrFileInputOrFile) {\n var inputs, fileInput,\n fileBlobOrInput = buttonOrFileInputOrFile;\n\n // We want the reference file/blob here if this is a proxy (a file that will be generated on-demand later)\n if (fileBlobOrInput instanceof qq.BlobProxy) {\n fileBlobOrInput = fileBlobOrInput.referenceBlob;\n }\n\n // If the item is a `Blob` it will never be associated with a button or drop zone.\n if (fileBlobOrInput && !qq.isBlob(fileBlobOrInput)) {\n if (qq.isFile(fileBlobOrInput)) {\n return fileBlobOrInput.qqButtonId;\n }\n else if (fileBlobOrInput.tagName.toLowerCase() === \"input\" &&\n fileBlobOrInput.type.toLowerCase() === \"file\") {\n\n return fileBlobOrInput.getAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME);\n }\n\n inputs = fileBlobOrInput.getElementsByTagName(\"input\");\n\n qq.each(inputs, function(idx, input) {\n if (input.getAttribute(\"type\") === \"file\") {\n fileInput = input;\n return false;\n }\n });\n\n if (fileInput) {\n return fileInput.getAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME);\n }\n }\n },\n\n _getCustomResumeData: function(fileId) {\n return this._customResumeDataStore.get(fileId);\n },\n\n _getNotFinished: function() {\n return this._uploadData.retrieve({\n status: [\n qq.status.UPLOADING,\n qq.status.UPLOAD_RETRYING,\n qq.status.QUEUED,\n qq.status.SUBMITTING,\n qq.status.SUBMITTED,\n qq.status.PAUSED\n ]\n }).length;\n },\n\n // Get the validation options for this button. Could be the default validation option\n // or a specific one assigned to this particular button.\n _getValidationBase: function(buttonId) {\n var extraButtonSpec = this._extraButtonSpecs[buttonId];\n\n return extraButtonSpec ? extraButtonSpec.validation : this._options.validation;\n },\n\n _getValidationDescriptor: function(fileWrapper) {\n if (fileWrapper.file instanceof qq.BlobProxy) {\n return {\n name: qq.getFilename(fileWrapper.file.referenceBlob),\n size: fileWrapper.file.referenceBlob.size\n };\n }\n\n return {\n name: this.getUploads({id: fileWrapper.id}).name,\n size: this.getUploads({id: fileWrapper.id}).size\n };\n },\n\n _getValidationDescriptors: function(fileWrappers) {\n var self = this,\n fileDescriptors = [];\n\n qq.each(fileWrappers, function(idx, fileWrapper) {\n fileDescriptors.push(self._getValidationDescriptor(fileWrapper));\n });\n\n return fileDescriptors;\n },\n\n // Allows camera access on either the default or an extra button for iOS devices.\n _handleCameraAccess: function() {\n if (this._options.camera.ios && qq.ios()) {\n var acceptIosCamera = \"image/*;capture=camera\",\n button = this._options.camera.button,\n buttonId = button ? this._getButtonId(button) : this._defaultButtonId,\n optionRoot = this._options;\n\n // If we are not targeting the default button, it is an \"extra\" button\n if (buttonId && buttonId !== this._defaultButtonId) {\n optionRoot = this._extraButtonSpecs[buttonId];\n }\n\n // Camera access won't work in iOS if the `multiple` attribute is present on the file input\n optionRoot.multiple = false;\n\n // update the options\n if (optionRoot.validation.acceptFiles === null) {\n optionRoot.validation.acceptFiles = acceptIosCamera;\n }\n else {\n optionRoot.validation.acceptFiles += \",\" + acceptIosCamera;\n }\n\n // update the already-created button\n qq.each(this._buttons, function(idx, button) {\n if (button.getButtonId() === buttonId) {\n button.setMultiple(optionRoot.multiple);\n button.setAcceptFiles(optionRoot.acceptFiles);\n\n return false;\n }\n });\n }\n },\n\n _handleCheckedCallback: function(details) {\n var self = this,\n callbackRetVal = details.callback();\n\n if (qq.isGenericPromise(callbackRetVal)) {\n this.log(details.name + \" - waiting for \" + details.name + \" promise to be fulfilled for \" + details.identifier);\n return callbackRetVal.then(\n function(successParam) {\n self.log(details.name + \" promise success for \" + details.identifier);\n details.onSuccess(successParam);\n },\n function() {\n if (details.onFailure) {\n self.log(details.name + \" promise failure for \" + details.identifier);\n details.onFailure();\n }\n else {\n self.log(details.name + \" promise failure for \" + details.identifier);\n }\n });\n }\n\n if (callbackRetVal !== false) {\n details.onSuccess(callbackRetVal);\n }\n else {\n if (details.onFailure) {\n this.log(details.name + \" - return value was 'false' for \" + details.identifier + \". Invoking failure callback.\");\n details.onFailure();\n }\n else {\n this.log(details.name + \" - return value was 'false' for \" + details.identifier + \". Will not proceed.\");\n }\n }\n\n return callbackRetVal;\n },\n\n // Updates internal state when a new file has been received, and adds it along with its ID to a passed array.\n _handleNewFile: function(file, batchId, newFileWrapperList) {\n var self = this,\n uuid = qq.getUniqueId(),\n size = -1,\n name = qq.getFilename(file),\n actualFile = file.blob || file,\n handler = this._customNewFileHandler ?\n this._customNewFileHandler :\n qq.bind(self._handleNewFileGeneric, self);\n\n if (!qq.isInput(actualFile) && actualFile.size >= 0) {\n size = actualFile.size;\n }\n\n handler(actualFile, name, uuid, size, newFileWrapperList, batchId, this._options.request.uuidName, {\n uploadData: self._uploadData,\n paramsStore: self._paramsStore,\n addFileToHandler: function(id, file) {\n self._handler.add(id, file);\n self._netUploadedOrQueued++;\n self._trackButton(id);\n }\n });\n },\n\n _handleNewFileGeneric: function(file, name, uuid, size, fileList, batchId) {\n var id = this._uploadData.addFile({\n uuid: uuid,\n name: name,\n size: size,\n batchId: batchId,\n file: file\n });\n\n this._handler.add(id, file);\n\n this._trackButton(id);\n\n this._netUploadedOrQueued++;\n\n fileList.push({id: id, file: file});\n },\n\n _handlePasteSuccess: function(blob, extSuppliedName) {\n var extension = blob.type.split(\"/\")[1],\n name = extSuppliedName;\n\n /*jshint eqeqeq: true, eqnull: true*/\n if (name == null) {\n name = this._options.paste.defaultName;\n }\n\n name += \".\" + extension;\n\n this.addFiles({\n name: name,\n blob: blob\n });\n },\n\n _handleDeleteSuccess: function(id) {\n if (this.getUploads({id: id}).status !== qq.status.DELETED) {\n var name = this.getName(id);\n\n this._netUploadedOrQueued--;\n this._netUploaded--;\n this._handler.expunge(id);\n this._uploadData.setStatus(id, qq.status.DELETED);\n this.log(\"Delete request for '\" + name + \"' has succeeded.\");\n }\n },\n\n _handleDeleteFailed: function(id, xhrOrXdr) {\n var name = this.getName(id);\n\n this._uploadData.setStatus(id, qq.status.DELETE_FAILED);\n this.log(\"Delete request for '\" + name + \"' has failed.\", \"error\");\n\n // Check first if xhrOrXdr is actually passed or valid\n // For error reporting, we only have access to the response status if this is not\n // an `XDomainRequest`.\n if (!xhrOrXdr || xhrOrXdr.withCredentials === undefined) {\n this._options.callbacks.onError(id, name, \"Delete request failed\", xhrOrXdr);\n }\n else {\n this._options.callbacks.onError(id, name, \"Delete request failed with response code \" + xhrOrXdr.status, xhrOrXdr);\n }\n },\n\n // Creates an extra button element\n _initExtraButton: function(spec) {\n var button = this._createUploadButton({\n accept: spec.validation.acceptFiles,\n allowedExtensions: spec.validation.allowedExtensions,\n element: spec.element,\n folders: spec.folders,\n multiple: spec.multiple,\n title: spec.fileInputTitle\n });\n\n this._extraButtonSpecs[button.getButtonId()] = spec;\n },\n\n _initFormSupportAndParams: function() {\n this._formSupport = qq.FormSupport && new qq.FormSupport(\n this._options.form, qq.bind(this.uploadStoredFiles, this), qq.bind(this.log, this)\n );\n\n if (this._formSupport && this._formSupport.attachedToForm) {\n this._paramsStore = this._createStore(\n this._options.request.params, this._formSupport.getFormInputsAsObject\n );\n\n this._options.autoUpload = this._formSupport.newAutoUpload;\n if (this._formSupport.newEndpoint) {\n this._options.request.endpoint = this._formSupport.newEndpoint;\n }\n }\n else {\n this._paramsStore = this._createStore(this._options.request.params);\n }\n },\n\n _isDeletePossible: function() {\n if (!qq.DeleteFileAjaxRequester || !this._options.deleteFile.enabled) {\n return false;\n }\n\n if (this._options.cors.expected) {\n if (qq.supportedFeatures.deleteFileCorsXhr) {\n return true;\n }\n\n if (qq.supportedFeatures.deleteFileCorsXdr && this._options.cors.allowXdr) {\n return true;\n }\n\n return false;\n }\n\n return true;\n },\n\n _isAllowedExtension: function(allowed, fileName) {\n var valid = false;\n\n if (!allowed.length) {\n return true;\n }\n\n qq.each(allowed, function(idx, allowedExt) {\n /**\n * If an argument is not a string, ignore it. Added when a possible issue with MooTools hijacking the\n * `allowedExtensions` array was discovered. See case #735 in the issue tracker for more details.\n */\n if (qq.isString(allowedExt)) {\n /*jshint eqeqeq: true, eqnull: true*/\n var extRegex = new RegExp(\"\\\\.\" + allowedExt + \"$\", \"i\");\n\n if (fileName.match(extRegex) != null) {\n valid = true;\n return false;\n }\n }\n });\n\n return valid;\n },\n\n /**\n * Constructs and returns a message that describes an item/file error. Also calls `onError` callback.\n *\n * @param code REQUIRED - a code that corresponds to a stock message describing this type of error\n * @param maybeNameOrNames names of the items that have failed, if applicable\n * @param item `File`, `Blob`, or ` `\n * @private\n */\n _itemError: function(code, maybeNameOrNames, item) {\n var message = this._options.messages[code],\n allowedExtensions = [],\n names = [].concat(maybeNameOrNames),\n name = names[0],\n buttonId = this._getButtonId(item),\n validationBase = this._getValidationBase(buttonId),\n extensionsForMessage, placeholderMatch;\n\n function r(name, replacement) { message = message.replace(name, replacement); }\n\n qq.each(validationBase.allowedExtensions, function(idx, allowedExtension) {\n /**\n * If an argument is not a string, ignore it. Added when a possible issue with MooTools hijacking the\n * `allowedExtensions` array was discovered. See case #735 in the issue tracker for more details.\n */\n if (qq.isString(allowedExtension)) {\n allowedExtensions.push(allowedExtension);\n }\n });\n\n extensionsForMessage = allowedExtensions.join(\", \").toLowerCase();\n\n r(\"{file}\", this._options.formatFileName(name));\n r(\"{extensions}\", extensionsForMessage);\n r(\"{sizeLimit}\", this._formatSize(validationBase.sizeLimit));\n r(\"{minSizeLimit}\", this._formatSize(validationBase.minSizeLimit));\n\n placeholderMatch = message.match(/(\\{\\w+\\})/g);\n if (placeholderMatch !== null) {\n qq.each(placeholderMatch, function(idx, placeholder) {\n r(placeholder, names[idx]);\n });\n }\n\n this._options.callbacks.onError(null, name, message, undefined);\n\n return message;\n },\n\n /**\n * Conditionally orders a manual retry of a failed upload.\n *\n * @param id File ID of the failed upload\n * @param callback Optional callback to invoke if a retry is prudent.\n * In lieu of asking the upload handler to retry.\n * @returns {boolean} true if a manual retry will occur\n * @private\n */\n _manualRetry: function(id, callback) {\n if (this._onBeforeManualRetry(id)) {\n this._netUploadedOrQueued++;\n this._uploadData.setStatus(id, qq.status.UPLOAD_RETRYING);\n\n if (callback) {\n callback(id);\n }\n else {\n this._handler.retry(id);\n }\n\n return true;\n }\n },\n\n _maybeAllComplete: function(id, status) {\n var self = this,\n notFinished = this._getNotFinished();\n\n if (status === qq.status.UPLOAD_SUCCESSFUL) {\n this._succeededSinceLastAllComplete.push(id);\n }\n else if (status === qq.status.UPLOAD_FAILED) {\n this._failedSinceLastAllComplete.push(id);\n }\n\n if (notFinished === 0 &&\n (this._succeededSinceLastAllComplete.length || this._failedSinceLastAllComplete.length)) {\n // Attempt to ensure onAllComplete is not invoked before other callbacks, such as onCancel & onComplete\n setTimeout(function() {\n self._onAllComplete(self._succeededSinceLastAllComplete, self._failedSinceLastAllComplete);\n }, 0);\n }\n },\n\n _maybeHandleIos8SafariWorkaround: function() {\n var self = this;\n\n if (this._options.workarounds.ios8SafariUploads && qq.ios800() && qq.iosSafari()) {\n setTimeout(function() {\n window.alert(self._options.messages.unsupportedBrowserIos8Safari);\n }, 0);\n throw new qq.Error(this._options.messages.unsupportedBrowserIos8Safari);\n }\n },\n\n _maybeParseAndSendUploadError: function(id, name, response, xhr) {\n // Assuming no one will actually set the response code to something other than 200\n // and still set 'success' to true...\n if (!response.success) {\n if (xhr && xhr.status !== 200 && !response.error) {\n this._options.callbacks.onError(id, name, \"XHR returned response code \" + xhr.status, xhr);\n }\n else {\n var errorReason = response.error ? response.error : this._options.text.defaultResponseError;\n this._options.callbacks.onError(id, name, errorReason, xhr);\n }\n }\n },\n\n _maybeProcessNextItemAfterOnValidateCallback: function(validItem, items, index, params, endpoint) {\n var self = this;\n\n if (items.length > index) {\n if (validItem || !this._options.validation.stopOnFirstInvalidFile) {\n //use setTimeout to prevent a stack overflow with a large number of files in the batch & non-promissory callbacks\n setTimeout(function() {\n var validationDescriptor = self._getValidationDescriptor(items[index]),\n buttonId = self._getButtonId(items[index].file),\n button = self._getButton(buttonId);\n\n self._handleCheckedCallback({\n name: \"onValidate\",\n callback: qq.bind(self._options.callbacks.onValidate, self, validationDescriptor, button),\n onSuccess: qq.bind(self._onValidateCallbackSuccess, self, items, index, params, endpoint),\n onFailure: qq.bind(self._onValidateCallbackFailure, self, items, index, params, endpoint),\n identifier: \"Item '\" + validationDescriptor.name + \"', size: \" + validationDescriptor.size\n });\n }, 0);\n }\n else if (!validItem) {\n for (; index < items.length; index++) {\n self._fileOrBlobRejected(items[index].id);\n }\n }\n }\n },\n\n _onAllComplete: function(successful, failed) {\n this._totalProgress && this._totalProgress.onAllComplete(successful, failed, this._preventRetries);\n\n this._options.callbacks.onAllComplete(qq.extend([], successful), qq.extend([], failed));\n\n this._succeededSinceLastAllComplete = [];\n this._failedSinceLastAllComplete = [];\n },\n\n /**\n * Attempt to automatically retry a failed upload.\n *\n * @param id The file ID of the failed upload\n * @param name The name of the file associated with the failed upload\n * @param responseJSON Response from the server, parsed into a javascript object\n * @param xhr Ajax transport used to send the failed request\n * @param callback Optional callback to be invoked if a retry is prudent.\n * Invoked in lieu of asking the upload handler to retry.\n * @returns {boolean} true if an auto-retry will occur\n * @private\n */\n _onAutoRetry: function(id, name, responseJSON, xhr, callback) {\n var self = this;\n\n self._preventRetries[id] = responseJSON[self._options.retry.preventRetryResponseProperty];\n\n if (self._shouldAutoRetry(id)) {\n var retryWaitPeriod = self._options.retry.autoAttemptDelay * 1000;\n\n self._maybeParseAndSendUploadError.apply(self, arguments);\n self._options.callbacks.onAutoRetry(id, name, self._autoRetries[id]);\n self._onBeforeAutoRetry(id, name);\n\n self._uploadData.setStatus(id, qq.status.UPLOAD_RETRYING);\n self._retryTimeouts[id] = setTimeout(function() {\n self.log(\"Starting retry for \" + name + \"...\");\n\n if (callback) {\n callback(id);\n }\n else {\n self._handler.retry(id);\n }\n }, retryWaitPeriod);\n\n return true;\n }\n },\n\n _onBeforeAutoRetry: function(id, name) {\n this.log(\"Waiting \" + this._options.retry.autoAttemptDelay + \" seconds before retrying \" + name + \"...\");\n },\n\n //return false if we should not attempt the requested retry\n _onBeforeManualRetry: function(id) {\n var itemLimit = this._currentItemLimit,\n fileName;\n\n if (this._preventRetries[id]) {\n this.log(\"Retries are forbidden for id \" + id, \"warn\");\n return false;\n }\n else if (this._handler.isValid(id)) {\n fileName = this.getName(id);\n\n if (this._options.callbacks.onManualRetry(id, fileName) === false) {\n return false;\n }\n\n if (itemLimit > 0 && this._netUploadedOrQueued + 1 > itemLimit) {\n this._itemError(\"retryFailTooManyItems\");\n return false;\n }\n\n this.log(\"Retrying upload for '\" + fileName + \"' (id: \" + id + \")...\");\n return true;\n }\n else {\n this.log(\"'\" + id + \"' is not a valid file ID\", \"error\");\n return false;\n }\n },\n\n _onCancel: function(id, name) {\n this._netUploadedOrQueued--;\n\n clearTimeout(this._retryTimeouts[id]);\n\n var storedItemIndex = qq.indexOf(this._storedIds, id);\n if (!this._options.autoUpload && storedItemIndex >= 0) {\n this._storedIds.splice(storedItemIndex, 1);\n }\n\n this._uploadData.setStatus(id, qq.status.CANCELED);\n },\n\n _onComplete: function(id, name, result, xhr) {\n if (!result.success) {\n this._netUploadedOrQueued--;\n this._uploadData.setStatus(id, qq.status.UPLOAD_FAILED);\n\n if (result[this._options.retry.preventRetryResponseProperty] === true) {\n this._preventRetries[id] = true;\n }\n }\n else {\n if (result.thumbnailUrl) {\n this._thumbnailUrls[id] = result.thumbnailUrl;\n }\n\n this._netUploaded++;\n this._uploadData.setStatus(id, qq.status.UPLOAD_SUCCESSFUL);\n }\n\n this._maybeParseAndSendUploadError(id, name, result, xhr);\n\n return result.success ? true : false;\n },\n\n _onDelete: function(id) {\n this._uploadData.setStatus(id, qq.status.DELETING);\n },\n\n _onDeleteComplete: function(id, xhrOrXdr, isError) {\n var name = this.getName(id);\n\n if (isError) {\n this._handleDeleteFailed(id, xhrOrXdr);\n }\n else {\n this._handleDeleteSuccess(id);\n }\n },\n\n _onInputChange: function(input) {\n var fileIndex;\n\n if (qq.supportedFeatures.ajaxUploading) {\n for (fileIndex = 0; fileIndex < input.files.length; fileIndex++) {\n this._annotateWithButtonId(input.files[fileIndex], input);\n }\n\n this.addFiles(input.files);\n }\n // Android 2.3.x will fire `onchange` even if no file has been selected\n else if (input.value.length > 0) {\n this.addFiles(input);\n }\n\n qq.each(this._buttons, function(idx, button) {\n button.reset();\n });\n },\n\n _onProgress: function(id, name, loaded, total) {\n this._totalProgress && this._totalProgress.onIndividualProgress(id, loaded, total);\n },\n\n _onSubmit: function(id, name) {\n //nothing to do yet in core uploader\n },\n\n _onSubmitCallbackSuccess: function(id, name) {\n this._onSubmit.apply(this, arguments);\n this._uploadData.setStatus(id, qq.status.SUBMITTED);\n this._onSubmitted.apply(this, arguments);\n\n if (this._options.autoUpload) {\n this._options.callbacks.onSubmitted.apply(this, arguments);\n this._uploadFile(id);\n }\n else {\n this._storeForLater(id);\n this._options.callbacks.onSubmitted.apply(this, arguments);\n }\n },\n\n _onSubmitDelete: function(id, onSuccessCallback, additionalMandatedParams) {\n var uuid = this.getUuid(id),\n adjustedOnSuccessCallback;\n\n if (onSuccessCallback) {\n adjustedOnSuccessCallback = qq.bind(onSuccessCallback, this, id, uuid, additionalMandatedParams);\n }\n\n if (this._isDeletePossible()) {\n this._handleCheckedCallback({\n name: \"onSubmitDelete\",\n callback: qq.bind(this._options.callbacks.onSubmitDelete, this, id),\n onSuccess: adjustedOnSuccessCallback ||\n qq.bind(this._deleteHandler.sendDelete, this, id, uuid, additionalMandatedParams),\n identifier: id\n });\n return true;\n }\n else {\n this.log(\"Delete request ignored for ID \" + id + \", delete feature is disabled or request not possible \" +\n \"due to CORS on a user agent that does not support pre-flighting.\", \"warn\");\n return false;\n }\n },\n\n _onSubmitted: function(id) {\n //nothing to do in the base uploader\n },\n\n _onTotalProgress: function(loaded, total) {\n this._options.callbacks.onTotalProgress(loaded, total);\n },\n\n _onUploadPrep: function(id) {\n // nothing to do in the core uploader for now\n },\n\n _onUpload: function(id, name) {\n this._uploadData.setStatus(id, qq.status.UPLOADING);\n },\n\n _onUploadChunk: function(id, chunkData) {\n //nothing to do in the base uploader\n },\n\n _onUploadChunkSuccess: function(id, chunkData) {\n if (!this._preventRetries[id] && this._options.retry.enableAuto) {\n this._autoRetries[id] = 0;\n }\n },\n\n _onUploadStatusChange: function(id, oldStatus, newStatus) {\n // Make sure a \"queued\" retry attempt is canceled if the upload has been paused\n if (newStatus === qq.status.PAUSED) {\n clearTimeout(this._retryTimeouts[id]);\n }\n },\n\n _onValidateBatchCallbackFailure: function(fileWrappers) {\n var self = this;\n\n qq.each(fileWrappers, function(idx, fileWrapper) {\n self._fileOrBlobRejected(fileWrapper.id);\n });\n },\n\n _onValidateBatchCallbackSuccess: function(validationDescriptors, items, params, endpoint, button) {\n var errorMessage,\n itemLimit = this._currentItemLimit,\n proposedNetFilesUploadedOrQueued = this._netUploadedOrQueued;\n\n if (itemLimit === 0 || proposedNetFilesUploadedOrQueued <= itemLimit) {\n if (items.length > 0) {\n this._handleCheckedCallback({\n name: \"onValidate\",\n callback: qq.bind(this._options.callbacks.onValidate, this, validationDescriptors[0], button),\n onSuccess: qq.bind(this._onValidateCallbackSuccess, this, items, 0, params, endpoint),\n onFailure: qq.bind(this._onValidateCallbackFailure, this, items, 0, params, endpoint),\n identifier: \"Item '\" + items[0].file.name + \"', size: \" + items[0].file.size\n });\n }\n else {\n this._itemError(\"noFilesError\");\n }\n }\n else {\n this._onValidateBatchCallbackFailure(items);\n errorMessage = this._options.messages.tooManyItemsError\n .replace(/\\{netItems\\}/g, proposedNetFilesUploadedOrQueued)\n .replace(/\\{itemLimit\\}/g, itemLimit);\n this._batchError(errorMessage);\n }\n },\n\n _onValidateCallbackFailure: function(items, index, params, endpoint) {\n var nextIndex = index + 1;\n\n this._fileOrBlobRejected(items[index].id, items[index].file.name);\n\n this._maybeProcessNextItemAfterOnValidateCallback(false, items, nextIndex, params, endpoint);\n },\n\n _onValidateCallbackSuccess: function(items, index, params, endpoint) {\n var self = this,\n nextIndex = index + 1,\n validationDescriptor = this._getValidationDescriptor(items[index]);\n\n this._validateFileOrBlobData(items[index], validationDescriptor)\n .then(\n function() {\n self._upload(items[index].id, params, endpoint);\n self._maybeProcessNextItemAfterOnValidateCallback(true, items, nextIndex, params, endpoint);\n },\n function() {\n self._maybeProcessNextItemAfterOnValidateCallback(false, items, nextIndex, params, endpoint);\n }\n );\n },\n\n _prepareItemsForUpload: function(items, params, endpoint) {\n if (items.length === 0) {\n this._itemError(\"noFilesError\");\n return;\n }\n\n var validationDescriptors = this._getValidationDescriptors(items),\n buttonId = this._getButtonId(items[0].file),\n button = this._getButton(buttonId);\n\n this._handleCheckedCallback({\n name: \"onValidateBatch\",\n callback: qq.bind(this._options.callbacks.onValidateBatch, this, validationDescriptors, button),\n onSuccess: qq.bind(this._onValidateBatchCallbackSuccess, this, validationDescriptors, items, params, endpoint, button),\n onFailure: qq.bind(this._onValidateBatchCallbackFailure, this, items),\n identifier: \"batch validation\"\n });\n },\n\n _preventLeaveInProgress: function() {\n var self = this;\n\n this._disposeSupport.attach(window, \"beforeunload\", function(e) {\n if (self.getInProgress()) {\n e = e || window.event;\n // for ie, ff\n e.returnValue = self._options.messages.onLeave;\n // for webkit\n return self._options.messages.onLeave;\n }\n });\n },\n\n // Attempts to refresh session data only if the `qq.Session` module exists\n // and a session endpoint has been specified. The `onSessionRequestComplete`\n // callback will be invoked once the refresh is complete.\n _refreshSessionData: function() {\n var self = this,\n options = this._options.session;\n\n /* jshint eqnull:true */\n if (qq.Session && this._options.session.endpoint != null) {\n if (!this._session) {\n qq.extend(options, {cors: this._options.cors});\n\n options.log = qq.bind(this.log, this);\n options.addFileRecord = qq.bind(this._addCannedFile, this);\n\n this._session = new qq.Session(options);\n }\n\n setTimeout(function() {\n self._session.refresh().then(function(response, xhrOrXdr) {\n self._sessionRequestComplete();\n self._options.callbacks.onSessionRequestComplete(response, true, xhrOrXdr);\n\n }, function(response, xhrOrXdr) {\n\n self._options.callbacks.onSessionRequestComplete(response, false, xhrOrXdr);\n });\n }, 0);\n }\n },\n\n _sessionRequestComplete: function() {},\n\n _setSize: function(id, newSize) {\n this._uploadData.updateSize(id, newSize);\n this._totalProgress && this._totalProgress.onNewSize(id);\n },\n\n _shouldAutoRetry: function(id) {\n var uploadData = this._uploadData.retrieve({id: id});\n\n /*jshint laxbreak: true */\n if (!this._preventRetries[id]\n && this._options.retry.enableAuto\n && uploadData.status !== qq.status.PAUSED) {\n\n if (this._autoRetries[id] === undefined) {\n this._autoRetries[id] = 0;\n }\n\n if (this._autoRetries[id] < this._options.retry.maxAutoAttempts) {\n this._autoRetries[id] += 1;\n return true;\n }\n }\n\n return false;\n },\n\n _storeForLater: function(id) {\n this._storedIds.push(id);\n },\n\n // Maps a file with the button that was used to select it.\n _trackButton: function(id) {\n var buttonId;\n\n if (qq.supportedFeatures.ajaxUploading) {\n buttonId = this._handler.getFile(id).qqButtonId;\n }\n else {\n buttonId = this._getButtonId(this._handler.getInput(id));\n }\n\n if (buttonId) {\n this._buttonIdsForFileIds[id] = buttonId;\n }\n },\n\n _updateFormSupportAndParams: function(formElementOrId) {\n this._options.form.element = formElementOrId;\n\n this._formSupport = qq.FormSupport && new qq.FormSupport(\n this._options.form, qq.bind(this.uploadStoredFiles, this), qq.bind(this.log, this)\n );\n\n if (this._formSupport && this._formSupport.attachedToForm) {\n this._paramsStore.addReadOnly(null, this._formSupport.getFormInputsAsObject);\n\n this._options.autoUpload = this._formSupport.newAutoUpload;\n if (this._formSupport.newEndpoint) {\n this.setEndpoint(this._formSupport.newEndpoint);\n }\n }\n },\n\n _upload: function(id, params, endpoint) {\n var name = this.getName(id);\n\n if (params) {\n this.setParams(params, id);\n }\n\n if (endpoint) {\n this.setEndpoint(endpoint, id);\n }\n\n this._handleCheckedCallback({\n name: \"onSubmit\",\n callback: qq.bind(this._options.callbacks.onSubmit, this, id, name),\n onSuccess: qq.bind(this._onSubmitCallbackSuccess, this, id, name),\n onFailure: qq.bind(this._fileOrBlobRejected, this, id, name),\n identifier: id\n });\n },\n\n _uploadFile: function(id) {\n if (!this._handler.upload(id)) {\n this._uploadData.setStatus(id, qq.status.QUEUED);\n }\n },\n\n _uploadStoredFiles: function() {\n var idToUpload, stillSubmitting,\n self = this;\n\n while (this._storedIds.length) {\n idToUpload = this._storedIds.shift();\n this._uploadFile(idToUpload);\n }\n\n // If we are still waiting for some files to clear validation, attempt to upload these again in a bit\n stillSubmitting = this.getUploads({status: qq.status.SUBMITTING}).length;\n if (stillSubmitting) {\n qq.log(\"Still waiting for \" + stillSubmitting + \" files to clear submit queue. Will re-parse stored IDs array shortly.\");\n setTimeout(function() {\n self._uploadStoredFiles();\n }, 1000);\n }\n },\n\n /**\n * Performs some internal validation checks on an item, defined in the `validation` option.\n *\n * @param fileWrapper Wrapper containing a `file` along with an `id`\n * @param validationDescriptor Normalized information about the item (`size`, `name`).\n * @returns qq.Promise with appropriate callbacks invoked depending on the validity of the file\n * @private\n */\n _validateFileOrBlobData: function(fileWrapper, validationDescriptor) {\n var self = this,\n file = (function() {\n if (fileWrapper.file instanceof qq.BlobProxy) {\n return fileWrapper.file.referenceBlob;\n }\n return fileWrapper.file;\n }()),\n name = validationDescriptor.name,\n size = validationDescriptor.size,\n buttonId = this._getButtonId(fileWrapper.file),\n validationBase = this._getValidationBase(buttonId),\n validityChecker = new qq.Promise();\n\n validityChecker.then(\n function() {},\n function() {\n self._fileOrBlobRejected(fileWrapper.id, name);\n });\n\n if (qq.isFileOrInput(file) && !this._isAllowedExtension(validationBase.allowedExtensions, name)) {\n this._itemError(\"typeError\", name, file);\n return validityChecker.failure();\n }\n\n if (!this._options.validation.allowEmpty && size === 0) {\n this._itemError(\"emptyError\", name, file);\n return validityChecker.failure();\n }\n\n if (size > 0 && validationBase.sizeLimit && size > validationBase.sizeLimit) {\n this._itemError(\"sizeError\", name, file);\n return validityChecker.failure();\n }\n\n if (size > 0 && size < validationBase.minSizeLimit) {\n this._itemError(\"minSizeError\", name, file);\n return validityChecker.failure();\n }\n\n if (qq.ImageValidation && qq.supportedFeatures.imagePreviews && qq.isFile(file)) {\n new qq.ImageValidation(file, qq.bind(self.log, self)).validate(validationBase.image).then(\n validityChecker.success,\n function(errorCode) {\n self._itemError(errorCode + \"ImageError\", name, file);\n validityChecker.failure();\n }\n );\n }\n else {\n validityChecker.success();\n }\n\n return validityChecker;\n },\n\n _wrapCallbacks: function() {\n var self, safeCallback, prop;\n\n self = this;\n\n safeCallback = function(name, callback, args) {\n var errorMsg;\n\n try {\n return callback.apply(self, args);\n }\n catch (exception) {\n errorMsg = exception.message || exception.toString();\n self.log(\"Caught exception in '\" + name + \"' callback - \" + errorMsg, \"error\");\n }\n };\n\n /* jshint forin: false, loopfunc: true */\n for (prop in this._options.callbacks) {\n (function() {\n var callbackName, callbackFunc;\n callbackName = prop;\n callbackFunc = self._options.callbacks[callbackName];\n self._options.callbacks[callbackName] = function() {\n return safeCallback(callbackName, callbackFunc, arguments);\n };\n }());\n }\n }\n };\n}());\n","/*globals qq*/\n(function() {\n \"use strict\";\n\n qq.FineUploaderBasic = function(o) {\n var self = this;\n\n // These options define FineUploaderBasic mode.\n this._options = {\n debug: false,\n button: null,\n multiple: true,\n maxConnections: 3,\n disableCancelForFormUploads: false,\n autoUpload: true,\n warnBeforeUnload: true,\n\n request: {\n customHeaders: {},\n endpoint: \"/server/upload\",\n filenameParam: \"qqfilename\",\n forceMultipart: true,\n inputName: \"qqfile\",\n method: \"POST\",\n omitDefaultParams: false,\n params: {},\n paramsInBody: true,\n requireSuccessJson: true,\n totalFileSizeName: \"qqtotalfilesize\",\n uuidName: \"qquuid\"\n },\n\n validation: {\n allowedExtensions: [],\n sizeLimit: 0,\n minSizeLimit: 0,\n itemLimit: 0,\n stopOnFirstInvalidFile: true,\n acceptFiles: null,\n image: {\n maxHeight: 0,\n maxWidth: 0,\n minHeight: 0,\n minWidth: 0\n },\n allowEmpty: false\n },\n\n callbacks: {\n onSubmit: function(id, name) {},\n onSubmitted: function(id, name) {},\n onComplete: function(id, name, responseJSON, maybeXhr) {},\n onAllComplete: function(successful, failed) {},\n onCancel: function(id, name) {},\n onUpload: function(id, name) {},\n onUploadChunk: function(id, name, chunkData) {},\n onUploadChunkSuccess: function(id, chunkData, responseJSON, xhr) {},\n onResume: function(id, fileName, chunkData, customResumeData) {},\n onProgress: function(id, name, loaded, total) {},\n onTotalProgress: function(loaded, total) {},\n onError: function(id, name, reason, maybeXhrOrXdr) {},\n onAutoRetry: function(id, name, attemptNumber) {},\n onManualRetry: function(id, name) {},\n onValidateBatch: function(fileOrBlobData) {},\n onValidate: function(fileOrBlobData) {},\n onSubmitDelete: function(id) {},\n onDelete: function(id) {},\n onDeleteComplete: function(id, xhrOrXdr, isError) {},\n onPasteReceived: function(blob) {},\n onStatusChange: function(id, oldStatus, newStatus) {},\n onSessionRequestComplete: function(response, success, xhrOrXdr) {}\n },\n\n messages: {\n typeError: \"{file} has an invalid extension. Valid extension(s): {extensions}.\",\n sizeError: \"{file} is too large, maximum file size is {sizeLimit}.\",\n minSizeError: \"{file} is too small, minimum file size is {minSizeLimit}.\",\n emptyError: \"{file} is empty, please select files again without it.\",\n noFilesError: \"No files to upload.\",\n tooManyItemsError: \"Too many items ({netItems}) would be uploaded. Item limit is {itemLimit}.\",\n maxHeightImageError: \"Image is too tall.\",\n maxWidthImageError: \"Image is too wide.\",\n minHeightImageError: \"Image is not tall enough.\",\n minWidthImageError: \"Image is not wide enough.\",\n retryFailTooManyItems: \"Retry failed - you have reached your file limit.\",\n onLeave: \"The files are being uploaded, if you leave now the upload will be canceled.\",\n unsupportedBrowserIos8Safari: \"Unrecoverable error - this browser does not permit file uploading of any kind due to serious bugs in iOS8 Safari. Please use iOS8 Chrome until Apple fixes these issues.\"\n },\n\n retry: {\n enableAuto: false,\n maxAutoAttempts: 3,\n autoAttemptDelay: 5,\n preventRetryResponseProperty: \"preventRetry\"\n },\n\n classes: {\n buttonHover: \"qq-upload-button-hover\",\n buttonFocus: \"qq-upload-button-focus\"\n },\n\n chunking: {\n enabled: false,\n concurrent: {\n enabled: false\n },\n mandatory: false,\n paramNames: {\n partIndex: \"qqpartindex\",\n partByteOffset: \"qqpartbyteoffset\",\n chunkSize: \"qqchunksize\",\n totalFileSize: \"qqtotalfilesize\",\n totalParts: \"qqtotalparts\"\n },\n partSize: function(id) {\n return 2000000;\n },\n // only relevant for traditional endpoints, only required when concurrent.enabled === true\n success: {\n endpoint: null,\n\n headers: function(id) {\n return null;\n },\n\n jsonPayload: false,\n\n method: \"POST\",\n\n params: function(id) {\n return null;\n },\n\n resetOnStatus: []\n }\n },\n\n resume: {\n enabled: false,\n recordsExpireIn: 7, //days\n paramNames: {\n resuming: \"qqresume\"\n },\n customKeys: function(fileId) {\n return [];\n }\n },\n\n formatFileName: function(fileOrBlobName) {\n return fileOrBlobName;\n },\n\n text: {\n defaultResponseError: \"Upload failure reason unknown\",\n fileInputTitle: \"file input\",\n sizeSymbols: [\"kB\", \"MB\", \"GB\", \"TB\", \"PB\", \"EB\"]\n },\n\n deleteFile: {\n enabled: false,\n method: \"DELETE\",\n endpoint: \"/server/upload\",\n customHeaders: {},\n params: {}\n },\n\n cors: {\n expected: false,\n sendCredentials: false,\n allowXdr: false\n },\n\n blobs: {\n defaultName: \"misc_data\"\n },\n\n paste: {\n targetElement: null,\n defaultName: \"pasted_image\"\n },\n\n camera: {\n ios: false,\n\n // if ios is true: button is null means target the default button, otherwise target the button specified\n button: null\n },\n\n // This refers to additional upload buttons to be handled by Fine Uploader.\n // Each element is an object, containing `element` as the only required\n // property. The `element` must be a container that will ultimately\n // contain an invisible ` ` created by Fine Uploader.\n // Optional properties of each object include `multiple`, `validation`,\n // and `folders`.\n extraButtons: [],\n\n // Depends on the session module. Used to query the server for an initial file list\n // during initialization and optionally after a `reset`.\n session: {\n endpoint: null,\n params: {},\n customHeaders: {},\n refreshOnReset: true\n },\n\n // Send parameters associated with an existing form along with the files\n form: {\n // Element ID, HTMLElement, or null\n element: \"qq-form\",\n\n // Overrides the base `autoUpload`, unless `element` is null.\n autoUpload: false,\n\n // true = upload files on form submission (and squelch submit event)\n interceptSubmit: true\n },\n\n // scale images client side, upload a new file for each scaled version\n scaling: {\n customResizer: null,\n\n // send the original file as well\n sendOriginal: true,\n\n // fox orientation for scaled images\n orient: true,\n\n // If null, scaled image type will match reference image type. This value will be referred to\n // for any size record that does not specific a type.\n defaultType: null,\n\n defaultQuality: 80,\n\n failureText: \"Failed to scale\",\n\n includeExif: false,\n\n // metadata about each requested scaled version\n sizes: []\n },\n\n workarounds: {\n iosEmptyVideos: true,\n ios8SafariUploads: true,\n ios8BrowserCrash: false\n }\n };\n\n // Replace any default options with user defined ones\n qq.extend(this._options, o, true);\n\n this._buttons = [];\n this._extraButtonSpecs = {};\n this._buttonIdsForFileIds = [];\n\n this._wrapCallbacks();\n this._disposeSupport = new qq.DisposeSupport();\n\n this._storedIds = [];\n this._autoRetries = [];\n this._retryTimeouts = [];\n this._preventRetries = [];\n this._thumbnailUrls = [];\n\n this._netUploadedOrQueued = 0;\n this._netUploaded = 0;\n this._uploadData = this._createUploadDataTracker();\n\n this._initFormSupportAndParams();\n\n this._customHeadersStore = this._createStore(this._options.request.customHeaders);\n this._deleteFileCustomHeadersStore = this._createStore(this._options.deleteFile.customHeaders);\n\n this._deleteFileParamsStore = this._createStore(this._options.deleteFile.params);\n\n this._endpointStore = this._createStore(this._options.request.endpoint);\n this._deleteFileEndpointStore = this._createStore(this._options.deleteFile.endpoint);\n\n this._handler = this._createUploadHandler();\n\n this._deleteHandler = qq.DeleteFileAjaxRequester && this._createDeleteHandler();\n\n if (this._options.button) {\n this._defaultButtonId = this._createUploadButton({\n element: this._options.button,\n title: this._options.text.fileInputTitle\n }).getButtonId();\n }\n\n this._generateExtraButtonSpecs();\n\n this._handleCameraAccess();\n\n if (this._options.paste.targetElement) {\n if (qq.PasteSupport) {\n this._pasteHandler = this._createPasteHandler();\n }\n else {\n this.log(\"Paste support module not found\", \"error\");\n }\n }\n\n this._options.warnBeforeUnload && this._preventLeaveInProgress();\n\n this._imageGenerator = qq.ImageGenerator && new qq.ImageGenerator(qq.bind(this.log, this));\n this._refreshSessionData();\n\n this._succeededSinceLastAllComplete = [];\n this._failedSinceLastAllComplete = [];\n\n this._scaler = (qq.Scaler && new qq.Scaler(this._options.scaling, qq.bind(this.log, this))) || {};\n if (this._scaler.enabled) {\n this._customNewFileHandler = qq.bind(this._scaler.handleNewFile, this._scaler);\n }\n\n if (qq.TotalProgress && qq.supportedFeatures.progressBar) {\n this._totalProgress = new qq.TotalProgress(\n qq.bind(this._onTotalProgress, this),\n\n function(id) {\n var entry = self._uploadData.retrieve({id: id});\n return (entry && entry.size) || 0;\n }\n );\n }\n\n this._currentItemLimit = this._options.validation.itemLimit;\n\n this._customResumeDataStore = this._createStore();\n };\n\n // Define the private & public API methods.\n qq.FineUploaderBasic.prototype = qq.basePublicApi;\n qq.extend(qq.FineUploaderBasic.prototype, qq.basePrivateApi);\n}());\n","/*globals qq, XDomainRequest*/\n/** Generic class for sending non-upload ajax requests and handling the associated responses **/\nqq.AjaxRequester = function(o) {\n \"use strict\";\n\n var log, shouldParamsBeInQueryString,\n queue = [],\n requestData = {},\n options = {\n acceptHeader: null,\n validMethods: [\"PATCH\", \"POST\", \"PUT\"],\n method: \"POST\",\n contentType: \"application/x-www-form-urlencoded\",\n maxConnections: 3,\n customHeaders: {},\n endpointStore: {},\n paramsStore: {},\n mandatedParams: {},\n allowXRequestedWithAndCacheControl: true,\n successfulResponseCodes: {\n DELETE: [200, 202, 204],\n PATCH: [200, 201, 202, 203, 204],\n POST: [200, 201, 202, 203, 204],\n PUT: [200, 201, 202, 203, 204],\n GET: [200]\n },\n cors: {\n expected: false,\n sendCredentials: false\n },\n log: function(str, level) {},\n onSend: function(id) {},\n onComplete: function(id, xhrOrXdr, isError) {},\n onProgress: null\n };\n\n qq.extend(options, o);\n log = options.log;\n\n if (qq.indexOf(options.validMethods, options.method) < 0) {\n throw new Error(\"'\" + options.method + \"' is not a supported method for this type of request!\");\n }\n\n // [Simple methods](http://www.w3.org/TR/cors/#simple-method)\n // are defined by the W3C in the CORS spec as a list of methods that, in part,\n // make a CORS request eligible to be exempt from preflighting.\n function isSimpleMethod() {\n return qq.indexOf([\"GET\", \"POST\", \"HEAD\"], options.method) >= 0;\n }\n\n // [Simple headers](http://www.w3.org/TR/cors/#simple-header)\n // are defined by the W3C in the CORS spec as a list of headers that, in part,\n // make a CORS request eligible to be exempt from preflighting.\n function containsNonSimpleHeaders(headers) {\n var containsNonSimple = false;\n\n qq.each(containsNonSimple, function(idx, header) {\n if (qq.indexOf([\"Accept\", \"Accept-Language\", \"Content-Language\", \"Content-Type\"], header) < 0) {\n containsNonSimple = true;\n return false;\n }\n });\n\n return containsNonSimple;\n }\n\n function isXdr(xhr) {\n //The `withCredentials` test is a commonly accepted way to determine if XHR supports CORS.\n return options.cors.expected && xhr.withCredentials === undefined;\n }\n\n // Returns either a new `XMLHttpRequest` or `XDomainRequest` instance.\n function getCorsAjaxTransport() {\n var xhrOrXdr;\n\n if (window.XMLHttpRequest || window.ActiveXObject) {\n xhrOrXdr = qq.createXhrInstance();\n\n if (xhrOrXdr.withCredentials === undefined) {\n xhrOrXdr = new XDomainRequest();\n // Workaround for XDR bug in IE9 - https://social.msdn.microsoft.com/Forums/ie/en-US/30ef3add-767c-4436-b8a9-f1ca19b4812e/ie9-rtm-xdomainrequest-issued-requests-may-abort-if-all-event-handlers-not-specified?forum=iewebdevelopment\n xhrOrXdr.onload = function() {};\n xhrOrXdr.onerror = function() {};\n xhrOrXdr.ontimeout = function() {};\n xhrOrXdr.onprogress = function() {};\n }\n }\n\n return xhrOrXdr;\n }\n\n // Returns either a new XHR/XDR instance, or an existing one for the associated `File` or `Blob`.\n function getXhrOrXdr(id, suppliedXhr) {\n var xhrOrXdr = requestData[id] && requestData[id].xhr;\n\n if (!xhrOrXdr) {\n if (suppliedXhr) {\n xhrOrXdr = suppliedXhr;\n }\n else {\n if (options.cors.expected) {\n xhrOrXdr = getCorsAjaxTransport();\n }\n else {\n xhrOrXdr = qq.createXhrInstance();\n }\n }\n\n requestData[id].xhr = xhrOrXdr;\n }\n\n return xhrOrXdr;\n }\n\n // Removes element from queue, sends next request\n function dequeue(id) {\n var i = qq.indexOf(queue, id),\n max = options.maxConnections,\n nextId;\n\n delete requestData[id];\n queue.splice(i, 1);\n\n if (queue.length >= max && i < max) {\n nextId = queue[max - 1];\n sendRequest(nextId);\n }\n }\n\n function onComplete(id, xdrError) {\n var xhr = getXhrOrXdr(id),\n method = options.method,\n isError = xdrError === true;\n\n dequeue(id);\n\n if (isError) {\n log(method + \" request for \" + id + \" has failed\", \"error\");\n }\n else if (!isXdr(xhr) && !isResponseSuccessful(xhr.status)) {\n isError = true;\n log(method + \" request for \" + id + \" has failed - response code \" + xhr.status, \"error\");\n }\n\n options.onComplete(id, xhr, isError);\n }\n\n function getParams(id) {\n var onDemandParams = requestData[id].additionalParams,\n mandatedParams = options.mandatedParams,\n params;\n\n if (options.paramsStore.get) {\n params = options.paramsStore.get(id);\n }\n\n if (onDemandParams) {\n qq.each(onDemandParams, function(name, val) {\n params = params || {};\n params[name] = val;\n });\n }\n\n if (mandatedParams) {\n qq.each(mandatedParams, function(name, val) {\n params = params || {};\n params[name] = val;\n });\n }\n\n return params;\n }\n\n function sendRequest(id, optXhr) {\n var xhr = getXhrOrXdr(id, optXhr),\n method = options.method,\n params = getParams(id),\n payload = requestData[id].payload,\n url;\n\n options.onSend(id);\n\n url = createUrl(id, params, requestData[id].additionalQueryParams);\n\n // XDR and XHR status detection APIs differ a bit.\n if (isXdr(xhr)) {\n xhr.onload = getXdrLoadHandler(id);\n xhr.onerror = getXdrErrorHandler(id);\n }\n else {\n xhr.onreadystatechange = getXhrReadyStateChangeHandler(id);\n }\n\n registerForUploadProgress(id);\n\n // The last parameter is assumed to be ignored if we are actually using `XDomainRequest`.\n xhr.open(method, url, true);\n\n // Instruct the transport to send cookies along with the CORS request,\n // unless we are using `XDomainRequest`, which is not capable of this.\n if (options.cors.expected && options.cors.sendCredentials && !isXdr(xhr)) {\n xhr.withCredentials = true;\n }\n\n setHeaders(id);\n\n log(\"Sending \" + method + \" request for \" + id);\n\n if (payload) {\n xhr.send(payload);\n }\n else if (shouldParamsBeInQueryString || !params) {\n xhr.send();\n }\n else if (params && options.contentType && options.contentType.toLowerCase().indexOf(\"application/x-www-form-urlencoded\") >= 0) {\n xhr.send(qq.obj2url(params, \"\"));\n }\n else if (params && options.contentType && options.contentType.toLowerCase().indexOf(\"application/json\") >= 0) {\n xhr.send(JSON.stringify(params));\n }\n else {\n xhr.send(params);\n }\n\n return xhr;\n }\n\n function createUrl(id, params, additionalQueryParams) {\n var endpoint = options.endpointStore.get(id),\n addToPath = requestData[id].addToPath;\n\n /*jshint -W116,-W041 */\n if (addToPath != undefined) {\n endpoint += \"/\" + addToPath;\n }\n\n if (shouldParamsBeInQueryString && params) {\n endpoint = qq.obj2url(params, endpoint);\n }\n\n if (additionalQueryParams) {\n endpoint = qq.obj2url(additionalQueryParams, endpoint);\n }\n\n return endpoint;\n }\n\n // Invoked by the UA to indicate a number of possible states that describe\n // a live `XMLHttpRequest` transport.\n function getXhrReadyStateChangeHandler(id) {\n return function() {\n if (getXhrOrXdr(id).readyState === 4) {\n onComplete(id);\n }\n };\n }\n\n function registerForUploadProgress(id) {\n var onProgress = options.onProgress;\n\n if (onProgress) {\n getXhrOrXdr(id).upload.onprogress = function(e) {\n if (e.lengthComputable) {\n onProgress(id, e.loaded, e.total);\n }\n };\n }\n }\n\n // This will be called by IE to indicate **success** for an associated\n // `XDomainRequest` transported request.\n function getXdrLoadHandler(id) {\n return function() {\n onComplete(id);\n };\n }\n\n // This will be called by IE to indicate **failure** for an associated\n // `XDomainRequest` transported request.\n function getXdrErrorHandler(id) {\n return function() {\n onComplete(id, true);\n };\n }\n\n function setHeaders(id) {\n var xhr = getXhrOrXdr(id),\n customHeaders = options.customHeaders,\n onDemandHeaders = requestData[id].additionalHeaders || {},\n method = options.method,\n allHeaders = {};\n\n // If XDomainRequest is being used, we can't set headers, so just ignore this block.\n if (!isXdr(xhr)) {\n options.acceptHeader && xhr.setRequestHeader(\"Accept\", options.acceptHeader);\n\n // Only attempt to add X-Requested-With & Cache-Control if permitted\n if (options.allowXRequestedWithAndCacheControl) {\n // Do not add X-Requested-With & Cache-Control if this is a cross-origin request\n // OR the cross-origin request contains a non-simple method or header.\n // This is done to ensure a preflight is not triggered exclusively based on the\n // addition of these 2 non-simple headers.\n if (!options.cors.expected || (!isSimpleMethod() || containsNonSimpleHeaders(customHeaders))) {\n xhr.setRequestHeader(\"X-Requested-With\", \"XMLHttpRequest\");\n xhr.setRequestHeader(\"Cache-Control\", \"no-cache\");\n }\n }\n\n if (options.contentType && (method === \"POST\" || method === \"PUT\")) {\n xhr.setRequestHeader(\"Content-Type\", options.contentType);\n }\n\n qq.extend(allHeaders, qq.isFunction(customHeaders) ? customHeaders(id) : customHeaders);\n qq.extend(allHeaders, onDemandHeaders);\n\n qq.each(allHeaders, function(name, val) {\n xhr.setRequestHeader(name, val);\n });\n }\n }\n\n function isResponseSuccessful(responseCode) {\n return qq.indexOf(options.successfulResponseCodes[options.method], responseCode) >= 0;\n }\n\n function prepareToSend(id, optXhr, addToPath, additionalParams, additionalQueryParams, additionalHeaders, payload) {\n requestData[id] = {\n addToPath: addToPath,\n additionalParams: additionalParams,\n additionalQueryParams: additionalQueryParams,\n additionalHeaders: additionalHeaders,\n payload: payload\n };\n\n var len = queue.push(id);\n\n // if too many active connections, wait...\n if (len <= options.maxConnections) {\n return sendRequest(id, optXhr);\n }\n }\n\n shouldParamsBeInQueryString = options.method === \"GET\" || options.method === \"DELETE\";\n\n qq.extend(this, {\n // Start the process of sending the request. The ID refers to the file associated with the request.\n initTransport: function(id) {\n var path, params, headers, payload, cacheBuster, additionalQueryParams;\n\n return {\n // Optionally specify the end of the endpoint path for the request.\n withPath: function(appendToPath) {\n path = appendToPath;\n return this;\n },\n\n // Optionally specify additional parameters to send along with the request.\n // These will be added to the query string for GET/DELETE requests or the payload\n // for POST/PUT requests. The Content-Type of the request will be used to determine\n // how these parameters should be formatted as well.\n withParams: function(additionalParams) {\n params = additionalParams;\n return this;\n },\n\n withQueryParams: function(_additionalQueryParams_) {\n additionalQueryParams = _additionalQueryParams_;\n return this;\n },\n\n // Optionally specify additional headers to send along with the request.\n withHeaders: function(additionalHeaders) {\n headers = additionalHeaders;\n return this;\n },\n\n // Optionally specify a payload/body for the request.\n withPayload: function(thePayload) {\n payload = thePayload;\n return this;\n },\n\n // Appends a cache buster (timestamp) to the request URL as a query parameter (only if GET or DELETE)\n withCacheBuster: function() {\n cacheBuster = true;\n return this;\n },\n\n // Send the constructed request.\n send: function(optXhr) {\n if (cacheBuster && qq.indexOf([\"GET\", \"DELETE\"], options.method) >= 0) {\n params.qqtimestamp = new Date().getTime();\n }\n\n return prepareToSend(id, optXhr, path, params, additionalQueryParams, headers, payload);\n }\n };\n },\n\n canceled: function(id) {\n dequeue(id);\n }\n });\n};\n","/* globals qq */\n/**\n * Common upload handler functions.\n *\n * @constructor\n */\nqq.UploadHandler = function(spec) {\n \"use strict\";\n\n var proxy = spec.proxy,\n fileState = {},\n onCancel = proxy.onCancel,\n getName = proxy.getName;\n\n qq.extend(this, {\n add: function(id, fileItem) {\n fileState[id] = fileItem;\n fileState[id].temp = {};\n },\n\n cancel: function(id) {\n var self = this,\n cancelFinalizationEffort = new qq.Promise(),\n onCancelRetVal = onCancel(id, getName(id), cancelFinalizationEffort);\n\n onCancelRetVal.then(function() {\n if (self.isValid(id)) {\n fileState[id].canceled = true;\n self.expunge(id);\n }\n cancelFinalizationEffort.success();\n });\n },\n\n expunge: function(id) {\n delete fileState[id];\n },\n\n getThirdPartyFileId: function(id) {\n return fileState[id].key;\n },\n\n isValid: function(id) {\n return fileState[id] !== undefined;\n },\n\n reset: function() {\n fileState = {};\n },\n\n _getFileState: function(id) {\n return fileState[id];\n },\n\n _setThirdPartyFileId: function(id, thirdPartyFileId) {\n fileState[id].key = thirdPartyFileId;\n },\n\n _wasCanceled: function(id) {\n return !!fileState[id].canceled;\n }\n });\n};\n","/*globals qq*/\n/**\n * Base upload handler module. Controls more specific handlers.\n *\n * @param o Options. Passed along to the specific handler submodule as well.\n * @param namespace [optional] Namespace for the specific handler.\n */\nqq.UploadHandlerController = function(o, namespace) {\n \"use strict\";\n\n var controller = this,\n chunkingPossible = false,\n concurrentChunkingPossible = false,\n chunking, preventRetryResponse, log, handler,\n\n options = {\n paramsStore: {},\n maxConnections: 3, // maximum number of concurrent uploads\n chunking: {\n enabled: false,\n multiple: {\n enabled: false\n }\n },\n log: function(str, level) {},\n onProgress: function(id, fileName, loaded, total) {},\n onComplete: function(id, fileName, response, xhr) {},\n onCancel: function(id, fileName) {},\n onUploadPrep: function(id) {}, // Called if non-trivial operations will be performed before onUpload\n onUpload: function(id, fileName) {},\n onUploadChunk: function(id, fileName, chunkData) {},\n onUploadChunkSuccess: function(id, chunkData, response, xhr) {},\n onAutoRetry: function(id, fileName, response, xhr) {},\n onResume: function(id, fileName, chunkData, customResumeData) {},\n onUuidChanged: function(id, newUuid) {},\n getName: function(id) {},\n setSize: function(id, newSize) {},\n isQueued: function(id) {},\n getIdsInProxyGroup: function(id) {},\n getIdsInBatch: function(id) {},\n isInProgress: function(id) {}\n },\n\n chunked = {\n // Called when each chunk has uploaded successfully\n done: function(id, chunkIdx, response, xhr) {\n var chunkData = handler._getChunkData(id, chunkIdx);\n\n handler._getFileState(id).attemptingResume = false;\n\n delete handler._getFileState(id).temp.chunkProgress[chunkIdx];\n handler._getFileState(id).loaded += chunkData.size;\n\n options.onUploadChunkSuccess(id, handler._getChunkDataForCallback(chunkData), response, xhr);\n },\n\n // Called when all chunks have been successfully uploaded and we want to ask the handler to perform any\n // logic associated with closing out the file, such as combining the chunks.\n finalize: function(id) {\n var size = options.getSize(id),\n name = options.getName(id);\n\n log(\"All chunks have been uploaded for \" + id + \" - finalizing....\");\n handler.finalizeChunks(id).then(\n function(response, xhr) {\n log(\"Finalize successful for \" + id);\n\n var normaizedResponse = upload.normalizeResponse(response, true);\n\n options.onProgress(id, name, size, size);\n handler._maybeDeletePersistedChunkData(id);\n upload.cleanup(id, normaizedResponse, xhr);\n },\n function(response, xhr) {\n var normalizedResponse = upload.normalizeResponse(response, false);\n\n log(\"Problem finalizing chunks for file ID \" + id + \" - \" + normalizedResponse.error, \"error\");\n\n if (\n normalizedResponse.reset ||\n (xhr && options.chunking.success.resetOnStatus.indexOf(xhr.status) >= 0)\n ) {\n chunked.reset(id);\n }\n\n if (!options.onAutoRetry(id, name, normalizedResponse, xhr)) {\n upload.cleanup(id, normalizedResponse, xhr);\n }\n }\n );\n },\n\n handleFailure: function(chunkIdx, id, response, xhr) {\n var name = options.getName(id);\n\n log(\"Chunked upload request failed for \" + id + \", chunk \" + chunkIdx);\n\n handler.clearCachedChunk(id, chunkIdx);\n\n var responseToReport = upload.normalizeResponse(response, false),\n inProgressIdx;\n\n if (responseToReport.reset) {\n chunked.reset(id);\n }\n else {\n var inProgressChunksArray = handler._getFileState(id).chunking.inProgress;\n\n inProgressIdx = inProgressChunksArray ? qq.indexOf(inProgressChunksArray, chunkIdx) : -1;\n if (inProgressIdx >= 0) {\n handler._getFileState(id).chunking.inProgress.splice(inProgressIdx, 1);\n handler._getFileState(id).chunking.remaining.unshift(chunkIdx);\n }\n }\n\n // We may have aborted all other in-progress chunks for this file due to a failure.\n // If so, ignore the failures associated with those aborts.\n if (!handler._getFileState(id).temp.ignoreFailure) {\n // If this chunk has failed, we want to ignore all other failures of currently in-progress\n // chunks since they will be explicitly aborted\n if (concurrentChunkingPossible) {\n handler._getFileState(id).temp.ignoreFailure = true;\n\n log(qq.format(\"Going to attempt to abort these chunks: {}. These are currently in-progress: {}.\", JSON.stringify(Object.keys(handler._getXhrs(id))), JSON.stringify(handler._getFileState(id).chunking.inProgress)));\n qq.each(handler._getXhrs(id), function(ckid, ckXhr) {\n log(qq.format(\"Attempting to abort file {}.{}. XHR readyState {}. \", id, ckid, ckXhr.readyState));\n ckXhr.abort();\n // Flag the transport, in case we are waiting for some other async operation\n // to complete before attempting to upload the chunk\n ckXhr._cancelled = true;\n });\n\n // We must indicate that all aborted chunks are no longer in progress\n handler.moveInProgressToRemaining(id);\n\n // Free up any connections used by these chunks, but don't allow any\n // other files to take up the connections (until we have exhausted all auto-retries)\n connectionManager.free(id, true);\n }\n\n if (!options.onAutoRetry(id, name, responseToReport, xhr)) {\n // If one chunk fails, abort all of the others to avoid odd race conditions that occur\n // if a chunk succeeds immediately after one fails before we have determined if the upload\n // is a failure or not.\n upload.cleanup(id, responseToReport, xhr);\n }\n }\n },\n\n hasMoreParts: function(id) {\n return !!handler._getFileState(id).chunking.remaining.length;\n },\n\n nextPart: function(id) {\n var nextIdx = handler._getFileState(id).chunking.remaining.shift();\n\n if (nextIdx >= handler._getTotalChunks(id)) {\n nextIdx = null;\n }\n\n return nextIdx;\n },\n\n reset: function(id) {\n log(\"Server or callback has ordered chunking effort to be restarted on next attempt for item ID \" + id, \"error\");\n\n handler._maybeDeletePersistedChunkData(id);\n handler.reevaluateChunking(id);\n handler._getFileState(id).loaded = 0;\n handler._getFileState(id).attemptingResume = false;\n },\n\n sendNext: function(id) {\n var size = options.getSize(id),\n name = options.getName(id),\n chunkIdx = chunked.nextPart(id),\n chunkData = handler._getChunkData(id, chunkIdx),\n fileState = handler._getFileState(id),\n resuming = fileState.attemptingResume,\n inProgressChunks = fileState.chunking.inProgress || [];\n\n if (fileState.loaded == null) {\n fileState.loaded = 0;\n }\n\n // Don't follow-through with the resume attempt if the integrator returns false from onResume\n if (resuming && options.onResume(id, name, chunkData, fileState.customResumeData) === false) {\n chunked.reset(id);\n chunkIdx = chunked.nextPart(id);\n chunkData = handler._getChunkData(id, chunkIdx);\n resuming = false;\n }\n\n // If all chunks have already uploaded successfully, we must be re-attempting the finalize step.\n if (chunkIdx == null && inProgressChunks.length === 0) {\n chunked.finalize(id);\n }\n\n // Send the next chunk\n else {\n inProgressChunks.push(chunkIdx);\n handler._getFileState(id).chunking.inProgress = inProgressChunks;\n\n if (concurrentChunkingPossible) {\n connectionManager.open(id, chunkIdx);\n }\n\n if (concurrentChunkingPossible && connectionManager.available() && handler._getFileState(id).chunking.remaining.length) {\n chunked.sendNext(id);\n }\n\n if (chunkData.blob.size === 0) {\n log(qq.format(\"Chunk {} for file {} will not be uploaded, zero sized chunk.\", chunkIdx, id), \"error\");\n chunked.handleFailure(chunkIdx, id, \"File is no longer available\", null);\n }\n\n var onUploadChunkPromise = options.onUploadChunk(id, name, handler._getChunkDataForCallback(chunkData));\n\n onUploadChunkPromise.then(\n function(requestOverrides) {\n if (!options.isInProgress(id)) {\n log(qq.format(\"Not sending chunked upload request for item {}.{} - no longer in progress.\", id, chunkIdx));\n }\n else {\n log(qq.format(\"Sending chunked upload request for item {}.{}, bytes {}-{} of {}.\", id, chunkIdx, chunkData.start + 1, chunkData.end, size));\n\n var uploadChunkData = {\n chunkIdx: chunkIdx,\n id: id,\n overrides: requestOverrides,\n resuming: resuming\n };\n\n handler.uploadChunk(uploadChunkData).then(\n // upload chunk success\n function success(response, xhr) {\n log(\"Chunked upload request succeeded for \" + id + \", chunk \" + chunkIdx);\n\n handler.clearCachedChunk(id, chunkIdx);\n\n var inProgressChunks = handler._getFileState(id).chunking.inProgress || [],\n responseToReport = upload.normalizeResponse(response, true),\n inProgressChunkIdx = qq.indexOf(inProgressChunks, chunkIdx);\n\n log(qq.format(\"Chunk {} for file {} uploaded successfully.\", chunkIdx, id));\n\n chunked.done(id, chunkIdx, responseToReport, xhr);\n\n if (inProgressChunkIdx >= 0) {\n inProgressChunks.splice(inProgressChunkIdx, 1);\n }\n\n handler._maybePersistChunkedState(id);\n\n if (!chunked.hasMoreParts(id) && inProgressChunks.length === 0) {\n chunked.finalize(id);\n }\n else if (chunked.hasMoreParts(id)) {\n chunked.sendNext(id);\n }\n else {\n log(qq.format(\"File ID {} has no more chunks to send and these chunk indexes are still marked as in-progress: {}\", id, JSON.stringify(inProgressChunks)));\n }\n },\n\n // upload chunk failure\n function failure(response, xhr) {\n chunked.handleFailure(chunkIdx, id, response, xhr);\n }\n )\n .done(function () {\n handler.clearXhr(id, chunkIdx);\n });\n }\n },\n\n function(error) {\n chunked.handleFailure(chunkIdx, id, error, null);\n }\n );\n }\n }\n },\n\n connectionManager = {\n _open: [],\n _openChunks: {},\n _waiting: [],\n\n available: function() {\n var max = options.maxConnections,\n openChunkEntriesCount = 0,\n openChunksCount = 0;\n\n qq.each(connectionManager._openChunks, function(fileId, openChunkIndexes) {\n openChunkEntriesCount++;\n openChunksCount += openChunkIndexes.length;\n });\n\n return max - (connectionManager._open.length - openChunkEntriesCount + openChunksCount);\n },\n\n /**\n * Removes element from queue, starts upload of next\n */\n free: function(id, dontAllowNext) {\n var allowNext = !dontAllowNext,\n waitingIndex = qq.indexOf(connectionManager._waiting, id),\n connectionsIndex = qq.indexOf(connectionManager._open, id),\n nextId;\n\n delete connectionManager._openChunks[id];\n\n if (upload.getProxyOrBlob(id) instanceof qq.BlobProxy) {\n log(\"Generated blob upload has ended for \" + id + \", disposing generated blob.\");\n delete handler._getFileState(id).file;\n }\n\n // If this file was not consuming a connection, it was just waiting, so remove it from the waiting array\n if (waitingIndex >= 0) {\n connectionManager._waiting.splice(waitingIndex, 1);\n }\n // If this file was consuming a connection, allow the next file to be uploaded\n else if (allowNext && connectionsIndex >= 0) {\n connectionManager._open.splice(connectionsIndex, 1);\n\n nextId = connectionManager._waiting.shift();\n if (nextId >= 0) {\n connectionManager._open.push(nextId);\n upload.start(nextId);\n }\n }\n },\n\n getWaitingOrConnected: function() {\n var waitingOrConnected = [];\n\n // Chunked files may have multiple connections open per chunk (if concurrent chunking is enabled)\n // We need to grab the file ID of any file that has at least one chunk consuming a connection.\n qq.each(connectionManager._openChunks, function(fileId, chunks) {\n if (chunks && chunks.length) {\n waitingOrConnected.push(parseInt(fileId));\n }\n });\n\n // For non-chunked files, only one connection will be consumed per file.\n // This is where we aggregate those file IDs.\n qq.each(connectionManager._open, function(idx, fileId) {\n if (!connectionManager._openChunks[fileId]) {\n waitingOrConnected.push(parseInt(fileId));\n }\n });\n\n // There may be files waiting for a connection.\n waitingOrConnected = waitingOrConnected.concat(connectionManager._waiting);\n\n return waitingOrConnected;\n },\n\n isUsingConnection: function(id) {\n return qq.indexOf(connectionManager._open, id) >= 0;\n },\n\n open: function(id, chunkIdx) {\n if (chunkIdx == null) {\n connectionManager._waiting.push(id);\n }\n\n if (connectionManager.available()) {\n if (chunkIdx == null) {\n connectionManager._waiting.pop();\n connectionManager._open.push(id);\n }\n else {\n (function() {\n var openChunksEntry = connectionManager._openChunks[id] || [];\n openChunksEntry.push(chunkIdx);\n connectionManager._openChunks[id] = openChunksEntry;\n }());\n }\n\n return true;\n }\n\n return false;\n },\n\n reset: function() {\n connectionManager._waiting = [];\n connectionManager._open = [];\n }\n },\n\n simple = {\n send: function(id, name) {\n var fileState = handler._getFileState(id);\n\n if (!fileState) {\n log(\"Ignoring send request as this upload may have been cancelled, File ID \" + id, \"warn\");\n return;\n }\n\n fileState.loaded = 0;\n\n log(\"Sending simple upload request for \" + id);\n handler.uploadFile(id).then(\n function(response, optXhr) {\n log(\"Simple upload request succeeded for \" + id);\n\n var responseToReport = upload.normalizeResponse(response, true),\n size = options.getSize(id);\n\n options.onProgress(id, name, size, size);\n upload.maybeNewUuid(id, responseToReport);\n upload.cleanup(id, responseToReport, optXhr);\n },\n\n function(response, optXhr) {\n log(\"Simple upload request failed for \" + id);\n\n var responseToReport = upload.normalizeResponse(response, false);\n\n if (!options.onAutoRetry(id, name, responseToReport, optXhr)) {\n upload.cleanup(id, responseToReport, optXhr);\n }\n }\n );\n }\n },\n\n upload = {\n cancel: function(id) {\n log(\"Cancelling \" + id);\n options.paramsStore.remove(id);\n connectionManager.free(id);\n },\n\n cleanup: function(id, response, optXhr) {\n var name = options.getName(id);\n\n options.onComplete(id, name, response, optXhr);\n\n if (handler._getFileState(id)) {\n handler._clearXhrs && handler._clearXhrs(id);\n }\n\n connectionManager.free(id);\n },\n\n // Returns a qq.BlobProxy, or an actual File/Blob if no proxy is involved, or undefined\n // if none of these are available for the ID\n getProxyOrBlob: function(id) {\n return (handler.getProxy && handler.getProxy(id)) ||\n (handler.getFile && handler.getFile(id));\n },\n\n initHandler: function() {\n var handlerType = namespace ? qq[namespace] : qq.traditional,\n handlerModuleSubtype = qq.supportedFeatures.ajaxUploading ? \"Xhr\" : \"Form\";\n\n handler = new handlerType[handlerModuleSubtype + \"UploadHandler\"](\n options,\n {\n getCustomResumeData: options.getCustomResumeData,\n getDataByUuid: options.getDataByUuid,\n getName: options.getName,\n getSize: options.getSize,\n getUuid: options.getUuid,\n log: log,\n onCancel: options.onCancel,\n onProgress: options.onProgress,\n onUuidChanged: options.onUuidChanged,\n onFinalizing: function(id) {\n options.setStatus(id, qq.status.UPLOAD_FINALIZING);\n }\n }\n );\n\n if (handler._removeExpiredChunkingRecords) {\n handler._removeExpiredChunkingRecords();\n }\n },\n\n isDeferredEligibleForUpload: function(id) {\n return options.isQueued(id);\n },\n\n // For Blobs that are part of a group of generated images, along with a reference image,\n // this will ensure the blobs in the group are uploaded in the order they were triggered,\n // even if some async processing must be completed on one or more Blobs first.\n maybeDefer: function(id, blob) {\n // If we don't have a file/blob yet & no file/blob exists for this item, request it,\n // and then submit the upload to the specific handler once the blob is available.\n // ASSUMPTION: This condition will only ever be true if XHR uploading is supported.\n if (blob && !handler.getFile(id) && blob instanceof qq.BlobProxy) {\n\n // Blob creation may take some time, so the caller may want to update the\n // UI to indicate that an operation is in progress, even before the actual\n // upload begins and an onUpload callback is invoked.\n options.onUploadPrep(id);\n\n log(\"Attempting to generate a blob on-demand for \" + id);\n blob.create().then(function(generatedBlob) {\n log(\"Generated an on-demand blob for \" + id);\n\n // Update record associated with this file by providing the generated Blob\n handler.updateBlob(id, generatedBlob);\n\n // Propagate the size for this generated Blob\n options.setSize(id, generatedBlob.size);\n\n // Order handler to recalculate chunking possibility, if applicable\n handler.reevaluateChunking(id);\n\n upload.maybeSendDeferredFiles(id);\n },\n\n // Blob could not be generated. Fail the upload & attempt to prevent retries. Also bubble error message.\n function(errorMessage) {\n var errorResponse = {};\n\n if (errorMessage) {\n errorResponse.error = errorMessage;\n }\n\n log(qq.format(\"Failed to generate blob for ID {}. Error message: {}.\", id, errorMessage), \"error\");\n\n options.onComplete(id, options.getName(id), qq.extend(errorResponse, preventRetryResponse), null);\n upload.maybeSendDeferredFiles(id);\n connectionManager.free(id);\n });\n }\n else {\n return upload.maybeSendDeferredFiles(id);\n }\n\n return false;\n },\n\n // Upload any grouped blobs, in the proper order, that are ready to be uploaded\n maybeSendDeferredFiles: function(id) {\n var idsInGroup = options.getIdsInProxyGroup(id),\n uploadedThisId = false;\n\n if (idsInGroup && idsInGroup.length) {\n log(\"Maybe ready to upload proxy group file \" + id);\n\n qq.each(idsInGroup, function(idx, idInGroup) {\n if (upload.isDeferredEligibleForUpload(idInGroup) && !!handler.getFile(idInGroup)) {\n uploadedThisId = idInGroup === id;\n upload.now(idInGroup);\n }\n else if (upload.isDeferredEligibleForUpload(idInGroup)) {\n return false;\n }\n });\n }\n else {\n uploadedThisId = true;\n upload.now(id);\n }\n\n return uploadedThisId;\n },\n\n maybeNewUuid: function(id, response) {\n if (response.newUuid !== undefined) {\n options.onUuidChanged(id, response.newUuid);\n }\n },\n\n // The response coming from handler implementations may be in various formats.\n // Instead of hoping a promise nested 5 levels deep will always return an object\n // as its first param, let's just normalize the response here.\n normalizeResponse: function(originalResponse, successful) {\n var response = originalResponse;\n\n // The passed \"response\" param may not be a response at all.\n // It could be a string, detailing the error, for example.\n if (!qq.isObject(originalResponse)) {\n response = {};\n\n if (qq.isString(originalResponse) && !successful) {\n response.error = originalResponse;\n }\n }\n\n response.success = successful;\n\n return response;\n },\n\n now: function(id) {\n var name = options.getName(id);\n\n if (!controller.isValid(id)) {\n throw new qq.Error(id + \" is not a valid file ID to upload!\");\n }\n\n options.onUpload(id, name).then(\n function(response) {\n if (response && response.pause) {\n options.setStatus(id, qq.status.PAUSED);\n handler.pause(id);\n connectionManager.free(id);\n }\n else {\n if (chunkingPossible && handler._shouldChunkThisFile(id)) {\n chunked.sendNext(id);\n }\n else {\n simple.send(id, name);\n }\n }\n },\n\n function(error) {\n error = error || {};\n\n log(id + \" upload start aborted due to rejected onUpload Promise - details: \" + error, \"error\");\n\n if (!options.onAutoRetry(id, name, error.responseJSON || {})) {\n var response = upload.normalizeResponse(error.responseJSON, false);\n upload.cleanup(id, response);\n }\n }\n );\n },\n\n start: function(id) {\n var blobToUpload = upload.getProxyOrBlob(id);\n\n if (blobToUpload) {\n return upload.maybeDefer(id, blobToUpload);\n }\n else {\n upload.now(id);\n return true;\n }\n }\n };\n\n qq.extend(this, {\n /**\n * Adds file or file input to the queue\n **/\n add: function(id, file) {\n handler.add.apply(this, arguments);\n },\n\n /**\n * Sends the file identified by id\n */\n upload: function(id) {\n if (connectionManager.open(id)) {\n return upload.start(id);\n }\n return false;\n },\n\n retry: function(id) {\n // On retry, if concurrent chunking has been enabled, we may have aborted all other in-progress chunks\n // for a file when encountering a failed chunk upload. We then signaled the controller to ignore\n // all failures associated with these aborts. We are now retrying, so we don't want to ignore\n // any more failures at this point.\n if (concurrentChunkingPossible) {\n handler._getFileState(id).temp.ignoreFailure = false;\n }\n\n // If we are attempting to retry a file that is already consuming a connection, this is likely an auto-retry.\n // Just go ahead and ask the handler to upload again.\n if (connectionManager.isUsingConnection(id)) {\n return upload.start(id);\n }\n\n // If we are attempting to retry a file that is not currently consuming a connection,\n // this is likely a manual retry attempt. We will need to ensure a connection is available\n // before the retry commences.\n else {\n return controller.upload(id);\n }\n },\n\n /**\n * Cancels file upload by id\n */\n cancel: function(id) {\n var cancelRetVal = handler.cancel(id);\n\n if (qq.isGenericPromise(cancelRetVal)) {\n cancelRetVal.then(function() {\n upload.cancel(id);\n });\n }\n else if (cancelRetVal !== false) {\n upload.cancel(id);\n }\n },\n\n /**\n * Cancels all queued or in-progress uploads\n */\n cancelAll: function() {\n var waitingOrConnected = connectionManager.getWaitingOrConnected(),\n i;\n\n // ensure files are cancelled in reverse order which they were added\n // to avoid a flash of time where a queued file begins to upload before it is canceled\n if (waitingOrConnected.length) {\n for (i = waitingOrConnected.length - 1; i >= 0; i--) {\n controller.cancel(waitingOrConnected[i]);\n }\n }\n\n connectionManager.reset();\n },\n\n // Returns a File, Blob, or the Blob/File for the reference/parent file if the targeted blob is a proxy.\n // Undefined if no file record is available.\n getFile: function(id) {\n if (handler.getProxy && handler.getProxy(id)) {\n return handler.getProxy(id).referenceBlob;\n }\n\n return handler.getFile && handler.getFile(id);\n },\n\n // Returns true if the Blob associated with the ID is related to a proxy s\n isProxied: function(id) {\n return !!(handler.getProxy && handler.getProxy(id));\n },\n\n getInput: function(id) {\n if (handler.getInput) {\n return handler.getInput(id);\n }\n },\n\n reset: function() {\n log(\"Resetting upload handler\");\n controller.cancelAll();\n connectionManager.reset();\n handler.reset();\n },\n\n expunge: function(id) {\n if (controller.isValid(id)) {\n return handler.expunge(id);\n }\n },\n\n /**\n * Determine if the file exists.\n */\n isValid: function(id) {\n return handler.isValid(id);\n },\n\n hasResumeRecord: function(id) {\n var key = handler.isValid(id) &&\n handler._getLocalStorageId &&\n handler._getLocalStorageId(id);\n\n if (key) {\n return !!localStorage.getItem(key);\n }\n\n return false;\n },\n\n getResumableFilesData: function() {\n if (handler.getResumableFilesData) {\n return handler.getResumableFilesData();\n }\n return [];\n },\n\n /**\n * This may or may not be implemented, depending on the handler. For handlers where a third-party ID is\n * available (such as the \"key\" for Amazon S3), this will return that value. Otherwise, the return value\n * will be undefined.\n *\n * @param id Internal file ID\n * @returns {*} Some identifier used by a 3rd-party service involved in the upload process\n */\n getThirdPartyFileId: function(id) {\n if (controller.isValid(id)) {\n return handler.getThirdPartyFileId(id);\n }\n },\n\n /**\n * Attempts to pause the associated upload if the specific handler supports this and the file is \"valid\".\n * @param id ID of the upload/file to pause\n * @returns {boolean} true if the upload was paused\n */\n pause: function(id) {\n if (controller.isResumable(id) && handler.pause && controller.isValid(id) && handler.pause(id)) {\n connectionManager.free(id);\n handler.moveInProgressToRemaining(id);\n return true;\n }\n return false;\n },\n\n isAttemptingResume: function(id) {\n return !!handler.isAttemptingResume && handler.isAttemptingResume(id);\n },\n\n // True if the file is eligible for pause/resume.\n isResumable: function(id) {\n return !!handler.isResumable && handler.isResumable(id);\n }\n });\n\n qq.extend(options, o);\n log = options.log;\n chunkingPossible = options.chunking.enabled && qq.supportedFeatures.chunking;\n concurrentChunkingPossible = chunkingPossible && options.chunking.concurrent.enabled;\n\n preventRetryResponse = (function() {\n var response = {};\n\n response[options.preventRetryParam] = true;\n\n return response;\n }());\n\n upload.initHandler();\n};\n","/*globals qq */\n/*jshint -W117 */\nqq.WindowReceiveMessage = function(o) {\n \"use strict\";\n\n var options = {\n log: function(message, level) {}\n },\n callbackWrapperDetachers = {};\n\n qq.extend(options, o);\n\n qq.extend(this, {\n receiveMessage: function(id, callback) {\n var onMessageCallbackWrapper = function(event) {\n callback(event.data);\n };\n\n if (window.postMessage) {\n callbackWrapperDetachers[id] = qq(window).attach(\"message\", onMessageCallbackWrapper);\n }\n else {\n log(\"iframe message passing not supported in this browser!\", \"error\");\n }\n },\n\n stopReceivingMessages: function(id) {\n if (window.postMessage) {\n var detacher = callbackWrapperDetachers[id];\n if (detacher) {\n detacher();\n }\n }\n }\n });\n};\n","/* globals qq */\n/**\n * Common APIs exposed to creators of upload via form/iframe handlers. This is reused and possibly overridden\n * in some cases by specific form upload handlers.\n *\n * @constructor\n */\nqq.FormUploadHandler = function(spec) {\n \"use strict\";\n\n var options = spec.options,\n handler = this,\n proxy = spec.proxy,\n formHandlerInstanceId = qq.getUniqueId(),\n onloadCallbacks = {},\n detachLoadEvents = {},\n postMessageCallbackTimers = {},\n isCors = options.isCors,\n inputName = options.inputName,\n getUuid = proxy.getUuid,\n log = proxy.log,\n corsMessageReceiver = new qq.WindowReceiveMessage({log: log});\n\n /**\n * Remove any trace of the file from the handler.\n *\n * @param id ID of the associated file\n */\n function expungeFile(id) {\n delete detachLoadEvents[id];\n\n // If we are dealing with CORS, we might still be waiting for a response from a loaded iframe.\n // In that case, terminate the timer waiting for a message from the loaded iframe\n // and stop listening for any more messages coming from this iframe.\n if (isCors) {\n clearTimeout(postMessageCallbackTimers[id]);\n delete postMessageCallbackTimers[id];\n corsMessageReceiver.stopReceivingMessages(id);\n }\n\n var iframe = document.getElementById(handler._getIframeName(id));\n if (iframe) {\n // To cancel request set src to something else. We use src=\"javascript:false;\"\n // because it doesn't trigger ie6 prompt on https\n /* jshint scripturl:true */\n iframe.setAttribute(\"src\", \"javascript:false;\");\n\n qq(iframe).remove();\n }\n }\n\n /**\n * @param iframeName `document`-unique Name of the associated iframe\n * @returns {*} ID of the associated file\n */\n function getFileIdForIframeName(iframeName) {\n return iframeName.split(\"_\")[0];\n }\n\n /**\n * Generates an iframe to be used as a target for upload-related form submits. This also adds the iframe\n * to the current `document`. Note that the iframe is hidden from view.\n *\n * @param name Name of the iframe.\n * @returns {HTMLIFrameElement} The created iframe\n */\n function initIframeForUpload(name) {\n var iframe = qq.toElement(\"\");\n\n iframe.setAttribute(\"id\", name);\n\n iframe.style.display = \"none\";\n document.body.appendChild(iframe);\n\n return iframe;\n }\n\n /**\n * If we are in CORS mode, we must listen for messages (containing the server response) from the associated\n * iframe, since we cannot directly parse the content of the iframe due to cross-origin restrictions.\n *\n * @param iframe Listen for messages on this iframe.\n * @param callback Invoke this callback with the message from the iframe.\n */\n function registerPostMessageCallback(iframe, callback) {\n var iframeName = iframe.id,\n fileId = getFileIdForIframeName(iframeName),\n uuid = getUuid(fileId);\n\n onloadCallbacks[uuid] = callback;\n\n // When the iframe has loaded (after the server responds to an upload request)\n // declare the attempt a failure if we don't receive a valid message shortly after the response comes in.\n detachLoadEvents[fileId] = qq(iframe).attach(\"load\", function() {\n if (handler.getInput(fileId)) {\n log(\"Received iframe load event for CORS upload request (iframe name \" + iframeName + \")\");\n\n postMessageCallbackTimers[iframeName] = setTimeout(function() {\n var errorMessage = \"No valid message received from loaded iframe for iframe name \" + iframeName;\n log(errorMessage, \"error\");\n callback({\n error: errorMessage\n });\n }, 1000);\n }\n });\n\n // Listen for messages coming from this iframe. When a message has been received, cancel the timer\n // that declares the upload a failure if a message is not received within a reasonable amount of time.\n corsMessageReceiver.receiveMessage(iframeName, function(message) {\n log(\"Received the following window message: '\" + message + \"'\");\n var fileId = getFileIdForIframeName(iframeName),\n response = handler._parseJsonResponse(message),\n uuid = response.uuid,\n onloadCallback;\n\n if (uuid && onloadCallbacks[uuid]) {\n log(\"Handling response for iframe name \" + iframeName);\n clearTimeout(postMessageCallbackTimers[iframeName]);\n delete postMessageCallbackTimers[iframeName];\n\n handler._detachLoadEvent(iframeName);\n\n onloadCallback = onloadCallbacks[uuid];\n\n delete onloadCallbacks[uuid];\n corsMessageReceiver.stopReceivingMessages(iframeName);\n onloadCallback(response);\n }\n else if (!uuid) {\n log(\"'\" + message + \"' does not contain a UUID - ignoring.\");\n }\n });\n }\n\n qq.extend(this, new qq.UploadHandler(spec));\n\n qq.override(this, function(super_) {\n return {\n /**\n * Adds File or Blob to the queue\n **/\n add: function(id, fileInput) {\n super_.add(id, {input: fileInput});\n\n fileInput.setAttribute(\"name\", inputName);\n\n // remove file input from DOM\n if (fileInput.parentNode) {\n qq(fileInput).remove();\n }\n },\n\n expunge: function(id) {\n expungeFile(id);\n super_.expunge(id);\n },\n\n isValid: function(id) {\n return super_.isValid(id) &&\n handler._getFileState(id).input !== undefined;\n }\n };\n });\n\n qq.extend(this, {\n getInput: function(id) {\n return handler._getFileState(id).input;\n },\n\n /**\n * This function either delegates to a more specific message handler if CORS is involved,\n * or simply registers a callback when the iframe has been loaded that invokes the passed callback\n * after determining if the content of the iframe is accessible.\n *\n * @param iframe Associated iframe\n * @param callback Callback to invoke after we have determined if the iframe content is accessible.\n */\n _attachLoadEvent: function(iframe, callback) {\n /*jslint eqeq: true*/\n var responseDescriptor;\n\n if (isCors) {\n registerPostMessageCallback(iframe, callback);\n }\n else {\n detachLoadEvents[iframe.id] = qq(iframe).attach(\"load\", function() {\n log(\"Received response for \" + iframe.id);\n\n // when we remove iframe from dom\n // the request stops, but in IE load\n // event fires\n if (!iframe.parentNode) {\n return;\n }\n\n try {\n // fixing Opera 10.53\n if (iframe.contentDocument &&\n iframe.contentDocument.body &&\n iframe.contentDocument.body.innerHTML == \"false\") {\n // In Opera event is fired second time\n // when body.innerHTML changed from false\n // to server response approx. after 1 sec\n // when we upload file with iframe\n return;\n }\n }\n catch (error) {\n //IE may throw an \"access is denied\" error when attempting to access contentDocument on the iframe in some cases\n log(\"Error when attempting to access iframe during handling of upload response (\" + error.message + \")\", \"error\");\n responseDescriptor = {success: false};\n }\n\n callback(responseDescriptor);\n });\n }\n },\n\n /**\n * Creates an iframe with a specific document-unique name.\n *\n * @param id ID of the associated file\n * @returns {HTMLIFrameElement}\n */\n _createIframe: function(id) {\n var iframeName = handler._getIframeName(id);\n\n return initIframeForUpload(iframeName);\n },\n\n /**\n * Called when we are no longer interested in being notified when an iframe has loaded.\n *\n * @param id Associated file ID\n */\n _detachLoadEvent: function(id) {\n if (detachLoadEvents[id] !== undefined) {\n detachLoadEvents[id]();\n delete detachLoadEvents[id];\n }\n },\n\n /**\n * @param fileId ID of the associated file\n * @returns {string} The `document`-unique name of the iframe\n */\n _getIframeName: function(fileId) {\n return fileId + \"_\" + formHandlerInstanceId;\n },\n\n /**\n * Generates a form element and appends it to the `document`. When the form is submitted, a specific iframe is targeted.\n * The name of the iframe is passed in as a property of the spec parameter, and must be unique in the `document`. Note\n * that the form is hidden from view.\n *\n * @param spec An object containing various properties to be used when constructing the form. Required properties are\n * currently: `method`, `endpoint`, `params`, `paramsInBody`, and `targetName`.\n * @returns {HTMLFormElement} The created form\n */\n _initFormForUpload: function(spec) {\n var method = spec.method,\n endpoint = spec.endpoint,\n params = spec.params,\n paramsInBody = spec.paramsInBody,\n targetName = spec.targetName,\n form = qq.toElement(\"\"),\n url = endpoint;\n\n if (paramsInBody) {\n qq.obj2Inputs(params, form);\n }\n else {\n url = qq.obj2url(params, endpoint);\n }\n\n form.setAttribute(\"action\", url);\n form.setAttribute(\"target\", targetName);\n form.style.display = \"none\";\n document.body.appendChild(form);\n\n return form;\n },\n\n /**\n * @param innerHtmlOrMessage JSON message\n * @returns {*} The parsed response, or an empty object if the response could not be parsed\n */\n _parseJsonResponse: function(innerHtmlOrMessage) {\n var response = {};\n\n try {\n response = qq.parseJson(innerHtmlOrMessage);\n }\n catch (error) {\n log(\"Error when attempting to parse iframe upload response (\" + error.message + \")\", \"error\");\n }\n\n return response;\n }\n });\n};\n","/* globals qq */\n/**\n * Common API exposed to creators of XHR handlers. This is reused and possibly overriding in some cases by specific\n * XHR upload handlers.\n *\n * @constructor\n */\nqq.XhrUploadHandler = function(spec) {\n \"use strict\";\n\n var handler = this,\n namespace = spec.options.namespace,\n proxy = spec.proxy,\n chunking = spec.options.chunking,\n getChunkSize = function(id) {\n var fileState = handler._getFileState(id);\n\n if (fileState.chunkSize) {\n return fileState.chunkSize;\n }\n\n else {\n var chunkSize = chunking.partSize;\n\n if (qq.isFunction(chunkSize)) {\n chunkSize = chunkSize(id, getSize(id));\n }\n\n fileState.chunkSize = chunkSize;\n return chunkSize;\n }\n },\n resume = spec.options.resume,\n chunkFiles = chunking && spec.options.chunking.enabled && qq.supportedFeatures.chunking,\n resumeEnabled = resume && spec.options.resume.enabled && chunkFiles && qq.supportedFeatures.resume,\n getName = proxy.getName,\n getSize = proxy.getSize,\n getUuid = proxy.getUuid,\n getEndpoint = proxy.getEndpoint,\n getDataByUuid = proxy.getDataByUuid,\n onUuidChanged = proxy.onUuidChanged,\n onProgress = proxy.onProgress,\n log = proxy.log,\n getCustomResumeData = proxy.getCustomResumeData;\n\n function abort(id) {\n qq.each(handler._getXhrs(id), function(xhrId, xhr) {\n var ajaxRequester = handler._getAjaxRequester(id, xhrId);\n\n xhr.onreadystatechange = null;\n xhr.upload.onprogress = null;\n xhr.abort();\n ajaxRequester && ajaxRequester.canceled && ajaxRequester.canceled(id);\n });\n }\n\n qq.extend(this, new qq.UploadHandler(spec));\n\n qq.override(this, function(super_) {\n return {\n /**\n * Adds File or Blob to the queue\n **/\n add: function(id, blobOrProxy) {\n if (qq.isFile(blobOrProxy) || qq.isBlob(blobOrProxy)) {\n super_.add(id, {file: blobOrProxy});\n }\n else if (blobOrProxy instanceof qq.BlobProxy) {\n super_.add(id, {proxy: blobOrProxy});\n }\n else {\n throw new Error(\"Passed obj is not a File, Blob, or proxy\");\n }\n\n handler._initTempState(id);\n resumeEnabled && handler._maybePrepareForResume(id);\n },\n\n expunge: function(id) {\n abort(id);\n handler._maybeDeletePersistedChunkData(id);\n handler._clearXhrs(id);\n super_.expunge(id);\n }\n };\n });\n\n qq.extend(this, {\n // Clear the cached chunk `Blob` after we are done with it, just in case the `Blob` bytes are stored in memory.\n clearCachedChunk: function(id, chunkIdx) {\n var fileState = handler._getFileState(id);\n\n if (fileState) {\n delete fileState.temp.cachedChunks[chunkIdx];\n }\n },\n\n clearXhr: function(id, chunkIdx) {\n var tempState = handler._getFileState(id).temp;\n\n if (tempState.xhrs) {\n delete tempState.xhrs[chunkIdx];\n }\n if (tempState.ajaxRequesters) {\n delete tempState.ajaxRequesters[chunkIdx];\n }\n },\n\n // Called when all chunks have been successfully uploaded. Expected promissory return type.\n // This defines the default behavior if nothing further is required when all chunks have been uploaded.\n finalizeChunks: function(id, responseParser) {\n var lastChunkIdx = handler._getTotalChunks(id) - 1,\n xhr = handler._getXhr(id, lastChunkIdx);\n\n if (responseParser) {\n return new qq.Promise().success(responseParser(xhr), xhr);\n }\n\n return new qq.Promise().success({}, xhr);\n },\n\n getFile: function(id) {\n return handler.isValid(id) && handler._getFileState(id).file;\n },\n\n getProxy: function(id) {\n return handler.isValid(id) && handler._getFileState(id).proxy;\n },\n\n /**\n * @returns {Array} Array of objects containing properties useful to integrators\n * when it is important to determine which files are potentially resumable.\n */\n getResumableFilesData: function() {\n var resumableFilesData = [];\n\n handler._iterateResumeRecords(function(key, uploadData) {\n handler.moveInProgressToRemaining(null, uploadData.chunking.inProgress, uploadData.chunking.remaining);\n\n var data = {\n name: uploadData.name,\n remaining: uploadData.chunking.remaining,\n size: uploadData.size,\n uuid: uploadData.uuid\n };\n\n if (uploadData.key) {\n data.key = uploadData.key;\n }\n\n if (uploadData.customResumeData) {\n data.customResumeData = uploadData.customResumeData;\n }\n\n resumableFilesData.push(data);\n });\n\n return resumableFilesData;\n },\n\n isAttemptingResume: function(id) {\n return handler._getFileState(id).attemptingResume;\n },\n\n isResumable: function(id) {\n return !!chunking && handler.isValid(id) &&\n !handler._getFileState(id).notResumable;\n },\n\n moveInProgressToRemaining: function(id, optInProgress, optRemaining) {\n var fileState = handler._getFileState(id) || {},\n chunkingState = fileState.chunking || {},\n inProgress = optInProgress || chunkingState.inProgress,\n remaining = optRemaining || chunkingState.remaining;\n\n if (inProgress) {\n log(qq.format(\"Moving these chunks from in-progress {}, to remaining.\", JSON.stringify(inProgress)));\n inProgress.reverse();\n qq.each(inProgress, function(idx, chunkIdx) {\n remaining.unshift(chunkIdx);\n });\n inProgress.length = 0;\n }\n },\n\n pause: function(id) {\n if (handler.isValid(id)) {\n log(qq.format(\"Aborting XHR upload for {} '{}' due to pause instruction.\", id, getName(id)));\n handler._getFileState(id).paused = true;\n abort(id);\n return true;\n }\n },\n\n reevaluateChunking: function(id) {\n if (chunking && handler.isValid(id)) {\n var state = handler._getFileState(id),\n totalChunks,\n i;\n\n delete state.chunking;\n\n state.chunking = {};\n totalChunks = handler._getTotalChunks(id);\n if (totalChunks > 1 || chunking.mandatory) {\n state.chunking.enabled = true;\n state.chunking.parts = totalChunks;\n state.chunking.remaining = [];\n\n for (i = 0; i < totalChunks; i++) {\n state.chunking.remaining.push(i);\n }\n\n handler._initTempState(id);\n }\n else {\n state.chunking.enabled = false;\n }\n }\n },\n\n updateBlob: function(id, newBlob) {\n if (handler.isValid(id)) {\n handler._getFileState(id).file = newBlob;\n }\n },\n\n _clearXhrs: function(id) {\n var tempState = handler._getFileState(id).temp;\n\n qq.each(tempState.ajaxRequesters, function(chunkId) {\n delete tempState.ajaxRequesters[chunkId];\n });\n\n qq.each(tempState.xhrs, function(chunkId) {\n delete tempState.xhrs[chunkId];\n });\n },\n\n /**\n * Creates an XHR instance for this file and stores it in the fileState.\n *\n * @param id File ID\n * @param optChunkIdx The chunk index associated with this XHR, if applicable\n * @returns {XMLHttpRequest}\n */\n _createXhr: function(id, optChunkIdx) {\n return handler._registerXhr(id, optChunkIdx, qq.createXhrInstance());\n },\n\n _getAjaxRequester: function(id, optChunkIdx) {\n var chunkIdx = optChunkIdx == null ? -1 : optChunkIdx;\n return handler._getFileState(id).temp.ajaxRequesters[chunkIdx];\n },\n\n _getChunkData: function(id, chunkIndex) {\n var chunkSize = getChunkSize(id),\n fileSize = getSize(id),\n fileOrBlob = handler.getFile(id),\n startBytes = chunkSize * chunkIndex,\n endBytes = startBytes + chunkSize >= fileSize ? fileSize : startBytes + chunkSize,\n totalChunks = handler._getTotalChunks(id),\n cachedChunks = this._getFileState(id).temp.cachedChunks,\n\n // To work around a Webkit GC bug, we must keep each chunk `Blob` in scope until we are done with it.\n // See https://github.com/FineUploader/fine-uploader/issues/937#issuecomment-41418760\n blob = cachedChunks[chunkIndex] || qq.sliceBlob(fileOrBlob, startBytes, endBytes);\n\n cachedChunks[chunkIndex] = blob;\n\n return {\n part: chunkIndex,\n start: startBytes,\n end: endBytes,\n count: totalChunks,\n blob: blob,\n size: endBytes - startBytes\n };\n },\n\n _getChunkDataForCallback: function(chunkData) {\n return {\n partIndex: chunkData.part,\n startByte: chunkData.start + 1,\n endByte: chunkData.end,\n totalParts: chunkData.count\n };\n },\n\n /**\n * @param id File ID\n * @returns {string} Identifier for this item that may appear in the browser's local storage\n */\n _getLocalStorageId: function(id) {\n var formatVersion = \"5.0\",\n name = getName(id),\n size = getSize(id),\n chunkSize = getChunkSize(id),\n endpoint = getEndpoint(id),\n customKeys = resume.customKeys(id),\n localStorageId = qq.format(\"qq{}resume{}-{}-{}-{}-{}\", namespace, formatVersion, name, size, chunkSize, endpoint);\n\n customKeys.forEach(function(key) {\n localStorageId += \"-\" + key;\n });\n\n return localStorageId;\n },\n\n _getMimeType: function(id) {\n return handler.getFile(id).type;\n },\n\n _getPersistableData: function(id) {\n return handler._getFileState(id).chunking;\n },\n\n /**\n * @param id ID of the associated file\n * @returns {number} Number of parts this file can be divided into, or undefined if chunking is not supported in this UA\n */\n _getTotalChunks: function(id) {\n if (chunking) {\n var fileSize = getSize(id),\n chunkSize = getChunkSize(id);\n\n return Math.ceil(fileSize / chunkSize);\n }\n },\n\n _getXhr: function(id, optChunkIdx) {\n var chunkIdx = optChunkIdx == null ? -1 : optChunkIdx;\n return handler._getFileState(id).temp.xhrs[chunkIdx];\n },\n\n _getXhrs: function(id) {\n return handler._getFileState(id).temp.xhrs;\n },\n\n // Iterates through all XHR handler-created resume records (in local storage),\n // invoking the passed callback and passing in the key and value of each local storage record.\n _iterateResumeRecords: function(callback) {\n if (resumeEnabled) {\n qq.each(localStorage, function(key, item) {\n if (key.indexOf(qq.format(\"qq{}resume\", namespace)) === 0) {\n var uploadData = JSON.parse(item);\n callback(key, uploadData);\n }\n });\n }\n },\n\n _initTempState: function(id) {\n handler._getFileState(id).temp = {\n ajaxRequesters: {},\n chunkProgress: {},\n xhrs: {},\n cachedChunks: {}\n };\n },\n\n _markNotResumable: function(id) {\n handler._getFileState(id).notResumable = true;\n },\n\n // Removes a chunked upload record from local storage, if possible.\n // Returns true if the item was removed, false otherwise.\n _maybeDeletePersistedChunkData: function(id) {\n var localStorageId;\n\n if (resumeEnabled && handler.isResumable(id)) {\n localStorageId = handler._getLocalStorageId(id);\n\n if (localStorageId && localStorage.getItem(localStorageId)) {\n localStorage.removeItem(localStorageId);\n return true;\n }\n }\n\n return false;\n },\n\n // If this is a resumable upload, grab the relevant data from storage and items in memory that track this upload\n // so we can pick up from where we left off.\n _maybePrepareForResume: function(id) {\n var state = handler._getFileState(id),\n localStorageId, persistedData;\n\n // Resume is enabled and possible and this is the first time we've tried to upload this file in this session,\n // so prepare for a resume attempt.\n if (resumeEnabled && state.key === undefined) {\n localStorageId = handler._getLocalStorageId(id);\n persistedData = localStorage.getItem(localStorageId);\n\n // If we found this item in local storage, maybe we should resume it.\n if (persistedData) {\n persistedData = JSON.parse(persistedData);\n\n // If we found a resume record but we have already handled this file in this session,\n // don't try to resume it & ensure we don't persist future check data\n if (getDataByUuid(persistedData.uuid)) {\n handler._markNotResumable(id);\n }\n else {\n log(qq.format(\"Identified file with ID {} and name of {} as resumable.\", id, getName(id)));\n\n onUuidChanged(id, persistedData.uuid);\n\n state.key = persistedData.key;\n state.chunking = persistedData.chunking;\n state.loaded = persistedData.loaded;\n state.customResumeData = persistedData.customResumeData;\n state.attemptingResume = true;\n\n handler.moveInProgressToRemaining(id);\n }\n }\n }\n },\n\n // Persist any data needed to resume this upload in a new session.\n _maybePersistChunkedState: function(id) {\n var state = handler._getFileState(id),\n localStorageId, persistedData;\n\n // If local storage isn't supported by the browser, or if resume isn't enabled or possible, give up\n if (resumeEnabled && handler.isResumable(id)) {\n var customResumeData = getCustomResumeData(id);\n\n localStorageId = handler._getLocalStorageId(id);\n\n persistedData = {\n name: getName(id),\n size: getSize(id),\n uuid: getUuid(id),\n key: state.key,\n chunking: state.chunking,\n loaded: state.loaded,\n lastUpdated: Date.now(),\n };\n\n if (customResumeData) {\n persistedData.customResumeData = customResumeData;\n }\n\n try {\n localStorage.setItem(localStorageId, JSON.stringify(persistedData));\n }\n catch (error) {\n log(qq.format(\"Unable to save resume data for '{}' due to error: '{}'.\", id, error.toString()), \"warn\");\n }\n }\n },\n\n _registerProgressHandler: function(id, chunkIdx, chunkSize) {\n var xhr = handler._getXhr(id, chunkIdx),\n name = getName(id),\n progressCalculator = {\n simple: function(loaded, total) {\n var fileSize = getSize(id);\n\n if (loaded === total) {\n onProgress(id, name, fileSize, fileSize);\n }\n else {\n onProgress(id, name, (loaded >= fileSize ? fileSize - 1 : loaded), fileSize);\n }\n },\n\n chunked: function(loaded, total) {\n var chunkProgress = handler._getFileState(id).temp.chunkProgress,\n totalSuccessfullyLoadedForFile = handler._getFileState(id).loaded,\n loadedForRequest = loaded,\n totalForRequest = total,\n totalFileSize = getSize(id),\n estActualChunkLoaded = loadedForRequest - (totalForRequest - chunkSize),\n totalLoadedForFile = totalSuccessfullyLoadedForFile;\n\n chunkProgress[chunkIdx] = estActualChunkLoaded;\n\n qq.each(chunkProgress, function(chunkIdx, chunkLoaded) {\n totalLoadedForFile += chunkLoaded;\n });\n\n onProgress(id, name, totalLoadedForFile, totalFileSize);\n }\n };\n\n xhr.upload.onprogress = function(e) {\n if (e.lengthComputable) {\n /* jshint eqnull: true */\n var type = chunkSize == null ? \"simple\" : \"chunked\";\n progressCalculator[type](e.loaded, e.total);\n }\n };\n },\n\n /**\n * Registers an XHR transport instance created elsewhere.\n *\n * @param id ID of the associated file\n * @param optChunkIdx The chunk index associated with this XHR, if applicable\n * @param xhr XMLHttpRequest object instance\n * @param optAjaxRequester `qq.AjaxRequester` associated with this request, if applicable.\n * @returns {XMLHttpRequest}\n */\n _registerXhr: function(id, optChunkIdx, xhr, optAjaxRequester) {\n var xhrsId = optChunkIdx == null ? -1 : optChunkIdx,\n tempState = handler._getFileState(id).temp;\n\n tempState.xhrs = tempState.xhrs || {};\n tempState.ajaxRequesters = tempState.ajaxRequesters || {};\n\n tempState.xhrs[xhrsId] = xhr;\n\n if (optAjaxRequester) {\n tempState.ajaxRequesters[xhrsId] = optAjaxRequester;\n }\n\n return xhr;\n },\n\n // Deletes any local storage records that are \"expired\".\n _removeExpiredChunkingRecords: function() {\n var expirationDays = resume.recordsExpireIn;\n\n handler._iterateResumeRecords(function(key, uploadData) {\n var expirationDate = new Date(uploadData.lastUpdated);\n\n // transform updated date into expiration date\n expirationDate.setDate(expirationDate.getDate() + expirationDays);\n\n if (expirationDate.getTime() <= Date.now()) {\n log(\"Removing expired resume record with key \" + key);\n localStorage.removeItem(key);\n }\n });\n },\n\n /**\n * Determine if the associated file should be chunked.\n *\n * @param id ID of the associated file\n * @returns {*} true if chunking is enabled, possible, and the file can be split into more than 1 part\n */\n _shouldChunkThisFile: function(id) {\n var state = handler._getFileState(id);\n\n // file may no longer be available if it was recently cancelled\n if (state) {\n if (!state.chunking) {\n handler.reevaluateChunking(id);\n }\n\n return state.chunking.enabled;\n }\n }\n });\n};\n","/*globals qq, XMLHttpRequest*/\nqq.DeleteFileAjaxRequester = function(o) {\n \"use strict\";\n\n var requester,\n options = {\n method: \"DELETE\",\n uuidParamName: \"qquuid\",\n endpointStore: {},\n maxConnections: 3,\n customHeaders: function(id) {return {};},\n paramsStore: {},\n cors: {\n expected: false,\n sendCredentials: false\n },\n log: function(str, level) {},\n onDelete: function(id) {},\n onDeleteComplete: function(id, xhrOrXdr, isError) {}\n };\n\n qq.extend(options, o);\n\n function getMandatedParams() {\n if (options.method.toUpperCase() === \"POST\") {\n return {\n _method: \"DELETE\"\n };\n }\n\n return {};\n }\n\n requester = qq.extend(this, new qq.AjaxRequester({\n acceptHeader: \"application/json\",\n validMethods: [\"POST\", \"DELETE\"],\n method: options.method,\n endpointStore: options.endpointStore,\n paramsStore: options.paramsStore,\n mandatedParams: getMandatedParams(),\n maxConnections: options.maxConnections,\n customHeaders: function(id) {\n return options.customHeaders.get(id);\n },\n log: options.log,\n onSend: options.onDelete,\n onComplete: options.onDeleteComplete,\n cors: options.cors\n }));\n\n qq.extend(this, {\n sendDelete: function(id, uuid, additionalMandatedParams) {\n var additionalOptions = additionalMandatedParams || {};\n\n options.log(\"Submitting delete file request for \" + id);\n\n if (options.method === \"DELETE\") {\n requester.initTransport(id)\n .withPath(uuid)\n .withParams(additionalOptions)\n .send();\n }\n else {\n additionalOptions[options.uuidParamName] = uuid;\n requester.initTransport(id)\n .withParams(additionalOptions)\n .send();\n }\n }\n });\n};\n","/*global qq, define */\n/*jshint strict:false,bitwise:false,nonew:false,asi:true,-W064,-W116,-W089 */\n/**\n * Mega pixel image rendering library for iOS6+\n *\n * Fixes iOS6+'s image file rendering issue for large size image (over mega-pixel),\n * which causes unexpected subsampling when drawing it in canvas.\n * By using this library, you can safely render the image with proper stretching.\n *\n * Copyright (c) 2012 Shinichi Tomita \n * Released under the MIT license\n *\n * Heavily modified by Widen for Fine Uploader\n */\n(function() {\n\n /**\n * Detect subsampling in loaded image.\n * In iOS, larger images than 2M pixels may be subsampled in rendering.\n */\n function detectSubsampling(img) {\n var iw = img.naturalWidth,\n ih = img.naturalHeight,\n canvas = document.createElement(\"canvas\"),\n ctx;\n\n if (iw * ih > 1024 * 1024) { // subsampling may happen over megapixel image\n canvas.width = canvas.height = 1;\n ctx = canvas.getContext(\"2d\");\n ctx.drawImage(img, -iw + 1, 0);\n // subsampled image becomes half smaller in rendering size.\n // check alpha channel value to confirm image is covering edge pixel or not.\n // if alpha value is 0 image is not covering, hence subsampled.\n return ctx.getImageData(0, 0, 1, 1).data[3] === 0;\n } else {\n return false;\n }\n }\n\n /**\n * Detecting vertical squash in loaded image.\n * Fixes a bug which squash image vertically while drawing into canvas for some images.\n */\n function detectVerticalSquash(img, iw, ih) {\n var canvas = document.createElement(\"canvas\"),\n sy = 0,\n ey = ih,\n py = ih,\n ctx, data, alpha, ratio;\n\n canvas.width = 1;\n canvas.height = ih;\n ctx = canvas.getContext(\"2d\");\n ctx.drawImage(img, 0, 0);\n data = ctx.getImageData(0, 0, 1, ih).data;\n\n // search image edge pixel position in case it is squashed vertically.\n while (py > sy) {\n alpha = data[(py - 1) * 4 + 3];\n if (alpha === 0) {\n ey = py;\n } else {\n sy = py;\n }\n py = (ey + sy) >> 1;\n }\n\n ratio = (py / ih);\n return (ratio === 0) ? 1 : ratio;\n }\n\n /**\n * Rendering image element (with resizing) and get its data URL\n */\n function renderImageToDataURL(img, blob, options, doSquash) {\n var canvas = document.createElement(\"canvas\"),\n mime = options.mime || \"image/jpeg\",\n promise = new qq.Promise();\n\n renderImageToCanvas(img, blob, canvas, options, doSquash)\n .then(function() {\n promise.success(\n canvas.toDataURL(mime, options.quality || 0.8)\n );\n });\n\n return promise;\n }\n\n function maybeCalculateDownsampledDimensions(spec) {\n var maxPixels = 5241000; //iOS specific value\n\n if (!qq.ios()) {\n throw new qq.Error(\"Downsampled dimensions can only be reliably calculated for iOS!\");\n }\n\n if (spec.origHeight * spec.origWidth > maxPixels) {\n return {\n newHeight: Math.round(Math.sqrt(maxPixels * (spec.origHeight / spec.origWidth))),\n newWidth: Math.round(Math.sqrt(maxPixels * (spec.origWidth / spec.origHeight)))\n };\n }\n }\n\n /**\n * Rendering image element (with resizing) into the canvas element\n */\n function renderImageToCanvas(img, blob, canvas, options, doSquash) {\n var iw = img.naturalWidth,\n ih = img.naturalHeight,\n width = options.width,\n height = options.height,\n ctx = canvas.getContext(\"2d\"),\n promise = new qq.Promise(),\n modifiedDimensions;\n\n ctx.save();\n\n if (options.resize) {\n return renderImageToCanvasWithCustomResizer({\n blob: blob,\n canvas: canvas,\n image: img,\n imageHeight: ih,\n imageWidth: iw,\n orientation: options.orientation,\n resize: options.resize,\n targetHeight: height,\n targetWidth: width\n });\n }\n\n if (!qq.supportedFeatures.unlimitedScaledImageSize) {\n modifiedDimensions = maybeCalculateDownsampledDimensions({\n origWidth: width,\n origHeight: height\n });\n\n if (modifiedDimensions) {\n qq.log(qq.format(\"Had to reduce dimensions due to device limitations from {}w / {}h to {}w / {}h\",\n width, height, modifiedDimensions.newWidth, modifiedDimensions.newHeight),\n \"warn\");\n\n width = modifiedDimensions.newWidth;\n height = modifiedDimensions.newHeight;\n }\n }\n\n transformCoordinate(canvas, width, height, options.orientation);\n\n // Fine Uploader specific: Save some CPU cycles if not using iOS\n // Assumption: This logic is only needed to overcome iOS image sampling issues\n if (qq.ios()) {\n (function() {\n if (detectSubsampling(img)) {\n iw /= 2;\n ih /= 2;\n }\n\n var d = 1024, // size of tiling canvas\n tmpCanvas = document.createElement(\"canvas\"),\n vertSquashRatio = doSquash ? detectVerticalSquash(img, iw, ih) : 1,\n dw = Math.ceil(d * width / iw),\n dh = Math.ceil(d * height / ih / vertSquashRatio),\n sy = 0,\n dy = 0,\n tmpCtx, sx, dx;\n\n tmpCanvas.width = tmpCanvas.height = d;\n tmpCtx = tmpCanvas.getContext(\"2d\");\n\n while (sy < ih) {\n sx = 0;\n dx = 0;\n while (sx < iw) {\n tmpCtx.clearRect(0, 0, d, d);\n tmpCtx.drawImage(img, -sx, -sy);\n ctx.drawImage(tmpCanvas, 0, 0, d, d, dx, dy, dw, dh);\n sx += d;\n dx += dw;\n }\n sy += d;\n dy += dh;\n }\n ctx.restore();\n tmpCanvas = tmpCtx = null;\n }());\n }\n else {\n ctx.drawImage(img, 0, 0, width, height);\n }\n\n canvas.qqImageRendered && canvas.qqImageRendered();\n promise.success();\n\n return promise;\n }\n\n function renderImageToCanvasWithCustomResizer(resizeInfo) {\n var blob = resizeInfo.blob,\n image = resizeInfo.image,\n imageHeight = resizeInfo.imageHeight,\n imageWidth = resizeInfo.imageWidth,\n orientation = resizeInfo.orientation,\n promise = new qq.Promise(),\n resize = resizeInfo.resize,\n sourceCanvas = document.createElement(\"canvas\"),\n sourceCanvasContext = sourceCanvas.getContext(\"2d\"),\n targetCanvas = resizeInfo.canvas,\n targetHeight = resizeInfo.targetHeight,\n targetWidth = resizeInfo.targetWidth;\n\n transformCoordinate(sourceCanvas, imageWidth, imageHeight, orientation);\n\n targetCanvas.height = targetHeight;\n targetCanvas.width = targetWidth;\n\n sourceCanvasContext.drawImage(image, 0, 0);\n\n resize({\n blob: blob,\n height: targetHeight,\n image: image,\n sourceCanvas: sourceCanvas,\n targetCanvas: targetCanvas,\n width: targetWidth\n })\n .then(\n function success() {\n targetCanvas.qqImageRendered && targetCanvas.qqImageRendered();\n promise.success();\n },\n promise.failure\n );\n\n return promise;\n }\n\n /**\n * Transform canvas coordination according to specified frame size and orientation\n * Orientation value is from EXIF tag\n */\n function transformCoordinate(canvas, width, height, orientation) {\n switch (orientation) {\n case 5:\n case 6:\n case 7:\n case 8:\n canvas.width = height;\n canvas.height = width;\n break;\n default:\n canvas.width = width;\n canvas.height = height;\n }\n var ctx = canvas.getContext(\"2d\");\n switch (orientation) {\n case 2:\n // horizontal flip\n ctx.translate(width, 0);\n ctx.scale(-1, 1);\n break;\n case 3:\n // 180 rotate left\n ctx.translate(width, height);\n ctx.rotate(Math.PI);\n break;\n case 4:\n // vertical flip\n ctx.translate(0, height);\n ctx.scale(1, -1);\n break;\n case 5:\n // vertical flip + 90 rotate right\n ctx.rotate(0.5 * Math.PI);\n ctx.scale(1, -1);\n break;\n case 6:\n // 90 rotate right\n ctx.rotate(0.5 * Math.PI);\n ctx.translate(0, -height);\n break;\n case 7:\n // horizontal flip + 90 rotate right\n ctx.rotate(0.5 * Math.PI);\n ctx.translate(width, -height);\n ctx.scale(-1, 1);\n break;\n case 8:\n // 90 rotate left\n ctx.rotate(-0.5 * Math.PI);\n ctx.translate(-width, 0);\n break;\n default:\n break;\n }\n }\n\n /**\n * MegaPixImage class\n */\n function MegaPixImage(srcImage, errorCallback) {\n var self = this;\n\n if (window.Blob && srcImage instanceof Blob) {\n (function() {\n var img = new Image(),\n URL = window.URL && window.URL.createObjectURL ? window.URL :\n window.webkitURL && window.webkitURL.createObjectURL ? window.webkitURL : null;\n if (!URL) { throw Error(\"No createObjectURL function found to create blob url\"); }\n img.src = URL.createObjectURL(srcImage);\n self.blob = srcImage;\n srcImage = img;\n }());\n }\n if (!srcImage.naturalWidth && !srcImage.naturalHeight) {\n srcImage.onload = function() {\n var listeners = self.imageLoadListeners;\n if (listeners) {\n self.imageLoadListeners = null;\n // IE11 doesn't reliably report actual image dimensions immediately after onload for small files,\n // so let's push this to the end of the UI thread queue.\n setTimeout(function() {\n for (var i = 0, len = listeners.length; i < len; i++) {\n listeners[i]();\n }\n }, 0);\n }\n };\n srcImage.onerror = errorCallback;\n this.imageLoadListeners = [];\n }\n this.srcImage = srcImage;\n }\n\n /**\n * Rendering megapix image into specified target element\n */\n MegaPixImage.prototype.render = function(target, options) {\n options = options || {};\n\n var self = this,\n imgWidth = this.srcImage.naturalWidth,\n imgHeight = this.srcImage.naturalHeight,\n width = options.width,\n height = options.height,\n maxWidth = options.maxWidth,\n maxHeight = options.maxHeight,\n doSquash = !this.blob || this.blob.type === \"image/jpeg\",\n tagName = target.tagName.toLowerCase(),\n opt;\n\n if (this.imageLoadListeners) {\n this.imageLoadListeners.push(function() { self.render(target, options); });\n return;\n }\n\n if (width && !height) {\n height = (imgHeight * width / imgWidth) << 0;\n } else if (height && !width) {\n width = (imgWidth * height / imgHeight) << 0;\n } else {\n width = imgWidth;\n height = imgHeight;\n }\n if (maxWidth && width > maxWidth) {\n width = maxWidth;\n height = (imgHeight * width / imgWidth) << 0;\n }\n if (maxHeight && height > maxHeight) {\n height = maxHeight;\n width = (imgWidth * height / imgHeight) << 0;\n }\n\n opt = { width: width, height: height },\n qq.each(options, function(optionsKey, optionsValue) {\n opt[optionsKey] = optionsValue;\n });\n\n if (tagName === \"img\") {\n (function() {\n var oldTargetSrc = target.src;\n renderImageToDataURL(self.srcImage, self.blob, opt, doSquash)\n .then(function(dataUri) {\n target.src = dataUri;\n oldTargetSrc === target.src && target.onload();\n });\n }());\n } else if (tagName === \"canvas\") {\n renderImageToCanvas(this.srcImage, this.blob, target, opt, doSquash);\n }\n if (typeof this.onrender === \"function\") {\n this.onrender(target);\n }\n };\n\n qq.MegaPixImage = MegaPixImage;\n})();\n","/*globals qq */\n/**\n * Draws a thumbnail of a Blob/File/URL onto an or .\n *\n * @constructor\n */\nqq.ImageGenerator = function(log) {\n \"use strict\";\n\n function isImg(el) {\n return el.tagName.toLowerCase() === \"img\";\n }\n\n function isCanvas(el) {\n return el.tagName.toLowerCase() === \"canvas\";\n }\n\n function isImgCorsSupported() {\n return new Image().crossOrigin !== undefined;\n }\n\n function isCanvasSupported() {\n var canvas = document.createElement(\"canvas\");\n\n return canvas.getContext && canvas.getContext(\"2d\");\n }\n\n // This is only meant to determine the MIME type of a renderable image file.\n // It is used to ensure images drawn from a URL that have transparent backgrounds\n // are rendered correctly, among other things.\n function determineMimeOfFileName(nameWithPath) {\n /*jshint -W015 */\n var pathSegments = nameWithPath.split(\"/\"),\n name = pathSegments[pathSegments.length - 1].split(\"?\")[0],\n extension = qq.getExtension(name);\n\n extension = extension && extension.toLowerCase();\n\n switch (extension) {\n case \"jpeg\":\n case \"jpg\":\n return \"image/jpeg\";\n case \"png\":\n return \"image/png\";\n case \"bmp\":\n return \"image/bmp\";\n case \"gif\":\n return \"image/gif\";\n case \"tiff\":\n case \"tif\":\n return \"image/tiff\";\n }\n }\n\n // This will likely not work correctly in IE8 and older.\n // It's only used as part of a formula to determine\n // if a canvas can be used to scale a server-hosted thumbnail.\n // If canvas isn't supported by the UA (IE8 and older)\n // this method should not even be called.\n function isCrossOrigin(url) {\n var targetAnchor = document.createElement(\"a\"),\n targetProtocol, targetHostname, targetPort;\n\n targetAnchor.href = url;\n\n targetProtocol = targetAnchor.protocol;\n targetPort = targetAnchor.port;\n targetHostname = targetAnchor.hostname;\n\n if (targetProtocol.toLowerCase() !== window.location.protocol.toLowerCase()) {\n return true;\n }\n\n if (targetHostname.toLowerCase() !== window.location.hostname.toLowerCase()) {\n return true;\n }\n\n // IE doesn't take ports into consideration when determining if two endpoints are same origin.\n if (targetPort !== window.location.port && !qq.ie()) {\n return true;\n }\n\n return false;\n }\n\n function registerImgLoadListeners(img, promise) {\n img.onload = function() {\n img.onload = null;\n img.onerror = null;\n promise.success(img);\n };\n\n img.onerror = function() {\n img.onload = null;\n img.onerror = null;\n log(\"Problem drawing thumbnail!\", \"error\");\n promise.failure(img, \"Problem drawing thumbnail!\");\n };\n }\n\n function registerCanvasDrawImageListener(canvas, promise) {\n // The image is drawn on the canvas by a third-party library,\n // and we want to know when this is completed. Since the library\n // may invoke drawImage many times in a loop, we need to be called\n // back when the image is fully rendered. So, we are expecting the\n // code that draws this image to follow a convention that involves a\n // function attached to the canvas instance be invoked when it is done.\n canvas.qqImageRendered = function() {\n promise.success(canvas);\n };\n }\n\n // Fulfills a `qq.Promise` when an image has been drawn onto the target,\n // whether that is a or an . The attempt is considered a\n // failure if the target is not an or a , or if the drawing\n // attempt was not successful.\n function registerThumbnailRenderedListener(imgOrCanvas, promise) {\n var registered = isImg(imgOrCanvas) || isCanvas(imgOrCanvas);\n\n if (isImg(imgOrCanvas)) {\n registerImgLoadListeners(imgOrCanvas, promise);\n }\n else if (isCanvas(imgOrCanvas)) {\n registerCanvasDrawImageListener(imgOrCanvas, promise);\n }\n else {\n promise.failure(imgOrCanvas);\n log(qq.format(\"Element container of type {} is not supported!\", imgOrCanvas.tagName), \"error\");\n }\n\n return registered;\n }\n\n // Draw a preview iff the current UA can natively display it.\n // Also rotate the image if necessary.\n function draw(fileOrBlob, container, options) {\n var drawPreview = new qq.Promise(),\n identifier = new qq.Identify(fileOrBlob, log),\n maxSize = options.maxSize,\n // jshint eqnull:true\n orient = options.orient == null ? true : options.orient,\n megapixErrorHandler = function() {\n container.onerror = null;\n container.onload = null;\n log(\"Could not render preview, file may be too large!\", \"error\");\n drawPreview.failure(container, \"Browser cannot render image!\");\n };\n\n identifier.isPreviewable().then(\n function(mime) {\n // If options explicitly specify that Orientation is not desired,\n // replace the orient task with a dummy promise that \"succeeds\" immediately.\n var dummyExif = {\n parse: function() {\n return new qq.Promise().success();\n }\n },\n exif = orient ? new qq.Exif(fileOrBlob, log) : dummyExif,\n mpImg = new qq.MegaPixImage(fileOrBlob, megapixErrorHandler);\n\n if (registerThumbnailRenderedListener(container, drawPreview)) {\n exif.parse().then(\n function(exif) {\n var orientation = exif && exif.Orientation;\n\n mpImg.render(container, {\n maxWidth: maxSize,\n maxHeight: maxSize,\n orientation: orientation,\n mime: mime,\n resize: options.customResizeFunction\n });\n },\n\n function(failureMsg) {\n log(qq.format(\"EXIF data could not be parsed ({}). Assuming orientation = 1.\", failureMsg));\n\n mpImg.render(container, {\n maxWidth: maxSize,\n maxHeight: maxSize,\n mime: mime,\n resize: options.customResizeFunction\n });\n }\n );\n }\n },\n\n function() {\n log(\"Not previewable\");\n drawPreview.failure(container, \"Not previewable\");\n }\n );\n\n return drawPreview;\n }\n\n function drawOnCanvasOrImgFromUrl(url, canvasOrImg, draw, maxSize, customResizeFunction) {\n var tempImg = new Image(),\n tempImgRender = new qq.Promise();\n\n registerThumbnailRenderedListener(tempImg, tempImgRender);\n\n if (isCrossOrigin(url)) {\n tempImg.crossOrigin = \"anonymous\";\n }\n\n tempImg.src = url;\n\n tempImgRender.then(\n function rendered() {\n registerThumbnailRenderedListener(canvasOrImg, draw);\n\n var mpImg = new qq.MegaPixImage(tempImg);\n mpImg.render(canvasOrImg, {\n maxWidth: maxSize,\n maxHeight: maxSize,\n mime: determineMimeOfFileName(url),\n resize: customResizeFunction\n });\n },\n\n draw.failure\n );\n }\n\n function drawOnImgFromUrlWithCssScaling(url, img, draw, maxSize) {\n registerThumbnailRenderedListener(img, draw);\n // NOTE: The fact that maxWidth/height is set on the thumbnail for scaled images\n // that must drop back to CSS is known and exploited by the templating module.\n // In this module, we pre-render \"waiting\" thumbs for all files immediately after they\n // are submitted, and we must be sure to pass any style associated with the \"waiting\" preview.\n qq(img).css({\n maxWidth: maxSize + \"px\",\n maxHeight: maxSize + \"px\"\n });\n\n img.src = url;\n }\n\n // Draw a (server-hosted) thumbnail given a URL.\n // This will optionally scale the thumbnail as well.\n // It attempts to use to scale, but will fall back\n // to max-width and max-height style properties if the UA\n // doesn't support canvas or if the images is cross-domain and\n // the UA doesn't support the crossorigin attribute on img tags,\n // which is required to scale a cross-origin image using &\n // then export it back to an .\n function drawFromUrl(url, container, options) {\n var draw = new qq.Promise(),\n scale = options.scale,\n maxSize = scale ? options.maxSize : null;\n\n // container is an img, scaling needed\n if (scale && isImg(container)) {\n // Iff canvas is available in this UA, try to use it for scaling.\n // Otherwise, fall back to CSS scaling\n if (isCanvasSupported()) {\n // Attempt to use for image scaling,\n // but we must fall back to scaling via CSS/styles\n // if this is a cross-origin image and the UA doesn't support CORS.\n if (isCrossOrigin(url) && !isImgCorsSupported()) {\n drawOnImgFromUrlWithCssScaling(url, container, draw, maxSize);\n }\n else {\n drawOnCanvasOrImgFromUrl(url, container, draw, maxSize);\n }\n }\n else {\n drawOnImgFromUrlWithCssScaling(url, container, draw, maxSize);\n }\n }\n // container is a canvas, scaling optional\n else if (isCanvas(container)) {\n drawOnCanvasOrImgFromUrl(url, container, draw, maxSize);\n }\n // container is an img & no scaling: just set the src attr to the passed url\n else if (registerThumbnailRenderedListener(container, draw)) {\n container.src = url;\n }\n\n return draw;\n }\n\n qq.extend(this, {\n /**\n * Generate a thumbnail. Depending on the arguments, this may either result in\n * a client-side rendering of an image (if a `Blob` is supplied) or a server-generated\n * image that may optionally be scaled client-side using or CSS/styles (as a fallback).\n *\n * @param fileBlobOrUrl a `File`, `Blob`, or a URL pointing to the image\n * @param container or to contain the preview\n * @param options possible properties include `maxSize` (int), `orient` (bool - default true), resize` (bool - default true), and `customResizeFunction`.\n * @returns qq.Promise fulfilled when the preview has been drawn, or the attempt has failed\n */\n generate: function(fileBlobOrUrl, container, options) {\n if (qq.isString(fileBlobOrUrl)) {\n log(\"Attempting to update thumbnail based on server response.\");\n return drawFromUrl(fileBlobOrUrl, container, options || {});\n }\n else {\n log(\"Attempting to draw client-side image preview.\");\n return draw(fileBlobOrUrl, container, options || {});\n }\n }\n });\n\n /**/\n this._testing = {};\n this._testing.isImg = isImg;\n this._testing.isCanvas = isCanvas;\n this._testing.isCrossOrigin = isCrossOrigin;\n this._testing.determineMimeOfFileName = determineMimeOfFileName;\n /* */\n};\n","/*globals qq */\n/**\n * EXIF image data parser. Currently only parses the Orientation tag value,\n * but this may be expanded to other tags in the future.\n *\n * @param fileOrBlob Attempt to parse EXIF data in this `Blob`\n * @constructor\n */\nqq.Exif = function(fileOrBlob, log) {\n \"use strict\";\n\n // Orientation is the only tag parsed here at this time.\n var TAG_IDS = [274],\n TAG_INFO = {\n 274: {\n name: \"Orientation\",\n bytes: 2\n }\n };\n\n // Convert a little endian (hex string) to big endian (decimal).\n function parseLittleEndian(hex) {\n var result = 0,\n pow = 0;\n\n while (hex.length > 0) {\n result += parseInt(hex.substring(0, 2), 16) * Math.pow(2, pow);\n hex = hex.substring(2, hex.length);\n pow += 8;\n }\n\n return result;\n }\n\n // Find the byte offset, of Application Segment 1 (EXIF).\n // External callers need not supply any arguments.\n function seekToApp1(offset, promise) {\n var theOffset = offset,\n thePromise = promise;\n if (theOffset === undefined) {\n theOffset = 2;\n thePromise = new qq.Promise();\n }\n\n qq.readBlobToHex(fileOrBlob, theOffset, 4).then(function(hex) {\n var match = /^ffe([0-9])/.exec(hex),\n segmentLength;\n\n if (match) {\n if (match[1] !== \"1\") {\n segmentLength = parseInt(hex.slice(4, 8), 16);\n seekToApp1(theOffset + segmentLength + 2, thePromise);\n }\n else {\n thePromise.success(theOffset);\n }\n }\n else {\n thePromise.failure(\"No EXIF header to be found!\");\n }\n });\n\n return thePromise;\n }\n\n // Find the byte offset of Application Segment 1 (EXIF) for valid JPEGs only.\n function getApp1Offset() {\n var promise = new qq.Promise();\n\n qq.readBlobToHex(fileOrBlob, 0, 6).then(function(hex) {\n if (hex.indexOf(\"ffd8\") !== 0) {\n promise.failure(\"Not a valid JPEG!\");\n }\n else {\n seekToApp1().then(function(offset) {\n promise.success(offset);\n },\n function(error) {\n promise.failure(error);\n });\n }\n });\n\n return promise;\n }\n\n // Determine the byte ordering of the EXIF header.\n function isLittleEndian(app1Start) {\n var promise = new qq.Promise();\n\n qq.readBlobToHex(fileOrBlob, app1Start + 10, 2).then(function(hex) {\n promise.success(hex === \"4949\");\n });\n\n return promise;\n }\n\n // Determine the number of directory entries in the EXIF header.\n function getDirEntryCount(app1Start, littleEndian) {\n var promise = new qq.Promise();\n\n qq.readBlobToHex(fileOrBlob, app1Start + 18, 2).then(function(hex) {\n if (littleEndian) {\n return promise.success(parseLittleEndian(hex));\n }\n else {\n promise.success(parseInt(hex, 16));\n }\n });\n\n return promise;\n }\n\n // Get the IFD portion of the EXIF header as a hex string.\n function getIfd(app1Start, dirEntries) {\n var offset = app1Start + 20,\n bytes = dirEntries * 12;\n\n return qq.readBlobToHex(fileOrBlob, offset, bytes);\n }\n\n // Obtain an array of all directory entries (as hex strings) in the EXIF header.\n function getDirEntries(ifdHex) {\n var entries = [],\n offset = 0;\n\n while (offset + 24 <= ifdHex.length) {\n entries.push(ifdHex.slice(offset, offset + 24));\n offset += 24;\n }\n\n return entries;\n }\n\n // Obtain values for all relevant tags and return them.\n function getTagValues(littleEndian, dirEntries) {\n var TAG_VAL_OFFSET = 16,\n tagsToFind = qq.extend([], TAG_IDS),\n vals = {};\n\n qq.each(dirEntries, function(idx, entry) {\n var idHex = entry.slice(0, 4),\n id = littleEndian ? parseLittleEndian(idHex) : parseInt(idHex, 16),\n tagsToFindIdx = tagsToFind.indexOf(id),\n tagValHex, tagName, tagValLength;\n\n if (tagsToFindIdx >= 0) {\n tagName = TAG_INFO[id].name;\n tagValLength = TAG_INFO[id].bytes;\n tagValHex = entry.slice(TAG_VAL_OFFSET, TAG_VAL_OFFSET + (tagValLength * 2));\n vals[tagName] = littleEndian ? parseLittleEndian(tagValHex) : parseInt(tagValHex, 16);\n\n tagsToFind.splice(tagsToFindIdx, 1);\n }\n\n if (tagsToFind.length === 0) {\n return false;\n }\n });\n\n return vals;\n }\n\n qq.extend(this, {\n /**\n * Attempt to parse the EXIF header for the `Blob` associated with this instance.\n *\n * @returns {qq.Promise} To be fulfilled when the parsing is complete.\n * If successful, the parsed EXIF header as an object will be included.\n */\n parse: function() {\n var parser = new qq.Promise(),\n onParseFailure = function(message) {\n log(qq.format(\"EXIF header parse failed: '{}' \", message));\n parser.failure(message);\n };\n\n getApp1Offset().then(function(app1Offset) {\n log(qq.format(\"Moving forward with EXIF header parsing for '{}'\", fileOrBlob.name === undefined ? \"blob\" : fileOrBlob.name));\n\n isLittleEndian(app1Offset).then(function(littleEndian) {\n\n log(qq.format(\"EXIF Byte order is {} endian\", littleEndian ? \"little\" : \"big\"));\n\n getDirEntryCount(app1Offset, littleEndian).then(function(dirEntryCount) {\n\n log(qq.format(\"Found {} APP1 directory entries\", dirEntryCount));\n\n getIfd(app1Offset, dirEntryCount).then(function(ifdHex) {\n var dirEntries = getDirEntries(ifdHex),\n tagValues = getTagValues(littleEndian, dirEntries);\n\n log(\"Successfully parsed some EXIF tags\");\n\n parser.success(tagValues);\n }, onParseFailure);\n }, onParseFailure);\n }, onParseFailure);\n }, onParseFailure);\n\n return parser;\n }\n });\n\n /**/\n this._testing = {};\n this._testing.parseLittleEndian = parseLittleEndian;\n /* */\n};\n","/*globals qq */\nqq.Identify = function(fileOrBlob, log) {\n \"use strict\";\n\n function isIdentifiable(magicBytes, questionableBytes) {\n var identifiable = false,\n magicBytesEntries = [].concat(magicBytes);\n\n qq.each(magicBytesEntries, function(idx, magicBytesArrayEntry) {\n if (questionableBytes.indexOf(magicBytesArrayEntry) === 0) {\n identifiable = true;\n return false;\n }\n });\n\n return identifiable;\n }\n\n qq.extend(this, {\n /**\n * Determines if a Blob can be displayed natively in the current browser. This is done by reading magic\n * bytes in the beginning of the file, so this is an asynchronous operation. Before we attempt to read the\n * file, we will examine the blob's type attribute to save CPU cycles.\n *\n * @returns {qq.Promise} Promise that is fulfilled when identification is complete.\n * If successful, the MIME string is passed to the success handler.\n */\n isPreviewable: function() {\n var self = this,\n identifier = new qq.Promise(),\n previewable = false,\n name = fileOrBlob.name === undefined ? \"blob\" : fileOrBlob.name;\n\n log(qq.format(\"Attempting to determine if {} can be rendered in this browser\", name));\n\n log(\"First pass: check type attribute of blob object.\");\n\n if (this.isPreviewableSync()) {\n log(\"Second pass: check for magic bytes in file header.\");\n\n qq.readBlobToHex(fileOrBlob, 0, 4).then(function(hex) {\n qq.each(self.PREVIEWABLE_MIME_TYPES, function(mime, bytes) {\n if (isIdentifiable(bytes, hex)) {\n // Safari is the only supported browser that can deal with TIFFs natively,\n // so, if this is a TIFF and the UA isn't Safari, declare this file \"non-previewable\".\n if (mime !== \"image/tiff\" || qq.supportedFeatures.tiffPreviews) {\n previewable = true;\n identifier.success(mime);\n }\n\n return false;\n }\n });\n\n log(qq.format(\"'{}' is {} able to be rendered in this browser\", name, previewable ? \"\" : \"NOT\"));\n\n if (!previewable) {\n identifier.failure();\n }\n },\n function() {\n log(\"Error reading file w/ name '\" + name + \"'. Not able to be rendered in this browser.\");\n identifier.failure();\n });\n }\n else {\n identifier.failure();\n }\n\n return identifier;\n },\n\n /**\n * Determines if a Blob can be displayed natively in the current browser. This is done by checking the\n * blob's type attribute. This is a synchronous operation, useful for situations where an asynchronous operation\n * would be challenging to support. Note that the blob's type property is not as accurate as reading the\n * file's magic bytes.\n *\n * @returns {Boolean} true if the blob can be rendered in the current browser\n */\n isPreviewableSync: function() {\n var fileMime = fileOrBlob.type,\n // Assumption: This will only ever be executed in browsers that support `Object.keys`.\n isRecognizedImage = qq.indexOf(Object.keys(this.PREVIEWABLE_MIME_TYPES), fileMime) >= 0,\n previewable = false,\n name = fileOrBlob.name === undefined ? \"blob\" : fileOrBlob.name;\n\n if (isRecognizedImage) {\n if (fileMime === \"image/tiff\") {\n previewable = qq.supportedFeatures.tiffPreviews;\n }\n else {\n previewable = true;\n }\n }\n\n !previewable && log(name + \" is not previewable in this browser per the blob's type attr\");\n\n return previewable;\n }\n });\n};\n\nqq.Identify.prototype.PREVIEWABLE_MIME_TYPES = {\n \"image/jpeg\": \"ffd8ff\",\n \"image/gif\": \"474946\",\n \"image/png\": \"89504e\",\n \"image/bmp\": \"424d\",\n \"image/tiff\": [\"49492a00\", \"4d4d002a\"]\n};\n","/*globals qq*/\n/**\n * Attempts to validate an image, wherever possible.\n *\n * @param blob File or Blob representing a user-selecting image.\n * @param log Uses this to post log messages to the console.\n * @constructor\n */\nqq.ImageValidation = function(blob, log) {\n \"use strict\";\n\n /**\n * @param limits Object with possible image-related limits to enforce.\n * @returns {boolean} true if at least one of the limits has a non-zero value\n */\n function hasNonZeroLimits(limits) {\n var atLeastOne = false;\n\n qq.each(limits, function(limit, value) {\n if (value > 0) {\n atLeastOne = true;\n return false;\n }\n });\n\n return atLeastOne;\n }\n\n /**\n * @returns {qq.Promise} The promise is a failure if we can't obtain the width & height.\n * Otherwise, `success` is called on the returned promise with an object containing\n * `width` and `height` properties.\n */\n function getWidthHeight() {\n var sizeDetermination = new qq.Promise();\n\n new qq.Identify(blob, log).isPreviewable().then(function() {\n var image = new Image(),\n url = window.URL && window.URL.createObjectURL ? window.URL :\n window.webkitURL && window.webkitURL.createObjectURL ? window.webkitURL :\n null;\n\n if (url) {\n image.onerror = function() {\n log(\"Cannot determine dimensions for image. May be too large.\", \"error\");\n sizeDetermination.failure();\n };\n\n image.onload = function() {\n sizeDetermination.success({\n width: this.width,\n height: this.height\n });\n };\n\n image.src = url.createObjectURL(blob);\n }\n else {\n log(\"No createObjectURL function available to generate image URL!\", \"error\");\n sizeDetermination.failure();\n }\n }, sizeDetermination.failure);\n\n return sizeDetermination;\n }\n\n /**\n *\n * @param limits Object with possible image-related limits to enforce.\n * @param dimensions Object containing `width` & `height` properties for the image to test.\n * @returns {String || undefined} The name of the failing limit. Undefined if no failing limits.\n */\n function getFailingLimit(limits, dimensions) {\n var failingLimit;\n\n qq.each(limits, function(limitName, limitValue) {\n if (limitValue > 0) {\n var limitMatcher = /(max|min)(Width|Height)/.exec(limitName),\n dimensionPropName = limitMatcher[2].charAt(0).toLowerCase() + limitMatcher[2].slice(1),\n actualValue = dimensions[dimensionPropName];\n\n /*jshint -W015*/\n switch (limitMatcher[1]) {\n case \"min\":\n if (actualValue < limitValue) {\n failingLimit = limitName;\n return false;\n }\n break;\n case \"max\":\n if (actualValue > limitValue) {\n failingLimit = limitName;\n return false;\n }\n break;\n }\n }\n });\n\n return failingLimit;\n }\n\n /**\n * Validate the associated blob.\n *\n * @param limits\n * @returns {qq.Promise} `success` is called on the promise is the image is valid or\n * if the blob is not an image, or if the image is not verifiable.\n * Otherwise, `failure` with the name of the failing limit.\n */\n this.validate = function(limits) {\n var validationEffort = new qq.Promise();\n\n log(\"Attempting to validate image.\");\n\n if (hasNonZeroLimits(limits)) {\n getWidthHeight().then(function(dimensions) {\n var failingLimit = getFailingLimit(limits, dimensions);\n\n if (failingLimit) {\n validationEffort.failure(failingLimit);\n }\n else {\n validationEffort.success();\n }\n }, validationEffort.success);\n }\n else {\n validationEffort.success();\n }\n\n return validationEffort;\n };\n};\n","/* globals qq */\n/**\n * Module used to control populating the initial list of files.\n *\n * @constructor\n */\nqq.Session = function(spec) {\n \"use strict\";\n\n var options = {\n endpoint: null,\n params: {},\n customHeaders: {},\n cors: {},\n addFileRecord: function(sessionData) {},\n log: function(message, level) {}\n };\n\n qq.extend(options, spec, true);\n\n function isJsonResponseValid(response) {\n if (qq.isArray(response)) {\n return true;\n }\n\n options.log(\"Session response is not an array.\", \"error\");\n }\n\n function handleFileItems(fileItems, success, xhrOrXdr, promise) {\n var someItemsIgnored = false;\n\n success = success && isJsonResponseValid(fileItems);\n\n if (success) {\n qq.each(fileItems, function(idx, fileItem) {\n /* jshint eqnull:true */\n if (fileItem.uuid == null) {\n someItemsIgnored = true;\n options.log(qq.format(\"Session response item {} did not include a valid UUID - ignoring.\", idx), \"error\");\n }\n else if (fileItem.name == null) {\n someItemsIgnored = true;\n options.log(qq.format(\"Session response item {} did not include a valid name - ignoring.\", idx), \"error\");\n }\n else {\n try {\n options.addFileRecord(fileItem);\n return true;\n }\n catch (err) {\n someItemsIgnored = true;\n options.log(err.message, \"error\");\n }\n }\n\n return false;\n });\n }\n\n promise[success && !someItemsIgnored ? \"success\" : \"failure\"](fileItems, xhrOrXdr);\n }\n\n // Initiate a call to the server that will be used to populate the initial file list.\n // Returns a `qq.Promise`.\n this.refresh = function() {\n /*jshint indent:false */\n var refreshEffort = new qq.Promise(),\n refreshCompleteCallback = function(response, success, xhrOrXdr) {\n handleFileItems(response, success, xhrOrXdr, refreshEffort);\n },\n requesterOptions = qq.extend({}, options),\n requester = new qq.SessionAjaxRequester(\n qq.extend(requesterOptions, {onComplete: refreshCompleteCallback})\n );\n\n requester.queryServer();\n\n return refreshEffort;\n };\n};\n","/*globals qq, XMLHttpRequest*/\n/**\n * Thin module used to send GET requests to the server, expecting information about session\n * data used to initialize an uploader instance.\n *\n * @param spec Various options used to influence the associated request.\n * @constructor\n */\nqq.SessionAjaxRequester = function(spec) {\n \"use strict\";\n\n var requester,\n options = {\n endpoint: null,\n customHeaders: {},\n params: {},\n cors: {\n expected: false,\n sendCredentials: false\n },\n onComplete: function(response, success, xhrOrXdr) {},\n log: function(str, level) {}\n };\n\n qq.extend(options, spec);\n\n function onComplete(id, xhrOrXdr, isError) {\n var response = null;\n\n /* jshint eqnull:true */\n if (xhrOrXdr.responseText != null) {\n try {\n response = qq.parseJson(xhrOrXdr.responseText);\n }\n catch (err) {\n options.log(\"Problem parsing session response: \" + err.message, \"error\");\n isError = true;\n }\n }\n\n options.onComplete(response, !isError, xhrOrXdr);\n }\n\n requester = qq.extend(this, new qq.AjaxRequester({\n acceptHeader: \"application/json\",\n validMethods: [\"GET\"],\n method: \"GET\",\n endpointStore: {\n get: function() {\n return options.endpoint;\n }\n },\n customHeaders: options.customHeaders,\n log: options.log,\n onComplete: onComplete,\n cors: options.cors\n }));\n\n qq.extend(this, {\n queryServer: function() {\n var params = qq.extend({}, options.params);\n\n options.log(\"Session query request.\");\n\n requester.initTransport(\"sessionRefresh\")\n .withParams(params)\n .withCacheBuster()\n .send();\n }\n });\n};\n","/* globals qq, ExifRestorer */\n/**\n * Controls generation of scaled images based on a reference image encapsulated in a `File` or `Blob`.\n * Scaled images are generated and converted to blobs on-demand.\n * Multiple scaled images per reference image with varying sizes and other properties are supported.\n *\n * @param spec Information about the scaled images to generate.\n * @param log Logger instance\n * @constructor\n */\nqq.Scaler = function(spec, log) {\n \"use strict\";\n\n var self = this,\n customResizeFunction = spec.customResizer,\n includeOriginal = spec.sendOriginal,\n orient = spec.orient,\n defaultType = spec.defaultType,\n defaultQuality = spec.defaultQuality / 100,\n failedToScaleText = spec.failureText,\n includeExif = spec.includeExif,\n sizes = this._getSortedSizes(spec.sizes);\n\n // Revealed API for instances of this module\n qq.extend(this, {\n // If no targeted sizes have been declared or if this browser doesn't support\n // client-side image preview generation, there is no scaling to do.\n enabled: qq.supportedFeatures.scaling && sizes.length > 0,\n\n getFileRecords: function(originalFileUuid, originalFileName, originalBlobOrBlobData) {\n var self = this,\n records = [],\n originalBlob = originalBlobOrBlobData.blob ? originalBlobOrBlobData.blob : originalBlobOrBlobData,\n identifier = new qq.Identify(originalBlob, log);\n\n // If the reference file cannot be rendered natively, we can't create scaled versions.\n if (identifier.isPreviewableSync()) {\n // Create records for each scaled version & add them to the records array, smallest first.\n qq.each(sizes, function(idx, sizeRecord) {\n var outputType = self._determineOutputType({\n defaultType: defaultType,\n requestedType: sizeRecord.type,\n refType: originalBlob.type\n });\n\n records.push({\n uuid: qq.getUniqueId(),\n name: self._getName(originalFileName, {\n name: sizeRecord.name,\n type: outputType,\n refType: originalBlob.type\n }),\n blob: new qq.BlobProxy(originalBlob,\n qq.bind(self._generateScaledImage, self, {\n customResizeFunction: customResizeFunction,\n maxSize: sizeRecord.maxSize,\n orient: orient,\n type: outputType,\n quality: defaultQuality,\n failedText: failedToScaleText,\n includeExif: includeExif,\n log: log\n }))\n });\n });\n\n records.push({\n uuid: originalFileUuid,\n name: originalFileName,\n size: originalBlob.size,\n blob: includeOriginal ? originalBlob : null\n });\n }\n else {\n records.push({\n uuid: originalFileUuid,\n name: originalFileName,\n size: originalBlob.size,\n blob: originalBlob\n });\n }\n\n return records;\n },\n\n handleNewFile: function(file, name, uuid, size, fileList, batchId, uuidParamName, api) {\n var self = this,\n buttonId = file.qqButtonId || (file.blob && file.blob.qqButtonId),\n scaledIds = [],\n originalId = null,\n addFileToHandler = api.addFileToHandler,\n uploadData = api.uploadData,\n paramsStore = api.paramsStore,\n proxyGroupId = qq.getUniqueId();\n\n qq.each(self.getFileRecords(uuid, name, file), function(idx, record) {\n var blobSize = record.size,\n id;\n\n if (record.blob instanceof qq.BlobProxy) {\n blobSize = -1;\n }\n\n id = uploadData.addFile({\n uuid: record.uuid,\n name: record.name,\n size: blobSize,\n batchId: batchId,\n proxyGroupId: proxyGroupId\n });\n\n if (record.blob instanceof qq.BlobProxy) {\n scaledIds.push(id);\n }\n else {\n originalId = id;\n }\n\n if (record.blob) {\n addFileToHandler(id, record.blob);\n fileList.push({id: id, file: record.blob});\n }\n else {\n uploadData.setStatus(id, qq.status.REJECTED);\n }\n });\n\n // If we are potentially uploading an original file and some scaled versions,\n // ensure the scaled versions include reference's to the parent's UUID and size\n // in their associated upload requests.\n if (originalId !== null) {\n qq.each(scaledIds, function(idx, scaledId) {\n var params = {\n qqparentuuid: uploadData.retrieve({id: originalId}).uuid,\n qqparentsize: uploadData.retrieve({id: originalId}).size\n };\n\n // Make sure the UUID for each scaled image is sent with the upload request,\n // to be consistent (since we may need to ensure it is sent for the original file as well).\n params[uuidParamName] = uploadData.retrieve({id: scaledId}).uuid;\n\n uploadData.setParentId(scaledId, originalId);\n paramsStore.addReadOnly(scaledId, params);\n });\n\n // If any scaled images are tied to this parent image, be SURE we send its UUID as an upload request\n // parameter as well.\n if (scaledIds.length) {\n (function() {\n var param = {};\n param[uuidParamName] = uploadData.retrieve({id: originalId}).uuid;\n paramsStore.addReadOnly(originalId, param);\n }());\n }\n }\n }\n });\n};\n\nqq.extend(qq.Scaler.prototype, {\n scaleImage: function(id, specs, api) {\n \"use strict\";\n\n if (!qq.supportedFeatures.scaling) {\n throw new qq.Error(\"Scaling is not supported in this browser!\");\n }\n\n var scalingEffort = new qq.Promise(),\n log = api.log,\n file = api.getFile(id),\n uploadData = api.uploadData.retrieve({id: id}),\n name = uploadData && uploadData.name,\n uuid = uploadData && uploadData.uuid,\n scalingOptions = {\n customResizer: specs.customResizer,\n sendOriginal: false,\n orient: specs.orient,\n defaultType: specs.type || null,\n defaultQuality: specs.quality,\n failedToScaleText: \"Unable to scale\",\n sizes: [{name: \"\", maxSize: specs.maxSize}]\n },\n scaler = new qq.Scaler(scalingOptions, log);\n\n if (!qq.Scaler || !qq.supportedFeatures.imagePreviews || !file) {\n scalingEffort.failure();\n\n log(\"Could not generate requested scaled image for \" + id + \". \" +\n \"Scaling is either not possible in this browser, or the file could not be located.\", \"error\");\n }\n else {\n (qq.bind(function() {\n // Assumption: There will never be more than one record\n var record = scaler.getFileRecords(uuid, name, file)[0];\n\n if (record && record.blob instanceof qq.BlobProxy) {\n record.blob.create().then(scalingEffort.success, scalingEffort.failure);\n }\n else {\n log(id + \" is not a scalable image!\", \"error\");\n scalingEffort.failure();\n }\n }, this)());\n }\n\n return scalingEffort;\n },\n\n // NOTE: We cannot reliably determine at this time if the UA supports a specific MIME type for the target format.\n // image/jpeg and image/png are the only safe choices at this time.\n _determineOutputType: function(spec) {\n \"use strict\";\n\n var requestedType = spec.requestedType,\n defaultType = spec.defaultType,\n referenceType = spec.refType;\n\n // If a default type and requested type have not been specified, this should be a\n // JPEG if the original type is a JPEG, otherwise, a PNG.\n if (!defaultType && !requestedType) {\n if (referenceType !== \"image/jpeg\") {\n return \"image/png\";\n }\n return referenceType;\n }\n\n // A specified default type is used when a requested type is not specified.\n if (!requestedType) {\n return defaultType;\n }\n\n // If requested type is specified, use it, as long as this recognized type is supported by the current UA\n if (qq.indexOf(Object.keys(qq.Identify.prototype.PREVIEWABLE_MIME_TYPES), requestedType) >= 0) {\n if (requestedType === \"image/tiff\") {\n return qq.supportedFeatures.tiffPreviews ? requestedType : defaultType;\n }\n\n return requestedType;\n }\n\n return defaultType;\n },\n\n // Get a file name for a generated scaled file record, based on the provided scaled image description\n _getName: function(originalName, scaledVersionProperties) {\n \"use strict\";\n\n var startOfExt = originalName.lastIndexOf(\".\"),\n versionType = scaledVersionProperties.type || \"image/png\",\n referenceType = scaledVersionProperties.refType,\n scaledName = \"\",\n scaledExt = qq.getExtension(originalName),\n nameAppendage = \"\";\n\n if (scaledVersionProperties.name && scaledVersionProperties.name.trim().length) {\n nameAppendage = \" (\" + scaledVersionProperties.name + \")\";\n }\n\n if (startOfExt >= 0) {\n scaledName = originalName.substr(0, startOfExt);\n\n if (referenceType !== versionType) {\n scaledExt = versionType.split(\"/\")[1];\n }\n\n scaledName += nameAppendage + \".\" + scaledExt;\n }\n else {\n scaledName = originalName + nameAppendage;\n }\n\n return scaledName;\n },\n\n // We want the smallest scaled file to be uploaded first\n _getSortedSizes: function(sizes) {\n \"use strict\";\n\n sizes = qq.extend([], sizes);\n\n return sizes.sort(function(a, b) {\n if (a.maxSize > b.maxSize) {\n return 1;\n }\n if (a.maxSize < b.maxSize) {\n return -1;\n }\n return 0;\n });\n },\n\n _generateScaledImage: function(spec, sourceFile) {\n \"use strict\";\n\n var self = this,\n customResizeFunction = spec.customResizeFunction,\n log = spec.log,\n maxSize = spec.maxSize,\n orient = spec.orient,\n type = spec.type,\n quality = spec.quality,\n failedText = spec.failedText,\n includeExif = spec.includeExif && sourceFile.type === \"image/jpeg\" && type === \"image/jpeg\",\n scalingEffort = new qq.Promise(),\n imageGenerator = new qq.ImageGenerator(log),\n canvas = document.createElement(\"canvas\");\n\n log(\"Attempting to generate scaled version for \" + sourceFile.name);\n\n imageGenerator.generate(sourceFile, canvas, {maxSize: maxSize, orient: orient, customResizeFunction: customResizeFunction}).then(function() {\n var scaledImageDataUri = canvas.toDataURL(type, quality),\n signalSuccess = function() {\n log(\"Success generating scaled version for \" + sourceFile.name);\n var blob = qq.dataUriToBlob(scaledImageDataUri);\n scalingEffort.success(blob);\n };\n\n if (includeExif) {\n self._insertExifHeader(sourceFile, scaledImageDataUri, log).then(function(scaledImageDataUriWithExif) {\n scaledImageDataUri = scaledImageDataUriWithExif;\n signalSuccess();\n },\n function() {\n log(\"Problem inserting EXIF header into scaled image. Using scaled image w/out EXIF data.\", \"error\");\n signalSuccess();\n });\n }\n else {\n signalSuccess();\n }\n }, function() {\n log(\"Failed attempt to generate scaled version for \" + sourceFile.name, \"error\");\n scalingEffort.failure(failedText);\n });\n\n return scalingEffort;\n },\n\n // Attempt to insert the original image's EXIF header into a scaled version.\n _insertExifHeader: function(originalImage, scaledImageDataUri, log) {\n \"use strict\";\n\n var reader = new FileReader(),\n insertionEffort = new qq.Promise(),\n originalImageDataUri = \"\";\n\n reader.onload = function() {\n originalImageDataUri = reader.result;\n insertionEffort.success(qq.ExifRestorer.restore(originalImageDataUri, scaledImageDataUri));\n };\n\n reader.onerror = function() {\n log(\"Problem reading \" + originalImage.name + \" during attempt to transfer EXIF data to scaled version.\", \"error\");\n insertionEffort.failure();\n };\n\n reader.readAsDataURL(originalImage);\n\n return insertionEffort;\n },\n\n _dataUriToBlob: function(dataUri) {\n \"use strict\";\n\n var byteString, mimeString, arrayBuffer, intArray;\n\n // convert base64 to raw binary data held in a string\n if (dataUri.split(\",\")[0].indexOf(\"base64\") >= 0) {\n byteString = atob(dataUri.split(\",\")[1]);\n }\n else {\n byteString = decodeURI(dataUri.split(\",\")[1]);\n }\n\n // extract the MIME\n mimeString = dataUri.split(\",\")[0]\n .split(\":\")[1]\n .split(\";\")[0];\n\n // write the bytes of the binary string to an ArrayBuffer\n arrayBuffer = new ArrayBuffer(byteString.length);\n intArray = new Uint8Array(arrayBuffer);\n qq.each(byteString, function(idx, character) {\n intArray[idx] = character.charCodeAt(0);\n });\n\n return this._createBlob(arrayBuffer, mimeString);\n },\n\n _createBlob: function(data, mime) {\n \"use strict\";\n\n var BlobBuilder = window.BlobBuilder ||\n window.WebKitBlobBuilder ||\n window.MozBlobBuilder ||\n window.MSBlobBuilder,\n blobBuilder = BlobBuilder && new BlobBuilder();\n\n if (blobBuilder) {\n blobBuilder.append(data);\n return blobBuilder.getBlob(mime);\n }\n else {\n return new Blob([data], {type: mime});\n }\n }\n});\n","//Based on MinifyJpeg\n//http://elicon.blog57.fc2.com/blog-entry-206.html\n\nqq.ExifRestorer = (function()\n{\n \n\tvar ExifRestorer = {};\n\t \n ExifRestorer.KEY_STR = \"ABCDEFGHIJKLMNOP\" +\n \"QRSTUVWXYZabcdef\" +\n \"ghijklmnopqrstuv\" +\n \"wxyz0123456789+/\" +\n \"=\";\n\n ExifRestorer.encode64 = function(input)\n {\n var output = \"\",\n chr1, chr2, chr3 = \"\",\n enc1, enc2, enc3, enc4 = \"\",\n i = 0;\n\n do {\n chr1 = input[i++];\n chr2 = input[i++];\n chr3 = input[i++];\n\n enc1 = chr1 >> 2;\n enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);\n enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);\n enc4 = chr3 & 63;\n\n if (isNaN(chr2)) {\n enc3 = enc4 = 64;\n } else if (isNaN(chr3)) {\n enc4 = 64;\n }\n\n output = output +\n this.KEY_STR.charAt(enc1) +\n this.KEY_STR.charAt(enc2) +\n this.KEY_STR.charAt(enc3) +\n this.KEY_STR.charAt(enc4);\n chr1 = chr2 = chr3 = \"\";\n enc1 = enc2 = enc3 = enc4 = \"\";\n } while (i < input.length);\n\n return output;\n };\n \n ExifRestorer.restore = function(origFileBase64, resizedFileBase64)\n {\n var expectedBase64Header = \"data:image/jpeg;base64,\";\n\n if (!origFileBase64.match(expectedBase64Header))\n {\n \treturn resizedFileBase64;\n } \n \n var rawImage = this.decode64(origFileBase64.replace(expectedBase64Header, \"\"));\n var segments = this.slice2Segments(rawImage);\n \n var image = this.exifManipulation(resizedFileBase64, segments);\n \n return expectedBase64Header + this.encode64(image);\n \n };\n\n\n ExifRestorer.exifManipulation = function(resizedFileBase64, segments)\n {\n var exifArray = this.getExifArray(segments),\n newImageArray = this.insertExif(resizedFileBase64, exifArray),\n aBuffer = new Uint8Array(newImageArray);\n\n return aBuffer;\n };\n\n\n ExifRestorer.getExifArray = function(segments)\n {\n var seg;\n for (var x = 0; x < segments.length; x++)\n {\n seg = segments[x];\n if (seg[0] == 255 & seg[1] == 225) //(ff e1)\n {\n return seg;\n }\n }\n return [];\n };\n\n\n ExifRestorer.insertExif = function(resizedFileBase64, exifArray)\n {\n var imageData = resizedFileBase64.replace(\"data:image/jpeg;base64,\", \"\"),\n buf = this.decode64(imageData),\n separatePoint = buf.indexOf(255,3),\n mae = buf.slice(0, separatePoint),\n ato = buf.slice(separatePoint),\n array = mae;\n\n array = array.concat(exifArray);\n array = array.concat(ato);\n return array;\n };\n\n\n \n ExifRestorer.slice2Segments = function(rawImageArray)\n {\n var head = 0,\n segments = [];\n\n while (1)\n {\n if (rawImageArray[head] == 255 & rawImageArray[head + 1] == 218){break;}\n if (rawImageArray[head] == 255 & rawImageArray[head + 1] == 216)\n {\n head += 2;\n }\n else\n {\n var length = rawImageArray[head + 2] * 256 + rawImageArray[head + 3],\n endPoint = head + length + 2,\n seg = rawImageArray.slice(head, endPoint);\n segments.push(seg);\n head = endPoint;\n }\n if (head > rawImageArray.length){break;}\n }\n\n return segments;\n };\n\n\n \n ExifRestorer.decode64 = function(input) \n {\n var output = \"\",\n chr1, chr2, chr3 = \"\",\n enc1, enc2, enc3, enc4 = \"\",\n i = 0,\n buf = [];\n\n // remove all characters that are not A-Z, a-z, 0-9, +, /, or =\n var base64test = /[^A-Za-z0-9\\+\\/\\=]/g;\n if (base64test.exec(input)) {\n throw new Error(\"There were invalid base64 characters in the input text. \" +\n \"Valid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='\");\n }\n input = input.replace(/[^A-Za-z0-9\\+\\/\\=]/g, \"\");\n\n do {\n enc1 = this.KEY_STR.indexOf(input.charAt(i++));\n enc2 = this.KEY_STR.indexOf(input.charAt(i++));\n enc3 = this.KEY_STR.indexOf(input.charAt(i++));\n enc4 = this.KEY_STR.indexOf(input.charAt(i++));\n\n chr1 = (enc1 << 2) | (enc2 >> 4);\n chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);\n chr3 = ((enc3 & 3) << 6) | enc4;\n\n buf.push(chr1);\n\n if (enc3 != 64) {\n buf.push(chr2);\n }\n if (enc4 != 64) {\n buf.push(chr3);\n }\n\n chr1 = chr2 = chr3 = \"\";\n enc1 = enc2 = enc3 = enc4 = \"\";\n\n } while (i < input.length);\n\n return buf;\n };\n\n \n return ExifRestorer;\n})();\n","/* globals qq */\n/**\n * Keeps a running tally of total upload progress for a batch of files.\n *\n * @param callback Invoked when total progress changes, passing calculated total loaded & total size values.\n * @param getSize Function that returns the size of a file given its ID\n * @constructor\n */\nqq.TotalProgress = function(callback, getSize) {\n \"use strict\";\n\n var perFileProgress = {},\n totalLoaded = 0,\n totalSize = 0,\n\n lastLoadedSent = -1,\n lastTotalSent = -1,\n callbackProxy = function(loaded, total) {\n if (loaded !== lastLoadedSent || total !== lastTotalSent) {\n callback(loaded, total);\n }\n\n lastLoadedSent = loaded;\n lastTotalSent = total;\n },\n\n /**\n * @param failed Array of file IDs that have failed\n * @param retryable Array of file IDs that are retryable\n * @returns true if none of the failed files are eligible for retry\n */\n noRetryableFiles = function(failed, retryable) {\n var none = true;\n\n qq.each(failed, function(idx, failedId) {\n if (qq.indexOf(retryable, failedId) >= 0) {\n none = false;\n return false;\n }\n });\n\n return none;\n },\n\n onCancel = function(id) {\n updateTotalProgress(id, -1, -1);\n delete perFileProgress[id];\n },\n\n onAllComplete = function(successful, failed, retryable) {\n if (failed.length === 0 || noRetryableFiles(failed, retryable)) {\n callbackProxy(totalSize, totalSize);\n this.reset();\n }\n },\n\n onNew = function(id) {\n var size = getSize(id);\n\n // We might not know the size yet, such as for blob proxies\n if (size > 0) {\n updateTotalProgress(id, 0, size);\n perFileProgress[id] = {loaded: 0, total: size};\n }\n },\n\n /**\n * Invokes the callback with the current total progress of all files in the batch. Called whenever it may\n * be appropriate to re-calculate and disseminate this data.\n *\n * @param id ID of a file that has changed in some important way\n * @param newLoaded New loaded value for this file. -1 if this value should no longer be part of calculations\n * @param newTotal New total size of the file. -1 if this value should no longer be part of calculations\n */\n updateTotalProgress = function(id, newLoaded, newTotal) {\n var oldLoaded = perFileProgress[id] ? perFileProgress[id].loaded : 0,\n oldTotal = perFileProgress[id] ? perFileProgress[id].total : 0;\n\n if (newLoaded === -1 && newTotal === -1) {\n totalLoaded -= oldLoaded;\n totalSize -= oldTotal;\n }\n else {\n if (newLoaded) {\n totalLoaded += newLoaded - oldLoaded;\n }\n if (newTotal) {\n totalSize += newTotal - oldTotal;\n }\n }\n\n callbackProxy(totalLoaded, totalSize);\n };\n\n qq.extend(this, {\n // Called when a batch of files has completed uploading.\n onAllComplete: onAllComplete,\n\n // Called when the status of a file has changed.\n onStatusChange: function(id, oldStatus, newStatus) {\n if (newStatus === qq.status.CANCELED || newStatus === qq.status.REJECTED) {\n onCancel(id);\n }\n else if (newStatus === qq.status.SUBMITTING) {\n onNew(id);\n }\n },\n\n // Called whenever the upload progress of an individual file has changed.\n onIndividualProgress: function(id, loaded, total) {\n updateTotalProgress(id, loaded, total);\n perFileProgress[id] = {loaded: loaded, total: total};\n },\n\n // Called whenever the total size of a file has changed, such as when the size of a generated blob is known.\n onNewSize: function(id) {\n onNew(id);\n },\n\n reset: function() {\n perFileProgress = {};\n totalLoaded = 0;\n totalSize = 0;\n }\n });\n};\n","/*globals qq*/\nqq.PasteSupport = function(o) {\n \"use strict\";\n\n var options, detachPasteHandler;\n\n options = {\n targetElement: null,\n callbacks: {\n log: function(message, level) {},\n pasteReceived: function(blob) {}\n }\n };\n\n function isImage(item) {\n return item.type &&\n item.type.indexOf(\"image/\") === 0;\n }\n\n function registerPasteHandler() {\n detachPasteHandler = qq(options.targetElement).attach(\"paste\", function(event) {\n var clipboardData = event.clipboardData;\n\n if (clipboardData) {\n qq.each(clipboardData.items, function(idx, item) {\n if (isImage(item)) {\n var blob = item.getAsFile();\n options.callbacks.pasteReceived(blob);\n }\n });\n }\n });\n }\n\n function unregisterPasteHandler() {\n if (detachPasteHandler) {\n detachPasteHandler();\n }\n }\n\n qq.extend(options, o);\n registerPasteHandler();\n\n qq.extend(this, {\n reset: function() {\n unregisterPasteHandler();\n }\n });\n};\n","/* globals qq */\n/**\n * Module that handles support for existing forms.\n *\n * @param options Options passed from the integrator-supplied options related to form support.\n * @param startUpload Callback to invoke when files \"stored\" should be uploaded.\n * @param log Proxy for the logger\n * @constructor\n */\nqq.FormSupport = function(options, startUpload, log) {\n \"use strict\";\n var self = this,\n interceptSubmit = options.interceptSubmit,\n formEl = options.element,\n autoUpload = options.autoUpload;\n\n // Available on the public API associated with this module.\n qq.extend(this, {\n // To be used by the caller to determine if the endpoint will be determined by some processing\n // that occurs in this module, such as if the form has an action attribute.\n // Ignore if `attachToForm === false`.\n newEndpoint: null,\n\n // To be used by the caller to determine if auto uploading should be allowed.\n // Ignore if `attachToForm === false`.\n newAutoUpload: autoUpload,\n\n // true if a form was detected and is being tracked by this module\n attachedToForm: false,\n\n // Returns an object with names and values for all valid form elements associated with the attached form.\n getFormInputsAsObject: function() {\n /* jshint eqnull:true */\n if (formEl == null) {\n return null;\n }\n\n return self._form2Obj(formEl);\n }\n });\n\n // If the form contains an action attribute, this should be the new upload endpoint.\n function determineNewEndpoint(formEl) {\n if (formEl.getAttribute(\"action\")) {\n self.newEndpoint = formEl.getAttribute(\"action\");\n }\n }\n\n // Return true only if the form is valid, or if we cannot make this determination.\n // If the form is invalid, ensure invalid field(s) are highlighted in the UI.\n function validateForm(formEl, nativeSubmit) {\n if (formEl.checkValidity && !formEl.checkValidity()) {\n log(\"Form did not pass validation checks - will not upload.\", \"error\");\n nativeSubmit();\n }\n else {\n return true;\n }\n }\n\n // Intercept form submit attempts, unless the integrator has told us not to do this.\n function maybeUploadOnSubmit(formEl) {\n var nativeSubmit = formEl.submit;\n\n // Intercept and squelch submit events.\n qq(formEl).attach(\"submit\", function(event) {\n event = event || window.event;\n\n if (event.preventDefault) {\n event.preventDefault();\n }\n else {\n event.returnValue = false;\n }\n\n validateForm(formEl, nativeSubmit) && startUpload();\n });\n\n // The form's `submit()` function may be called instead (i.e. via jQuery.submit()).\n // Intercept that too.\n formEl.submit = function() {\n validateForm(formEl, nativeSubmit) && startUpload();\n };\n }\n\n // If the element value passed from the uploader is a string, assume it is an element ID - select it.\n // The rest of the code in this module depends on this being an HTMLElement.\n function determineFormEl(formEl) {\n if (formEl) {\n if (qq.isString(formEl)) {\n formEl = document.getElementById(formEl);\n }\n\n if (formEl) {\n log(\"Attaching to form element.\");\n determineNewEndpoint(formEl);\n interceptSubmit && maybeUploadOnSubmit(formEl);\n }\n }\n\n return formEl;\n }\n\n formEl = determineFormEl(formEl);\n this.attachedToForm = !!formEl;\n};\n\nqq.extend(qq.FormSupport.prototype, {\n // Converts all relevant form fields to key/value pairs. This is meant to mimic the data a browser will\n // construct from a given form when the form is submitted.\n _form2Obj: function(form) {\n \"use strict\";\n var obj = {},\n notIrrelevantType = function(type) {\n var irrelevantTypes = [\n \"button\",\n \"image\",\n \"reset\",\n \"submit\"\n ];\n\n return qq.indexOf(irrelevantTypes, type.toLowerCase()) < 0;\n },\n radioOrCheckbox = function(type) {\n return qq.indexOf([\"checkbox\", \"radio\"], type.toLowerCase()) >= 0;\n },\n ignoreValue = function(el) {\n if (radioOrCheckbox(el.type) && !el.checked) {\n return true;\n }\n\n return el.disabled && el.type.toLowerCase() !== \"hidden\";\n },\n selectValue = function(select) {\n var value = null;\n\n qq.each(qq(select).children(), function(idx, child) {\n if (child.tagName.toLowerCase() === \"option\" && child.selected) {\n value = child.value;\n return false;\n }\n });\n\n return value;\n };\n\n qq.each(form.elements, function(idx, el) {\n if ((qq.isInput(el, true) || el.tagName.toLowerCase() === \"textarea\") &&\n notIrrelevantType(el.type) &&\n !ignoreValue(el)) {\n\n obj[el.name] = el.value;\n }\n else if (el.tagName.toLowerCase() === \"select\" && !ignoreValue(el)) {\n var value = selectValue(el);\n\n if (value !== null) {\n obj[el.name] = value;\n }\n }\n });\n\n return obj;\n }\n});\n","/*globals qq*/\n/**\n * Upload handler used that assumes the current user agent does not have any support for the\n * File API, and, therefore, makes use of iframes and forms to submit the files directly to\n * a generic server.\n *\n * @param options Options passed from the base handler\n * @param proxy Callbacks & methods used to query for or push out data/changes\n */\nqq.traditional = qq.traditional || {};\nqq.traditional.FormUploadHandler = function(options, proxy) {\n \"use strict\";\n\n var handler = this,\n getName = proxy.getName,\n getUuid = proxy.getUuid,\n log = proxy.log;\n\n /**\n * Returns json object received by iframe from server.\n */\n function getIframeContentJson(id, iframe) {\n /*jshint evil: true*/\n\n var response, doc, innerHtml;\n\n //IE may throw an \"access is denied\" error when attempting to access contentDocument on the iframe in some cases\n try {\n // iframe.contentWindow.document - for IE<7\n doc = iframe.contentDocument || iframe.contentWindow.document;\n innerHtml = doc.body.innerHTML;\n\n log(\"converting iframe's innerHTML to JSON\");\n log(\"innerHTML = \" + innerHtml);\n //plain text response may be wrapped in tag\n if (innerHtml && innerHtml.match(/^ 1 && !options.allowMultipleItems) {\n options.callbacks.processingDroppedFilesComplete([]);\n options.callbacks.dropError(\"tooManyFilesError\", \"\");\n uploadDropZone.dropDisabled(false);\n handleDataTransferPromise.failure();\n }\n else {\n droppedFiles = [];\n\n if (qq.isFolderDropSupported(dataTransfer)) {\n qq.each(dataTransfer.items, function(idx, item) {\n var entry = item.webkitGetAsEntry();\n\n if (entry) {\n //due to a bug in Chrome's File System API impl - #149735\n if (entry.isFile) {\n droppedFiles.push(item.getAsFile());\n }\n\n else {\n pendingFolderPromises.push(traverseFileTree(entry).done(function() {\n pendingFolderPromises.pop();\n if (pendingFolderPromises.length === 0) {\n handleDataTransferPromise.success();\n }\n }));\n }\n }\n });\n }\n else {\n droppedFiles = dataTransfer.files;\n }\n\n if (pendingFolderPromises.length === 0) {\n handleDataTransferPromise.success();\n }\n }\n\n return handleDataTransferPromise;\n }\n\n function setupDropzone(dropArea) {\n var dropZone = new qq.UploadDropZone({\n HIDE_ZONES_EVENT_NAME: HIDE_ZONES_EVENT_NAME,\n element: dropArea,\n onEnter: function(e) {\n qq(dropArea).addClass(options.classes.dropActive);\n e.stopPropagation();\n },\n onLeaveNotDescendants: function(e) {\n qq(dropArea).removeClass(options.classes.dropActive);\n },\n onDrop: function(e) {\n handleDataTransfer(e.dataTransfer, dropZone).then(\n function() {\n uploadDroppedFiles(droppedFiles, dropZone);\n },\n function() {\n options.callbacks.dropLog(\"Drop event DataTransfer parsing failed. No files will be uploaded.\", \"error\");\n }\n );\n }\n });\n\n disposeSupport.addDisposer(function() {\n dropZone.dispose();\n });\n\n qq(dropArea).hasAttribute(HIDE_BEFORE_ENTER_ATTR) && qq(dropArea).hide();\n\n uploadDropZones.push(dropZone);\n\n return dropZone;\n }\n\n function isFileDrag(dragEvent) {\n var fileDrag;\n\n qq.each(dragEvent.dataTransfer.types, function(key, val) {\n if (val === \"Files\") {\n fileDrag = true;\n return false;\n }\n });\n\n return fileDrag;\n }\n\n // Attempt to determine when the file has left the document. It is not always possible to detect this\n // in all cases, but it is generally possible in all browsers, with a few exceptions.\n //\n // Exceptions:\n // * IE10+ & Safari: We can't detect a file leaving the document if the Explorer window housing the file\n // overlays the browser window.\n // * IE10+: If the file is dragged out of the window too quickly, IE does not set the expected values of the\n // event's X & Y properties.\n function leavingDocumentOut(e) {\n if (qq.safari()) {\n return e.x < 0 || e.y < 0;\n }\n\n return e.x === 0 && e.y === 0;\n }\n\n function setupDragDrop() {\n var dropZones = options.dropZoneElements,\n\n maybeHideDropZones = function() {\n setTimeout(function() {\n qq.each(dropZones, function(idx, dropZone) {\n qq(dropZone).hasAttribute(HIDE_BEFORE_ENTER_ATTR) && qq(dropZone).hide();\n qq(dropZone).removeClass(options.classes.dropActive);\n });\n }, 10);\n };\n\n qq.each(dropZones, function(idx, dropZone) {\n var uploadDropZone = setupDropzone(dropZone);\n\n // IE <= 9 does not support the File API used for drag+drop uploads\n if (dropZones.length && qq.supportedFeatures.fileDrop) {\n disposeSupport.attach(document, \"dragenter\", function(e) {\n if (!uploadDropZone.dropDisabled() && isFileDrag(e)) {\n qq.each(dropZones, function(idx, dropZone) {\n // We can't apply styles to non-HTMLElements, since they lack the `style` property.\n // Also, if the drop zone isn't initially hidden, let's not mess with `style.display`.\n if (dropZone instanceof HTMLElement &&\n qq(dropZone).hasAttribute(HIDE_BEFORE_ENTER_ATTR)) {\n\n qq(dropZone).css({display: \"block\"});\n }\n });\n }\n });\n }\n });\n\n disposeSupport.attach(document, \"dragleave\", function(e) {\n if (leavingDocumentOut(e)) {\n maybeHideDropZones();\n }\n });\n\n // Just in case we were not able to detect when a dragged file has left the document,\n // hide all relevant drop zones the next time the mouse enters the document.\n // Note that mouse events such as this one are not fired during drag operations.\n disposeSupport.attach(qq(document).children()[0], \"mouseenter\", function(e) {\n maybeHideDropZones();\n });\n\n disposeSupport.attach(document, \"drop\", function(e) {\n if (isFileDrag(e)) {\n e.preventDefault();\n maybeHideDropZones();\n }\n });\n\n disposeSupport.attach(document, HIDE_ZONES_EVENT_NAME, maybeHideDropZones);\n }\n\n setupDragDrop();\n\n qq.extend(this, {\n setupExtraDropzone: function(element) {\n options.dropZoneElements.push(element);\n setupDropzone(element);\n },\n\n removeDropzone: function(element) {\n var i,\n dzs = options.dropZoneElements;\n\n for (i in dzs) {\n if (dzs[i] === element) {\n return dzs.splice(i, 1);\n }\n }\n },\n\n dispose: function() {\n disposeSupport.dispose();\n qq.each(uploadDropZones, function(idx, dropZone) {\n dropZone.dispose();\n });\n }\n });\n\n this._testing = {};\n this._testing.extractDirectoryPath = extractDirectoryPath;\n};\n\nqq.DragAndDrop.callbacks = function() {\n \"use strict\";\n\n return {\n processingDroppedFiles: function() {},\n processingDroppedFilesComplete: function(files, targetEl) {},\n dropError: function(code, errorSpecifics) {\n qq.log(\"Drag & drop error code '\" + code + \" with these specifics: '\" + errorSpecifics + \"'\", \"error\");\n },\n dropLog: function(message, level) {\n qq.log(message, level);\n }\n };\n};\n\nqq.UploadDropZone = function(o) {\n \"use strict\";\n\n var disposeSupport = new qq.DisposeSupport(),\n options, element, preventDrop, dropOutsideDisabled;\n\n options = {\n element: null,\n onEnter: function(e) {},\n onLeave: function(e) {},\n // is not fired when leaving element by hovering descendants\n onLeaveNotDescendants: function(e) {},\n onDrop: function(e) {}\n };\n\n qq.extend(options, o);\n element = options.element;\n\n function dragoverShouldBeCanceled() {\n return qq.safari() || (qq.firefox() && qq.windows());\n }\n\n function disableDropOutside(e) {\n // run only once for all instances\n if (!dropOutsideDisabled) {\n\n // for these cases we need to catch onDrop to reset dropArea\n if (dragoverShouldBeCanceled) {\n disposeSupport.attach(document, \"dragover\", function(e) {\n e.preventDefault();\n });\n } else {\n disposeSupport.attach(document, \"dragover\", function(e) {\n if (e.dataTransfer) {\n e.dataTransfer.dropEffect = \"none\";\n e.preventDefault();\n }\n });\n }\n\n dropOutsideDisabled = true;\n }\n }\n\n function isValidFileDrag(e) {\n // e.dataTransfer currently causing IE errors\n // IE9 does NOT support file API, so drag-and-drop is not possible\n if (!qq.supportedFeatures.fileDrop) {\n return false;\n }\n\n var effectTest, dt = e.dataTransfer,\n // do not check dt.types.contains in webkit, because it crashes safari 4\n isSafari = qq.safari();\n\n // dt.effectAllowed is none in Safari 5\n\n // dt.effectAllowed crashes IE 11 & 10 when files have been dragged from\n // the filesystem\n effectTest = qq.ie() && qq.supportedFeatures.fileDrop ? true : dt.effectAllowed !== \"none\";\n return dt && effectTest &&\n (\n (dt.files && dt.files.length) || // Valid for drop events with files\n (!isSafari && dt.types.contains && dt.types.contains(\"Files\")) || // Valid in Chrome/Firefox\n (dt.types.includes && dt.types.includes(\"Files\")) // Valid in IE\n );\n }\n\n function isOrSetDropDisabled(isDisabled) {\n if (isDisabled !== undefined) {\n preventDrop = isDisabled;\n }\n return preventDrop;\n }\n\n function triggerHidezonesEvent() {\n var hideZonesEvent;\n\n function triggerUsingOldApi() {\n hideZonesEvent = document.createEvent(\"Event\");\n hideZonesEvent.initEvent(options.HIDE_ZONES_EVENT_NAME, true, true);\n }\n\n if (window.CustomEvent) {\n try {\n hideZonesEvent = new CustomEvent(options.HIDE_ZONES_EVENT_NAME);\n }\n catch (err) {\n triggerUsingOldApi();\n }\n }\n else {\n triggerUsingOldApi();\n }\n\n document.dispatchEvent(hideZonesEvent);\n }\n\n function attachEvents() {\n disposeSupport.attach(element, \"dragover\", function(e) {\n if (!isValidFileDrag(e)) {\n return;\n }\n\n // dt.effectAllowed crashes IE 11 & 10 when files have been dragged from\n // the filesystem\n var effect = qq.ie() && qq.supportedFeatures.fileDrop ? null : e.dataTransfer.effectAllowed;\n if (effect === \"move\" || effect === \"linkMove\") {\n e.dataTransfer.dropEffect = \"move\"; // for FF (only move allowed)\n } else {\n e.dataTransfer.dropEffect = \"copy\"; // for Chrome\n }\n\n e.stopPropagation();\n e.preventDefault();\n });\n\n disposeSupport.attach(element, \"dragenter\", function(e) {\n if (!isOrSetDropDisabled()) {\n if (!isValidFileDrag(e)) {\n return;\n }\n options.onEnter(e);\n }\n });\n\n disposeSupport.attach(element, \"dragleave\", function(e) {\n if (!isValidFileDrag(e)) {\n return;\n }\n\n options.onLeave(e);\n\n var relatedTarget = document.elementFromPoint(e.clientX, e.clientY);\n // do not fire when moving a mouse over a descendant\n if (qq(this).contains(relatedTarget)) {\n return;\n }\n\n options.onLeaveNotDescendants(e);\n });\n\n disposeSupport.attach(element, \"drop\", function(e) {\n if (!isOrSetDropDisabled()) {\n if (!isValidFileDrag(e)) {\n return;\n }\n\n e.preventDefault();\n e.stopPropagation();\n options.onDrop(e);\n\n triggerHidezonesEvent();\n }\n });\n }\n\n disableDropOutside();\n attachEvents();\n\n qq.extend(this, {\n dropDisabled: function(isDisabled) {\n return isOrSetDropDisabled(isDisabled);\n },\n\n dispose: function() {\n disposeSupport.dispose();\n },\n\n getElement: function() {\n return element;\n }\n });\n\n this._testing = {};\n this._testing.isValidFileDrag = isValidFileDrag;\n};\n","/*globals qq */\n/**\n * Defines the public API for FineUploader mode.\n */\n(function() {\n \"use strict\";\n\n qq.uiPublicApi = {\n addInitialFiles: function(cannedFileList) {\n this._parent.prototype.addInitialFiles.apply(this, arguments);\n this._templating.addCacheToDom();\n },\n\n clearStoredFiles: function() {\n this._parent.prototype.clearStoredFiles.apply(this, arguments);\n this._templating.clearFiles();\n },\n\n addExtraDropzone: function(element) {\n this._dnd && this._dnd.setupExtraDropzone(element);\n },\n\n removeExtraDropzone: function(element) {\n if (this._dnd) {\n return this._dnd.removeDropzone(element);\n }\n },\n\n getItemByFileId: function(id) {\n if (!this._templating.isHiddenForever(id)) {\n return this._templating.getFileContainer(id);\n }\n },\n\n reset: function() {\n this._parent.prototype.reset.apply(this, arguments);\n this._templating.reset();\n\n if (!this._options.button && this._templating.getButton()) {\n this._defaultButtonId = this._createUploadButton({\n element: this._templating.getButton(),\n title: this._options.text.fileInputTitle\n }).getButtonId();\n }\n\n if (this._dnd) {\n this._dnd.dispose();\n this._dnd = this._setupDragAndDrop();\n }\n\n this._totalFilesInBatch = 0;\n this._filesInBatchAddedToUi = 0;\n\n this._setupClickAndEditEventHandlers();\n },\n\n setName: function(id, newName) {\n var formattedFilename = this._options.formatFileName(newName);\n\n this._parent.prototype.setName.apply(this, arguments);\n this._templating.updateFilename(id, formattedFilename);\n },\n\n pauseUpload: function(id) {\n var paused = this._parent.prototype.pauseUpload.apply(this, arguments);\n\n paused && this._templating.uploadPaused(id);\n return paused;\n },\n\n continueUpload: function(id) {\n var continued = this._parent.prototype.continueUpload.apply(this, arguments);\n\n continued && this._templating.uploadContinued(id);\n return continued;\n },\n\n getId: function(fileContainerOrChildEl) {\n return this._templating.getFileId(fileContainerOrChildEl);\n },\n\n getDropTarget: function(fileId) {\n var file = this.getFile(fileId);\n\n return file.qqDropTarget;\n }\n };\n\n /**\n * Defines the private (internal) API for FineUploader mode.\n */\n qq.uiPrivateApi = {\n _getButton: function(buttonId) {\n var button = this._parent.prototype._getButton.apply(this, arguments);\n\n if (!button) {\n if (buttonId === this._defaultButtonId) {\n button = this._templating.getButton();\n }\n }\n\n return button;\n },\n\n _removeFileItem: function(fileId) {\n this._templating.removeFile(fileId);\n },\n\n _setupClickAndEditEventHandlers: function() {\n this._fileButtonsClickHandler = qq.FileButtonsClickHandler && this._bindFileButtonsClickEvent();\n\n // A better approach would be to check specifically for focusin event support by querying the DOM API,\n // but the DOMFocusIn event is not exposed as a property, so we have to resort to UA string sniffing.\n this._focusinEventSupported = !qq.firefox();\n\n if (this._isEditFilenameEnabled())\n {\n this._filenameClickHandler = this._bindFilenameClickEvent();\n this._filenameInputFocusInHandler = this._bindFilenameInputFocusInEvent();\n this._filenameInputFocusHandler = this._bindFilenameInputFocusEvent();\n }\n },\n\n _setupDragAndDrop: function() {\n var self = this,\n dropZoneElements = this._options.dragAndDrop.extraDropzones,\n templating = this._templating,\n defaultDropZone = templating.getDropZone();\n\n defaultDropZone && dropZoneElements.push(defaultDropZone);\n\n return new qq.DragAndDrop({\n dropZoneElements: dropZoneElements,\n allowMultipleItems: this._options.multiple,\n classes: {\n dropActive: this._options.classes.dropActive\n },\n callbacks: {\n processingDroppedFiles: function() {\n templating.showDropProcessing();\n },\n processingDroppedFilesComplete: function(files, targetEl) {\n templating.hideDropProcessing();\n\n qq.each(files, function(idx, file) {\n file.qqDropTarget = targetEl;\n });\n\n if (files.length) {\n self.addFiles(files, null, null);\n }\n },\n dropError: function(code, errorData) {\n self._itemError(code, errorData);\n },\n dropLog: function(message, level) {\n self.log(message, level);\n }\n }\n });\n },\n\n _bindFileButtonsClickEvent: function() {\n var self = this;\n\n return new qq.FileButtonsClickHandler({\n templating: this._templating,\n\n log: function(message, lvl) {\n self.log(message, lvl);\n },\n\n onDeleteFile: function(fileId) {\n self.deleteFile(fileId);\n },\n\n onCancel: function(fileId) {\n self.cancel(fileId);\n },\n\n onRetry: function(fileId) {\n self.retry(fileId);\n },\n\n onPause: function(fileId) {\n self.pauseUpload(fileId);\n },\n\n onContinue: function(fileId) {\n self.continueUpload(fileId);\n },\n\n onGetName: function(fileId) {\n return self.getName(fileId);\n }\n });\n },\n\n _isEditFilenameEnabled: function() {\n /*jshint -W014 */\n return this._templating.isEditFilenamePossible()\n && !this._options.autoUpload\n && qq.FilenameClickHandler\n && qq.FilenameInputFocusHandler\n && qq.FilenameInputFocusHandler;\n },\n\n _filenameEditHandler: function() {\n var self = this,\n templating = this._templating;\n\n return {\n templating: templating,\n log: function(message, lvl) {\n self.log(message, lvl);\n },\n onGetUploadStatus: function(fileId) {\n return self.getUploads({id: fileId}).status;\n },\n onGetName: function(fileId) {\n return self.getName(fileId);\n },\n onSetName: function(id, newName) {\n self.setName(id, newName);\n },\n onEditingStatusChange: function(id, isEditing) {\n var qqInput = qq(templating.getEditInput(id)),\n qqFileContainer = qq(templating.getFileContainer(id));\n\n if (isEditing) {\n qqInput.addClass(\"qq-editing\");\n templating.hideFilename(id);\n templating.hideEditIcon(id);\n }\n else {\n qqInput.removeClass(\"qq-editing\");\n templating.showFilename(id);\n templating.showEditIcon(id);\n }\n\n // Force IE8 and older to repaint\n qqFileContainer.addClass(\"qq-temp\").removeClass(\"qq-temp\");\n }\n };\n },\n\n _onUploadStatusChange: function(id, oldStatus, newStatus) {\n this._parent.prototype._onUploadStatusChange.apply(this, arguments);\n\n if (this._isEditFilenameEnabled()) {\n // Status for a file exists before it has been added to the DOM, so we must be careful here.\n if (this._templating.getFileContainer(id) && newStatus !== qq.status.SUBMITTED) {\n this._templating.markFilenameEditable(id);\n this._templating.hideEditIcon(id);\n }\n }\n\n if (oldStatus === qq.status.UPLOAD_RETRYING && newStatus === qq.status.UPLOADING) {\n this._templating.hideRetry(id);\n this._templating.setStatusText(id);\n qq(this._templating.getFileContainer(id)).removeClass(this._classes.retrying);\n }\n else if (newStatus === qq.status.UPLOAD_FAILED) {\n this._templating.hidePause(id);\n }\n },\n\n _bindFilenameInputFocusInEvent: function() {\n var spec = qq.extend({}, this._filenameEditHandler());\n\n return new qq.FilenameInputFocusInHandler(spec);\n },\n\n _bindFilenameInputFocusEvent: function() {\n var spec = qq.extend({}, this._filenameEditHandler());\n\n return new qq.FilenameInputFocusHandler(spec);\n },\n\n _bindFilenameClickEvent: function() {\n var spec = qq.extend({}, this._filenameEditHandler());\n\n return new qq.FilenameClickHandler(spec);\n },\n\n _storeForLater: function(id) {\n this._parent.prototype._storeForLater.apply(this, arguments);\n this._templating.hideSpinner(id);\n },\n\n _onAllComplete: function(successful, failed) {\n this._parent.prototype._onAllComplete.apply(this, arguments);\n this._templating.resetTotalProgress();\n },\n\n _onSubmit: function(id, name) {\n var file = this.getFile(id);\n\n if (file && file.qqPath && this._options.dragAndDrop.reportDirectoryPaths) {\n this._paramsStore.addReadOnly(id, {\n qqpath: file.qqPath\n });\n }\n\n this._parent.prototype._onSubmit.apply(this, arguments);\n this._addToList(id, name);\n },\n\n // The file item has been added to the DOM.\n _onSubmitted: function(id) {\n // If the edit filename feature is enabled, mark the filename element as \"editable\" and the associated edit icon\n if (this._isEditFilenameEnabled()) {\n this._templating.markFilenameEditable(id);\n this._templating.showEditIcon(id);\n\n // If the focusin event is not supported, we must add a focus handler to the newly create edit filename text input\n if (!this._focusinEventSupported) {\n this._filenameInputFocusHandler.addHandler(this._templating.getEditInput(id));\n }\n }\n },\n\n // Update the progress bar & percentage as the file is uploaded\n _onProgress: function(id, name, loaded, total) {\n this._parent.prototype._onProgress.apply(this, arguments);\n\n this._templating.updateProgress(id, loaded, total);\n\n if (total === 0 || Math.round(loaded / total * 100) === 100) {\n this._templating.hideCancel(id);\n this._templating.hidePause(id);\n this._templating.hideProgress(id);\n this._templating.setStatusText(id, this._options.text.waitingForResponse);\n\n // If ~last byte was sent, display total file size\n this._displayFileSize(id);\n }\n else {\n // If still uploading, display percentage - total size is actually the total request(s) size\n this._displayFileSize(id, loaded, total);\n }\n },\n\n _onTotalProgress: function(loaded, total) {\n this._parent.prototype._onTotalProgress.apply(this, arguments);\n this._templating.updateTotalProgress(loaded, total);\n },\n\n _onComplete: function(id, name, result, xhr) {\n var parentRetVal = this._parent.prototype._onComplete.apply(this, arguments),\n templating = this._templating,\n fileContainer = templating.getFileContainer(id),\n self = this;\n\n function completeUpload(result) {\n // If this file is not represented in the templating module, perhaps it was hidden intentionally.\n // If so, don't perform any UI-related tasks related to this file.\n if (!fileContainer) {\n return;\n }\n\n templating.setStatusText(id);\n\n qq(fileContainer).removeClass(self._classes.retrying);\n templating.hideProgress(id);\n\n if (self.getUploads({id: id}).status !== qq.status.UPLOAD_FAILED) {\n templating.hideCancel(id);\n }\n templating.hideSpinner(id);\n\n if (result.success) {\n self._markFileAsSuccessful(id);\n }\n else {\n qq(fileContainer).addClass(self._classes.fail);\n templating.showCancel(id);\n\n if (templating.isRetryPossible() && !self._preventRetries[id]) {\n qq(fileContainer).addClass(self._classes.retryable);\n templating.showRetry(id);\n }\n self._controlFailureTextDisplay(id, result);\n }\n }\n\n // The parent may need to perform some async operation before we can accurately determine the status of the upload.\n if (parentRetVal instanceof qq.Promise) {\n parentRetVal.done(function(newResult) {\n completeUpload(newResult);\n });\n\n }\n else {\n completeUpload(result);\n }\n\n return parentRetVal;\n },\n\n _markFileAsSuccessful: function(id) {\n var templating = this._templating;\n\n if (this._isDeletePossible()) {\n templating.showDeleteButton(id);\n }\n\n qq(templating.getFileContainer(id)).addClass(this._classes.success);\n\n this._maybeUpdateThumbnail(id);\n },\n\n _onUploadPrep: function(id) {\n this._parent.prototype._onUploadPrep.apply(this, arguments);\n this._templating.showSpinner(id);\n },\n\n _onUpload: function(id, name) {\n var parentRetVal = this._parent.prototype._onUpload.apply(this, arguments);\n\n this._templating.showSpinner(id);\n\n return parentRetVal;\n },\n\n _onUploadChunk: function(id, chunkData) {\n this._parent.prototype._onUploadChunk.apply(this, arguments);\n\n // Only display the pause button if we have finished uploading at least one chunk\n // & this file can be resumed\n if (chunkData.partIndex > 0 && this._handler.isResumable(id)) {\n this._templating.allowPause(id);\n }\n },\n\n _onCancel: function(id, name) {\n this._parent.prototype._onCancel.apply(this, arguments);\n this._removeFileItem(id);\n\n if (this._getNotFinished() === 0) {\n this._templating.resetTotalProgress();\n }\n },\n\n _onBeforeAutoRetry: function(id) {\n var retryNumForDisplay, maxAuto, retryNote;\n\n this._parent.prototype._onBeforeAutoRetry.apply(this, arguments);\n\n this._showCancelLink(id);\n\n if (this._options.retry.showAutoRetryNote) {\n retryNumForDisplay = this._autoRetries[id];\n maxAuto = this._options.retry.maxAutoAttempts;\n\n retryNote = this._options.retry.autoRetryNote.replace(/\\{retryNum\\}/g, retryNumForDisplay);\n retryNote = retryNote.replace(/\\{maxAuto\\}/g, maxAuto);\n\n this._templating.setStatusText(id, retryNote);\n qq(this._templating.getFileContainer(id)).addClass(this._classes.retrying);\n }\n },\n\n //return false if we should not attempt the requested retry\n _onBeforeManualRetry: function(id) {\n if (this._parent.prototype._onBeforeManualRetry.apply(this, arguments)) {\n this._templating.resetProgress(id);\n qq(this._templating.getFileContainer(id)).removeClass(this._classes.fail);\n this._templating.setStatusText(id);\n this._templating.showSpinner(id);\n this._showCancelLink(id);\n return true;\n }\n else {\n qq(this._templating.getFileContainer(id)).addClass(this._classes.retryable);\n this._templating.showRetry(id);\n return false;\n }\n },\n\n _onSubmitDelete: function(id) {\n var onSuccessCallback = qq.bind(this._onSubmitDeleteSuccess, this);\n\n this._parent.prototype._onSubmitDelete.call(this, id, onSuccessCallback);\n },\n\n _onSubmitDeleteSuccess: function(id, uuid, additionalMandatedParams) {\n if (this._options.deleteFile.forceConfirm) {\n this._showDeleteConfirm.apply(this, arguments);\n }\n else {\n this._sendDeleteRequest.apply(this, arguments);\n }\n },\n\n _onDeleteComplete: function(id, xhr, isError) {\n this._parent.prototype._onDeleteComplete.apply(this, arguments);\n\n this._templating.hideSpinner(id);\n\n if (isError) {\n this._templating.setStatusText(id, this._options.deleteFile.deletingFailedText);\n this._templating.showDeleteButton(id);\n }\n else {\n this._removeFileItem(id);\n }\n },\n\n _sendDeleteRequest: function(id, uuid, additionalMandatedParams) {\n this._templating.hideDeleteButton(id);\n this._templating.showSpinner(id);\n this._templating.setStatusText(id, this._options.deleteFile.deletingStatusText);\n this._deleteHandler.sendDelete.apply(this, arguments);\n },\n\n _showDeleteConfirm: function(id, uuid, mandatedParams) {\n /*jshint -W004 */\n var fileName = this.getName(id),\n confirmMessage = this._options.deleteFile.confirmMessage.replace(/\\{filename\\}/g, fileName),\n uuid = this.getUuid(id),\n deleteRequestArgs = arguments,\n self = this,\n retVal;\n\n retVal = this._options.showConfirm(confirmMessage);\n\n if (qq.isGenericPromise(retVal)) {\n retVal.then(function() {\n self._sendDeleteRequest.apply(self, deleteRequestArgs);\n });\n }\n else if (retVal !== false) {\n self._sendDeleteRequest.apply(self, deleteRequestArgs);\n }\n },\n\n _addToList: function(id, name, canned) {\n var prependData,\n prependIndex = 0,\n dontDisplay = this._handler.isProxied(id) && this._options.scaling.hideScaled,\n record;\n\n if (this._options.display.prependFiles) {\n if (this._totalFilesInBatch > 1 && this._filesInBatchAddedToUi > 0) {\n prependIndex = this._filesInBatchAddedToUi - 1;\n }\n\n prependData = {\n index: prependIndex\n };\n }\n\n if (!canned) {\n if (this._options.disableCancelForFormUploads && !qq.supportedFeatures.ajaxUploading) {\n this._templating.disableCancel();\n }\n\n // Cancel all existing (previous) files and clear the list if this file is not part of\n // a scaled file group that has already been accepted, or if this file is not part of\n // a scaled file group at all.\n if (!this._options.multiple) {\n record = this.getUploads({id: id});\n\n this._handledProxyGroup = this._handledProxyGroup || record.proxyGroupId;\n\n if (record.proxyGroupId !== this._handledProxyGroup || !record.proxyGroupId) {\n this._handler.cancelAll();\n this._clearList();\n this._handledProxyGroup = null;\n }\n }\n }\n\n if (canned) {\n this._templating.addFileToCache(id, this._options.formatFileName(name), prependData, dontDisplay);\n this._templating.updateThumbnail(id, this._thumbnailUrls[id], true, this._options.thumbnails.customResizer);\n }\n else {\n this._templating.addFile(id, this._options.formatFileName(name), prependData, dontDisplay);\n this._templating.generatePreview(id, this.getFile(id), this._options.thumbnails.customResizer);\n }\n\n this._filesInBatchAddedToUi += 1;\n\n if (canned ||\n (this._options.display.fileSizeOnSubmit && qq.supportedFeatures.ajaxUploading)) {\n\n this._displayFileSize(id);\n }\n },\n\n _clearList: function() {\n this._templating.clearFiles();\n this.clearStoredFiles();\n },\n\n _displayFileSize: function(id, loadedSize, totalSize) {\n var size = this.getSize(id),\n sizeForDisplay = this._formatSize(size);\n\n if (size >= 0) {\n if (loadedSize !== undefined && totalSize !== undefined) {\n sizeForDisplay = this._formatProgress(loadedSize, totalSize);\n }\n\n this._templating.updateSize(id, sizeForDisplay);\n }\n },\n\n _formatProgress: function(uploadedSize, totalSize) {\n var message = this._options.text.formatProgress;\n function r(name, replacement) { message = message.replace(name, replacement); }\n\n r(\"{percent}\", Math.round(uploadedSize / totalSize * 100));\n r(\"{total_size}\", this._formatSize(totalSize));\n return message;\n },\n\n _controlFailureTextDisplay: function(id, response) {\n var mode, responseProperty, failureReason;\n\n mode = this._options.failedUploadTextDisplay.mode;\n responseProperty = this._options.failedUploadTextDisplay.responseProperty;\n\n if (mode === \"custom\") {\n failureReason = response[responseProperty];\n if (!failureReason) {\n failureReason = this._options.text.failUpload;\n }\n\n this._templating.setStatusText(id, failureReason);\n\n if (this._options.failedUploadTextDisplay.enableTooltip) {\n this._showTooltip(id, failureReason);\n }\n }\n else if (mode === \"default\") {\n this._templating.setStatusText(id, this._options.text.failUpload);\n }\n else if (mode !== \"none\") {\n this.log(\"failedUploadTextDisplay.mode value of '\" + mode + \"' is not valid\", \"warn\");\n }\n },\n\n _showTooltip: function(id, text) {\n this._templating.getFileContainer(id).title = text;\n },\n\n _showCancelLink: function(id) {\n if (!this._options.disableCancelForFormUploads || qq.supportedFeatures.ajaxUploading) {\n this._templating.showCancel(id);\n }\n },\n\n _itemError: function(code, name, item) {\n var message = this._parent.prototype._itemError.apply(this, arguments);\n this._options.showMessage(message);\n },\n\n _batchError: function(message) {\n this._parent.prototype._batchError.apply(this, arguments);\n this._options.showMessage(message);\n },\n\n _setupPastePrompt: function() {\n var self = this;\n\n this._options.callbacks.onPasteReceived = function() {\n var message = self._options.paste.namePromptMessage,\n defaultVal = self._options.paste.defaultName;\n\n return self._options.showPrompt(message, defaultVal);\n };\n },\n\n _fileOrBlobRejected: function(id, name) {\n this._totalFilesInBatch -= 1;\n this._parent.prototype._fileOrBlobRejected.apply(this, arguments);\n },\n\n _prepareItemsForUpload: function(items, params, endpoint) {\n this._totalFilesInBatch = items.length;\n this._filesInBatchAddedToUi = 0;\n this._parent.prototype._prepareItemsForUpload.apply(this, arguments);\n },\n\n _maybeUpdateThumbnail: function(fileId) {\n var thumbnailUrl = this._thumbnailUrls[fileId],\n fileStatus = this.getUploads({id: fileId}).status;\n\n if (fileStatus !== qq.status.DELETED &&\n (thumbnailUrl ||\n this._options.thumbnails.placeholders.waitUntilResponse ||\n !qq.supportedFeatures.imagePreviews)) {\n\n // This will replace the \"waiting\" placeholder with a \"preview not available\" placeholder\n // if called with a null thumbnailUrl.\n this._templating.updateThumbnail(fileId, thumbnailUrl, this._options.thumbnails.customResizer);\n }\n },\n\n _addCannedFile: function(sessionData) {\n var id = this._parent.prototype._addCannedFile.apply(this, arguments);\n\n this._addToList(id, this.getName(id), true);\n this._templating.hideSpinner(id);\n this._templating.hideCancel(id);\n this._markFileAsSuccessful(id);\n\n return id;\n },\n\n _setSize: function(id, newSize) {\n this._parent.prototype._setSize.apply(this, arguments);\n\n this._templating.updateSize(id, this._formatSize(newSize));\n },\n\n _sessionRequestComplete: function() {\n this._templating.addCacheToDom();\n this._parent.prototype._sessionRequestComplete.apply(this, arguments);\n }\n };\n}());\n","/*globals qq */\n/**\n * This defines FineUploader mode, which is a default UI w/ drag & drop uploading.\n */\nqq.FineUploader = function(o, namespace) {\n \"use strict\";\n\n var self = this;\n\n // By default this should inherit instance data from FineUploaderBasic, but this can be overridden\n // if the (internal) caller defines a different parent. The parent is also used by\n // the private and public API functions that need to delegate to a parent function.\n this._parent = namespace ? qq[namespace].FineUploaderBasic : qq.FineUploaderBasic;\n this._parent.apply(this, arguments);\n\n // Options provided by FineUploader mode\n qq.extend(this._options, {\n element: null,\n\n button: null,\n\n listElement: null,\n\n dragAndDrop: {\n extraDropzones: [],\n reportDirectoryPaths: false\n },\n\n text: {\n formatProgress: \"{percent}% of {total_size}\",\n failUpload: \"Upload failed\",\n waitingForResponse: \"Processing...\",\n paused: \"Paused\"\n },\n\n template: \"qq-template\",\n\n classes: {\n retrying: \"qq-upload-retrying\",\n retryable: \"qq-upload-retryable\",\n success: \"qq-upload-success\",\n fail: \"qq-upload-fail\",\n editable: \"qq-editable\",\n hide: \"qq-hide\",\n dropActive: \"qq-upload-drop-area-active\"\n },\n\n failedUploadTextDisplay: {\n mode: \"default\", //default, custom, or none\n responseProperty: \"error\",\n enableTooltip: true\n },\n\n messages: {\n tooManyFilesError: \"You may only drop one file\",\n unsupportedBrowser: \"Unrecoverable error - this browser does not permit file uploading of any kind.\"\n },\n\n retry: {\n showAutoRetryNote: true,\n autoRetryNote: \"Retrying {retryNum}/{maxAuto}...\"\n },\n\n deleteFile: {\n forceConfirm: false,\n confirmMessage: \"Are you sure you want to delete {filename}?\",\n deletingStatusText: \"Deleting...\",\n deletingFailedText: \"Delete failed\"\n\n },\n\n display: {\n fileSizeOnSubmit: false,\n prependFiles: false\n },\n\n paste: {\n promptForName: false,\n namePromptMessage: \"Please name this image\"\n },\n\n thumbnails: {\n customResizer: null,\n maxCount: 0,\n placeholders: {\n waitUntilResponse: false,\n notAvailablePath: null,\n waitingPath: null\n },\n timeBetweenThumbs: 750\n },\n\n scaling: {\n hideScaled: false\n },\n\n showMessage: function(message) {\n if (self._templating.hasDialog(\"alert\")) {\n return self._templating.showDialog(\"alert\", message);\n }\n else {\n setTimeout(function() {\n window.alert(message);\n }, 0);\n }\n },\n\n showConfirm: function(message) {\n if (self._templating.hasDialog(\"confirm\")) {\n return self._templating.showDialog(\"confirm\", message);\n }\n else {\n return window.confirm(message);\n }\n },\n\n showPrompt: function(message, defaultValue) {\n if (self._templating.hasDialog(\"prompt\")) {\n return self._templating.showDialog(\"prompt\", message, defaultValue);\n }\n else {\n return window.prompt(message, defaultValue);\n }\n }\n }, true);\n\n // Replace any default options with user defined ones\n qq.extend(this._options, o, true);\n\n this._templating = new qq.Templating({\n log: qq.bind(this.log, this),\n templateIdOrEl: this._options.template,\n containerEl: this._options.element,\n fileContainerEl: this._options.listElement,\n button: this._options.button,\n imageGenerator: this._imageGenerator,\n classes: {\n hide: this._options.classes.hide,\n editable: this._options.classes.editable\n },\n limits: {\n maxThumbs: this._options.thumbnails.maxCount,\n timeBetweenThumbs: this._options.thumbnails.timeBetweenThumbs\n },\n placeholders: {\n waitUntilUpdate: this._options.thumbnails.placeholders.waitUntilResponse,\n thumbnailNotAvailable: this._options.thumbnails.placeholders.notAvailablePath,\n waitingForThumbnail: this._options.thumbnails.placeholders.waitingPath\n },\n text: this._options.text\n });\n\n if (this._options.workarounds.ios8SafariUploads && qq.ios800() && qq.iosSafari()) {\n this._templating.renderFailure(this._options.messages.unsupportedBrowserIos8Safari);\n }\n else if (!qq.supportedFeatures.uploading || (this._options.cors.expected && !qq.supportedFeatures.uploadCors)) {\n this._templating.renderFailure(this._options.messages.unsupportedBrowser);\n }\n else {\n this._wrapCallbacks();\n\n this._templating.render();\n\n this._classes = this._options.classes;\n\n if (!this._options.button && this._templating.getButton()) {\n this._defaultButtonId = this._createUploadButton({\n element: this._templating.getButton(),\n title: this._options.text.fileInputTitle\n }).getButtonId();\n }\n\n this._setupClickAndEditEventHandlers();\n\n if (qq.DragAndDrop && qq.supportedFeatures.fileDrop) {\n this._dnd = this._setupDragAndDrop();\n }\n\n if (this._options.paste.targetElement && this._options.paste.promptForName) {\n if (qq.PasteSupport) {\n this._setupPastePrompt();\n }\n else {\n this.log(\"Paste support module not found.\", \"error\");\n }\n }\n\n this._totalFilesInBatch = 0;\n this._filesInBatchAddedToUi = 0;\n }\n};\n\n// Inherit the base public & private API methods\nqq.extend(qq.FineUploader.prototype, qq.basePublicApi);\nqq.extend(qq.FineUploader.prototype, qq.basePrivateApi);\n\n// Add the FineUploader/default UI public & private UI methods, which may override some base methods.\nqq.extend(qq.FineUploader.prototype, qq.uiPublicApi);\nqq.extend(qq.FineUploader.prototype, qq.uiPrivateApi);\n","/* globals qq */\n/* jshint -W065 */\n/**\n * Module responsible for rendering all Fine Uploader UI templates. This module also asserts at least\n * a limited amount of control over the template elements after they are added to the DOM.\n * Wherever possible, this module asserts total control over template elements present in the DOM.\n *\n * @param spec Specification object used to control various templating behaviors\n * @constructor\n */\nqq.Templating = function(spec) {\n \"use strict\";\n\n var FILE_ID_ATTR = \"qq-file-id\",\n FILE_CLASS_PREFIX = \"qq-file-id-\",\n THUMBNAIL_MAX_SIZE_ATTR = \"qq-max-size\",\n THUMBNAIL_SERVER_SCALE_ATTR = \"qq-server-scale\",\n // This variable is duplicated in the DnD module since it can function as a standalone as well\n HIDE_DROPZONE_ATTR = \"qq-hide-dropzone\",\n DROPZPONE_TEXT_ATTR = \"qq-drop-area-text\",\n IN_PROGRESS_CLASS = \"qq-in-progress\",\n HIDDEN_FOREVER_CLASS = \"qq-hidden-forever\",\n fileBatch = {\n content: document.createDocumentFragment(),\n map: {}\n },\n isCancelDisabled = false,\n generatedThumbnails = 0,\n thumbnailQueueMonitorRunning = false,\n thumbGenerationQueue = [],\n thumbnailMaxSize = -1,\n options = {\n log: null,\n limits: {\n maxThumbs: 0,\n timeBetweenThumbs: 750\n },\n templateIdOrEl: \"qq-template\",\n containerEl: null,\n fileContainerEl: null,\n button: null,\n imageGenerator: null,\n classes: {\n hide: \"qq-hide\",\n editable: \"qq-editable\"\n },\n placeholders: {\n waitUntilUpdate: false,\n thumbnailNotAvailable: null,\n waitingForThumbnail: null\n },\n text: {\n paused: \"Paused\"\n }\n },\n selectorClasses = {\n button: \"qq-upload-button-selector\",\n alertDialog: \"qq-alert-dialog-selector\",\n dialogCancelButton: \"qq-cancel-button-selector\",\n confirmDialog: \"qq-confirm-dialog-selector\",\n dialogMessage: \"qq-dialog-message-selector\",\n dialogOkButton: \"qq-ok-button-selector\",\n promptDialog: \"qq-prompt-dialog-selector\",\n uploader: \"qq-uploader-selector\",\n drop: \"qq-upload-drop-area-selector\",\n list: \"qq-upload-list-selector\",\n progressBarContainer: \"qq-progress-bar-container-selector\",\n progressBar: \"qq-progress-bar-selector\",\n totalProgressBarContainer: \"qq-total-progress-bar-container-selector\",\n totalProgressBar: \"qq-total-progress-bar-selector\",\n file: \"qq-upload-file-selector\",\n spinner: \"qq-upload-spinner-selector\",\n size: \"qq-upload-size-selector\",\n cancel: \"qq-upload-cancel-selector\",\n pause: \"qq-upload-pause-selector\",\n continueButton: \"qq-upload-continue-selector\",\n deleteButton: \"qq-upload-delete-selector\",\n retry: \"qq-upload-retry-selector\",\n statusText: \"qq-upload-status-text-selector\",\n editFilenameInput: \"qq-edit-filename-selector\",\n editNameIcon: \"qq-edit-filename-icon-selector\",\n dropText: \"qq-upload-drop-area-text-selector\",\n dropProcessing: \"qq-drop-processing-selector\",\n dropProcessingSpinner: \"qq-drop-processing-spinner-selector\",\n thumbnail: \"qq-thumbnail-selector\"\n },\n previewGeneration = {},\n cachedThumbnailNotAvailableImg = new qq.Promise(),\n cachedWaitingForThumbnailImg = new qq.Promise(),\n log,\n isEditElementsExist,\n isRetryElementExist,\n templateDom,\n container,\n fileList,\n showThumbnails,\n serverScale,\n\n // During initialization of the templating module we should cache any\n // placeholder images so we can quickly swap them into the file list on demand.\n // Any placeholder images that cannot be loaded/found are simply ignored.\n cacheThumbnailPlaceholders = function() {\n var notAvailableUrl = options.placeholders.thumbnailNotAvailable,\n waitingUrl = options.placeholders.waitingForThumbnail,\n spec = {\n maxSize: thumbnailMaxSize,\n scale: serverScale\n };\n\n if (showThumbnails) {\n if (notAvailableUrl) {\n options.imageGenerator.generate(notAvailableUrl, new Image(), spec).then(\n function(updatedImg) {\n cachedThumbnailNotAvailableImg.success(updatedImg);\n },\n function() {\n cachedThumbnailNotAvailableImg.failure();\n log(\"Problem loading 'not available' placeholder image at \" + notAvailableUrl, \"error\");\n }\n );\n }\n else {\n cachedThumbnailNotAvailableImg.failure();\n }\n\n if (waitingUrl) {\n options.imageGenerator.generate(waitingUrl, new Image(), spec).then(\n function(updatedImg) {\n cachedWaitingForThumbnailImg.success(updatedImg);\n },\n function() {\n cachedWaitingForThumbnailImg.failure();\n log(\"Problem loading 'waiting for thumbnail' placeholder image at \" + waitingUrl, \"error\");\n }\n );\n }\n else {\n cachedWaitingForThumbnailImg.failure();\n }\n }\n },\n\n // Displays a \"waiting for thumbnail\" type placeholder image\n // iff we were able to load it during initialization of the templating module.\n displayWaitingImg = function(thumbnail) {\n var waitingImgPlacement = new qq.Promise();\n\n cachedWaitingForThumbnailImg.then(function(img) {\n maybeScalePlaceholderViaCss(img, thumbnail);\n /* jshint eqnull:true */\n if (!thumbnail.src) {\n thumbnail.src = img.src;\n thumbnail.onload = function() {\n thumbnail.onload = null;\n show(thumbnail);\n waitingImgPlacement.success();\n };\n }\n else {\n waitingImgPlacement.success();\n }\n }, function() {\n // In some browsers (such as IE9 and older) an img w/out a src attribute\n // are displayed as \"broken\" images, so we should just hide the img tag\n // if we aren't going to display the \"waiting\" placeholder.\n hide(thumbnail);\n waitingImgPlacement.success();\n });\n\n return waitingImgPlacement;\n },\n\n generateNewPreview = function(id, blob, spec) {\n var thumbnail = getThumbnail(id);\n\n log(\"Generating new thumbnail for \" + id);\n blob.qqThumbnailId = id;\n\n return options.imageGenerator.generate(blob, thumbnail, spec).then(\n function() {\n generatedThumbnails++;\n show(thumbnail);\n previewGeneration[id].success();\n },\n function() {\n previewGeneration[id].failure();\n\n // Display the \"not available\" placeholder img only if we are\n // not expecting a thumbnail at a later point, such as in a server response.\n if (!options.placeholders.waitUntilUpdate) {\n maybeSetDisplayNotAvailableImg(id, thumbnail);\n }\n });\n },\n\n generateNextQueuedPreview = function() {\n if (thumbGenerationQueue.length) {\n thumbnailQueueMonitorRunning = true;\n\n var queuedThumbRequest = thumbGenerationQueue.shift();\n\n if (queuedThumbRequest.update) {\n processUpdateQueuedPreviewRequest(queuedThumbRequest);\n }\n else {\n processNewQueuedPreviewRequest(queuedThumbRequest);\n }\n }\n else {\n thumbnailQueueMonitorRunning = false;\n }\n },\n\n getCancel = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.cancel);\n },\n\n getContinue = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.continueButton);\n },\n\n getDialog = function(type) {\n return getTemplateEl(container, selectorClasses[type + \"Dialog\"]);\n },\n\n getDelete = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.deleteButton);\n },\n\n getDropProcessing = function() {\n return getTemplateEl(container, selectorClasses.dropProcessing);\n },\n\n getEditIcon = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.editNameIcon);\n },\n\n getFile = function(id) {\n return fileBatch.map[id] || qq(fileList).getFirstByClass(FILE_CLASS_PREFIX + id);\n },\n\n getFilename = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.file);\n },\n\n getPause = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.pause);\n },\n\n getProgress = function(id) {\n /* jshint eqnull:true */\n // Total progress bar\n if (id == null) {\n return getTemplateEl(container, selectorClasses.totalProgressBarContainer) ||\n getTemplateEl(container, selectorClasses.totalProgressBar);\n }\n\n // Per-file progress bar\n return getTemplateEl(getFile(id), selectorClasses.progressBarContainer) ||\n getTemplateEl(getFile(id), selectorClasses.progressBar);\n },\n\n getRetry = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.retry);\n },\n\n getSize = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.size);\n },\n\n getSpinner = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.spinner);\n },\n\n getTemplateEl = function(context, cssClass) {\n return context && qq(context).getFirstByClass(cssClass);\n },\n\n getThumbnail = function(id) {\n return showThumbnails && getTemplateEl(getFile(id), selectorClasses.thumbnail);\n },\n\n hide = function(el) {\n el && qq(el).addClass(options.classes.hide);\n },\n\n // Ensures a placeholder image does not exceed any max size specified\n // via `style` attribute properties iff was not used to scale\n // the placeholder AND the target doesn't already have these `style` attribute properties set.\n maybeScalePlaceholderViaCss = function(placeholder, thumbnail) {\n var maxWidth = placeholder.style.maxWidth,\n maxHeight = placeholder.style.maxHeight;\n\n if (maxHeight && maxWidth && !thumbnail.style.maxWidth && !thumbnail.style.maxHeight) {\n qq(thumbnail).css({\n maxWidth: maxWidth,\n maxHeight: maxHeight\n });\n }\n },\n\n // Displays a \"thumbnail not available\" type placeholder image\n // iff we were able to load this placeholder during initialization\n // of the templating module or after preview generation has failed.\n maybeSetDisplayNotAvailableImg = function(id, thumbnail) {\n var previewing = previewGeneration[id] || new qq.Promise().failure(),\n notAvailableImgPlacement = new qq.Promise();\n\n cachedThumbnailNotAvailableImg.then(function(img) {\n previewing.then(\n function() {\n notAvailableImgPlacement.success();\n },\n function() {\n maybeScalePlaceholderViaCss(img, thumbnail);\n\n thumbnail.onload = function() {\n thumbnail.onload = null;\n notAvailableImgPlacement.success();\n };\n\n thumbnail.src = img.src;\n show(thumbnail);\n }\n );\n });\n\n return notAvailableImgPlacement;\n },\n\n /**\n * Grabs the HTML from the script tag holding the template markup. This function will also adjust\n * some internally-tracked state variables based on the contents of the template.\n * The template is filtered so that irrelevant elements (such as the drop zone if DnD is not supported)\n * are omitted from the DOM. Useful errors will be thrown if the template cannot be parsed.\n *\n * @returns {{template: *, fileTemplate: *}} HTML for the top-level file items templates\n */\n parseAndGetTemplate = function() {\n var scriptEl,\n scriptHtml,\n fileListNode,\n tempTemplateEl,\n fileListEl,\n defaultButton,\n dropArea,\n thumbnail,\n dropProcessing,\n dropTextEl,\n uploaderEl;\n\n log(\"Parsing template\");\n\n /*jshint -W116*/\n if (options.templateIdOrEl == null) {\n throw new Error(\"You MUST specify either a template element or ID!\");\n }\n\n // Grab the contents of the script tag holding the template.\n if (qq.isString(options.templateIdOrEl)) {\n scriptEl = document.getElementById(options.templateIdOrEl);\n\n if (scriptEl === null) {\n throw new Error(qq.format(\"Cannot find template script at ID '{}'!\", options.templateIdOrEl));\n }\n\n scriptHtml = scriptEl.innerHTML;\n }\n else {\n if (options.templateIdOrEl.innerHTML === undefined) {\n throw new Error(\"You have specified an invalid value for the template option! \" +\n \"It must be an ID or an Element.\");\n }\n\n scriptHtml = options.templateIdOrEl.innerHTML;\n }\n\n scriptHtml = qq.trimStr(scriptHtml);\n tempTemplateEl = document.createElement(\"div\");\n tempTemplateEl.appendChild(qq.toElement(scriptHtml));\n uploaderEl = qq(tempTemplateEl).getFirstByClass(selectorClasses.uploader);\n\n // Don't include the default template button in the DOM\n // if an alternate button container has been specified.\n if (options.button) {\n defaultButton = qq(tempTemplateEl).getFirstByClass(selectorClasses.button);\n if (defaultButton) {\n qq(defaultButton).remove();\n }\n }\n\n // Omit the drop processing element from the DOM if DnD is not supported by the UA,\n // or the drag and drop module is not found.\n // NOTE: We are consciously not removing the drop zone if the UA doesn't support DnD\n // to support layouts where the drop zone is also a container for visible elements,\n // such as the file list.\n if (!qq.DragAndDrop || !qq.supportedFeatures.fileDrop) {\n dropProcessing = qq(tempTemplateEl).getFirstByClass(selectorClasses.dropProcessing);\n if (dropProcessing) {\n qq(dropProcessing).remove();\n }\n }\n\n dropArea = qq(tempTemplateEl).getFirstByClass(selectorClasses.drop);\n\n // If DnD is not available then remove\n // it from the DOM as well.\n if (dropArea && !qq.DragAndDrop) {\n log(\"DnD module unavailable.\", \"info\");\n qq(dropArea).remove();\n }\n\n if (!qq.supportedFeatures.fileDrop) {\n // don't display any \"drop files to upload\" background text\n uploaderEl.removeAttribute(DROPZPONE_TEXT_ATTR);\n\n if (dropArea && qq(dropArea).hasAttribute(HIDE_DROPZONE_ATTR)) {\n // If there is a drop area defined in the template, and the current UA doesn't support DnD,\n // and the drop area is marked as \"hide before enter\", ensure it is hidden as the DnD module\n // will not do this (since we will not be loading the DnD module)\n qq(dropArea).css({\n display: \"none\"\n });\n }\n }\n else if (qq(uploaderEl).hasAttribute(DROPZPONE_TEXT_ATTR) && dropArea) {\n dropTextEl = qq(dropArea).getFirstByClass(selectorClasses.dropText);\n dropTextEl && qq(dropTextEl).remove();\n }\n\n // Ensure the `showThumbnails` flag is only set if the thumbnail element\n // is present in the template AND the current UA is capable of generating client-side previews.\n thumbnail = qq(tempTemplateEl).getFirstByClass(selectorClasses.thumbnail);\n if (!showThumbnails) {\n thumbnail && qq(thumbnail).remove();\n }\n else if (thumbnail) {\n thumbnailMaxSize = parseInt(thumbnail.getAttribute(THUMBNAIL_MAX_SIZE_ATTR));\n // Only enforce max size if the attr value is non-zero\n thumbnailMaxSize = thumbnailMaxSize > 0 ? thumbnailMaxSize : null;\n\n serverScale = qq(thumbnail).hasAttribute(THUMBNAIL_SERVER_SCALE_ATTR);\n }\n showThumbnails = showThumbnails && thumbnail;\n\n isEditElementsExist = qq(tempTemplateEl).getByClass(selectorClasses.editFilenameInput).length > 0;\n isRetryElementExist = qq(tempTemplateEl).getByClass(selectorClasses.retry).length > 0;\n\n fileListNode = qq(tempTemplateEl).getFirstByClass(selectorClasses.list);\n /*jshint -W116*/\n if (fileListNode == null) {\n throw new Error(\"Could not find the file list container in the template!\");\n }\n\n fileListEl = fileListNode.children[0].cloneNode(true);\n fileListNode.innerHTML = \"\";\n\n // We must call `createElement` in IE8 in order to target and hide any via CSS\n if (tempTemplateEl.getElementsByTagName(\"DIALOG\").length) {\n document.createElement(\"dialog\");\n }\n\n log(\"Template parsing complete\");\n\n return {\n template: tempTemplateEl,\n fileTemplate: fileListEl\n };\n },\n\n prependFile = function(el, index, fileList) {\n var parentEl = fileList,\n beforeEl = parentEl.firstChild;\n\n if (index > 0) {\n beforeEl = qq(parentEl).children()[index].nextSibling;\n\n }\n\n parentEl.insertBefore(el, beforeEl);\n },\n\n processNewQueuedPreviewRequest = function(queuedThumbRequest) {\n var id = queuedThumbRequest.id,\n optFileOrBlob = queuedThumbRequest.optFileOrBlob,\n relatedThumbnailId = optFileOrBlob && optFileOrBlob.qqThumbnailId,\n thumbnail = getThumbnail(id),\n spec = {\n customResizeFunction: queuedThumbRequest.customResizeFunction,\n maxSize: thumbnailMaxSize,\n orient: true,\n scale: true\n };\n\n if (qq.supportedFeatures.imagePreviews) {\n if (thumbnail) {\n if (options.limits.maxThumbs && options.limits.maxThumbs <= generatedThumbnails) {\n maybeSetDisplayNotAvailableImg(id, thumbnail);\n generateNextQueuedPreview();\n }\n else {\n displayWaitingImg(thumbnail).done(function() {\n previewGeneration[id] = new qq.Promise();\n\n previewGeneration[id].done(function() {\n setTimeout(generateNextQueuedPreview, options.limits.timeBetweenThumbs);\n });\n\n /* jshint eqnull: true */\n // If we've already generated an for this file, use the one that exists,\n // don't waste resources generating a new one.\n if (relatedThumbnailId != null) {\n useCachedPreview(id, relatedThumbnailId);\n }\n else {\n generateNewPreview(id, optFileOrBlob, spec);\n }\n });\n }\n }\n // File element in template may have been removed, so move on to next item in queue\n else {\n generateNextQueuedPreview();\n }\n }\n else if (thumbnail) {\n displayWaitingImg(thumbnail);\n generateNextQueuedPreview();\n }\n },\n\n processUpdateQueuedPreviewRequest = function(queuedThumbRequest) {\n var id = queuedThumbRequest.id,\n thumbnailUrl = queuedThumbRequest.thumbnailUrl,\n showWaitingImg = queuedThumbRequest.showWaitingImg,\n thumbnail = getThumbnail(id),\n spec = {\n customResizeFunction: queuedThumbRequest.customResizeFunction,\n scale: serverScale,\n maxSize: thumbnailMaxSize\n };\n\n if (thumbnail) {\n if (thumbnailUrl) {\n if (options.limits.maxThumbs && options.limits.maxThumbs <= generatedThumbnails) {\n maybeSetDisplayNotAvailableImg(id, thumbnail);\n generateNextQueuedPreview();\n }\n else {\n if (showWaitingImg) {\n displayWaitingImg(thumbnail);\n }\n\n return options.imageGenerator.generate(thumbnailUrl, thumbnail, spec).then(\n function() {\n show(thumbnail);\n generatedThumbnails++;\n setTimeout(generateNextQueuedPreview, options.limits.timeBetweenThumbs);\n },\n\n function() {\n maybeSetDisplayNotAvailableImg(id, thumbnail);\n setTimeout(generateNextQueuedPreview, options.limits.timeBetweenThumbs);\n }\n );\n }\n }\n else {\n maybeSetDisplayNotAvailableImg(id, thumbnail);\n generateNextQueuedPreview();\n }\n }\n },\n\n setProgressBarWidth = function(id, percent) {\n var bar = getProgress(id),\n /* jshint eqnull:true */\n progressBarSelector = id == null ? selectorClasses.totalProgressBar : selectorClasses.progressBar;\n\n if (bar && !qq(bar).hasClass(progressBarSelector)) {\n bar = qq(bar).getFirstByClass(progressBarSelector);\n }\n\n if (bar) {\n qq(bar).css({width: percent + \"%\"});\n bar.setAttribute(\"aria-valuenow\", percent);\n }\n },\n\n show = function(el) {\n el && qq(el).removeClass(options.classes.hide);\n },\n\n useCachedPreview = function(targetThumbnailId, cachedThumbnailId) {\n var targetThumbnail = getThumbnail(targetThumbnailId),\n cachedThumbnail = getThumbnail(cachedThumbnailId);\n\n log(qq.format(\"ID {} is the same file as ID {}. Will use generated thumbnail from ID {} instead.\", targetThumbnailId, cachedThumbnailId, cachedThumbnailId));\n\n // Generation of the related thumbnail may still be in progress, so, wait until it is done.\n previewGeneration[cachedThumbnailId].then(function() {\n generatedThumbnails++;\n previewGeneration[targetThumbnailId].success();\n log(qq.format(\"Now using previously generated thumbnail created for ID {} on ID {}.\", cachedThumbnailId, targetThumbnailId));\n targetThumbnail.src = cachedThumbnail.src;\n show(targetThumbnail);\n },\n function() {\n previewGeneration[targetThumbnailId].failure();\n if (!options.placeholders.waitUntilUpdate) {\n maybeSetDisplayNotAvailableImg(targetThumbnailId, targetThumbnail);\n }\n });\n };\n\n qq.extend(options, spec);\n log = options.log;\n\n // No need to worry about conserving CPU or memory on older browsers,\n // since there is no ability to preview, and thumbnail display is primitive and quick.\n if (!qq.supportedFeatures.imagePreviews) {\n options.limits.timeBetweenThumbs = 0;\n options.limits.maxThumbs = 0;\n }\n\n container = options.containerEl;\n showThumbnails = options.imageGenerator !== undefined;\n templateDom = parseAndGetTemplate();\n\n cacheThumbnailPlaceholders();\n\n qq.extend(this, {\n render: function() {\n log(\"Rendering template in DOM.\");\n\n generatedThumbnails = 0;\n\n container.appendChild(templateDom.template.cloneNode(true));\n hide(getDropProcessing());\n this.hideTotalProgress();\n fileList = options.fileContainerEl || getTemplateEl(container, selectorClasses.list);\n\n log(\"Template rendering complete\");\n },\n\n renderFailure: function(message) {\n var cantRenderEl = qq.toElement(message);\n container.innerHTML = \"\";\n container.appendChild(cantRenderEl);\n },\n\n reset: function() {\n container.innerHTML = \"\";\n this.render();\n },\n\n clearFiles: function() {\n fileList.innerHTML = \"\";\n },\n\n disableCancel: function() {\n isCancelDisabled = true;\n },\n\n addFile: function(id, name, prependInfo, hideForever, batch) {\n var fileEl = templateDom.fileTemplate.cloneNode(true),\n fileNameEl = getTemplateEl(fileEl, selectorClasses.file),\n uploaderEl = getTemplateEl(container, selectorClasses.uploader),\n fileContainer = batch ? fileBatch.content : fileList,\n thumb;\n\n if (batch) {\n fileBatch.map[id] = fileEl;\n }\n\n qq(fileEl).addClass(FILE_CLASS_PREFIX + id);\n uploaderEl.removeAttribute(DROPZPONE_TEXT_ATTR);\n\n if (fileNameEl) {\n qq(fileNameEl).setText(name);\n fileNameEl.setAttribute(\"title\", name);\n }\n\n fileEl.setAttribute(FILE_ID_ATTR, id);\n\n if (prependInfo) {\n prependFile(fileEl, prependInfo.index, fileContainer);\n }\n else {\n fileContainer.appendChild(fileEl);\n }\n\n if (hideForever) {\n fileEl.style.display = \"none\";\n qq(fileEl).addClass(HIDDEN_FOREVER_CLASS);\n }\n else {\n hide(getProgress(id));\n hide(getSize(id));\n hide(getDelete(id));\n hide(getRetry(id));\n hide(getPause(id));\n hide(getContinue(id));\n\n if (isCancelDisabled) {\n this.hideCancel(id);\n }\n\n thumb = getThumbnail(id);\n if (thumb && !thumb.src) {\n cachedWaitingForThumbnailImg.then(function(waitingImg) {\n thumb.src = waitingImg.src;\n if (waitingImg.style.maxHeight && waitingImg.style.maxWidth) {\n qq(thumb).css({\n maxHeight: waitingImg.style.maxHeight,\n maxWidth: waitingImg.style.maxWidth\n });\n }\n\n show(thumb);\n });\n }\n }\n },\n\n addFileToCache: function(id, name, prependInfo, hideForever) {\n this.addFile(id, name, prependInfo, hideForever, true);\n },\n\n addCacheToDom: function() {\n fileList.appendChild(fileBatch.content);\n fileBatch.content = document.createDocumentFragment();\n fileBatch.map = {};\n },\n\n removeFile: function(id) {\n qq(getFile(id)).remove();\n },\n\n getFileId: function(el) {\n var currentNode = el;\n\n if (currentNode) {\n /*jshint -W116*/\n while (currentNode.getAttribute(FILE_ID_ATTR) == null) {\n currentNode = currentNode.parentNode;\n }\n\n return parseInt(currentNode.getAttribute(FILE_ID_ATTR));\n }\n },\n\n getFileList: function() {\n return fileList;\n },\n\n markFilenameEditable: function(id) {\n var filename = getFilename(id);\n\n filename && qq(filename).addClass(options.classes.editable);\n },\n\n updateFilename: function(id, name) {\n var filenameEl = getFilename(id);\n\n if (filenameEl) {\n qq(filenameEl).setText(name);\n filenameEl.setAttribute(\"title\", name);\n }\n },\n\n hideFilename: function(id) {\n hide(getFilename(id));\n },\n\n showFilename: function(id) {\n show(getFilename(id));\n },\n\n isFileName: function(el) {\n return qq(el).hasClass(selectorClasses.file);\n },\n\n getButton: function() {\n return options.button || getTemplateEl(container, selectorClasses.button);\n },\n\n hideDropProcessing: function() {\n hide(getDropProcessing());\n },\n\n showDropProcessing: function() {\n show(getDropProcessing());\n },\n\n getDropZone: function() {\n return getTemplateEl(container, selectorClasses.drop);\n },\n\n isEditFilenamePossible: function() {\n return isEditElementsExist;\n },\n\n hideRetry: function(id) {\n hide(getRetry(id));\n },\n\n isRetryPossible: function() {\n return isRetryElementExist;\n },\n\n showRetry: function(id) {\n show(getRetry(id));\n },\n\n getFileContainer: function(id) {\n return getFile(id);\n },\n\n showEditIcon: function(id) {\n var icon = getEditIcon(id);\n\n icon && qq(icon).addClass(options.classes.editable);\n },\n\n isHiddenForever: function(id) {\n return qq(getFile(id)).hasClass(HIDDEN_FOREVER_CLASS);\n },\n\n hideEditIcon: function(id) {\n var icon = getEditIcon(id);\n\n icon && qq(icon).removeClass(options.classes.editable);\n },\n\n isEditIcon: function(el) {\n return qq(el).hasClass(selectorClasses.editNameIcon, true);\n },\n\n getEditInput: function(id) {\n return getTemplateEl(getFile(id), selectorClasses.editFilenameInput);\n },\n\n isEditInput: function(el) {\n return qq(el).hasClass(selectorClasses.editFilenameInput, true);\n },\n\n updateProgress: function(id, loaded, total) {\n var bar = getProgress(id),\n percent;\n\n if (bar && total > 0) {\n percent = Math.round(loaded / total * 100);\n\n if (percent === 100) {\n hide(bar);\n }\n else {\n show(bar);\n }\n\n setProgressBarWidth(id, percent);\n }\n },\n\n updateTotalProgress: function(loaded, total) {\n this.updateProgress(null, loaded, total);\n },\n\n hideProgress: function(id) {\n var bar = getProgress(id);\n\n bar && hide(bar);\n },\n\n hideTotalProgress: function() {\n this.hideProgress();\n },\n\n resetProgress: function(id) {\n setProgressBarWidth(id, 0);\n this.hideTotalProgress(id);\n },\n\n resetTotalProgress: function() {\n this.resetProgress();\n },\n\n showCancel: function(id) {\n if (!isCancelDisabled) {\n var cancel = getCancel(id);\n\n cancel && qq(cancel).removeClass(options.classes.hide);\n }\n },\n\n hideCancel: function(id) {\n hide(getCancel(id));\n },\n\n isCancel: function(el) {\n return qq(el).hasClass(selectorClasses.cancel, true);\n },\n\n allowPause: function(id) {\n show(getPause(id));\n hide(getContinue(id));\n },\n\n uploadPaused: function(id) {\n this.setStatusText(id, options.text.paused);\n this.allowContinueButton(id);\n hide(getSpinner(id));\n },\n\n hidePause: function(id) {\n hide(getPause(id));\n },\n\n isPause: function(el) {\n return qq(el).hasClass(selectorClasses.pause, true);\n },\n\n isContinueButton: function(el) {\n return qq(el).hasClass(selectorClasses.continueButton, true);\n },\n\n allowContinueButton: function(id) {\n show(getContinue(id));\n hide(getPause(id));\n },\n\n uploadContinued: function(id) {\n this.setStatusText(id, \"\");\n this.allowPause(id);\n show(getSpinner(id));\n },\n\n showDeleteButton: function(id) {\n show(getDelete(id));\n },\n\n hideDeleteButton: function(id) {\n hide(getDelete(id));\n },\n\n isDeleteButton: function(el) {\n return qq(el).hasClass(selectorClasses.deleteButton, true);\n },\n\n isRetry: function(el) {\n return qq(el).hasClass(selectorClasses.retry, true);\n },\n\n updateSize: function(id, text) {\n var size = getSize(id);\n\n if (size) {\n show(size);\n qq(size).setText(text);\n }\n },\n\n setStatusText: function(id, text) {\n var textEl = getTemplateEl(getFile(id), selectorClasses.statusText);\n\n if (textEl) {\n /*jshint -W116*/\n if (text == null) {\n qq(textEl).clearText();\n }\n else {\n qq(textEl).setText(text);\n }\n }\n },\n\n hideSpinner: function(id) {\n qq(getFile(id)).removeClass(IN_PROGRESS_CLASS);\n hide(getSpinner(id));\n },\n\n showSpinner: function(id) {\n qq(getFile(id)).addClass(IN_PROGRESS_CLASS);\n show(getSpinner(id));\n },\n\n generatePreview: function(id, optFileOrBlob, customResizeFunction) {\n if (!this.isHiddenForever(id)) {\n thumbGenerationQueue.push({id: id, customResizeFunction: customResizeFunction, optFileOrBlob: optFileOrBlob});\n !thumbnailQueueMonitorRunning && generateNextQueuedPreview();\n }\n },\n\n updateThumbnail: function(id, thumbnailUrl, showWaitingImg, customResizeFunction) {\n if (!this.isHiddenForever(id)) {\n thumbGenerationQueue.push({customResizeFunction: customResizeFunction, update: true, id: id, thumbnailUrl: thumbnailUrl, showWaitingImg: showWaitingImg});\n !thumbnailQueueMonitorRunning && generateNextQueuedPreview();\n }\n },\n\n hasDialog: function(type) {\n return qq.supportedFeatures.dialogElement && !!getDialog(type);\n },\n\n showDialog: function(type, message, defaultValue) {\n var dialog = getDialog(type),\n messageEl = getTemplateEl(dialog, selectorClasses.dialogMessage),\n inputEl = dialog.getElementsByTagName(\"INPUT\")[0],\n cancelBtn = getTemplateEl(dialog, selectorClasses.dialogCancelButton),\n okBtn = getTemplateEl(dialog, selectorClasses.dialogOkButton),\n promise = new qq.Promise(),\n\n closeHandler = function() {\n cancelBtn.removeEventListener(\"click\", cancelClickHandler);\n okBtn && okBtn.removeEventListener(\"click\", okClickHandler);\n promise.failure();\n },\n\n cancelClickHandler = function() {\n cancelBtn.removeEventListener(\"click\", cancelClickHandler);\n dialog.close();\n },\n\n okClickHandler = function() {\n dialog.removeEventListener(\"close\", closeHandler);\n okBtn.removeEventListener(\"click\", okClickHandler);\n dialog.close();\n\n promise.success(inputEl && inputEl.value);\n };\n\n dialog.addEventListener(\"close\", closeHandler);\n cancelBtn.addEventListener(\"click\", cancelClickHandler);\n okBtn && okBtn.addEventListener(\"click\", okClickHandler);\n\n if (inputEl) {\n inputEl.value = defaultValue;\n }\n messageEl.textContent = message;\n\n dialog.showModal();\n\n return promise;\n }\n });\n};\n","/*globals qq */\n// Base handler for UI (FineUploader mode) events.\n// Some more specific handlers inherit from this one.\nqq.UiEventHandler = function(s, protectedApi) {\n \"use strict\";\n\n var disposer = new qq.DisposeSupport(),\n spec = {\n eventType: \"click\",\n attachTo: null,\n onHandled: function(target, event) {}\n };\n\n // This makes up the \"public\" API methods that will be accessible\n // to instances constructing a base or child handler\n qq.extend(this, {\n addHandler: function(element) {\n addHandler(element);\n },\n\n dispose: function() {\n disposer.dispose();\n }\n });\n\n function addHandler(element) {\n disposer.attach(element, spec.eventType, function(event) {\n // Only in IE: the `event` is a property of the `window`.\n event = event || window.event;\n\n // On older browsers, we must check the `srcElement` instead of the `target`.\n var target = event.target || event.srcElement;\n\n spec.onHandled(target, event);\n });\n }\n\n // These make up the \"protected\" API methods that children of this base handler will utilize.\n qq.extend(protectedApi, {\n getFileIdFromItem: function(item) {\n return item.qqFileId;\n },\n\n getDisposeSupport: function() {\n return disposer;\n }\n });\n\n qq.extend(spec, s);\n\n if (spec.attachTo) {\n addHandler(spec.attachTo);\n }\n};\n","/* global qq */\nqq.FileButtonsClickHandler = function(s) {\n \"use strict\";\n\n var inheritedInternalApi = {},\n spec = {\n templating: null,\n log: function(message, lvl) {},\n onDeleteFile: function(fileId) {},\n onCancel: function(fileId) {},\n onRetry: function(fileId) {},\n onPause: function(fileId) {},\n onContinue: function(fileId) {},\n onGetName: function(fileId) {}\n },\n buttonHandlers = {\n cancel: function(id) { spec.onCancel(id); },\n retry: function(id) { spec.onRetry(id); },\n deleteButton: function(id) { spec.onDeleteFile(id); },\n pause: function(id) { spec.onPause(id); },\n continueButton: function(id) { spec.onContinue(id); }\n };\n\n function examineEvent(target, event) {\n qq.each(buttonHandlers, function(buttonType, handler) {\n var firstLetterCapButtonType = buttonType.charAt(0).toUpperCase() + buttonType.slice(1),\n fileId;\n\n if (spec.templating[\"is\" + firstLetterCapButtonType](target)) {\n fileId = spec.templating.getFileId(target);\n qq.preventDefault(event);\n spec.log(qq.format(\"Detected valid file button click event on file '{}', ID: {}.\", spec.onGetName(fileId), fileId));\n handler(fileId);\n return false;\n }\n });\n }\n\n qq.extend(spec, s);\n\n spec.eventType = \"click\";\n spec.onHandled = examineEvent;\n spec.attachTo = spec.templating.getFileList();\n\n qq.extend(this, new qq.UiEventHandler(spec, inheritedInternalApi));\n};\n","/*globals qq */\n// Child of FilenameEditHandler. Used to detect click events on filename display elements.\nqq.FilenameClickHandler = function(s) {\n \"use strict\";\n\n var inheritedInternalApi = {},\n spec = {\n templating: null,\n log: function(message, lvl) {},\n classes: {\n file: \"qq-upload-file\",\n editNameIcon: \"qq-edit-filename-icon\"\n },\n onGetUploadStatus: function(fileId) {},\n onGetName: function(fileId) {}\n };\n\n qq.extend(spec, s);\n\n // This will be called by the parent handler when a `click` event is received on the list element.\n function examineEvent(target, event) {\n if (spec.templating.isFileName(target) || spec.templating.isEditIcon(target)) {\n var fileId = spec.templating.getFileId(target),\n status = spec.onGetUploadStatus(fileId);\n\n // We only allow users to change filenames of files that have been submitted but not yet uploaded.\n if (status === qq.status.SUBMITTED) {\n spec.log(qq.format(\"Detected valid filename click event on file '{}', ID: {}.\", spec.onGetName(fileId), fileId));\n qq.preventDefault(event);\n\n inheritedInternalApi.handleFilenameEdit(fileId, target, true);\n }\n }\n }\n\n spec.eventType = \"click\";\n spec.onHandled = examineEvent;\n\n qq.extend(this, new qq.FilenameEditHandler(spec, inheritedInternalApi));\n};\n","/*globals qq */\n// Child of FilenameEditHandler. Used to detect focusin events on file edit input elements.\nqq.FilenameInputFocusInHandler = function(s, inheritedInternalApi) {\n \"use strict\";\n\n var spec = {\n templating: null,\n onGetUploadStatus: function(fileId) {},\n log: function(message, lvl) {}\n };\n\n if (!inheritedInternalApi) {\n inheritedInternalApi = {};\n }\n\n // This will be called by the parent handler when a `focusin` event is received on the list element.\n function handleInputFocus(target, event) {\n if (spec.templating.isEditInput(target)) {\n var fileId = spec.templating.getFileId(target),\n status = spec.onGetUploadStatus(fileId);\n\n if (status === qq.status.SUBMITTED) {\n spec.log(qq.format(\"Detected valid filename input focus event on file '{}', ID: {}.\", spec.onGetName(fileId), fileId));\n inheritedInternalApi.handleFilenameEdit(fileId, target);\n }\n }\n }\n\n spec.eventType = \"focusin\";\n spec.onHandled = handleInputFocus;\n\n qq.extend(spec, s);\n qq.extend(this, new qq.FilenameEditHandler(spec, inheritedInternalApi));\n};\n","/*globals qq */\n/**\n * Child of FilenameInputFocusInHandler. Used to detect focus events on file edit input elements. This child module is only\n * needed for UAs that do not support the focusin event. Currently, only Firefox lacks this event.\n *\n * @param spec Overrides for default specifications\n */\nqq.FilenameInputFocusHandler = function(spec) {\n \"use strict\";\n\n spec.eventType = \"focus\";\n spec.attachTo = null;\n\n qq.extend(this, new qq.FilenameInputFocusInHandler(spec, {}));\n};\n","/*globals qq */\n// Handles edit-related events on a file item (FineUploader mode). This is meant to be a parent handler.\n// Children will delegate to this handler when specific edit-related actions are detected.\nqq.FilenameEditHandler = function(s, inheritedInternalApi) {\n \"use strict\";\n\n var spec = {\n templating: null,\n log: function(message, lvl) {},\n onGetUploadStatus: function(fileId) {},\n onGetName: function(fileId) {},\n onSetName: function(fileId, newName) {},\n onEditingStatusChange: function(fileId, isEditing) {}\n };\n\n function getFilenameSansExtension(fileId) {\n var filenameSansExt = spec.onGetName(fileId),\n extIdx = filenameSansExt.lastIndexOf(\".\");\n\n if (extIdx > 0) {\n filenameSansExt = filenameSansExt.substr(0, extIdx);\n }\n\n return filenameSansExt;\n }\n\n function getOriginalExtension(fileId) {\n var origName = spec.onGetName(fileId);\n return qq.getExtension(origName);\n }\n\n // Callback iff the name has been changed\n function handleNameUpdate(newFilenameInputEl, fileId) {\n var newName = newFilenameInputEl.value,\n origExtension;\n\n if (newName !== undefined && qq.trimStr(newName).length > 0) {\n origExtension = getOriginalExtension(fileId);\n\n if (origExtension !== undefined) {\n newName = newName + \".\" + origExtension;\n }\n\n spec.onSetName(fileId, newName);\n }\n\n spec.onEditingStatusChange(fileId, false);\n }\n\n // The name has been updated if the filename edit input loses focus.\n function registerInputBlurHandler(inputEl, fileId) {\n inheritedInternalApi.getDisposeSupport().attach(inputEl, \"blur\", function() {\n handleNameUpdate(inputEl, fileId);\n });\n }\n\n // The name has been updated if the user presses enter.\n function registerInputEnterKeyHandler(inputEl, fileId) {\n inheritedInternalApi.getDisposeSupport().attach(inputEl, \"keyup\", function(event) {\n\n var code = event.keyCode || event.which;\n\n if (code === 13) {\n handleNameUpdate(inputEl, fileId);\n }\n });\n }\n\n qq.extend(spec, s);\n\n spec.attachTo = spec.templating.getFileList();\n\n qq.extend(this, new qq.UiEventHandler(spec, inheritedInternalApi));\n\n qq.extend(inheritedInternalApi, {\n handleFilenameEdit: function(id, target, focusInput) {\n var newFilenameInputEl = spec.templating.getEditInput(id);\n\n spec.onEditingStatusChange(id, true);\n\n newFilenameInputEl.value = getFilenameSansExtension(id);\n\n if (focusInput) {\n newFilenameInputEl.focus();\n }\n\n registerInputBlurHandler(newFilenameInputEl, id);\n registerInputEnterKeyHandler(newFilenameInputEl, id);\n }\n });\n};\n"]}
\ No newline at end of file
diff --git a/styles/bootstrap/fine-uploader/jquery.fine-uploader.min.js b/styles/bootstrap/fine-uploader/jquery.fine-uploader.min.js
index 4d1ee506f..8ac83d6a9 100644
--- a/styles/bootstrap/fine-uploader/jquery.fine-uploader.min.js
+++ b/styles/bootstrap/fine-uploader/jquery.fine-uploader.min.js
@@ -1,7 +1,7 @@
-// Fine Uploader 5.12.0 - (c) 2013-present Widen Enterprises, Inc. MIT licensed. http://fineuploader.com
-!function(global){!function(e){"use strict";function t(e){var t=s(e||{}),i=n(t);return o(i),a(t,i),d}function n(e){var t=r("uploaderType"),n=r("endpointType");return t?(t=t.charAt(0).toUpperCase()+t.slice(1).toLowerCase(),n?new qq[n]["FineUploader"+t](e):new qq["FineUploader"+t](e)):n?new qq[n].FineUploader(e):new qq.FineUploader(e)}function i(e,t){var n=d.data("fineuploader");return t?(void 0===n&&(n={}),n[e]=t,d.data("fineuploader",n),void 0):void 0===n?null:n[e]}function o(e){return i("uploader",e)}function r(e,t){return i(e,t)}function a(t,n){var i=t.callbacks={};e.each(n._options.callbacks,function(t,n){var o,r;o=/^on(\w+)/.exec(t)[1],o=o.substring(0,1).toLowerCase()+o.substring(1),r=d,i[t]=function(){var t,i,a=Array.prototype.slice.call(arguments),s=[];e.each(a,function(e,t){s.push(c(t))}),t=n.apply(this,a);try{i=r.triggerHandler(o,s)}catch(e){qq.log("Caught error in Fine Uploader jQuery event handler: "+e.message,"error")}return null!=t?t:i}}),n._options.callbacks=i}function s(t,n){var i,o;if(i=void 0===n?"basic"!==t.uploaderType?{element:d[0]}:{}:n,e.each(t,function(t,n){e.inArray(t,p)>=0?r(t,n):n instanceof e?i[t]=n[0]:e.isPlainObject(n)?(i[t]={},s(n,i[t])):e.isArray(n)?(o=[],e.each(n,function(t,n){var i={};n instanceof e?e.merge(o,n):e.isPlainObject(n)?(s(n,i),o.push(i)):o.push(n)}),i[t]=o):i[t]=n}),void 0===n)return i}function l(t){return"string"===e.type(t)&&!t.match(/^_/)&&void 0!==o()[t]}function u(e){var t,n=[],i=Array.prototype.slice.call(arguments,1);return s(i,n),t=o()[e].apply(o(),n),c(t)}function c(t){var n=t;return null==t||"object"!=typeof t||1!==t.nodeType&&9!==t.nodeType||!t.cloneNode||(n=e(t)),n}var d,p=["uploaderType","endpointType"];e.fn.fineUploader=function(n){var i=this,r=arguments,a=[];return this.each(function(s,c){if(d=e(c),o()&&l(n)){if(a.push(u.apply(i,r)),1===i.length)return!1}else"object"!=typeof n&&n?e.error("Method "+n+" does not exist on jQuery.fineUploader"):t.apply(i,r)}),1===a.length?a[0]:a.length>1?a:this}}(jQuery),function(e){"use strict";function t(e){e||(e={}),e.dropZoneElements=[l];var t=r(e);return o(t),i(new qq.DragAndDrop(t)),l}function n(e,t){var n=l.data(u);return t?(void 0===n&&(n={}),n[e]=t,l.data(u,n),void 0):void 0===n?null:n[e]}function i(e){return n("dndInstance",e)}function o(t){var n=t.callbacks={};e.each(new qq.DragAndDrop.callbacks,function(e,t){var i,o=e;i=l,n[e]=function(){var e=Array.prototype.slice.call(arguments),t=i.triggerHandler(o,e);return t}})}function r(t,n){var i,o;if(i=void 0===n?{}:n,e.each(t,function(t,n){n instanceof e?i[t]=n[0]:e.isPlainObject(n)?(i[t]={},r(n,i[t])):e.isArray(n)?(o=[],e.each(n,function(t,n){n instanceof e?e.merge(o,n):o.push(n)}),i[t]=o):i[t]=n}),void 0===n)return i}function a(t){return"string"===e.type(t)&&"dispose"===t&&void 0!==i()[t]}function s(e){var t=[],n=Array.prototype.slice.call(arguments,1);return r(n,t),i()[e].apply(i(),t)}var l,u="fineUploaderDnd";e.fn.fineUploaderDnd=function(n){var o=this,r=arguments,u=[];return this.each(function(c,d){if(l=e(d),i()&&a(n)){if(u.push(s.apply(o,r)),1===o.length)return!1}else"object"!=typeof n&&n?e.error("Method "+n+" does not exist in Fine Uploader's DnD module."):t.apply(o,r)}),1===u.length?u[0]:u.length>1?u:this}}(jQuery);var qq=function(e){"use strict";return{hide:function(){return e.style.display="none",this},attach:function(t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent&&e.attachEvent("on"+t,n),function(){qq(e).detach(t,n)}},detach:function(t,n){return e.removeEventListener?e.removeEventListener(t,n,!1):e.attachEvent&&e.detachEvent("on"+t,n),this},contains:function(t){return!!t&&(e===t||(e.contains?e.contains(t):!!(8&t.compareDocumentPosition(e))))},insertBefore:function(t){return t.parentNode.insertBefore(e,t),this},remove:function(){return e.parentNode.removeChild(e),this},css:function(t){if(null==e.style)throw new qq.Error("Can't apply style to node as it is not on the HTMLElement prototype chain!");return null!=t.opacity&&"string"!=typeof e.style.opacity&&"undefined"!=typeof e.filters&&(t.filter="alpha(opacity="+Math.round(100*t.opacity)+")"),qq.extend(e.style,t),this},hasClass:function(t,n){var i=new RegExp("(^| )"+t+"( |$)");return i.test(e.className)||!(!n||!i.test(e.parentNode.className))},addClass:function(t){return qq(e).hasClass(t)||(e.className+=" "+t),this},removeClass:function(t){var n=new RegExp("(^| )"+t+"( |$)");return e.className=e.className.replace(n," ").replace(/^\s+|\s+$/g,""),this},getByClass:function(t,n){var i,o=[];return n&&e.querySelector?e.querySelector("."+t):e.querySelectorAll?e.querySelectorAll("."+t):(i=e.getElementsByTagName("*"),qq.each(i,function(e,n){qq(n).hasClass(t)&&o.push(n)}),n?o[0]:o)},getFirstByClass:function(t){return qq(e).getByClass(t,!0)},children:function(){for(var t=[],n=e.firstChild;n;)1===n.nodeType&&t.push(n),n=n.nextSibling;return t},setText:function(t){return e.innerText=t,e.textContent=t,this},clearText:function(){return qq(e).setText("")},hasAttribute:function(t){var n;return e.hasAttribute?!!e.hasAttribute(t)&&null==/^false$/i.exec(e.getAttribute(t)):(n=e[t],void 0!==n&&null==/^false$/i.exec(n))}}};!function(){"use strict";qq.canvasToBlob=function(e,t,n){return qq.dataUriToBlob(e.toDataURL(t,n))},qq.dataUriToBlob=function(e){var t,n,i,o,r=function(e,t){var n=window.BlobBuilder||window.WebKitBlobBuilder||window.MozBlobBuilder||window.MSBlobBuilder,i=n&&new n;return i?(i.append(e),i.getBlob(t)):new Blob([e],{type:t})};return n=e.split(",")[0].indexOf("base64")>=0?atob(e.split(",")[1]):decodeURI(e.split(",")[1]),o=e.split(",")[0].split(":")[1].split(";")[0],t=new ArrayBuffer(n.length),i=new Uint8Array(t),qq.each(n,function(e,t){i[e]=t.charCodeAt(0)}),r(t,o)},qq.log=function(e,t){window.console&&(t&&"info"!==t?window.console[t]?window.console[t](e):window.console.log("<"+t+"> "+e):window.console.log(e))},qq.isObject=function(e){return e&&!e.nodeType&&"[object Object]"===Object.prototype.toString.call(e)},qq.isFunction=function(e){return"function"==typeof e},qq.isArray=function(e){return"[object Array]"===Object.prototype.toString.call(e)||e&&window.ArrayBuffer&&e.buffer&&e.buffer.constructor===ArrayBuffer},qq.isItemList=function(e){return"[object DataTransferItemList]"===Object.prototype.toString.call(e)},qq.isNodeList=function(e){return"[object NodeList]"===Object.prototype.toString.call(e)||e.item&&e.namedItem},qq.isString=function(e){return"[object String]"===Object.prototype.toString.call(e)},qq.trimStr=function(e){return String.prototype.trim?e.trim():e.replace(/^\s+|\s+$/g,"")},qq.format=function(e){var t=Array.prototype.slice.call(arguments,1),n=e,i=n.indexOf("{}");return qq.each(t,function(e,t){var o=n.substring(0,i),r=n.substring(i+2);if(n=o+t+r,i=n.indexOf("{}",i+t.length),i<0)return!1}),n},qq.isFile=function(e){return window.File&&"[object File]"===Object.prototype.toString.call(e)},qq.isFileList=function(e){return window.FileList&&"[object FileList]"===Object.prototype.toString.call(e)},qq.isFileOrInput=function(e){return qq.isFile(e)||qq.isInput(e)},qq.isInput=function(e,t){var n=function(e){var n=e.toLowerCase();return t?"file"!==n:"file"===n};return!!(window.HTMLInputElement&&"[object HTMLInputElement]"===Object.prototype.toString.call(e)&&e.type&&n(e.type))||!!(e.tagName&&"input"===e.tagName.toLowerCase()&&e.type&&n(e.type))},qq.isBlob=function(e){if(window.Blob&&"[object Blob]"===Object.prototype.toString.call(e))return!0},qq.isXhrUploadSupported=function(){var e=document.createElement("input");return e.type="file",void 0!==e.multiple&&"undefined"!=typeof File&&"undefined"!=typeof FormData&&"undefined"!=typeof qq.createXhrInstance().upload},qq.createXhrInstance=function(){if(window.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(e){return qq.log("Neither XHR or ActiveX are supported!","error"),null}},qq.isFolderDropSupported=function(e){return e.items&&e.items.length>0&&e.items[0].webkitGetAsEntry},qq.isFileChunkingSupported=function(){return!qq.androidStock()&&qq.isXhrUploadSupported()&&(void 0!==File.prototype.slice||void 0!==File.prototype.webkitSlice||void 0!==File.prototype.mozSlice)},qq.sliceBlob=function(e,t,n){var i=e.slice||e.mozSlice||e.webkitSlice;return i.call(e,t,n)},qq.arrayBufferToHex=function(e){var t="",n=new Uint8Array(e);return qq.each(n,function(e,n){var i=n.toString(16);i.length<2&&(i="0"+i),t+=i}),t},qq.readBlobToHex=function(e,t,n){var i=qq.sliceBlob(e,t,t+n),o=new FileReader,r=new qq.Promise;return o.onload=function(){r.success(qq.arrayBufferToHex(o.result))},o.onerror=r.failure,o.readAsArrayBuffer(i),r},qq.extend=function(e,t,n){return qq.each(t,function(t,i){n&&qq.isObject(i)?(void 0===e[t]&&(e[t]={}),qq.extend(e[t],i,!0)):e[t]=i}),e},qq.override=function(e,t){var n={},i=t(n);return qq.each(i,function(t,i){void 0!==e[t]&&(n[t]=e[t]),e[t]=i}),e},qq.indexOf=function(e,t,n){if(e.indexOf)return e.indexOf(t,n);n=n||0;var i=e.length;for(n<0&&(n+=i);n=0},qq.safari=function(){return void 0!==navigator.vendor&&navigator.vendor.indexOf("Apple")!==-1},qq.chrome=function(){return void 0!==navigator.vendor&&navigator.vendor.indexOf("Google")!==-1},qq.opera=function(){return void 0!==navigator.vendor&&navigator.vendor.indexOf("Opera")!==-1},qq.firefox=function(){return!qq.edge()&&!qq.ie11()&&navigator.userAgent.indexOf("Mozilla")!==-1&&void 0!==navigator.vendor&&""===navigator.vendor},qq.windows=function(){return"Win32"===navigator.platform},qq.android=function(){return navigator.userAgent.toLowerCase().indexOf("android")!==-1},qq.androidStock=function(){return qq.android()&&navigator.userAgent.toLowerCase().indexOf("chrome")<0},qq.ios6=function(){return qq.ios()&&navigator.userAgent.indexOf(" OS 6_")!==-1},qq.ios7=function(){return qq.ios()&&navigator.userAgent.indexOf(" OS 7_")!==-1},qq.ios8=function(){return qq.ios()&&navigator.userAgent.indexOf(" OS 8_")!==-1},qq.ios800=function(){return qq.ios()&&navigator.userAgent.indexOf(" OS 8_0 ")!==-1},qq.ios=function(){return navigator.userAgent.indexOf("iPad")!==-1||navigator.userAgent.indexOf("iPod")!==-1||navigator.userAgent.indexOf("iPhone")!==-1},qq.iosChrome=function(){return qq.ios()&&navigator.userAgent.indexOf("CriOS")!==-1},qq.iosSafari=function(){return qq.ios()&&!qq.iosChrome()&&navigator.userAgent.indexOf("Safari")!==-1},qq.iosSafariWebView=function(){return qq.ios()&&!qq.iosChrome()&&!qq.iosSafari()},qq.preventDefault=function(e){e.preventDefault?e.preventDefault():e.returnValue=!1},qq.toElement=function(){var e=document.createElement("div");return function(t){e.innerHTML=t;var n=e.firstChild;return e.removeChild(n),n}}(),qq.each=function(e,t){var n,i;if(e)if(window.Storage&&e.constructor===window.Storage)for(n=0;n0)return e.substr(t,e.length-t)},qq.getFilename=function(e){return qq.isInput(e)?e.value.replace(/.*(\/|\\)/,""):qq.isFile(e)&&null!==e.fileName&&void 0!==e.fileName?e.fileName:e.name},qq.DisposeSupport=function(){var e=[];return{dispose:function(){var t;do t=e.shift(),t&&t();while(t)},attach:function(){var e=arguments;this.addDisposer(qq(e[0]).attach.apply(this,Array.prototype.slice.call(arguments,1)))},addDisposer:function(t){e.push(t)}}}}(),function(){"use strict";"function"==typeof define&&define.amd?define(function(){return qq}):"undefined"!=typeof module&&module.exports?module.exports=qq:global.qq=qq}(),function(){"use strict";qq.Error=function(e){this.message="[Fine Uploader "+qq.version+"] "+e},qq.Error.prototype=new Error}(),qq.version="5.12.0",qq.supportedFeatures=function(){"use strict";function e(){var e,t=!0;try{e=document.createElement("input"),e.type="file",qq(e).hide(),e.disabled&&(t=!1)}catch(e){t=!1}return t}function t(){return(qq.chrome()||qq.opera())&&void 0!==navigator.userAgent.match(/Chrome\/[2][1-9]|Chrome\/[3-9][0-9]/)}function n(){return(qq.chrome()||qq.opera())&&void 0!==navigator.userAgent.match(/Chrome\/[1][4-9]|Chrome\/[2-9][0-9]/)}function i(){if(window.XMLHttpRequest){var e=qq.createXhrInstance();return void 0!==e.withCredentials}return!1}function o(){return void 0!==window.XDomainRequest}function r(){return!!i()||o()}function a(){return void 0!==document.createElement("input").webkitdirectory}function s(){try{return!!window.localStorage&&qq.isFunction(window.localStorage.setItem)}catch(e){return!1}}function l(){var e=document.createElement("span");return("draggable"in e||"ondragstart"in e&&"ondrop"in e)&&!qq.android()&&!qq.ios()}var u,c,d,p,h,f,q,m,g,_,v,b,y,S,w;return u=e(),p=u&&qq.isXhrUploadSupported(),c=p&&!qq.androidStock(),d=p&&l(),h=d&&t(),f=p&&qq.isFileChunkingSupported(),q=p&&f&&s(),m=p&&n(),g=u&&(void 0!==window.postMessage||p),v=i(),_=o(),b=r(),y=a(),S=p&&void 0!==window.FileReader,w=function(){return!!p&&(!qq.androidStock()&&!qq.iosChrome())}(),{ajaxUploading:p,blobUploading:c,canDetermineSize:p,chunking:f,deleteFileCors:b,deleteFileCorsXdr:_,deleteFileCorsXhr:v,dialogElement:!!window.HTMLDialogElement,fileDrop:d,folderDrop:h,folderSelection:y,imagePreviews:S,imageValidation:S,itemSizeValidation:p,pause:f,progressBar:w,resume:q,scaling:S&&c,tiffPreviews:qq.safari(),unlimitedScaledImageSize:!qq.ios(),uploading:u,uploadCors:g,uploadCustomHeaders:p,uploadNonMultipart:p,uploadViaPaste:m}}(),qq.isGenericPromise=function(e){"use strict";return!!(e&&e.then&&qq.isFunction(e.then))},qq.Promise=function(){"use strict";var e,t,n=[],i=[],o=[],r=0;qq.extend(this,{then:function(o,a){return 0===r?(o&&n.push(o),a&&i.push(a)):r===-1?a&&a.apply(null,t):o&&o.apply(null,e),this},done:function(n){return 0===r?o.push(n):n.apply(null,void 0===t?e:t),this},success:function(){return r=1,e=arguments,n.length&&qq.each(n,function(t,n){n.apply(null,e)}),o.length&&qq.each(o,function(t,n){n.apply(null,e)}),this},failure:function(){return r=-1,t=arguments,i.length&&qq.each(i,function(e,n){n.apply(null,t)}),o.length&&qq.each(o,function(e,n){n.apply(null,t)}),this}})},qq.BlobProxy=function(e,t){"use strict";qq.extend(this,{referenceBlob:e,create:function(){return t(e)}})},qq.UploadButton=function(e){"use strict";function t(){var e=document.createElement("input");return e.setAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME,i),e.setAttribute("title",a.title),o.setMultiple(a.multiple,e),a.folders&&qq.supportedFeatures.folderSelection&&e.setAttribute("webkitdirectory",""),a.acceptFiles&&e.setAttribute("accept",a.acceptFiles),e.setAttribute("type","file"),e.setAttribute("name",a.name),qq(e).css({position:"absolute",right:0,top:0,fontFamily:"Arial",fontSize:qq.ie()&&!qq.ie8()?"3500px":"118px",margin:0,padding:0,cursor:"pointer",opacity:0}),!qq.ie7()&&qq(e).css({height:"100%"}),a.element.appendChild(e),r.attach(e,"change",function(){a.onChange(e)}),r.attach(e,"mouseover",function(){qq(a.element).addClass(a.hoverClass)}),r.attach(e,"mouseout",function(){qq(a.element).removeClass(a.hoverClass)}),r.attach(e,"focus",function(){qq(a.element).addClass(a.focusClass)}),r.attach(e,"blur",function(){qq(a.element).removeClass(a.focusClass)}),e}var n,i,o=this,r=new qq.DisposeSupport,a={acceptFiles:null,element:null,focusClass:"qq-upload-button-focus",folders:!1,hoverClass:"qq-upload-button-hover",ios8BrowserCrashWorkaround:!1,multiple:!1,name:"qqfile",onChange:function(e){},title:null};qq.extend(a,e),i=qq.getUniqueId(),qq(a.element).css({position:"relative",overflow:"hidden",direction:"ltr"}),qq.extend(this,{getInput:function(){return n},getButtonId:function(){return i},setMultiple:function(e,t){var n=t||this.getInput();a.ios8BrowserCrashWorkaround&&qq.ios8()&&(qq.iosChrome()||qq.iosSafariWebView())?n.setAttribute("multiple",""):e?n.setAttribute("multiple",""):n.removeAttribute("multiple")},setAcceptFiles:function(e){e!==a.acceptFiles&&n.setAttribute("accept",e)},reset:function(){n.parentNode&&qq(n).remove(),qq(a.element).removeClass(a.focusClass),n=null,n=t()}}),n=t()},qq.UploadButton.BUTTON_ID_ATTR_NAME="qq-button-id",qq.UploadData=function(e){"use strict";function t(e){if(qq.isArray(e)){var t=[];return qq.each(e,function(e,n){t.push(o[n])}),t}return o[e]}function n(e){if(qq.isArray(e)){var t=[];return qq.each(e,function(e,n){t.push(o[r[n]])}),t}return o[r[e]]}function i(e){var t=[],n=[].concat(e);return qq.each(n,function(e,n){var i=a[n];void 0!==i&&qq.each(i,function(e,n){t.push(o[n])})}),t}var o=[],r={},a={},s={},l={};qq.extend(this,{addFile:function(t){var n=t.status||qq.status.SUBMITTING,i=o.push({name:t.name,originalName:t.name,uuid:t.uuid,size:null==t.size?-1:t.size,status:n})-1;return t.batchId&&(o[i].batchId=t.batchId,void 0===l[t.batchId]&&(l[t.batchId]=[]),l[t.batchId].push(i)),t.proxyGroupId&&(o[i].proxyGroupId=t.proxyGroupId,void 0===s[t.proxyGroupId]&&(s[t.proxyGroupId]=[]),s[t.proxyGroupId].push(i)),o[i].id=i,r[t.uuid]=i,void 0===a[n]&&(a[n]=[]),a[n].push(i),e.onStatusChange(i,null,n),i},retrieve:function(e){return qq.isObject(e)&&o.length?void 0!==e.id?t(e.id):void 0!==e.uuid?n(e.uuid):e.status?i(e.status):void 0:qq.extend([],o,!0)},reset:function(){o=[],r={},a={},l={}},setStatus:function(t,n){var i=o[t].status,r=qq.indexOf(a[i],t);a[i].splice(r,1),o[t].status=n,void 0===a[n]&&(a[n]=[]),a[n].push(t),e.onStatusChange(t,i,n)},uuidChanged:function(e,t){var n=o[e].uuid;o[e].uuid=t,r[t]=e,delete r[n]},updateName:function(e,t){o[e].name=t},updateSize:function(e,t){o[e].size=t},setParentId:function(e,t){o[e].parentId=t},getIdsInProxyGroup:function(e){var t=o[e].proxyGroupId;return t?s[t]:[]},getIdsInBatch:function(e){var t=o[e].batchId;return l[t]}})},qq.status={SUBMITTING:"submitting",SUBMITTED:"submitted",REJECTED:"rejected",QUEUED:"queued",CANCELED:"canceled",PAUSED:"paused",UPLOADING:"uploading",UPLOAD_RETRYING:"retrying upload",UPLOAD_SUCCESSFUL:"upload successful",UPLOAD_FAILED:"upload failed",DELETE_FAILED:"delete failed",DELETING:"deleting",DELETED:"deleted"},function(){"use strict";qq.basePublicApi={addBlobs:function(e,t,n){this.addFiles(e,t,n)},addInitialFiles:function(e){var t=this;qq.each(e,function(e,n){t._addCannedFile(n)})},addFiles:function(e,t,n){this._maybeHandleIos8SafariWorkaround();var i=0===this._storedIds.length?qq.getUniqueId():this._currentBatchId,o=qq.bind(function(e){this._handleNewFile({blob:e,name:this._options.blobs.defaultName},i,d)},this),r=qq.bind(function(e){this._handleNewFile(e,i,d)},this),a=qq.bind(function(e){var t=qq.canvasToBlob(e);this._handleNewFile({blob:t,name:this._options.blobs.defaultName+".png"},i,d)},this),s=qq.bind(function(e){var t=e.quality&&e.quality/100,n=qq.canvasToBlob(e.canvas,e.type,t);this._handleNewFile({blob:n,name:e.name},i,d)},this),l=qq.bind(function(e){if(qq.isInput(e)&&qq.supportedFeatures.ajaxUploading){var t=Array.prototype.slice.call(e.files),n=this;qq.each(t,function(e,t){n._handleNewFile(t,i,d)})}else this._handleNewFile(e,i,d)},this),u=function(){qq.isFileList(e)&&(e=Array.prototype.slice.call(e)),e=[].concat(e)},c=this,d=[];this._currentBatchId=i,e&&(u(),qq.each(e,function(e,t){qq.isFileOrInput(t)?l(t):qq.isBlob(t)?o(t):qq.isObject(t)?t.blob&&t.name?r(t):t.canvas&&t.name&&s(t):t.tagName&&"canvas"===t.tagName.toLowerCase()?a(t):c.log(t+" is not a valid file container! Ignoring!","warn")}),this.log("Received "+d.length+" files."),this._prepareItemsForUpload(d,t,n))},cancel:function(e){this._handler.cancel(e)},cancelAll:function(){var e=[],t=this;qq.extend(e,this._storedIds),qq.each(e,function(e,n){t.cancel(n)}),this._handler.cancelAll()},clearStoredFiles:function(){this._storedIds=[]},continueUpload:function(e){var t=this._uploadData.retrieve({id:e});return!(!qq.supportedFeatures.pause||!this._options.chunking.enabled)&&(t.status===qq.status.PAUSED?(this.log(qq.format("Paused file ID {} ({}) will be continued. Not paused.",e,this.getName(e))),this._uploadFile(e),!0):(this.log(qq.format("Ignoring continue for file ID {} ({}). Not paused.",e,this.getName(e)),"error"),!1))},deleteFile:function(e){return this._onSubmitDelete(e)},doesExist:function(e){return this._handler.isValid(e)},drawThumbnail:function(e,t,n,i,o){var r,a,s=new qq.Promise;return this._imageGenerator?(r=this._thumbnailUrls[e],a={customResizeFunction:o,maxSize:n>0?n:null,scale:n>0},!i&&qq.supportedFeatures.imagePreviews&&(r=this.getFile(e)),null==r?s.failure({container:t,error:"File or URL not found."}):this._imageGenerator.generate(r,t,a).then(function(e){s.success(e)},function(e,t){s.failure({container:e,error:t||"Problem generating thumbnail"})})):s.failure({container:t,error:"Missing image generator module"}),s},getButton:function(e){return this._getButton(this._buttonIdsForFileIds[e])},getEndpoint:function(e){return this._endpointStore.get(e)},getFile:function(e){return this._handler.getFile(e)||null},getInProgress:function(){return this._uploadData.retrieve({status:[qq.status.UPLOADING,qq.status.UPLOAD_RETRYING,qq.status.QUEUED]}).length},getName:function(e){return this._uploadData.retrieve({id:e}).name},getParentId:function(e){var t=this.getUploads({id:e}),n=null;return t&&void 0!==t.parentId&&(n=t.parentId),n},getResumableFilesData:function(){return this._handler.getResumableFilesData()},getSize:function(e){return this._uploadData.retrieve({id:e}).size},getNetUploads:function(){return this._netUploaded},getRemainingAllowedItems:function(){var e=this._currentItemLimit;return e>0?e-this._netUploadedOrQueued:null},getUploads:function(e){return this._uploadData.retrieve(e)},getUuid:function(e){return this._uploadData.retrieve({id:e}).uuid},log:function(e,t){!this._options.debug||t&&"info"!==t?t&&"info"!==t&&qq.log("[Fine Uploader "+qq.version+"] "+e,t):qq.log("[Fine Uploader "+qq.version+"] "+e)},pauseUpload:function(e){var t=this._uploadData.retrieve({id:e});if(!qq.supportedFeatures.pause||!this._options.chunking.enabled)return!1;if(qq.indexOf([qq.status.UPLOADING,qq.status.UPLOAD_RETRYING],t.status)>=0){if(this._handler.pause(e))return this._uploadData.setStatus(e,qq.status.PAUSED),!0;this.log(qq.format("Unable to pause file ID {} ({}).",e,this.getName(e)),"error")}else this.log(qq.format("Ignoring pause for file ID {} ({}). Not in progress.",e,this.getName(e)),"error");return!1},reset:function(){this.log("Resetting uploader..."),this._handler.reset(),this._storedIds=[],this._autoRetries=[],this._retryTimeouts=[],this._preventRetries=[],this._thumbnailUrls=[],qq.each(this._buttons,function(e,t){t.reset()}),this._paramsStore.reset(),this._endpointStore.reset(),this._netUploadedOrQueued=0,this._netUploaded=0,this._uploadData.reset(),this._buttonIdsForFileIds=[],this._pasteHandler&&this._pasteHandler.reset(),this._options.session.refreshOnReset&&this._refreshSessionData(),this._succeededSinceLastAllComplete=[],this._failedSinceLastAllComplete=[],this._totalProgress&&this._totalProgress.reset()},retry:function(e){return this._manualRetry(e)},scaleImage:function(e,t){var n=this;return qq.Scaler.prototype.scaleImage(e,t,{log:qq.bind(n.log,n),getFile:qq.bind(n.getFile,n),uploadData:n._uploadData})},setCustomHeaders:function(e,t){this._customHeadersStore.set(e,t)},setDeleteFileCustomHeaders:function(e,t){this._deleteFileCustomHeadersStore.set(e,t)},setDeleteFileEndpoint:function(e,t){this._deleteFileEndpointStore.set(e,t)},setDeleteFileParams:function(e,t){this._deleteFileParamsStore.set(e,t)},setEndpoint:function(e,t){this._endpointStore.set(e,t)},setForm:function(e){this._updateFormSupportAndParams(e)},setItemLimit:function(e){this._currentItemLimit=e},setName:function(e,t){this._uploadData.updateName(e,t)},setParams:function(e,t){this._paramsStore.set(e,t)},setUuid:function(e,t){return this._uploadData.uuidChanged(e,t)},uploadStoredFiles:function(){0===this._storedIds.length?this._itemError("noFilesError"):this._uploadStoredFiles()}},qq.basePrivateApi={_addCannedFile:function(e){var t=this._uploadData.addFile({uuid:e.uuid,name:e.name,size:e.size,status:qq.status.UPLOAD_SUCCESSFUL});return e.deleteFileEndpoint&&this.setDeleteFileEndpoint(e.deleteFileEndpoint,t),e.deleteFileParams&&this.setDeleteFileParams(e.deleteFileParams,t),e.thumbnailUrl&&(this._thumbnailUrls[t]=e.thumbnailUrl),this._netUploaded++,this._netUploadedOrQueued++,t},_annotateWithButtonId:function(e,t){qq.isFile(e)&&(e.qqButtonId=this._getButtonId(t))},_batchError:function(e){this._options.callbacks.onError(null,null,e,void 0)},_createDeleteHandler:function(){var e=this;return new qq.DeleteFileAjaxRequester({method:this._options.deleteFile.method.toUpperCase(),maxConnections:this._options.maxConnections,uuidParamName:this._options.request.uuidName,customHeaders:this._deleteFileCustomHeadersStore,paramsStore:this._deleteFileParamsStore,endpointStore:this._deleteFileEndpointStore,cors:this._options.cors,log:qq.bind(e.log,e),onDelete:function(t){e._onDelete(t),e._options.callbacks.onDelete(t)},onDeleteComplete:function(t,n,i){e._onDeleteComplete(t,n,i),e._options.callbacks.onDeleteComplete(t,n,i)}})},_createPasteHandler:function(){var e=this;return new qq.PasteSupport({targetElement:this._options.paste.targetElement,callbacks:{log:qq.bind(e.log,e),pasteReceived:function(t){e._handleCheckedCallback({name:"onPasteReceived",callback:qq.bind(e._options.callbacks.onPasteReceived,e,t),onSuccess:qq.bind(e._handlePasteSuccess,e,t),identifier:"pasted image"})}}})},_createStore:function(e,t){var n={},i=e,o={},r=t,a=function(e){return qq.isObject(e)?qq.extend({},e):e},s=function(){return qq.isFunction(r)?r():r},l=function(e,t){r&&qq.isObject(t)&&qq.extend(t,s()),o[e]&&qq.extend(t,o[e])};return{set:function(e,t){null==t?(n={},i=a(e)):n[t]=a(e)},get:function(e){var t;return t=null!=e&&n[e]?n[e]:a(i),l(e,t),a(t)},addReadOnly:function(e,t){qq.isObject(n)&&(null===e?qq.isFunction(t)?r=t:(r=r||{},qq.extend(r,t)):(o[e]=o[e]||{},qq.extend(o[e],t)))},remove:function(e){return delete n[e]},reset:function(){n={},o={},i=e}}},_createUploadDataTracker:function(){var e=this;return new qq.UploadData({getName:function(t){return e.getName(t)},getUuid:function(t){return e.getUuid(t)},getSize:function(t){return e.getSize(t)},onStatusChange:function(t,n,i){e._onUploadStatusChange(t,n,i),e._options.callbacks.onStatusChange(t,n,i),e._maybeAllComplete(t,i),e._totalProgress&&setTimeout(function(){e._totalProgress.onStatusChange(t,n,i)},0)}})},_createUploadButton:function(e){function t(){return!!qq.supportedFeatures.ajaxUploading&&(!(i._options.workarounds.iosEmptyVideos&&qq.ios()&&!qq.ios6()&&i._isAllowedExtension(r,".mov"))&&(void 0===e.multiple?i._options.multiple:e.multiple))}var n,i=this,o=e.accept||this._options.validation.acceptFiles,r=e.allowedExtensions||this._options.validation.allowedExtensions;return n=new qq.UploadButton({acceptFiles:o,element:e.element,focusClass:this._options.classes.buttonFocus,folders:e.folders,hoverClass:this._options.classes.buttonHover,ios8BrowserCrashWorkaround:this._options.workarounds.ios8BrowserCrash,multiple:t(),name:this._options.request.inputName,onChange:function(e){i._onInputChange(e)},title:null==e.title?this._options.text.fileInputTitle:e.title}),this._disposeSupport.addDisposer(function(){n.dispose()}),i._buttons.push(n),n},_createUploadHandler:function(e,t){var n=this,i={},o={debug:this._options.debug,maxConnections:this._options.maxConnections,cors:this._options.cors,paramsStore:this._paramsStore,endpointStore:this._endpointStore,chunking:this._options.chunking,resume:this._options.resume,blobs:this._options.blobs,log:qq.bind(n.log,n),preventRetryParam:this._options.retry.preventRetryResponseProperty,onProgress:function(e,t,o,r){o<0||r<0||(i[e]?i[e].loaded===o&&i[e].total===r||(n._onProgress(e,t,o,r),n._options.callbacks.onProgress(e,t,o,r)):(n._onProgress(e,t,o,r),n._options.callbacks.onProgress(e,t,o,r)),i[e]={loaded:o,total:r})},onComplete:function(e,t,o,r){delete i[e];var a,s=n.getUploads({id:e}).status;s!==qq.status.UPLOAD_SUCCESSFUL&&s!==qq.status.UPLOAD_FAILED&&(a=n._onComplete(e,t,o,r),a instanceof qq.Promise?a.done(function(){n._options.callbacks.onComplete(e,t,o,r)}):n._options.callbacks.onComplete(e,t,o,r))},onCancel:function(e,t,i){var o=new qq.Promise;return n._handleCheckedCallback({name:"onCancel",callback:qq.bind(n._options.callbacks.onCancel,n,e,t),onFailure:o.failure,onSuccess:function(){i.then(function(){n._onCancel(e,t)}),o.success()},identifier:e}),o},onUploadPrep:qq.bind(this._onUploadPrep,this),onUpload:function(e,t){n._onUpload(e,t),n._options.callbacks.onUpload(e,t)},onUploadChunk:function(e,t,i){n._onUploadChunk(e,i),n._options.callbacks.onUploadChunk(e,t,i)},onUploadChunkSuccess:function(e,t,i,o){n._options.callbacks.onUploadChunkSuccess.apply(n,arguments)},onResume:function(e,t,i){return n._options.callbacks.onResume(e,t,i)},onAutoRetry:function(e,t,i,o){return n._onAutoRetry.apply(n,arguments)},onUuidChanged:function(e,t){n.log("Server requested UUID change from '"+n.getUuid(e)+"' to '"+t+"'"),n.setUuid(e,t)},getName:qq.bind(n.getName,n),getUuid:qq.bind(n.getUuid,n),getSize:qq.bind(n.getSize,n),setSize:qq.bind(n._setSize,n),getDataByUuid:function(e){return n.getUploads({uuid:e})},isQueued:function(e){var t=n.getUploads({id:e}).status;return t===qq.status.QUEUED||t===qq.status.SUBMITTED||t===qq.status.UPLOAD_RETRYING||t===qq.status.PAUSED},getIdsInProxyGroup:n._uploadData.getIdsInProxyGroup,getIdsInBatch:n._uploadData.getIdsInBatch};return qq.each(this._options.request,function(e,t){o[e]=t}),o.customHeaders=this._customHeadersStore,e&&qq.each(e,function(e,t){o[e]=t}),new qq.UploadHandlerController(o,t)},_fileOrBlobRejected:function(e){this._netUploadedOrQueued--,this._uploadData.setStatus(e,qq.status.REJECTED)},_formatSize:function(e){if(0===e)return e+this._options.text.sizeSymbols[0];var t=-1;do e/=1e3,t++;while(e>999);
-return Math.max(e,.1).toFixed(1)+this._options.text.sizeSymbols[t]},_generateExtraButtonSpecs:function(){var e=this;this._extraButtonSpecs={},qq.each(this._options.extraButtons,function(t,n){var i=n.multiple,o=qq.extend({},e._options.validation,!0),r=qq.extend({},n);void 0===i&&(i=e._options.multiple),r.validation&&qq.extend(o,n.validation,!0),qq.extend(r,{multiple:i,validation:o},!0),e._initExtraButton(r)})},_getButton:function(e){var t=this._extraButtonSpecs[e];return t?t.element:e===this._defaultButtonId?this._options.button:void 0},_getButtonId:function(e){var t,n,i=e;if(i instanceof qq.BlobProxy&&(i=i.referenceBlob),i&&!qq.isBlob(i)){if(qq.isFile(i))return i.qqButtonId;if("input"===i.tagName.toLowerCase()&&"file"===i.type.toLowerCase())return i.getAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME);if(t=i.getElementsByTagName("input"),qq.each(t,function(e,t){if("file"===t.getAttribute("type"))return n=t,!1}),n)return n.getAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME)}},_getNotFinished:function(){return this._uploadData.retrieve({status:[qq.status.UPLOADING,qq.status.UPLOAD_RETRYING,qq.status.QUEUED,qq.status.SUBMITTING,qq.status.SUBMITTED,qq.status.PAUSED]}).length},_getValidationBase:function(e){var t=this._extraButtonSpecs[e];return t?t.validation:this._options.validation},_getValidationDescriptor:function(e){return e.file instanceof qq.BlobProxy?{name:qq.getFilename(e.file.referenceBlob),size:e.file.referenceBlob.size}:{name:this.getUploads({id:e.id}).name,size:this.getUploads({id:e.id}).size}},_getValidationDescriptors:function(e){var t=this,n=[];return qq.each(e,function(e,i){n.push(t._getValidationDescriptor(i))}),n},_handleCameraAccess:function(){if(this._options.camera.ios&&qq.ios()){var e="image/*;capture=camera",t=this._options.camera.button,n=t?this._getButtonId(t):this._defaultButtonId,i=this._options;n&&n!==this._defaultButtonId&&(i=this._extraButtonSpecs[n]),i.multiple=!1,null===i.validation.acceptFiles?i.validation.acceptFiles=e:i.validation.acceptFiles+=","+e,qq.each(this._buttons,function(e,t){if(t.getButtonId()===n)return t.setMultiple(i.multiple),t.setAcceptFiles(i.acceptFiles),!1})}},_handleCheckedCallback:function(e){var t=this,n=e.callback();return qq.isGenericPromise(n)?(this.log(e.name+" - waiting for "+e.name+" promise to be fulfilled for "+e.identifier),n.then(function(n){t.log(e.name+" promise success for "+e.identifier),e.onSuccess(n)},function(){e.onFailure?(t.log(e.name+" promise failure for "+e.identifier),e.onFailure()):t.log(e.name+" promise failure for "+e.identifier)})):(n!==!1?e.onSuccess(n):e.onFailure?(this.log(e.name+" - return value was 'false' for "+e.identifier+". Invoking failure callback."),e.onFailure()):this.log(e.name+" - return value was 'false' for "+e.identifier+". Will not proceed."),n)},_handleNewFile:function(e,t,n){var i=this,o=qq.getUniqueId(),r=-1,a=qq.getFilename(e),s=e.blob||e,l=this._customNewFileHandler?this._customNewFileHandler:qq.bind(i._handleNewFileGeneric,i);!qq.isInput(s)&&s.size>=0&&(r=s.size),l(s,a,o,r,n,t,this._options.request.uuidName,{uploadData:i._uploadData,paramsStore:i._paramsStore,addFileToHandler:function(e,t){i._handler.add(e,t),i._netUploadedOrQueued++,i._trackButton(e)}})},_handleNewFileGeneric:function(e,t,n,i,o,r){var a=this._uploadData.addFile({uuid:n,name:t,size:i,batchId:r});this._handler.add(a,e),this._trackButton(a),this._netUploadedOrQueued++,o.push({id:a,file:e})},_handlePasteSuccess:function(e,t){var n=e.type.split("/")[1],i=t;null==i&&(i=this._options.paste.defaultName),i+="."+n,this.addFiles({name:i,blob:e})},_initExtraButton:function(e){var t=this._createUploadButton({accept:e.validation.acceptFiles,allowedExtensions:e.validation.allowedExtensions,element:e.element,folders:e.folders,multiple:e.multiple,title:e.fileInputTitle});this._extraButtonSpecs[t.getButtonId()]=e},_initFormSupportAndParams:function(){this._formSupport=qq.FormSupport&&new qq.FormSupport(this._options.form,qq.bind(this.uploadStoredFiles,this),qq.bind(this.log,this)),this._formSupport&&this._formSupport.attachedToForm?(this._paramsStore=this._createStore(this._options.request.params,this._formSupport.getFormInputsAsObject),this._options.autoUpload=this._formSupport.newAutoUpload,this._formSupport.newEndpoint&&(this._options.request.endpoint=this._formSupport.newEndpoint)):this._paramsStore=this._createStore(this._options.request.params)},_isDeletePossible:function(){return!(!qq.DeleteFileAjaxRequester||!this._options.deleteFile.enabled)&&(!this._options.cors.expected||(!!qq.supportedFeatures.deleteFileCorsXhr||!(!qq.supportedFeatures.deleteFileCorsXdr||!this._options.cors.allowXdr)))},_isAllowedExtension:function(e,t){var n=!1;return!e.length||(qq.each(e,function(e,i){if(qq.isString(i)){var o=new RegExp("\\."+i+"$","i");if(null!=t.match(o))return n=!0,!1}}),n)},_itemError:function(e,t,n){function i(e,t){a=a.replace(e,t)}var o,r,a=this._options.messages[e],s=[],l=[].concat(t),u=l[0],c=this._getButtonId(n),d=this._getValidationBase(c);return qq.each(d.allowedExtensions,function(e,t){qq.isString(t)&&s.push(t)}),o=s.join(", ").toLowerCase(),i("{file}",this._options.formatFileName(u)),i("{extensions}",o),i("{sizeLimit}",this._formatSize(d.sizeLimit)),i("{minSizeLimit}",this._formatSize(d.minSizeLimit)),r=a.match(/(\{\w+\})/g),null!==r&&qq.each(r,function(e,t){i(t,l[e])}),this._options.callbacks.onError(null,u,a,void 0),a},_manualRetry:function(e,t){if(this._onBeforeManualRetry(e))return this._netUploadedOrQueued++,this._uploadData.setStatus(e,qq.status.UPLOAD_RETRYING),t?t(e):this._handler.retry(e),!0},_maybeAllComplete:function(e,t){var n=this,i=this._getNotFinished();t===qq.status.UPLOAD_SUCCESSFUL?this._succeededSinceLastAllComplete.push(e):t===qq.status.UPLOAD_FAILED&&this._failedSinceLastAllComplete.push(e),0===i&&(this._succeededSinceLastAllComplete.length||this._failedSinceLastAllComplete.length)&&setTimeout(function(){n._onAllComplete(n._succeededSinceLastAllComplete,n._failedSinceLastAllComplete)},0)},_maybeHandleIos8SafariWorkaround:function(){var e=this;if(this._options.workarounds.ios8SafariUploads&&qq.ios800()&&qq.iosSafari())throw setTimeout(function(){window.alert(e._options.messages.unsupportedBrowserIos8Safari)},0),new qq.Error(this._options.messages.unsupportedBrowserIos8Safari)},_maybeParseAndSendUploadError:function(e,t,n,i){if(!n.success)if(i&&200!==i.status&&!n.error)this._options.callbacks.onError(e,t,"XHR returned response code "+i.status,i);else{var o=n.error?n.error:this._options.text.defaultResponseError;this._options.callbacks.onError(e,t,o,i)}},_maybeProcessNextItemAfterOnValidateCallback:function(e,t,n,i,o){var r=this;if(t.length>n)if(e||!this._options.validation.stopOnFirstInvalidFile)setTimeout(function(){var e=r._getValidationDescriptor(t[n]),a=r._getButtonId(t[n].file),s=r._getButton(a);r._handleCheckedCallback({name:"onValidate",callback:qq.bind(r._options.callbacks.onValidate,r,e,s),onSuccess:qq.bind(r._onValidateCallbackSuccess,r,t,n,i,o),onFailure:qq.bind(r._onValidateCallbackFailure,r,t,n,i,o),identifier:"Item '"+e.name+"', size: "+e.size})},0);else if(!e)for(;n0&&this._netUploadedOrQueued+1>n?(this._itemError("retryFailTooManyItems"),!1):(this.log("Retrying upload for '"+t+"' (id: "+e+")..."),!0))):(this.log("'"+e+"' is not a valid file ID","error"),!1)},_onCancel:function(e,t){this._netUploadedOrQueued--,clearTimeout(this._retryTimeouts[e]);var n=qq.indexOf(this._storedIds,e);!this._options.autoUpload&&n>=0&&this._storedIds.splice(n,1),this._uploadData.setStatus(e,qq.status.CANCELED)},_onComplete:function(e,t,n,i){return n.success?(n.thumbnailUrl&&(this._thumbnailUrls[e]=n.thumbnailUrl),this._netUploaded++,this._uploadData.setStatus(e,qq.status.UPLOAD_SUCCESSFUL)):(this._netUploadedOrQueued--,this._uploadData.setStatus(e,qq.status.UPLOAD_FAILED),n[this._options.retry.preventRetryResponseProperty]===!0&&(this._preventRetries[e]=!0)),this._maybeParseAndSendUploadError(e,t,n,i),!!n.success},_onDelete:function(e){this._uploadData.setStatus(e,qq.status.DELETING)},_onDeleteComplete:function(e,t,n){var i=this.getName(e);n?(this._uploadData.setStatus(e,qq.status.DELETE_FAILED),this.log("Delete request for '"+i+"' has failed.","error"),void 0===t.withCredentials?this._options.callbacks.onError(e,i,"Delete request failed",t):this._options.callbacks.onError(e,i,"Delete request failed with response code "+t.status,t)):(this._netUploadedOrQueued--,this._netUploaded--,this._handler.expunge(e),this._uploadData.setStatus(e,qq.status.DELETED),this.log("Delete request for '"+i+"' has succeeded."))},_onInputChange:function(e){var t;if(qq.supportedFeatures.ajaxUploading){for(t=0;t0&&this.addFiles(e);qq.each(this._buttons,function(e,t){t.reset()})},_onProgress:function(e,t,n,i){this._totalProgress&&this._totalProgress.onIndividualProgress(e,n,i)},_onSubmit:function(e,t){},_onSubmitCallbackSuccess:function(e,t){this._onSubmit.apply(this,arguments),this._uploadData.setStatus(e,qq.status.SUBMITTED),this._onSubmitted.apply(this,arguments),this._options.autoUpload?(this._options.callbacks.onSubmitted.apply(this,arguments),this._uploadFile(e)):(this._storeForLater(e),this._options.callbacks.onSubmitted.apply(this,arguments))},_onSubmitDelete:function(e,t,n){var i,o=this.getUuid(e);return t&&(i=qq.bind(t,this,e,o,n)),this._isDeletePossible()?(this._handleCheckedCallback({name:"onSubmitDelete",callback:qq.bind(this._options.callbacks.onSubmitDelete,this,e),onSuccess:i||qq.bind(this._deleteHandler.sendDelete,this,e,o,n),identifier:e}),!0):(this.log("Delete request ignored for ID "+e+", delete feature is disabled or request not possible due to CORS on a user agent that does not support pre-flighting.","warn"),!1)},_onSubmitted:function(e){},_onTotalProgress:function(e,t){this._options.callbacks.onTotalProgress(e,t)},_onUploadPrep:function(e){},_onUpload:function(e,t){this._uploadData.setStatus(e,qq.status.UPLOADING)},_onUploadChunk:function(e,t){},_onUploadStatusChange:function(e,t,n){n===qq.status.PAUSED&&clearTimeout(this._retryTimeouts[e])},_onValidateBatchCallbackFailure:function(e){var t=this;qq.each(e,function(e,n){t._fileOrBlobRejected(n.id)})},_onValidateBatchCallbackSuccess:function(e,t,n,i,o){var r,a=this._currentItemLimit,s=this._netUploadedOrQueued;0===a||s<=a?t.length>0?this._handleCheckedCallback({name:"onValidate",callback:qq.bind(this._options.callbacks.onValidate,this,e[0],o),onSuccess:qq.bind(this._onValidateCallbackSuccess,this,t,0,n,i),onFailure:qq.bind(this._onValidateCallbackFailure,this,t,0,n,i),identifier:"Item '"+t[0].file.name+"', size: "+t[0].file.size}):this._itemError("noFilesError"):(this._onValidateBatchCallbackFailure(t),r=this._options.messages.tooManyItemsError.replace(/\{netItems\}/g,s).replace(/\{itemLimit\}/g,a),this._batchError(r))},_onValidateCallbackFailure:function(e,t,n,i){var o=t+1;this._fileOrBlobRejected(e[t].id,e[t].file.name),this._maybeProcessNextItemAfterOnValidateCallback(!1,e,o,n,i)},_onValidateCallbackSuccess:function(e,t,n,i){var o=this,r=t+1,a=this._getValidationDescriptor(e[t]);this._validateFileOrBlobData(e[t],a).then(function(){o._upload(e[t].id,n,i),o._maybeProcessNextItemAfterOnValidateCallback(!0,e,r,n,i)},function(){o._maybeProcessNextItemAfterOnValidateCallback(!1,e,r,n,i)})},_prepareItemsForUpload:function(e,t,n){if(0===e.length)return void this._itemError("noFilesError");var i=this._getValidationDescriptors(e),o=this._getButtonId(e[0].file),r=this._getButton(o);this._handleCheckedCallback({name:"onValidateBatch",callback:qq.bind(this._options.callbacks.onValidateBatch,this,i,r),onSuccess:qq.bind(this._onValidateBatchCallbackSuccess,this,i,e,t,n,r),onFailure:qq.bind(this._onValidateBatchCallbackFailure,this,e),identifier:"batch validation"})},_preventLeaveInProgress:function(){var e=this;this._disposeSupport.attach(window,"beforeunload",function(t){if(e.getInProgress())return t=t||window.event,t.returnValue=e._options.messages.onLeave,e._options.messages.onLeave})},_refreshSessionData:function(){var e=this,t=this._options.session;qq.Session&&null!=this._options.session.endpoint&&(this._session||(qq.extend(t,{cors:this._options.cors}),t.log=qq.bind(this.log,this),t.addFileRecord=qq.bind(this._addCannedFile,this),this._session=new qq.Session(t)),setTimeout(function(){e._session.refresh().then(function(t,n){e._sessionRequestComplete(),e._options.callbacks.onSessionRequestComplete(t,!0,n)},function(t,n){e._options.callbacks.onSessionRequestComplete(t,!1,n)})},0))},_sessionRequestComplete:function(){},_setSize:function(e,t){this._uploadData.updateSize(e,t),this._totalProgress&&this._totalProgress.onNewSize(e)},_shouldAutoRetry:function(e,t,n){var i=this._uploadData.retrieve({id:e});return!!(!this._preventRetries[e]&&this._options.retry.enableAuto&&i.status!==qq.status.PAUSED&&(void 0===this._autoRetries[e]&&(this._autoRetries[e]=0),this._autoRetries[e]0&&s.sizeLimit&&r>s.sizeLimit?(this._itemError("sizeError",o,i),l.failure()):r>0&&r=0}function n(e){var t=!1;return qq.each(t,function(e,n){if(qq.indexOf(["Accept","Accept-Language","Content-Language","Content-Type"],n)<0)return t=!0,!1}),t}function i(e){return S.cors.expected&&void 0===e.withCredentials}function o(){var e;return(window.XMLHttpRequest||window.ActiveXObject)&&(e=qq.createXhrInstance(),void 0===e.withCredentials&&(e=new XDomainRequest,e.onload=function(){},e.onerror=function(){},e.ontimeout=function(){},e.onprogress=function(){})),e}function r(e,t){var n=y[e].xhr;return n||(n=t?t:S.cors.expected?o():qq.createXhrInstance(),y[e].xhr=n),n}function a(e){var t,n=qq.indexOf(b,e),i=S.maxConnections;delete y[e],b.splice(n,1),b.length>=i&&n=0?o.send(qq.obj2url(s,"")):s&&S.contentType&&S.contentType.toLowerCase().indexOf("application/json")>=0?o.send(JSON.stringify(s)):o.send(s),o}function c(e,t,n){var i=S.endpointStore.get(e),o=y[e].addToPath;return void 0!=o&&(i+="/"+o),v&&t&&(i=qq.obj2url(t,i)),n&&(i=qq.obj2url(n,i)),i}function d(e){return function(){4===r(e).readyState&&s(e)}}function p(e){var t=S.onProgress;t&&(r(e).upload.onprogress=function(n){n.lengthComputable&&t(e,n.loaded,n.total)})}function h(e){return function(){s(e)}}function f(e){return function(){s(e,!0)}}function q(e){var o=r(e),a=S.customHeaders,s=y[e].additionalHeaders||{},l=S.method,u={};i(o)||(S.acceptHeader&&o.setRequestHeader("Accept",S.acceptHeader),S.allowXRequestedWithAndCacheControl&&(S.cors.expected&&t()&&!n(a)||(o.setRequestHeader("X-Requested-With","XMLHttpRequest"),o.setRequestHeader("Cache-Control","no-cache"))),!S.contentType||"POST"!==l&&"PUT"!==l||o.setRequestHeader("Content-Type",S.contentType),qq.extend(u,qq.isFunction(a)?a(e):a),qq.extend(u,s),qq.each(u,function(e,t){o.setRequestHeader(e,t)}))}function m(e){return qq.indexOf(S.successfulResponseCodes[S.method],e)>=0}function g(e,t,n,i,o,r,a){y[e]={addToPath:n,additionalParams:i,additionalQueryParams:o,additionalHeaders:r,payload:a};var s=b.push(e);if(s<=S.maxConnections)return u(e,t)}var _,v,b=[],y={},S={acceptHeader:null,validMethods:["PATCH","POST","PUT"],method:"POST",contentType:"application/x-www-form-urlencoded",maxConnections:3,customHeaders:{},endpointStore:{},paramsStore:{},mandatedParams:{},allowXRequestedWithAndCacheControl:!0,successfulResponseCodes:{DELETE:[200,202,204],PATCH:[200,201,202,203,204],POST:[200,201,202,203,204],PUT:[200,201,202,203,204],GET:[200]},cors:{expected:!1,sendCredentials:!1},log:function(e,t){},onSend:function(e){},onComplete:function(e,t,n){},onProgress:null};if(qq.extend(S,e),_=S.log,qq.indexOf(S.validMethods,S.method)<0)throw new Error("'"+S.method+"' is not a supported method for this type of request!");v="GET"===S.method||"DELETE"===S.method,qq.extend(this,{initTransport:function(e){var t,n,i,o,r,a;return{withPath:function(e){return t=e,this},withParams:function(e){return n=e,this},withQueryParams:function(e){return a=e,this},withHeaders:function(e){return i=e,this},withPayload:function(e){return o=e,this},withCacheBuster:function(){return r=!0,this},send:function(s){return r&&qq.indexOf(["GET","DELETE"],S.method)>=0&&(n.qqtimestamp=(new Date).getTime()),g(e,s,t,n,a,i,o)}}},canceled:function(e){a(e)}})},qq.UploadHandler=function(e){"use strict";var t=e.proxy,n={},i=t.onCancel,o=t.getName;qq.extend(this,{add:function(e,t){n[e]=t,n[e].temp={}},cancel:function(e){var t=this,r=new qq.Promise,a=i(e,o(e),r);a.then(function(){t.isValid(e)&&(n[e].canceled=!0,t.expunge(e)),r.success()})},expunge:function(e){delete n[e]},getThirdPartyFileId:function(e){return n[e].key},isValid:function(e){return void 0!==n[e]},reset:function(){n={}},_getFileState:function(e){return n[e]},_setThirdPartyFileId:function(e,t){n[e].key=t},_wasCanceled:function(e){return!!n[e].canceled}})},qq.UploadHandlerController=function(e,t){"use strict";var n,i,o,r=this,a=!1,s=!1,l={paramsStore:{},maxConnections:3,chunking:{enabled:!1,multiple:{enabled:!1}},log:function(e,t){},onProgress:function(e,t,n,i){},onComplete:function(e,t,n,i){},onCancel:function(e,t){},onUploadPrep:function(e){},onUpload:function(e,t){},onUploadChunk:function(e,t,n){},onUploadChunkSuccess:function(e,t,n,i){},onAutoRetry:function(e,t,n,i){},onResume:function(e,t,n){},onUuidChanged:function(e,t){},getName:function(e){},setSize:function(e,t){},isQueued:function(e){},getIdsInProxyGroup:function(e){},getIdsInBatch:function(e){}},u={done:function(e,t,n,i){var r=o._getChunkData(e,t);o._getFileState(e).attemptingResume=!1,delete o._getFileState(e).temp.chunkProgress[t],o._getFileState(e).loaded+=r.size,l.onUploadChunkSuccess(e,o._getChunkDataForCallback(r),n,i)},finalize:function(e){var t=l.getSize(e),n=l.getName(e);i("All chunks have been uploaded for "+e+" - finalizing...."),o.finalizeChunks(e).then(function(r,a){i("Finalize successful for "+e);var s=p.normalizeResponse(r,!0);l.onProgress(e,n,t,t),o._maybeDeletePersistedChunkData(e),p.cleanup(e,s,a)},function(t,o){var r=p.normalizeResponse(t,!1);i("Problem finalizing chunks for file ID "+e+" - "+r.error,"error"),r.reset&&u.reset(e),l.onAutoRetry(e,n,r,o)||p.cleanup(e,r,o)})},handleFailure:function(e,t,n,r){var a=l.getName(t);i("Chunked upload request failed for "+t+", chunk "+e),o.clearCachedChunk(t,e);var d,h=p.normalizeResponse(n,!1);h.reset?u.reset(t):(d=qq.indexOf(o._getFileState(t).chunking.inProgress,e),d>=0&&(o._getFileState(t).chunking.inProgress.splice(d,1),o._getFileState(t).chunking.remaining.unshift(e))),o._getFileState(t).temp.ignoreFailure||(s&&(o._getFileState(t).temp.ignoreFailure=!0,i(qq.format("Going to attempt to abort these chunks: {}. These are currently in-progress: {}.",JSON.stringify(Object.keys(o._getXhrs(t))),JSON.stringify(o._getFileState(t).chunking.inProgress))),qq.each(o._getXhrs(t),function(e,n){i(qq.format("Attempting to abort file {}.{}. XHR readyState {}. ",t,e,n.readyState)),n.abort(),n._cancelled=!0}),o.moveInProgressToRemaining(t),c.free(t,!0)),l.onAutoRetry(t,a,h,r)||p.cleanup(t,h,r))},hasMoreParts:function(e){return!!o._getFileState(e).chunking.remaining.length},nextPart:function(e){var t=o._getFileState(e).chunking.remaining.shift();return t>=o._getTotalChunks(e)&&(t=null),t},reset:function(e){i("Server or callback has ordered chunking effort to be restarted on next attempt for item ID "+e,"error"),o._maybeDeletePersistedChunkData(e),o.reevaluateChunking(e),o._getFileState(e).loaded=0},sendNext:function(e){var t=l.getSize(e),n=l.getName(e),r=u.nextPart(e),a=o._getChunkData(e,r),d=o._getFileState(e).attemptingResume,h=o._getFileState(e).chunking.inProgress||[];null==o._getFileState(e).loaded&&(o._getFileState(e).loaded=0),d&&l.onResume(e,n,a)===!1&&(u.reset(e),r=u.nextPart(e),a=o._getChunkData(e,r),d=!1),null==r&&0===h.length?u.finalize(e):(i(qq.format("Sending chunked upload request for item {}.{}, bytes {}-{} of {}.",e,r,a.start+1,a.end,t)),l.onUploadChunk(e,n,o._getChunkDataForCallback(a)),h.push(r),o._getFileState(e).chunking.inProgress=h,s&&c.open(e,r),s&&c.available()&&o._getFileState(e).chunking.remaining.length&&u.sendNext(e),0===a.blob.size?(i(qq.format("Chunk {} for file {} will not be uploaded, zero sized chunk.",r,e),"error"),u.handleFailure(r,e,"File is no longer available",null)):o.uploadChunk(e,r,d).then(function(t,n){i("Chunked upload request succeeded for "+e+", chunk "+r),o.clearCachedChunk(e,r);var a=o._getFileState(e).chunking.inProgress||[],s=p.normalizeResponse(t,!0),l=qq.indexOf(a,r);i(qq.format("Chunk {} for file {} uploaded successfully.",r,e)),u.done(e,r,s,n),l>=0&&a.splice(l,1),o._maybePersistChunkedState(e),u.hasMoreParts(e)||0!==a.length?u.hasMoreParts(e)?u.sendNext(e):i(qq.format("File ID {} has no more chunks to send and these chunk indexes are still marked as in-progress: {}",e,JSON.stringify(a))):u.finalize(e)},function(t,n){u.handleFailure(r,e,t,n)}).done(function(){o.clearXhr(e,r)}))}},c={_open:[],_openChunks:{},_waiting:[],available:function(){var e=l.maxConnections,t=0,n=0;return qq.each(c._openChunks,function(e,i){t++,n+=i.length}),e-(c._open.length-t+n)},free:function(e,t){var n,r=!t,a=qq.indexOf(c._waiting,e),s=qq.indexOf(c._open,e);delete c._openChunks[e],p.getProxyOrBlob(e)instanceof qq.BlobProxy&&(i("Generated blob upload has ended for "+e+", disposing generated blob."),delete o._getFileState(e).file),a>=0?c._waiting.splice(a,1):r&&s>=0&&(c._open.splice(s,1),n=c._waiting.shift(),n>=0&&(c._open.push(n),p.start(n)))},getWaitingOrConnected:function(){var e=[];return qq.each(c._openChunks,function(t,n){n&&n.length&&e.push(parseInt(t))}),qq.each(c._open,function(t,n){c._openChunks[n]||e.push(parseInt(n))}),e=e.concat(c._waiting)},isUsingConnection:function(e){return qq.indexOf(c._open,e)>=0;
-},open:function(e,t){return null==t&&c._waiting.push(e),!!c.available()&&(null==t?(c._waiting.pop(),c._open.push(e)):!function(){var n=c._openChunks[e]||[];n.push(t),c._openChunks[e]=n}(),!0)},reset:function(){c._waiting=[],c._open=[]}},d={send:function(e,t){o._getFileState(e).loaded=0,i("Sending simple upload request for "+e),o.uploadFile(e).then(function(n,o){i("Simple upload request succeeded for "+e);var r=p.normalizeResponse(n,!0),a=l.getSize(e);l.onProgress(e,t,a,a),p.maybeNewUuid(e,r),p.cleanup(e,r,o)},function(n,o){i("Simple upload request failed for "+e);var r=p.normalizeResponse(n,!1);l.onAutoRetry(e,t,r,o)||p.cleanup(e,r,o)})}},p={cancel:function(e){i("Cancelling "+e),l.paramsStore.remove(e),c.free(e)},cleanup:function(e,t,n){var i=l.getName(e);l.onComplete(e,i,t,n),o._getFileState(e)&&o._clearXhrs&&o._clearXhrs(e),c.free(e)},getProxyOrBlob:function(e){return o.getProxy&&o.getProxy(e)||o.getFile&&o.getFile(e)},initHandler:function(){var e=t?qq[t]:qq.traditional,n=qq.supportedFeatures.ajaxUploading?"Xhr":"Form";o=new e[n+"UploadHandler"](l,{getDataByUuid:l.getDataByUuid,getName:l.getName,getSize:l.getSize,getUuid:l.getUuid,log:i,onCancel:l.onCancel,onProgress:l.onProgress,onUuidChanged:l.onUuidChanged}),o._removeExpiredChunkingRecords&&o._removeExpiredChunkingRecords()},isDeferredEligibleForUpload:function(e){return l.isQueued(e)},maybeDefer:function(e,t){return t&&!o.getFile(e)&&t instanceof qq.BlobProxy?(l.onUploadPrep(e),i("Attempting to generate a blob on-demand for "+e),t.create().then(function(t){i("Generated an on-demand blob for "+e),o.updateBlob(e,t),l.setSize(e,t.size),o.reevaluateChunking(e),p.maybeSendDeferredFiles(e)},function(t){var o={};t&&(o.error=t),i(qq.format("Failed to generate blob for ID {}. Error message: {}.",e,t),"error"),l.onComplete(e,l.getName(e),qq.extend(o,n),null),p.maybeSendDeferredFiles(e),c.free(e)}),!1):p.maybeSendDeferredFiles(e)},maybeSendDeferredFiles:function(e){var t=l.getIdsInProxyGroup(e),n=!1;return t&&t.length?(i("Maybe ready to upload proxy group file "+e),qq.each(t,function(t,i){if(p.isDeferredEligibleForUpload(i)&&o.getFile(i))n=i===e,p.now(i);else if(p.isDeferredEligibleForUpload(i))return!1})):(n=!0,p.now(e)),n},maybeNewUuid:function(e,t){void 0!==t.newUuid&&l.onUuidChanged(e,t.newUuid)},normalizeResponse:function(e,t){var n=e;return qq.isObject(e)||(n={},qq.isString(e)&&!t&&(n.error=e)),n.success=t,n},now:function(e){var t=l.getName(e);if(!r.isValid(e))throw new qq.Error(e+" is not a valid file ID to upload!");l.onUpload(e,t),a&&o._shouldChunkThisFile(e)?u.sendNext(e):d.send(e,t)},start:function(e){var t=p.getProxyOrBlob(e);return t?p.maybeDefer(e,t):(p.now(e),!0)}};qq.extend(this,{add:function(e,t){o.add.apply(this,arguments)},upload:function(e){return!!c.open(e)&&p.start(e)},retry:function(e){return s&&(o._getFileState(e).temp.ignoreFailure=!1),c.isUsingConnection(e)?p.start(e):r.upload(e)},cancel:function(e){var t=o.cancel(e);qq.isGenericPromise(t)?t.then(function(){p.cancel(e)}):t!==!1&&p.cancel(e)},cancelAll:function(){var e,t=c.getWaitingOrConnected();if(t.length)for(e=t.length-1;e>=0;e--)r.cancel(t[e]);c.reset()},getFile:function(e){return o.getProxy&&o.getProxy(e)?o.getProxy(e).referenceBlob:o.getFile&&o.getFile(e)},isProxied:function(e){return!(!o.getProxy||!o.getProxy(e))},getInput:function(e){if(o.getInput)return o.getInput(e)},reset:function(){i("Resetting upload handler"),r.cancelAll(),c.reset(),o.reset()},expunge:function(e){if(r.isValid(e))return o.expunge(e)},isValid:function(e){return o.isValid(e)},getResumableFilesData:function(){return o.getResumableFilesData?o.getResumableFilesData():[]},getThirdPartyFileId:function(e){if(r.isValid(e))return o.getThirdPartyFileId(e)},pause:function(e){return!!(r.isResumable(e)&&o.pause&&r.isValid(e)&&o.pause(e))&&(c.free(e),o.moveInProgressToRemaining(e),!0)},isResumable:function(e){return!!o.isResumable&&o.isResumable(e)}}),qq.extend(l,e),i=l.log,a=l.chunking.enabled&&qq.supportedFeatures.chunking,s=a&&l.chunking.concurrent.enabled,n=function(){var e={};return e[l.preventRetryParam]=!0,e}(),p.initHandler()},qq.WindowReceiveMessage=function(e){"use strict";var t={log:function(e,t){}},n={};qq.extend(t,e),qq.extend(this,{receiveMessage:function(e,t){var i=function(e){t(e.data)};window.postMessage?n[e]=qq(window).attach("message",i):log("iframe message passing not supported in this browser!","error")},stopReceivingMessages:function(e){if(window.postMessage){var t=n[e];t&&t()}}})},qq.FormUploadHandler=function(e){"use strict";function t(e){delete c[e],p&&(clearTimeout(d[e]),delete d[e],m.stopReceivingMessages(e));var t=document.getElementById(a._getIframeName(e));t&&(t.setAttribute("src","javascript:false;"),qq(t).remove())}function n(e){return e.split("_")[0]}function i(e){var t=qq.toElement("");return t.setAttribute("id",e),t.style.display="none",document.body.appendChild(t),t}function o(e,t){var i=e.id,o=n(i),r=f(o);u[r]=t,c[o]=qq(e).attach("load",function(){a.getInput(o)&&(q("Received iframe load event for CORS upload request (iframe name "+i+")"),d[i]=setTimeout(function(){var e="No valid message received from loaded iframe for iframe name "+i;q(e,"error"),t({error:e})},1e3))}),m.receiveMessage(i,function(e){q("Received the following window message: '"+e+"'");var t,o=(n(i),a._parseJsonResponse(e)),r=o.uuid;r&&u[r]?(q("Handling response for iframe name "+i),clearTimeout(d[i]),delete d[i],a._detachLoadEvent(i),t=u[r],delete u[r],m.stopReceivingMessages(i),t(o)):r||q("'"+e+"' does not contain a UUID - ignoring.")})}var r=e.options,a=this,s=e.proxy,l=qq.getUniqueId(),u={},c={},d={},p=r.isCors,h=r.inputName,f=s.getUuid,q=s.log,m=new qq.WindowReceiveMessage({log:q});qq.extend(this,new qq.UploadHandler(e)),qq.override(this,function(e){return{add:function(t,n){e.add(t,{input:n}),n.setAttribute("name",h),n.parentNode&&qq(n).remove()},expunge:function(n){t(n),e.expunge(n)},isValid:function(t){return e.isValid(t)&&void 0!==a._getFileState(t).input}}}),qq.extend(this,{getInput:function(e){return a._getFileState(e).input},_attachLoadEvent:function(e,t){var n;p?o(e,t):c[e.id]=qq(e).attach("load",function(){if(q("Received response for "+e.id),e.parentNode){try{if(e.contentDocument&&e.contentDocument.body&&"false"==e.contentDocument.body.innerHTML)return}catch(e){q("Error when attempting to access iframe during handling of upload response ("+e.message+")","error"),n={success:!1}}t(n)}})},_createIframe:function(e){var t=a._getIframeName(e);return i(t)},_detachLoadEvent:function(e){void 0!==c[e]&&(c[e](),delete c[e])},_getIframeName:function(e){return e+"_"+l},_initFormForUpload:function(e){var t=e.method,n=e.endpoint,i=e.params,o=e.paramsInBody,r=e.targetName,a=qq.toElement(""),s=n;return o?qq.obj2Inputs(i,a):s=qq.obj2url(i,n),a.setAttribute("action",s),a.setAttribute("target",r),a.style.display="none",document.body.appendChild(a),a},_parseJsonResponse:function(e){var t={};try{t=qq.parseJson(e)}catch(e){q("Error when attempting to parse iframe upload response ("+e.message+")","error")}return t}})},qq.XhrUploadHandler=function(e){"use strict";function t(e){qq.each(n._getXhrs(e),function(t,i){var o=n._getAjaxRequester(e,t);i.onreadystatechange=null,i.upload.onprogress=null,i.abort(),o&&o.canceled&&o.canceled(e)})}var n=this,i=e.options.namespace,o=e.proxy,r=e.options.chunking,a=e.options.resume,s=r&&e.options.chunking.enabled&&qq.supportedFeatures.chunking,l=a&&e.options.resume.enabled&&s&&qq.supportedFeatures.resume,u=o.getName,c=o.getSize,d=o.getUuid,p=o.getEndpoint,h=o.getDataByUuid,f=o.onUuidChanged,q=o.onProgress,m=o.log;qq.extend(this,new qq.UploadHandler(e)),qq.override(this,function(e){return{add:function(t,i){if(qq.isFile(i)||qq.isBlob(i))e.add(t,{file:i});else{if(!(i instanceof qq.BlobProxy))throw new Error("Passed obj is not a File, Blob, or proxy");e.add(t,{proxy:i})}n._initTempState(t),l&&n._maybePrepareForResume(t)},expunge:function(i){t(i),n._maybeDeletePersistedChunkData(i),n._clearXhrs(i),e.expunge(i)}}}),qq.extend(this,{clearCachedChunk:function(e,t){delete n._getFileState(e).temp.cachedChunks[t]},clearXhr:function(e,t){var i=n._getFileState(e).temp;i.xhrs&&delete i.xhrs[t],i.ajaxRequesters&&delete i.ajaxRequesters[t]},finalizeChunks:function(e,t){var i=n._getTotalChunks(e)-1,o=n._getXhr(e,i);return t?(new qq.Promise).success(t(o),o):(new qq.Promise).success({},o)},getFile:function(e){return n.isValid(e)&&n._getFileState(e).file},getProxy:function(e){return n.isValid(e)&&n._getFileState(e).proxy},getResumableFilesData:function(){var e=[];return n._iterateResumeRecords(function(t,i){n.moveInProgressToRemaining(null,i.chunking.inProgress,i.chunking.remaining);var o={name:i.name,remaining:i.chunking.remaining,size:i.size,uuid:i.uuid};i.key&&(o.key=i.key),e.push(o)}),e},isResumable:function(e){return!!r&&n.isValid(e)&&!n._getFileState(e).notResumable},moveInProgressToRemaining:function(e,t,i){var o=t||n._getFileState(e).chunking.inProgress,r=i||n._getFileState(e).chunking.remaining;o&&(m(qq.format("Moving these chunks from in-progress {}, to remaining.",JSON.stringify(o))),o.reverse(),qq.each(o,function(e,t){r.unshift(t)}),o.length=0)},pause:function(e){if(n.isValid(e))return m(qq.format("Aborting XHR upload for {} '{}' due to pause instruction.",e,u(e))),n._getFileState(e).paused=!0,t(e),!0},reevaluateChunking:function(e){if(r&&n.isValid(e)){var t,i,o=n._getFileState(e);if(delete o.chunking,o.chunking={},t=n._getTotalChunks(e),t>1||r.mandatory){for(o.chunking.enabled=!0,o.chunking.parts=t,o.chunking.remaining=[],i=0;i=o?o:s+i,u=n._getTotalChunks(e),d=this._getFileState(e).temp.cachedChunks,p=d[t]||qq.sliceBlob(a,s,l);return d[t]=p,{part:t,start:s,end:l,count:u,blob:p,size:l-s}},_getChunkDataForCallback:function(e){return{partIndex:e.part,startByte:e.start+1,endByte:e.end,totalParts:e.count}},_getLocalStorageId:function(e){var t="5.0",n=u(e),o=c(e),a=r.partSize,s=p(e);return qq.format("qq{}resume{}-{}-{}-{}-{}",i,t,n,o,a,s)},_getMimeType:function(e){return n.getFile(e).type},_getPersistableData:function(e){return n._getFileState(e).chunking},_getTotalChunks:function(e){if(r){var t=c(e),n=r.partSize;return Math.ceil(t/n)}},_getXhr:function(e,t){var i=null==t?-1:t;return n._getFileState(e).temp.xhrs[i]},_getXhrs:function(e){return n._getFileState(e).temp.xhrs},_iterateResumeRecords:function(e){l&&qq.each(localStorage,function(t,n){if(0===t.indexOf(qq.format("qq{}resume",i))){var o=JSON.parse(n);e(t,o)}})},_initTempState:function(e){n._getFileState(e).temp={ajaxRequesters:{},chunkProgress:{},xhrs:{},cachedChunks:{}}},_markNotResumable:function(e){n._getFileState(e).notResumable=!0},_maybeDeletePersistedChunkData:function(e){var t;return!!(l&&n.isResumable(e)&&(t=n._getLocalStorageId(e),t&&localStorage.getItem(t)))&&(localStorage.removeItem(t),!0)},_maybePrepareForResume:function(e){var t,i,o=n._getFileState(e);l&&void 0===o.key&&(t=n._getLocalStorageId(e),i=localStorage.getItem(t),i&&(i=JSON.parse(i),h(i.uuid)?n._markNotResumable(e):(m(qq.format("Identified file with ID {} and name of {} as resumable.",e,u(e))),f(e,i.uuid),o.key=i.key,o.chunking=i.chunking,o.loaded=i.loaded,o.attemptingResume=!0,n.moveInProgressToRemaining(e))))},_maybePersistChunkedState:function(e){var t,i,o=n._getFileState(e);if(l&&n.isResumable(e)){t=n._getLocalStorageId(e),i={name:u(e),size:c(e),uuid:d(e),key:o.key,chunking:o.chunking,loaded:o.loaded,lastUpdated:Date.now()};try{localStorage.setItem(t,JSON.stringify(i))}catch(t){m(qq.format("Unable to save resume data for '{}' due to error: '{}'.",e,t.toString()),"warn")}}},_registerProgressHandler:function(e,t,i){var o=n._getXhr(e,t),r=u(e),a={simple:function(t,n){var i=c(e);t===n?q(e,r,i,i):q(e,r,t>=i?i-1:t,i)},chunked:function(o,a){var s=n._getFileState(e).temp.chunkProgress,l=n._getFileState(e).loaded,u=o,d=a,p=c(e),h=u-(d-i),f=l;s[t]=h,qq.each(s,function(e,t){f+=t}),q(e,r,f,p)}};o.upload.onprogress=function(e){if(e.lengthComputable){var t=null==i?"simple":"chunked";a[t](e.loaded,e.total)}}},_registerXhr:function(e,t,i,o){var r=null==t?-1:t,a=n._getFileState(e).temp;return a.xhrs=a.xhrs||{},a.ajaxRequesters=a.ajaxRequesters||{},a.xhrs[r]=i,o&&(a.ajaxRequesters[r]=o),i},_removeExpiredChunkingRecords:function(){var e=a.recordsExpireIn;n._iterateResumeRecords(function(t,n){var i=new Date(n.lastUpdated);i.setDate(i.getDate()+e),i.getTime()<=Date.now()&&(m("Removing expired resume record with key "+t),localStorage.removeItem(t))})},_shouldChunkThisFile:function(e){var t=n._getFileState(e);return t.chunking||n.reevaluateChunking(e),t.chunking.enabled}})},qq.DeleteFileAjaxRequester=function(e){"use strict";function t(){return"POST"===i.method.toUpperCase()?{_method:"DELETE"}:{}}var n,i={method:"DELETE",uuidParamName:"qquuid",endpointStore:{},maxConnections:3,customHeaders:function(e){return{}},paramsStore:{},cors:{expected:!1,sendCredentials:!1},log:function(e,t){},onDelete:function(e){},onDeleteComplete:function(e,t,n){}};qq.extend(i,e),n=qq.extend(this,new qq.AjaxRequester({acceptHeader:"application/json",validMethods:["POST","DELETE"],method:i.method,endpointStore:i.endpointStore,paramsStore:i.paramsStore,mandatedParams:t(),maxConnections:i.maxConnections,customHeaders:function(e){return i.customHeaders.get(e)},log:i.log,onSend:i.onDelete,onComplete:i.onDeleteComplete,cors:i.cors})),qq.extend(this,{sendDelete:function(e,t,o){var r=o||{};i.log("Submitting delete file request for "+e),"DELETE"===i.method?n.initTransport(e).withPath(t).withParams(r).send():(r[i.uuidParamName]=t,n.initTransport(e).withParams(r).send())}})},function(){function e(e){var t,n=e.naturalWidth,i=e.naturalHeight,o=document.createElement("canvas");return n*i>1048576&&(o.width=o.height=1,t=o.getContext("2d"),t.drawImage(e,-n+1,0),0===t.getImageData(0,0,1,1).data[3])}function t(e,t,n){var i,o,r,a,s=document.createElement("canvas"),l=0,u=n,c=n;for(s.width=1,s.height=n,i=s.getContext("2d"),i.drawImage(e,0,0),o=i.getImageData(0,0,1,n).data;c>l;)r=o[4*(c-1)+3],0===r?u=c:l=c,c=u+l>>1;return a=c/n,0===a?1:a}function n(e,t,n,i){var r=document.createElement("canvas"),a=n.mime||"image/jpeg",s=new qq.Promise;return o(e,t,r,n,i).then(function(){s.success(r.toDataURL(a,n.quality||.8))}),s}function i(e){var t=5241e3;if(!qq.ios())throw new qq.Error("Downsampled dimensions can only be reliably calculated for iOS!");if(e.origHeight*e.origWidth>t)return{newHeight:Math.round(Math.sqrt(t*(e.origHeight/e.origWidth))),newWidth:Math.round(Math.sqrt(t*(e.origWidth/e.origHeight)))}}function o(n,o,s,l,u){var c,d=n.naturalWidth,p=n.naturalHeight,h=l.width,f=l.height,q=s.getContext("2d"),m=new qq.Promise;return q.save(),l.resize?r({blob:o,canvas:s,image:n,imageHeight:p,imageWidth:d,orientation:l.orientation,resize:l.resize,targetHeight:f,targetWidth:h}):(qq.supportedFeatures.unlimitedScaledImageSize||(c=i({origWidth:h,origHeight:f}),c&&(qq.log(qq.format("Had to reduce dimensions due to device limitations from {}w / {}h to {}w / {}h",h,f,c.newWidth,c.newHeight),"warn"),h=c.newWidth,f=c.newHeight)),a(s,h,f,l.orientation),qq.ios()?!function(){e(n)&&(d/=2,p/=2);var i,o,r,a=1024,s=document.createElement("canvas"),l=u?t(n,d,p):1,c=Math.ceil(a*h/d),m=Math.ceil(a*f/p/l),g=0,_=0;for(s.width=s.height=a,i=s.getContext("2d");gc&&(l=c,u=s*l/a<<0),d&&u>d&&(u=d,l=a*u/s<<0),i={width:l,height:u},qq.each(t,function(e,t){i[e]=t}),"img"===h?!function(){var t=e.src;n(r.srcImage,r.blob,i,p).then(function(n){e.src=n,t===e.src&&e.onload()})}():"canvas"===h&&o(this.srcImage,this.blob,e,i,p),void("function"==typeof this.onrender&&this.onrender(e)))},qq.MegaPixImage=s}(),qq.ImageGenerator=function(e){"use strict";function t(e){return"img"===e.tagName.toLowerCase()}function n(e){return"canvas"===e.tagName.toLowerCase()}function i(){return void 0!==(new Image).crossOrigin}function o(){var e=document.createElement("canvas");return e.getContext&&e.getContext("2d")}function r(e){var t=e.split("/"),n=t[t.length-1].split("?")[0],i=qq.getExtension(n);switch(i=i&&i.toLowerCase()){case"jpeg":case"jpg":return"image/jpeg";case"png":return"image/png";case"bmp":return"image/bmp";case"gif":return"image/gif";case"tiff":case"tif":return"image/tiff"}}function a(e){var t,n,i,o=document.createElement("a");return o.href=e,t=o.protocol,i=o.port,n=o.hostname,t.toLowerCase()!==window.location.protocol.toLowerCase()||(n.toLowerCase()!==window.location.hostname.toLowerCase()||i!==window.location.port&&!qq.ie())}function s(t,n){t.onload=function(){t.onload=null,t.onerror=null,n.success(t)},t.onerror=function(){t.onload=null,t.onerror=null,e("Problem drawing thumbnail!","error"),n.failure(t,"Problem drawing thumbnail!")}}function l(e,t){e.qqImageRendered=function(){t.success(e)}}function u(i,o){var r=t(i)||n(i);return t(i)?s(i,o):n(i)?l(i,o):(o.failure(i),e(qq.format("Element container of type {} is not supported!",i.tagName),"error")),r}function c(t,n,i){var o=new qq.Promise,r=new qq.Identify(t,e),a=i.maxSize,s=null==i.orient||i.orient,l=function(){n.onerror=null,n.onload=null,e("Could not render preview, file may be too large!","error"),o.failure(n,"Browser cannot render image!")};return r.isPreviewable().then(function(r){var c={parse:function(){return(new qq.Promise).success()}},d=s?new qq.Exif(t,e):c,p=new qq.MegaPixImage(t,l);u(n,o)&&d.parse().then(function(e){var t=e&&e.Orientation;p.render(n,{maxWidth:a,maxHeight:a,orientation:t,mime:r,resize:i.customResizeFunction})},function(t){e(qq.format("EXIF data could not be parsed ({}). Assuming orientation = 1.",t)),p.render(n,{maxWidth:a,maxHeight:a,mime:r,resize:i.customResizeFunction})})},function(){e("Not previewable"),o.failure(n,"Not previewable")}),o}function d(e,t,n,i,o){var s=new Image,l=new qq.Promise;u(s,l),a(e)&&(s.crossOrigin="anonymous"),s.src=e,l.then(function(){u(t,n);var a=new qq.MegaPixImage(s);a.render(t,{maxWidth:i,maxHeight:i,mime:r(e),resize:o})},n.failure)}function p(e,t,n,i){u(t,n),qq(t).css({maxWidth:i+"px",maxHeight:i+"px"}),t.src=e}function h(e,r,s){var l=new qq.Promise,c=s.scale,h=c?s.maxSize:null;return c&&t(r)?o()?a(e)&&!i()?p(e,r,l,h):d(e,r,l,h):p(e,r,l,h):n(r)?d(e,r,l,h):u(r,l)&&(r.src=e),l}qq.extend(this,{generate:function(t,n,i){return qq.isString(t)?(e("Attempting to update thumbnail based on server response."),h(t,n,i||{})):(e("Attempting to draw client-side image preview."),c(t,n,i||{}))}}),this._testing={},this._testing.isImg=t,this._testing.isCanvas=n,this._testing.isCrossOrigin=a,this._testing.determineMimeOfFileName=r},qq.Exif=function(e,t){"use strict";function n(e){for(var t=0,n=0;e.length>0;)t+=parseInt(e.substring(0,2),16)*Math.pow(2,n),e=e.substring(2,e.length),n+=8;return t}function i(t,n){var o=t,r=n;return void 0===o&&(o=2,r=new qq.Promise),qq.readBlobToHex(e,o,4).then(function(e){var t,n=/^ffe([0-9])/.exec(e);n?"1"!==n[1]?(t=parseInt(e.slice(4,8),16),i(o+t+2,r)):r.success(o):r.failure("No EXIF header to be found!")}),r}function o(){var t=new qq.Promise;return qq.readBlobToHex(e,0,6).then(function(e){0!==e.indexOf("ffd8")?t.failure("Not a valid JPEG!"):i().then(function(e){t.success(e)},function(e){t.failure(e)})}),t}function r(t){var n=new qq.Promise;return qq.readBlobToHex(e,t+10,2).then(function(e){n.success("4949"===e)}),n}function a(t,i){var o=new qq.Promise;return qq.readBlobToHex(e,t+18,2).then(function(e){return i?o.success(n(e)):void o.success(parseInt(e,16))}),o}function s(t,n){var i=t+20,o=12*n;return qq.readBlobToHex(e,i,o)}function l(e){for(var t=[],n=0;n+24<=e.length;)t.push(e.slice(n,n+24)),n+=24;return t}function u(e,t){var i=16,o=qq.extend([],c),r={};return qq.each(t,function(t,a){var s,l,u,c=a.slice(0,4),p=e?n(c):parseInt(c,16),h=o.indexOf(p);if(h>=0&&(l=d[p].name,u=d[p].bytes,s=a.slice(i,i+2*u),r[l]=e?n(s):parseInt(s,16),o.splice(h,1)),0===o.length)return!1}),r}var c=[274],d={274:{name:"Orientation",bytes:2}};qq.extend(this,{parse:function(){var n=new qq.Promise,i=function(e){t(qq.format("EXIF header parse failed: '{}' ",e)),n.failure(e)};return o().then(function(o){t(qq.format("Moving forward with EXIF header parsing for '{}'",void 0===e.name?"blob":e.name)),r(o).then(function(e){t(qq.format("EXIF Byte order is {} endian",e?"little":"big")),a(o,e).then(function(r){t(qq.format("Found {} APP1 directory entries",r)),s(o,r).then(function(i){var o=l(i),r=u(e,o);t("Successfully parsed some EXIF tags"),n.success(r)},i)},i)},i)},i),n}}),this._testing={},this._testing.parseLittleEndian=n},qq.Identify=function(e,t){"use strict";function n(e,t){var n=!1,i=[].concat(e);return qq.each(i,function(e,i){if(0===t.indexOf(i))return n=!0,!1}),n}qq.extend(this,{isPreviewable:function(){var i=this,o=new qq.Promise,r=!1,a=void 0===e.name?"blob":e.name;return t(qq.format("Attempting to determine if {} can be rendered in this browser",a)),t("First pass: check type attribute of blob object."),this.isPreviewableSync()?(t("Second pass: check for magic bytes in file header."),qq.readBlobToHex(e,0,4).then(function(e){qq.each(i.PREVIEWABLE_MIME_TYPES,function(t,i){if(n(i,e))return("image/tiff"!==t||qq.supportedFeatures.tiffPreviews)&&(r=!0,o.success(t)),!1}),t(qq.format("'{}' is {} able to be rendered in this browser",a,r?"":"NOT")),r||o.failure()},function(){t("Error reading file w/ name '"+a+"'. Not able to be rendered in this browser."),o.failure()})):o.failure(),o},isPreviewableSync:function(){var n=e.type,i=qq.indexOf(Object.keys(this.PREVIEWABLE_MIME_TYPES),n)>=0,o=!1,r=void 0===e.name?"blob":e.name;return i&&(o="image/tiff"!==n||qq.supportedFeatures.tiffPreviews),!o&&t(r+" is not previewable in this browser per the blob's type attr"),o}})},qq.Identify.prototype.PREVIEWABLE_MIME_TYPES={"image/jpeg":"ffd8ff","image/gif":"474946","image/png":"89504e","image/bmp":"424d","image/tiff":["49492a00","4d4d002a"]},qq.ImageValidation=function(e,t){"use strict";function n(e){var t=!1;return qq.each(e,function(e,n){if(n>0)return t=!0,!1}),t}function i(){var n=new qq.Promise;return new qq.Identify(e,t).isPreviewable().then(function(){var i=new Image,o=window.URL&&window.URL.createObjectURL?window.URL:window.webkitURL&&window.webkitURL.createObjectURL?window.webkitURL:null;o?(i.onerror=function(){t("Cannot determine dimensions for image. May be too large.","error"),n.failure()},i.onload=function(){n.success({width:this.width,height:this.height})},i.src=o.createObjectURL(e)):(t("No createObjectURL function available to generate image URL!","error"),n.failure())},n.failure),n}function o(e,t){var n;return qq.each(e,function(e,i){if(i>0){var o=/(max|min)(Width|Height)/.exec(e),r=o[2].charAt(0).toLowerCase()+o[2].slice(1),a=t[r];switch(o[1]){case"min":if(ai)return n=e,!1}}}),n}this.validate=function(e){var r=new qq.Promise;return t("Attempting to validate image."),n(e)?i().then(function(t){var n=o(e,t);n?r.failure(n):r.success()},r.success):r.success(),r}},qq.Session=function(e){"use strict";function t(e){return!!qq.isArray(e)||void i.log("Session response is not an array.","error")}function n(e,n,o,r){var a=!1;n=n&&t(e),n&&qq.each(e,function(e,t){if(null==t.uuid)a=!0,i.log(qq.format("Session response item {} did not include a valid UUID - ignoring.",e),"error");else if(null==t.name)a=!0,i.log(qq.format("Session response item {} did not include a valid name - ignoring.",e),"error");else try{return i.addFileRecord(t),!0}catch(e){a=!0,i.log(e.message,"error")}return!1}),r[n&&!a?"success":"failure"](e,o)}var i={endpoint:null,params:{},customHeaders:{},cors:{},addFileRecord:function(e){},log:function(e,t){}};qq.extend(i,e,!0),this.refresh=function(){var e=new qq.Promise,t=function(t,i,o){n(t,i,o,e)},o=qq.extend({},i),r=new qq.SessionAjaxRequester(qq.extend(o,{onComplete:t}));return r.queryServer(),e}},qq.SessionAjaxRequester=function(e){"use strict";function t(e,t,n){var o=null;if(null!=t.responseText)try{o=qq.parseJson(t.responseText)}catch(e){i.log("Problem parsing session response: "+e.message,"error"),n=!0}i.onComplete(o,!n,t)}var n,i={endpoint:null,customHeaders:{},params:{},cors:{expected:!1,sendCredentials:!1},onComplete:function(e,t,n){},log:function(e,t){}};qq.extend(i,e),n=qq.extend(this,new qq.AjaxRequester({acceptHeader:"application/json",validMethods:["GET"],method:"GET",endpointStore:{get:function(){return i.endpoint}},customHeaders:i.customHeaders,log:i.log,onComplete:t,cors:i.cors})),qq.extend(this,{queryServer:function(){var e=qq.extend({},i.params);i.log("Session query request."),n.initTransport("sessionRefresh").withParams(e).withCacheBuster().send()}})},qq.Scaler=function(e,t){"use strict";var n=e.customResizer,i=e.sendOriginal,o=e.orient,r=e.defaultType,a=e.defaultQuality/100,s=e.failureText,l=e.includeExif,u=this._getSortedSizes(e.sizes);qq.extend(this,{enabled:qq.supportedFeatures.scaling&&u.length>0,getFileRecords:function(e,c,d){var p=this,h=[],f=d.blob?d.blob:d,q=new qq.Identify(f,t);return q.isPreviewableSync()?(qq.each(u,function(e,i){var u=p._determineOutputType({defaultType:r,requestedType:i.type,refType:f.type});h.push({uuid:qq.getUniqueId(),name:p._getName(c,{name:i.name,type:u,refType:f.type}),blob:new qq.BlobProxy(f,qq.bind(p._generateScaledImage,p,{customResizeFunction:n,maxSize:i.maxSize,orient:o,type:u,quality:a,failedText:s,includeExif:l,log:t}))})}),h.push({uuid:e,name:c,size:f.size,blob:i?f:null})):h.push({uuid:e,name:c,size:f.size,blob:f}),h},handleNewFile:function(e,t,n,i,o,r,a,s){var l=this,u=(e.qqButtonId||e.blob&&e.blob.qqButtonId,[]),c=null,d=s.addFileToHandler,p=s.uploadData,h=s.paramsStore,f=qq.getUniqueId();qq.each(l.getFileRecords(n,t,e),function(e,t){var n,i=t.size;t.blob instanceof qq.BlobProxy&&(i=-1),n=p.addFile({uuid:t.uuid,name:t.name,size:i,batchId:r,proxyGroupId:f}),t.blob instanceof qq.BlobProxy?u.push(n):c=n,t.blob?(d(n,t.blob),o.push({id:n,file:t.blob})):p.setStatus(n,qq.status.REJECTED)}),null!==c&&(qq.each(u,function(e,t){var n={qqparentuuid:p.retrieve({id:c}).uuid,qqparentsize:p.retrieve({id:c}).size};n[a]=p.retrieve({id:t}).uuid,p.setParentId(t,c),h.addReadOnly(t,n)}),u.length&&!function(){var e={};e[a]=p.retrieve({id:c}).uuid,h.addReadOnly(c,e)}())}})},qq.extend(qq.Scaler.prototype,{scaleImage:function(e,t,n){"use strict";if(!qq.supportedFeatures.scaling)throw new qq.Error("Scaling is not supported in this browser!");var i=new qq.Promise,o=n.log,r=n.getFile(e),a=n.uploadData.retrieve({id:e}),s=a&&a.name,l=a&&a.uuid,u={customResizer:t.customResizer,sendOriginal:!1,orient:t.orient,defaultType:t.type||null,defaultQuality:t.quality,failedToScaleText:"Unable to scale",sizes:[{name:"",maxSize:t.maxSize}]},c=new qq.Scaler(u,o);return qq.Scaler&&qq.supportedFeatures.imagePreviews&&r?qq.bind(function(){var t=c.getFileRecords(l,s,r)[0];t&&t.blob instanceof qq.BlobProxy?t.blob.create().then(i.success,i.failure):(o(e+" is not a scalable image!","error"),i.failure())},this)():(i.failure(),o("Could not generate requested scaled image for "+e+". Scaling is either not possible in this browser, or the file could not be located.","error")),i},_determineOutputType:function(e){"use strict";var t=e.requestedType,n=e.defaultType,i=e.refType;return n||t?t&&qq.indexOf(Object.keys(qq.Identify.prototype.PREVIEWABLE_MIME_TYPES),t)>=0?"image/tiff"===t?qq.supportedFeatures.tiffPreviews?t:n:t:n:"image/jpeg"!==i?"image/png":i},_getName:function(e,t){"use strict";var n=e.lastIndexOf("."),i=t.type||"image/png",o=t.refType,r="",a=qq.getExtension(e),s="";return t.name&&t.name.trim().length&&(s=" ("+t.name+")"),n>=0?(r=e.substr(0,n),o!==i&&(a=i.split("/")[1]),r+=s+"."+a):r=e+s,r},_getSortedSizes:function(e){"use strict";return e=qq.extend([],e),e.sort(function(e,t){return e.maxSize>t.maxSize?1:e.maxSize=0?atob(e.split(",")[1]):decodeURI(e.split(",")[1]),n=e.split(",")[0].split(":")[1].split(";")[0],i=new ArrayBuffer(t.length),o=new Uint8Array(i),qq.each(t,function(e,t){o[e]=t.charCodeAt(0)}),this._createBlob(i,n)},_createBlob:function(e,t){"use strict";var n=window.BlobBuilder||window.WebKitBlobBuilder||window.MozBlobBuilder||window.MSBlobBuilder,i=n&&new n;return i?(i.append(e),i.getBlob(t)):new Blob([e],{type:t})}}),qq.ExifRestorer=function(){var e={};return e.KEY_STR="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
-e.encode64=function(e){var t,n,i,o,r,a="",s="",l="",u=0;do t=e[u++],n=e[u++],s=e[u++],i=t>>2,o=(3&t)<<4|n>>4,r=(15&n)<<2|s>>6,l=63&s,isNaN(n)?r=l=64:isNaN(s)&&(l=64),a=a+this.KEY_STR.charAt(i)+this.KEY_STR.charAt(o)+this.KEY_STR.charAt(r)+this.KEY_STR.charAt(l),t=n=s="",i=o=r=l="";while(ue.length)break}return n},e.decode64=function(e){var t,n,i,o,r,a="",s="",l=0,u=[],c=/[^A-Za-z0-9\+\/\=]/g;if(c.exec(e))throw new Error("There were invalid base64 characters in the input text. Valid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='");e=e.replace(/[^A-Za-z0-9\+\/\=]/g,"");do i=this.KEY_STR.indexOf(e.charAt(l++)),o=this.KEY_STR.indexOf(e.charAt(l++)),r=this.KEY_STR.indexOf(e.charAt(l++)),s=this.KEY_STR.indexOf(e.charAt(l++)),t=i<<2|o>>4,n=(15&o)<<4|r>>2,a=(3&r)<<6|s,u.push(t),64!=r&&u.push(n),64!=s&&u.push(a),t=n=a="",i=o=r=s="";while(l=0)return n=!1,!1}),n},u=function(e){p(e,-1,-1),delete n[e]},c=function(e,t,n){(0===t.length||l(t,n))&&(s(o,o),this.reset())},d=function(e){var i=t(e);i>0&&(p(e,0,i),n[e]={loaded:0,total:i})},p=function(e,t,r){var a=n[e]?n[e].loaded:0,l=n[e]?n[e].total:0;t===-1&&r===-1?(i-=a,o-=l):(t&&(i+=t-a),r&&(o+=r-l)),s(i,o)};qq.extend(this,{onAllComplete:c,onStatusChange:function(e,t,n){n===qq.status.CANCELED||n===qq.status.REJECTED?u(e):n===qq.status.SUBMITTING&&d(e)},onIndividualProgress:function(e,t,i){p(e,t,i),n[e]={loaded:t,total:i}},onNewSize:function(e){d(e)},reset:function(){n={},i=0,o=0}})},qq.PasteSupport=function(e){"use strict";function t(e){return e.type&&0===e.type.indexOf("image/")}function n(){r=qq(o.targetElement).attach("paste",function(e){var n=e.clipboardData;n&&qq.each(n.items,function(e,n){if(t(n)){var i=n.getAsFile();o.callbacks.pasteReceived(i)}})})}function i(){r&&r()}var o,r;o={targetElement:null,callbacks:{log:function(e,t){},pasteReceived:function(e){}}},qq.extend(o,e),n(),qq.extend(this,{reset:function(){i()}})},qq.FormSupport=function(e,t,n){"use strict";function i(e){e.getAttribute("action")&&(s.newEndpoint=e.getAttribute("action"))}function o(e,t){return!(e.checkValidity&&!e.checkValidity())||(n("Form did not pass validation checks - will not upload.","error"),void t())}function r(e){var n=e.submit;qq(e).attach("submit",function(i){i=i||window.event,i.preventDefault?i.preventDefault():i.returnValue=!1,o(e,n)&&t()}),e.submit=function(){o(e,n)&&t()}}function a(e){return e&&(qq.isString(e)&&(e=document.getElementById(e)),e&&(n("Attaching to form element."),i(e),l&&r(e))),e}var s=this,l=e.interceptSubmit,u=e.element,c=e.autoUpload;qq.extend(this,{newEndpoint:null,newAutoUpload:c,attachedToForm:!1,getFormInputsAsObject:function(){return null==u?null:s._form2Obj(u)}}),u=a(u),this.attachedToForm=!!u},qq.extend(qq.FormSupport.prototype,{_form2Obj:function(e){"use strict";var t={},n=function(e){var t=["button","image","reset","submit"];return qq.indexOf(t,e.toLowerCase())<0},i=function(e){return qq.indexOf(["checkbox","radio"],e.toLowerCase())>=0},o=function(e){return!(!i(e.type)||e.checked)||e.disabled&&"hidden"!==e.type.toLowerCase()},r=function(e){var t=null;return qq.each(qq(e).children(),function(e,n){if("option"===n.tagName.toLowerCase()&&n.selected)return t=n.value,!1}),t};return qq.each(e.elements,function(e,i){if(!qq.isInput(i,!0)&&"textarea"!==i.tagName.toLowerCase()||!n(i.type)||o(i)){if("select"===i.tagName.toLowerCase()&&!o(i)){var a=r(i);null!==a&&(t[i.name]=a)}}else t[i.name]=i.value}),t}}),qq.traditional=qq.traditional||{},qq.traditional.FormUploadHandler=function(e,t){"use strict";function n(e,t){var n,i,r;try{i=t.contentDocument||t.contentWindow.document,r=i.body.innerHTML,s("converting iframe's innerHTML to JSON"),s("innerHTML = "+r),r&&r.match(/^1&&!u.allowMultipleItems?(u.callbacks.processingDroppedFilesComplete([]),u.callbacks.dropError("tooManyFilesError",""),t.dropDisabled(!1),o.failure()):(h=[],qq.isFolderDropSupported(e)?qq.each(e.items,function(e,t){var r=t.webkitGetAsEntry();r&&(r.isFile?h.push(t.getAsFile()):i.push(n(r).done(function(){i.pop(),0===i.length&&o.success()})))}):h=e.files,0===i.length&&o.success()),o}function r(e){var n=new qq.UploadDropZone({HIDE_ZONES_EVENT_NAME:c,element:e,onEnter:function(t){qq(e).addClass(u.classes.dropActive),t.stopPropagation()},onLeaveNotDescendants:function(t){qq(e).removeClass(u.classes.dropActive)},onDrop:function(e){o(e.dataTransfer,n).then(function(){t(h,n)},function(){u.callbacks.dropLog("Drop event DataTransfer parsing failed. No files will be uploaded.","error")})}});return f.addDisposer(function(){n.dispose()}),qq(e).hasAttribute(d)&&qq(e).hide(),p.push(n),n}function a(e){var t;return qq.each(e.dataTransfer.types,function(e,n){if("Files"===n)return t=!0,!1}),t}function s(e){return qq.firefox()?!e.relatedTarget:qq.safari()?e.x<0||e.y<0:0===e.x&&0===e.y}function l(){var e=u.dropZoneElements,t=function(){setTimeout(function(){qq.each(e,function(e,t){qq(t).hasAttribute(d)&&qq(t).hide(),qq(t).removeClass(u.classes.dropActive)})},10)};qq.each(e,function(t,n){var i=r(n);e.length&&qq.supportedFeatures.fileDrop&&f.attach(document,"dragenter",function(t){!i.dropDisabled()&&a(t)&&qq.each(e,function(e,t){t instanceof HTMLElement&&qq(t).hasAttribute(d)&&qq(t).css({display:"block"})})})}),f.attach(document,"dragleave",function(e){s(e)&&t()}),f.attach(qq(document).children()[0],"mouseenter",function(e){t()}),f.attach(document,"drop",function(e){e.preventDefault(),t()}),f.attach(document,c,t)}var u,c="qq-hidezones",d="qq-hide-dropzone",p=[],h=[],f=new qq.DisposeSupport;u={dropZoneElements:[],allowMultipleItems:!0,classes:{dropActive:null},callbacks:new qq.DragAndDrop.callbacks},qq.extend(u,e,!0),l(),qq.extend(this,{setupExtraDropzone:function(e){u.dropZoneElements.push(e),r(e)},removeDropzone:function(e){var t,n=u.dropZoneElements;for(t in n)if(n[t]===e)return n.splice(t,1)},dispose:function(){f.dispose(),qq.each(p,function(e,t){t.dispose()})}})},qq.DragAndDrop.callbacks=function(){"use strict";return{processingDroppedFiles:function(){},processingDroppedFilesComplete:function(e,t){},dropError:function(e,t){qq.log("Drag & drop error code '"+e+" with these specifics: '"+t+"'","error")},dropLog:function(e,t){qq.log(e,t)}}},qq.UploadDropZone=function(e){"use strict";function t(){return qq.safari()||qq.firefox()&&qq.windows()}function n(e){c||(t?d.attach(document,"dragover",function(e){e.preventDefault()}):d.attach(document,"dragover",function(e){e.dataTransfer&&(e.dataTransfer.dropEffect="none",e.preventDefault())}),c=!0)}function i(e){if(!qq.supportedFeatures.fileDrop)return!1;var t,n=e.dataTransfer,i=qq.safari();return t=!(!qq.ie()||!qq.supportedFeatures.fileDrop)||"none"!==n.effectAllowed,n&&t&&(n.files||!i&&n.types.contains&&n.types.contains("Files"))}function o(e){return void 0!==e&&(u=e),u}function r(){function e(){t=document.createEvent("Event"),t.initEvent(s.HIDE_ZONES_EVENT_NAME,!0,!0)}var t;if(window.CustomEvent)try{t=new CustomEvent(s.HIDE_ZONES_EVENT_NAME)}catch(t){e()}else e();document.dispatchEvent(t)}function a(){d.attach(l,"dragover",function(e){if(i(e)){var t=qq.ie()&&qq.supportedFeatures.fileDrop?null:e.dataTransfer.effectAllowed;"move"===t||"linkMove"===t?e.dataTransfer.dropEffect="move":e.dataTransfer.dropEffect="copy",e.stopPropagation(),e.preventDefault()}}),d.attach(l,"dragenter",function(e){if(!o()){if(!i(e))return;s.onEnter(e)}}),d.attach(l,"dragleave",function(e){if(i(e)){s.onLeave(e);var t=document.elementFromPoint(e.clientX,e.clientY);qq(this).contains(t)||s.onLeaveNotDescendants(e)}}),d.attach(l,"drop",function(e){if(!o()){if(!i(e))return;e.preventDefault(),e.stopPropagation(),s.onDrop(e),r()}})}var s,l,u,c,d=new qq.DisposeSupport;s={element:null,onEnter:function(e){},onLeave:function(e){},onLeaveNotDescendants:function(e){},onDrop:function(e){}},qq.extend(s,e),l=s.element,n(),a(),qq.extend(this,{dropDisabled:function(e){return o(e)},dispose:function(){d.dispose()},getElement:function(){return l}})},function(){"use strict";qq.uiPublicApi={addInitialFiles:function(e){this._parent.prototype.addInitialFiles.apply(this,arguments),this._templating.addCacheToDom()},clearStoredFiles:function(){this._parent.prototype.clearStoredFiles.apply(this,arguments),this._templating.clearFiles()},addExtraDropzone:function(e){this._dnd&&this._dnd.setupExtraDropzone(e)},removeExtraDropzone:function(e){if(this._dnd)return this._dnd.removeDropzone(e)},getItemByFileId:function(e){if(!this._templating.isHiddenForever(e))return this._templating.getFileContainer(e)},reset:function(){this._parent.prototype.reset.apply(this,arguments),this._templating.reset(),!this._options.button&&this._templating.getButton()&&(this._defaultButtonId=this._createUploadButton({element:this._templating.getButton(),title:this._options.text.fileInputTitle}).getButtonId()),this._dnd&&(this._dnd.dispose(),this._dnd=this._setupDragAndDrop()),this._totalFilesInBatch=0,this._filesInBatchAddedToUi=0,this._setupClickAndEditEventHandlers()},setName:function(e,t){var n=this._options.formatFileName(t);this._parent.prototype.setName.apply(this,arguments),this._templating.updateFilename(e,n)},pauseUpload:function(e){var t=this._parent.prototype.pauseUpload.apply(this,arguments);return t&&this._templating.uploadPaused(e),t},continueUpload:function(e){var t=this._parent.prototype.continueUpload.apply(this,arguments);return t&&this._templating.uploadContinued(e),t},getId:function(e){return this._templating.getFileId(e)},getDropTarget:function(e){var t=this.getFile(e);return t.qqDropTarget}},qq.uiPrivateApi={_getButton:function(e){var t=this._parent.prototype._getButton.apply(this,arguments);return t||e===this._defaultButtonId&&(t=this._templating.getButton()),t},_removeFileItem:function(e){this._templating.removeFile(e)},_setupClickAndEditEventHandlers:function(){this._fileButtonsClickHandler=qq.FileButtonsClickHandler&&this._bindFileButtonsClickEvent(),this._focusinEventSupported=!qq.firefox(),this._isEditFilenameEnabled()&&(this._filenameClickHandler=this._bindFilenameClickEvent(),this._filenameInputFocusInHandler=this._bindFilenameInputFocusInEvent(),this._filenameInputFocusHandler=this._bindFilenameInputFocusEvent())},_setupDragAndDrop:function(){var e=this,t=this._options.dragAndDrop.extraDropzones,n=this._templating,i=n.getDropZone();return i&&t.push(i),new qq.DragAndDrop({dropZoneElements:t,allowMultipleItems:this._options.multiple,classes:{dropActive:this._options.classes.dropActive},callbacks:{processingDroppedFiles:function(){n.showDropProcessing()},processingDroppedFilesComplete:function(t,i){n.hideDropProcessing(),qq.each(t,function(e,t){t.qqDropTarget=i}),t.length&&e.addFiles(t,null,null)},dropError:function(t,n){e._itemError(t,n)},dropLog:function(t,n){e.log(t,n)}}})},_bindFileButtonsClickEvent:function(){var e=this;return new qq.FileButtonsClickHandler({templating:this._templating,log:function(t,n){e.log(t,n)},onDeleteFile:function(t){e.deleteFile(t)},onCancel:function(t){e.cancel(t)},onRetry:function(t){e.retry(t)},onPause:function(t){e.pauseUpload(t)},onContinue:function(t){e.continueUpload(t)},onGetName:function(t){return e.getName(t)}})},_isEditFilenameEnabled:function(){return this._templating.isEditFilenamePossible()&&!this._options.autoUpload&&qq.FilenameClickHandler&&qq.FilenameInputFocusHandler&&qq.FilenameInputFocusHandler},_filenameEditHandler:function(){var e=this,t=this._templating;return{templating:t,log:function(t,n){e.log(t,n)},onGetUploadStatus:function(t){return e.getUploads({id:t}).status},onGetName:function(t){return e.getName(t)},onSetName:function(t,n){e.setName(t,n)},onEditingStatusChange:function(e,n){var i=qq(t.getEditInput(e)),o=qq(t.getFileContainer(e));n?(i.addClass("qq-editing"),t.hideFilename(e),t.hideEditIcon(e)):(i.removeClass("qq-editing"),t.showFilename(e),t.showEditIcon(e)),o.addClass("qq-temp").removeClass("qq-temp")}}},_onUploadStatusChange:function(e,t,n){this._parent.prototype._onUploadStatusChange.apply(this,arguments),this._isEditFilenameEnabled()&&this._templating.getFileContainer(e)&&n!==qq.status.SUBMITTED&&(this._templating.markFilenameEditable(e),this._templating.hideEditIcon(e)),t===qq.status.UPLOAD_RETRYING&&n===qq.status.UPLOADING?(this._templating.hideRetry(e),this._templating.setStatusText(e),qq(this._templating.getFileContainer(e)).removeClass(this._classes.retrying)):n===qq.status.UPLOAD_FAILED&&this._templating.hidePause(e)},_bindFilenameInputFocusInEvent:function(){var e=qq.extend({},this._filenameEditHandler());return new qq.FilenameInputFocusInHandler(e)},_bindFilenameInputFocusEvent:function(){var e=qq.extend({},this._filenameEditHandler());return new qq.FilenameInputFocusHandler(e)},_bindFilenameClickEvent:function(){var e=qq.extend({},this._filenameEditHandler());return new qq.FilenameClickHandler(e)},_storeForLater:function(e){this._parent.prototype._storeForLater.apply(this,arguments),this._templating.hideSpinner(e)},_onAllComplete:function(e,t){this._parent.prototype._onAllComplete.apply(this,arguments),this._templating.resetTotalProgress()},_onSubmit:function(e,t){var n=this.getFile(e);n&&n.qqPath&&this._options.dragAndDrop.reportDirectoryPaths&&this._paramsStore.addReadOnly(e,{qqpath:n.qqPath}),this._parent.prototype._onSubmit.apply(this,arguments),this._addToList(e,t)},_onSubmitted:function(e){this._isEditFilenameEnabled()&&(this._templating.markFilenameEditable(e),this._templating.showEditIcon(e),this._focusinEventSupported||this._filenameInputFocusHandler.addHandler(this._templating.getEditInput(e)))},_onProgress:function(e,t,n,i){this._parent.prototype._onProgress.apply(this,arguments),this._templating.updateProgress(e,n,i),0===i||100===Math.round(n/i*100)?(this._templating.hideCancel(e),this._templating.hidePause(e),this._templating.hideProgress(e),this._templating.setStatusText(e,this._options.text.waitingForResponse),this._displayFileSize(e)):this._displayFileSize(e,n,i)},_onTotalProgress:function(e,t){this._parent.prototype._onTotalProgress.apply(this,arguments),this._templating.updateTotalProgress(e,t)},_onComplete:function(e,t,n,i){function o(t){s&&(a.setStatusText(e),qq(s).removeClass(l._classes.retrying),a.hideProgress(e),l.getUploads({id:e}).status!==qq.status.UPLOAD_FAILED&&a.hideCancel(e),a.hideSpinner(e),t.success?l._markFileAsSuccessful(e):(qq(s).addClass(l._classes.fail),a.showCancel(e),a.isRetryPossible()&&!l._preventRetries[e]&&(qq(s).addClass(l._classes.retryable),a.showRetry(e)),l._controlFailureTextDisplay(e,t)))}var r=this._parent.prototype._onComplete.apply(this,arguments),a=this._templating,s=a.getFileContainer(e),l=this;return r instanceof qq.Promise?r.done(function(e){o(e)}):o(n),r},_markFileAsSuccessful:function(e){var t=this._templating;this._isDeletePossible()&&t.showDeleteButton(e),qq(t.getFileContainer(e)).addClass(this._classes.success),this._maybeUpdateThumbnail(e)},_onUploadPrep:function(e){this._parent.prototype._onUploadPrep.apply(this,arguments),this._templating.showSpinner(e)},_onUpload:function(e,t){var n=this._parent.prototype._onUpload.apply(this,arguments);return this._templating.showSpinner(e),n},_onUploadChunk:function(e,t){this._parent.prototype._onUploadChunk.apply(this,arguments),t.partIndex>0&&this._handler.isResumable(e)&&this._templating.allowPause(e)},_onCancel:function(e,t){this._parent.prototype._onCancel.apply(this,arguments),this._removeFileItem(e),0===this._getNotFinished()&&this._templating.resetTotalProgress()},_onBeforeAutoRetry:function(e){var t,n,i;this._parent.prototype._onBeforeAutoRetry.apply(this,arguments),this._showCancelLink(e),this._options.retry.showAutoRetryNote&&(t=this._autoRetries[e],n=this._options.retry.maxAutoAttempts,i=this._options.retry.autoRetryNote.replace(/\{retryNum\}/g,t),i=i.replace(/\{maxAuto\}/g,n),this._templating.setStatusText(e,i),qq(this._templating.getFileContainer(e)).addClass(this._classes.retrying))},_onBeforeManualRetry:function(e){return this._parent.prototype._onBeforeManualRetry.apply(this,arguments)?(this._templating.resetProgress(e),qq(this._templating.getFileContainer(e)).removeClass(this._classes.fail),this._templating.setStatusText(e),this._templating.showSpinner(e),this._showCancelLink(e),!0):(qq(this._templating.getFileContainer(e)).addClass(this._classes.retryable),this._templating.showRetry(e),!1)},_onSubmitDelete:function(e){var t=qq.bind(this._onSubmitDeleteSuccess,this);this._parent.prototype._onSubmitDelete.call(this,e,t)},_onSubmitDeleteSuccess:function(e,t,n){this._options.deleteFile.forceConfirm?this._showDeleteConfirm.apply(this,arguments):this._sendDeleteRequest.apply(this,arguments)},_onDeleteComplete:function(e,t,n){this._parent.prototype._onDeleteComplete.apply(this,arguments),this._templating.hideSpinner(e),n?(this._templating.setStatusText(e,this._options.deleteFile.deletingFailedText),this._templating.showDeleteButton(e)):this._removeFileItem(e)},_sendDeleteRequest:function(e,t,n){this._templating.hideDeleteButton(e),this._templating.showSpinner(e),this._templating.setStatusText(e,this._options.deleteFile.deletingStatusText),this._deleteHandler.sendDelete.apply(this,arguments)},_showDeleteConfirm:function(e,t,n){var i,o=this.getName(e),r=this._options.deleteFile.confirmMessage.replace(/\{filename\}/g,o),a=(this.getUuid(e),arguments),s=this;i=this._options.showConfirm(r),qq.isGenericPromise(i)?i.then(function(){s._sendDeleteRequest.apply(s,a)}):i!==!1&&s._sendDeleteRequest.apply(s,a)},_addToList:function(e,t,n){var i,o,r=0,a=this._handler.isProxied(e)&&this._options.scaling.hideScaled;this._options.display.prependFiles&&(this._totalFilesInBatch>1&&this._filesInBatchAddedToUi>0&&(r=this._filesInBatchAddedToUi-1),i={index:r}),n||(this._options.disableCancelForFormUploads&&!qq.supportedFeatures.ajaxUploading&&this._templating.disableCancel(),this._options.multiple||(o=this.getUploads({id:e}),this._handledProxyGroup=this._handledProxyGroup||o.proxyGroupId,o.proxyGroupId===this._handledProxyGroup&&o.proxyGroupId||(this._handler.cancelAll(),this._clearList(),this._handledProxyGroup=null))),n?(this._templating.addFileToCache(e,this._options.formatFileName(t),i,a),this._templating.updateThumbnail(e,this._thumbnailUrls[e],!0,this._options.thumbnails.customResizer)):(this._templating.addFile(e,this._options.formatFileName(t),i,a),this._templating.generatePreview(e,this.getFile(e),this._options.thumbnails.customResizer)),this._filesInBatchAddedToUi+=1,(n||this._options.display.fileSizeOnSubmit&&qq.supportedFeatures.ajaxUploading)&&this._displayFileSize(e)},_clearList:function(){this._templating.clearFiles(),this.clearStoredFiles()},_displayFileSize:function(e,t,n){var i=this.getSize(e),o=this._formatSize(i);i>=0&&(void 0!==t&&void 0!==n&&(o=this._formatProgress(t,n)),this._templating.updateSize(e,o))},_formatProgress:function(e,t){function n(e,t){i=i.replace(e,t)}var i=this._options.text.formatProgress;return n("{percent}",Math.round(e/t*100)),n("{total_size}",this._formatSize(t)),i},_controlFailureTextDisplay:function(e,t){var n,i,o;n=this._options.failedUploadTextDisplay.mode,i=this._options.failedUploadTextDisplay.responseProperty,"custom"===n?(o=t[i],o||(o=this._options.text.failUpload),this._templating.setStatusText(e,o),this._options.failedUploadTextDisplay.enableTooltip&&this._showTooltip(e,o)):"default"===n?this._templating.setStatusText(e,this._options.text.failUpload):"none"!==n&&this.log("failedUploadTextDisplay.mode value of '"+n+"' is not valid","warn")},_showTooltip:function(e,t){this._templating.getFileContainer(e).title=t},_showCancelLink:function(e){this._options.disableCancelForFormUploads&&!qq.supportedFeatures.ajaxUploading||this._templating.showCancel(e)},_itemError:function(e,t,n){var i=this._parent.prototype._itemError.apply(this,arguments);this._options.showMessage(i)},_batchError:function(e){this._parent.prototype._batchError.apply(this,arguments),this._options.showMessage(e)},_setupPastePrompt:function(){var e=this;this._options.callbacks.onPasteReceived=function(){var t=e._options.paste.namePromptMessage,n=e._options.paste.defaultName;return e._options.showPrompt(t,n)}},_fileOrBlobRejected:function(e,t){this._totalFilesInBatch-=1,this._parent.prototype._fileOrBlobRejected.apply(this,arguments)},_prepareItemsForUpload:function(e,t,n){this._totalFilesInBatch=e.length,this._filesInBatchAddedToUi=0,this._parent.prototype._prepareItemsForUpload.apply(this,arguments)},_maybeUpdateThumbnail:function(e){var t=this._thumbnailUrls[e],n=this.getUploads({id:e}).status;n===qq.status.DELETED||!t&&!this._options.thumbnails.placeholders.waitUntilResponse&&qq.supportedFeatures.imagePreviews||this._templating.updateThumbnail(e,t,this._options.thumbnails.customResizer)},_addCannedFile:function(e){var t=this._parent.prototype._addCannedFile.apply(this,arguments);return this._addToList(t,this.getName(t),!0),this._templating.hideSpinner(t),this._templating.hideCancel(t),this._markFileAsSuccessful(t),t},_setSize:function(e,t){this._parent.prototype._setSize.apply(this,arguments),this._templating.updateSize(e,this._formatSize(t))},_sessionRequestComplete:function(){this._templating.addCacheToDom(),this._parent.prototype._sessionRequestComplete.apply(this,arguments)}}}(),qq.FineUploader=function(e,t){"use strict";var n=this;this._parent=t?qq[t].FineUploaderBasic:qq.FineUploaderBasic,this._parent.apply(this,arguments),qq.extend(this._options,{element:null,button:null,listElement:null,dragAndDrop:{extraDropzones:[],reportDirectoryPaths:!1},text:{formatProgress:"{percent}% of {total_size}",failUpload:"Upload failed",waitingForResponse:"Processing...",paused:"Paused"},template:"qq-template",classes:{retrying:"qq-upload-retrying",retryable:"qq-upload-retryable",success:"qq-upload-success",fail:"qq-upload-fail",editable:"qq-editable",hide:"qq-hide",dropActive:"qq-upload-drop-area-active"},failedUploadTextDisplay:{mode:"default",responseProperty:"error",enableTooltip:!0},messages:{tooManyFilesError:"You may only drop one file",unsupportedBrowser:"Unrecoverable error - this browser does not permit file uploading of any kind."},retry:{showAutoRetryNote:!0,autoRetryNote:"Retrying {retryNum}/{maxAuto}..."},deleteFile:{forceConfirm:!1,confirmMessage:"Are you sure you want to delete {filename}?",deletingStatusText:"Deleting...",deletingFailedText:"Delete failed"},display:{fileSizeOnSubmit:!1,prependFiles:!1},paste:{promptForName:!1,namePromptMessage:"Please name this image"},thumbnails:{customResizer:null,maxCount:0,placeholders:{waitUntilResponse:!1,notAvailablePath:null,waitingPath:null},timeBetweenThumbs:750},scaling:{hideScaled:!1},showMessage:function(e){return n._templating.hasDialog("alert")?n._templating.showDialog("alert",e):void setTimeout(function(){window.alert(e)},0)},showConfirm:function(e){return n._templating.hasDialog("confirm")?n._templating.showDialog("confirm",e):window.confirm(e)},showPrompt:function(e,t){return n._templating.hasDialog("prompt")?n._templating.showDialog("prompt",e,t):window.prompt(e,t)}},!0),qq.extend(this._options,e,!0),this._templating=new qq.Templating({log:qq.bind(this.log,this),templateIdOrEl:this._options.template,containerEl:this._options.element,fileContainerEl:this._options.listElement,button:this._options.button,imageGenerator:this._imageGenerator,classes:{hide:this._options.classes.hide,editable:this._options.classes.editable},limits:{maxThumbs:this._options.thumbnails.maxCount,timeBetweenThumbs:this._options.thumbnails.timeBetweenThumbs},placeholders:{waitUntilUpdate:this._options.thumbnails.placeholders.waitUntilResponse,thumbnailNotAvailable:this._options.thumbnails.placeholders.notAvailablePath,waitingForThumbnail:this._options.thumbnails.placeholders.waitingPath},text:this._options.text}),this._options.workarounds.ios8SafariUploads&&qq.ios800()&&qq.iosSafari()?this._templating.renderFailure(this._options.messages.unsupportedBrowserIos8Safari):!qq.supportedFeatures.uploading||this._options.cors.expected&&!qq.supportedFeatures.uploadCors?this._templating.renderFailure(this._options.messages.unsupportedBrowser):(this._wrapCallbacks(),this._templating.render(),this._classes=this._options.classes,!this._options.button&&this._templating.getButton()&&(this._defaultButtonId=this._createUploadButton({element:this._templating.getButton(),title:this._options.text.fileInputTitle}).getButtonId()),this._setupClickAndEditEventHandlers(),qq.DragAndDrop&&qq.supportedFeatures.fileDrop&&(this._dnd=this._setupDragAndDrop()),this._options.paste.targetElement&&this._options.paste.promptForName&&(qq.PasteSupport?this._setupPastePrompt():this.log("Paste support module not found.","error")),this._totalFilesInBatch=0,this._filesInBatchAddedToUi=0)},qq.extend(qq.FineUploader.prototype,qq.basePublicApi),qq.extend(qq.FineUploader.prototype,qq.basePrivateApi),qq.extend(qq.FineUploader.prototype,qq.uiPublicApi),qq.extend(qq.FineUploader.prototype,qq.uiPrivateApi),qq.Templating=function(e){"use strict";var t,n,i,o,r,a,s,l,u="qq-file-id",c="qq-file-id-",d="qq-max-size",p="qq-server-scale",h="qq-hide-dropzone",f="qq-drop-area-text",q="qq-in-progress",m="qq-hidden-forever",g={content:document.createDocumentFragment(),map:{}},_=!1,v=0,b=!1,y=[],S=-1,w={log:null,limits:{maxThumbs:0,timeBetweenThumbs:750},templateIdOrEl:"qq-template",containerEl:null,fileContainerEl:null,button:null,imageGenerator:null,
-classes:{hide:"qq-hide",editable:"qq-editable"},placeholders:{waitUntilUpdate:!1,thumbnailNotAvailable:null,waitingForThumbnail:null},text:{paused:"Paused"}},F={button:"qq-upload-button-selector",alertDialog:"qq-alert-dialog-selector",dialogCancelButton:"qq-cancel-button-selector",confirmDialog:"qq-confirm-dialog-selector",dialogMessage:"qq-dialog-message-selector",dialogOkButton:"qq-ok-button-selector",promptDialog:"qq-prompt-dialog-selector",uploader:"qq-uploader-selector",drop:"qq-upload-drop-area-selector",list:"qq-upload-list-selector",progressBarContainer:"qq-progress-bar-container-selector",progressBar:"qq-progress-bar-selector",totalProgressBarContainer:"qq-total-progress-bar-container-selector",totalProgressBar:"qq-total-progress-bar-selector",file:"qq-upload-file-selector",spinner:"qq-upload-spinner-selector",size:"qq-upload-size-selector",cancel:"qq-upload-cancel-selector",pause:"qq-upload-pause-selector",continueButton:"qq-upload-continue-selector",deleteButton:"qq-upload-delete-selector",retry:"qq-upload-retry-selector",statusText:"qq-upload-status-text-selector",editFilenameInput:"qq-edit-filename-selector",editNameIcon:"qq-edit-filename-icon-selector",dropText:"qq-upload-drop-area-text-selector",dropProcessing:"qq-drop-processing-selector",dropProcessingSpinner:"qq-drop-processing-spinner-selector",thumbnail:"qq-thumbnail-selector"},x={},C=new qq.Promise,E=new qq.Promise,I=function(){var e=w.placeholders.thumbnailNotAvailable,n=w.placeholders.waitingForThumbnail,i={maxSize:S,scale:l};s&&(e?w.imageGenerator.generate(e,new Image,i).then(function(e){C.success(e)},function(){C.failure(),t("Problem loading 'not available' placeholder image at "+e,"error")}):C.failure(),n?w.imageGenerator.generate(n,new Image,i).then(function(e){E.success(e)},function(){E.failure(),t("Problem loading 'waiting for thumbnail' placeholder image at "+n,"error")}):E.failure())},P=function(e){var t=new qq.Promise;return E.then(function(n){Q(n,e),e.src?t.success():(e.src=n.src,e.onload=function(){e.onload=null,te(e),t.success()})},function(){W(e),t.success()}),t},D=function(e,n,i){var o=X(e);return t("Generating new thumbnail for "+e),n.qqThumbnailId=e,w.imageGenerator.generate(n,o,i).then(function(){v++,te(o),x[e].success()},function(){x[e].failure(),w.placeholders.waitUntilUpdate||Y(e,o)})},T=function(){if(y.length){b=!0;var e=y.shift();e.update?$(e):K(e)}else b=!1},U=function(e){return V(L(e),F.cancel)},k=function(e){return V(L(e),F.continueButton)},A=function(e){return V(r,F[e+"Dialog"])},R=function(e){return V(L(e),F.deleteButton)},B=function(){return V(r,F.dropProcessing)},N=function(e){return V(L(e),F.editNameIcon)},L=function(e){return g.map[e]||qq(a).getFirstByClass(c+e)},O=function(e){return V(L(e),F.file)},H=function(e){return V(L(e),F.pause)},z=function(e){return null==e?V(r,F.totalProgressBarContainer)||V(r,F.totalProgressBar):V(L(e),F.progressBarContainer)||V(L(e),F.progressBar)},M=function(e){return V(L(e),F.retry)},j=function(e){return V(L(e),F.size)},G=function(e){return V(L(e),F.spinner)},V=function(e,t){return e&&qq(e).getFirstByClass(t)},X=function(e){return s&&V(L(e),F.thumbnail)},W=function(e){e&&qq(e).addClass(w.classes.hide)},Q=function(e,t){var n=e.style.maxWidth,i=e.style.maxHeight;i&&n&&!t.style.maxWidth&&!t.style.maxHeight&&qq(t).css({maxWidth:n,maxHeight:i})},Y=function(e,t){var n=x[e]||(new qq.Promise).failure(),i=new qq.Promise;return C.then(function(e){n.then(function(){i.success()},function(){Q(e,t),t.onload=function(){t.onload=null,i.success()},t.src=e.src,te(t)})}),i},J=function(){var e,o,r,a,u,c,q,m,g,_,v;if(t("Parsing template"),null==w.templateIdOrEl)throw new Error("You MUST specify either a template element or ID!");if(qq.isString(w.templateIdOrEl)){if(e=document.getElementById(w.templateIdOrEl),null===e)throw new Error(qq.format("Cannot find template script at ID '{}'!",w.templateIdOrEl));o=e.innerHTML}else{if(void 0===w.templateIdOrEl.innerHTML)throw new Error("You have specified an invalid value for the template option! It must be an ID or an Element.");o=w.templateIdOrEl.innerHTML}if(o=qq.trimStr(o),a=document.createElement("div"),a.appendChild(qq.toElement(o)),v=qq(a).getFirstByClass(F.uploader),w.button&&(c=qq(a).getFirstByClass(F.button),c&&qq(c).remove()),qq.DragAndDrop&&qq.supportedFeatures.fileDrop||(g=qq(a).getFirstByClass(F.dropProcessing),g&&qq(g).remove()),q=qq(a).getFirstByClass(F.drop),q&&!qq.DragAndDrop&&(t("DnD module unavailable.","info"),qq(q).remove()),qq.supportedFeatures.fileDrop?qq(v).hasAttribute(f)&&q&&(_=qq(q).getFirstByClass(F.dropText),_&&qq(_).remove()):(v.removeAttribute(f),q&&qq(q).hasAttribute(h)&&qq(q).css({display:"none"})),m=qq(a).getFirstByClass(F.thumbnail),s?m&&(S=parseInt(m.getAttribute(d)),S=S>0?S:null,l=qq(m).hasAttribute(p)):m&&qq(m).remove(),s=s&&m,n=qq(a).getByClass(F.editFilenameInput).length>0,i=qq(a).getByClass(F.retry).length>0,r=qq(a).getFirstByClass(F.list),null==r)throw new Error("Could not find the file list container in the template!");return u=r.innerHTML,r.innerHTML="",a.getElementsByTagName("DIALOG").length&&document.createElement("dialog"),t("Template parsing complete"),{template:qq.trimStr(a.innerHTML),fileTemplate:qq.trimStr(u)}},Z=function(e,t,n){var i=n,o=i.firstChild;t>0&&(o=qq(i).children()[t].nextSibling),i.insertBefore(e,o)},K=function(e){var t=e.id,n=e.optFileOrBlob,i=n&&n.qqThumbnailId,o=X(t),r={customResizeFunction:e.customResizeFunction,maxSize:S,orient:!0,scale:!0};qq.supportedFeatures.imagePreviews?o?w.limits.maxThumbs&&w.limits.maxThumbs<=v?(Y(t,o),T()):P(o).done(function(){x[t]=new qq.Promise,x[t].done(function(){setTimeout(T,w.limits.timeBetweenThumbs)}),null!=i?ne(t,i):D(t,n,r)}):T():o&&(P(o),T())},$=function(e){var t=e.id,n=e.thumbnailUrl,i=e.showWaitingImg,o=X(t),r={customResizeFunction:e.customResizeFunction,scale:l,maxSize:S};if(o)if(n){if(!(w.limits.maxThumbs&&w.limits.maxThumbs<=v))return i&&P(o),w.imageGenerator.generate(n,o,r).then(function(){te(o),v++,setTimeout(T,w.limits.timeBetweenThumbs)},function(){Y(t,o),setTimeout(T,w.limits.timeBetweenThumbs)});Y(t,o),T()}else Y(t,o),T()},ee=function(e,t){var n=z(e),i=null==e?F.totalProgressBar:F.progressBar;n&&!qq(n).hasClass(i)&&(n=qq(n).getFirstByClass(i)),n&&(qq(n).css({width:t+"%"}),n.setAttribute("aria-valuenow",t))},te=function(e){e&&qq(e).removeClass(w.classes.hide)},ne=function(e,n){var i=X(e),o=X(n);t(qq.format("ID {} is the same file as ID {}. Will use generated thumbnail from ID {} instead.",e,n,n)),x[n].then(function(){v++,x[e].success(),t(qq.format("Now using previously generated thumbnail created for ID {} on ID {}.",n,e)),i.src=o.src,te(i)},function(){x[e].failure(),w.placeholders.waitUntilUpdate||Y(e,i)})};qq.extend(w,e),t=w.log,qq.supportedFeatures.imagePreviews||(w.limits.timeBetweenThumbs=0,w.limits.maxThumbs=0),r=w.containerEl,s=void 0!==w.imageGenerator,o=J(),I(),qq.extend(this,{render:function(){t("Rendering template in DOM."),v=0,r.innerHTML=o.template,W(B()),this.hideTotalProgress(),a=w.fileContainerEl||V(r,F.list),t("Template rendering complete")},renderFailure:function(e){var t=qq.toElement(e);r.innerHTML="",r.appendChild(t)},reset:function(){this.render()},clearFiles:function(){a.innerHTML=""},disableCancel:function(){_=!0},addFile:function(e,t,n,i,s){var l,d=qq.toElement(o.fileTemplate),p=V(d,F.file),h=V(r,F.uploader),q=s?g.content:a;s&&(g.map[e]=d),qq(d).addClass(c+e),h.removeAttribute(f),p&&(qq(p).setText(t),p.setAttribute("title",t)),d.setAttribute(u,e),n?Z(d,n.index,q):q.appendChild(d),i?(d.style.display="none",qq(d).addClass(m)):(W(z(e)),W(j(e)),W(R(e)),W(M(e)),W(H(e)),W(k(e)),_&&this.hideCancel(e),l=X(e),l&&!l.src&&E.then(function(e){l.src=e.src,e.style.maxHeight&&e.style.maxWidth&&qq(l).css({maxHeight:e.style.maxHeight,maxWidth:e.style.maxWidth}),te(l)}))},addFileToCache:function(e,t,n,i){this.addFile(e,t,n,i,!0)},addCacheToDom:function(){a.appendChild(g.content),g.content=document.createDocumentFragment(),g.map={}},removeFile:function(e){qq(L(e)).remove()},getFileId:function(e){var t=e;if(t){for(;null==t.getAttribute(u);)t=t.parentNode;return parseInt(t.getAttribute(u))}},getFileList:function(){return a},markFilenameEditable:function(e){var t=O(e);t&&qq(t).addClass(w.classes.editable)},updateFilename:function(e,t){var n=O(e);n&&(qq(n).setText(t),n.setAttribute("title",t))},hideFilename:function(e){W(O(e))},showFilename:function(e){te(O(e))},isFileName:function(e){return qq(e).hasClass(F.file)},getButton:function(){return w.button||V(r,F.button)},hideDropProcessing:function(){W(B())},showDropProcessing:function(){te(B())},getDropZone:function(){return V(r,F.drop)},isEditFilenamePossible:function(){return n},hideRetry:function(e){W(M(e))},isRetryPossible:function(){return i},showRetry:function(e){te(M(e))},getFileContainer:function(e){return L(e)},showEditIcon:function(e){var t=N(e);t&&qq(t).addClass(w.classes.editable)},isHiddenForever:function(e){return qq(L(e)).hasClass(m)},hideEditIcon:function(e){var t=N(e);t&&qq(t).removeClass(w.classes.editable)},isEditIcon:function(e){return qq(e).hasClass(F.editNameIcon,!0)},getEditInput:function(e){return V(L(e),F.editFilenameInput)},isEditInput:function(e){return qq(e).hasClass(F.editFilenameInput,!0)},updateProgress:function(e,t,n){var i,o=z(e);o&&n>0&&(i=Math.round(t/n*100),100===i?W(o):te(o),ee(e,i))},updateTotalProgress:function(e,t){this.updateProgress(null,e,t)},hideProgress:function(e){var t=z(e);t&&W(t)},hideTotalProgress:function(){this.hideProgress()},resetProgress:function(e){ee(e,0),this.hideTotalProgress(e)},resetTotalProgress:function(){this.resetProgress()},showCancel:function(e){if(!_){var t=U(e);t&&qq(t).removeClass(w.classes.hide)}},hideCancel:function(e){W(U(e))},isCancel:function(e){return qq(e).hasClass(F.cancel,!0)},allowPause:function(e){te(H(e)),W(k(e))},uploadPaused:function(e){this.setStatusText(e,w.text.paused),this.allowContinueButton(e),W(G(e))},hidePause:function(e){W(H(e))},isPause:function(e){return qq(e).hasClass(F.pause,!0)},isContinueButton:function(e){return qq(e).hasClass(F.continueButton,!0)},allowContinueButton:function(e){te(k(e)),W(H(e))},uploadContinued:function(e){this.setStatusText(e,""),this.allowPause(e),te(G(e))},showDeleteButton:function(e){te(R(e))},hideDeleteButton:function(e){W(R(e))},isDeleteButton:function(e){return qq(e).hasClass(F.deleteButton,!0)},isRetry:function(e){return qq(e).hasClass(F.retry,!0)},updateSize:function(e,t){var n=j(e);n&&(te(n),qq(n).setText(t))},setStatusText:function(e,t){var n=V(L(e),F.statusText);n&&(null==t?qq(n).clearText():qq(n).setText(t))},hideSpinner:function(e){qq(L(e)).removeClass(q),W(G(e))},showSpinner:function(e){qq(L(e)).addClass(q),te(G(e))},generatePreview:function(e,t,n){this.isHiddenForever(e)||(y.push({id:e,customResizeFunction:n,optFileOrBlob:t}),!b&&T())},updateThumbnail:function(e,t,n,i){this.isHiddenForever(e)||(y.push({customResizeFunction:i,update:!0,id:e,thumbnailUrl:t,showWaitingImg:n}),!b&&T())},hasDialog:function(e){return qq.supportedFeatures.dialogElement&&!!A(e)},showDialog:function(e,t,n){var i=A(e),o=V(i,F.dialogMessage),r=i.getElementsByTagName("INPUT")[0],a=V(i,F.dialogCancelButton),s=V(i,F.dialogOkButton),l=new qq.Promise,u=function(){a.removeEventListener("click",c),s&&s.removeEventListener("click",d),l.failure()},c=function(){a.removeEventListener("click",c),i.close()},d=function(){i.removeEventListener("close",u),s.removeEventListener("click",d),i.close(),l.success(r&&r.value)};return i.addEventListener("close",u),a.addEventListener("click",c),s&&s.addEventListener("click",d),r&&(r.value=n),o.textContent=t,i.showModal(),l}})},qq.UiEventHandler=function(e,t){"use strict";function n(e){i.attach(e,o.eventType,function(e){e=e||window.event;var t=e.target||e.srcElement;o.onHandled(t,e)})}var i=new qq.DisposeSupport,o={eventType:"click",attachTo:null,onHandled:function(e,t){}};qq.extend(this,{addHandler:function(e){n(e)},dispose:function(){i.dispose()}}),qq.extend(t,{getFileIdFromItem:function(e){return e.qqFileId},getDisposeSupport:function(){return i}}),qq.extend(o,e),o.attachTo&&n(o.attachTo)},qq.FileButtonsClickHandler=function(e){"use strict";function t(e,t){qq.each(o,function(n,o){var r,a=n.charAt(0).toUpperCase()+n.slice(1);if(i.templating["is"+a](e))return r=i.templating.getFileId(e),qq.preventDefault(t),i.log(qq.format("Detected valid file button click event on file '{}', ID: {}.",i.onGetName(r),r)),o(r),!1})}var n={},i={templating:null,log:function(e,t){},onDeleteFile:function(e){},onCancel:function(e){},onRetry:function(e){},onPause:function(e){},onContinue:function(e){},onGetName:function(e){}},o={cancel:function(e){i.onCancel(e)},retry:function(e){i.onRetry(e)},deleteButton:function(e){i.onDeleteFile(e)},pause:function(e){i.onPause(e)},continueButton:function(e){i.onContinue(e)}};qq.extend(i,e),i.eventType="click",i.onHandled=t,i.attachTo=i.templating.getFileList(),qq.extend(this,new qq.UiEventHandler(i,n))},qq.FilenameClickHandler=function(e){"use strict";function t(e,t){if(i.templating.isFileName(e)||i.templating.isEditIcon(e)){var o=i.templating.getFileId(e),r=i.onGetUploadStatus(o);r===qq.status.SUBMITTED&&(i.log(qq.format("Detected valid filename click event on file '{}', ID: {}.",i.onGetName(o),o)),qq.preventDefault(t),n.handleFilenameEdit(o,e,!0))}}var n={},i={templating:null,log:function(e,t){},classes:{file:"qq-upload-file",editNameIcon:"qq-edit-filename-icon"},onGetUploadStatus:function(e){},onGetName:function(e){}};qq.extend(i,e),i.eventType="click",i.onHandled=t,qq.extend(this,new qq.FilenameEditHandler(i,n))},qq.FilenameInputFocusInHandler=function(e,t){"use strict";function n(e,n){if(i.templating.isEditInput(e)){var o=i.templating.getFileId(e),r=i.onGetUploadStatus(o);r===qq.status.SUBMITTED&&(i.log(qq.format("Detected valid filename input focus event on file '{}', ID: {}.",i.onGetName(o),o)),t.handleFilenameEdit(o,e))}}var i={templating:null,onGetUploadStatus:function(e){},log:function(e,t){}};t||(t={}),i.eventType="focusin",i.onHandled=n,qq.extend(i,e),qq.extend(this,new qq.FilenameEditHandler(i,t))},qq.FilenameInputFocusHandler=function(e){"use strict";e.eventType="focus",e.attachTo=null,qq.extend(this,new qq.FilenameInputFocusInHandler(e,{}))},qq.FilenameEditHandler=function(e,t){"use strict";function n(e){var t=s.onGetName(e),n=t.lastIndexOf(".");return n>0&&(t=t.substr(0,n)),t}function i(e){var t=s.onGetName(e);return qq.getExtension(t)}function o(e,t){var n,o=e.value;void 0!==o&&qq.trimStr(o).length>0&&(n=i(t),void 0!==n&&(o=o+"."+n),s.onSetName(t,o)),s.onEditingStatusChange(t,!1)}function r(e,n){t.getDisposeSupport().attach(e,"blur",function(){o(e,n)})}function a(e,n){t.getDisposeSupport().attach(e,"keyup",function(t){var i=t.keyCode||t.which;13===i&&o(e,n)})}var s={templating:null,log:function(e,t){},onGetUploadStatus:function(e){},onGetName:function(e){},onSetName:function(e,t){},onEditingStatusChange:function(e,t){}};qq.extend(s,e),s.attachTo=s.templating.getFileList(),qq.extend(this,new qq.UiEventHandler(s,t)),qq.extend(t,{handleFilenameEdit:function(e,t,i){var o=s.templating.getEditInput(e);s.onEditingStatusChange(e,!0),o.value=n(e),i&&o.focus(),r(o,e),a(o,e)}})}}(window);
+// Fine Uploader 5.16.2 - MIT licensed. http://fineuploader.com
+!function(global){!function(e){"use strict";function t(e){var t=s(e||{}),i=n(t);return o(i),a(t,i),d}function n(e){var t=r("uploaderType"),n=r("endpointType");return t?(t=t.charAt(0).toUpperCase()+t.slice(1).toLowerCase(),n?new qq[n]["FineUploader"+t](e):new qq["FineUploader"+t](e)):n?new qq[n].FineUploader(e):new qq.FineUploader(e)}function i(e,t){var n=d.data("fineuploader");if(!t)return void 0===n?null:n[e];void 0===n&&(n={}),n[e]=t,d.data("fineuploader",n)}function o(e){return i("uploader",e)}function r(e,t){return i(e,t)}function a(t,n){var i=t.callbacks={};e.each(n._options.callbacks,function(t,n){var o,r;o=/^on(\w+)/.exec(t)[1],o=o.substring(0,1).toLowerCase()+o.substring(1),r=d,i[t]=function(){var t,i,a=Array.prototype.slice.call(arguments),s=[];e.each(a,function(e,t){s.push(c(t))}),t=n.apply(this,a);try{i=r.triggerHandler(o,s)}catch(e){qq.log("Caught error in Fine Uploader jQuery event handler: "+e.message,"error")}return null!=t?t:i}}),n._options.callbacks=i}function s(t,n){var i,o;if(i=void 0===n?"basic"!==t.uploaderType?{element:d[0]}:{}:n,e.each(t,function(t,n){e.inArray(t,p)>=0?r(t,n):n instanceof e?i[t]=n[0]:e.isPlainObject(n)?(i[t]={},s(n,i[t])):e.isArray(n)?(o=[],e.each(n,function(t,n){var i={};n instanceof e?e.merge(o,n):e.isPlainObject(n)?(s(n,i),o.push(i)):o.push(n)}),i[t]=o):i[t]=n}),void 0===n)return i}function u(t){return"string"===e.type(t)&&!t.match(/^_/)&&void 0!==o()[t]}function l(e){var t,n=[],i=Array.prototype.slice.call(arguments,1);return s(i,n),t=o()[e].apply(o(),n),c(t)}function c(t){var n=t;return null==t||"object"!=typeof t||1!==t.nodeType&&9!==t.nodeType||!t.cloneNode||(n=e(t)),n}var d,p=["uploaderType","endpointType"];e.fn.fineUploader=function(n){var i=this,r=arguments,a=[];return this.each(function(s,c){if(d=e(c),o()&&u(n)){if(a.push(l.apply(i,r)),1===i.length)return!1}else"object"!=typeof n&&n?e.error("Method "+n+" does not exist on jQuery.fineUploader"):t.apply(i,r)}),1===a.length?a[0]:a.length>1?a:this}}(jQuery),function(e){"use strict";function t(e){e||(e={}),e.dropZoneElements=[u];var t=r(e);return o(t),i(new qq.DragAndDrop(t)),u}function n(e,t){var n=u.data("fineUploaderDnd");if(!t)return void 0===n?null:n[e];void 0===n&&(n={}),n[e]=t,u.data("fineUploaderDnd",n)}function i(e){return n("dndInstance",e)}function o(t){var n=t.callbacks={};e.each(new qq.DragAndDrop.callbacks,function(e,t){var i,o=e;i=u,n[e]=function(){var e=Array.prototype.slice.call(arguments);return i.triggerHandler(o,e)}})}function r(t,n){var i,o;if(i=void 0===n?{}:n,e.each(t,function(t,n){n instanceof e?i[t]=n[0]:e.isPlainObject(n)?(i[t]={},r(n,i[t])):e.isArray(n)?(o=[],e.each(n,function(t,n){n instanceof e?e.merge(o,n):o.push(n)}),i[t]=o):i[t]=n}),void 0===n)return i}function a(t){return"string"===e.type(t)&&"dispose"===t&&void 0!==i()[t]}function s(e){var t=[];return r(Array.prototype.slice.call(arguments,1),t),i()[e].apply(i(),t)}var u;e.fn.fineUploaderDnd=function(n){var o=this,r=arguments,l=[];return this.each(function(c,d){if(u=e(d),i()&&a(n)){if(l.push(s.apply(o,r)),1===o.length)return!1}else"object"!=typeof n&&n?e.error("Method "+n+" does not exist in Fine Uploader's DnD module."):t.apply(o,r)}),1===l.length?l[0]:l.length>1?l:this}}(jQuery);var qq=function(e){"use strict";return{hide:function(){return e.style.display="none",this},attach:function(t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent&&e.attachEvent("on"+t,n),function(){qq(e).detach(t,n)}},detach:function(t,n){return e.removeEventListener?e.removeEventListener(t,n,!1):e.attachEvent&&e.detachEvent("on"+t,n),this},contains:function(t){return!!t&&(e===t||(e.contains?e.contains(t):!!(8&t.compareDocumentPosition(e))))},insertBefore:function(t){return t.parentNode.insertBefore(e,t),this},remove:function(){return e.parentNode.removeChild(e),this},css:function(t){if(null==e.style)throw new qq.Error("Can't apply style to node as it is not on the HTMLElement prototype chain!");return null!=t.opacity&&"string"!=typeof e.style.opacity&&void 0!==e.filters&&(t.filter="alpha(opacity="+Math.round(100*t.opacity)+")"),qq.extend(e.style,t),this},hasClass:function(t,n){var i=new RegExp("(^| )"+t+"( |$)");return i.test(e.className)||!(!n||!i.test(e.parentNode.className))},addClass:function(t){return qq(e).hasClass(t)||(e.className+=" "+t),this},removeClass:function(t){var n=new RegExp("(^| )"+t+"( |$)");return e.className=e.className.replace(n," ").replace(/^\s+|\s+$/g,""),this},getByClass:function(t,n){var i,o=[];return n&&e.querySelector?e.querySelector("."+t):e.querySelectorAll?e.querySelectorAll("."+t):(i=e.getElementsByTagName("*"),qq.each(i,function(e,n){qq(n).hasClass(t)&&o.push(n)}),n?o[0]:o)},getFirstByClass:function(t){return qq(e).getByClass(t,!0)},children:function(){for(var t=[],n=e.firstChild;n;)1===n.nodeType&&t.push(n),n=n.nextSibling;return t},setText:function(t){return e.innerText=t,e.textContent=t,this},clearText:function(){return qq(e).setText("")},hasAttribute:function(t){var n;return e.hasAttribute?!!e.hasAttribute(t)&&null==/^false$/i.exec(e.getAttribute(t)):(n=e[t],void 0!==n&&null==/^false$/i.exec(n))}}};!function(){"use strict";qq.canvasToBlob=function(e,t,n){return qq.dataUriToBlob(e.toDataURL(t,n))},qq.dataUriToBlob=function(e){var t,n,i,o,r=function(e,t){var n=window.BlobBuilder||window.WebKitBlobBuilder||window.MozBlobBuilder||window.MSBlobBuilder,i=n&&new n;return i?(i.append(e),i.getBlob(t)):new Blob([e],{type:t})};return n=e.split(",")[0].indexOf("base64")>=0?atob(e.split(",")[1]):decodeURI(e.split(",")[1]),o=e.split(",")[0].split(":")[1].split(";")[0],t=new ArrayBuffer(n.length),i=new Uint8Array(t),qq.each(n,function(e,t){i[e]=t.charCodeAt(0)}),r(t,o)},qq.log=function(e,t){window.console&&(t&&"info"!==t?window.console[t]?window.console[t](e):window.console.log("<"+t+"> "+e):window.console.log(e))},qq.isObject=function(e){return e&&!e.nodeType&&"[object Object]"===Object.prototype.toString.call(e)},qq.isFunction=function(e){return"function"==typeof e},qq.isArray=function(e){return"[object Array]"===Object.prototype.toString.call(e)||e&&window.ArrayBuffer&&e.buffer&&e.buffer.constructor===ArrayBuffer},qq.isItemList=function(e){return"[object DataTransferItemList]"===Object.prototype.toString.call(e)},qq.isNodeList=function(e){return"[object NodeList]"===Object.prototype.toString.call(e)||e.item&&e.namedItem},qq.isString=function(e){return"[object String]"===Object.prototype.toString.call(e)},qq.trimStr=function(e){return String.prototype.trim?e.trim():e.replace(/^\s+|\s+$/g,"")},qq.format=function(e){var t=Array.prototype.slice.call(arguments,1),n=e,i=n.indexOf("{}");return qq.each(t,function(e,t){if(n=n.substring(0,i)+t+n.substring(i+2),i=n.indexOf("{}",i+t.length),i<0)return!1}),n},qq.isFile=function(e){return window.File&&"[object File]"===Object.prototype.toString.call(e)},qq.isFileList=function(e){return window.FileList&&"[object FileList]"===Object.prototype.toString.call(e)},qq.isFileOrInput=function(e){return qq.isFile(e)||qq.isInput(e)},qq.isInput=function(e,t){var n=function(e){var n=e.toLowerCase();return t?"file"!==n:"file"===n};return!!(window.HTMLInputElement&&"[object HTMLInputElement]"===Object.prototype.toString.call(e)&&e.type&&n(e.type))||!!(e.tagName&&"input"===e.tagName.toLowerCase()&&e.type&&n(e.type))},qq.isBlob=function(e){if(window.Blob&&"[object Blob]"===Object.prototype.toString.call(e))return!0},qq.isXhrUploadSupported=function(){var e=document.createElement("input");return e.type="file",void 0!==e.multiple&&"undefined"!=typeof File&&"undefined"!=typeof FormData&&void 0!==qq.createXhrInstance().upload},qq.createXhrInstance=function(){if(window.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(e){return qq.log("Neither XHR or ActiveX are supported!","error"),null}},qq.isFolderDropSupported=function(e){return e.items&&e.items.length>0&&e.items[0].webkitGetAsEntry},qq.isFileChunkingSupported=function(){return!qq.androidStock()&&qq.isXhrUploadSupported()&&(void 0!==File.prototype.slice||void 0!==File.prototype.webkitSlice||void 0!==File.prototype.mozSlice)},qq.sliceBlob=function(e,t,n){return(e.slice||e.mozSlice||e.webkitSlice).call(e,t,n)},qq.arrayBufferToHex=function(e){var t="",n=new Uint8Array(e);return qq.each(n,function(e,n){var i=n.toString(16);i.length<2&&(i="0"+i),t+=i}),t},qq.readBlobToHex=function(e,t,n){var i=qq.sliceBlob(e,t,t+n),o=new FileReader,r=new qq.Promise;return o.onload=function(){r.success(qq.arrayBufferToHex(o.result))},o.onerror=r.failure,o.readAsArrayBuffer(i),r},qq.extend=function(e,t,n){return qq.each(t,function(t,i){n&&qq.isObject(i)?(void 0===e[t]&&(e[t]={}),qq.extend(e[t],i,!0)):e[t]=i}),e},qq.override=function(e,t){var n={},i=t(n);return qq.each(i,function(t,i){void 0!==e[t]&&(n[t]=e[t]),e[t]=i}),e},qq.indexOf=function(e,t,n){if(e.indexOf)return e.indexOf(t,n);n=n||0;var i=e.length;for(n<0&&(n+=i);n=0},qq.safari=function(){return void 0!==navigator.vendor&&navigator.vendor.indexOf("Apple")!==-1},qq.chrome=function(){return void 0!==navigator.vendor&&navigator.vendor.indexOf("Google")!==-1},qq.opera=function(){return void 0!==navigator.vendor&&navigator.vendor.indexOf("Opera")!==-1},qq.firefox=function(){return!qq.edge()&&!qq.ie11()&&navigator.userAgent.indexOf("Mozilla")!==-1&&void 0!==navigator.vendor&&""===navigator.vendor},qq.windows=function(){return"Win32"===navigator.platform},qq.android=function(){return navigator.userAgent.toLowerCase().indexOf("android")!==-1},qq.androidStock=function(){return qq.android()&&navigator.userAgent.toLowerCase().indexOf("chrome")<0},qq.ios6=function(){return qq.ios()&&navigator.userAgent.indexOf(" OS 6_")!==-1},qq.ios7=function(){return qq.ios()&&navigator.userAgent.indexOf(" OS 7_")!==-1},qq.ios8=function(){return qq.ios()&&navigator.userAgent.indexOf(" OS 8_")!==-1},qq.ios800=function(){return qq.ios()&&navigator.userAgent.indexOf(" OS 8_0 ")!==-1},qq.ios=function(){return navigator.userAgent.indexOf("iPad")!==-1||navigator.userAgent.indexOf("iPod")!==-1||navigator.userAgent.indexOf("iPhone")!==-1},qq.iosChrome=function(){return qq.ios()&&navigator.userAgent.indexOf("CriOS")!==-1},qq.iosSafari=function(){return qq.ios()&&!qq.iosChrome()&&navigator.userAgent.indexOf("Safari")!==-1},qq.iosSafariWebView=function(){return qq.ios()&&!qq.iosChrome()&&!qq.iosSafari()},qq.preventDefault=function(e){e.preventDefault?e.preventDefault():e.returnValue=!1},qq.toElement=function(){var e=document.createElement("div");return function(t){e.innerHTML=t;var n=e.firstChild;return e.removeChild(n),n}}(),qq.each=function(e,t){var n,i;if(e)if(window.Storage&&e.constructor===window.Storage)for(n=0;n0)return e.substr(t,e.length-t)},qq.getFilename=function(e){return qq.isInput(e)?e.value.replace(/.*(\/|\\)/,""):qq.isFile(e)&&null!==e.fileName&&void 0!==e.fileName?e.fileName:e.name},qq.DisposeSupport=function(){var e=[];return{dispose:function(){var t;do t=e.shift(),t&&t();while(t)},attach:function(){var e=arguments;this.addDisposer(qq(e[0]).attach.apply(this,Array.prototype.slice.call(arguments,1)))},addDisposer:function(t){e.push(t)}}}}(),function(){"use strict";"function"==typeof define&&define.amd?define(function(){return qq}):"undefined"!=typeof module&&module.exports?module.exports=qq:global.qq=qq}(),function(){"use strict";qq.Error=function(e){this.message="[Fine Uploader "+qq.version+"] "+e},qq.Error.prototype=new Error}(),qq.version="5.16.2",qq.supportedFeatures=function(){"use strict";function e(){var e,t=!0;try{e=document.createElement("input"),e.type="file",qq(e).hide(),e.disabled&&(t=!1)}catch(e){t=!1}return t}function t(){return(qq.chrome()||qq.opera())&&void 0!==navigator.userAgent.match(/Chrome\/[1][4-9]|Chrome\/[2-9][0-9]/)}function n(){if(window.XMLHttpRequest){return void 0!==qq.createXhrInstance().withCredentials}return!1}function i(){return void 0!==window.XDomainRequest}function o(){return!!n()||i()}function r(){return void 0!==document.createElement("input").webkitdirectory}function a(){try{return!!window.localStorage&&qq.isFunction(window.localStorage.setItem)}catch(e){return!1}}function s(){var e=document.createElement("span");return("draggable"in e||"ondragstart"in e&&"ondrop"in e)&&!qq.android()&&!qq.ios()}var u,l,c,d,p,h,f,q,m,g,_,v,b,y,S;return u=e(),d=u&&qq.isXhrUploadSupported(),l=d&&!qq.androidStock(),c=d&&s(),p=c&&function(){var e=document.createElement("input");return e.type="file",!!("webkitdirectory"in(e||document.querySelectorAll("input[type=file]")[0]))}(),h=d&&qq.isFileChunkingSupported(),f=d&&h&&a(),q=d&&t(),m=u&&(void 0!==window.postMessage||d),_=n(),g=i(),v=o(),b=r(),y=d&&void 0!==window.FileReader,S=function(){return!!d&&(!qq.androidStock()&&!qq.iosChrome())}(),{ajaxUploading:d,blobUploading:l,canDetermineSize:d,chunking:h,deleteFileCors:v,deleteFileCorsXdr:g,deleteFileCorsXhr:_,dialogElement:!!window.HTMLDialogElement,fileDrop:c,folderDrop:p,folderSelection:b,imagePreviews:y,imageValidation:y,itemSizeValidation:d,pause:h,progressBar:S,resume:f,scaling:y&&l,tiffPreviews:qq.safari(),unlimitedScaledImageSize:!qq.ios(),uploading:u,uploadCors:m,uploadCustomHeaders:d,uploadNonMultipart:d,uploadViaPaste:q}}(),qq.isGenericPromise=function(e){"use strict";return!!(e&&e.then&&qq.isFunction(e.then))},qq.Promise=function(){"use strict";var e,t,n=[],i=[],o=[],r=0;qq.extend(this,{then:function(o,a){return 0===r?(o&&n.push(o),a&&i.push(a)):r===-1?a&&a.apply(null,t):o&&o.apply(null,e),this},done:function(n){return 0===r?o.push(n):n.apply(null,void 0===t?e:t),this},success:function(){return r=1,e=arguments,n.length&&qq.each(n,function(t,n){n.apply(null,e)}),o.length&&qq.each(o,function(t,n){n.apply(null,e)}),this},failure:function(){return r=-1,t=arguments,i.length&&qq.each(i,function(e,n){n.apply(null,t)}),o.length&&qq.each(o,function(e,n){n.apply(null,t)}),this}})},qq.BlobProxy=function(e,t){"use strict";qq.extend(this,{referenceBlob:e,create:function(){return t(e)}})},qq.UploadButton=function(e){"use strict";function t(){var e=document.createElement("input");return e.setAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME,i),e.setAttribute("title",a.title),o.setMultiple(a.multiple,e),a.folders&&qq.supportedFeatures.folderSelection&&e.setAttribute("webkitdirectory",""),a.acceptFiles&&e.setAttribute("accept",a.acceptFiles),e.setAttribute("type","file"),e.setAttribute("name",a.name),qq(e).css({position:"absolute",right:0,top:0,fontFamily:"Arial",fontSize:qq.ie()&&!qq.ie8()?"3500px":"118px",margin:0,padding:0,cursor:"pointer",opacity:0}),!qq.ie7()&&qq(e).css({height:"100%"}),a.element.appendChild(e),r.attach(e,"change",function(){a.onChange(e)}),r.attach(e,"mouseover",function(){qq(a.element).addClass(a.hoverClass)}),r.attach(e,"mouseout",function(){qq(a.element).removeClass(a.hoverClass)}),r.attach(e,"focus",function(){qq(a.element).addClass(a.focusClass)}),r.attach(e,"blur",function(){qq(a.element).removeClass(a.focusClass)}),e}var n,i,o=this,r=new qq.DisposeSupport,a={acceptFiles:null,element:null,focusClass:"qq-upload-button-focus",folders:!1,hoverClass:"qq-upload-button-hover",ios8BrowserCrashWorkaround:!1,multiple:!1,name:"qqfile",onChange:function(e){},title:null};qq.extend(a,e),i=qq.getUniqueId(),qq(a.element).css({position:"relative",overflow:"hidden",direction:"ltr"}),qq.extend(this,{getInput:function(){return n},getButtonId:function(){return i},setMultiple:function(e,t){var n=t||this.getInput();a.ios8BrowserCrashWorkaround&&qq.ios8()&&(qq.iosChrome()||qq.iosSafariWebView())?n.setAttribute("multiple",""):e?n.setAttribute("multiple",""):n.removeAttribute("multiple")},setAcceptFiles:function(e){e!==a.acceptFiles&&n.setAttribute("accept",e)},reset:function(){n.parentNode&&qq(n).remove(),qq(a.element).removeClass(a.focusClass),n=null,n=t()}}),n=t()},qq.UploadButton.BUTTON_ID_ATTR_NAME="qq-button-id",qq.UploadData=function(e){"use strict";function t(e){if(qq.isArray(e)){var t=[];return qq.each(e,function(e,n){t.push(o[n])}),t}return o[e]}function n(e){if(qq.isArray(e)){var t=[];return qq.each(e,function(e,n){t.push(o[r[n]])}),t}return o[r[e]]}function i(e){var t=[],n=[].concat(e);return qq.each(n,function(e,n){var i=a[n];void 0!==i&&qq.each(i,function(e,n){t.push(o[n])})}),t}var o=[],r={},a={},s={},u={};qq.extend(this,{addFile:function(t){var n=t.status||qq.status.SUBMITTING,i=o.push({name:t.name,originalName:t.name,uuid:t.uuid,size:null==t.size?-1:t.size,status:n,file:t.file})-1;return t.batchId&&(o[i].batchId=t.batchId,void 0===u[t.batchId]&&(u[t.batchId]=[]),u[t.batchId].push(i)),t.proxyGroupId&&(o[i].proxyGroupId=t.proxyGroupId,void 0===s[t.proxyGroupId]&&(s[t.proxyGroupId]=[]),s[t.proxyGroupId].push(i)),o[i].id=i,r[t.uuid]=i,void 0===a[n]&&(a[n]=[]),a[n].push(i),t.onBeforeStatusChange&&t.onBeforeStatusChange(i),e.onStatusChange(i,null,n),i},retrieve:function(e){return qq.isObject(e)&&o.length?void 0!==e.id?t(e.id):void 0!==e.uuid?n(e.uuid):e.status?i(e.status):void 0:qq.extend([],o,!0)},removeFileRef:function(e){var n=t(e);n&&delete n.file},reset:function(){o=[],r={},a={},u={}},setStatus:function(t,n){var i=o[t].status,r=qq.indexOf(a[i],t);a[i].splice(r,1),o[t].status=n,void 0===a[n]&&(a[n]=[]),a[n].push(t),e.onStatusChange(t,i,n)},uuidChanged:function(e,t){var n=o[e].uuid;o[e].uuid=t,r[t]=e,delete r[n]},updateName:function(e,t){o[e].name=t},updateSize:function(e,t){o[e].size=t},setParentId:function(e,t){o[e].parentId=t},getIdsInProxyGroup:function(e){var t=o[e].proxyGroupId;return t?s[t]:[]},getIdsInBatch:function(e){return u[o[e].batchId]}})},qq.status={SUBMITTING:"submitting",SUBMITTED:"submitted",REJECTED:"rejected",QUEUED:"queued",CANCELED:"canceled",PAUSED:"paused",UPLOADING:"uploading",UPLOAD_FINALIZING:"upload finalizing",UPLOAD_RETRYING:"retrying upload",UPLOAD_SUCCESSFUL:"upload successful",UPLOAD_FAILED:"upload failed",DELETE_FAILED:"delete failed",DELETING:"deleting",DELETED:"deleted"},function(){"use strict";qq.basePublicApi={addBlobs:function(e,t,n){this.addFiles(e,t,n)},addInitialFiles:function(e){var t=this;qq.each(e,function(e,n){t._addCannedFile(n)})},addFiles:function(e,t,n){this._maybeHandleIos8SafariWorkaround();var i=0===this._storedIds.length?qq.getUniqueId():this._currentBatchId,o=qq.bind(function(e){this._handleNewFile({blob:e,name:this._options.blobs.defaultName},i,d)},this),r=qq.bind(function(e){this._handleNewFile(e,i,d)},this),a=qq.bind(function(e){var t=qq.canvasToBlob(e);this._handleNewFile({blob:t,name:this._options.blobs.defaultName+".png"},i,d)},this),s=qq.bind(function(e){var t=e.quality&&e.quality/100,n=qq.canvasToBlob(e.canvas,e.type,t);this._handleNewFile({blob:n,name:e.name},i,d)},this),u=qq.bind(function(e){if(qq.isInput(e)&&qq.supportedFeatures.ajaxUploading){var t=Array.prototype.slice.call(e.files),n=this;qq.each(t,function(e,t){n._handleNewFile(t,i,d)})}else this._handleNewFile(e,i,d)},this),l=function(){qq.isFileList(e)&&(e=Array.prototype.slice.call(e)),e=[].concat(e)},c=this,d=[];this._currentBatchId=i,e&&(l(),qq.each(e,function(e,t){qq.isFileOrInput(t)?u(t):qq.isBlob(t)?o(t):qq.isObject(t)?t.blob&&t.name?r(t):t.canvas&&t.name&&s(t):t.tagName&&"canvas"===t.tagName.toLowerCase()?a(t):c.log(t+" is not a valid file container! Ignoring!","warn")}),this.log("Received "+d.length+" files."),this._prepareItemsForUpload(d,t,n))},cancel:function(e){var t=this._uploadData.retrieve({id:e});t&&t.status===qq.status.UPLOAD_FINALIZING?this.log(qq.format("Ignoring cancel for file ID {} ({}). Finalizing upload.",e,this.getName(e)),"error"):this._handler.cancel(e)},cancelAll:function(){var e=[],t=this;qq.extend(e,this._storedIds),qq.each(e,function(e,n){t.cancel(n)}),this._handler.cancelAll()},clearStoredFiles:function(){this._storedIds=[]},continueUpload:function(e){var t=this._uploadData.retrieve({id:e});return!(!qq.supportedFeatures.pause||!this._options.chunking.enabled)&&(t.status===qq.status.PAUSED?(this.log(qq.format("Paused file ID {} ({}) will be continued. Not paused.",e,this.getName(e))),this._uploadFile(e),!0):(this.log(qq.format("Ignoring continue for file ID {} ({}). Not paused.",e,this.getName(e)),"error"),!1))},deleteFile:function(e){return this._onSubmitDelete(e)},doesExist:function(e){return this._handler.isValid(e)},drawThumbnail:function(e,t,n,i,o){var r,a,s=new qq.Promise;return this._imageGenerator?(r=this._thumbnailUrls[e],a={customResizeFunction:o,maxSize:n>0?n:null,scale:n>0},!i&&qq.supportedFeatures.imagePreviews&&(r=this.getFile(e)),null==r?s.failure({container:t,error:"File or URL not found."}):this._imageGenerator.generate(r,t,a).then(function(e){s.success(e)},function(e,t){s.failure({container:e,error:t||"Problem generating thumbnail"})})):s.failure({container:t,error:"Missing image generator module"}),s},getButton:function(e){return this._getButton(this._buttonIdsForFileIds[e])},getEndpoint:function(e){return this._endpointStore.get(e)},getFile:function(e){var t,n=this._handler.getFile(e);return n||(t=this._uploadData.retrieve({id:e}),t&&(n=t.file)),n||null},getInProgress:function(){return this._uploadData.retrieve({status:[qq.status.UPLOADING,qq.status.UPLOAD_RETRYING,qq.status.QUEUED]}).length},getName:function(e){return this._uploadData.retrieve({id:e}).name},getParentId:function(e){var t=this.getUploads({id:e}),n=null;return t&&void 0!==t.parentId&&(n=t.parentId),n},getResumableFilesData:function(){return this._handler.getResumableFilesData()},getSize:function(e){return this._uploadData.retrieve({id:e}).size},getNetUploads:function(){return this._netUploaded},getRemainingAllowedItems:function(){var e=this._currentItemLimit;return e>0?e-this._netUploadedOrQueued:null},getUploads:function(e){return this._uploadData.retrieve(e)},getUuid:function(e){return this._uploadData.retrieve({id:e}).uuid},isResumable:function(e){return this._handler.hasResumeRecord(e)},log:function(e,t){!this._options.debug||t&&"info"!==t?t&&"info"!==t&&qq.log("[Fine Uploader "+qq.version+"] "+e,t):qq.log("[Fine Uploader "+qq.version+"] "+e)},pauseUpload:function(e){var t=this._uploadData.retrieve({id:e});if(!qq.supportedFeatures.pause||!this._options.chunking.enabled)return!1;if(qq.indexOf([qq.status.UPLOADING,qq.status.UPLOAD_RETRYING],t.status)>=0){if(this._handler.pause(e))return this._uploadData.setStatus(e,qq.status.PAUSED),!0;this.log(qq.format("Unable to pause file ID {} ({}).",e,this.getName(e)),"error")}else this.log(qq.format("Ignoring pause for file ID {} ({}). Not in progress.",e,this.getName(e)),"error");return!1},removeFileRef:function(e){this._handler.expunge(e),this._uploadData.removeFileRef(e)},reset:function(){this.log("Resetting uploader..."),this._handler.reset(),this._storedIds=[],this._autoRetries=[],this._retryTimeouts=[],this._preventRetries=[],this._thumbnailUrls=[],qq.each(this._buttons,function(e,t){t.reset()}),this._paramsStore.reset(),this._endpointStore.reset(),this._netUploadedOrQueued=0,this._netUploaded=0,this._uploadData.reset(),this._buttonIdsForFileIds=[],this._pasteHandler&&this._pasteHandler.reset(),this._options.session.refreshOnReset&&this._refreshSessionData(),this._succeededSinceLastAllComplete=[],this._failedSinceLastAllComplete=[],this._totalProgress&&this._totalProgress.reset(),this._customResumeDataStore.reset()},retry:function(e){return this._manualRetry(e)},scaleImage:function(e,t){var n=this;return qq.Scaler.prototype.scaleImage(e,t,{log:qq.bind(n.log,n),getFile:qq.bind(n.getFile,n),uploadData:n._uploadData})},setCustomHeaders:function(e,t){this._customHeadersStore.set(e,t)},setCustomResumeData:function(e,t){this._customResumeDataStore.set(t,e)},setDeleteFileCustomHeaders:function(e,t){this._deleteFileCustomHeadersStore.set(e,t)},setDeleteFileEndpoint:function(e,t){this._deleteFileEndpointStore.set(e,t)},setDeleteFileParams:function(e,t){this._deleteFileParamsStore.set(e,t)},setEndpoint:function(e,t){this._endpointStore.set(e,t)},setForm:function(e){this._updateFormSupportAndParams(e)},setItemLimit:function(e){this._currentItemLimit=e},setName:function(e,t){this._uploadData.updateName(e,t)},setParams:function(e,t){this._paramsStore.set(e,t)},setUuid:function(e,t){return this._uploadData.uuidChanged(e,t)},setStatus:function(e,t){if(!this.getUploads({id:e}))throw new qq.Error(e+" is not a valid file ID.");switch(t){case qq.status.DELETED:this._onDeleteComplete(e,null,!1);break;case qq.status.DELETE_FAILED:this._onDeleteComplete(e,null,!0);break;default:var n="Method setStatus called on '"+name+"' not implemented yet for "+t;throw this.log(n),new qq.Error(n)}},uploadStoredFiles:function(){0===this._storedIds.length?this._itemError("noFilesError"):this._uploadStoredFiles()}},qq.basePrivateApi={_addCannedFile:function(e){var t=this;return this._uploadData.addFile({uuid:e.uuid,name:e.name,size:e.size,status:qq.status.UPLOAD_SUCCESSFUL,onBeforeStatusChange:function(n){e.deleteFileEndpoint&&t.setDeleteFileEndpoint(e.deleteFileEndpoint,n),e.deleteFileParams&&t.setDeleteFileParams(e.deleteFileParams,n),e.thumbnailUrl&&(t._thumbnailUrls[n]=e.thumbnailUrl),t._netUploaded++,t._netUploadedOrQueued++}})},_annotateWithButtonId:function(e,t){qq.isFile(e)&&(e.qqButtonId=this._getButtonId(t))},_batchError:function(e){this._options.callbacks.onError(null,null,e,void 0)},_createDeleteHandler:function(){var e=this;return new qq.DeleteFileAjaxRequester({method:this._options.deleteFile.method.toUpperCase(),maxConnections:this._options.maxConnections,uuidParamName:this._options.request.uuidName,customHeaders:this._deleteFileCustomHeadersStore,paramsStore:this._deleteFileParamsStore,endpointStore:this._deleteFileEndpointStore,cors:this._options.cors,log:qq.bind(e.log,e),onDelete:function(t){e._onDelete(t),e._options.callbacks.onDelete(t)},onDeleteComplete:function(t,n,i){e._onDeleteComplete(t,n,i),e._options.callbacks.onDeleteComplete(t,n,i)}})},_createPasteHandler:function(){var e=this;return new qq.PasteSupport({targetElement:this._options.paste.targetElement,callbacks:{log:qq.bind(e.log,e),pasteReceived:function(t){e._handleCheckedCallback({name:"onPasteReceived",callback:qq.bind(e._options.callbacks.onPasteReceived,e,t),onSuccess:qq.bind(e._handlePasteSuccess,e,t),identifier:"pasted image"})}}})},_createStore:function(e,t){var n={},i=e,o={},r=t,a=function(e){return qq.isObject(e)?qq.extend({},e):e},s=function(){return qq.isFunction(r)?r():r},u=function(e,t){r&&qq.isObject(t)&&qq.extend(t,s()),o[e]&&qq.extend(t,o[e])};return{set:function(e,t){null==t?(n={},i=a(e)):n[t]=a(e)},get:function(e){var t;return t=null!=e&&n[e]?n[e]:a(i),u(e,t),a(t)},addReadOnly:function(e,t){qq.isObject(n)&&(null===e?qq.isFunction(t)?r=t:(r=r||{},qq.extend(r,t)):(o[e]=o[e]||{},qq.extend(o[e],t)))},remove:function(e){return delete n[e]},reset:function(){n={},o={},i=e}}},_createUploadDataTracker:function(){var e=this;return new qq.UploadData({getName:function(t){return e.getName(t)},getUuid:function(t){return e.getUuid(t)},getSize:function(t){return e.getSize(t)},onStatusChange:function(t,n,i){e._onUploadStatusChange(t,n,i),e._options.callbacks.onStatusChange(t,n,i),e._maybeAllComplete(t,i),e._totalProgress&&setTimeout(function(){e._totalProgress.onStatusChange(t,n,i)},0)}})},_createUploadButton:function(e){function t(){return!!qq.supportedFeatures.ajaxUploading&&(!(i._options.workarounds.iosEmptyVideos&&qq.ios()&&!qq.ios6()&&i._isAllowedExtension(r,".mov"))&&(void 0===e.multiple?i._options.multiple:e.multiple))}var n,i=this,o=e.accept||this._options.validation.acceptFiles,r=e.allowedExtensions||this._options.validation.allowedExtensions;return n=new qq.UploadButton({acceptFiles:o,element:e.element,focusClass:this._options.classes.buttonFocus,folders:e.folders,hoverClass:this._options.classes.buttonHover,ios8BrowserCrashWorkaround:this._options.workarounds.ios8BrowserCrash,multiple:t(),name:this._options.request.inputName,onChange:function(e){i._onInputChange(e)},title:null==e.title?this._options.text.fileInputTitle:e.title}),this._disposeSupport.addDisposer(function(){n.dispose()}),i._buttons.push(n),n},_createUploadHandler:function(e,t){var n=this,i={},o={debug:this._options.debug,maxConnections:this._options.maxConnections,cors:this._options.cors,paramsStore:this._paramsStore,endpointStore:this._endpointStore,chunking:this._options.chunking,resume:this._options.resume,blobs:this._options.blobs,log:qq.bind(n.log,n),preventRetryParam:this._options.retry.preventRetryResponseProperty,onProgress:function(e,t,o,r){o<0||r<0||(i[e]?i[e].loaded===o&&i[e].total===r||(n._onProgress(e,t,o,r),n._options.callbacks.onProgress(e,t,o,r)):(n._onProgress(e,t,o,r),n._options.callbacks.onProgress(e,t,o,r)),i[e]={loaded:o,total:r})},onComplete:function(e,t,o,r){delete i[e];var a,s=n.getUploads({id:e}).status;s!==qq.status.UPLOAD_SUCCESSFUL&&s!==qq.status.UPLOAD_FAILED&&(a=n._onComplete(e,t,o,r),a instanceof qq.Promise?a.done(function(){n._options.callbacks.onComplete(e,t,o,r)}):n._options.callbacks.onComplete(e,t,o,r))},onCancel:function(e,t,i){var o=new qq.Promise;return n._handleCheckedCallback({name:"onCancel",callback:qq.bind(n._options.callbacks.onCancel,n,e,t),onFailure:o.failure,onSuccess:function(){i.then(function(){n._onCancel(e,t)}),o.success()},identifier:e}),o},onUploadPrep:qq.bind(this._onUploadPrep,this),onUpload:function(e,t){n._onUpload(e,t);var i=n._options.callbacks.onUpload(e,t);return qq.isGenericPromise(i)?(n.log(qq.format("onUpload for {} returned a Promise - waiting for resolution.",e)),i):(new qq.Promise).success()},onUploadChunk:function(e,t,i){n._onUploadChunk(e,i);var o=n._options.callbacks.onUploadChunk(e,t,i)
+;return qq.isGenericPromise(o)?(n.log(qq.format("onUploadChunk for {}.{} returned a Promise - waiting for resolution.",e,i.partIndex)),o):(new qq.Promise).success()},onUploadChunkSuccess:function(e,t,i,o){n._onUploadChunkSuccess(e,t),n._options.callbacks.onUploadChunkSuccess.apply(n,arguments)},onResume:function(e,t,i,o){return n._options.callbacks.onResume(e,t,i,o)},onAutoRetry:function(e,t,i,o){return n._onAutoRetry.apply(n,arguments)},onUuidChanged:function(e,t){n.log("Server requested UUID change from '"+n.getUuid(e)+"' to '"+t+"'"),n.setUuid(e,t)},getName:qq.bind(n.getName,n),getUuid:qq.bind(n.getUuid,n),getSize:qq.bind(n.getSize,n),setSize:qq.bind(n._setSize,n),getDataByUuid:function(e){return n.getUploads({uuid:e})},isQueued:function(e){var t=n.getUploads({id:e}).status;return t===qq.status.QUEUED||t===qq.status.SUBMITTED||t===qq.status.UPLOAD_RETRYING||t===qq.status.PAUSED},getIdsInProxyGroup:n._uploadData.getIdsInProxyGroup,getIdsInBatch:n._uploadData.getIdsInBatch,isInProgress:function(e){return n.getUploads({id:e}).status===qq.status.UPLOADING},getCustomResumeData:qq.bind(n._getCustomResumeData,n),setStatus:function(e,t){n._uploadData.setStatus(e,t)}};return qq.each(this._options.request,function(e,t){o[e]=t}),o.customHeaders=this._customHeadersStore,e&&qq.each(e,function(e,t){o[e]=t}),new qq.UploadHandlerController(o,t)},_fileOrBlobRejected:function(e){this._netUploadedOrQueued--,this._uploadData.setStatus(e,qq.status.REJECTED)},_formatSize:function(e){if(0===e)return e+this._options.text.sizeSymbols[0];var t=-1;do e/=1e3,t++;while(e>999);return Math.max(e,.1).toFixed(1)+this._options.text.sizeSymbols[t]},_generateExtraButtonSpecs:function(){var e=this;this._extraButtonSpecs={},qq.each(this._options.extraButtons,function(t,n){var i=n.multiple,o=qq.extend({},e._options.validation,!0),r=qq.extend({},n);void 0===i&&(i=e._options.multiple),r.validation&&qq.extend(o,n.validation,!0),qq.extend(r,{multiple:i,validation:o},!0),e._initExtraButton(r)})},_getButton:function(e){var t=this._extraButtonSpecs[e];return t?t.element:e===this._defaultButtonId?this._options.button:void 0},_getButtonId:function(e){var t,n,i=e;if(i instanceof qq.BlobProxy&&(i=i.referenceBlob),i&&!qq.isBlob(i)){if(qq.isFile(i))return i.qqButtonId;if("input"===i.tagName.toLowerCase()&&"file"===i.type.toLowerCase())return i.getAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME);if(t=i.getElementsByTagName("input"),qq.each(t,function(e,t){if("file"===t.getAttribute("type"))return n=t,!1}),n)return n.getAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME)}},_getCustomResumeData:function(e){return this._customResumeDataStore.get(e)},_getNotFinished:function(){return this._uploadData.retrieve({status:[qq.status.UPLOADING,qq.status.UPLOAD_RETRYING,qq.status.QUEUED,qq.status.SUBMITTING,qq.status.SUBMITTED,qq.status.PAUSED]}).length},_getValidationBase:function(e){var t=this._extraButtonSpecs[e];return t?t.validation:this._options.validation},_getValidationDescriptor:function(e){return e.file instanceof qq.BlobProxy?{name:qq.getFilename(e.file.referenceBlob),size:e.file.referenceBlob.size}:{name:this.getUploads({id:e.id}).name,size:this.getUploads({id:e.id}).size}},_getValidationDescriptors:function(e){var t=this,n=[];return qq.each(e,function(e,i){n.push(t._getValidationDescriptor(i))}),n},_handleCameraAccess:function(){if(this._options.camera.ios&&qq.ios()){var e=this._options.camera.button,t=e?this._getButtonId(e):this._defaultButtonId,n=this._options;t&&t!==this._defaultButtonId&&(n=this._extraButtonSpecs[t]),n.multiple=!1,null===n.validation.acceptFiles?n.validation.acceptFiles="image/*;capture=camera":n.validation.acceptFiles+=",image/*;capture=camera",qq.each(this._buttons,function(e,i){if(i.getButtonId()===t)return i.setMultiple(n.multiple),i.setAcceptFiles(n.acceptFiles),!1})}},_handleCheckedCallback:function(e){var t=this,n=e.callback();return qq.isGenericPromise(n)?(this.log(e.name+" - waiting for "+e.name+" promise to be fulfilled for "+e.identifier),n.then(function(n){t.log(e.name+" promise success for "+e.identifier),e.onSuccess(n)},function(){e.onFailure?(t.log(e.name+" promise failure for "+e.identifier),e.onFailure()):t.log(e.name+" promise failure for "+e.identifier)})):(n!==!1?e.onSuccess(n):e.onFailure?(this.log(e.name+" - return value was 'false' for "+e.identifier+". Invoking failure callback."),e.onFailure()):this.log(e.name+" - return value was 'false' for "+e.identifier+". Will not proceed."),n)},_handleNewFile:function(e,t,n){var i=this,o=qq.getUniqueId(),r=-1,a=qq.getFilename(e),s=e.blob||e,u=this._customNewFileHandler?this._customNewFileHandler:qq.bind(i._handleNewFileGeneric,i);!qq.isInput(s)&&s.size>=0&&(r=s.size),u(s,a,o,r,n,t,this._options.request.uuidName,{uploadData:i._uploadData,paramsStore:i._paramsStore,addFileToHandler:function(e,t){i._handler.add(e,t),i._netUploadedOrQueued++,i._trackButton(e)}})},_handleNewFileGeneric:function(e,t,n,i,o,r){var a=this._uploadData.addFile({uuid:n,name:t,size:i,batchId:r,file:e});this._handler.add(a,e),this._trackButton(a),this._netUploadedOrQueued++,o.push({id:a,file:e})},_handlePasteSuccess:function(e,t){var n=e.type.split("/")[1],i=t;null==i&&(i=this._options.paste.defaultName),i+="."+n,this.addFiles({name:i,blob:e})},_handleDeleteSuccess:function(e){if(this.getUploads({id:e}).status!==qq.status.DELETED){var t=this.getName(e);this._netUploadedOrQueued--,this._netUploaded--,this._handler.expunge(e),this._uploadData.setStatus(e,qq.status.DELETED),this.log("Delete request for '"+t+"' has succeeded.")}},_handleDeleteFailed:function(e,t){var n=this.getName(e);this._uploadData.setStatus(e,qq.status.DELETE_FAILED),this.log("Delete request for '"+n+"' has failed.","error"),t&&void 0!==t.withCredentials?this._options.callbacks.onError(e,n,"Delete request failed with response code "+t.status,t):this._options.callbacks.onError(e,n,"Delete request failed",t)},_initExtraButton:function(e){var t=this._createUploadButton({accept:e.validation.acceptFiles,allowedExtensions:e.validation.allowedExtensions,element:e.element,folders:e.folders,multiple:e.multiple,title:e.fileInputTitle});this._extraButtonSpecs[t.getButtonId()]=e},_initFormSupportAndParams:function(){this._formSupport=qq.FormSupport&&new qq.FormSupport(this._options.form,qq.bind(this.uploadStoredFiles,this),qq.bind(this.log,this)),this._formSupport&&this._formSupport.attachedToForm?(this._paramsStore=this._createStore(this._options.request.params,this._formSupport.getFormInputsAsObject),this._options.autoUpload=this._formSupport.newAutoUpload,this._formSupport.newEndpoint&&(this._options.request.endpoint=this._formSupport.newEndpoint)):this._paramsStore=this._createStore(this._options.request.params)},_isDeletePossible:function(){return!(!qq.DeleteFileAjaxRequester||!this._options.deleteFile.enabled)&&(!this._options.cors.expected||(!!qq.supportedFeatures.deleteFileCorsXhr||!(!qq.supportedFeatures.deleteFileCorsXdr||!this._options.cors.allowXdr)))},_isAllowedExtension:function(e,t){var n=!1;return!e.length||(qq.each(e,function(e,i){if(qq.isString(i)){var o=new RegExp("\\."+i+"$","i");if(null!=t.match(o))return n=!0,!1}}),n)},_itemError:function(e,t,n){function i(e,t){a=a.replace(e,t)}var o,r,a=this._options.messages[e],s=[],u=[].concat(t),l=u[0],c=this._getButtonId(n),d=this._getValidationBase(c);return qq.each(d.allowedExtensions,function(e,t){qq.isString(t)&&s.push(t)}),o=s.join(", ").toLowerCase(),i("{file}",this._options.formatFileName(l)),i("{extensions}",o),i("{sizeLimit}",this._formatSize(d.sizeLimit)),i("{minSizeLimit}",this._formatSize(d.minSizeLimit)),r=a.match(/(\{\w+\})/g),null!==r&&qq.each(r,function(e,t){i(t,u[e])}),this._options.callbacks.onError(null,l,a,void 0),a},_manualRetry:function(e,t){if(this._onBeforeManualRetry(e))return this._netUploadedOrQueued++,this._uploadData.setStatus(e,qq.status.UPLOAD_RETRYING),t?t(e):this._handler.retry(e),!0},_maybeAllComplete:function(e,t){var n=this,i=this._getNotFinished();t===qq.status.UPLOAD_SUCCESSFUL?this._succeededSinceLastAllComplete.push(e):t===qq.status.UPLOAD_FAILED&&this._failedSinceLastAllComplete.push(e),0===i&&(this._succeededSinceLastAllComplete.length||this._failedSinceLastAllComplete.length)&&setTimeout(function(){n._onAllComplete(n._succeededSinceLastAllComplete,n._failedSinceLastAllComplete)},0)},_maybeHandleIos8SafariWorkaround:function(){var e=this;if(this._options.workarounds.ios8SafariUploads&&qq.ios800()&&qq.iosSafari())throw setTimeout(function(){window.alert(e._options.messages.unsupportedBrowserIos8Safari)},0),new qq.Error(this._options.messages.unsupportedBrowserIos8Safari)},_maybeParseAndSendUploadError:function(e,t,n,i){if(!n.success)if(i&&200!==i.status&&!n.error)this._options.callbacks.onError(e,t,"XHR returned response code "+i.status,i);else{var o=n.error?n.error:this._options.text.defaultResponseError;this._options.callbacks.onError(e,t,o,i)}},_maybeProcessNextItemAfterOnValidateCallback:function(e,t,n,i,o){var r=this;if(t.length>n)if(e||!this._options.validation.stopOnFirstInvalidFile)setTimeout(function(){var e=r._getValidationDescriptor(t[n]),a=r._getButtonId(t[n].file),s=r._getButton(a);r._handleCheckedCallback({name:"onValidate",callback:qq.bind(r._options.callbacks.onValidate,r,e,s),onSuccess:qq.bind(r._onValidateCallbackSuccess,r,t,n,i,o),onFailure:qq.bind(r._onValidateCallbackFailure,r,t,n,i,o),identifier:"Item '"+e.name+"', size: "+e.size})},0);else if(!e)for(;n0&&this._netUploadedOrQueued+1>n?(this._itemError("retryFailTooManyItems"),!1):(this.log("Retrying upload for '"+t+"' (id: "+e+")..."),!0))):(this.log("'"+e+"' is not a valid file ID","error"),!1)},_onCancel:function(e,t){this._netUploadedOrQueued--,clearTimeout(this._retryTimeouts[e]);var n=qq.indexOf(this._storedIds,e);!this._options.autoUpload&&n>=0&&this._storedIds.splice(n,1),this._uploadData.setStatus(e,qq.status.CANCELED)},_onComplete:function(e,t,n,i){return n.success?(n.thumbnailUrl&&(this._thumbnailUrls[e]=n.thumbnailUrl),this._netUploaded++,this._uploadData.setStatus(e,qq.status.UPLOAD_SUCCESSFUL)):(this._netUploadedOrQueued--,this._uploadData.setStatus(e,qq.status.UPLOAD_FAILED),n[this._options.retry.preventRetryResponseProperty]===!0&&(this._preventRetries[e]=!0)),this._maybeParseAndSendUploadError(e,t,n,i),!!n.success},_onDelete:function(e){this._uploadData.setStatus(e,qq.status.DELETING)},_onDeleteComplete:function(e,t,n){this.getName(e);n?this._handleDeleteFailed(e,t):this._handleDeleteSuccess(e)},_onInputChange:function(e){var t;if(qq.supportedFeatures.ajaxUploading){for(t=0;t0&&this.addFiles(e);qq.each(this._buttons,function(e,t){t.reset()})},_onProgress:function(e,t,n,i){this._totalProgress&&this._totalProgress.onIndividualProgress(e,n,i)},_onSubmit:function(e,t){},_onSubmitCallbackSuccess:function(e,t){this._onSubmit.apply(this,arguments),this._uploadData.setStatus(e,qq.status.SUBMITTED),this._onSubmitted.apply(this,arguments),this._options.autoUpload?(this._options.callbacks.onSubmitted.apply(this,arguments),this._uploadFile(e)):(this._storeForLater(e),this._options.callbacks.onSubmitted.apply(this,arguments))},_onSubmitDelete:function(e,t,n){var i,o=this.getUuid(e);return t&&(i=qq.bind(t,this,e,o,n)),this._isDeletePossible()?(this._handleCheckedCallback({name:"onSubmitDelete",callback:qq.bind(this._options.callbacks.onSubmitDelete,this,e),onSuccess:i||qq.bind(this._deleteHandler.sendDelete,this,e,o,n),identifier:e}),!0):(this.log("Delete request ignored for ID "+e+", delete feature is disabled or request not possible due to CORS on a user agent that does not support pre-flighting.","warn"),!1)},_onSubmitted:function(e){},_onTotalProgress:function(e,t){this._options.callbacks.onTotalProgress(e,t)},_onUploadPrep:function(e){},_onUpload:function(e,t){this._uploadData.setStatus(e,qq.status.UPLOADING)},_onUploadChunk:function(e,t){},_onUploadChunkSuccess:function(e,t){!this._preventRetries[e]&&this._options.retry.enableAuto&&(this._autoRetries[e]=0)},_onUploadStatusChange:function(e,t,n){n===qq.status.PAUSED&&clearTimeout(this._retryTimeouts[e])},_onValidateBatchCallbackFailure:function(e){var t=this;qq.each(e,function(e,n){t._fileOrBlobRejected(n.id)})},_onValidateBatchCallbackSuccess:function(e,t,n,i,o){var r,a=this._currentItemLimit,s=this._netUploadedOrQueued;0===a||s<=a?t.length>0?this._handleCheckedCallback({name:"onValidate",callback:qq.bind(this._options.callbacks.onValidate,this,e[0],o),onSuccess:qq.bind(this._onValidateCallbackSuccess,this,t,0,n,i),onFailure:qq.bind(this._onValidateCallbackFailure,this,t,0,n,i),identifier:"Item '"+t[0].file.name+"', size: "+t[0].file.size}):this._itemError("noFilesError"):(this._onValidateBatchCallbackFailure(t),r=this._options.messages.tooManyItemsError.replace(/\{netItems\}/g,s).replace(/\{itemLimit\}/g,a),this._batchError(r))},_onValidateCallbackFailure:function(e,t,n,i){var o=t+1;this._fileOrBlobRejected(e[t].id,e[t].file.name),this._maybeProcessNextItemAfterOnValidateCallback(!1,e,o,n,i)},_onValidateCallbackSuccess:function(e,t,n,i){var o=this,r=t+1,a=this._getValidationDescriptor(e[t]);this._validateFileOrBlobData(e[t],a).then(function(){o._upload(e[t].id,n,i),o._maybeProcessNextItemAfterOnValidateCallback(!0,e,r,n,i)},function(){o._maybeProcessNextItemAfterOnValidateCallback(!1,e,r,n,i)})},_prepareItemsForUpload:function(e,t,n){if(0===e.length)return void this._itemError("noFilesError");var i=this._getValidationDescriptors(e),o=this._getButtonId(e[0].file),r=this._getButton(o);this._handleCheckedCallback({name:"onValidateBatch",callback:qq.bind(this._options.callbacks.onValidateBatch,this,i,r),onSuccess:qq.bind(this._onValidateBatchCallbackSuccess,this,i,e,t,n,r),onFailure:qq.bind(this._onValidateBatchCallbackFailure,this,e),identifier:"batch validation"})},_preventLeaveInProgress:function(){var e=this;this._disposeSupport.attach(window,"beforeunload",function(t){if(e.getInProgress())return t=t||window.event,t.returnValue=e._options.messages.onLeave,e._options.messages.onLeave})},_refreshSessionData:function(){var e=this,t=this._options.session;qq.Session&&null!=this._options.session.endpoint&&(this._session||(qq.extend(t,{cors:this._options.cors}),t.log=qq.bind(this.log,this),t.addFileRecord=qq.bind(this._addCannedFile,this),this._session=new qq.Session(t)),setTimeout(function(){e._session.refresh().then(function(t,n){e._sessionRequestComplete(),e._options.callbacks.onSessionRequestComplete(t,!0,n)},function(t,n){e._options.callbacks.onSessionRequestComplete(t,!1,n)})},0))},_sessionRequestComplete:function(){},_setSize:function(e,t){this._uploadData.updateSize(e,t),this._totalProgress&&this._totalProgress.onNewSize(e)},_shouldAutoRetry:function(e){var t=this._uploadData.retrieve({id:e});return!!(!this._preventRetries[e]&&this._options.retry.enableAuto&&t.status!==qq.status.PAUSED&&(void 0===this._autoRetries[e]&&(this._autoRetries[e]=0),this._autoRetries[e]0&&s.sizeLimit&&r>s.sizeLimit?(this._itemError("sizeError",o,i),u.failure()):r>0&&r=0}function n(e){var t=!1;return qq.each(t,function(e,n){if(qq.indexOf(["Accept","Accept-Language","Content-Language","Content-Type"],n)<0)return t=!0,!1}),t}function i(e){return S.cors.expected&&void 0===e.withCredentials}function o(){var e;return(window.XMLHttpRequest||window.ActiveXObject)&&(e=qq.createXhrInstance(),void 0===e.withCredentials&&(e=new XDomainRequest,e.onload=function(){},e.onerror=function(){},e.ontimeout=function(){},e.onprogress=function(){})),e}function r(e,t){var n=y[e]&&y[e].xhr;return n||(n=t?t:S.cors.expected?o():qq.createXhrInstance(),y[e].xhr=n),n}function a(e){var t,n=qq.indexOf(b,e),i=S.maxConnections;delete y[e],b.splice(n,1),b.length>=i&&n=0?o.send(qq.obj2url(s,"")):s&&S.contentType&&S.contentType.toLowerCase().indexOf("application/json")>=0?o.send(JSON.stringify(s)):o.send(s),o}function c(e,t,n){var i=S.endpointStore.get(e),o=y[e].addToPath;return void 0!=o&&(i+="/"+o),v&&t&&(i=qq.obj2url(t,i)),n&&(i=qq.obj2url(n,i)),i}function d(e){return function(){4===r(e).readyState&&s(e)}}function p(e){var t=S.onProgress;t&&(r(e).upload.onprogress=function(n){n.lengthComputable&&t(e,n.loaded,n.total)})}function h(e){return function(){s(e)}}function f(e){return function(){s(e,!0)}}function q(e){var o=r(e),a=S.customHeaders,s=y[e].additionalHeaders||{},u=S.method,l={};i(o)||(S.acceptHeader&&o.setRequestHeader("Accept",S.acceptHeader),S.allowXRequestedWithAndCacheControl&&(S.cors.expected&&t()&&!n(a)||(o.setRequestHeader("X-Requested-With","XMLHttpRequest"),o.setRequestHeader("Cache-Control","no-cache"))),!S.contentType||"POST"!==u&&"PUT"!==u||o.setRequestHeader("Content-Type",S.contentType),qq.extend(l,qq.isFunction(a)?a(e):a),qq.extend(l,s),qq.each(l,function(e,t){o.setRequestHeader(e,t)}))}function m(e){return qq.indexOf(S.successfulResponseCodes[S.method],e)>=0}function g(e,t,n,i,o,r,a){if(y[e]={addToPath:n,additionalParams:i,additionalQueryParams:o,additionalHeaders:r,payload:a},b.push(e)<=S.maxConnections)return l(e,t)}var _,v,b=[],y={},S={acceptHeader:null,validMethods:["PATCH","POST","PUT"],method:"POST",contentType:"application/x-www-form-urlencoded",maxConnections:3,customHeaders:{},endpointStore:{},paramsStore:{},mandatedParams:{},allowXRequestedWithAndCacheControl:!0,successfulResponseCodes:{DELETE:[200,202,204],PATCH:[200,201,202,203,204],POST:[200,201,202,203,204],PUT:[200,201,202,203,204],GET:[200]},cors:{expected:!1,sendCredentials:!1},log:function(e,t){},onSend:function(e){},onComplete:function(e,t,n){},onProgress:null};if(qq.extend(S,e),_=S.log,qq.indexOf(S.validMethods,S.method)<0)throw new Error("'"+S.method+"' is not a supported method for this type of request!");v="GET"===S.method||"DELETE"===S.method,qq.extend(this,{initTransport:function(e){var t,n,i,o,r,a;return{withPath:function(e){return t=e,this},withParams:function(e){return n=e,this},withQueryParams:function(e){return a=e,this},withHeaders:function(e){return i=e,this},withPayload:function(e){return o=e,this},withCacheBuster:function(){return r=!0,this},send:function(s){return r&&qq.indexOf(["GET","DELETE"],S.method)>=0&&(n.qqtimestamp=(new Date).getTime()),g(e,s,t,n,a,i,o)}}},canceled:function(e){a(e)}})},qq.UploadHandler=function(e){"use strict";var t=e.proxy,n={},i=t.onCancel,o=t.getName;qq.extend(this,{add:function(e,t){n[e]=t,n[e].temp={}},cancel:function(e){var t=this,r=new qq.Promise;i(e,o(e),r).then(function(){t.isValid(e)&&(n[e].canceled=!0,t.expunge(e)),r.success()})},expunge:function(e){delete n[e]},getThirdPartyFileId:function(e){return n[e].key},isValid:function(e){return void 0!==n[e]},reset:function(){n={}},_getFileState:function(e){return n[e]},_setThirdPartyFileId:function(e,t){n[e].key=t},_wasCanceled:function(e){return!!n[e].canceled}})},qq.UploadHandlerController=function(e,t){"use strict";var n,i,o,r=this,a=!1,s=!1,u={paramsStore:{},maxConnections:3,chunking:{enabled:!1,multiple:{enabled:!1}},log:function(e,t){},onProgress:function(e,t,n,i){},onComplete:function(e,t,n,i){},onCancel:function(e,t){},onUploadPrep:function(e){},onUpload:function(e,t){},onUploadChunk:function(e,t,n){},onUploadChunkSuccess:function(e,t,n,i){},onAutoRetry:function(e,t,n,i){},onResume:function(e,t,n,i){},onUuidChanged:function(e,t){},getName:function(e){},setSize:function(e,t){},isQueued:function(e){},getIdsInProxyGroup:function(e){},getIdsInBatch:function(e){},isInProgress:function(e){}},l={done:function(e,t,n,i){var r=o._getChunkData(e,t);o._getFileState(e).attemptingResume=!1,delete o._getFileState(e).temp.chunkProgress[t],o._getFileState(e).loaded+=r.size,u.onUploadChunkSuccess(e,o._getChunkDataForCallback(r),n,i)},finalize:function(e){var t=u.getSize(e),n=u.getName(e);i("All chunks have been uploaded for "+e+" - finalizing...."),o.finalizeChunks(e).then(function(r,a){i("Finalize successful for "+e);var s=p.normalizeResponse(r,!0);u.onProgress(e,n,t,t),o._maybeDeletePersistedChunkData(e),p.cleanup(e,s,a)},function(t,o){var r=p.normalizeResponse(t,!1);i("Problem finalizing chunks for file ID "+e+" - "+r.error,"error"),(r.reset||o&&u.chunking.success.resetOnStatus.indexOf(o.status)>=0)&&l.reset(e),u.onAutoRetry(e,n,r,o)||p.cleanup(e,r,o)})},handleFailure:function(e,t,n,r){var a=u.getName(t);i("Chunked upload request failed for "+t+", chunk "+e),o.clearCachedChunk(t,e);var d,h=p.normalizeResponse(n,!1);if(h.reset)l.reset(t);else{var f=o._getFileState(t).chunking.inProgress;d=f?qq.indexOf(f,e):-1,d>=0&&(o._getFileState(t).chunking.inProgress.splice(d,1),o._getFileState(t).chunking.remaining.unshift(e))}o._getFileState(t).temp.ignoreFailure||(s&&(o._getFileState(t).temp.ignoreFailure=!0,i(qq.format("Going to attempt to abort these chunks: {}. These are currently in-progress: {}.",JSON.stringify(Object.keys(o._getXhrs(t))),JSON.stringify(o._getFileState(t).chunking.inProgress))),qq.each(o._getXhrs(t),function(e,n){i(qq.format("Attempting to abort file {}.{}. XHR readyState {}. ",t,e,n.readyState)),n.abort(),n._cancelled=!0}),o.moveInProgressToRemaining(t),c.free(t,!0)),u.onAutoRetry(t,a,h,r)||p.cleanup(t,h,r))},hasMoreParts:function(e){return!!o._getFileState(e).chunking.remaining.length},nextPart:function(e){var t=o._getFileState(e).chunking.remaining.shift();return t>=o._getTotalChunks(e)&&(t=null),t},reset:function(e){
+i("Server or callback has ordered chunking effort to be restarted on next attempt for item ID "+e,"error"),o._maybeDeletePersistedChunkData(e),o.reevaluateChunking(e),o._getFileState(e).loaded=0,o._getFileState(e).attemptingResume=!1},sendNext:function(e){var t=u.getSize(e),n=u.getName(e),r=l.nextPart(e),a=o._getChunkData(e,r),d=o._getFileState(e),h=d.attemptingResume,f=d.chunking.inProgress||[];if(null==d.loaded&&(d.loaded=0),h&&u.onResume(e,n,a,d.customResumeData)===!1&&(l.reset(e),r=l.nextPart(e),a=o._getChunkData(e,r),h=!1),null==r&&0===f.length)l.finalize(e);else{f.push(r),o._getFileState(e).chunking.inProgress=f,s&&c.open(e,r),s&&c.available()&&o._getFileState(e).chunking.remaining.length&&l.sendNext(e),0===a.blob.size&&(i(qq.format("Chunk {} for file {} will not be uploaded, zero sized chunk.",r,e),"error"),l.handleFailure(r,e,"File is no longer available",null));u.onUploadChunk(e,n,o._getChunkDataForCallback(a)).then(function(n){if(u.isInProgress(e)){i(qq.format("Sending chunked upload request for item {}.{}, bytes {}-{} of {}.",e,r,a.start+1,a.end,t));var s={chunkIdx:r,id:e,overrides:n,resuming:h};o.uploadChunk(s).then(function(t,n){i("Chunked upload request succeeded for "+e+", chunk "+r),o.clearCachedChunk(e,r);var a=o._getFileState(e).chunking.inProgress||[],s=p.normalizeResponse(t,!0),u=qq.indexOf(a,r);i(qq.format("Chunk {} for file {} uploaded successfully.",r,e)),l.done(e,r,s,n),u>=0&&a.splice(u,1),o._maybePersistChunkedState(e),l.hasMoreParts(e)||0!==a.length?l.hasMoreParts(e)?l.sendNext(e):i(qq.format("File ID {} has no more chunks to send and these chunk indexes are still marked as in-progress: {}",e,JSON.stringify(a))):l.finalize(e)},function(t,n){l.handleFailure(r,e,t,n)}).done(function(){o.clearXhr(e,r)})}else i(qq.format("Not sending chunked upload request for item {}.{} - no longer in progress.",e,r))},function(t){l.handleFailure(r,e,t,null)})}}},c={_open:[],_openChunks:{},_waiting:[],available:function(){var e=u.maxConnections,t=0,n=0;return qq.each(c._openChunks,function(e,i){t++,n+=i.length}),e-(c._open.length-t+n)},free:function(e,t){var n,r=!t,a=qq.indexOf(c._waiting,e),s=qq.indexOf(c._open,e);delete c._openChunks[e],p.getProxyOrBlob(e)instanceof qq.BlobProxy&&(i("Generated blob upload has ended for "+e+", disposing generated blob."),delete o._getFileState(e).file),a>=0?c._waiting.splice(a,1):r&&s>=0&&(c._open.splice(s,1),n=c._waiting.shift(),n>=0&&(c._open.push(n),p.start(n)))},getWaitingOrConnected:function(){var e=[];return qq.each(c._openChunks,function(t,n){n&&n.length&&e.push(parseInt(t))}),qq.each(c._open,function(t,n){c._openChunks[n]||e.push(parseInt(n))}),e=e.concat(c._waiting)},isUsingConnection:function(e){return qq.indexOf(c._open,e)>=0},open:function(e,t){return null==t&&c._waiting.push(e),!!c.available()&&(null==t?(c._waiting.pop(),c._open.push(e)):function(){var n=c._openChunks[e]||[];n.push(t),c._openChunks[e]=n}(),!0)},reset:function(){c._waiting=[],c._open=[]}},d={send:function(e,t){var n=o._getFileState(e);if(!n)return void i("Ignoring send request as this upload may have been cancelled, File ID "+e,"warn");n.loaded=0,i("Sending simple upload request for "+e),o.uploadFile(e).then(function(n,o){i("Simple upload request succeeded for "+e);var r=p.normalizeResponse(n,!0),a=u.getSize(e);u.onProgress(e,t,a,a),p.maybeNewUuid(e,r),p.cleanup(e,r,o)},function(n,o){i("Simple upload request failed for "+e);var r=p.normalizeResponse(n,!1);u.onAutoRetry(e,t,r,o)||p.cleanup(e,r,o)})}},p={cancel:function(e){i("Cancelling "+e),u.paramsStore.remove(e),c.free(e)},cleanup:function(e,t,n){var i=u.getName(e);u.onComplete(e,i,t,n),o._getFileState(e)&&o._clearXhrs&&o._clearXhrs(e),c.free(e)},getProxyOrBlob:function(e){return o.getProxy&&o.getProxy(e)||o.getFile&&o.getFile(e)},initHandler:function(){o=new(t?qq[t]:qq.traditional)[(qq.supportedFeatures.ajaxUploading?"Xhr":"Form")+"UploadHandler"](u,{getCustomResumeData:u.getCustomResumeData,getDataByUuid:u.getDataByUuid,getName:u.getName,getSize:u.getSize,getUuid:u.getUuid,log:i,onCancel:u.onCancel,onProgress:u.onProgress,onUuidChanged:u.onUuidChanged,onFinalizing:function(e){u.setStatus(e,qq.status.UPLOAD_FINALIZING)}}),o._removeExpiredChunkingRecords&&o._removeExpiredChunkingRecords()},isDeferredEligibleForUpload:function(e){return u.isQueued(e)},maybeDefer:function(e,t){return t&&!o.getFile(e)&&t instanceof qq.BlobProxy?(u.onUploadPrep(e),i("Attempting to generate a blob on-demand for "+e),t.create().then(function(t){i("Generated an on-demand blob for "+e),o.updateBlob(e,t),u.setSize(e,t.size),o.reevaluateChunking(e),p.maybeSendDeferredFiles(e)},function(t){var o={};t&&(o.error=t),i(qq.format("Failed to generate blob for ID {}. Error message: {}.",e,t),"error"),u.onComplete(e,u.getName(e),qq.extend(o,n),null),p.maybeSendDeferredFiles(e),c.free(e)}),!1):p.maybeSendDeferredFiles(e)},maybeSendDeferredFiles:function(e){var t=u.getIdsInProxyGroup(e),n=!1;return t&&t.length?(i("Maybe ready to upload proxy group file "+e),qq.each(t,function(t,i){if(p.isDeferredEligibleForUpload(i)&&o.getFile(i))n=i===e,p.now(i);else if(p.isDeferredEligibleForUpload(i))return!1})):(n=!0,p.now(e)),n},maybeNewUuid:function(e,t){void 0!==t.newUuid&&u.onUuidChanged(e,t.newUuid)},normalizeResponse:function(e,t){var n=e;return qq.isObject(e)||(n={},qq.isString(e)&&!t&&(n.error=e)),n.success=t,n},now:function(e){var t=u.getName(e);if(!r.isValid(e))throw new qq.Error(e+" is not a valid file ID to upload!");u.onUpload(e,t).then(function(n){n&&n.pause?(u.setStatus(e,qq.status.PAUSED),o.pause(e),c.free(e)):a&&o._shouldChunkThisFile(e)?l.sendNext(e):d.send(e,t)},function(n){if(n=n||{},i(e+" upload start aborted due to rejected onUpload Promise - details: "+n,"error"),!u.onAutoRetry(e,t,n.responseJSON||{})){var o=p.normalizeResponse(n.responseJSON,!1);p.cleanup(e,o)}})},start:function(e){var t=p.getProxyOrBlob(e);return t?p.maybeDefer(e,t):(p.now(e),!0)}};qq.extend(this,{add:function(e,t){o.add.apply(this,arguments)},upload:function(e){return!!c.open(e)&&p.start(e)},retry:function(e){return s&&(o._getFileState(e).temp.ignoreFailure=!1),c.isUsingConnection(e)?p.start(e):r.upload(e)},cancel:function(e){var t=o.cancel(e);qq.isGenericPromise(t)?t.then(function(){p.cancel(e)}):t!==!1&&p.cancel(e)},cancelAll:function(){var e,t=c.getWaitingOrConnected();if(t.length)for(e=t.length-1;e>=0;e--)r.cancel(t[e]);c.reset()},getFile:function(e){return o.getProxy&&o.getProxy(e)?o.getProxy(e).referenceBlob:o.getFile&&o.getFile(e)},isProxied:function(e){return!(!o.getProxy||!o.getProxy(e))},getInput:function(e){if(o.getInput)return o.getInput(e)},reset:function(){i("Resetting upload handler"),r.cancelAll(),c.reset(),o.reset()},expunge:function(e){if(r.isValid(e))return o.expunge(e)},isValid:function(e){return o.isValid(e)},hasResumeRecord:function(e){var t=o.isValid(e)&&o._getLocalStorageId&&o._getLocalStorageId(e);return!!t&&!!localStorage.getItem(t)},getResumableFilesData:function(){return o.getResumableFilesData?o.getResumableFilesData():[]},getThirdPartyFileId:function(e){if(r.isValid(e))return o.getThirdPartyFileId(e)},pause:function(e){return!!(r.isResumable(e)&&o.pause&&r.isValid(e)&&o.pause(e))&&(c.free(e),o.moveInProgressToRemaining(e),!0)},isAttemptingResume:function(e){return!!o.isAttemptingResume&&o.isAttemptingResume(e)},isResumable:function(e){return!!o.isResumable&&o.isResumable(e)}}),qq.extend(u,e),i=u.log,a=u.chunking.enabled&&qq.supportedFeatures.chunking,s=a&&u.chunking.concurrent.enabled,n=function(){var e={};return e[u.preventRetryParam]=!0,e}(),p.initHandler()},qq.WindowReceiveMessage=function(e){"use strict";var t={log:function(e,t){}},n={};qq.extend(t,e),qq.extend(this,{receiveMessage:function(e,t){var i=function(e){t(e.data)};window.postMessage?n[e]=qq(window).attach("message",i):log("iframe message passing not supported in this browser!","error")},stopReceivingMessages:function(e){if(window.postMessage){var t=n[e];t&&t()}}})},qq.FormUploadHandler=function(e){"use strict";function t(e){delete c[e],p&&(clearTimeout(d[e]),delete d[e],m.stopReceivingMessages(e));var t=document.getElementById(a._getIframeName(e));t&&(t.setAttribute("src","javascript:false;"),qq(t).remove())}function n(e){return e.split("_")[0]}function i(e){var t=qq.toElement("");return t.setAttribute("id",e),t.style.display="none",document.body.appendChild(t),t}function o(e,t){var i=e.id,o=n(i);l[f(o)]=t,c[o]=qq(e).attach("load",function(){a.getInput(o)&&(q("Received iframe load event for CORS upload request (iframe name "+i+")"),d[i]=setTimeout(function(){var e="No valid message received from loaded iframe for iframe name "+i;q(e,"error"),t({error:e})},1e3))}),m.receiveMessage(i,function(e){q("Received the following window message: '"+e+"'");var t,o=(n(i),a._parseJsonResponse(e)),r=o.uuid;r&&l[r]?(q("Handling response for iframe name "+i),clearTimeout(d[i]),delete d[i],a._detachLoadEvent(i),t=l[r],delete l[r],m.stopReceivingMessages(i),t(o)):r||q("'"+e+"' does not contain a UUID - ignoring.")})}var r=e.options,a=this,s=e.proxy,u=qq.getUniqueId(),l={},c={},d={},p=r.isCors,h=r.inputName,f=s.getUuid,q=s.log,m=new qq.WindowReceiveMessage({log:q});qq.extend(this,new qq.UploadHandler(e)),qq.override(this,function(e){return{add:function(t,n){e.add(t,{input:n}),n.setAttribute("name",h),n.parentNode&&qq(n).remove()},expunge:function(n){t(n),e.expunge(n)},isValid:function(t){return e.isValid(t)&&void 0!==a._getFileState(t).input}}}),qq.extend(this,{getInput:function(e){return a._getFileState(e).input},_attachLoadEvent:function(e,t){var n;p?o(e,t):c[e.id]=qq(e).attach("load",function(){if(q("Received response for "+e.id),e.parentNode){try{if(e.contentDocument&&e.contentDocument.body&&"false"==e.contentDocument.body.innerHTML)return}catch(e){q("Error when attempting to access iframe during handling of upload response ("+e.message+")","error"),n={success:!1}}t(n)}})},_createIframe:function(e){return i(a._getIframeName(e))},_detachLoadEvent:function(e){void 0!==c[e]&&(c[e](),delete c[e])},_getIframeName:function(e){return e+"_"+u},_initFormForUpload:function(e){var t=e.method,n=e.endpoint,i=e.params,o=e.paramsInBody,r=e.targetName,a=qq.toElement(""),s=n;return o?qq.obj2Inputs(i,a):s=qq.obj2url(i,n),a.setAttribute("action",s),a.setAttribute("target",r),a.style.display="none",document.body.appendChild(a),a},_parseJsonResponse:function(e){var t={};try{t=qq.parseJson(e)}catch(e){q("Error when attempting to parse iframe upload response ("+e.message+")","error")}return t}})},qq.XhrUploadHandler=function(e){"use strict";function t(e){qq.each(n._getXhrs(e),function(t,i){var o=n._getAjaxRequester(e,t);i.onreadystatechange=null,i.upload.onprogress=null,i.abort(),o&&o.canceled&&o.canceled(e)})}var n=this,i=e.options.namespace,o=e.proxy,r=e.options.chunking,a=function(e){var t=n._getFileState(e);if(t.chunkSize)return t.chunkSize;var i=r.partSize;return qq.isFunction(i)&&(i=i(e,d(e))),t.chunkSize=i,i},s=e.options.resume,u=r&&e.options.chunking.enabled&&qq.supportedFeatures.chunking,l=s&&e.options.resume.enabled&&u&&qq.supportedFeatures.resume,c=o.getName,d=o.getSize,p=o.getUuid,h=o.getEndpoint,f=o.getDataByUuid,q=o.onUuidChanged,m=o.onProgress,g=o.log,_=o.getCustomResumeData;qq.extend(this,new qq.UploadHandler(e)),qq.override(this,function(e){return{add:function(t,i){if(qq.isFile(i)||qq.isBlob(i))e.add(t,{file:i});else{if(!(i instanceof qq.BlobProxy))throw new Error("Passed obj is not a File, Blob, or proxy");e.add(t,{proxy:i})}n._initTempState(t),l&&n._maybePrepareForResume(t)},expunge:function(i){t(i),n._maybeDeletePersistedChunkData(i),n._clearXhrs(i),e.expunge(i)}}}),qq.extend(this,{clearCachedChunk:function(e,t){var i=n._getFileState(e);i&&delete i.temp.cachedChunks[t]},clearXhr:function(e,t){var i=n._getFileState(e).temp;i.xhrs&&delete i.xhrs[t],i.ajaxRequesters&&delete i.ajaxRequesters[t]},finalizeChunks:function(e,t){var i=n._getTotalChunks(e)-1,o=n._getXhr(e,i);return t?(new qq.Promise).success(t(o),o):(new qq.Promise).success({},o)},getFile:function(e){return n.isValid(e)&&n._getFileState(e).file},getProxy:function(e){return n.isValid(e)&&n._getFileState(e).proxy},getResumableFilesData:function(){var e=[];return n._iterateResumeRecords(function(t,i){n.moveInProgressToRemaining(null,i.chunking.inProgress,i.chunking.remaining);var o={name:i.name,remaining:i.chunking.remaining,size:i.size,uuid:i.uuid};i.key&&(o.key=i.key),i.customResumeData&&(o.customResumeData=i.customResumeData),e.push(o)}),e},isAttemptingResume:function(e){return n._getFileState(e).attemptingResume},isResumable:function(e){return!!r&&n.isValid(e)&&!n._getFileState(e).notResumable},moveInProgressToRemaining:function(e,t,i){var o=n._getFileState(e)||{},r=o.chunking||{},a=t||r.inProgress,s=i||r.remaining;a&&(g(qq.format("Moving these chunks from in-progress {}, to remaining.",JSON.stringify(a))),a.reverse(),qq.each(a,function(e,t){s.unshift(t)}),a.length=0)},pause:function(e){if(n.isValid(e))return g(qq.format("Aborting XHR upload for {} '{}' due to pause instruction.",e,c(e))),n._getFileState(e).paused=!0,t(e),!0},reevaluateChunking:function(e){if(r&&n.isValid(e)){var t,i,o=n._getFileState(e);if(delete o.chunking,o.chunking={},t=n._getTotalChunks(e),t>1||r.mandatory){for(o.chunking.enabled=!0,o.chunking.parts=t,o.chunking.remaining=[],i=0;i=o?o:s+i,l=n._getTotalChunks(e),c=this._getFileState(e).temp.cachedChunks,p=c[t]||qq.sliceBlob(r,s,u);return c[t]=p,{part:t,start:s,end:u,count:l,blob:p,size:u-s}},_getChunkDataForCallback:function(e){return{partIndex:e.part,startByte:e.start+1,endByte:e.end,totalParts:e.count}},_getLocalStorageId:function(e){var t=c(e),n=d(e),o=a(e),r=h(e),u=s.customKeys(e),l=qq.format("qq{}resume{}-{}-{}-{}-{}",i,"5.0",t,n,o,r);return u.forEach(function(e){l+="-"+e}),l},_getMimeType:function(e){return n.getFile(e).type},_getPersistableData:function(e){return n._getFileState(e).chunking},_getTotalChunks:function(e){if(r){var t=d(e),n=a(e);return Math.ceil(t/n)}},_getXhr:function(e,t){var i=null==t?-1:t;return n._getFileState(e).temp.xhrs[i]},_getXhrs:function(e){return n._getFileState(e).temp.xhrs},_iterateResumeRecords:function(e){l&&qq.each(localStorage,function(t,n){if(0===t.indexOf(qq.format("qq{}resume",i))){e(t,JSON.parse(n))}})},_initTempState:function(e){n._getFileState(e).temp={ajaxRequesters:{},chunkProgress:{},xhrs:{},cachedChunks:{}}},_markNotResumable:function(e){n._getFileState(e).notResumable=!0},_maybeDeletePersistedChunkData:function(e){var t;return!!(l&&n.isResumable(e)&&(t=n._getLocalStorageId(e),t&&localStorage.getItem(t)))&&(localStorage.removeItem(t),!0)},_maybePrepareForResume:function(e){var t,i,o=n._getFileState(e);l&&void 0===o.key&&(t=n._getLocalStorageId(e),i=localStorage.getItem(t),i&&(i=JSON.parse(i),f(i.uuid)?n._markNotResumable(e):(g(qq.format("Identified file with ID {} and name of {} as resumable.",e,c(e))),q(e,i.uuid),o.key=i.key,o.chunking=i.chunking,o.loaded=i.loaded,o.customResumeData=i.customResumeData,o.attemptingResume=!0,n.moveInProgressToRemaining(e))))},_maybePersistChunkedState:function(e){var t,i,o=n._getFileState(e);if(l&&n.isResumable(e)){var r=_(e);t=n._getLocalStorageId(e),i={name:c(e),size:d(e),uuid:p(e),key:o.key,chunking:o.chunking,loaded:o.loaded,lastUpdated:Date.now()},r&&(i.customResumeData=r);try{localStorage.setItem(t,JSON.stringify(i))}catch(t){g(qq.format("Unable to save resume data for '{}' due to error: '{}'.",e,t.toString()),"warn")}}},_registerProgressHandler:function(e,t,i){var o=n._getXhr(e,t),r=c(e),a={simple:function(t,n){var i=d(e);t===n?m(e,r,i,i):m(e,r,t>=i?i-1:t,i)},chunked:function(o,a){var s=n._getFileState(e).temp.chunkProgress,u=n._getFileState(e).loaded,l=o,c=a,p=d(e),h=l-(c-i),f=u;s[t]=h,qq.each(s,function(e,t){f+=t}),m(e,r,f,p)}};o.upload.onprogress=function(e){if(e.lengthComputable){a[null==i?"simple":"chunked"](e.loaded,e.total)}}},_registerXhr:function(e,t,i,o){var r=null==t?-1:t,a=n._getFileState(e).temp;return a.xhrs=a.xhrs||{},a.ajaxRequesters=a.ajaxRequesters||{},a.xhrs[r]=i,o&&(a.ajaxRequesters[r]=o),i},_removeExpiredChunkingRecords:function(){var e=s.recordsExpireIn;n._iterateResumeRecords(function(t,n){var i=new Date(n.lastUpdated);i.setDate(i.getDate()+e),i.getTime()<=Date.now()&&(g("Removing expired resume record with key "+t),localStorage.removeItem(t))})},_shouldChunkThisFile:function(e){var t=n._getFileState(e);if(t)return t.chunking||n.reevaluateChunking(e),t.chunking.enabled}})},qq.DeleteFileAjaxRequester=function(e){"use strict";function t(){return"POST"===i.method.toUpperCase()?{_method:"DELETE"}:{}}var n,i={method:"DELETE",uuidParamName:"qquuid",endpointStore:{},maxConnections:3,customHeaders:function(e){return{}},paramsStore:{},cors:{expected:!1,sendCredentials:!1},log:function(e,t){},onDelete:function(e){},onDeleteComplete:function(e,t,n){}};qq.extend(i,e),n=qq.extend(this,new qq.AjaxRequester({acceptHeader:"application/json",validMethods:["POST","DELETE"],method:i.method,endpointStore:i.endpointStore,paramsStore:i.paramsStore,mandatedParams:t(),maxConnections:i.maxConnections,customHeaders:function(e){return i.customHeaders.get(e)},log:i.log,onSend:i.onDelete,onComplete:i.onDeleteComplete,cors:i.cors})),qq.extend(this,{sendDelete:function(e,t,o){var r=o||{};i.log("Submitting delete file request for "+e),"DELETE"===i.method?n.initTransport(e).withPath(t).withParams(r).send():(r[i.uuidParamName]=t,n.initTransport(e).withParams(r).send())}})},function(){function e(e){var t,n=e.naturalWidth,i=e.naturalHeight,o=document.createElement("canvas");return n*i>1048576&&(o.width=o.height=1,t=o.getContext("2d"),t.drawImage(e,-n+1,0),0===t.getImageData(0,0,1,1).data[3])}function t(e,t,n){var i,o,r,a,s=document.createElement("canvas"),u=0,l=n,c=n;for(s.width=1,s.height=n,i=s.getContext("2d"),i.drawImage(e,0,0),o=i.getImageData(0,0,1,n).data;c>u;)r=o[4*(c-1)+3],0===r?l=c:u=c,c=l+u>>1;return a=c/n,0===a?1:a}function n(e,t,n,i){var r=document.createElement("canvas"),a=n.mime||"image/jpeg",s=new qq.Promise;return o(e,t,r,n,i).then(function(){s.success(r.toDataURL(a,n.quality||.8))}),s}function i(e){if(!qq.ios())throw new qq.Error("Downsampled dimensions can only be reliably calculated for iOS!");if(e.origHeight*e.origWidth>5241e3)return{newHeight:Math.round(Math.sqrt(5241e3*(e.origHeight/e.origWidth))),newWidth:Math.round(Math.sqrt(5241e3*(e.origWidth/e.origHeight)))}}function o(n,o,s,u,l){var c,d=n.naturalWidth,p=n.naturalHeight,h=u.width,f=u.height,q=s.getContext("2d"),m=new qq.Promise;return q.save(),u.resize?r({blob:o,canvas:s,image:n,imageHeight:p,imageWidth:d,orientation:u.orientation,resize:u.resize,targetHeight:f,targetWidth:h}):(qq.supportedFeatures.unlimitedScaledImageSize||(c=i({origWidth:h,origHeight:f}),c&&(qq.log(qq.format("Had to reduce dimensions due to device limitations from {}w / {}h to {}w / {}h",h,f,c.newWidth,c.newHeight),"warn"),h=c.newWidth,f=c.newHeight)),a(s,h,f,u.orientation),qq.ios()?function(){e(n)&&(d/=2,p/=2);var i,o,r,a=1024,s=document.createElement("canvas"),u=l?t(n,d,p):1,c=Math.ceil(a*h/d),m=Math.ceil(a*f/p/u),g=0,_=0;for(s.width=s.height=a,i=s.getContext("2d");gc&&(u=c,l=s*u/a<<0),d&&l>d&&(l=d,u=a*l/s<<0),i={width:u,height:l},qq.each(t,function(e,t){i[e]=t}),"img"===h?function(){var t=e.src;n(r.srcImage,r.blob,i,p).then(function(n){e.src=n,t===e.src&&e.onload()})}():"canvas"===h&&o(this.srcImage,this.blob,e,i,p),"function"==typeof this.onrender&&this.onrender(e)},qq.MegaPixImage=s}(),qq.ImageGenerator=function(e){"use strict";function t(e){return"img"===e.tagName.toLowerCase()}function n(e){return"canvas"===e.tagName.toLowerCase()}function i(){return void 0!==(new Image).crossOrigin}function o(){var e=document.createElement("canvas");return e.getContext&&e.getContext("2d")}function r(e){var t=e.split("/"),n=t[t.length-1].split("?")[0],i=qq.getExtension(n);switch(i=i&&i.toLowerCase()){case"jpeg":case"jpg":return"image/jpeg";case"png":return"image/png";case"bmp":return"image/bmp";case"gif":return"image/gif";case"tiff":case"tif":return"image/tiff"}}function a(e){var t,n,i,o=document.createElement("a");return o.href=e,t=o.protocol,i=o.port,n=o.hostname,t.toLowerCase()!==window.location.protocol.toLowerCase()||(n.toLowerCase()!==window.location.hostname.toLowerCase()||i!==window.location.port&&!qq.ie())}function s(t,n){t.onload=function(){t.onload=null,t.onerror=null,n.success(t)},t.onerror=function(){t.onload=null,t.onerror=null,e("Problem drawing thumbnail!","error"),n.failure(t,"Problem drawing thumbnail!")}}function u(e,t){e.qqImageRendered=function(){t.success(e)}}function l(i,o){var r=t(i)||n(i);return t(i)?s(i,o):n(i)?u(i,o):(o.failure(i),e(qq.format("Element container of type {} is not supported!",i.tagName),"error")),r}function c(t,n,i){var o=new qq.Promise,r=new qq.Identify(t,e),a=i.maxSize,s=null==i.orient||i.orient,u=function(){n.onerror=null,n.onload=null,e("Could not render preview, file may be too large!","error"),o.failure(n,"Browser cannot render image!")};return r.isPreviewable().then(function(r){var c={parse:function(){return(new qq.Promise).success()}},d=s?new qq.Exif(t,e):c,p=new qq.MegaPixImage(t,u);l(n,o)&&d.parse().then(function(e){var t=e&&e.Orientation;p.render(n,{maxWidth:a,maxHeight:a,orientation:t,mime:r,resize:i.customResizeFunction})},function(t){e(qq.format("EXIF data could not be parsed ({}). Assuming orientation = 1.",t)),p.render(n,{maxWidth:a,maxHeight:a,mime:r,resize:i.customResizeFunction})})},function(){e("Not previewable"),o.failure(n,"Not previewable")}),o}function d(e,t,n,i,o){var s=new Image,u=new qq.Promise;l(s,u),a(e)&&(s.crossOrigin="anonymous"),s.src=e,u.then(function(){l(t,n),new qq.MegaPixImage(s).render(t,{maxWidth:i,maxHeight:i,mime:r(e),resize:o})},n.failure)}function p(e,t,n,i){l(t,n),qq(t).css({maxWidth:i+"px",maxHeight:i+"px"}),t.src=e}function h(e,r,s){var u=new qq.Promise,c=s.scale,h=c?s.maxSize:null;return c&&t(r)?o()?a(e)&&!i()?p(e,r,u,h):d(e,r,u,h):p(e,r,u,h):n(r)?d(e,r,u,h):l(r,u)&&(r.src=e),u}qq.extend(this,{generate:function(t,n,i){return qq.isString(t)?(e("Attempting to update thumbnail based on server response."),h(t,n,i||{})):(e("Attempting to draw client-side image preview."),c(t,n,i||{}))}}),this._testing={},this._testing.isImg=t,this._testing.isCanvas=n,this._testing.isCrossOrigin=a,this._testing.determineMimeOfFileName=r},qq.Exif=function(e,t){"use strict";function n(e){for(var t=0,n=0;e.length>0;)t+=parseInt(e.substring(0,2),16)*Math.pow(2,n),e=e.substring(2,e.length),n+=8;return t}function i(t,n){var o=t,r=n;return void 0===o&&(o=2,r=new qq.Promise),qq.readBlobToHex(e,o,4).then(function(e){var t,n=/^ffe([0-9])/.exec(e);n?"1"!==n[1]?(t=parseInt(e.slice(4,8),16),i(o+t+2,r)):r.success(o):r.failure("No EXIF header to be found!")}),r}function o(){var t=new qq.Promise;return qq.readBlobToHex(e,0,6).then(function(e){0!==e.indexOf("ffd8")?t.failure("Not a valid JPEG!"):i().then(function(e){t.success(e)},function(e){t.failure(e)})}),t}function r(t){var n=new qq.Promise;return qq.readBlobToHex(e,t+10,2).then(function(e){n.success("4949"===e)}),n}function a(t,i){var o=new qq.Promise;return qq.readBlobToHex(e,t+18,2).then(function(e){if(i)return o.success(n(e));o.success(parseInt(e,16))}),o}function s(t,n){var i=t+20,o=12*n;return qq.readBlobToHex(e,i,o)}function u(e){for(var t=[],n=0;n+24<=e.length;)t.push(e.slice(n,n+24)),n+=24;return t}function l(e,t){var i=qq.extend([],c),o={};return qq.each(t,function(t,r){var a,s,u,l=r.slice(0,4),c=e?n(l):parseInt(l,16),p=i.indexOf(c);if(p>=0&&(s=d[c].name,u=d[c].bytes,a=r.slice(16,16+2*u),o[s]=e?n(a):parseInt(a,16),i.splice(p,1)),0===i.length)return!1}),o}var c=[274],d={274:{name:"Orientation",bytes:2}};qq.extend(this,{parse:function(){var n=new qq.Promise,i=function(e){t(qq.format("EXIF header parse failed: '{}' ",e)),n.failure(e)};return o().then(function(o){t(qq.format("Moving forward with EXIF header parsing for '{}'",void 0===e.name?"blob":e.name)),r(o).then(function(e){t(qq.format("EXIF Byte order is {} endian",e?"little":"big")),a(o,e).then(function(r){t(qq.format("Found {} APP1 directory entries",r)),s(o,r).then(function(i){var o=u(i),r=l(e,o);t("Successfully parsed some EXIF tags"),n.success(r)},i)},i)},i)},i),n}}),this._testing={},this._testing.parseLittleEndian=n},qq.Identify=function(e,t){"use strict";function n(e,t){var n=!1,i=[].concat(e);return qq.each(i,function(e,i){if(0===t.indexOf(i))return n=!0,!1}),n}qq.extend(this,{isPreviewable:function(){var i=this,o=new qq.Promise,r=!1,a=void 0===e.name?"blob":e.name;return t(qq.format("Attempting to determine if {} can be rendered in this browser",a)),t("First pass: check type attribute of blob object."),this.isPreviewableSync()?(t("Second pass: check for magic bytes in file header."),qq.readBlobToHex(e,0,4).then(function(e){qq.each(i.PREVIEWABLE_MIME_TYPES,function(t,i){if(n(i,e))return("image/tiff"!==t||qq.supportedFeatures.tiffPreviews)&&(r=!0,o.success(t)),!1}),t(qq.format("'{}' is {} able to be rendered in this browser",a,r?"":"NOT")),r||o.failure()},function(){t("Error reading file w/ name '"+a+"'. Not able to be rendered in this browser."),o.failure()})):o.failure(),o},isPreviewableSync:function(){var n=e.type,i=qq.indexOf(Object.keys(this.PREVIEWABLE_MIME_TYPES),n)>=0,o=!1,r=void 0===e.name?"blob":e.name;return i&&(o="image/tiff"!==n||qq.supportedFeatures.tiffPreviews),!o&&t(r+" is not previewable in this browser per the blob's type attr"),o}})},qq.Identify.prototype.PREVIEWABLE_MIME_TYPES={"image/jpeg":"ffd8ff","image/gif":"474946","image/png":"89504e","image/bmp":"424d","image/tiff":["49492a00","4d4d002a"]},qq.ImageValidation=function(e,t){"use strict";function n(e){var t=!1;return qq.each(e,function(e,n){if(n>0)return t=!0,!1}),t}function i(){var n=new qq.Promise;return new qq.Identify(e,t).isPreviewable().then(function(){var i=new Image,o=window.URL&&window.URL.createObjectURL?window.URL:window.webkitURL&&window.webkitURL.createObjectURL?window.webkitURL:null;o?(i.onerror=function(){t("Cannot determine dimensions for image. May be too large.","error"),n.failure()},i.onload=function(){n.success({width:this.width,height:this.height})},i.src=o.createObjectURL(e)):(t("No createObjectURL function available to generate image URL!","error"),n.failure())},n.failure),n}function o(e,t){var n;return qq.each(e,function(e,i){if(i>0){var o=/(max|min)(Width|Height)/.exec(e),r=o[2].charAt(0).toLowerCase()+o[2].slice(1),a=t[r];switch(o[1]){case"min":if(ai)return n=e,!1}}}),n}this.validate=function(e){var r=new qq.Promise;return t("Attempting to validate image."),n(e)?i().then(function(t){var n=o(e,t);n?r.failure(n):r.success()},r.success):r.success(),r}},qq.Session=function(e){"use strict";function t(e){if(qq.isArray(e))return!0;i.log("Session response is not an array.","error")}function n(e,n,o,r){var a=!1;n=n&&t(e),n&&qq.each(e,function(e,t){if(null==t.uuid)a=!0,i.log(qq.format("Session response item {} did not include a valid UUID - ignoring.",e),"error");else if(null==t.name)a=!0,i.log(qq.format("Session response item {} did not include a valid name - ignoring.",e),"error");else try{return i.addFileRecord(t),!0}catch(e){a=!0,i.log(e.message,"error")}return!1}),r[n&&!a?"success":"failure"](e,o)}var i={endpoint:null,params:{},customHeaders:{},cors:{},addFileRecord:function(e){},log:function(e,t){}};qq.extend(i,e,!0),this.refresh=function(){var e=new qq.Promise,t=function(t,i,o){n(t,i,o,e)},o=qq.extend({},i);return new qq.SessionAjaxRequester(qq.extend(o,{onComplete:t})).queryServer(),e}},qq.SessionAjaxRequester=function(e){"use strict";function t(e,t,n){var o=null;if(null!=t.responseText)try{o=qq.parseJson(t.responseText)}catch(e){i.log("Problem parsing session response: "+e.message,"error"),n=!0}i.onComplete(o,!n,t)}var n,i={endpoint:null,customHeaders:{},params:{},cors:{expected:!1,sendCredentials:!1},onComplete:function(e,t,n){},log:function(e,t){}};qq.extend(i,e),n=qq.extend(this,new qq.AjaxRequester({acceptHeader:"application/json",validMethods:["GET"],method:"GET",endpointStore:{get:function(){return i.endpoint}},customHeaders:i.customHeaders,log:i.log,onComplete:t,cors:i.cors})),qq.extend(this,{queryServer:function(){var e=qq.extend({},i.params);i.log("Session query request."),n.initTransport("sessionRefresh").withParams(e).withCacheBuster().send()}})},qq.Scaler=function(e,t){"use strict";var n=e.customResizer,i=e.sendOriginal,o=e.orient,r=e.defaultType,a=e.defaultQuality/100,s=e.failureText,u=e.includeExif,l=this._getSortedSizes(e.sizes);qq.extend(this,{enabled:qq.supportedFeatures.scaling&&l.length>0,getFileRecords:function(e,c,d){var p=this,h=[],f=d.blob?d.blob:d;return new qq.Identify(f,t).isPreviewableSync()?(qq.each(l,function(e,i){var l=p._determineOutputType({defaultType:r,requestedType:i.type,refType:f.type});h.push({uuid:qq.getUniqueId(),name:p._getName(c,{name:i.name,type:l,refType:f.type}),blob:new qq.BlobProxy(f,qq.bind(p._generateScaledImage,p,{customResizeFunction:n,maxSize:i.maxSize,orient:o,type:l,quality:a,failedText:s,includeExif:u,log:t}))})}),h.push({uuid:e,name:c,size:f.size,blob:i?f:null})):h.push({uuid:e,name:c,size:f.size,blob:f}),h},handleNewFile:function(e,t,n,i,o,r,a,s){var u=this,l=(e.qqButtonId||e.blob&&e.blob.qqButtonId,[]),c=null,d=s.addFileToHandler,p=s.uploadData,h=s.paramsStore,f=qq.getUniqueId();qq.each(u.getFileRecords(n,t,e),function(e,t){var n,i=t.size
+;t.blob instanceof qq.BlobProxy&&(i=-1),n=p.addFile({uuid:t.uuid,name:t.name,size:i,batchId:r,proxyGroupId:f}),t.blob instanceof qq.BlobProxy?l.push(n):c=n,t.blob?(d(n,t.blob),o.push({id:n,file:t.blob})):p.setStatus(n,qq.status.REJECTED)}),null!==c&&(qq.each(l,function(e,t){var n={qqparentuuid:p.retrieve({id:c}).uuid,qqparentsize:p.retrieve({id:c}).size};n[a]=p.retrieve({id:t}).uuid,p.setParentId(t,c),h.addReadOnly(t,n)}),l.length&&function(){var e={};e[a]=p.retrieve({id:c}).uuid,h.addReadOnly(c,e)}())}})},qq.extend(qq.Scaler.prototype,{scaleImage:function(e,t,n){"use strict";if(!qq.supportedFeatures.scaling)throw new qq.Error("Scaling is not supported in this browser!");var i=new qq.Promise,o=n.log,r=n.getFile(e),a=n.uploadData.retrieve({id:e}),s=a&&a.name,u=a&&a.uuid,l={customResizer:t.customResizer,sendOriginal:!1,orient:t.orient,defaultType:t.type||null,defaultQuality:t.quality,failedToScaleText:"Unable to scale",sizes:[{name:"",maxSize:t.maxSize}]},c=new qq.Scaler(l,o);return qq.Scaler&&qq.supportedFeatures.imagePreviews&&r?qq.bind(function(){var t=c.getFileRecords(u,s,r)[0];t&&t.blob instanceof qq.BlobProxy?t.blob.create().then(i.success,i.failure):(o(e+" is not a scalable image!","error"),i.failure())},this)():(i.failure(),o("Could not generate requested scaled image for "+e+". Scaling is either not possible in this browser, or the file could not be located.","error")),i},_determineOutputType:function(e){"use strict";var t=e.requestedType,n=e.defaultType,i=e.refType;return n||t?t&&qq.indexOf(Object.keys(qq.Identify.prototype.PREVIEWABLE_MIME_TYPES),t)>=0?"image/tiff"===t?qq.supportedFeatures.tiffPreviews?t:n:t:n:"image/jpeg"!==i?"image/png":i},_getName:function(e,t){"use strict";var n=e.lastIndexOf("."),i=t.type||"image/png",o=t.refType,r="",a=qq.getExtension(e),s="";return t.name&&t.name.trim().length&&(s=" ("+t.name+")"),n>=0?(r=e.substr(0,n),o!==i&&(a=i.split("/")[1]),r+=s+"."+a):r=e+s,r},_getSortedSizes:function(e){"use strict";return e=qq.extend([],e),e.sort(function(e,t){return e.maxSize>t.maxSize?1:e.maxSize=0?atob(e.split(",")[1]):decodeURI(e.split(",")[1]),n=e.split(",")[0].split(":")[1].split(";")[0],i=new ArrayBuffer(t.length),o=new Uint8Array(i),qq.each(t,function(e,t){o[e]=t.charCodeAt(0)}),this._createBlob(i,n)},_createBlob:function(e,t){"use strict";var n=window.BlobBuilder||window.WebKitBlobBuilder||window.MozBlobBuilder||window.MSBlobBuilder,i=n&&new n;return i?(i.append(e),i.getBlob(t)):new Blob([e],{type:t})}}),qq.ExifRestorer=function(){var e={};return e.KEY_STR="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",e.encode64=function(e){var t,n,i,o,r,a="",s="",u="",l=0;do t=e[l++],n=e[l++],s=e[l++],i=t>>2,o=(3&t)<<4|n>>4,r=(15&n)<<2|s>>6,u=63&s,isNaN(n)?r=u=64:isNaN(s)&&(u=64),a=a+this.KEY_STR.charAt(i)+this.KEY_STR.charAt(o)+this.KEY_STR.charAt(r)+this.KEY_STR.charAt(u),t=n=s="",i=o=r=u="";while(le.length)break}return n},e.decode64=function(e){var t,n,i,o,r,a="",s="",u=0,l=[];if(/[^A-Za-z0-9\+\/\=]/g.exec(e))throw new Error("There were invalid base64 characters in the input text. Valid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='");e=e.replace(/[^A-Za-z0-9\+\/\=]/g,"");do i=this.KEY_STR.indexOf(e.charAt(u++)),o=this.KEY_STR.indexOf(e.charAt(u++)),r=this.KEY_STR.indexOf(e.charAt(u++)),s=this.KEY_STR.indexOf(e.charAt(u++)),t=i<<2|o>>4,n=(15&o)<<4|r>>2,a=(3&r)<<6|s,l.push(t),64!=r&&l.push(n),64!=s&&l.push(a),t=n=a="",i=o=r=s="";while(u=0)return n=!1,!1}),n},l=function(e){p(e,-1,-1),delete n[e]},c=function(e,t,n){(0===t.length||u(t,n))&&(s(o,o),this.reset())},d=function(e){var i=t(e);i>0&&(p(e,0,i),n[e]={loaded:0,total:i})},p=function(e,t,r){var a=n[e]?n[e].loaded:0,u=n[e]?n[e].total:0;t===-1&&r===-1?(i-=a,o-=u):(t&&(i+=t-a),r&&(o+=r-u)),s(i,o)};qq.extend(this,{onAllComplete:c,onStatusChange:function(e,t,n){n===qq.status.CANCELED||n===qq.status.REJECTED?l(e):n===qq.status.SUBMITTING&&d(e)},onIndividualProgress:function(e,t,i){p(e,t,i),n[e]={loaded:t,total:i}},onNewSize:function(e){d(e)},reset:function(){n={},i=0,o=0}})},qq.PasteSupport=function(e){"use strict";function t(e){return e.type&&0===e.type.indexOf("image/")}function n(){r=qq(o.targetElement).attach("paste",function(e){var n=e.clipboardData;n&&qq.each(n.items,function(e,n){if(t(n)){var i=n.getAsFile();o.callbacks.pasteReceived(i)}})})}function i(){r&&r()}var o,r;o={targetElement:null,callbacks:{log:function(e,t){},pasteReceived:function(e){}}},qq.extend(o,e),n(),qq.extend(this,{reset:function(){i()}})},qq.FormSupport=function(e,t,n){"use strict";function i(e){e.getAttribute("action")&&(s.newEndpoint=e.getAttribute("action"))}function o(e,t){if(!e.checkValidity||e.checkValidity())return!0;n("Form did not pass validation checks - will not upload.","error"),t()}function r(e){var n=e.submit;qq(e).attach("submit",function(i){i=i||window.event,i.preventDefault?i.preventDefault():i.returnValue=!1,o(e,n)&&t()}),e.submit=function(){o(e,n)&&t()}}function a(e){return e&&(qq.isString(e)&&(e=document.getElementById(e)),e&&(n("Attaching to form element."),i(e),u&&r(e))),e}var s=this,u=e.interceptSubmit,l=e.element,c=e.autoUpload;qq.extend(this,{newEndpoint:null,newAutoUpload:c,attachedToForm:!1,getFormInputsAsObject:function(){return null==l?null:s._form2Obj(l)}}),l=a(l),this.attachedToForm=!!l},qq.extend(qq.FormSupport.prototype,{_form2Obj:function(e){"use strict";var t={},n=function(e){var t=["button","image","reset","submit"];return qq.indexOf(t,e.toLowerCase())<0},i=function(e){return qq.indexOf(["checkbox","radio"],e.toLowerCase())>=0},o=function(e){return!(!i(e.type)||e.checked)||e.disabled&&"hidden"!==e.type.toLowerCase()},r=function(e){var t=null;return qq.each(qq(e).children(),function(e,n){if("option"===n.tagName.toLowerCase()&&n.selected)return t=n.value,!1}),t};return qq.each(e.elements,function(e,i){if(!qq.isInput(i,!0)&&"textarea"!==i.tagName.toLowerCase()||!n(i.type)||o(i)){if("select"===i.tagName.toLowerCase()&&!o(i)){var a=r(i);null!==a&&(t[i.name]=a)}}else t[i.name]=i.value}),t}}),qq.traditional=qq.traditional||{},qq.traditional.FormUploadHandler=function(e,t){"use strict";function n(e,t){var n,i,r;try{i=t.contentDocument||t.contentWindow.document,r=i.body.innerHTML,s("converting iframe's innerHTML to JSON"),s("innerHTML = "+r),r&&r.match(/^1&&!c.allowMultipleItems?(c.callbacks.processingDroppedFilesComplete([]),c.callbacks.dropError("tooManyFilesError",""),t.dropDisabled(!1),o.failure()):(p=[],qq.isFolderDropSupported(e)?qq.each(e.items,function(e,t){var r=t.webkitGetAsEntry();r&&(r.isFile?p.push(t.getAsFile()):i.push(n(r).done(function(){i.pop(),0===i.length&&o.success()})))}):p=e.files,0===i.length&&o.success()),o}function a(e){var n=new qq.UploadDropZone({HIDE_ZONES_EVENT_NAME:"qq-hidezones",element:e,onEnter:function(t){qq(e).addClass(c.classes.dropActive),t.stopPropagation()},onLeaveNotDescendants:function(t){qq(e).removeClass(c.classes.dropActive)},onDrop:function(e){r(e.dataTransfer,n).then(function(){t(p,n)},function(){c.callbacks.dropLog("Drop event DataTransfer parsing failed. No files will be uploaded.","error")})}});return h.addDisposer(function(){n.dispose()}),qq(e).hasAttribute("qq-hide-dropzone")&&qq(e).hide(),d.push(n),n}function s(e){var t;return qq.each(e.dataTransfer.types,function(e,n){if("Files"===n)return t=!0,!1}),t}function u(e){return qq.safari()?e.x<0||e.y<0:0===e.x&&0===e.y}function l(){var e=c.dropZoneElements,t=function(){setTimeout(function(){qq.each(e,function(e,t){qq(t).hasAttribute("qq-hide-dropzone")&&qq(t).hide(),qq(t).removeClass(c.classes.dropActive)})},10)};qq.each(e,function(t,n){var i=a(n);e.length&&qq.supportedFeatures.fileDrop&&h.attach(document,"dragenter",function(t){!i.dropDisabled()&&s(t)&&qq.each(e,function(e,t){t instanceof HTMLElement&&qq(t).hasAttribute("qq-hide-dropzone")&&qq(t).css({display:"block"})})})}),h.attach(document,"dragleave",function(e){u(e)&&t()}),h.attach(qq(document).children()[0],"mouseenter",function(e){t()}),h.attach(document,"drop",function(e){s(e)&&(e.preventDefault(),t())}),h.attach(document,"qq-hidezones",t)}var c,d=[],p=[],h=new qq.DisposeSupport;c={dropZoneElements:[],allowMultipleItems:!0,classes:{dropActive:null},callbacks:new qq.DragAndDrop.callbacks},qq.extend(c,e,!0),l(),qq.extend(this,{setupExtraDropzone:function(e){c.dropZoneElements.push(e),a(e)},removeDropzone:function(e){var t,n=c.dropZoneElements;for(t in n)if(n[t]===e)return n.splice(t,1)},dispose:function(){h.dispose(),qq.each(d,function(e,t){t.dispose()})}}),this._testing={},this._testing.extractDirectoryPath=i},qq.DragAndDrop.callbacks=function(){"use strict";return{processingDroppedFiles:function(){},processingDroppedFilesComplete:function(e,t){},dropError:function(e,t){qq.log("Drag & drop error code '"+e+" with these specifics: '"+t+"'","error")},dropLog:function(e,t){qq.log(e,t)}}},qq.UploadDropZone=function(e){"use strict";function t(){return qq.safari()||qq.firefox()&&qq.windows()}function n(e){c||(t?d.attach(document,"dragover",function(e){e.preventDefault()}):d.attach(document,"dragover",function(e){e.dataTransfer&&(e.dataTransfer.dropEffect="none",e.preventDefault())}),c=!0)}function i(e){if(!qq.supportedFeatures.fileDrop)return!1;var t,n=e.dataTransfer,i=qq.safari();return t=!(!qq.ie()||!qq.supportedFeatures.fileDrop)||"none"!==n.effectAllowed,n&&t&&(n.files&&n.files.length||!i&&n.types.contains&&n.types.contains("Files")||n.types.includes&&n.types.includes("Files"))}function o(e){return void 0!==e&&(l=e),l}function r(){function e(){t=document.createEvent("Event"),t.initEvent(s.HIDE_ZONES_EVENT_NAME,!0,!0)}var t;if(window.CustomEvent)try{t=new CustomEvent(s.HIDE_ZONES_EVENT_NAME)}catch(t){e()}else e();document.dispatchEvent(t)}function a(){d.attach(u,"dragover",function(e){if(i(e)){var t=qq.ie()&&qq.supportedFeatures.fileDrop?null:e.dataTransfer.effectAllowed;e.dataTransfer.dropEffect="move"===t||"linkMove"===t?"move":"copy",e.stopPropagation(),e.preventDefault()}}),d.attach(u,"dragenter",function(e){if(!o()){if(!i(e))return;s.onEnter(e)}}),d.attach(u,"dragleave",function(e){if(i(e)){s.onLeave(e);var t=document.elementFromPoint(e.clientX,e.clientY);qq(this).contains(t)||s.onLeaveNotDescendants(e)}}),d.attach(u,"drop",function(e){if(!o()){if(!i(e))return;e.preventDefault(),e.stopPropagation(),s.onDrop(e),r()}})}var s,u,l,c,d=new qq.DisposeSupport;s={element:null,onEnter:function(e){},onLeave:function(e){},onLeaveNotDescendants:function(e){},onDrop:function(e){}},qq.extend(s,e),u=s.element,n(),a(),qq.extend(this,{dropDisabled:function(e){return o(e)},dispose:function(){d.dispose()},getElement:function(){return u}}),this._testing={},this._testing.isValidFileDrag=i},function(){"use strict";qq.uiPublicApi={addInitialFiles:function(e){this._parent.prototype.addInitialFiles.apply(this,arguments),this._templating.addCacheToDom()},clearStoredFiles:function(){this._parent.prototype.clearStoredFiles.apply(this,arguments),this._templating.clearFiles()},addExtraDropzone:function(e){this._dnd&&this._dnd.setupExtraDropzone(e)},removeExtraDropzone:function(e){if(this._dnd)return this._dnd.removeDropzone(e)},getItemByFileId:function(e){if(!this._templating.isHiddenForever(e))return this._templating.getFileContainer(e)},reset:function(){this._parent.prototype.reset.apply(this,arguments),this._templating.reset(),!this._options.button&&this._templating.getButton()&&(this._defaultButtonId=this._createUploadButton({element:this._templating.getButton(),title:this._options.text.fileInputTitle}).getButtonId()),this._dnd&&(this._dnd.dispose(),this._dnd=this._setupDragAndDrop()),this._totalFilesInBatch=0,this._filesInBatchAddedToUi=0,this._setupClickAndEditEventHandlers()},setName:function(e,t){var n=this._options.formatFileName(t);this._parent.prototype.setName.apply(this,arguments),this._templating.updateFilename(e,n)},pauseUpload:function(e){var t=this._parent.prototype.pauseUpload.apply(this,arguments);return t&&this._templating.uploadPaused(e),t},continueUpload:function(e){var t=this._parent.prototype.continueUpload.apply(this,arguments);return t&&this._templating.uploadContinued(e),t},getId:function(e){return this._templating.getFileId(e)},getDropTarget:function(e){return this.getFile(e).qqDropTarget}},qq.uiPrivateApi={_getButton:function(e){var t=this._parent.prototype._getButton.apply(this,arguments);return t||e===this._defaultButtonId&&(t=this._templating.getButton()),t},_removeFileItem:function(e){this._templating.removeFile(e)},_setupClickAndEditEventHandlers:function(){this._fileButtonsClickHandler=qq.FileButtonsClickHandler&&this._bindFileButtonsClickEvent(),this._focusinEventSupported=!qq.firefox(),this._isEditFilenameEnabled()&&(this._filenameClickHandler=this._bindFilenameClickEvent(),this._filenameInputFocusInHandler=this._bindFilenameInputFocusInEvent(),this._filenameInputFocusHandler=this._bindFilenameInputFocusEvent())},_setupDragAndDrop:function(){var e=this,t=this._options.dragAndDrop.extraDropzones,n=this._templating,i=n.getDropZone();return i&&t.push(i),new qq.DragAndDrop({dropZoneElements:t,allowMultipleItems:this._options.multiple,classes:{dropActive:this._options.classes.dropActive},callbacks:{processingDroppedFiles:function(){n.showDropProcessing()},processingDroppedFilesComplete:function(t,i){n.hideDropProcessing(),qq.each(t,function(e,t){t.qqDropTarget=i}),t.length&&e.addFiles(t,null,null)},dropError:function(t,n){e._itemError(t,n)},dropLog:function(t,n){e.log(t,n)}}})},_bindFileButtonsClickEvent:function(){var e=this;return new qq.FileButtonsClickHandler({templating:this._templating,log:function(t,n){e.log(t,n)},onDeleteFile:function(t){e.deleteFile(t)},onCancel:function(t){e.cancel(t)},onRetry:function(t){e.retry(t)},onPause:function(t){e.pauseUpload(t)},onContinue:function(t){e.continueUpload(t)},onGetName:function(t){return e.getName(t)}})},_isEditFilenameEnabled:function(){return this._templating.isEditFilenamePossible()&&!this._options.autoUpload&&qq.FilenameClickHandler&&qq.FilenameInputFocusHandler&&qq.FilenameInputFocusHandler},_filenameEditHandler:function(){var e=this,t=this._templating;return{templating:t,log:function(t,n){e.log(t,n)},onGetUploadStatus:function(t){return e.getUploads({id:t}).status},onGetName:function(t){return e.getName(t)},onSetName:function(t,n){e.setName(t,n)},onEditingStatusChange:function(e,n){var i=qq(t.getEditInput(e)),o=qq(t.getFileContainer(e));n?(i.addClass("qq-editing"),t.hideFilename(e),t.hideEditIcon(e)):(i.removeClass("qq-editing"),t.showFilename(e),t.showEditIcon(e)),o.addClass("qq-temp").removeClass("qq-temp")}}},_onUploadStatusChange:function(e,t,n){this._parent.prototype._onUploadStatusChange.apply(this,arguments),this._isEditFilenameEnabled()&&this._templating.getFileContainer(e)&&n!==qq.status.SUBMITTED&&(this._templating.markFilenameEditable(e),this._templating.hideEditIcon(e)),t===qq.status.UPLOAD_RETRYING&&n===qq.status.UPLOADING?(this._templating.hideRetry(e),this._templating.setStatusText(e),qq(this._templating.getFileContainer(e)).removeClass(this._classes.retrying)):n===qq.status.UPLOAD_FAILED&&this._templating.hidePause(e)},_bindFilenameInputFocusInEvent:function(){var e=qq.extend({},this._filenameEditHandler());return new qq.FilenameInputFocusInHandler(e)},_bindFilenameInputFocusEvent:function(){var e=qq.extend({},this._filenameEditHandler());return new qq.FilenameInputFocusHandler(e)},_bindFilenameClickEvent:function(){var e=qq.extend({},this._filenameEditHandler());return new qq.FilenameClickHandler(e)},_storeForLater:function(e){this._parent.prototype._storeForLater.apply(this,arguments),this._templating.hideSpinner(e)},_onAllComplete:function(e,t){this._parent.prototype._onAllComplete.apply(this,arguments),this._templating.resetTotalProgress()},_onSubmit:function(e,t){var n=this.getFile(e);n&&n.qqPath&&this._options.dragAndDrop.reportDirectoryPaths&&this._paramsStore.addReadOnly(e,{qqpath:n.qqPath}),this._parent.prototype._onSubmit.apply(this,arguments),this._addToList(e,t)},_onSubmitted:function(e){this._isEditFilenameEnabled()&&(this._templating.markFilenameEditable(e),this._templating.showEditIcon(e),this._focusinEventSupported||this._filenameInputFocusHandler.addHandler(this._templating.getEditInput(e)))},_onProgress:function(e,t,n,i){this._parent.prototype._onProgress.apply(this,arguments),this._templating.updateProgress(e,n,i),0===i||100===Math.round(n/i*100)?(this._templating.hideCancel(e),this._templating.hidePause(e),this._templating.hideProgress(e),this._templating.setStatusText(e,this._options.text.waitingForResponse),this._displayFileSize(e)):this._displayFileSize(e,n,i)},_onTotalProgress:function(e,t){this._parent.prototype._onTotalProgress.apply(this,arguments),this._templating.updateTotalProgress(e,t)},_onComplete:function(e,t,n,i){function o(t){s&&(a.setStatusText(e),qq(s).removeClass(u._classes.retrying),a.hideProgress(e),u.getUploads({id:e}).status!==qq.status.UPLOAD_FAILED&&a.hideCancel(e),a.hideSpinner(e),t.success?u._markFileAsSuccessful(e):(qq(s).addClass(u._classes.fail),a.showCancel(e),a.isRetryPossible()&&!u._preventRetries[e]&&(qq(s).addClass(u._classes.retryable),a.showRetry(e)),u._controlFailureTextDisplay(e,t)))}var r=this._parent.prototype._onComplete.apply(this,arguments),a=this._templating,s=a.getFileContainer(e),u=this;return r instanceof qq.Promise?r.done(function(e){o(e)}):o(n),r},_markFileAsSuccessful:function(e){var t=this._templating;this._isDeletePossible()&&t.showDeleteButton(e),qq(t.getFileContainer(e)).addClass(this._classes.success),this._maybeUpdateThumbnail(e)},_onUploadPrep:function(e){this._parent.prototype._onUploadPrep.apply(this,arguments),this._templating.showSpinner(e)},_onUpload:function(e,t){var n=this._parent.prototype._onUpload.apply(this,arguments);return this._templating.showSpinner(e),n},_onUploadChunk:function(e,t){this._parent.prototype._onUploadChunk.apply(this,arguments),t.partIndex>0&&this._handler.isResumable(e)&&this._templating.allowPause(e)},_onCancel:function(e,t){this._parent.prototype._onCancel.apply(this,arguments),this._removeFileItem(e),0===this._getNotFinished()&&this._templating.resetTotalProgress()},_onBeforeAutoRetry:function(e){var t,n,i;this._parent.prototype._onBeforeAutoRetry.apply(this,arguments),this._showCancelLink(e),this._options.retry.showAutoRetryNote&&(t=this._autoRetries[e],n=this._options.retry.maxAutoAttempts,i=this._options.retry.autoRetryNote.replace(/\{retryNum\}/g,t),i=i.replace(/\{maxAuto\}/g,n),this._templating.setStatusText(e,i),qq(this._templating.getFileContainer(e)).addClass(this._classes.retrying))},_onBeforeManualRetry:function(e){return this._parent.prototype._onBeforeManualRetry.apply(this,arguments)?(this._templating.resetProgress(e),qq(this._templating.getFileContainer(e)).removeClass(this._classes.fail),this._templating.setStatusText(e),this._templating.showSpinner(e),this._showCancelLink(e),!0):(qq(this._templating.getFileContainer(e)).addClass(this._classes.retryable),this._templating.showRetry(e),!1)},_onSubmitDelete:function(e){var t=qq.bind(this._onSubmitDeleteSuccess,this);this._parent.prototype._onSubmitDelete.call(this,e,t)},_onSubmitDeleteSuccess:function(e,t,n){this._options.deleteFile.forceConfirm?this._showDeleteConfirm.apply(this,arguments):this._sendDeleteRequest.apply(this,arguments)},_onDeleteComplete:function(e,t,n){this._parent.prototype._onDeleteComplete.apply(this,arguments),this._templating.hideSpinner(e),n?(this._templating.setStatusText(e,this._options.deleteFile.deletingFailedText),this._templating.showDeleteButton(e)):this._removeFileItem(e)},_sendDeleteRequest:function(e,t,n){this._templating.hideDeleteButton(e),this._templating.showSpinner(e),this._templating.setStatusText(e,this._options.deleteFile.deletingStatusText),this._deleteHandler.sendDelete.apply(this,arguments)},_showDeleteConfirm:function(e,t,n){var i,o=this.getName(e),r=this._options.deleteFile.confirmMessage.replace(/\{filename\}/g,o),a=(this.getUuid(e),arguments),s=this;i=this._options.showConfirm(r),qq.isGenericPromise(i)?i.then(function(){s._sendDeleteRequest.apply(s,a)}):i!==!1&&s._sendDeleteRequest.apply(s,a)},_addToList:function(e,t,n){var i,o,r=0,a=this._handler.isProxied(e)&&this._options.scaling.hideScaled;this._options.display.prependFiles&&(this._totalFilesInBatch>1&&this._filesInBatchAddedToUi>0&&(r=this._filesInBatchAddedToUi-1),i={index:r}),n||(this._options.disableCancelForFormUploads&&!qq.supportedFeatures.ajaxUploading&&this._templating.disableCancel(),this._options.multiple||(o=this.getUploads({id:e}),this._handledProxyGroup=this._handledProxyGroup||o.proxyGroupId,o.proxyGroupId===this._handledProxyGroup&&o.proxyGroupId||(this._handler.cancelAll(),this._clearList(),this._handledProxyGroup=null))),n?(this._templating.addFileToCache(e,this._options.formatFileName(t),i,a),this._templating.updateThumbnail(e,this._thumbnailUrls[e],!0,this._options.thumbnails.customResizer)):(this._templating.addFile(e,this._options.formatFileName(t),i,a),this._templating.generatePreview(e,this.getFile(e),this._options.thumbnails.customResizer)),this._filesInBatchAddedToUi+=1,(n||this._options.display.fileSizeOnSubmit&&qq.supportedFeatures.ajaxUploading)&&this._displayFileSize(e)},_clearList:function(){this._templating.clearFiles(),this.clearStoredFiles()},_displayFileSize:function(e,t,n){var i=this.getSize(e),o=this._formatSize(i);i>=0&&(void 0!==t&&void 0!==n&&(o=this._formatProgress(t,n)),this._templating.updateSize(e,o))},_formatProgress:function(e,t){function n(e,t){i=i.replace(e,t)}var i=this._options.text.formatProgress;return n("{percent}",Math.round(e/t*100)),n("{total_size}",this._formatSize(t)),i},_controlFailureTextDisplay:function(e,t){var n,i,o;n=this._options.failedUploadTextDisplay.mode,i=this._options.failedUploadTextDisplay.responseProperty,"custom"===n?(o=t[i],o||(o=this._options.text.failUpload),this._templating.setStatusText(e,o),this._options.failedUploadTextDisplay.enableTooltip&&this._showTooltip(e,o)):"default"===n?this._templating.setStatusText(e,this._options.text.failUpload):"none"!==n&&this.log("failedUploadTextDisplay.mode value of '"+n+"' is not valid","warn")},_showTooltip:function(e,t){this._templating.getFileContainer(e).title=t},_showCancelLink:function(e){this._options.disableCancelForFormUploads&&!qq.supportedFeatures.ajaxUploading||this._templating.showCancel(e)},_itemError:function(e,t,n){var i=this._parent.prototype._itemError.apply(this,arguments);this._options.showMessage(i)},_batchError:function(e){this._parent.prototype._batchError.apply(this,arguments),this._options.showMessage(e)},_setupPastePrompt:function(){var e=this;this._options.callbacks.onPasteReceived=function(){var t=e._options.paste.namePromptMessage,n=e._options.paste.defaultName;return e._options.showPrompt(t,n)}},_fileOrBlobRejected:function(e,t){this._totalFilesInBatch-=1,this._parent.prototype._fileOrBlobRejected.apply(this,arguments)},_prepareItemsForUpload:function(e,t,n){
+this._totalFilesInBatch=e.length,this._filesInBatchAddedToUi=0,this._parent.prototype._prepareItemsForUpload.apply(this,arguments)},_maybeUpdateThumbnail:function(e){var t=this._thumbnailUrls[e];this.getUploads({id:e}).status===qq.status.DELETED||!t&&!this._options.thumbnails.placeholders.waitUntilResponse&&qq.supportedFeatures.imagePreviews||this._templating.updateThumbnail(e,t,this._options.thumbnails.customResizer)},_addCannedFile:function(e){var t=this._parent.prototype._addCannedFile.apply(this,arguments);return this._addToList(t,this.getName(t),!0),this._templating.hideSpinner(t),this._templating.hideCancel(t),this._markFileAsSuccessful(t),t},_setSize:function(e,t){this._parent.prototype._setSize.apply(this,arguments),this._templating.updateSize(e,this._formatSize(t))},_sessionRequestComplete:function(){this._templating.addCacheToDom(),this._parent.prototype._sessionRequestComplete.apply(this,arguments)}}}(),qq.FineUploader=function(e,t){"use strict";var n=this;this._parent=t?qq[t].FineUploaderBasic:qq.FineUploaderBasic,this._parent.apply(this,arguments),qq.extend(this._options,{element:null,button:null,listElement:null,dragAndDrop:{extraDropzones:[],reportDirectoryPaths:!1},text:{formatProgress:"{percent}% of {total_size}",failUpload:"Upload failed",waitingForResponse:"Processing...",paused:"Paused"},template:"qq-template",classes:{retrying:"qq-upload-retrying",retryable:"qq-upload-retryable",success:"qq-upload-success",fail:"qq-upload-fail",editable:"qq-editable",hide:"qq-hide",dropActive:"qq-upload-drop-area-active"},failedUploadTextDisplay:{mode:"default",responseProperty:"error",enableTooltip:!0},messages:{tooManyFilesError:"You may only drop one file",unsupportedBrowser:"Unrecoverable error - this browser does not permit file uploading of any kind."},retry:{showAutoRetryNote:!0,autoRetryNote:"Retrying {retryNum}/{maxAuto}..."},deleteFile:{forceConfirm:!1,confirmMessage:"Are you sure you want to delete {filename}?",deletingStatusText:"Deleting...",deletingFailedText:"Delete failed"},display:{fileSizeOnSubmit:!1,prependFiles:!1},paste:{promptForName:!1,namePromptMessage:"Please name this image"},thumbnails:{customResizer:null,maxCount:0,placeholders:{waitUntilResponse:!1,notAvailablePath:null,waitingPath:null},timeBetweenThumbs:750},scaling:{hideScaled:!1},showMessage:function(e){if(n._templating.hasDialog("alert"))return n._templating.showDialog("alert",e);setTimeout(function(){window.alert(e)},0)},showConfirm:function(e){return n._templating.hasDialog("confirm")?n._templating.showDialog("confirm",e):window.confirm(e)},showPrompt:function(e,t){return n._templating.hasDialog("prompt")?n._templating.showDialog("prompt",e,t):window.prompt(e,t)}},!0),qq.extend(this._options,e,!0),this._templating=new qq.Templating({log:qq.bind(this.log,this),templateIdOrEl:this._options.template,containerEl:this._options.element,fileContainerEl:this._options.listElement,button:this._options.button,imageGenerator:this._imageGenerator,classes:{hide:this._options.classes.hide,editable:this._options.classes.editable},limits:{maxThumbs:this._options.thumbnails.maxCount,timeBetweenThumbs:this._options.thumbnails.timeBetweenThumbs},placeholders:{waitUntilUpdate:this._options.thumbnails.placeholders.waitUntilResponse,thumbnailNotAvailable:this._options.thumbnails.placeholders.notAvailablePath,waitingForThumbnail:this._options.thumbnails.placeholders.waitingPath},text:this._options.text}),this._options.workarounds.ios8SafariUploads&&qq.ios800()&&qq.iosSafari()?this._templating.renderFailure(this._options.messages.unsupportedBrowserIos8Safari):!qq.supportedFeatures.uploading||this._options.cors.expected&&!qq.supportedFeatures.uploadCors?this._templating.renderFailure(this._options.messages.unsupportedBrowser):(this._wrapCallbacks(),this._templating.render(),this._classes=this._options.classes,!this._options.button&&this._templating.getButton()&&(this._defaultButtonId=this._createUploadButton({element:this._templating.getButton(),title:this._options.text.fileInputTitle}).getButtonId()),this._setupClickAndEditEventHandlers(),qq.DragAndDrop&&qq.supportedFeatures.fileDrop&&(this._dnd=this._setupDragAndDrop()),this._options.paste.targetElement&&this._options.paste.promptForName&&(qq.PasteSupport?this._setupPastePrompt():this.log("Paste support module not found.","error")),this._totalFilesInBatch=0,this._filesInBatchAddedToUi=0)},qq.extend(qq.FineUploader.prototype,qq.basePublicApi),qq.extend(qq.FineUploader.prototype,qq.basePrivateApi),qq.extend(qq.FineUploader.prototype,qq.uiPublicApi),qq.extend(qq.FineUploader.prototype,qq.uiPrivateApi),qq.Templating=function(e){"use strict";var t,n,i,o,r,a,s,u,l={content:document.createDocumentFragment(),map:{}},c=!1,d=0,p=!1,h=[],f=-1,q={log:null,limits:{maxThumbs:0,timeBetweenThumbs:750},templateIdOrEl:"qq-template",containerEl:null,fileContainerEl:null,button:null,imageGenerator:null,classes:{hide:"qq-hide",editable:"qq-editable"},placeholders:{waitUntilUpdate:!1,thumbnailNotAvailable:null,waitingForThumbnail:null},text:{paused:"Paused"}},m={button:"qq-upload-button-selector",alertDialog:"qq-alert-dialog-selector",dialogCancelButton:"qq-cancel-button-selector",confirmDialog:"qq-confirm-dialog-selector",dialogMessage:"qq-dialog-message-selector",dialogOkButton:"qq-ok-button-selector",promptDialog:"qq-prompt-dialog-selector",uploader:"qq-uploader-selector",drop:"qq-upload-drop-area-selector",list:"qq-upload-list-selector",progressBarContainer:"qq-progress-bar-container-selector",progressBar:"qq-progress-bar-selector",totalProgressBarContainer:"qq-total-progress-bar-container-selector",totalProgressBar:"qq-total-progress-bar-selector",file:"qq-upload-file-selector",spinner:"qq-upload-spinner-selector",size:"qq-upload-size-selector",cancel:"qq-upload-cancel-selector",pause:"qq-upload-pause-selector",continueButton:"qq-upload-continue-selector",deleteButton:"qq-upload-delete-selector",retry:"qq-upload-retry-selector",statusText:"qq-upload-status-text-selector",editFilenameInput:"qq-edit-filename-selector",editNameIcon:"qq-edit-filename-icon-selector",dropText:"qq-upload-drop-area-text-selector",dropProcessing:"qq-drop-processing-selector",dropProcessingSpinner:"qq-drop-processing-spinner-selector",thumbnail:"qq-thumbnail-selector"},g={},_=new qq.Promise,v=new qq.Promise,b=function(){var e=q.placeholders.thumbnailNotAvailable,n=q.placeholders.waitingForThumbnail,i={maxSize:f,scale:u};s&&(e?q.imageGenerator.generate(e,new Image,i).then(function(e){_.success(e)},function(){_.failure(),t("Problem loading 'not available' placeholder image at "+e,"error")}):_.failure(),n?q.imageGenerator.generate(n,new Image,i).then(function(e){v.success(e)},function(){v.failure(),t("Problem loading 'waiting for thumbnail' placeholder image at "+n,"error")}):v.failure())},y=function(e){var t=new qq.Promise;return v.then(function(n){z(n,e),e.src?t.success():(e.src=n.src,e.onload=function(){e.onload=null,W(e),t.success()})},function(){L(e),t.success()}),t},S=function(e,n,i){var o=O(e);return t("Generating new thumbnail for "+e),n.qqThumbnailId=e,q.imageGenerator.generate(n,o,i).then(function(){d++,W(o),g[e].success()},function(){g[e].failure(),q.placeholders.waitUntilUpdate||H(e,o)})},w=function(){if(h.length){p=!0;var e=h.shift();e.update?V(e):G(e)}else p=!1},F=function(e){return N(P(e),m.cancel)},x=function(e){return N(P(e),m.continueButton)},C=function(e){return N(r,m[e+"Dialog"])},I=function(e){return N(P(e),m.deleteButton)},E=function(){return N(r,m.dropProcessing)},D=function(e){return N(P(e),m.editNameIcon)},P=function(e){return l.map[e]||qq(a).getFirstByClass("qq-file-id-"+e)},U=function(e){return N(P(e),m.file)},T=function(e){return N(P(e),m.pause)},R=function(e){return null==e?N(r,m.totalProgressBarContainer)||N(r,m.totalProgressBar):N(P(e),m.progressBarContainer)||N(P(e),m.progressBar)},k=function(e){return N(P(e),m.retry)},A=function(e){return N(P(e),m.size)},B=function(e){return N(P(e),m.spinner)},N=function(e,t){return e&&qq(e).getFirstByClass(t)},O=function(e){return s&&N(P(e),m.thumbnail)},L=function(e){e&&qq(e).addClass(q.classes.hide)},z=function(e,t){var n=e.style.maxWidth,i=e.style.maxHeight;i&&n&&!t.style.maxWidth&&!t.style.maxHeight&&qq(t).css({maxWidth:n,maxHeight:i})},H=function(e,t){var n=g[e]||(new qq.Promise).failure(),i=new qq.Promise;return _.then(function(e){n.then(function(){i.success()},function(){z(e,t),t.onload=function(){t.onload=null,i.success()},t.src=e.src,W(t)})}),i},j=function(){var e,o,r,a,l,c,d,p,h,g,_;if(t("Parsing template"),null==q.templateIdOrEl)throw new Error("You MUST specify either a template element or ID!");if(qq.isString(q.templateIdOrEl)){if(e=document.getElementById(q.templateIdOrEl),null===e)throw new Error(qq.format("Cannot find template script at ID '{}'!",q.templateIdOrEl));o=e.innerHTML}else{if(void 0===q.templateIdOrEl.innerHTML)throw new Error("You have specified an invalid value for the template option! It must be an ID or an Element.");o=q.templateIdOrEl.innerHTML}if(o=qq.trimStr(o),a=document.createElement("div"),a.appendChild(qq.toElement(o)),_=qq(a).getFirstByClass(m.uploader),q.button&&(c=qq(a).getFirstByClass(m.button),c&&qq(c).remove()),qq.DragAndDrop&&qq.supportedFeatures.fileDrop||(h=qq(a).getFirstByClass(m.dropProcessing),h&&qq(h).remove()),d=qq(a).getFirstByClass(m.drop),d&&!qq.DragAndDrop&&(t("DnD module unavailable.","info"),qq(d).remove()),qq.supportedFeatures.fileDrop?qq(_).hasAttribute("qq-drop-area-text")&&d&&(g=qq(d).getFirstByClass(m.dropText),g&&qq(g).remove()):(_.removeAttribute("qq-drop-area-text"),d&&qq(d).hasAttribute("qq-hide-dropzone")&&qq(d).css({display:"none"})),p=qq(a).getFirstByClass(m.thumbnail),s?p&&(f=parseInt(p.getAttribute("qq-max-size")),f=f>0?f:null,u=qq(p).hasAttribute("qq-server-scale")):p&&qq(p).remove(),s=s&&p,n=qq(a).getByClass(m.editFilenameInput).length>0,i=qq(a).getByClass(m.retry).length>0,r=qq(a).getFirstByClass(m.list),null==r)throw new Error("Could not find the file list container in the template!");return l=r.children[0].cloneNode(!0),r.innerHTML="",a.getElementsByTagName("DIALOG").length&&document.createElement("dialog"),t("Template parsing complete"),{template:a,fileTemplate:l}},M=function(e,t,n){var i=n,o=i.firstChild;t>0&&(o=qq(i).children()[t].nextSibling),i.insertBefore(e,o)},G=function(e){var t=e.id,n=e.optFileOrBlob,i=n&&n.qqThumbnailId,o=O(t),r={customResizeFunction:e.customResizeFunction,maxSize:f,orient:!0,scale:!0};qq.supportedFeatures.imagePreviews?o?q.limits.maxThumbs&&q.limits.maxThumbs<=d?(H(t,o),w()):y(o).done(function(){g[t]=new qq.Promise,g[t].done(function(){setTimeout(w,q.limits.timeBetweenThumbs)}),null!=i?Q(t,i):S(t,n,r)}):w():o&&(y(o),w())},V=function(e){var t=e.id,n=e.thumbnailUrl,i=e.showWaitingImg,o=O(t),r={customResizeFunction:e.customResizeFunction,scale:u,maxSize:f};if(o)if(n){if(!(q.limits.maxThumbs&&q.limits.maxThumbs<=d))return i&&y(o),q.imageGenerator.generate(n,o,r).then(function(){W(o),d++,setTimeout(w,q.limits.timeBetweenThumbs)},function(){H(t,o),setTimeout(w,q.limits.timeBetweenThumbs)});H(t,o),w()}else H(t,o),w()},X=function(e,t){var n=R(e),i=null==e?m.totalProgressBar:m.progressBar;n&&!qq(n).hasClass(i)&&(n=qq(n).getFirstByClass(i)),n&&(qq(n).css({width:t+"%"}),n.setAttribute("aria-valuenow",t))},W=function(e){e&&qq(e).removeClass(q.classes.hide)},Q=function(e,n){var i=O(e),o=O(n);t(qq.format("ID {} is the same file as ID {}. Will use generated thumbnail from ID {} instead.",e,n,n)),g[n].then(function(){d++,g[e].success(),t(qq.format("Now using previously generated thumbnail created for ID {} on ID {}.",n,e)),i.src=o.src,W(i)},function(){g[e].failure(),q.placeholders.waitUntilUpdate||H(e,i)})};qq.extend(q,e),t=q.log,qq.supportedFeatures.imagePreviews||(q.limits.timeBetweenThumbs=0,q.limits.maxThumbs=0),r=q.containerEl,s=void 0!==q.imageGenerator,o=j(),b(),qq.extend(this,{render:function(){t("Rendering template in DOM."),d=0,r.appendChild(o.template.cloneNode(!0)),L(E()),this.hideTotalProgress(),a=q.fileContainerEl||N(r,m.list),t("Template rendering complete")},renderFailure:function(e){var t=qq.toElement(e);r.innerHTML="",r.appendChild(t)},reset:function(){r.innerHTML="",this.render()},clearFiles:function(){a.innerHTML=""},disableCancel:function(){c=!0},addFile:function(e,t,n,i,s){var u,d=o.fileTemplate.cloneNode(!0),p=N(d,m.file),h=N(r,m.uploader),f=s?l.content:a;s&&(l.map[e]=d),qq(d).addClass("qq-file-id-"+e),h.removeAttribute("qq-drop-area-text"),p&&(qq(p).setText(t),p.setAttribute("title",t)),d.setAttribute("qq-file-id",e),n?M(d,n.index,f):f.appendChild(d),i?(d.style.display="none",qq(d).addClass("qq-hidden-forever")):(L(R(e)),L(A(e)),L(I(e)),L(k(e)),L(T(e)),L(x(e)),c&&this.hideCancel(e),u=O(e),u&&!u.src&&v.then(function(e){u.src=e.src,e.style.maxHeight&&e.style.maxWidth&&qq(u).css({maxHeight:e.style.maxHeight,maxWidth:e.style.maxWidth}),W(u)}))},addFileToCache:function(e,t,n,i){this.addFile(e,t,n,i,!0)},addCacheToDom:function(){a.appendChild(l.content),l.content=document.createDocumentFragment(),l.map={}},removeFile:function(e){qq(P(e)).remove()},getFileId:function(e){var t=e;if(t){for(;null==t.getAttribute("qq-file-id");)t=t.parentNode;return parseInt(t.getAttribute("qq-file-id"))}},getFileList:function(){return a},markFilenameEditable:function(e){var t=U(e);t&&qq(t).addClass(q.classes.editable)},updateFilename:function(e,t){var n=U(e);n&&(qq(n).setText(t),n.setAttribute("title",t))},hideFilename:function(e){L(U(e))},showFilename:function(e){W(U(e))},isFileName:function(e){return qq(e).hasClass(m.file)},getButton:function(){return q.button||N(r,m.button)},hideDropProcessing:function(){L(E())},showDropProcessing:function(){W(E())},getDropZone:function(){return N(r,m.drop)},isEditFilenamePossible:function(){return n},hideRetry:function(e){L(k(e))},isRetryPossible:function(){return i},showRetry:function(e){W(k(e))},getFileContainer:function(e){return P(e)},showEditIcon:function(e){var t=D(e);t&&qq(t).addClass(q.classes.editable)},isHiddenForever:function(e){return qq(P(e)).hasClass("qq-hidden-forever")},hideEditIcon:function(e){var t=D(e);t&&qq(t).removeClass(q.classes.editable)},isEditIcon:function(e){return qq(e).hasClass(m.editNameIcon,!0)},getEditInput:function(e){return N(P(e),m.editFilenameInput)},isEditInput:function(e){return qq(e).hasClass(m.editFilenameInput,!0)},updateProgress:function(e,t,n){var i,o=R(e);o&&n>0&&(i=Math.round(t/n*100),100===i?L(o):W(o),X(e,i))},updateTotalProgress:function(e,t){this.updateProgress(null,e,t)},hideProgress:function(e){var t=R(e);t&&L(t)},hideTotalProgress:function(){this.hideProgress()},resetProgress:function(e){X(e,0),this.hideTotalProgress(e)},resetTotalProgress:function(){this.resetProgress()},showCancel:function(e){if(!c){var t=F(e);t&&qq(t).removeClass(q.classes.hide)}},hideCancel:function(e){L(F(e))},isCancel:function(e){return qq(e).hasClass(m.cancel,!0)},allowPause:function(e){W(T(e)),L(x(e))},uploadPaused:function(e){this.setStatusText(e,q.text.paused),this.allowContinueButton(e),L(B(e))},hidePause:function(e){L(T(e))},isPause:function(e){return qq(e).hasClass(m.pause,!0)},isContinueButton:function(e){return qq(e).hasClass(m.continueButton,!0)},allowContinueButton:function(e){W(x(e)),L(T(e))},uploadContinued:function(e){this.setStatusText(e,""),this.allowPause(e),W(B(e))},showDeleteButton:function(e){W(I(e))},hideDeleteButton:function(e){L(I(e))},isDeleteButton:function(e){return qq(e).hasClass(m.deleteButton,!0)},isRetry:function(e){return qq(e).hasClass(m.retry,!0)},updateSize:function(e,t){var n=A(e);n&&(W(n),qq(n).setText(t))},setStatusText:function(e,t){var n=N(P(e),m.statusText);n&&(null==t?qq(n).clearText():qq(n).setText(t))},hideSpinner:function(e){qq(P(e)).removeClass("qq-in-progress"),L(B(e))},showSpinner:function(e){qq(P(e)).addClass("qq-in-progress"),W(B(e))},generatePreview:function(e,t,n){this.isHiddenForever(e)||(h.push({id:e,customResizeFunction:n,optFileOrBlob:t}),!p&&w())},updateThumbnail:function(e,t,n,i){this.isHiddenForever(e)||(h.push({customResizeFunction:i,update:!0,id:e,thumbnailUrl:t,showWaitingImg:n}),!p&&w())},hasDialog:function(e){return qq.supportedFeatures.dialogElement&&!!C(e)},showDialog:function(e,t,n){var i=C(e),o=N(i,m.dialogMessage),r=i.getElementsByTagName("INPUT")[0],a=N(i,m.dialogCancelButton),s=N(i,m.dialogOkButton),u=new qq.Promise,l=function(){a.removeEventListener("click",c),s&&s.removeEventListener("click",d),u.failure()},c=function(){a.removeEventListener("click",c),i.close()},d=function(){i.removeEventListener("close",l),s.removeEventListener("click",d),i.close(),u.success(r&&r.value)};return i.addEventListener("close",l),a.addEventListener("click",c),s&&s.addEventListener("click",d),r&&(r.value=n),o.textContent=t,i.showModal(),u}})},qq.UiEventHandler=function(e,t){"use strict";function n(e){i.attach(e,o.eventType,function(e){e=e||window.event;var t=e.target||e.srcElement;o.onHandled(t,e)})}var i=new qq.DisposeSupport,o={eventType:"click",attachTo:null,onHandled:function(e,t){}};qq.extend(this,{addHandler:function(e){n(e)},dispose:function(){i.dispose()}}),qq.extend(t,{getFileIdFromItem:function(e){return e.qqFileId},getDisposeSupport:function(){return i}}),qq.extend(o,e),o.attachTo&&n(o.attachTo)},qq.FileButtonsClickHandler=function(e){"use strict";function t(e,t){qq.each(o,function(n,o){var r,a=n.charAt(0).toUpperCase()+n.slice(1);if(i.templating["is"+a](e))return r=i.templating.getFileId(e),qq.preventDefault(t),i.log(qq.format("Detected valid file button click event on file '{}', ID: {}.",i.onGetName(r),r)),o(r),!1})}var n={},i={templating:null,log:function(e,t){},onDeleteFile:function(e){},onCancel:function(e){},onRetry:function(e){},onPause:function(e){},onContinue:function(e){},onGetName:function(e){}},o={cancel:function(e){i.onCancel(e)},retry:function(e){i.onRetry(e)},deleteButton:function(e){i.onDeleteFile(e)},pause:function(e){i.onPause(e)},continueButton:function(e){i.onContinue(e)}};qq.extend(i,e),i.eventType="click",i.onHandled=t,i.attachTo=i.templating.getFileList(),qq.extend(this,new qq.UiEventHandler(i,n))},qq.FilenameClickHandler=function(e){"use strict";function t(e,t){if(i.templating.isFileName(e)||i.templating.isEditIcon(e)){var o=i.templating.getFileId(e);i.onGetUploadStatus(o)===qq.status.SUBMITTED&&(i.log(qq.format("Detected valid filename click event on file '{}', ID: {}.",i.onGetName(o),o)),qq.preventDefault(t),n.handleFilenameEdit(o,e,!0))}}var n={},i={templating:null,log:function(e,t){},classes:{file:"qq-upload-file",editNameIcon:"qq-edit-filename-icon"},onGetUploadStatus:function(e){},onGetName:function(e){}};qq.extend(i,e),i.eventType="click",i.onHandled=t,qq.extend(this,new qq.FilenameEditHandler(i,n))},qq.FilenameInputFocusInHandler=function(e,t){"use strict";function n(e,n){if(i.templating.isEditInput(e)){var o=i.templating.getFileId(e);i.onGetUploadStatus(o)===qq.status.SUBMITTED&&(i.log(qq.format("Detected valid filename input focus event on file '{}', ID: {}.",i.onGetName(o),o)),t.handleFilenameEdit(o,e))}}var i={templating:null,onGetUploadStatus:function(e){},log:function(e,t){}};t||(t={}),i.eventType="focusin",i.onHandled=n,qq.extend(i,e),qq.extend(this,new qq.FilenameEditHandler(i,t))},qq.FilenameInputFocusHandler=function(e){"use strict";e.eventType="focus",e.attachTo=null,qq.extend(this,new qq.FilenameInputFocusInHandler(e,{}))},qq.FilenameEditHandler=function(e,t){"use strict";function n(e){var t=s.onGetName(e),n=t.lastIndexOf(".");return n>0&&(t=t.substr(0,n)),t}function i(e){var t=s.onGetName(e);return qq.getExtension(t)}function o(e,t){var n,o=e.value;void 0!==o&&qq.trimStr(o).length>0&&(n=i(t),void 0!==n&&(o=o+"."+n),s.onSetName(t,o)),s.onEditingStatusChange(t,!1)}function r(e,n){t.getDisposeSupport().attach(e,"blur",function(){o(e,n)})}function a(e,n){t.getDisposeSupport().attach(e,"keyup",function(t){13===(t.keyCode||t.which)&&o(e,n)})}var s={templating:null,log:function(e,t){},onGetUploadStatus:function(e){},onGetName:function(e){},onSetName:function(e,t){},onEditingStatusChange:function(e,t){}};qq.extend(s,e),s.attachTo=s.templating.getFileList(),qq.extend(this,new qq.UiEventHandler(s,t)),qq.extend(t,{handleFilenameEdit:function(e,t,i){var o=s.templating.getEditInput(e);s.onEditingStatusChange(e,!0),o.value=n(e),i&&o.focus(),r(o,e),a(o,e)}})}}(window);
//# sourceMappingURL=jquery.fine-uploader.min.js.map
\ No newline at end of file
diff --git a/styles/bootstrap/fine-uploader/jquery.fine-uploader.min.js.map b/styles/bootstrap/fine-uploader/jquery.fine-uploader.min.js.map
index 06720b606..77ae5ad30 100644
--- a/styles/bootstrap/fine-uploader/jquery.fine-uploader.min.js.map
+++ b/styles/bootstrap/fine-uploader/jquery.fine-uploader.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["?","../client/js/jquery-plugin.js","../client/js/jquery-dnd.js","../client/js/util.js","../client/js/export.js","../client/js/error/error.js","../client/js/version.js","../client/js/features.js","../client/js/promise.js","../client/js/blob-proxy.js","../client/js/button.js","../client/js/upload-data.js","../client/js/uploader.basic.api.js","../client/js/uploader.basic.js","../client/js/ajax.requester.js","../client/js/upload-handler/upload.handler.js","../client/js/upload-handler/upload.handler.controller.js","../client/js/window.receive.message.js","../client/js/upload-handler/form.upload.handler.js","../client/js/upload-handler/xhr.upload.handler.js","../client/js/deletefile.ajax.requester.js","../client/js/image-support/megapix-image.js","../client/js/image-support/image.js","../client/js/image-support/exif.js","../client/js/identify.js","../client/js/image-support/validation.image.js","../client/js/session.js","../client/js/session.ajax.requester.js","../client/js/image-support/scaler.js","../client/js/third-party/ExifRestorer.js","../client/js/total-progress.js","../client/js/paste.js","../client/js/form-support.js","../client/js/traditional/traditional.form.upload.handler.js","../client/js/traditional/traditional.xhr.upload.handler.js","../client/js/traditional/all-chunks-done.ajax.requester.js","../client/js/dnd.js","../client/js/uploader.api.js","../client/js/uploader.js","../client/js/templating.js","../client/js/ui.handler.events.js","../client/js/ui.handler.click.filebuttons.js","../client/js/ui.handler.click.filename.js","../client/js/ui.handler.focusin.filenameinput.js","../client/js/ui.handler.focus.filenameinput.js","../client/js/ui.handler.edit.filename.js"],"names":["global","$","init","options","xformedOpts","transformVariables","newUploaderInstance","getNewUploaderInstance","uploader","addCallbacks","$el","params","uploaderType","pluginOption","namespace","charAt","toUpperCase","slice","toLowerCase","qq","FineUploader","dataStore","key","val","data","undefined","instanceToStore","option","optionVal","transformedOpts","callbacks","each","_options","prop","nonJqueryCallback","name","callbackEventTarget","exec","substring","nonJqueryCallbackRetVal","jqueryEventCallbackRetVal","originalArgs","Array","prototype","call","arguments","transformedArgs","idx","arg","push","maybeWrapInJquery","apply","this","triggerHandler","error","log","message","source","dest","xformed","arrayVals","element","inArray","pluginOptions","isPlainObject","isArray","arrayVal","arrayObjDest","merge","isValidCommand","command","type","match","delegateCommand","retVal","xformedArgs","origArgs","transformedVal","nodeType","cloneNode","fn","fineUploader","optionsOrCommand","self","selfArgs","retVals","index","el","length","jQuery","dropZoneElements","dnd","DragAndDrop","rootDataKey","func","$callbackEl","args","jqueryHandlerResult","fineUploaderDnd","hide","style","display","attach","addEventListener","attachEvent","detach","removeEventListener","detachEvent","contains","descendant","compareDocumentPosition","insertBefore","elementB","parentNode","remove","removeChild","css","styles","Error","opacity","filter","Math","round","extend","hasClass","considerParent","re","RegExp","test","className","addClass","removeClass","replace","getByClass","first","candidates","result","querySelector","querySelectorAll","getElementsByTagName","getFirstByClass","children","child","firstChild","nextSibling","setText","text","innerText","textContent","clearText","hasAttribute","attrName","attrVal","getAttribute","canvasToBlob","canvas","mime","quality","dataUriToBlob","toDataURL","dataUri","arrayBuffer","byteString","intArray","mimeString","createBlob","BlobBuilder","window","WebKitBlobBuilder","MozBlobBuilder","MSBlobBuilder","blobBuilder","append","getBlob","Blob","split","indexOf","atob","decodeURI","ArrayBuffer","Uint8Array","character","charCodeAt","level","console","isObject","variable","Object","toString","isFunction","value","buffer","constructor","isItemList","maybeItemList","isNodeList","maybeNodeList","item","namedItem","isString","maybeString","trimStr","string","String","trim","format","str","newStr","nextIdxToReplace","strBefore","strAfter","isFile","maybeFile","File","isFileList","maybeFileList","FileList","isFileOrInput","maybeFileOrInput","isInput","maybeInput","notFile","evaluateType","normalizedType","HTMLInputElement","tagName","isBlob","maybeBlob","isXhrUploadSupported","input","document","createElement","multiple","FormData","createXhrInstance","upload","XMLHttpRequest","ActiveXObject","isFolderDropSupported","dataTransfer","items","webkitGetAsEntry","isFileChunkingSupported","androidStock","webkitSlice","mozSlice","sliceBlob","fileOrBlob","start","end","slicer","arrayBufferToHex","bytesAsHex","bytes","byt","byteAsHexStr","readBlobToHex","blob","startOffset","initialBlob","fileReader","FileReader","promise","Promise","onload","success","onerror","failure","readAsArrayBuffer","second","extendNested","override","target","sourceFn","super_","srcPropName","srcPropVal","arr","elt","from","len","hasOwnProperty","getUniqueId","c","r","random","v","ie","navigator","userAgent","ie7","ie8","ie10","ie11","edge","safari","vendor","chrome","opera","firefox","windows","platform","android","ios6","ios","ios7","ios8","ios800","iosChrome","iosSafari","iosSafariWebView","preventDefault","e","returnValue","toElement","div","html","innerHTML","iterableItem","callback","keyOrIndex","Storage","getItem","bind","oldFunc","context","newArgs","concat","obj2url","obj","temp","prefixDone","uristrings","prefix","add","nextObj","i","nextTemp","encodeURIComponent","join","obj2FormData","formData","arrayKeyName","obj2Inputs","form","setAttribute","appendChild","parseJson","json","JSON","parse","eval","getExtension","filename","extIdx","lastIndexOf","substr","getFilename","blobOrFileInput","fileName","DisposeSupport","disposers","dispose","disposer","shift","addDisposer","disposeFunction","define","amd","module","exports","version","supportedFeatures","testSupportsFileInputElement","tempInput","supported","disabled","ex","isChrome21OrHigher","isChrome14OrHigher","isCrossOriginXhrSupported","xhr","withCredentials","isXdrSupported","XDomainRequest","isCrossOriginAjaxSupported","isFolderSelectionSupported","webkitdirectory","isLocalStorageSupported","localStorage","setItem","isDragAndDropSupported","span","supportsUploading","supportsUploadingBlobs","supportsFileDrop","supportsAjaxFileUploading","supportsFolderDrop","supportsChunking","supportsResume","supportsUploadViaPaste","supportsUploadCors","supportsDeleteFileXdr","supportsDeleteFileCorsXhr","supportsDeleteFileCors","supportsFolderSelection","supportsImagePreviews","supportsUploadProgress","postMessage","ajaxUploading","blobUploading","canDetermineSize","chunking","deleteFileCors","deleteFileCorsXdr","deleteFileCorsXhr","dialogElement","HTMLDialogElement","fileDrop","folderDrop","folderSelection","imagePreviews","imageValidation","itemSizeValidation","pause","progressBar","resume","scaling","tiffPreviews","unlimitedScaledImageSize","uploading","uploadCors","uploadCustomHeaders","uploadNonMultipart","uploadViaPaste","isGenericPromise","maybePromise","then","successArgs","failureArgs","successCallbacks","failureCallbacks","doneCallbacks","state","onSuccess","onFailure","done","BlobProxy","referenceBlob","onCreate","create","UploadButton","o","createInput","BUTTON_ID_ATTR_NAME","buttonId","title","setMultiple","folders","acceptFiles","position","right","top","fontFamily","fontSize","margin","padding","cursor","height","disposeSupport","onChange","hoverClass","focusClass","ios8BrowserCrashWorkaround","overflow","direction","getInput","getButtonId","isMultiple","optInput","removeAttribute","setAcceptFiles","reset","UploadData","uploaderProxy","getDataByIds","idOrIds","entries","id","getDataByUuids","uuids","uuid","byUuid","getDataByStatus","status","statusResults","statuses","statusEnum","statusResultIndexes","byStatus","dataIndex","byProxyGroupId","byBatchId","addFile","spec","SUBMITTING","originalName","size","batchId","proxyGroupId","onStatusChange","retrieve","optionalFilter","setStatus","newStatus","oldStatus","byStatusOldStatusIndex","splice","uuidChanged","newUuid","oldUuid","updateName","newName","updateSize","newSize","setParentId","targetId","parentId","getIdsInProxyGroup","getIdsInBatch","SUBMITTED","REJECTED","QUEUED","CANCELED","PAUSED","UPLOADING","UPLOAD_RETRYING","UPLOAD_SUCCESSFUL","UPLOAD_FAILED","DELETE_FAILED","DELETING","DELETED","basePublicApi","addBlobs","blobDataOrArray","endpoint","addFiles","addInitialFiles","cannedFileList","cannedFile","_addCannedFile","_maybeHandleIos8SafariWorkaround","_storedIds","_currentBatchId","processBlob","_handleNewFile","blobs","defaultName","verifiedFiles","processBlobData","blobData","processCanvas","processCanvasData","canvasData","normalizedQuality","processFileOrInput","fileOrInput","files","file","normalizeData","fileContainer","_prepareItemsForUpload","cancel","_handler","cancelAll","storedIdsCopy","storedFileId","clearStoredFiles","continueUpload","uploadData","_uploadData","enabled","getName","_uploadFile","deleteFile","_onSubmitDelete","doesExist","fileOrBlobId","isValid","drawThumbnail","fileId","imgOrCanvas","maxSize","fromServer","customResizeFunction","fileOrUrl","promiseToReturn","_imageGenerator","_thumbnailUrls","scale","getFile","container","generate","modifiedContainer","reason","getButton","_getButton","_buttonIdsForFileIds","getEndpoint","_endpointStore","get","getInProgress","getParentId","uploadDataEntry","getUploads","getResumableFilesData","getSize","getNetUploads","_netUploaded","getRemainingAllowedItems","allowedItems","_currentItemLimit","_netUploadedOrQueued","getUuid","debug","pauseUpload","_autoRetries","_retryTimeouts","_preventRetries","_buttons","button","_paramsStore","_pasteHandler","session","refreshOnReset","_refreshSessionData","_succeededSinceLastAllComplete","_failedSinceLastAllComplete","_totalProgress","retry","_manualRetry","scaleImage","specs","Scaler","setCustomHeaders","headers","_customHeadersStore","set","setDeleteFileCustomHeaders","_deleteFileCustomHeadersStore","setDeleteFileEndpoint","_deleteFileEndpointStore","setDeleteFileParams","_deleteFileParamsStore","setEndpoint","setForm","elementOrId","_updateFormSupportAndParams","setItemLimit","newItemLimit","setName","setParams","setUuid","uploadStoredFiles","_itemError","_uploadStoredFiles","basePrivateApi","sessionData","deleteFileEndpoint","deleteFileParams","thumbnailUrl","_annotateWithButtonId","associatedInput","qqButtonId","_getButtonId","_batchError","onError","_createDeleteHandler","DeleteFileAjaxRequester","method","maxConnections","uuidParamName","request","uuidName","customHeaders","paramsStore","endpointStore","cors","onDelete","_onDelete","onDeleteComplete","xhrOrXdr","isError","_onDeleteComplete","_createPasteHandler","PasteSupport","targetElement","paste","pasteReceived","_handleCheckedCallback","onPasteReceived","_handlePasteSuccess","identifier","_createStore","initialValue","_readOnlyValues_","store","catchall","perIdReadOnlyValues","readOnlyValues","copy","orig","getReadOnlyValues","includeReadOnlyValues","existing","values","addReadOnly","_createUploadDataTracker","_onUploadStatusChange","_maybeAllComplete","setTimeout","_createUploadButton","allowMultiple","workarounds","iosEmptyVideos","_isAllowedExtension","allowedExtensions","accept","validation","classes","buttonFocus","buttonHover","ios8BrowserCrash","inputName","_onInputChange","fileInputTitle","_disposeSupport","_createUploadHandler","additionalOptions","lastOnProgress","preventRetryParam","preventRetryResponseProperty","onProgress","loaded","total","_onProgress","onComplete","_onComplete","onCancel","cancelFinalizationEffort","_onCancel","onUploadPrep","_onUploadPrep","onUpload","_onUpload","onUploadChunk","chunkData","_onUploadChunk","onUploadChunkSuccess","onResume","onAutoRetry","responseJSON","_onAutoRetry","onUuidChanged","setSize","_setSize","getDataByUuid","isQueued","UploadHandlerController","_fileOrBlobRejected","_formatSize","sizeSymbols","max","toFixed","_generateExtraButtonSpecs","_extraButtonSpecs","extraButtons","extraButtonOptionEntry","extraButtonSpec","_initExtraButton","extraButtonsSpec","_defaultButtonId","buttonOrFileInputOrFile","inputs","fileInput","fileBlobOrInput","_getNotFinished","_getValidationBase","_getValidationDescriptor","fileWrapper","_getValidationDescriptors","fileWrappers","fileDescriptors","_handleCameraAccess","camera","acceptIosCamera","optionRoot","details","callbackRetVal","successParam","newFileWrapperList","actualFile","handler","_customNewFileHandler","_handleNewFileGeneric","addFileToHandler","_trackButton","fileList","extSuppliedName","extension","_initFormSupportAndParams","_formSupport","FormSupport","attachedToForm","getFormInputsAsObject","autoUpload","newAutoUpload","newEndpoint","_isDeletePossible","expected","allowXdr","allowed","valid","allowedExt","extRegex","code","maybeNameOrNames","replacement","extensionsForMessage","placeholderMatch","messages","names","validationBase","allowedExtension","formatFileName","sizeLimit","minSizeLimit","placeholder","_onBeforeManualRetry","notFinished","_onAllComplete","ios8SafariUploads","alert","unsupportedBrowserIos8Safari","_maybeParseAndSendUploadError","response","errorReason","defaultResponseError","_maybeProcessNextItemAfterOnValidateCallback","validItem","stopOnFirstInvalidFile","validationDescriptor","onValidate","_onValidateCallbackSuccess","_onValidateCallbackFailure","successful","failed","onAllComplete","_shouldAutoRetry","retryWaitPeriod","autoAttemptDelay","_onBeforeAutoRetry","itemLimit","onManualRetry","clearTimeout","storedItemIndex","expunge","fileIndex","onIndividualProgress","_onSubmit","_onSubmitCallbackSuccess","_onSubmitted","onSubmitted","_storeForLater","onSuccessCallback","additionalMandatedParams","adjustedOnSuccessCallback","onSubmitDelete","_deleteHandler","sendDelete","_onTotalProgress","onTotalProgress","_onValidateBatchCallbackFailure","_onValidateBatchCallbackSuccess","validationDescriptors","errorMessage","proposedNetFilesUploadedOrQueued","tooManyItemsError","nextIndex","_validateFileOrBlobData","_upload","onValidateBatch","_preventLeaveInProgress","event","onLeave","Session","_session","addFileRecord","refresh","_sessionRequestComplete","onSessionRequestComplete","onNewSize","enableAuto","maxAutoAttempts","formElementOrId","onSubmit","idToUpload","stillSubmitting","validityChecker","allowEmpty","ImageValidation","validate","image","errorCode","_wrapCallbacks","safeCallback","errorMsg","exception","callbackName","callbackFunc","FineUploaderBasic","disableCancelForFormUploads","filenameParam","forceMultipart","paramsInBody","totalFileSizeName","maxHeight","maxWidth","minHeight","minWidth","maybeXhr","maybeXhrOrXdr","attemptNumber","fileOrBlobData","typeError","sizeError","minSizeError","emptyError","noFilesError","maxHeightImageError","maxWidthImageError","minHeightImageError","minWidthImageError","retryFailTooManyItems","concurrent","mandatory","paramNames","partIndex","partByteOffset","chunkSize","totalFileSize","totalParts","partSize","recordsExpireIn","resuming","fileOrBlobName","sendCredentials","interceptSubmit","customResizer","sendOriginal","orient","defaultType","defaultQuality","failureText","includeExif","sizes","ImageGenerator","_scaler","handleNewFile","TotalProgress","entry","AjaxRequester","isSimpleMethod","containsNonSimpleHeaders","containsNonSimple","header","isXdr","getCorsAjaxTransport","ontimeout","onprogress","getXhrOrXdr","suppliedXhr","requestData","dequeue","nextId","queue","sendRequest","xdrError","isResponseSuccessful","getParams","onDemandParams","additionalParams","mandatedParams","optXhr","url","payload","onSend","createUrl","additionalQueryParams","getXdrLoadHandler","getXdrErrorHandler","onreadystatechange","getXhrReadyStateChangeHandler","registerForUploadProgress","open","setHeaders","send","shouldParamsBeInQueryString","contentType","stringify","addToPath","readyState","lengthComputable","onDemandHeaders","additionalHeaders","allHeaders","acceptHeader","setRequestHeader","allowXRequestedWithAndCacheControl","responseCode","successfulResponseCodes","prepareToSend","validMethods","DELETE","PATCH","POST","PUT","GET","initTransport","path","cacheBuster","withPath","appendToPath","withParams","withQueryParams","_additionalQueryParams_","withHeaders","withPayload","thePayload","withCacheBuster","qqtimestamp","Date","getTime","canceled","UploadHandler","proxy","fileState","fileItem","onCancelRetVal","getThirdPartyFileId","_getFileState","_setThirdPartyFileId","thirdPartyFileId","_wasCanceled","preventRetryResponse","controller","chunkingPossible","concurrentChunkingPossible","chunked","chunkIdx","_getChunkData","attemptingResume","chunkProgress","_getChunkDataForCallback","finalize","finalizeChunks","normaizedResponse","normalizeResponse","_maybeDeletePersistedChunkData","cleanup","handleFailure","clearCachedChunk","inProgressIdx","responseToReport","inProgress","remaining","unshift","ignoreFailure","keys","_getXhrs","ckid","ckXhr","abort","_cancelled","moveInProgressToRemaining","connectionManager","free","hasMoreParts","nextPart","nextIdx","_getTotalChunks","reevaluateChunking","sendNext","inProgressChunks","available","uploadChunk","inProgressChunkIdx","_maybePersistChunkedState","clearXhr","_open","_openChunks","_waiting","openChunkEntriesCount","openChunksCount","openChunkIndexes","dontAllowNext","allowNext","waitingIndex","connectionsIndex","getProxyOrBlob","getWaitingOrConnected","waitingOrConnected","chunks","parseInt","isUsingConnection","pop","openChunksEntry","simple","uploadFile","maybeNewUuid","_clearXhrs","getProxy","initHandler","handlerType","traditional","handlerModuleSubtype","_removeExpiredChunkingRecords","isDeferredEligibleForUpload","maybeDefer","generatedBlob","updateBlob","maybeSendDeferredFiles","errorResponse","idsInGroup","uploadedThisId","idInGroup","now","originalResponse","_shouldChunkThisFile","blobToUpload","cancelRetVal","isProxied","isResumable","WindowReceiveMessage","callbackWrapperDetachers","receiveMessage","onMessageCallbackWrapper","stopReceivingMessages","detacher","FormUploadHandler","expungeFile","detachLoadEvents","isCors","postMessageCallbackTimers","corsMessageReceiver","iframe","getElementById","_getIframeName","getFileIdForIframeName","iframeName","initIframeForUpload","body","registerPostMessageCallback","onloadCallbacks","onloadCallback","_parseJsonResponse","_detachLoadEvent","formHandlerInstanceId","_attachLoadEvent","responseDescriptor","contentDocument","_createIframe","_initFormForUpload","targetName","innerHtmlOrMessage","XhrUploadHandler","xhrId","ajaxRequester","_getAjaxRequester","chunkFiles","resumeEnabled","blobOrProxy","_initTempState","_maybePrepareForResume","cachedChunks","tempState","xhrs","ajaxRequesters","responseParser","lastChunkIdx","_getXhr","resumableFilesData","_iterateResumeRecords","notResumable","optInProgress","optRemaining","reverse","paused","totalChunks","parts","newBlob","chunkId","_createXhr","optChunkIdx","_registerXhr","chunkIndex","fileSize","startBytes","endBytes","part","count","startByte","endByte","_getLocalStorageId","formatVersion","_getMimeType","_getPersistableData","ceil","_markNotResumable","localStorageId","removeItem","persistedData","lastUpdated","_registerProgressHandler","progressCalculator","totalSuccessfullyLoadedForFile","loadedForRequest","totalForRequest","estActualChunkLoaded","totalLoadedForFile","chunkLoaded","optAjaxRequester","xhrsId","expirationDays","expirationDate","setDate","getDate","getMandatedParams","_method","requester","detectSubsampling","img","ctx","iw","naturalWidth","ih","naturalHeight","width","getContext","drawImage","getImageData","detectVerticalSquash","alpha","ratio","sy","ey","py","renderImageToDataURL","doSquash","renderImageToCanvas","maybeCalculateDownsampledDimensions","maxPixels","origHeight","origWidth","newHeight","sqrt","newWidth","modifiedDimensions","save","resize","renderImageToCanvasWithCustomResizer","imageHeight","imageWidth","orientation","targetHeight","targetWidth","transformCoordinate","tmpCtx","sx","dx","d","tmpCanvas","vertSquashRatio","dw","dh","dy","clearRect","restore","qqImageRendered","resizeInfo","sourceCanvas","sourceCanvasContext","targetCanvas","translate","rotate","PI","MegaPixImage","srcImage","errorCallback","Image","URL","createObjectURL","webkitURL","src","listeners","imageLoadListeners","render","opt","imgWidth","imgHeight","optionsKey","optionsValue","oldTargetSrc","onrender","isImg","isCanvas","isImgCorsSupported","crossOrigin","isCanvasSupported","determineMimeOfFileName","nameWithPath","pathSegments","isCrossOrigin","targetProtocol","targetHostname","targetPort","targetAnchor","href","protocol","port","hostname","location","registerImgLoadListeners","registerCanvasDrawImageListener","registerThumbnailRenderedListener","registered","draw","drawPreview","Identify","megapixErrorHandler","isPreviewable","dummyExif","exif","Exif","mpImg","Orientation","failureMsg","drawOnCanvasOrImgFromUrl","canvasOrImg","tempImg","tempImgRender","drawOnImgFromUrlWithCssScaling","drawFromUrl","fileBlobOrUrl","_testing","parseLittleEndian","hex","pow","seekToApp1","offset","theOffset","thePromise","segmentLength","getApp1Offset","isLittleEndian","app1Start","getDirEntryCount","littleEndian","getIfd","dirEntries","getDirEntries","ifdHex","getTagValues","TAG_VAL_OFFSET","tagsToFind","TAG_IDS","vals","tagValHex","tagValLength","idHex","tagsToFindIdx","TAG_INFO","274","parser","onParseFailure","app1Offset","dirEntryCount","tagValues","isIdentifiable","magicBytes","questionableBytes","identifiable","magicBytesEntries","magicBytesArrayEntry","previewable","isPreviewableSync","PREVIEWABLE_MIME_TYPES","fileMime","isRecognizedImage","image/jpeg","image/gif","image/png","image/bmp","image/tiff","hasNonZeroLimits","limits","atLeastOne","limit","getWidthHeight","sizeDetermination","getFailingLimit","dimensions","failingLimit","limitName","limitValue","limitMatcher","dimensionPropName","actualValue","validationEffort","isJsonResponseValid","handleFileItems","fileItems","someItemsIgnored","err","refreshEffort","refreshCompleteCallback","requesterOptions","SessionAjaxRequester","queryServer","responseText","includeOriginal","failedToScaleText","_getSortedSizes","getFileRecords","originalFileUuid","originalFileName","originalBlobOrBlobData","records","originalBlob","sizeRecord","outputType","_determineOutputType","requestedType","refType","_getName","_generateScaledImage","failedText","api","scaledIds","originalId","record","blobSize","scaledId","qqparentuuid","qqparentsize","param","scalingEffort","scalingOptions","scaler","referenceType","scaledVersionProperties","startOfExt","versionType","scaledName","scaledExt","nameAppendage","sort","a","b","sourceFile","imageGenerator","scaledImageDataUri","signalSuccess","_insertExifHeader","scaledImageDataUriWithExif","originalImage","reader","insertionEffort","originalImageDataUri","ExifRestorer","readAsDataURL","_dataUriToBlob","_createBlob","KEY_STR","encode64","chr1","chr2","enc1","enc2","enc3","output","chr3","enc4","isNaN","origFileBase64","resizedFileBase64","expectedBase64Header","rawImage","decode64","segments","slice2Segments","exifManipulation","exifArray","getExifArray","newImageArray","insertExif","aBuffer","seg","x","imageData","buf","separatePoint","mae","ato","array","rawImageArray","head","endPoint","base64test","perFileProgress","totalLoaded","totalSize","lastLoadedSent","lastTotalSent","callbackProxy","noRetryableFiles","retryable","none","failedId","updateTotalProgress","onNew","newLoaded","newTotal","oldLoaded","oldTotal","isImage","registerPasteHandler","detachPasteHandler","clipboardData","getAsFile","unregisterPasteHandler","startUpload","determineNewEndpoint","formEl","validateForm","nativeSubmit","checkValidity","maybeUploadOnSubmit","submit","determineFormEl","_form2Obj","notIrrelevantType","irrelevantTypes","radioOrCheckbox","ignoreValue","checked","selectValue","select","selected","elements","getIframeContentJson","doc","innerHtml","contentWindow","nodeValue","createForm","responseFromMessage","multipart","addChunkingSpecificParams","allChunksDoneRequester","AllChunksDoneAjaxRequester","createReadyStateChangedHandler","onUploadOrChunkComplete","getChunksCompleteParams","isErrorUploadResponse","parseResponse","sendChunksCompleteRequest","complete","setParamsAndGetEntityToSend","setUploadHeaders","extraHeaders","toSend","promises","endpointHandler","uploadDroppedFiles","uploadDropZone","filesAsArray","dropLog","dropDisabled","processingDroppedFilesComplete","getElement","traverseFileTree","parseEntryPromise","fullPath","indexOfNameInFullPath","qqPath","droppedFiles","fileError","isDirectory","getFilesInDirectory","entriesLeft","accumEntries","existingPromise","dirReader","createReader","readEntries","newEntries","handleDataTransfer","pendingFolderPromises","handleDataTransferPromise","processingDroppedFiles","allowMultipleItems","dropError","setupDropzone","dropArea","dropZone","UploadDropZone","HIDE_ZONES_EVENT_NAME","onEnter","dropActive","stopPropagation","onLeaveNotDescendants","onDrop","HIDE_BEFORE_ENTER_ATTR","uploadDropZones","isFileDrag","dragEvent","fileDrag","types","leavingDocumentOut","relatedTarget","y","setupDragDrop","dropZones","maybeHideDropZones","HTMLElement","setupExtraDropzone","removeDropzone","dzs","targetEl","errorSpecifics","dragoverShouldBeCanceled","disableDropOutside","dropOutsideDisabled","dropEffect","isValidFileDrag","effectTest","dt","isSafari","effectAllowed","isOrSetDropDisabled","isDisabled","preventDrop","triggerHidezonesEvent","triggerUsingOldApi","hideZonesEvent","createEvent","initEvent","CustomEvent","dispatchEvent","attachEvents","effect","elementFromPoint","clientX","clientY","uiPublicApi","_parent","_templating","addCacheToDom","clearFiles","addExtraDropzone","_dnd","removeExtraDropzone","getItemByFileId","isHiddenForever","getFileContainer","_setupDragAndDrop","_totalFilesInBatch","_filesInBatchAddedToUi","_setupClickAndEditEventHandlers","formattedFilename","updateFilename","uploadPaused","continued","uploadContinued","getId","fileContainerOrChildEl","getFileId","getDropTarget","qqDropTarget","uiPrivateApi","_removeFileItem","removeFile","_fileButtonsClickHandler","FileButtonsClickHandler","_bindFileButtonsClickEvent","_focusinEventSupported","_isEditFilenameEnabled","_filenameClickHandler","_bindFilenameClickEvent","_filenameInputFocusInHandler","_bindFilenameInputFocusInEvent","_filenameInputFocusHandler","_bindFilenameInputFocusEvent","dragAndDrop","extraDropzones","templating","defaultDropZone","getDropZone","showDropProcessing","hideDropProcessing","errorData","lvl","onDeleteFile","onRetry","onPause","onContinue","onGetName","isEditFilenamePossible","FilenameClickHandler","FilenameInputFocusHandler","_filenameEditHandler","onGetUploadStatus","onSetName","onEditingStatusChange","isEditing","qqInput","getEditInput","qqFileContainer","hideFilename","hideEditIcon","showFilename","showEditIcon","markFilenameEditable","hideRetry","setStatusText","_classes","retrying","hidePause","FilenameInputFocusInHandler","hideSpinner","resetTotalProgress","reportDirectoryPaths","qqpath","_addToList","addHandler","updateProgress","hideCancel","hideProgress","waitingForResponse","_displayFileSize","completeUpload","_markFileAsSuccessful","fail","showCancel","isRetryPossible","showRetry","_controlFailureTextDisplay","parentRetVal","newResult","showDeleteButton","_maybeUpdateThumbnail","showSpinner","allowPause","retryNumForDisplay","maxAuto","retryNote","_showCancelLink","showAutoRetryNote","autoRetryNote","resetProgress","_onSubmitDeleteSuccess","forceConfirm","_showDeleteConfirm","_sendDeleteRequest","deletingFailedText","hideDeleteButton","deletingStatusText","confirmMessage","deleteRequestArgs","showConfirm","canned","prependData","prependIndex","dontDisplay","hideScaled","prependFiles","disableCancel","_handledProxyGroup","_clearList","addFileToCache","updateThumbnail","thumbnails","generatePreview","fileSizeOnSubmit","loadedSize","sizeForDisplay","_formatProgress","uploadedSize","formatProgress","mode","responseProperty","failureReason","failedUploadTextDisplay","failUpload","enableTooltip","_showTooltip","showMessage","_setupPastePrompt","namePromptMessage","defaultVal","showPrompt","fileStatus","placeholders","waitUntilResponse","listElement","template","editable","tooManyFilesError","unsupportedBrowser","promptForName","maxCount","notAvailablePath","waitingPath","timeBetweenThumbs","hasDialog","showDialog","confirm","defaultValue","prompt","Templating","templateIdOrEl","containerEl","fileContainerEl","maxThumbs","waitUntilUpdate","thumbnailNotAvailable","waitingForThumbnail","renderFailure","isEditElementsExist","isRetryElementExist","templateHtml","showThumbnails","serverScale","FILE_ID_ATTR","FILE_CLASS_PREFIX","THUMBNAIL_MAX_SIZE_ATTR","THUMBNAIL_SERVER_SCALE_ATTR","HIDE_DROPZONE_ATTR","DROPZPONE_TEXT_ATTR","IN_PROGRESS_CLASS","HIDDEN_FOREVER_CLASS","fileBatch","content","createDocumentFragment","map","isCancelDisabled","generatedThumbnails","thumbnailQueueMonitorRunning","thumbGenerationQueue","thumbnailMaxSize","selectorClasses","alertDialog","dialogCancelButton","confirmDialog","dialogMessage","dialogOkButton","promptDialog","drop","list","progressBarContainer","totalProgressBarContainer","totalProgressBar","spinner","continueButton","deleteButton","statusText","editFilenameInput","editNameIcon","dropText","dropProcessing","dropProcessingSpinner","thumbnail","previewGeneration","cachedThumbnailNotAvailableImg","cachedWaitingForThumbnailImg","cacheThumbnailPlaceholders","notAvailableUrl","waitingUrl","updatedImg","displayWaitingImg","waitingImgPlacement","maybeScalePlaceholderViaCss","show","generateNewPreview","getThumbnail","qqThumbnailId","maybeSetDisplayNotAvailableImg","generateNextQueuedPreview","queuedThumbRequest","update","processUpdateQueuedPreviewRequest","processNewQueuedPreviewRequest","getCancel","getTemplateEl","getContinue","getDialog","getDelete","getDropProcessing","getEditIcon","getPause","getProgress","getRetry","getSpinner","cssClass","previewing","notAvailableImgPlacement","parseAndGetTemplate","scriptEl","scriptHtml","fileListNode","tempTemplateEl","fileListHtml","defaultButton","dropTextEl","uploaderEl","fileTemplate","prependFile","parentEl","beforeEl","optFileOrBlob","relatedThumbnailId","useCachedPreview","showWaitingImg","setProgressBarWidth","percent","bar","progressBarSelector","targetThumbnailId","cachedThumbnailId","targetThumbnail","cachedThumbnail","hideTotalProgress","cantRenderEl","prependInfo","hideForever","batch","thumb","fileEl","fileNameEl","waitingImg","currentNode","getFileList","filenameEl","isFileName","icon","isEditIcon","isEditInput","isCancel","allowContinueButton","isPause","isContinueButton","isDeleteButton","isRetry","textEl","dialog","messageEl","inputEl","cancelBtn","okBtn","closeHandler","cancelClickHandler","okClickHandler","close","showModal","UiEventHandler","s","protectedApi","eventType","srcElement","onHandled","attachTo","getFileIdFromItem","qqFileId","getDisposeSupport","examineEvent","buttonHandlers","buttonType","firstLetterCapButtonType","inheritedInternalApi","handleFilenameEdit","FilenameEditHandler","handleInputFocus","getFilenameSansExtension","filenameSansExt","getOriginalExtension","origName","handleNameUpdate","newFilenameInputEl","origExtension","registerInputBlurHandler","registerInputEnterKeyHandler","keyCode","which","focusInput","focus"],"mappings":"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","file":"jquery.fine-uploader.min.js","sourcesContent":[null,"/*globals jQuery, qq*/\n(function($) {\n \"use strict\";\n var $el,\n pluginOptions = [\"uploaderType\", \"endpointType\"];\n\n function init(options) {\n var xformedOpts = transformVariables(options || {}),\n newUploaderInstance = getNewUploaderInstance(xformedOpts);\n\n uploader(newUploaderInstance);\n addCallbacks(xformedOpts, newUploaderInstance);\n\n return $el;\n }\n\n function getNewUploaderInstance(params) {\n var uploaderType = pluginOption(\"uploaderType\"),\n namespace = pluginOption(\"endpointType\");\n\n // If the integrator has defined a specific type of uploader to load, use that, otherwise assume `qq.FineUploader`\n if (uploaderType) {\n // We can determine the correct constructor function to invoke by combining \"FineUploader\"\n // with the upper camel cased `uploaderType` value.\n uploaderType = uploaderType.charAt(0).toUpperCase() + uploaderType.slice(1).toLowerCase();\n\n if (namespace) {\n return new qq[namespace][\"FineUploader\" + uploaderType](params);\n }\n\n return new qq[\"FineUploader\" + uploaderType](params);\n }\n else {\n if (namespace) {\n return new qq[namespace].FineUploader(params);\n }\n\n return new qq.FineUploader(params);\n }\n }\n\n function dataStore(key, val) {\n var data = $el.data(\"fineuploader\");\n\n if (val) {\n if (data === undefined) {\n data = {};\n }\n data[key] = val;\n $el.data(\"fineuploader\", data);\n }\n else {\n if (data === undefined) {\n return null;\n }\n return data[key];\n }\n }\n\n //the underlying Fine Uploader instance is stored in jQuery's data stored, associated with the element\n // tied to this instance of the plug-in\n function uploader(instanceToStore) {\n return dataStore(\"uploader\", instanceToStore);\n }\n\n function pluginOption(option, optionVal) {\n return dataStore(option, optionVal);\n }\n\n // Implement all callbacks defined in Fine Uploader as functions that trigger appropriately names events and\n // return the result of executing the bound handler back to Fine Uploader\n function addCallbacks(transformedOpts, newUploaderInstance) {\n var callbacks = transformedOpts.callbacks = {};\n\n $.each(newUploaderInstance._options.callbacks, function(prop, nonJqueryCallback) {\n var name, callbackEventTarget;\n\n name = /^on(\\w+)/.exec(prop)[1];\n name = name.substring(0, 1).toLowerCase() + name.substring(1);\n callbackEventTarget = $el;\n\n callbacks[prop] = function() {\n var originalArgs = Array.prototype.slice.call(arguments),\n transformedArgs = [],\n nonJqueryCallbackRetVal, jqueryEventCallbackRetVal;\n\n $.each(originalArgs, function(idx, arg) {\n transformedArgs.push(maybeWrapInJquery(arg));\n });\n\n nonJqueryCallbackRetVal = nonJqueryCallback.apply(this, originalArgs);\n\n try {\n jqueryEventCallbackRetVal = callbackEventTarget.triggerHandler(name, transformedArgs);\n }\n catch (error) {\n qq.log(\"Caught error in Fine Uploader jQuery event handler: \" + error.message, \"error\");\n }\n\n /*jshint -W116*/\n if (nonJqueryCallbackRetVal != null) {\n return nonJqueryCallbackRetVal;\n }\n return jqueryEventCallbackRetVal;\n };\n });\n\n newUploaderInstance._options.callbacks = callbacks;\n }\n\n //transform jQuery objects into HTMLElements, and pass along all other option properties\n function transformVariables(source, dest) {\n var xformed, arrayVals;\n\n if (dest === undefined) {\n if (source.uploaderType !== \"basic\") {\n xformed = { element: $el[0] };\n }\n else {\n xformed = {};\n }\n }\n else {\n xformed = dest;\n }\n\n $.each(source, function(prop, val) {\n if ($.inArray(prop, pluginOptions) >= 0) {\n pluginOption(prop, val);\n }\n else if (val instanceof $) {\n xformed[prop] = val[0];\n }\n else if ($.isPlainObject(val)) {\n xformed[prop] = {};\n transformVariables(val, xformed[prop]);\n }\n else if ($.isArray(val)) {\n arrayVals = [];\n $.each(val, function(idx, arrayVal) {\n var arrayObjDest = {};\n\n if (arrayVal instanceof $) {\n $.merge(arrayVals, arrayVal);\n }\n else if ($.isPlainObject(arrayVal)) {\n transformVariables(arrayVal, arrayObjDest);\n arrayVals.push(arrayObjDest);\n }\n else {\n arrayVals.push(arrayVal);\n }\n });\n xformed[prop] = arrayVals;\n }\n else {\n xformed[prop] = val;\n }\n });\n\n if (dest === undefined) {\n return xformed;\n }\n }\n\n function isValidCommand(command) {\n return $.type(command) === \"string\" &&\n !command.match(/^_/) && //enforce private methods convention\n uploader()[command] !== undefined;\n }\n\n // Assuming we have already verified that this is a valid command, call the associated function in the underlying\n // Fine Uploader instance (passing along the arguments from the caller) and return the result of the call back to the caller\n function delegateCommand(command) {\n var xformedArgs = [],\n origArgs = Array.prototype.slice.call(arguments, 1),\n retVal;\n\n transformVariables(origArgs, xformedArgs);\n\n retVal = uploader()[command].apply(uploader(), xformedArgs);\n\n return maybeWrapInJquery(retVal);\n }\n\n // If the value is an `HTMLElement` or `HTMLDocument`, wrap it in a `jQuery` object\n function maybeWrapInJquery(val) {\n var transformedVal = val;\n\n // If the command is returning an `HTMLElement` or `HTMLDocument`, wrap it in a `jQuery` object\n /*jshint -W116*/\n if (val != null && typeof val === \"object\" &&\n (val.nodeType === 1 || val.nodeType === 9) && val.cloneNode) {\n\n transformedVal = $(val);\n }\n\n return transformedVal;\n }\n\n $.fn.fineUploader = function(optionsOrCommand) {\n var self = this, selfArgs = arguments, retVals = [];\n\n this.each(function(index, el) {\n $el = $(el);\n\n if (uploader() && isValidCommand(optionsOrCommand)) {\n retVals.push(delegateCommand.apply(self, selfArgs));\n\n if (self.length === 1) {\n return false;\n }\n }\n else if (typeof optionsOrCommand === \"object\" || !optionsOrCommand) {\n init.apply(self, selfArgs);\n }\n else {\n $.error(\"Method \" + optionsOrCommand + \" does not exist on jQuery.fineUploader\");\n }\n });\n\n if (retVals.length === 1) {\n return retVals[0];\n }\n else if (retVals.length > 1) {\n return retVals;\n }\n\n return this;\n };\n\n}(jQuery));\n","/*globals jQuery, qq*/\n(function($) {\n \"use strict\";\n var rootDataKey = \"fineUploaderDnd\",\n $el;\n\n function init(options) {\n if (!options) {\n options = {};\n }\n\n options.dropZoneElements = [$el];\n var xformedOpts = transformVariables(options);\n addCallbacks(xformedOpts);\n dnd(new qq.DragAndDrop(xformedOpts));\n\n return $el;\n }\n\n function dataStore(key, val) {\n var data = $el.data(rootDataKey);\n\n if (val) {\n if (data === undefined) {\n data = {};\n }\n data[key] = val;\n $el.data(rootDataKey, data);\n }\n else {\n if (data === undefined) {\n return null;\n }\n return data[key];\n }\n }\n\n function dnd(instanceToStore) {\n return dataStore(\"dndInstance\", instanceToStore);\n }\n\n function addCallbacks(transformedOpts) {\n var callbacks = transformedOpts.callbacks = {};\n\n $.each(new qq.DragAndDrop.callbacks(), function(prop, func) {\n var name = prop,\n $callbackEl;\n\n $callbackEl = $el;\n\n callbacks[prop] = function() {\n var args = Array.prototype.slice.call(arguments),\n jqueryHandlerResult = $callbackEl.triggerHandler(name, args);\n\n return jqueryHandlerResult;\n };\n });\n }\n\n //transform jQuery objects into HTMLElements, and pass along all other option properties\n function transformVariables(source, dest) {\n var xformed, arrayVals;\n\n if (dest === undefined) {\n xformed = {};\n }\n else {\n xformed = dest;\n }\n\n $.each(source, function(prop, val) {\n if (val instanceof $) {\n xformed[prop] = val[0];\n }\n else if ($.isPlainObject(val)) {\n xformed[prop] = {};\n transformVariables(val, xformed[prop]);\n }\n else if ($.isArray(val)) {\n arrayVals = [];\n $.each(val, function(idx, arrayVal) {\n if (arrayVal instanceof $) {\n $.merge(arrayVals, arrayVal);\n }\n else {\n arrayVals.push(arrayVal);\n }\n });\n xformed[prop] = arrayVals;\n }\n else {\n xformed[prop] = val;\n }\n });\n\n if (dest === undefined) {\n return xformed;\n }\n }\n\n function isValidCommand(command) {\n return $.type(command) === \"string\" &&\n command === \"dispose\" &&\n dnd()[command] !== undefined;\n }\n\n function delegateCommand(command) {\n var xformedArgs = [], origArgs = Array.prototype.slice.call(arguments, 1);\n transformVariables(origArgs, xformedArgs);\n return dnd()[command].apply(dnd(), xformedArgs);\n }\n\n $.fn.fineUploaderDnd = function(optionsOrCommand) {\n var self = this, selfArgs = arguments, retVals = [];\n\n this.each(function(index, el) {\n $el = $(el);\n\n if (dnd() && isValidCommand(optionsOrCommand)) {\n retVals.push(delegateCommand.apply(self, selfArgs));\n\n if (self.length === 1) {\n return false;\n }\n }\n else if (typeof optionsOrCommand === \"object\" || !optionsOrCommand) {\n init.apply(self, selfArgs);\n }\n else {\n $.error(\"Method \" + optionsOrCommand + \" does not exist in Fine Uploader's DnD module.\");\n }\n });\n\n if (retVals.length === 1) {\n return retVals[0];\n }\n else if (retVals.length > 1) {\n return retVals;\n }\n\n return this;\n };\n\n}(jQuery));\n","/*globals window, navigator, document, FormData, File, HTMLInputElement, XMLHttpRequest, Blob, Storage, ActiveXObject */\n/* jshint -W079 */\nvar qq = function(element) {\n \"use strict\";\n\n return {\n hide: function() {\n element.style.display = \"none\";\n return this;\n },\n\n /** Returns the function which detaches attached event */\n attach: function(type, fn) {\n if (element.addEventListener) {\n element.addEventListener(type, fn, false);\n } else if (element.attachEvent) {\n element.attachEvent(\"on\" + type, fn);\n }\n return function() {\n qq(element).detach(type, fn);\n };\n },\n\n detach: function(type, fn) {\n if (element.removeEventListener) {\n element.removeEventListener(type, fn, false);\n } else if (element.attachEvent) {\n element.detachEvent(\"on\" + type, fn);\n }\n return this;\n },\n\n contains: function(descendant) {\n // The [W3C spec](http://www.w3.org/TR/domcore/#dom-node-contains)\n // says a `null` (or ostensibly `undefined`) parameter\n // passed into `Node.contains` should result in a false return value.\n // IE7 throws an exception if the parameter is `undefined` though.\n if (!descendant) {\n return false;\n }\n\n // compareposition returns false in this case\n if (element === descendant) {\n return true;\n }\n\n if (element.contains) {\n return element.contains(descendant);\n } else {\n /*jslint bitwise: true*/\n return !!(descendant.compareDocumentPosition(element) & 8);\n }\n },\n\n /**\n * Insert this element before elementB.\n */\n insertBefore: function(elementB) {\n elementB.parentNode.insertBefore(element, elementB);\n return this;\n },\n\n remove: function() {\n element.parentNode.removeChild(element);\n return this;\n },\n\n /**\n * Sets styles for an element.\n * Fixes opacity in IE6-8.\n */\n css: function(styles) {\n /*jshint eqnull: true*/\n if (element.style == null) {\n throw new qq.Error(\"Can't apply style to node as it is not on the HTMLElement prototype chain!\");\n }\n\n /*jshint -W116*/\n if (styles.opacity != null) {\n if (typeof element.style.opacity !== \"string\" && typeof (element.filters) !== \"undefined\") {\n styles.filter = \"alpha(opacity=\" + Math.round(100 * styles.opacity) + \")\";\n }\n }\n qq.extend(element.style, styles);\n\n return this;\n },\n\n hasClass: function(name, considerParent) {\n var re = new RegExp(\"(^| )\" + name + \"( |$)\");\n return re.test(element.className) || !!(considerParent && re.test(element.parentNode.className));\n },\n\n addClass: function(name) {\n if (!qq(element).hasClass(name)) {\n element.className += \" \" + name;\n }\n return this;\n },\n\n removeClass: function(name) {\n var re = new RegExp(\"(^| )\" + name + \"( |$)\");\n element.className = element.className.replace(re, \" \").replace(/^\\s+|\\s+$/g, \"\");\n return this;\n },\n\n getByClass: function(className, first) {\n var candidates,\n result = [];\n\n if (first && element.querySelector) {\n return element.querySelector(\".\" + className);\n }\n else if (element.querySelectorAll) {\n return element.querySelectorAll(\".\" + className);\n }\n\n candidates = element.getElementsByTagName(\"*\");\n\n qq.each(candidates, function(idx, val) {\n if (qq(val).hasClass(className)) {\n result.push(val);\n }\n });\n return first ? result[0] : result;\n },\n\n getFirstByClass: function(className) {\n return qq(element).getByClass(className, true);\n },\n\n children: function() {\n var children = [],\n child = element.firstChild;\n\n while (child) {\n if (child.nodeType === 1) {\n children.push(child);\n }\n child = child.nextSibling;\n }\n\n return children;\n },\n\n setText: function(text) {\n element.innerText = text;\n element.textContent = text;\n return this;\n },\n\n clearText: function() {\n return qq(element).setText(\"\");\n },\n\n // Returns true if the attribute exists on the element\n // AND the value of the attribute is NOT \"false\" (case-insensitive)\n hasAttribute: function(attrName) {\n var attrVal;\n\n if (element.hasAttribute) {\n\n if (!element.hasAttribute(attrName)) {\n return false;\n }\n\n /*jshint -W116*/\n return (/^false$/i).exec(element.getAttribute(attrName)) == null;\n }\n else {\n attrVal = element[attrName];\n\n if (attrVal === undefined) {\n return false;\n }\n\n /*jshint -W116*/\n return (/^false$/i).exec(attrVal) == null;\n }\n }\n };\n};\n\n(function() {\n \"use strict\";\n\n qq.canvasToBlob = function(canvas, mime, quality) {\n return qq.dataUriToBlob(canvas.toDataURL(mime, quality));\n };\n\n qq.dataUriToBlob = function(dataUri) {\n var arrayBuffer, byteString,\n createBlob = function(data, mime) {\n var BlobBuilder = window.BlobBuilder ||\n window.WebKitBlobBuilder ||\n window.MozBlobBuilder ||\n window.MSBlobBuilder,\n blobBuilder = BlobBuilder && new BlobBuilder();\n\n if (blobBuilder) {\n blobBuilder.append(data);\n return blobBuilder.getBlob(mime);\n }\n else {\n return new Blob([data], {type: mime});\n }\n },\n intArray, mimeString;\n\n // convert base64 to raw binary data held in a string\n if (dataUri.split(\",\")[0].indexOf(\"base64\") >= 0) {\n byteString = atob(dataUri.split(\",\")[1]);\n }\n else {\n byteString = decodeURI(dataUri.split(\",\")[1]);\n }\n\n // extract the MIME\n mimeString = dataUri.split(\",\")[0]\n .split(\":\")[1]\n .split(\";\")[0];\n\n // write the bytes of the binary string to an ArrayBuffer\n arrayBuffer = new ArrayBuffer(byteString.length);\n intArray = new Uint8Array(arrayBuffer);\n qq.each(byteString, function(idx, character) {\n intArray[idx] = character.charCodeAt(0);\n });\n\n return createBlob(arrayBuffer, mimeString);\n };\n\n qq.log = function(message, level) {\n if (window.console) {\n if (!level || level === \"info\") {\n window.console.log(message);\n }\n else\n {\n if (window.console[level]) {\n window.console[level](message);\n }\n else {\n window.console.log(\"<\" + level + \"> \" + message);\n }\n }\n }\n };\n\n qq.isObject = function(variable) {\n return variable && !variable.nodeType && Object.prototype.toString.call(variable) === \"[object Object]\";\n };\n\n qq.isFunction = function(variable) {\n return typeof (variable) === \"function\";\n };\n\n /**\n * Check the type of a value. Is it an \"array\"?\n *\n * @param value value to test.\n * @returns true if the value is an array or associated with an `ArrayBuffer`\n */\n qq.isArray = function(value) {\n return Object.prototype.toString.call(value) === \"[object Array]\" ||\n (value && window.ArrayBuffer && value.buffer && value.buffer.constructor === ArrayBuffer);\n };\n\n // Looks for an object on a `DataTransfer` object that is associated with drop events when utilizing the Filesystem API.\n qq.isItemList = function(maybeItemList) {\n return Object.prototype.toString.call(maybeItemList) === \"[object DataTransferItemList]\";\n };\n\n // Looks for an object on a `NodeList` or an `HTMLCollection`|`HTMLFormElement`|`HTMLSelectElement`\n // object that is associated with collections of Nodes.\n qq.isNodeList = function(maybeNodeList) {\n return Object.prototype.toString.call(maybeNodeList) === \"[object NodeList]\" ||\n // If `HTMLCollection` is the actual type of the object, we must determine this\n // by checking for expected properties/methods on the object\n (maybeNodeList.item && maybeNodeList.namedItem);\n };\n\n qq.isString = function(maybeString) {\n return Object.prototype.toString.call(maybeString) === \"[object String]\";\n };\n\n qq.trimStr = function(string) {\n if (String.prototype.trim) {\n return string.trim();\n }\n\n return string.replace(/^\\s+|\\s+$/g, \"\");\n };\n\n /**\n * @param str String to format.\n * @returns {string} A string, swapping argument values with the associated occurrence of {} in the passed string.\n */\n qq.format = function(str) {\n\n var args = Array.prototype.slice.call(arguments, 1),\n newStr = str,\n nextIdxToReplace = newStr.indexOf(\"{}\");\n\n qq.each(args, function(idx, val) {\n var strBefore = newStr.substring(0, nextIdxToReplace),\n strAfter = newStr.substring(nextIdxToReplace + 2);\n\n newStr = strBefore + val + strAfter;\n nextIdxToReplace = newStr.indexOf(\"{}\", nextIdxToReplace + val.length);\n\n // End the loop if we have run out of tokens (when the arguments exceed the # of tokens)\n if (nextIdxToReplace < 0) {\n return false;\n }\n });\n\n return newStr;\n };\n\n qq.isFile = function(maybeFile) {\n return window.File && Object.prototype.toString.call(maybeFile) === \"[object File]\";\n };\n\n qq.isFileList = function(maybeFileList) {\n return window.FileList && Object.prototype.toString.call(maybeFileList) === \"[object FileList]\";\n };\n\n qq.isFileOrInput = function(maybeFileOrInput) {\n return qq.isFile(maybeFileOrInput) || qq.isInput(maybeFileOrInput);\n };\n\n qq.isInput = function(maybeInput, notFile) {\n var evaluateType = function(type) {\n var normalizedType = type.toLowerCase();\n\n if (notFile) {\n return normalizedType !== \"file\";\n }\n\n return normalizedType === \"file\";\n };\n\n if (window.HTMLInputElement) {\n if (Object.prototype.toString.call(maybeInput) === \"[object HTMLInputElement]\") {\n if (maybeInput.type && evaluateType(maybeInput.type)) {\n return true;\n }\n }\n }\n if (maybeInput.tagName) {\n if (maybeInput.tagName.toLowerCase() === \"input\") {\n if (maybeInput.type && evaluateType(maybeInput.type)) {\n return true;\n }\n }\n }\n\n return false;\n };\n\n qq.isBlob = function(maybeBlob) {\n if (window.Blob && Object.prototype.toString.call(maybeBlob) === \"[object Blob]\") {\n return true;\n }\n };\n\n qq.isXhrUploadSupported = function() {\n var input = document.createElement(\"input\");\n input.type = \"file\";\n\n return (\n input.multiple !== undefined &&\n typeof File !== \"undefined\" &&\n typeof FormData !== \"undefined\" &&\n typeof (qq.createXhrInstance()).upload !== \"undefined\");\n };\n\n // Fall back to ActiveX is native XHR is disabled (possible in any version of IE).\n qq.createXhrInstance = function() {\n if (window.XMLHttpRequest) {\n return new XMLHttpRequest();\n }\n\n try {\n return new ActiveXObject(\"MSXML2.XMLHTTP.3.0\");\n }\n catch (error) {\n qq.log(\"Neither XHR or ActiveX are supported!\", \"error\");\n return null;\n }\n };\n\n qq.isFolderDropSupported = function(dataTransfer) {\n return dataTransfer.items &&\n dataTransfer.items.length > 0 &&\n dataTransfer.items[0].webkitGetAsEntry;\n };\n\n qq.isFileChunkingSupported = function() {\n return !qq.androidStock() && //Android's stock browser cannot upload Blobs correctly\n qq.isXhrUploadSupported() &&\n (File.prototype.slice !== undefined || File.prototype.webkitSlice !== undefined || File.prototype.mozSlice !== undefined);\n };\n\n qq.sliceBlob = function(fileOrBlob, start, end) {\n var slicer = fileOrBlob.slice || fileOrBlob.mozSlice || fileOrBlob.webkitSlice;\n\n return slicer.call(fileOrBlob, start, end);\n };\n\n qq.arrayBufferToHex = function(buffer) {\n var bytesAsHex = \"\",\n bytes = new Uint8Array(buffer);\n\n qq.each(bytes, function(idx, byt) {\n var byteAsHexStr = byt.toString(16);\n\n if (byteAsHexStr.length < 2) {\n byteAsHexStr = \"0\" + byteAsHexStr;\n }\n\n bytesAsHex += byteAsHexStr;\n });\n\n return bytesAsHex;\n };\n\n qq.readBlobToHex = function(blob, startOffset, length) {\n var initialBlob = qq.sliceBlob(blob, startOffset, startOffset + length),\n fileReader = new FileReader(),\n promise = new qq.Promise();\n\n fileReader.onload = function() {\n promise.success(qq.arrayBufferToHex(fileReader.result));\n };\n\n fileReader.onerror = promise.failure;\n\n fileReader.readAsArrayBuffer(initialBlob);\n\n return promise;\n };\n\n qq.extend = function(first, second, extendNested) {\n qq.each(second, function(prop, val) {\n if (extendNested && qq.isObject(val)) {\n if (first[prop] === undefined) {\n first[prop] = {};\n }\n qq.extend(first[prop], val, true);\n }\n else {\n first[prop] = val;\n }\n });\n\n return first;\n };\n\n /**\n * Allow properties in one object to override properties in another,\n * keeping track of the original values from the target object.\n *\n * Note that the pre-overriden properties to be overriden by the source will be passed into the `sourceFn` when it is invoked.\n *\n * @param target Update properties in this object from some source\n * @param sourceFn A function that, when invoked, will return properties that will replace properties with the same name in the target.\n * @returns {object} The target object\n */\n qq.override = function(target, sourceFn) {\n var super_ = {},\n source = sourceFn(super_);\n\n qq.each(source, function(srcPropName, srcPropVal) {\n if (target[srcPropName] !== undefined) {\n super_[srcPropName] = target[srcPropName];\n }\n\n target[srcPropName] = srcPropVal;\n });\n\n return target;\n };\n\n /**\n * Searches for a given element (elt) in the array, returns -1 if it is not present.\n */\n qq.indexOf = function(arr, elt, from) {\n if (arr.indexOf) {\n return arr.indexOf(elt, from);\n }\n\n from = from || 0;\n var len = arr.length;\n\n if (from < 0) {\n from += len;\n }\n\n for (; from < len; from += 1) {\n if (arr.hasOwnProperty(from) && arr[from] === elt) {\n return from;\n }\n }\n return -1;\n };\n\n //this is a version 4 UUID\n qq.getUniqueId = function() {\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, function(c) {\n /*jslint eqeq: true, bitwise: true*/\n var r = Math.random() * 16 | 0, v = c == \"x\" ? r : (r & 0x3 | 0x8);\n return v.toString(16);\n });\n };\n\n //\n // Browsers and platforms detection\n qq.ie = function() {\n return navigator.userAgent.indexOf(\"MSIE\") !== -1 ||\n navigator.userAgent.indexOf(\"Trident\") !== -1;\n };\n\n qq.ie7 = function() {\n return navigator.userAgent.indexOf(\"MSIE 7\") !== -1;\n };\n\n qq.ie8 = function() {\n return navigator.userAgent.indexOf(\"MSIE 8\") !== -1;\n };\n\n qq.ie10 = function() {\n return navigator.userAgent.indexOf(\"MSIE 10\") !== -1;\n };\n\n qq.ie11 = function() {\n return qq.ie() && navigator.userAgent.indexOf(\"rv:11\") !== -1;\n };\n\n qq.edge = function() {\n return navigator.userAgent.indexOf(\"Edge\") >= 0;\n };\n\n qq.safari = function() {\n return navigator.vendor !== undefined && navigator.vendor.indexOf(\"Apple\") !== -1;\n };\n\n qq.chrome = function() {\n return navigator.vendor !== undefined && navigator.vendor.indexOf(\"Google\") !== -1;\n };\n\n qq.opera = function() {\n return navigator.vendor !== undefined && navigator.vendor.indexOf(\"Opera\") !== -1;\n };\n\n qq.firefox = function() {\n return (!qq.edge() && !qq.ie11() && navigator.userAgent.indexOf(\"Mozilla\") !== -1 && navigator.vendor !== undefined && navigator.vendor === \"\");\n };\n\n qq.windows = function() {\n return navigator.platform === \"Win32\";\n };\n\n qq.android = function() {\n return navigator.userAgent.toLowerCase().indexOf(\"android\") !== -1;\n };\n\n // We need to identify the Android stock browser via the UA string to work around various bugs in this browser,\n // such as the one that prevents a `Blob` from being uploaded.\n qq.androidStock = function() {\n return qq.android() && navigator.userAgent.toLowerCase().indexOf(\"chrome\") < 0;\n };\n\n qq.ios6 = function() {\n return qq.ios() && navigator.userAgent.indexOf(\" OS 6_\") !== -1;\n };\n\n qq.ios7 = function() {\n return qq.ios() && navigator.userAgent.indexOf(\" OS 7_\") !== -1;\n };\n\n qq.ios8 = function() {\n return qq.ios() && navigator.userAgent.indexOf(\" OS 8_\") !== -1;\n };\n\n // iOS 8.0.0\n qq.ios800 = function() {\n return qq.ios() && navigator.userAgent.indexOf(\" OS 8_0 \") !== -1;\n };\n\n qq.ios = function() {\n /*jshint -W014 */\n return navigator.userAgent.indexOf(\"iPad\") !== -1\n || navigator.userAgent.indexOf(\"iPod\") !== -1\n || navigator.userAgent.indexOf(\"iPhone\") !== -1;\n };\n\n qq.iosChrome = function() {\n return qq.ios() && navigator.userAgent.indexOf(\"CriOS\") !== -1;\n };\n\n qq.iosSafari = function() {\n return qq.ios() && !qq.iosChrome() && navigator.userAgent.indexOf(\"Safari\") !== -1;\n };\n\n qq.iosSafariWebView = function() {\n return qq.ios() && !qq.iosChrome() && !qq.iosSafari();\n };\n\n //\n // Events\n\n qq.preventDefault = function(e) {\n if (e.preventDefault) {\n e.preventDefault();\n } else {\n e.returnValue = false;\n }\n };\n\n /**\n * Creates and returns element from html string\n * Uses innerHTML to create an element\n */\n qq.toElement = (function() {\n var div = document.createElement(\"div\");\n return function(html) {\n div.innerHTML = html;\n var element = div.firstChild;\n div.removeChild(element);\n return element;\n };\n }());\n\n //key and value are passed to callback for each entry in the iterable item\n qq.each = function(iterableItem, callback) {\n var keyOrIndex, retVal;\n\n if (iterableItem) {\n // Iterate through [`Storage`](http://www.w3.org/TR/webstorage/#the-storage-interface) items\n if (window.Storage && iterableItem.constructor === window.Storage) {\n for (keyOrIndex = 0; keyOrIndex < iterableItem.length; keyOrIndex++) {\n retVal = callback(iterableItem.key(keyOrIndex), iterableItem.getItem(iterableItem.key(keyOrIndex)));\n if (retVal === false) {\n break;\n }\n }\n }\n // `DataTransferItemList` & `NodeList` objects are array-like and should be treated as arrays\n // when iterating over items inside the object.\n else if (qq.isArray(iterableItem) || qq.isItemList(iterableItem) || qq.isNodeList(iterableItem)) {\n for (keyOrIndex = 0; keyOrIndex < iterableItem.length; keyOrIndex++) {\n retVal = callback(keyOrIndex, iterableItem[keyOrIndex]);\n if (retVal === false) {\n break;\n }\n }\n }\n else if (qq.isString(iterableItem)) {\n for (keyOrIndex = 0; keyOrIndex < iterableItem.length; keyOrIndex++) {\n retVal = callback(keyOrIndex, iterableItem.charAt(keyOrIndex));\n if (retVal === false) {\n break;\n }\n }\n }\n else {\n for (keyOrIndex in iterableItem) {\n if (Object.prototype.hasOwnProperty.call(iterableItem, keyOrIndex)) {\n retVal = callback(keyOrIndex, iterableItem[keyOrIndex]);\n if (retVal === false) {\n break;\n }\n }\n }\n }\n }\n };\n\n //include any args that should be passed to the new function after the context arg\n qq.bind = function(oldFunc, context) {\n if (qq.isFunction(oldFunc)) {\n var args = Array.prototype.slice.call(arguments, 2);\n\n return function() {\n var newArgs = qq.extend([], args);\n if (arguments.length) {\n newArgs = newArgs.concat(Array.prototype.slice.call(arguments));\n }\n return oldFunc.apply(context, newArgs);\n };\n }\n\n throw new Error(\"first parameter must be a function!\");\n };\n\n /**\n * obj2url() takes a json-object as argument and generates\n * a querystring. pretty much like jQuery.param()\n *\n * how to use:\n *\n * `qq.obj2url({a:'b',c:'d'},'http://any.url/upload?otherParam=value');`\n *\n * will result in:\n *\n * `http://any.url/upload?otherParam=value&a=b&c=d`\n *\n * @param Object JSON-Object\n * @param String current querystring-part\n * @return String encoded querystring\n */\n qq.obj2url = function(obj, temp, prefixDone) {\n /*jshint laxbreak: true*/\n var uristrings = [],\n prefix = \"&\",\n add = function(nextObj, i) {\n var nextTemp = temp\n ? (/\\[\\]$/.test(temp)) // prevent double-encoding\n ? temp\n : temp + \"[\" + i + \"]\"\n : i;\n if ((nextTemp !== \"undefined\") && (i !== \"undefined\")) {\n uristrings.push(\n (typeof nextObj === \"object\")\n ? qq.obj2url(nextObj, nextTemp, true)\n : (Object.prototype.toString.call(nextObj) === \"[object Function]\")\n ? encodeURIComponent(nextTemp) + \"=\" + encodeURIComponent(nextObj())\n : encodeURIComponent(nextTemp) + \"=\" + encodeURIComponent(nextObj)\n );\n }\n };\n\n if (!prefixDone && temp) {\n prefix = (/\\?/.test(temp)) ? (/\\?$/.test(temp)) ? \"\" : \"&\" : \"?\";\n uristrings.push(temp);\n uristrings.push(qq.obj2url(obj));\n } else if ((Object.prototype.toString.call(obj) === \"[object Array]\") && (typeof obj !== \"undefined\")) {\n qq.each(obj, function(idx, val) {\n add(val, idx);\n });\n } else if ((typeof obj !== \"undefined\") && (obj !== null) && (typeof obj === \"object\")) {\n qq.each(obj, function(prop, val) {\n add(val, prop);\n });\n } else {\n uristrings.push(encodeURIComponent(temp) + \"=\" + encodeURIComponent(obj));\n }\n\n if (temp) {\n return uristrings.join(prefix);\n } else {\n return uristrings.join(prefix)\n .replace(/^&/, \"\")\n .replace(/%20/g, \"+\");\n }\n };\n\n qq.obj2FormData = function(obj, formData, arrayKeyName) {\n if (!formData) {\n formData = new FormData();\n }\n\n qq.each(obj, function(key, val) {\n key = arrayKeyName ? arrayKeyName + \"[\" + key + \"]\" : key;\n\n if (qq.isObject(val)) {\n qq.obj2FormData(val, formData, key);\n }\n else if (qq.isFunction(val)) {\n formData.append(key, val());\n }\n else {\n formData.append(key, val);\n }\n });\n\n return formData;\n };\n\n qq.obj2Inputs = function(obj, form) {\n var input;\n\n if (!form) {\n form = document.createElement(\"form\");\n }\n\n qq.obj2FormData(obj, {\n append: function(key, val) {\n input = document.createElement(\"input\");\n input.setAttribute(\"name\", key);\n input.setAttribute(\"value\", val);\n form.appendChild(input);\n }\n });\n\n return form;\n };\n\n /**\n * Not recommended for use outside of Fine Uploader since this falls back to an unchecked eval if JSON.parse is not\n * implemented. For a more secure JSON.parse polyfill, use Douglas Crockford's json2.js.\n */\n qq.parseJson = function(json) {\n /*jshint evil: true*/\n if (window.JSON && qq.isFunction(JSON.parse)) {\n return JSON.parse(json);\n } else {\n return eval(\"(\" + json + \")\");\n }\n };\n\n /**\n * Retrieve the extension of a file, if it exists.\n *\n * @param filename\n * @returns {string || undefined}\n */\n qq.getExtension = function(filename) {\n var extIdx = filename.lastIndexOf(\".\") + 1;\n\n if (extIdx > 0) {\n return filename.substr(extIdx, filename.length - extIdx);\n }\n };\n\n qq.getFilename = function(blobOrFileInput) {\n /*jslint regexp: true*/\n\n if (qq.isInput(blobOrFileInput)) {\n // get input value and remove path to normalize\n return blobOrFileInput.value.replace(/.*(\\/|\\\\)/, \"\");\n }\n else if (qq.isFile(blobOrFileInput)) {\n if (blobOrFileInput.fileName !== null && blobOrFileInput.fileName !== undefined) {\n return blobOrFileInput.fileName;\n }\n }\n\n return blobOrFileInput.name;\n };\n\n /**\n * A generic module which supports object disposing in dispose() method.\n * */\n qq.DisposeSupport = function() {\n var disposers = [];\n\n return {\n /** Run all registered disposers */\n dispose: function() {\n var disposer;\n do {\n disposer = disposers.shift();\n if (disposer) {\n disposer();\n }\n }\n while (disposer);\n },\n\n /** Attach event handler and register de-attacher as a disposer */\n attach: function() {\n var args = arguments;\n /*jslint undef:true*/\n this.addDisposer(qq(args[0]).attach.apply(this, Array.prototype.slice.call(arguments, 1)));\n },\n\n /** Add disposer to the collection */\n addDisposer: function(disposeFunction) {\n disposers.push(disposeFunction);\n }\n };\n };\n}());\n","/* globals define, module, global, qq */\n(function() {\n \"use strict\";\n if (typeof define === \"function\" && define.amd) {\n define(function() {\n return qq;\n });\n }\n else if (typeof module !== \"undefined\" && module.exports) {\n module.exports = qq;\n }\n else {\n global.qq = qq;\n }\n}());\n","/* globals qq */\n/**\n * Fine Uploader top-level Error container. Inherits from `Error`.\n */\n(function() {\n \"use strict\";\n\n qq.Error = function(message) {\n this.message = \"[Fine Uploader \" + qq.version + \"] \" + message;\n };\n\n qq.Error.prototype = new Error();\n}());\n","/*global qq */\nqq.version = \"5.12.0\";\n","/* globals qq */\nqq.supportedFeatures = (function() {\n \"use strict\";\n\n var supportsUploading,\n supportsUploadingBlobs,\n supportsFileDrop,\n supportsAjaxFileUploading,\n supportsFolderDrop,\n supportsChunking,\n supportsResume,\n supportsUploadViaPaste,\n supportsUploadCors,\n supportsDeleteFileXdr,\n supportsDeleteFileCorsXhr,\n supportsDeleteFileCors,\n supportsFolderSelection,\n supportsImagePreviews,\n supportsUploadProgress;\n\n function testSupportsFileInputElement() {\n var supported = true,\n tempInput;\n\n try {\n tempInput = document.createElement(\"input\");\n tempInput.type = \"file\";\n qq(tempInput).hide();\n\n if (tempInput.disabled) {\n supported = false;\n }\n }\n catch (ex) {\n supported = false;\n }\n\n return supported;\n }\n\n //only way to test for Filesystem API support since webkit does not expose the DataTransfer interface\n function isChrome21OrHigher() {\n return (qq.chrome() || qq.opera()) &&\n navigator.userAgent.match(/Chrome\\/[2][1-9]|Chrome\\/[3-9][0-9]/) !== undefined;\n }\n\n //only way to test for complete Clipboard API support at this time\n function isChrome14OrHigher() {\n return (qq.chrome() || qq.opera()) &&\n navigator.userAgent.match(/Chrome\\/[1][4-9]|Chrome\\/[2-9][0-9]/) !== undefined;\n }\n\n //Ensure we can send cross-origin `XMLHttpRequest`s\n function isCrossOriginXhrSupported() {\n if (window.XMLHttpRequest) {\n var xhr = qq.createXhrInstance();\n\n //Commonly accepted test for XHR CORS support.\n return xhr.withCredentials !== undefined;\n }\n\n return false;\n }\n\n //Test for (terrible) cross-origin ajax transport fallback for IE9 and IE8\n function isXdrSupported() {\n return window.XDomainRequest !== undefined;\n }\n\n // CORS Ajax requests are supported if it is either possible to send credentialed `XMLHttpRequest`s,\n // or if `XDomainRequest` is an available alternative.\n function isCrossOriginAjaxSupported() {\n if (isCrossOriginXhrSupported()) {\n return true;\n }\n\n return isXdrSupported();\n }\n\n function isFolderSelectionSupported() {\n // We know that folder selection is only supported in Chrome via this proprietary attribute for now\n return document.createElement(\"input\").webkitdirectory !== undefined;\n }\n\n function isLocalStorageSupported() {\n try {\n return !!window.localStorage &&\n // unpatched versions of IE10/11 have buggy impls of localStorage where setItem is a string\n qq.isFunction(window.localStorage.setItem);\n }\n catch (error) {\n // probably caught a security exception, so no localStorage for you\n return false;\n }\n }\n\n function isDragAndDropSupported() {\n var span = document.createElement(\"span\");\n\n return (\"draggable\" in span || (\"ondragstart\" in span && \"ondrop\" in span)) &&\n !qq.android() && !qq.ios();\n }\n\n supportsUploading = testSupportsFileInputElement();\n\n supportsAjaxFileUploading = supportsUploading && qq.isXhrUploadSupported();\n\n supportsUploadingBlobs = supportsAjaxFileUploading && !qq.androidStock();\n\n supportsFileDrop = supportsAjaxFileUploading && isDragAndDropSupported();\n\n supportsFolderDrop = supportsFileDrop && isChrome21OrHigher();\n\n supportsChunking = supportsAjaxFileUploading && qq.isFileChunkingSupported();\n\n supportsResume = supportsAjaxFileUploading && supportsChunking && isLocalStorageSupported();\n\n supportsUploadViaPaste = supportsAjaxFileUploading && isChrome14OrHigher();\n\n supportsUploadCors = supportsUploading && (window.postMessage !== undefined || supportsAjaxFileUploading);\n\n supportsDeleteFileCorsXhr = isCrossOriginXhrSupported();\n\n supportsDeleteFileXdr = isXdrSupported();\n\n supportsDeleteFileCors = isCrossOriginAjaxSupported();\n\n supportsFolderSelection = isFolderSelectionSupported();\n\n supportsImagePreviews = supportsAjaxFileUploading && window.FileReader !== undefined;\n\n supportsUploadProgress = (function() {\n if (supportsAjaxFileUploading) {\n return !qq.androidStock() && !qq.iosChrome();\n }\n return false;\n }());\n\n return {\n ajaxUploading: supportsAjaxFileUploading,\n blobUploading: supportsUploadingBlobs,\n canDetermineSize: supportsAjaxFileUploading,\n chunking: supportsChunking,\n deleteFileCors: supportsDeleteFileCors,\n deleteFileCorsXdr: supportsDeleteFileXdr, //NOTE: will also return true in IE10, where XDR is also supported\n deleteFileCorsXhr: supportsDeleteFileCorsXhr,\n dialogElement: !!window.HTMLDialogElement,\n fileDrop: supportsFileDrop,\n folderDrop: supportsFolderDrop,\n folderSelection: supportsFolderSelection,\n imagePreviews: supportsImagePreviews,\n imageValidation: supportsImagePreviews,\n itemSizeValidation: supportsAjaxFileUploading,\n pause: supportsChunking,\n progressBar: supportsUploadProgress,\n resume: supportsResume,\n scaling: supportsImagePreviews && supportsUploadingBlobs,\n tiffPreviews: qq.safari(), // Not the best solution, but simple and probably accurate enough (for now)\n unlimitedScaledImageSize: !qq.ios(), // false simply indicates that there is some known limit\n uploading: supportsUploading,\n uploadCors: supportsUploadCors,\n uploadCustomHeaders: supportsAjaxFileUploading,\n uploadNonMultipart: supportsAjaxFileUploading,\n uploadViaPaste: supportsUploadViaPaste\n };\n\n}());\n","/*globals qq*/\n\n// Is the passed object a promise instance?\nqq.isGenericPromise = function(maybePromise) {\n \"use strict\";\n return !!(maybePromise && maybePromise.then && qq.isFunction(maybePromise.then));\n};\n\nqq.Promise = function() {\n \"use strict\";\n\n var successArgs, failureArgs,\n successCallbacks = [],\n failureCallbacks = [],\n doneCallbacks = [],\n state = 0;\n\n qq.extend(this, {\n then: function(onSuccess, onFailure) {\n if (state === 0) {\n if (onSuccess) {\n successCallbacks.push(onSuccess);\n }\n if (onFailure) {\n failureCallbacks.push(onFailure);\n }\n }\n else if (state === -1) {\n onFailure && onFailure.apply(null, failureArgs);\n }\n else if (onSuccess) {\n onSuccess.apply(null, successArgs);\n }\n\n return this;\n },\n\n done: function(callback) {\n if (state === 0) {\n doneCallbacks.push(callback);\n }\n else {\n callback.apply(null, failureArgs === undefined ? successArgs : failureArgs);\n }\n\n return this;\n },\n\n success: function() {\n state = 1;\n successArgs = arguments;\n\n if (successCallbacks.length) {\n qq.each(successCallbacks, function(idx, callback) {\n callback.apply(null, successArgs);\n });\n }\n\n if (doneCallbacks.length) {\n qq.each(doneCallbacks, function(idx, callback) {\n callback.apply(null, successArgs);\n });\n }\n\n return this;\n },\n\n failure: function() {\n state = -1;\n failureArgs = arguments;\n\n if (failureCallbacks.length) {\n qq.each(failureCallbacks, function(idx, callback) {\n callback.apply(null, failureArgs);\n });\n }\n\n if (doneCallbacks.length) {\n qq.each(doneCallbacks, function(idx, callback) {\n callback.apply(null, failureArgs);\n });\n }\n\n return this;\n }\n });\n};\n","/* globals qq */\n/**\n * Placeholder for a Blob that will be generated on-demand.\n *\n * @param referenceBlob Parent of the generated blob\n * @param onCreate Function to invoke when the blob must be created. Must be promissory.\n * @constructor\n */\nqq.BlobProxy = function(referenceBlob, onCreate) {\n \"use strict\";\n\n qq.extend(this, {\n referenceBlob: referenceBlob,\n\n create: function() {\n return onCreate(referenceBlob);\n }\n });\n};\n","/*globals qq*/\n\n/**\n * This module represents an upload or \"Select File(s)\" button. It's job is to embed an opaque ` `\n * element as a child of a provided \"container\" element. This \"container\" element (`options.element`) is used to provide\n * a custom style for the ` ` element. The ability to change the style of the container element is also\n * provided here by adding CSS classes to the container on hover/focus.\n *\n * TODO Eliminate the mouseover and mouseout event handlers since the :hover CSS pseudo-class should now be\n * available on all supported browsers.\n *\n * @param o Options to override the default values\n */\nqq.UploadButton = function(o) {\n \"use strict\";\n\n var self = this,\n\n disposeSupport = new qq.DisposeSupport(),\n\n options = {\n // Corresponds to the `accept` attribute on the associated ` `\n acceptFiles: null,\n\n // \"Container\" element\n element: null,\n\n focusClass: \"qq-upload-button-focus\",\n\n // A true value allows folders to be selected, if supported by the UA\n folders: false,\n\n // **This option will be removed** in the future as the :hover CSS pseudo-class is available on all supported browsers\n hoverClass: \"qq-upload-button-hover\",\n\n ios8BrowserCrashWorkaround: false,\n\n // If true adds `multiple` attribute to ` `\n multiple: false,\n\n // `name` attribute of ` `\n name: \"qqfile\",\n\n // Called when the browser invokes the onchange handler on the ` `\n onChange: function(input) {},\n\n title: null\n },\n input, buttonId;\n\n // Overrides any of the default option values with any option values passed in during construction.\n qq.extend(options, o);\n\n buttonId = qq.getUniqueId();\n\n // Embed an opaque ` ` element as a child of `options.element`.\n function createInput() {\n var input = document.createElement(\"input\");\n\n input.setAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME, buttonId);\n input.setAttribute(\"title\", options.title);\n\n self.setMultiple(options.multiple, input);\n\n if (options.folders && qq.supportedFeatures.folderSelection) {\n // selecting directories is only possible in Chrome now, via a vendor-specific prefixed attribute\n input.setAttribute(\"webkitdirectory\", \"\");\n }\n\n if (options.acceptFiles) {\n input.setAttribute(\"accept\", options.acceptFiles);\n }\n\n input.setAttribute(\"type\", \"file\");\n input.setAttribute(\"name\", options.name);\n\n qq(input).css({\n position: \"absolute\",\n // in Opera only 'browse' button\n // is clickable and it is located at\n // the right side of the input\n right: 0,\n top: 0,\n fontFamily: \"Arial\",\n // It's especially important to make this an arbitrarily large value\n // to ensure the rendered input button in IE takes up the entire\n // space of the container element. Otherwise, the left side of the\n // button will require a double-click to invoke the file chooser.\n // In other browsers, this might cause other issues, so a large font-size\n // is only used in IE. There is a bug in IE8 where the opacity style is ignored\n // in some cases when the font-size is large. So, this workaround is not applied\n // to IE8.\n fontSize: qq.ie() && !qq.ie8() ? \"3500px\" : \"118px\",\n margin: 0,\n padding: 0,\n cursor: \"pointer\",\n opacity: 0\n });\n\n // Setting the file input's height to 100% in IE7 causes\n // most of the visible button to be unclickable.\n !qq.ie7() && qq(input).css({height: \"100%\"});\n\n options.element.appendChild(input);\n\n disposeSupport.attach(input, \"change\", function() {\n options.onChange(input);\n });\n\n // **These event handlers will be removed** in the future as the :hover CSS pseudo-class is available on all supported browsers\n disposeSupport.attach(input, \"mouseover\", function() {\n qq(options.element).addClass(options.hoverClass);\n });\n disposeSupport.attach(input, \"mouseout\", function() {\n qq(options.element).removeClass(options.hoverClass);\n });\n\n disposeSupport.attach(input, \"focus\", function() {\n qq(options.element).addClass(options.focusClass);\n });\n disposeSupport.attach(input, \"blur\", function() {\n qq(options.element).removeClass(options.focusClass);\n });\n\n return input;\n }\n\n // Make button suitable container for input\n qq(options.element).css({\n position: \"relative\",\n overflow: \"hidden\",\n // Make sure browse button is in the right side in Internet Explorer\n direction: \"ltr\"\n });\n\n // Exposed API\n qq.extend(this, {\n getInput: function() {\n return input;\n },\n\n getButtonId: function() {\n return buttonId;\n },\n\n setMultiple: function(isMultiple, optInput) {\n var input = optInput || this.getInput();\n\n // Temporary workaround for bug in in iOS8 UIWebView that causes the browser to crash\n // before the file chooser appears if the file input doesn't contain a multiple attribute.\n // See #1283.\n if (options.ios8BrowserCrashWorkaround && qq.ios8() && (qq.iosChrome() || qq.iosSafariWebView())) {\n input.setAttribute(\"multiple\", \"\");\n }\n\n else {\n if (isMultiple) {\n input.setAttribute(\"multiple\", \"\");\n }\n else {\n input.removeAttribute(\"multiple\");\n }\n }\n },\n\n setAcceptFiles: function(acceptFiles) {\n if (acceptFiles !== options.acceptFiles) {\n input.setAttribute(\"accept\", acceptFiles);\n }\n },\n\n reset: function() {\n if (input.parentNode) {\n qq(input).remove();\n }\n\n qq(options.element).removeClass(options.focusClass);\n input = null;\n input = createInput();\n }\n });\n\n input = createInput();\n};\n\nqq.UploadButton.BUTTON_ID_ATTR_NAME = \"qq-button-id\";\n","/*globals qq */\nqq.UploadData = function(uploaderProxy) {\n \"use strict\";\n\n var data = [],\n byUuid = {},\n byStatus = {},\n byProxyGroupId = {},\n byBatchId = {};\n\n function getDataByIds(idOrIds) {\n if (qq.isArray(idOrIds)) {\n var entries = [];\n\n qq.each(idOrIds, function(idx, id) {\n entries.push(data[id]);\n });\n\n return entries;\n }\n\n return data[idOrIds];\n }\n\n function getDataByUuids(uuids) {\n if (qq.isArray(uuids)) {\n var entries = [];\n\n qq.each(uuids, function(idx, uuid) {\n entries.push(data[byUuid[uuid]]);\n });\n\n return entries;\n }\n\n return data[byUuid[uuids]];\n }\n\n function getDataByStatus(status) {\n var statusResults = [],\n statuses = [].concat(status);\n\n qq.each(statuses, function(index, statusEnum) {\n var statusResultIndexes = byStatus[statusEnum];\n\n if (statusResultIndexes !== undefined) {\n qq.each(statusResultIndexes, function(i, dataIndex) {\n statusResults.push(data[dataIndex]);\n });\n }\n });\n\n return statusResults;\n }\n\n qq.extend(this, {\n /**\n * Adds a new file to the data cache for tracking purposes.\n *\n * @param spec Data that describes this file. Possible properties are:\n *\n * - uuid: Initial UUID for this file.\n * - name: Initial name of this file.\n * - size: Size of this file, omit if this cannot be determined\n * - status: Initial `qq.status` for this file. Omit for `qq.status.SUBMITTING`.\n * - batchId: ID of the batch this file belongs to\n * - proxyGroupId: ID of the proxy group associated with this file\n *\n * @returns {number} Internal ID for this file.\n */\n addFile: function(spec) {\n var status = spec.status || qq.status.SUBMITTING,\n id = data.push({\n name: spec.name,\n originalName: spec.name,\n uuid: spec.uuid,\n size: spec.size == null ? -1 : spec.size,\n status: status\n }) - 1;\n\n if (spec.batchId) {\n data[id].batchId = spec.batchId;\n\n if (byBatchId[spec.batchId] === undefined) {\n byBatchId[spec.batchId] = [];\n }\n byBatchId[spec.batchId].push(id);\n }\n\n if (spec.proxyGroupId) {\n data[id].proxyGroupId = spec.proxyGroupId;\n\n if (byProxyGroupId[spec.proxyGroupId] === undefined) {\n byProxyGroupId[spec.proxyGroupId] = [];\n }\n byProxyGroupId[spec.proxyGroupId].push(id);\n }\n\n data[id].id = id;\n byUuid[spec.uuid] = id;\n\n if (byStatus[status] === undefined) {\n byStatus[status] = [];\n }\n byStatus[status].push(id);\n\n uploaderProxy.onStatusChange(id, null, status);\n\n return id;\n },\n\n retrieve: function(optionalFilter) {\n if (qq.isObject(optionalFilter) && data.length) {\n if (optionalFilter.id !== undefined) {\n return getDataByIds(optionalFilter.id);\n }\n\n else if (optionalFilter.uuid !== undefined) {\n return getDataByUuids(optionalFilter.uuid);\n }\n\n else if (optionalFilter.status) {\n return getDataByStatus(optionalFilter.status);\n }\n }\n else {\n return qq.extend([], data, true);\n }\n },\n\n reset: function() {\n data = [];\n byUuid = {};\n byStatus = {};\n byBatchId = {};\n },\n\n setStatus: function(id, newStatus) {\n var oldStatus = data[id].status,\n byStatusOldStatusIndex = qq.indexOf(byStatus[oldStatus], id);\n\n byStatus[oldStatus].splice(byStatusOldStatusIndex, 1);\n\n data[id].status = newStatus;\n\n if (byStatus[newStatus] === undefined) {\n byStatus[newStatus] = [];\n }\n byStatus[newStatus].push(id);\n\n uploaderProxy.onStatusChange(id, oldStatus, newStatus);\n },\n\n uuidChanged: function(id, newUuid) {\n var oldUuid = data[id].uuid;\n\n data[id].uuid = newUuid;\n byUuid[newUuid] = id;\n delete byUuid[oldUuid];\n },\n\n updateName: function(id, newName) {\n data[id].name = newName;\n },\n\n updateSize: function(id, newSize) {\n data[id].size = newSize;\n },\n\n // Only applicable if this file has a parent that we may want to reference later.\n setParentId: function(targetId, parentId) {\n data[targetId].parentId = parentId;\n },\n\n getIdsInProxyGroup: function(id) {\n var proxyGroupId = data[id].proxyGroupId;\n\n if (proxyGroupId) {\n return byProxyGroupId[proxyGroupId];\n }\n return [];\n },\n\n getIdsInBatch: function(id) {\n var batchId = data[id].batchId;\n\n return byBatchId[batchId];\n }\n });\n};\n\nqq.status = {\n SUBMITTING: \"submitting\",\n SUBMITTED: \"submitted\",\n REJECTED: \"rejected\",\n QUEUED: \"queued\",\n CANCELED: \"canceled\",\n PAUSED: \"paused\",\n UPLOADING: \"uploading\",\n UPLOAD_RETRYING: \"retrying upload\",\n UPLOAD_SUCCESSFUL: \"upload successful\",\n UPLOAD_FAILED: \"upload failed\",\n DELETE_FAILED: \"delete failed\",\n DELETING: \"deleting\",\n DELETED: \"deleted\"\n};\n","/*globals qq*/\n/**\n * Defines the public API for FineUploaderBasic mode.\n */\n(function() {\n \"use strict\";\n\n qq.basePublicApi = {\n // DEPRECATED - TODO REMOVE IN NEXT MAJOR RELEASE (replaced by addFiles)\n addBlobs: function(blobDataOrArray, params, endpoint) {\n this.addFiles(blobDataOrArray, params, endpoint);\n },\n\n addInitialFiles: function(cannedFileList) {\n var self = this;\n\n qq.each(cannedFileList, function(index, cannedFile) {\n self._addCannedFile(cannedFile);\n });\n },\n\n addFiles: function(data, params, endpoint) {\n this._maybeHandleIos8SafariWorkaround();\n\n var batchId = this._storedIds.length === 0 ? qq.getUniqueId() : this._currentBatchId,\n\n processBlob = qq.bind(function(blob) {\n this._handleNewFile({\n blob: blob,\n name: this._options.blobs.defaultName\n }, batchId, verifiedFiles);\n }, this),\n\n processBlobData = qq.bind(function(blobData) {\n this._handleNewFile(blobData, batchId, verifiedFiles);\n }, this),\n\n processCanvas = qq.bind(function(canvas) {\n var blob = qq.canvasToBlob(canvas);\n\n this._handleNewFile({\n blob: blob,\n name: this._options.blobs.defaultName + \".png\"\n }, batchId, verifiedFiles);\n }, this),\n\n processCanvasData = qq.bind(function(canvasData) {\n var normalizedQuality = canvasData.quality && canvasData.quality / 100,\n blob = qq.canvasToBlob(canvasData.canvas, canvasData.type, normalizedQuality);\n\n this._handleNewFile({\n blob: blob,\n name: canvasData.name\n }, batchId, verifiedFiles);\n }, this),\n\n processFileOrInput = qq.bind(function(fileOrInput) {\n if (qq.isInput(fileOrInput) && qq.supportedFeatures.ajaxUploading) {\n var files = Array.prototype.slice.call(fileOrInput.files),\n self = this;\n\n qq.each(files, function(idx, file) {\n self._handleNewFile(file, batchId, verifiedFiles);\n });\n }\n else {\n this._handleNewFile(fileOrInput, batchId, verifiedFiles);\n }\n }, this),\n\n normalizeData = function() {\n if (qq.isFileList(data)) {\n data = Array.prototype.slice.call(data);\n }\n data = [].concat(data);\n },\n\n self = this,\n verifiedFiles = [];\n\n this._currentBatchId = batchId;\n\n if (data) {\n normalizeData();\n\n qq.each(data, function(idx, fileContainer) {\n if (qq.isFileOrInput(fileContainer)) {\n processFileOrInput(fileContainer);\n }\n else if (qq.isBlob(fileContainer)) {\n processBlob(fileContainer);\n }\n else if (qq.isObject(fileContainer)) {\n if (fileContainer.blob && fileContainer.name) {\n processBlobData(fileContainer);\n }\n else if (fileContainer.canvas && fileContainer.name) {\n processCanvasData(fileContainer);\n }\n }\n else if (fileContainer.tagName && fileContainer.tagName.toLowerCase() === \"canvas\") {\n processCanvas(fileContainer);\n }\n else {\n self.log(fileContainer + \" is not a valid file container! Ignoring!\", \"warn\");\n }\n });\n\n this.log(\"Received \" + verifiedFiles.length + \" files.\");\n this._prepareItemsForUpload(verifiedFiles, params, endpoint);\n }\n },\n\n cancel: function(id) {\n this._handler.cancel(id);\n },\n\n cancelAll: function() {\n var storedIdsCopy = [],\n self = this;\n\n qq.extend(storedIdsCopy, this._storedIds);\n qq.each(storedIdsCopy, function(idx, storedFileId) {\n self.cancel(storedFileId);\n });\n\n this._handler.cancelAll();\n },\n\n clearStoredFiles: function() {\n this._storedIds = [];\n },\n\n continueUpload: function(id) {\n var uploadData = this._uploadData.retrieve({id: id});\n\n if (!qq.supportedFeatures.pause || !this._options.chunking.enabled) {\n return false;\n }\n\n if (uploadData.status === qq.status.PAUSED) {\n this.log(qq.format(\"Paused file ID {} ({}) will be continued. Not paused.\", id, this.getName(id)));\n this._uploadFile(id);\n return true;\n }\n else {\n this.log(qq.format(\"Ignoring continue for file ID {} ({}). Not paused.\", id, this.getName(id)), \"error\");\n }\n\n return false;\n },\n\n deleteFile: function(id) {\n return this._onSubmitDelete(id);\n },\n\n // TODO document?\n doesExist: function(fileOrBlobId) {\n return this._handler.isValid(fileOrBlobId);\n },\n\n // Generate a variable size thumbnail on an img or canvas,\n // returning a promise that is fulfilled when the attempt completes.\n // Thumbnail can either be based off of a URL for an image returned\n // by the server in the upload response, or the associated `Blob`.\n drawThumbnail: function(fileId, imgOrCanvas, maxSize, fromServer, customResizeFunction) {\n var promiseToReturn = new qq.Promise(),\n fileOrUrl, options;\n\n if (this._imageGenerator) {\n fileOrUrl = this._thumbnailUrls[fileId];\n options = {\n customResizeFunction: customResizeFunction,\n maxSize: maxSize > 0 ? maxSize : null,\n scale: maxSize > 0\n };\n\n // If client-side preview generation is possible\n // and we are not specifically looking for the image URl returned by the server...\n if (!fromServer && qq.supportedFeatures.imagePreviews) {\n fileOrUrl = this.getFile(fileId);\n }\n\n /* jshint eqeqeq:false,eqnull:true */\n if (fileOrUrl == null) {\n promiseToReturn.failure({container: imgOrCanvas, error: \"File or URL not found.\"});\n }\n else {\n this._imageGenerator.generate(fileOrUrl, imgOrCanvas, options).then(\n function success(modifiedContainer) {\n promiseToReturn.success(modifiedContainer);\n },\n\n function failure(container, reason) {\n promiseToReturn.failure({container: container, error: reason || \"Problem generating thumbnail\"});\n }\n );\n }\n }\n else {\n promiseToReturn.failure({container: imgOrCanvas, error: \"Missing image generator module\"});\n }\n\n return promiseToReturn;\n },\n\n getButton: function(fileId) {\n return this._getButton(this._buttonIdsForFileIds[fileId]);\n },\n\n getEndpoint: function(fileId) {\n return this._endpointStore.get(fileId);\n },\n\n getFile: function(fileOrBlobId) {\n return this._handler.getFile(fileOrBlobId) || null;\n },\n\n getInProgress: function() {\n return this._uploadData.retrieve({\n status: [\n qq.status.UPLOADING,\n qq.status.UPLOAD_RETRYING,\n qq.status.QUEUED\n ]\n }).length;\n },\n\n getName: function(id) {\n return this._uploadData.retrieve({id: id}).name;\n },\n\n // Parent ID for a specific file, or null if this is the parent, or if it has no parent.\n getParentId: function(id) {\n var uploadDataEntry = this.getUploads({id: id}),\n parentId = null;\n\n if (uploadDataEntry) {\n if (uploadDataEntry.parentId !== undefined) {\n parentId = uploadDataEntry.parentId;\n }\n }\n\n return parentId;\n },\n\n getResumableFilesData: function() {\n return this._handler.getResumableFilesData();\n },\n\n getSize: function(id) {\n return this._uploadData.retrieve({id: id}).size;\n },\n\n getNetUploads: function() {\n return this._netUploaded;\n },\n\n getRemainingAllowedItems: function() {\n var allowedItems = this._currentItemLimit;\n\n if (allowedItems > 0) {\n return allowedItems - this._netUploadedOrQueued;\n }\n\n return null;\n },\n\n getUploads: function(optionalFilter) {\n return this._uploadData.retrieve(optionalFilter);\n },\n\n getUuid: function(id) {\n return this._uploadData.retrieve({id: id}).uuid;\n },\n\n log: function(str, level) {\n if (this._options.debug && (!level || level === \"info\")) {\n qq.log(\"[Fine Uploader \" + qq.version + \"] \" + str);\n }\n else if (level && level !== \"info\") {\n qq.log(\"[Fine Uploader \" + qq.version + \"] \" + str, level);\n\n }\n },\n\n pauseUpload: function(id) {\n var uploadData = this._uploadData.retrieve({id: id});\n\n if (!qq.supportedFeatures.pause || !this._options.chunking.enabled) {\n return false;\n }\n\n // Pause only really makes sense if the file is uploading or retrying\n if (qq.indexOf([qq.status.UPLOADING, qq.status.UPLOAD_RETRYING], uploadData.status) >= 0) {\n if (this._handler.pause(id)) {\n this._uploadData.setStatus(id, qq.status.PAUSED);\n return true;\n }\n else {\n this.log(qq.format(\"Unable to pause file ID {} ({}).\", id, this.getName(id)), \"error\");\n }\n }\n else {\n this.log(qq.format(\"Ignoring pause for file ID {} ({}). Not in progress.\", id, this.getName(id)), \"error\");\n }\n\n return false;\n },\n\n reset: function() {\n this.log(\"Resetting uploader...\");\n\n this._handler.reset();\n this._storedIds = [];\n this._autoRetries = [];\n this._retryTimeouts = [];\n this._preventRetries = [];\n this._thumbnailUrls = [];\n\n qq.each(this._buttons, function(idx, button) {\n button.reset();\n });\n\n this._paramsStore.reset();\n this._endpointStore.reset();\n this._netUploadedOrQueued = 0;\n this._netUploaded = 0;\n this._uploadData.reset();\n this._buttonIdsForFileIds = [];\n\n this._pasteHandler && this._pasteHandler.reset();\n this._options.session.refreshOnReset && this._refreshSessionData();\n\n this._succeededSinceLastAllComplete = [];\n this._failedSinceLastAllComplete = [];\n\n this._totalProgress && this._totalProgress.reset();\n },\n\n retry: function(id) {\n return this._manualRetry(id);\n },\n\n scaleImage: function(id, specs) {\n var self = this;\n\n return qq.Scaler.prototype.scaleImage(id, specs, {\n log: qq.bind(self.log, self),\n getFile: qq.bind(self.getFile, self),\n uploadData: self._uploadData\n });\n },\n\n setCustomHeaders: function(headers, id) {\n this._customHeadersStore.set(headers, id);\n },\n\n setDeleteFileCustomHeaders: function(headers, id) {\n this._deleteFileCustomHeadersStore.set(headers, id);\n },\n\n setDeleteFileEndpoint: function(endpoint, id) {\n this._deleteFileEndpointStore.set(endpoint, id);\n },\n\n setDeleteFileParams: function(params, id) {\n this._deleteFileParamsStore.set(params, id);\n },\n\n // Re-sets the default endpoint, an endpoint for a specific file, or an endpoint for a specific button\n setEndpoint: function(endpoint, id) {\n this._endpointStore.set(endpoint, id);\n },\n\n setForm: function(elementOrId) {\n this._updateFormSupportAndParams(elementOrId);\n },\n\n setItemLimit: function(newItemLimit) {\n this._currentItemLimit = newItemLimit;\n },\n\n setName: function(id, newName) {\n this._uploadData.updateName(id, newName);\n },\n\n setParams: function(params, id) {\n this._paramsStore.set(params, id);\n },\n\n setUuid: function(id, newUuid) {\n return this._uploadData.uuidChanged(id, newUuid);\n },\n\n uploadStoredFiles: function() {\n if (this._storedIds.length === 0) {\n this._itemError(\"noFilesError\");\n }\n else {\n this._uploadStoredFiles();\n }\n }\n };\n\n /**\n * Defines the private (internal) API for FineUploaderBasic mode.\n */\n qq.basePrivateApi = {\n // Updates internal state with a file record (not backed by a live file). Returns the assigned ID.\n _addCannedFile: function(sessionData) {\n var id = this._uploadData.addFile({\n uuid: sessionData.uuid,\n name: sessionData.name,\n size: sessionData.size,\n status: qq.status.UPLOAD_SUCCESSFUL\n });\n\n sessionData.deleteFileEndpoint && this.setDeleteFileEndpoint(sessionData.deleteFileEndpoint, id);\n sessionData.deleteFileParams && this.setDeleteFileParams(sessionData.deleteFileParams, id);\n\n if (sessionData.thumbnailUrl) {\n this._thumbnailUrls[id] = sessionData.thumbnailUrl;\n }\n\n this._netUploaded++;\n this._netUploadedOrQueued++;\n\n return id;\n },\n\n _annotateWithButtonId: function(file, associatedInput) {\n if (qq.isFile(file)) {\n file.qqButtonId = this._getButtonId(associatedInput);\n }\n },\n\n _batchError: function(message) {\n this._options.callbacks.onError(null, null, message, undefined);\n },\n\n _createDeleteHandler: function() {\n var self = this;\n\n return new qq.DeleteFileAjaxRequester({\n method: this._options.deleteFile.method.toUpperCase(),\n maxConnections: this._options.maxConnections,\n uuidParamName: this._options.request.uuidName,\n customHeaders: this._deleteFileCustomHeadersStore,\n paramsStore: this._deleteFileParamsStore,\n endpointStore: this._deleteFileEndpointStore,\n cors: this._options.cors,\n log: qq.bind(self.log, self),\n onDelete: function(id) {\n self._onDelete(id);\n self._options.callbacks.onDelete(id);\n },\n onDeleteComplete: function(id, xhrOrXdr, isError) {\n self._onDeleteComplete(id, xhrOrXdr, isError);\n self._options.callbacks.onDeleteComplete(id, xhrOrXdr, isError);\n }\n\n });\n },\n\n _createPasteHandler: function() {\n var self = this;\n\n return new qq.PasteSupport({\n targetElement: this._options.paste.targetElement,\n callbacks: {\n log: qq.bind(self.log, self),\n pasteReceived: function(blob) {\n self._handleCheckedCallback({\n name: \"onPasteReceived\",\n callback: qq.bind(self._options.callbacks.onPasteReceived, self, blob),\n onSuccess: qq.bind(self._handlePasteSuccess, self, blob),\n identifier: \"pasted image\"\n });\n }\n }\n });\n },\n\n _createStore: function(initialValue, _readOnlyValues_) {\n var store = {},\n catchall = initialValue,\n perIdReadOnlyValues = {},\n readOnlyValues = _readOnlyValues_,\n copy = function(orig) {\n if (qq.isObject(orig)) {\n return qq.extend({}, orig);\n }\n return orig;\n },\n getReadOnlyValues = function() {\n if (qq.isFunction(readOnlyValues)) {\n return readOnlyValues();\n }\n return readOnlyValues;\n },\n includeReadOnlyValues = function(id, existing) {\n if (readOnlyValues && qq.isObject(existing)) {\n qq.extend(existing, getReadOnlyValues());\n }\n\n if (perIdReadOnlyValues[id]) {\n qq.extend(existing, perIdReadOnlyValues[id]);\n }\n };\n\n return {\n set: function(val, id) {\n /*jshint eqeqeq: true, eqnull: true*/\n if (id == null) {\n store = {};\n catchall = copy(val);\n }\n else {\n store[id] = copy(val);\n }\n },\n\n get: function(id) {\n var values;\n\n /*jshint eqeqeq: true, eqnull: true*/\n if (id != null && store[id]) {\n values = store[id];\n }\n else {\n values = copy(catchall);\n }\n\n includeReadOnlyValues(id, values);\n\n return copy(values);\n },\n\n addReadOnly: function(id, values) {\n // Only applicable to Object stores\n if (qq.isObject(store)) {\n // If null ID, apply readonly values to all files\n if (id === null) {\n if (qq.isFunction(values)) {\n readOnlyValues = values;\n }\n else {\n readOnlyValues = readOnlyValues || {};\n qq.extend(readOnlyValues, values);\n }\n }\n else {\n perIdReadOnlyValues[id] = perIdReadOnlyValues[id] || {};\n qq.extend(perIdReadOnlyValues[id], values);\n }\n }\n },\n\n remove: function(fileId) {\n return delete store[fileId];\n },\n\n reset: function() {\n store = {};\n perIdReadOnlyValues = {};\n catchall = initialValue;\n }\n };\n },\n\n _createUploadDataTracker: function() {\n var self = this;\n\n return new qq.UploadData({\n getName: function(id) {\n return self.getName(id);\n },\n getUuid: function(id) {\n return self.getUuid(id);\n },\n getSize: function(id) {\n return self.getSize(id);\n },\n onStatusChange: function(id, oldStatus, newStatus) {\n self._onUploadStatusChange(id, oldStatus, newStatus);\n self._options.callbacks.onStatusChange(id, oldStatus, newStatus);\n self._maybeAllComplete(id, newStatus);\n\n if (self._totalProgress) {\n setTimeout(function() {\n self._totalProgress.onStatusChange(id, oldStatus, newStatus);\n }, 0);\n }\n }\n });\n },\n\n /**\n * Generate a tracked upload button.\n *\n * @param spec Object containing a required `element` property\n * along with optional `multiple`, `accept`, and `folders`.\n * @returns {qq.UploadButton}\n * @private\n */\n _createUploadButton: function(spec) {\n var self = this,\n acceptFiles = spec.accept || this._options.validation.acceptFiles,\n allowedExtensions = spec.allowedExtensions || this._options.validation.allowedExtensions,\n button;\n\n function allowMultiple() {\n if (qq.supportedFeatures.ajaxUploading) {\n // Workaround for bug in iOS7+ (see #1039)\n if (self._options.workarounds.iosEmptyVideos &&\n qq.ios() &&\n !qq.ios6() &&\n self._isAllowedExtension(allowedExtensions, \".mov\")) {\n\n return false;\n }\n\n if (spec.multiple === undefined) {\n return self._options.multiple;\n }\n\n return spec.multiple;\n }\n\n return false;\n }\n\n button = new qq.UploadButton({\n acceptFiles: acceptFiles,\n element: spec.element,\n focusClass: this._options.classes.buttonFocus,\n folders: spec.folders,\n hoverClass: this._options.classes.buttonHover,\n ios8BrowserCrashWorkaround: this._options.workarounds.ios8BrowserCrash,\n multiple: allowMultiple(),\n name: this._options.request.inputName,\n onChange: function(input) {\n self._onInputChange(input);\n },\n title: spec.title == null ? this._options.text.fileInputTitle : spec.title\n });\n\n this._disposeSupport.addDisposer(function() {\n button.dispose();\n });\n\n self._buttons.push(button);\n\n return button;\n },\n\n _createUploadHandler: function(additionalOptions, namespace) {\n var self = this,\n lastOnProgress = {},\n options = {\n debug: this._options.debug,\n maxConnections: this._options.maxConnections,\n cors: this._options.cors,\n paramsStore: this._paramsStore,\n endpointStore: this._endpointStore,\n chunking: this._options.chunking,\n resume: this._options.resume,\n blobs: this._options.blobs,\n log: qq.bind(self.log, self),\n preventRetryParam: this._options.retry.preventRetryResponseProperty,\n onProgress: function(id, name, loaded, total) {\n if (loaded < 0 || total < 0) {\n return;\n }\n\n if (lastOnProgress[id]) {\n if (lastOnProgress[id].loaded !== loaded || lastOnProgress[id].total !== total) {\n self._onProgress(id, name, loaded, total);\n self._options.callbacks.onProgress(id, name, loaded, total);\n }\n }\n else {\n self._onProgress(id, name, loaded, total);\n self._options.callbacks.onProgress(id, name, loaded, total);\n }\n\n lastOnProgress[id] = {loaded: loaded, total: total};\n\n },\n onComplete: function(id, name, result, xhr) {\n delete lastOnProgress[id];\n\n var status = self.getUploads({id: id}).status,\n retVal;\n\n // This is to deal with some observed cases where the XHR readyStateChange handler is\n // invoked by the browser multiple times for the same XHR instance with the same state\n // readyState value. Higher level: don't invoke complete-related code if we've already\n // done this.\n if (status === qq.status.UPLOAD_SUCCESSFUL || status === qq.status.UPLOAD_FAILED) {\n return;\n }\n\n retVal = self._onComplete(id, name, result, xhr);\n\n // If the internal `_onComplete` handler returns a promise, don't invoke the `onComplete` callback\n // until the promise has been fulfilled.\n if (retVal instanceof qq.Promise) {\n retVal.done(function() {\n self._options.callbacks.onComplete(id, name, result, xhr);\n });\n }\n else {\n self._options.callbacks.onComplete(id, name, result, xhr);\n }\n },\n onCancel: function(id, name, cancelFinalizationEffort) {\n var promise = new qq.Promise();\n\n self._handleCheckedCallback({\n name: \"onCancel\",\n callback: qq.bind(self._options.callbacks.onCancel, self, id, name),\n onFailure: promise.failure,\n onSuccess: function() {\n cancelFinalizationEffort.then(function() {\n self._onCancel(id, name);\n });\n\n promise.success();\n },\n identifier: id\n });\n\n return promise;\n },\n onUploadPrep: qq.bind(this._onUploadPrep, this),\n onUpload: function(id, name) {\n self._onUpload(id, name);\n self._options.callbacks.onUpload(id, name);\n },\n onUploadChunk: function(id, name, chunkData) {\n self._onUploadChunk(id, chunkData);\n self._options.callbacks.onUploadChunk(id, name, chunkData);\n },\n onUploadChunkSuccess: function(id, chunkData, result, xhr) {\n self._options.callbacks.onUploadChunkSuccess.apply(self, arguments);\n },\n onResume: function(id, name, chunkData) {\n return self._options.callbacks.onResume(id, name, chunkData);\n },\n onAutoRetry: function(id, name, responseJSON, xhr) {\n return self._onAutoRetry.apply(self, arguments);\n },\n onUuidChanged: function(id, newUuid) {\n self.log(\"Server requested UUID change from '\" + self.getUuid(id) + \"' to '\" + newUuid + \"'\");\n self.setUuid(id, newUuid);\n },\n getName: qq.bind(self.getName, self),\n getUuid: qq.bind(self.getUuid, self),\n getSize: qq.bind(self.getSize, self),\n setSize: qq.bind(self._setSize, self),\n getDataByUuid: function(uuid) {\n return self.getUploads({uuid: uuid});\n },\n isQueued: function(id) {\n var status = self.getUploads({id: id}).status;\n return status === qq.status.QUEUED ||\n status === qq.status.SUBMITTED ||\n status === qq.status.UPLOAD_RETRYING ||\n status === qq.status.PAUSED;\n },\n getIdsInProxyGroup: self._uploadData.getIdsInProxyGroup,\n getIdsInBatch: self._uploadData.getIdsInBatch\n };\n\n qq.each(this._options.request, function(prop, val) {\n options[prop] = val;\n });\n\n options.customHeaders = this._customHeadersStore;\n\n if (additionalOptions) {\n qq.each(additionalOptions, function(key, val) {\n options[key] = val;\n });\n }\n\n return new qq.UploadHandlerController(options, namespace);\n },\n\n _fileOrBlobRejected: function(id) {\n this._netUploadedOrQueued--;\n this._uploadData.setStatus(id, qq.status.REJECTED);\n },\n\n _formatSize: function(bytes) {\n if (bytes === 0) {\n return bytes + this._options.text.sizeSymbols[0];\n }\n var i = -1;\n do {\n bytes = bytes / 1000;\n i++;\n } while (bytes > 999);\n\n return Math.max(bytes, 0.1).toFixed(1) + this._options.text.sizeSymbols[i];\n },\n\n // Creates an internal object that tracks various properties of each extra button,\n // and then actually creates the extra button.\n _generateExtraButtonSpecs: function() {\n var self = this;\n\n this._extraButtonSpecs = {};\n\n qq.each(this._options.extraButtons, function(idx, extraButtonOptionEntry) {\n var multiple = extraButtonOptionEntry.multiple,\n validation = qq.extend({}, self._options.validation, true),\n extraButtonSpec = qq.extend({}, extraButtonOptionEntry);\n\n if (multiple === undefined) {\n multiple = self._options.multiple;\n }\n\n if (extraButtonSpec.validation) {\n qq.extend(validation, extraButtonOptionEntry.validation, true);\n }\n\n qq.extend(extraButtonSpec, {\n multiple: multiple,\n validation: validation\n }, true);\n\n self._initExtraButton(extraButtonSpec);\n });\n },\n\n _getButton: function(buttonId) {\n var extraButtonsSpec = this._extraButtonSpecs[buttonId];\n\n if (extraButtonsSpec) {\n return extraButtonsSpec.element;\n }\n else if (buttonId === this._defaultButtonId) {\n return this._options.button;\n }\n },\n\n /**\n * Gets the internally used tracking ID for a button.\n *\n * @param buttonOrFileInputOrFile `File`, ` `, or a button container element\n * @returns {*} The button's ID, or undefined if no ID is recoverable\n * @private\n */\n _getButtonId: function(buttonOrFileInputOrFile) {\n var inputs, fileInput,\n fileBlobOrInput = buttonOrFileInputOrFile;\n\n // We want the reference file/blob here if this is a proxy (a file that will be generated on-demand later)\n if (fileBlobOrInput instanceof qq.BlobProxy) {\n fileBlobOrInput = fileBlobOrInput.referenceBlob;\n }\n\n // If the item is a `Blob` it will never be associated with a button or drop zone.\n if (fileBlobOrInput && !qq.isBlob(fileBlobOrInput)) {\n if (qq.isFile(fileBlobOrInput)) {\n return fileBlobOrInput.qqButtonId;\n }\n else if (fileBlobOrInput.tagName.toLowerCase() === \"input\" &&\n fileBlobOrInput.type.toLowerCase() === \"file\") {\n\n return fileBlobOrInput.getAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME);\n }\n\n inputs = fileBlobOrInput.getElementsByTagName(\"input\");\n\n qq.each(inputs, function(idx, input) {\n if (input.getAttribute(\"type\") === \"file\") {\n fileInput = input;\n return false;\n }\n });\n\n if (fileInput) {\n return fileInput.getAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME);\n }\n }\n },\n\n _getNotFinished: function() {\n return this._uploadData.retrieve({\n status: [\n qq.status.UPLOADING,\n qq.status.UPLOAD_RETRYING,\n qq.status.QUEUED,\n qq.status.SUBMITTING,\n qq.status.SUBMITTED,\n qq.status.PAUSED\n ]\n }).length;\n },\n\n // Get the validation options for this button. Could be the default validation option\n // or a specific one assigned to this particular button.\n _getValidationBase: function(buttonId) {\n var extraButtonSpec = this._extraButtonSpecs[buttonId];\n\n return extraButtonSpec ? extraButtonSpec.validation : this._options.validation;\n },\n\n _getValidationDescriptor: function(fileWrapper) {\n if (fileWrapper.file instanceof qq.BlobProxy) {\n return {\n name: qq.getFilename(fileWrapper.file.referenceBlob),\n size: fileWrapper.file.referenceBlob.size\n };\n }\n\n return {\n name: this.getUploads({id: fileWrapper.id}).name,\n size: this.getUploads({id: fileWrapper.id}).size\n };\n },\n\n _getValidationDescriptors: function(fileWrappers) {\n var self = this,\n fileDescriptors = [];\n\n qq.each(fileWrappers, function(idx, fileWrapper) {\n fileDescriptors.push(self._getValidationDescriptor(fileWrapper));\n });\n\n return fileDescriptors;\n },\n\n // Allows camera access on either the default or an extra button for iOS devices.\n _handleCameraAccess: function() {\n if (this._options.camera.ios && qq.ios()) {\n var acceptIosCamera = \"image/*;capture=camera\",\n button = this._options.camera.button,\n buttonId = button ? this._getButtonId(button) : this._defaultButtonId,\n optionRoot = this._options;\n\n // If we are not targeting the default button, it is an \"extra\" button\n if (buttonId && buttonId !== this._defaultButtonId) {\n optionRoot = this._extraButtonSpecs[buttonId];\n }\n\n // Camera access won't work in iOS if the `multiple` attribute is present on the file input\n optionRoot.multiple = false;\n\n // update the options\n if (optionRoot.validation.acceptFiles === null) {\n optionRoot.validation.acceptFiles = acceptIosCamera;\n }\n else {\n optionRoot.validation.acceptFiles += \",\" + acceptIosCamera;\n }\n\n // update the already-created button\n qq.each(this._buttons, function(idx, button) {\n if (button.getButtonId() === buttonId) {\n button.setMultiple(optionRoot.multiple);\n button.setAcceptFiles(optionRoot.acceptFiles);\n\n return false;\n }\n });\n }\n },\n\n _handleCheckedCallback: function(details) {\n var self = this,\n callbackRetVal = details.callback();\n\n if (qq.isGenericPromise(callbackRetVal)) {\n this.log(details.name + \" - waiting for \" + details.name + \" promise to be fulfilled for \" + details.identifier);\n return callbackRetVal.then(\n function(successParam) {\n self.log(details.name + \" promise success for \" + details.identifier);\n details.onSuccess(successParam);\n },\n function() {\n if (details.onFailure) {\n self.log(details.name + \" promise failure for \" + details.identifier);\n details.onFailure();\n }\n else {\n self.log(details.name + \" promise failure for \" + details.identifier);\n }\n });\n }\n\n if (callbackRetVal !== false) {\n details.onSuccess(callbackRetVal);\n }\n else {\n if (details.onFailure) {\n this.log(details.name + \" - return value was 'false' for \" + details.identifier + \". Invoking failure callback.\");\n details.onFailure();\n }\n else {\n this.log(details.name + \" - return value was 'false' for \" + details.identifier + \". Will not proceed.\");\n }\n }\n\n return callbackRetVal;\n },\n\n // Updates internal state when a new file has been received, and adds it along with its ID to a passed array.\n _handleNewFile: function(file, batchId, newFileWrapperList) {\n var self = this,\n uuid = qq.getUniqueId(),\n size = -1,\n name = qq.getFilename(file),\n actualFile = file.blob || file,\n handler = this._customNewFileHandler ?\n this._customNewFileHandler :\n qq.bind(self._handleNewFileGeneric, self);\n\n if (!qq.isInput(actualFile) && actualFile.size >= 0) {\n size = actualFile.size;\n }\n\n handler(actualFile, name, uuid, size, newFileWrapperList, batchId, this._options.request.uuidName, {\n uploadData: self._uploadData,\n paramsStore: self._paramsStore,\n addFileToHandler: function(id, file) {\n self._handler.add(id, file);\n self._netUploadedOrQueued++;\n self._trackButton(id);\n }\n });\n },\n\n _handleNewFileGeneric: function(file, name, uuid, size, fileList, batchId) {\n var id = this._uploadData.addFile({uuid: uuid, name: name, size: size, batchId: batchId});\n\n this._handler.add(id, file);\n this._trackButton(id);\n\n this._netUploadedOrQueued++;\n\n fileList.push({id: id, file: file});\n },\n\n _handlePasteSuccess: function(blob, extSuppliedName) {\n var extension = blob.type.split(\"/\")[1],\n name = extSuppliedName;\n\n /*jshint eqeqeq: true, eqnull: true*/\n if (name == null) {\n name = this._options.paste.defaultName;\n }\n\n name += \".\" + extension;\n\n this.addFiles({\n name: name,\n blob: blob\n });\n },\n\n // Creates an extra button element\n _initExtraButton: function(spec) {\n var button = this._createUploadButton({\n accept: spec.validation.acceptFiles,\n allowedExtensions: spec.validation.allowedExtensions,\n element: spec.element,\n folders: spec.folders,\n multiple: spec.multiple,\n title: spec.fileInputTitle\n });\n\n this._extraButtonSpecs[button.getButtonId()] = spec;\n },\n\n _initFormSupportAndParams: function() {\n this._formSupport = qq.FormSupport && new qq.FormSupport(\n this._options.form, qq.bind(this.uploadStoredFiles, this), qq.bind(this.log, this)\n );\n\n if (this._formSupport && this._formSupport.attachedToForm) {\n this._paramsStore = this._createStore(\n this._options.request.params, this._formSupport.getFormInputsAsObject\n );\n\n this._options.autoUpload = this._formSupport.newAutoUpload;\n if (this._formSupport.newEndpoint) {\n this._options.request.endpoint = this._formSupport.newEndpoint;\n }\n }\n else {\n this._paramsStore = this._createStore(this._options.request.params);\n }\n },\n\n _isDeletePossible: function() {\n if (!qq.DeleteFileAjaxRequester || !this._options.deleteFile.enabled) {\n return false;\n }\n\n if (this._options.cors.expected) {\n if (qq.supportedFeatures.deleteFileCorsXhr) {\n return true;\n }\n\n if (qq.supportedFeatures.deleteFileCorsXdr && this._options.cors.allowXdr) {\n return true;\n }\n\n return false;\n }\n\n return true;\n },\n\n _isAllowedExtension: function(allowed, fileName) {\n var valid = false;\n\n if (!allowed.length) {\n return true;\n }\n\n qq.each(allowed, function(idx, allowedExt) {\n /**\n * If an argument is not a string, ignore it. Added when a possible issue with MooTools hijacking the\n * `allowedExtensions` array was discovered. See case #735 in the issue tracker for more details.\n */\n if (qq.isString(allowedExt)) {\n /*jshint eqeqeq: true, eqnull: true*/\n var extRegex = new RegExp(\"\\\\.\" + allowedExt + \"$\", \"i\");\n\n if (fileName.match(extRegex) != null) {\n valid = true;\n return false;\n }\n }\n });\n\n return valid;\n },\n\n /**\n * Constructs and returns a message that describes an item/file error. Also calls `onError` callback.\n *\n * @param code REQUIRED - a code that corresponds to a stock message describing this type of error\n * @param maybeNameOrNames names of the items that have failed, if applicable\n * @param item `File`, `Blob`, or ` `\n * @private\n */\n _itemError: function(code, maybeNameOrNames, item) {\n var message = this._options.messages[code],\n allowedExtensions = [],\n names = [].concat(maybeNameOrNames),\n name = names[0],\n buttonId = this._getButtonId(item),\n validationBase = this._getValidationBase(buttonId),\n extensionsForMessage, placeholderMatch;\n\n function r(name, replacement) { message = message.replace(name, replacement); }\n\n qq.each(validationBase.allowedExtensions, function(idx, allowedExtension) {\n /**\n * If an argument is not a string, ignore it. Added when a possible issue with MooTools hijacking the\n * `allowedExtensions` array was discovered. See case #735 in the issue tracker for more details.\n */\n if (qq.isString(allowedExtension)) {\n allowedExtensions.push(allowedExtension);\n }\n });\n\n extensionsForMessage = allowedExtensions.join(\", \").toLowerCase();\n\n r(\"{file}\", this._options.formatFileName(name));\n r(\"{extensions}\", extensionsForMessage);\n r(\"{sizeLimit}\", this._formatSize(validationBase.sizeLimit));\n r(\"{minSizeLimit}\", this._formatSize(validationBase.minSizeLimit));\n\n placeholderMatch = message.match(/(\\{\\w+\\})/g);\n if (placeholderMatch !== null) {\n qq.each(placeholderMatch, function(idx, placeholder) {\n r(placeholder, names[idx]);\n });\n }\n\n this._options.callbacks.onError(null, name, message, undefined);\n\n return message;\n },\n\n /**\n * Conditionally orders a manual retry of a failed upload.\n *\n * @param id File ID of the failed upload\n * @param callback Optional callback to invoke if a retry is prudent.\n * In lieu of asking the upload handler to retry.\n * @returns {boolean} true if a manual retry will occur\n * @private\n */\n _manualRetry: function(id, callback) {\n if (this._onBeforeManualRetry(id)) {\n this._netUploadedOrQueued++;\n this._uploadData.setStatus(id, qq.status.UPLOAD_RETRYING);\n\n if (callback) {\n callback(id);\n }\n else {\n this._handler.retry(id);\n }\n\n return true;\n }\n },\n\n _maybeAllComplete: function(id, status) {\n var self = this,\n notFinished = this._getNotFinished();\n\n if (status === qq.status.UPLOAD_SUCCESSFUL) {\n this._succeededSinceLastAllComplete.push(id);\n }\n else if (status === qq.status.UPLOAD_FAILED) {\n this._failedSinceLastAllComplete.push(id);\n }\n\n if (notFinished === 0 &&\n (this._succeededSinceLastAllComplete.length || this._failedSinceLastAllComplete.length)) {\n // Attempt to ensure onAllComplete is not invoked before other callbacks, such as onCancel & onComplete\n setTimeout(function() {\n self._onAllComplete(self._succeededSinceLastAllComplete, self._failedSinceLastAllComplete);\n }, 0);\n }\n },\n\n _maybeHandleIos8SafariWorkaround: function() {\n var self = this;\n\n if (this._options.workarounds.ios8SafariUploads && qq.ios800() && qq.iosSafari()) {\n setTimeout(function() {\n window.alert(self._options.messages.unsupportedBrowserIos8Safari);\n }, 0);\n throw new qq.Error(this._options.messages.unsupportedBrowserIos8Safari);\n }\n },\n\n _maybeParseAndSendUploadError: function(id, name, response, xhr) {\n // Assuming no one will actually set the response code to something other than 200\n // and still set 'success' to true...\n if (!response.success) {\n if (xhr && xhr.status !== 200 && !response.error) {\n this._options.callbacks.onError(id, name, \"XHR returned response code \" + xhr.status, xhr);\n }\n else {\n var errorReason = response.error ? response.error : this._options.text.defaultResponseError;\n this._options.callbacks.onError(id, name, errorReason, xhr);\n }\n }\n },\n\n _maybeProcessNextItemAfterOnValidateCallback: function(validItem, items, index, params, endpoint) {\n var self = this;\n\n if (items.length > index) {\n if (validItem || !this._options.validation.stopOnFirstInvalidFile) {\n //use setTimeout to prevent a stack overflow with a large number of files in the batch & non-promissory callbacks\n setTimeout(function() {\n var validationDescriptor = self._getValidationDescriptor(items[index]),\n buttonId = self._getButtonId(items[index].file),\n button = self._getButton(buttonId);\n\n self._handleCheckedCallback({\n name: \"onValidate\",\n callback: qq.bind(self._options.callbacks.onValidate, self, validationDescriptor, button),\n onSuccess: qq.bind(self._onValidateCallbackSuccess, self, items, index, params, endpoint),\n onFailure: qq.bind(self._onValidateCallbackFailure, self, items, index, params, endpoint),\n identifier: \"Item '\" + validationDescriptor.name + \"', size: \" + validationDescriptor.size\n });\n }, 0);\n }\n else if (!validItem) {\n for (; index < items.length; index++) {\n self._fileOrBlobRejected(items[index].id);\n }\n }\n }\n },\n\n _onAllComplete: function(successful, failed) {\n this._totalProgress && this._totalProgress.onAllComplete(successful, failed, this._preventRetries);\n\n this._options.callbacks.onAllComplete(qq.extend([], successful), qq.extend([], failed));\n\n this._succeededSinceLastAllComplete = [];\n this._failedSinceLastAllComplete = [];\n },\n\n /**\n * Attempt to automatically retry a failed upload.\n *\n * @param id The file ID of the failed upload\n * @param name The name of the file associated with the failed upload\n * @param responseJSON Response from the server, parsed into a javascript object\n * @param xhr Ajax transport used to send the failed request\n * @param callback Optional callback to be invoked if a retry is prudent.\n * Invoked in lieu of asking the upload handler to retry.\n * @returns {boolean} true if an auto-retry will occur\n * @private\n */\n _onAutoRetry: function(id, name, responseJSON, xhr, callback) {\n var self = this;\n\n self._preventRetries[id] = responseJSON[self._options.retry.preventRetryResponseProperty];\n\n if (self._shouldAutoRetry(id, name, responseJSON)) {\n var retryWaitPeriod = self._options.retry.autoAttemptDelay * 1000;\n\n self._maybeParseAndSendUploadError.apply(self, arguments);\n self._options.callbacks.onAutoRetry(id, name, self._autoRetries[id]);\n self._onBeforeAutoRetry(id, name);\n\n self._uploadData.setStatus(id, qq.status.UPLOAD_RETRYING);\n self._retryTimeouts[id] = setTimeout(function() {\n self.log(\"Starting retry for \" + name + \"...\");\n\n if (callback) {\n callback(id);\n }\n else {\n self._handler.retry(id);\n }\n }, retryWaitPeriod);\n\n return true;\n }\n },\n\n _onBeforeAutoRetry: function(id, name) {\n this.log(\"Waiting \" + this._options.retry.autoAttemptDelay + \" seconds before retrying \" + name + \"...\");\n },\n\n //return false if we should not attempt the requested retry\n _onBeforeManualRetry: function(id) {\n var itemLimit = this._currentItemLimit,\n fileName;\n\n if (this._preventRetries[id]) {\n this.log(\"Retries are forbidden for id \" + id, \"warn\");\n return false;\n }\n else if (this._handler.isValid(id)) {\n fileName = this.getName(id);\n\n if (this._options.callbacks.onManualRetry(id, fileName) === false) {\n return false;\n }\n\n if (itemLimit > 0 && this._netUploadedOrQueued + 1 > itemLimit) {\n this._itemError(\"retryFailTooManyItems\");\n return false;\n }\n\n this.log(\"Retrying upload for '\" + fileName + \"' (id: \" + id + \")...\");\n return true;\n }\n else {\n this.log(\"'\" + id + \"' is not a valid file ID\", \"error\");\n return false;\n }\n },\n\n _onCancel: function(id, name) {\n this._netUploadedOrQueued--;\n\n clearTimeout(this._retryTimeouts[id]);\n\n var storedItemIndex = qq.indexOf(this._storedIds, id);\n if (!this._options.autoUpload && storedItemIndex >= 0) {\n this._storedIds.splice(storedItemIndex, 1);\n }\n\n this._uploadData.setStatus(id, qq.status.CANCELED);\n },\n\n _onComplete: function(id, name, result, xhr) {\n if (!result.success) {\n this._netUploadedOrQueued--;\n this._uploadData.setStatus(id, qq.status.UPLOAD_FAILED);\n\n if (result[this._options.retry.preventRetryResponseProperty] === true) {\n this._preventRetries[id] = true;\n }\n }\n else {\n if (result.thumbnailUrl) {\n this._thumbnailUrls[id] = result.thumbnailUrl;\n }\n\n this._netUploaded++;\n this._uploadData.setStatus(id, qq.status.UPLOAD_SUCCESSFUL);\n }\n\n this._maybeParseAndSendUploadError(id, name, result, xhr);\n\n return result.success ? true : false;\n },\n\n _onDelete: function(id) {\n this._uploadData.setStatus(id, qq.status.DELETING);\n },\n\n _onDeleteComplete: function(id, xhrOrXdr, isError) {\n var name = this.getName(id);\n\n if (isError) {\n this._uploadData.setStatus(id, qq.status.DELETE_FAILED);\n this.log(\"Delete request for '\" + name + \"' has failed.\", \"error\");\n\n // For error reporting, we only have access to the response status if this is not\n // an `XDomainRequest`.\n if (xhrOrXdr.withCredentials === undefined) {\n this._options.callbacks.onError(id, name, \"Delete request failed\", xhrOrXdr);\n }\n else {\n this._options.callbacks.onError(id, name, \"Delete request failed with response code \" + xhrOrXdr.status, xhrOrXdr);\n }\n }\n else {\n this._netUploadedOrQueued--;\n this._netUploaded--;\n this._handler.expunge(id);\n this._uploadData.setStatus(id, qq.status.DELETED);\n this.log(\"Delete request for '\" + name + \"' has succeeded.\");\n }\n },\n\n _onInputChange: function(input) {\n var fileIndex;\n\n if (qq.supportedFeatures.ajaxUploading) {\n for (fileIndex = 0; fileIndex < input.files.length; fileIndex++) {\n this._annotateWithButtonId(input.files[fileIndex], input);\n }\n\n this.addFiles(input.files);\n }\n // Android 2.3.x will fire `onchange` even if no file has been selected\n else if (input.value.length > 0) {\n this.addFiles(input);\n }\n\n qq.each(this._buttons, function(idx, button) {\n button.reset();\n });\n },\n\n _onProgress: function(id, name, loaded, total) {\n this._totalProgress && this._totalProgress.onIndividualProgress(id, loaded, total);\n },\n\n _onSubmit: function(id, name) {\n //nothing to do yet in core uploader\n },\n\n _onSubmitCallbackSuccess: function(id, name) {\n this._onSubmit.apply(this, arguments);\n this._uploadData.setStatus(id, qq.status.SUBMITTED);\n this._onSubmitted.apply(this, arguments);\n\n if (this._options.autoUpload) {\n this._options.callbacks.onSubmitted.apply(this, arguments);\n this._uploadFile(id);\n }\n else {\n this._storeForLater(id);\n this._options.callbacks.onSubmitted.apply(this, arguments);\n }\n },\n\n _onSubmitDelete: function(id, onSuccessCallback, additionalMandatedParams) {\n var uuid = this.getUuid(id),\n adjustedOnSuccessCallback;\n\n if (onSuccessCallback) {\n adjustedOnSuccessCallback = qq.bind(onSuccessCallback, this, id, uuid, additionalMandatedParams);\n }\n\n if (this._isDeletePossible()) {\n this._handleCheckedCallback({\n name: \"onSubmitDelete\",\n callback: qq.bind(this._options.callbacks.onSubmitDelete, this, id),\n onSuccess: adjustedOnSuccessCallback ||\n qq.bind(this._deleteHandler.sendDelete, this, id, uuid, additionalMandatedParams),\n identifier: id\n });\n return true;\n }\n else {\n this.log(\"Delete request ignored for ID \" + id + \", delete feature is disabled or request not possible \" +\n \"due to CORS on a user agent that does not support pre-flighting.\", \"warn\");\n return false;\n }\n },\n\n _onSubmitted: function(id) {\n //nothing to do in the base uploader\n },\n\n _onTotalProgress: function(loaded, total) {\n this._options.callbacks.onTotalProgress(loaded, total);\n },\n\n _onUploadPrep: function(id) {\n // nothing to do in the core uploader for now\n },\n\n _onUpload: function(id, name) {\n this._uploadData.setStatus(id, qq.status.UPLOADING);\n },\n\n _onUploadChunk: function(id, chunkData) {\n //nothing to do in the base uploader\n },\n\n _onUploadStatusChange: function(id, oldStatus, newStatus) {\n // Make sure a \"queued\" retry attempt is canceled if the upload has been paused\n if (newStatus === qq.status.PAUSED) {\n clearTimeout(this._retryTimeouts[id]);\n }\n },\n\n _onValidateBatchCallbackFailure: function(fileWrappers) {\n var self = this;\n\n qq.each(fileWrappers, function(idx, fileWrapper) {\n self._fileOrBlobRejected(fileWrapper.id);\n });\n },\n\n _onValidateBatchCallbackSuccess: function(validationDescriptors, items, params, endpoint, button) {\n var errorMessage,\n itemLimit = this._currentItemLimit,\n proposedNetFilesUploadedOrQueued = this._netUploadedOrQueued;\n\n if (itemLimit === 0 || proposedNetFilesUploadedOrQueued <= itemLimit) {\n if (items.length > 0) {\n this._handleCheckedCallback({\n name: \"onValidate\",\n callback: qq.bind(this._options.callbacks.onValidate, this, validationDescriptors[0], button),\n onSuccess: qq.bind(this._onValidateCallbackSuccess, this, items, 0, params, endpoint),\n onFailure: qq.bind(this._onValidateCallbackFailure, this, items, 0, params, endpoint),\n identifier: \"Item '\" + items[0].file.name + \"', size: \" + items[0].file.size\n });\n }\n else {\n this._itemError(\"noFilesError\");\n }\n }\n else {\n this._onValidateBatchCallbackFailure(items);\n errorMessage = this._options.messages.tooManyItemsError\n .replace(/\\{netItems\\}/g, proposedNetFilesUploadedOrQueued)\n .replace(/\\{itemLimit\\}/g, itemLimit);\n this._batchError(errorMessage);\n }\n },\n\n _onValidateCallbackFailure: function(items, index, params, endpoint) {\n var nextIndex = index + 1;\n\n this._fileOrBlobRejected(items[index].id, items[index].file.name);\n\n this._maybeProcessNextItemAfterOnValidateCallback(false, items, nextIndex, params, endpoint);\n },\n\n _onValidateCallbackSuccess: function(items, index, params, endpoint) {\n var self = this,\n nextIndex = index + 1,\n validationDescriptor = this._getValidationDescriptor(items[index]);\n\n this._validateFileOrBlobData(items[index], validationDescriptor)\n .then(\n function() {\n self._upload(items[index].id, params, endpoint);\n self._maybeProcessNextItemAfterOnValidateCallback(true, items, nextIndex, params, endpoint);\n },\n function() {\n self._maybeProcessNextItemAfterOnValidateCallback(false, items, nextIndex, params, endpoint);\n }\n );\n },\n\n _prepareItemsForUpload: function(items, params, endpoint) {\n if (items.length === 0) {\n this._itemError(\"noFilesError\");\n return;\n }\n\n var validationDescriptors = this._getValidationDescriptors(items),\n buttonId = this._getButtonId(items[0].file),\n button = this._getButton(buttonId);\n\n this._handleCheckedCallback({\n name: \"onValidateBatch\",\n callback: qq.bind(this._options.callbacks.onValidateBatch, this, validationDescriptors, button),\n onSuccess: qq.bind(this._onValidateBatchCallbackSuccess, this, validationDescriptors, items, params, endpoint, button),\n onFailure: qq.bind(this._onValidateBatchCallbackFailure, this, items),\n identifier: \"batch validation\"\n });\n },\n\n _preventLeaveInProgress: function() {\n var self = this;\n\n this._disposeSupport.attach(window, \"beforeunload\", function(e) {\n if (self.getInProgress()) {\n e = e || window.event;\n // for ie, ff\n e.returnValue = self._options.messages.onLeave;\n // for webkit\n return self._options.messages.onLeave;\n }\n });\n },\n\n // Attempts to refresh session data only if the `qq.Session` module exists\n // and a session endpoint has been specified. The `onSessionRequestComplete`\n // callback will be invoked once the refresh is complete.\n _refreshSessionData: function() {\n var self = this,\n options = this._options.session;\n\n /* jshint eqnull:true */\n if (qq.Session && this._options.session.endpoint != null) {\n if (!this._session) {\n qq.extend(options, {cors: this._options.cors});\n\n options.log = qq.bind(this.log, this);\n options.addFileRecord = qq.bind(this._addCannedFile, this);\n\n this._session = new qq.Session(options);\n }\n\n setTimeout(function() {\n self._session.refresh().then(function(response, xhrOrXdr) {\n self._sessionRequestComplete();\n self._options.callbacks.onSessionRequestComplete(response, true, xhrOrXdr);\n\n }, function(response, xhrOrXdr) {\n\n self._options.callbacks.onSessionRequestComplete(response, false, xhrOrXdr);\n });\n }, 0);\n }\n },\n\n _sessionRequestComplete: function() {},\n\n _setSize: function(id, newSize) {\n this._uploadData.updateSize(id, newSize);\n this._totalProgress && this._totalProgress.onNewSize(id);\n },\n\n _shouldAutoRetry: function(id, name, responseJSON) {\n var uploadData = this._uploadData.retrieve({id: id});\n\n /*jshint laxbreak: true */\n if (!this._preventRetries[id]\n && this._options.retry.enableAuto\n && uploadData.status !== qq.status.PAUSED) {\n\n if (this._autoRetries[id] === undefined) {\n this._autoRetries[id] = 0;\n }\n\n if (this._autoRetries[id] < this._options.retry.maxAutoAttempts) {\n this._autoRetries[id] += 1;\n return true;\n }\n }\n\n return false;\n },\n\n _storeForLater: function(id) {\n this._storedIds.push(id);\n },\n\n // Maps a file with the button that was used to select it.\n _trackButton: function(id) {\n var buttonId;\n\n if (qq.supportedFeatures.ajaxUploading) {\n buttonId = this._handler.getFile(id).qqButtonId;\n }\n else {\n buttonId = this._getButtonId(this._handler.getInput(id));\n }\n\n if (buttonId) {\n this._buttonIdsForFileIds[id] = buttonId;\n }\n },\n\n _updateFormSupportAndParams: function(formElementOrId) {\n this._options.form.element = formElementOrId;\n\n this._formSupport = qq.FormSupport && new qq.FormSupport(\n this._options.form, qq.bind(this.uploadStoredFiles, this), qq.bind(this.log, this)\n );\n\n if (this._formSupport && this._formSupport.attachedToForm) {\n this._paramsStore.addReadOnly(null, this._formSupport.getFormInputsAsObject);\n\n this._options.autoUpload = this._formSupport.newAutoUpload;\n if (this._formSupport.newEndpoint) {\n this.setEndpoint(this._formSupport.newEndpoint);\n }\n }\n },\n\n _upload: function(id, params, endpoint) {\n var name = this.getName(id);\n\n if (params) {\n this.setParams(params, id);\n }\n\n if (endpoint) {\n this.setEndpoint(endpoint, id);\n }\n\n this._handleCheckedCallback({\n name: \"onSubmit\",\n callback: qq.bind(this._options.callbacks.onSubmit, this, id, name),\n onSuccess: qq.bind(this._onSubmitCallbackSuccess, this, id, name),\n onFailure: qq.bind(this._fileOrBlobRejected, this, id, name),\n identifier: id\n });\n },\n\n _uploadFile: function(id) {\n if (!this._handler.upload(id)) {\n this._uploadData.setStatus(id, qq.status.QUEUED);\n }\n },\n\n _uploadStoredFiles: function() {\n var idToUpload, stillSubmitting,\n self = this;\n\n while (this._storedIds.length) {\n idToUpload = this._storedIds.shift();\n this._uploadFile(idToUpload);\n }\n\n // If we are still waiting for some files to clear validation, attempt to upload these again in a bit\n stillSubmitting = this.getUploads({status: qq.status.SUBMITTING}).length;\n if (stillSubmitting) {\n qq.log(\"Still waiting for \" + stillSubmitting + \" files to clear submit queue. Will re-parse stored IDs array shortly.\");\n setTimeout(function() {\n self._uploadStoredFiles();\n }, 1000);\n }\n },\n\n /**\n * Performs some internal validation checks on an item, defined in the `validation` option.\n *\n * @param fileWrapper Wrapper containing a `file` along with an `id`\n * @param validationDescriptor Normalized information about the item (`size`, `name`).\n * @returns qq.Promise with appropriate callbacks invoked depending on the validity of the file\n * @private\n */\n _validateFileOrBlobData: function(fileWrapper, validationDescriptor) {\n var self = this,\n file = (function() {\n if (fileWrapper.file instanceof qq.BlobProxy) {\n return fileWrapper.file.referenceBlob;\n }\n return fileWrapper.file;\n }()),\n name = validationDescriptor.name,\n size = validationDescriptor.size,\n buttonId = this._getButtonId(fileWrapper.file),\n validationBase = this._getValidationBase(buttonId),\n validityChecker = new qq.Promise();\n\n validityChecker.then(\n function() {},\n function() {\n self._fileOrBlobRejected(fileWrapper.id, name);\n });\n\n if (qq.isFileOrInput(file) && !this._isAllowedExtension(validationBase.allowedExtensions, name)) {\n this._itemError(\"typeError\", name, file);\n return validityChecker.failure();\n }\n\n if (!this._options.validation.allowEmpty && size === 0) {\n this._itemError(\"emptyError\", name, file);\n return validityChecker.failure();\n }\n\n if (size > 0 && validationBase.sizeLimit && size > validationBase.sizeLimit) {\n this._itemError(\"sizeError\", name, file);\n return validityChecker.failure();\n }\n\n if (size > 0 && size < validationBase.minSizeLimit) {\n this._itemError(\"minSizeError\", name, file);\n return validityChecker.failure();\n }\n\n if (qq.ImageValidation && qq.supportedFeatures.imagePreviews && qq.isFile(file)) {\n new qq.ImageValidation(file, qq.bind(self.log, self)).validate(validationBase.image).then(\n validityChecker.success,\n function(errorCode) {\n self._itemError(errorCode + \"ImageError\", name, file);\n validityChecker.failure();\n }\n );\n }\n else {\n validityChecker.success();\n }\n\n return validityChecker;\n },\n\n _wrapCallbacks: function() {\n var self, safeCallback, prop;\n\n self = this;\n\n safeCallback = function(name, callback, args) {\n var errorMsg;\n\n try {\n return callback.apply(self, args);\n }\n catch (exception) {\n errorMsg = exception.message || exception.toString();\n self.log(\"Caught exception in '\" + name + \"' callback - \" + errorMsg, \"error\");\n }\n };\n\n /* jshint forin: false, loopfunc: true */\n for (prop in this._options.callbacks) {\n (function() {\n var callbackName, callbackFunc;\n callbackName = prop;\n callbackFunc = self._options.callbacks[callbackName];\n self._options.callbacks[callbackName] = function() {\n return safeCallback(callbackName, callbackFunc, arguments);\n };\n }());\n }\n }\n };\n}());\n","/*globals qq*/\n(function() {\n \"use strict\";\n\n qq.FineUploaderBasic = function(o) {\n var self = this;\n\n // These options define FineUploaderBasic mode.\n this._options = {\n debug: false,\n button: null,\n multiple: true,\n maxConnections: 3,\n disableCancelForFormUploads: false,\n autoUpload: true,\n\n request: {\n customHeaders: {},\n endpoint: \"/server/upload\",\n filenameParam: \"qqfilename\",\n forceMultipart: true,\n inputName: \"qqfile\",\n method: \"POST\",\n params: {},\n paramsInBody: true,\n totalFileSizeName: \"qqtotalfilesize\",\n uuidName: \"qquuid\"\n },\n\n validation: {\n allowedExtensions: [],\n sizeLimit: 0,\n minSizeLimit: 0,\n itemLimit: 0,\n stopOnFirstInvalidFile: true,\n acceptFiles: null,\n image: {\n maxHeight: 0,\n maxWidth: 0,\n minHeight: 0,\n minWidth: 0\n },\n allowEmpty: false\n },\n\n callbacks: {\n onSubmit: function(id, name) {},\n onSubmitted: function(id, name) {},\n onComplete: function(id, name, responseJSON, maybeXhr) {},\n onAllComplete: function(successful, failed) {},\n onCancel: function(id, name) {},\n onUpload: function(id, name) {},\n onUploadChunk: function(id, name, chunkData) {},\n onUploadChunkSuccess: function(id, chunkData, responseJSON, xhr) {},\n onResume: function(id, fileName, chunkData) {},\n onProgress: function(id, name, loaded, total) {},\n onTotalProgress: function(loaded, total) {},\n onError: function(id, name, reason, maybeXhrOrXdr) {},\n onAutoRetry: function(id, name, attemptNumber) {},\n onManualRetry: function(id, name) {},\n onValidateBatch: function(fileOrBlobData) {},\n onValidate: function(fileOrBlobData) {},\n onSubmitDelete: function(id) {},\n onDelete: function(id) {},\n onDeleteComplete: function(id, xhrOrXdr, isError) {},\n onPasteReceived: function(blob) {},\n onStatusChange: function(id, oldStatus, newStatus) {},\n onSessionRequestComplete: function(response, success, xhrOrXdr) {}\n },\n\n messages: {\n typeError: \"{file} has an invalid extension. Valid extension(s): {extensions}.\",\n sizeError: \"{file} is too large, maximum file size is {sizeLimit}.\",\n minSizeError: \"{file} is too small, minimum file size is {minSizeLimit}.\",\n emptyError: \"{file} is empty, please select files again without it.\",\n noFilesError: \"No files to upload.\",\n tooManyItemsError: \"Too many items ({netItems}) would be uploaded. Item limit is {itemLimit}.\",\n maxHeightImageError: \"Image is too tall.\",\n maxWidthImageError: \"Image is too wide.\",\n minHeightImageError: \"Image is not tall enough.\",\n minWidthImageError: \"Image is not wide enough.\",\n retryFailTooManyItems: \"Retry failed - you have reached your file limit.\",\n onLeave: \"The files are being uploaded, if you leave now the upload will be canceled.\",\n unsupportedBrowserIos8Safari: \"Unrecoverable error - this browser does not permit file uploading of any kind due to serious bugs in iOS8 Safari. Please use iOS8 Chrome until Apple fixes these issues.\"\n },\n\n retry: {\n enableAuto: false,\n maxAutoAttempts: 3,\n autoAttemptDelay: 5,\n preventRetryResponseProperty: \"preventRetry\"\n },\n\n classes: {\n buttonHover: \"qq-upload-button-hover\",\n buttonFocus: \"qq-upload-button-focus\"\n },\n\n chunking: {\n enabled: false,\n concurrent: {\n enabled: false\n },\n mandatory: false,\n paramNames: {\n partIndex: \"qqpartindex\",\n partByteOffset: \"qqpartbyteoffset\",\n chunkSize: \"qqchunksize\",\n totalFileSize: \"qqtotalfilesize\",\n totalParts: \"qqtotalparts\"\n },\n partSize: 2000000,\n // only relevant for traditional endpoints, only required when concurrent.enabled === true\n success: {\n endpoint: null\n }\n },\n\n resume: {\n enabled: false,\n recordsExpireIn: 7, //days\n paramNames: {\n resuming: \"qqresume\"\n }\n },\n\n formatFileName: function(fileOrBlobName) {\n return fileOrBlobName;\n },\n\n text: {\n defaultResponseError: \"Upload failure reason unknown\",\n fileInputTitle: \"file input\",\n sizeSymbols: [\"kB\", \"MB\", \"GB\", \"TB\", \"PB\", \"EB\"]\n },\n\n deleteFile: {\n enabled: false,\n method: \"DELETE\",\n endpoint: \"/server/upload\",\n customHeaders: {},\n params: {}\n },\n\n cors: {\n expected: false,\n sendCredentials: false,\n allowXdr: false\n },\n\n blobs: {\n defaultName: \"misc_data\"\n },\n\n paste: {\n targetElement: null,\n defaultName: \"pasted_image\"\n },\n\n camera: {\n ios: false,\n\n // if ios is true: button is null means target the default button, otherwise target the button specified\n button: null\n },\n\n // This refers to additional upload buttons to be handled by Fine Uploader.\n // Each element is an object, containing `element` as the only required\n // property. The `element` must be a container that will ultimately\n // contain an invisible ` ` created by Fine Uploader.\n // Optional properties of each object include `multiple`, `validation`,\n // and `folders`.\n extraButtons: [],\n\n // Depends on the session module. Used to query the server for an initial file list\n // during initialization and optionally after a `reset`.\n session: {\n endpoint: null,\n params: {},\n customHeaders: {},\n refreshOnReset: true\n },\n\n // Send parameters associated with an existing form along with the files\n form: {\n // Element ID, HTMLElement, or null\n element: \"qq-form\",\n\n // Overrides the base `autoUpload`, unless `element` is null.\n autoUpload: false,\n\n // true = upload files on form submission (and squelch submit event)\n interceptSubmit: true\n },\n\n // scale images client side, upload a new file for each scaled version\n scaling: {\n customResizer: null,\n\n // send the original file as well\n sendOriginal: true,\n\n // fox orientation for scaled images\n orient: true,\n\n // If null, scaled image type will match reference image type. This value will be referred to\n // for any size record that does not specific a type.\n defaultType: null,\n\n defaultQuality: 80,\n\n failureText: \"Failed to scale\",\n\n includeExif: false,\n\n // metadata about each requested scaled version\n sizes: []\n },\n\n workarounds: {\n iosEmptyVideos: true,\n ios8SafariUploads: true,\n ios8BrowserCrash: false\n }\n };\n\n // Replace any default options with user defined ones\n qq.extend(this._options, o, true);\n\n this._buttons = [];\n this._extraButtonSpecs = {};\n this._buttonIdsForFileIds = [];\n\n this._wrapCallbacks();\n this._disposeSupport = new qq.DisposeSupport();\n\n this._storedIds = [];\n this._autoRetries = [];\n this._retryTimeouts = [];\n this._preventRetries = [];\n this._thumbnailUrls = [];\n\n this._netUploadedOrQueued = 0;\n this._netUploaded = 0;\n this._uploadData = this._createUploadDataTracker();\n\n this._initFormSupportAndParams();\n\n this._customHeadersStore = this._createStore(this._options.request.customHeaders);\n this._deleteFileCustomHeadersStore = this._createStore(this._options.deleteFile.customHeaders);\n\n this._deleteFileParamsStore = this._createStore(this._options.deleteFile.params);\n\n this._endpointStore = this._createStore(this._options.request.endpoint);\n this._deleteFileEndpointStore = this._createStore(this._options.deleteFile.endpoint);\n\n this._handler = this._createUploadHandler();\n\n this._deleteHandler = qq.DeleteFileAjaxRequester && this._createDeleteHandler();\n\n if (this._options.button) {\n this._defaultButtonId = this._createUploadButton({\n element: this._options.button,\n title: this._options.text.fileInputTitle\n }).getButtonId();\n }\n\n this._generateExtraButtonSpecs();\n\n this._handleCameraAccess();\n\n if (this._options.paste.targetElement) {\n if (qq.PasteSupport) {\n this._pasteHandler = this._createPasteHandler();\n }\n else {\n this.log(\"Paste support module not found\", \"error\");\n }\n }\n\n this._preventLeaveInProgress();\n\n this._imageGenerator = qq.ImageGenerator && new qq.ImageGenerator(qq.bind(this.log, this));\n this._refreshSessionData();\n\n this._succeededSinceLastAllComplete = [];\n this._failedSinceLastAllComplete = [];\n\n this._scaler = (qq.Scaler && new qq.Scaler(this._options.scaling, qq.bind(this.log, this))) || {};\n if (this._scaler.enabled) {\n this._customNewFileHandler = qq.bind(this._scaler.handleNewFile, this._scaler);\n }\n\n if (qq.TotalProgress && qq.supportedFeatures.progressBar) {\n this._totalProgress = new qq.TotalProgress(\n qq.bind(this._onTotalProgress, this),\n\n function(id) {\n var entry = self._uploadData.retrieve({id: id});\n return (entry && entry.size) || 0;\n }\n );\n }\n\n this._currentItemLimit = this._options.validation.itemLimit;\n };\n\n // Define the private & public API methods.\n qq.FineUploaderBasic.prototype = qq.basePublicApi;\n qq.extend(qq.FineUploaderBasic.prototype, qq.basePrivateApi);\n}());\n","/*globals qq, XDomainRequest*/\n/** Generic class for sending non-upload ajax requests and handling the associated responses **/\nqq.AjaxRequester = function(o) {\n \"use strict\";\n\n var log, shouldParamsBeInQueryString,\n queue = [],\n requestData = {},\n options = {\n acceptHeader: null,\n validMethods: [\"PATCH\", \"POST\", \"PUT\"],\n method: \"POST\",\n contentType: \"application/x-www-form-urlencoded\",\n maxConnections: 3,\n customHeaders: {},\n endpointStore: {},\n paramsStore: {},\n mandatedParams: {},\n allowXRequestedWithAndCacheControl: true,\n successfulResponseCodes: {\n DELETE: [200, 202, 204],\n PATCH: [200, 201, 202, 203, 204],\n POST: [200, 201, 202, 203, 204],\n PUT: [200, 201, 202, 203, 204],\n GET: [200]\n },\n cors: {\n expected: false,\n sendCredentials: false\n },\n log: function(str, level) {},\n onSend: function(id) {},\n onComplete: function(id, xhrOrXdr, isError) {},\n onProgress: null\n };\n\n qq.extend(options, o);\n log = options.log;\n\n if (qq.indexOf(options.validMethods, options.method) < 0) {\n throw new Error(\"'\" + options.method + \"' is not a supported method for this type of request!\");\n }\n\n // [Simple methods](http://www.w3.org/TR/cors/#simple-method)\n // are defined by the W3C in the CORS spec as a list of methods that, in part,\n // make a CORS request eligible to be exempt from preflighting.\n function isSimpleMethod() {\n return qq.indexOf([\"GET\", \"POST\", \"HEAD\"], options.method) >= 0;\n }\n\n // [Simple headers](http://www.w3.org/TR/cors/#simple-header)\n // are defined by the W3C in the CORS spec as a list of headers that, in part,\n // make a CORS request eligible to be exempt from preflighting.\n function containsNonSimpleHeaders(headers) {\n var containsNonSimple = false;\n\n qq.each(containsNonSimple, function(idx, header) {\n if (qq.indexOf([\"Accept\", \"Accept-Language\", \"Content-Language\", \"Content-Type\"], header) < 0) {\n containsNonSimple = true;\n return false;\n }\n });\n\n return containsNonSimple;\n }\n\n function isXdr(xhr) {\n //The `withCredentials` test is a commonly accepted way to determine if XHR supports CORS.\n return options.cors.expected && xhr.withCredentials === undefined;\n }\n\n // Returns either a new `XMLHttpRequest` or `XDomainRequest` instance.\n function getCorsAjaxTransport() {\n var xhrOrXdr;\n\n if (window.XMLHttpRequest || window.ActiveXObject) {\n xhrOrXdr = qq.createXhrInstance();\n\n if (xhrOrXdr.withCredentials === undefined) {\n xhrOrXdr = new XDomainRequest();\n // Workaround for XDR bug in IE9 - https://social.msdn.microsoft.com/Forums/ie/en-US/30ef3add-767c-4436-b8a9-f1ca19b4812e/ie9-rtm-xdomainrequest-issued-requests-may-abort-if-all-event-handlers-not-specified?forum=iewebdevelopment\n xhrOrXdr.onload = function() {};\n xhrOrXdr.onerror = function() {};\n xhrOrXdr.ontimeout = function() {};\n xhrOrXdr.onprogress = function() {};\n }\n }\n\n return xhrOrXdr;\n }\n\n // Returns either a new XHR/XDR instance, or an existing one for the associated `File` or `Blob`.\n function getXhrOrXdr(id, suppliedXhr) {\n var xhrOrXdr = requestData[id].xhr;\n\n if (!xhrOrXdr) {\n if (suppliedXhr) {\n xhrOrXdr = suppliedXhr;\n }\n else {\n if (options.cors.expected) {\n xhrOrXdr = getCorsAjaxTransport();\n }\n else {\n xhrOrXdr = qq.createXhrInstance();\n }\n }\n\n requestData[id].xhr = xhrOrXdr;\n }\n\n return xhrOrXdr;\n }\n\n // Removes element from queue, sends next request\n function dequeue(id) {\n var i = qq.indexOf(queue, id),\n max = options.maxConnections,\n nextId;\n\n delete requestData[id];\n queue.splice(i, 1);\n\n if (queue.length >= max && i < max) {\n nextId = queue[max - 1];\n sendRequest(nextId);\n }\n }\n\n function onComplete(id, xdrError) {\n var xhr = getXhrOrXdr(id),\n method = options.method,\n isError = xdrError === true;\n\n dequeue(id);\n\n if (isError) {\n log(method + \" request for \" + id + \" has failed\", \"error\");\n }\n else if (!isXdr(xhr) && !isResponseSuccessful(xhr.status)) {\n isError = true;\n log(method + \" request for \" + id + \" has failed - response code \" + xhr.status, \"error\");\n }\n\n options.onComplete(id, xhr, isError);\n }\n\n function getParams(id) {\n var onDemandParams = requestData[id].additionalParams,\n mandatedParams = options.mandatedParams,\n params;\n\n if (options.paramsStore.get) {\n params = options.paramsStore.get(id);\n }\n\n if (onDemandParams) {\n qq.each(onDemandParams, function(name, val) {\n params = params || {};\n params[name] = val;\n });\n }\n\n if (mandatedParams) {\n qq.each(mandatedParams, function(name, val) {\n params = params || {};\n params[name] = val;\n });\n }\n\n return params;\n }\n\n function sendRequest(id, optXhr) {\n var xhr = getXhrOrXdr(id, optXhr),\n method = options.method,\n params = getParams(id),\n payload = requestData[id].payload,\n url;\n\n options.onSend(id);\n\n url = createUrl(id, params, requestData[id].additionalQueryParams);\n\n // XDR and XHR status detection APIs differ a bit.\n if (isXdr(xhr)) {\n xhr.onload = getXdrLoadHandler(id);\n xhr.onerror = getXdrErrorHandler(id);\n }\n else {\n xhr.onreadystatechange = getXhrReadyStateChangeHandler(id);\n }\n\n registerForUploadProgress(id);\n\n // The last parameter is assumed to be ignored if we are actually using `XDomainRequest`.\n xhr.open(method, url, true);\n\n // Instruct the transport to send cookies along with the CORS request,\n // unless we are using `XDomainRequest`, which is not capable of this.\n if (options.cors.expected && options.cors.sendCredentials && !isXdr(xhr)) {\n xhr.withCredentials = true;\n }\n\n setHeaders(id);\n\n log(\"Sending \" + method + \" request for \" + id);\n\n if (payload) {\n xhr.send(payload);\n }\n else if (shouldParamsBeInQueryString || !params) {\n xhr.send();\n }\n else if (params && options.contentType && options.contentType.toLowerCase().indexOf(\"application/x-www-form-urlencoded\") >= 0) {\n xhr.send(qq.obj2url(params, \"\"));\n }\n else if (params && options.contentType && options.contentType.toLowerCase().indexOf(\"application/json\") >= 0) {\n xhr.send(JSON.stringify(params));\n }\n else {\n xhr.send(params);\n }\n\n return xhr;\n }\n\n function createUrl(id, params, additionalQueryParams) {\n var endpoint = options.endpointStore.get(id),\n addToPath = requestData[id].addToPath;\n\n /*jshint -W116,-W041 */\n if (addToPath != undefined) {\n endpoint += \"/\" + addToPath;\n }\n\n if (shouldParamsBeInQueryString && params) {\n endpoint = qq.obj2url(params, endpoint);\n }\n\n if (additionalQueryParams) {\n endpoint = qq.obj2url(additionalQueryParams, endpoint);\n }\n\n return endpoint;\n }\n\n // Invoked by the UA to indicate a number of possible states that describe\n // a live `XMLHttpRequest` transport.\n function getXhrReadyStateChangeHandler(id) {\n return function() {\n if (getXhrOrXdr(id).readyState === 4) {\n onComplete(id);\n }\n };\n }\n\n function registerForUploadProgress(id) {\n var onProgress = options.onProgress;\n\n if (onProgress) {\n getXhrOrXdr(id).upload.onprogress = function(e) {\n if (e.lengthComputable) {\n onProgress(id, e.loaded, e.total);\n }\n };\n }\n }\n\n // This will be called by IE to indicate **success** for an associated\n // `XDomainRequest` transported request.\n function getXdrLoadHandler(id) {\n return function() {\n onComplete(id);\n };\n }\n\n // This will be called by IE to indicate **failure** for an associated\n // `XDomainRequest` transported request.\n function getXdrErrorHandler(id) {\n return function() {\n onComplete(id, true);\n };\n }\n\n function setHeaders(id) {\n var xhr = getXhrOrXdr(id),\n customHeaders = options.customHeaders,\n onDemandHeaders = requestData[id].additionalHeaders || {},\n method = options.method,\n allHeaders = {};\n\n // If XDomainRequest is being used, we can't set headers, so just ignore this block.\n if (!isXdr(xhr)) {\n options.acceptHeader && xhr.setRequestHeader(\"Accept\", options.acceptHeader);\n\n // Only attempt to add X-Requested-With & Cache-Control if permitted\n if (options.allowXRequestedWithAndCacheControl) {\n // Do not add X-Requested-With & Cache-Control if this is a cross-origin request\n // OR the cross-origin request contains a non-simple method or header.\n // This is done to ensure a preflight is not triggered exclusively based on the\n // addition of these 2 non-simple headers.\n if (!options.cors.expected || (!isSimpleMethod() || containsNonSimpleHeaders(customHeaders))) {\n xhr.setRequestHeader(\"X-Requested-With\", \"XMLHttpRequest\");\n xhr.setRequestHeader(\"Cache-Control\", \"no-cache\");\n }\n }\n\n if (options.contentType && (method === \"POST\" || method === \"PUT\")) {\n xhr.setRequestHeader(\"Content-Type\", options.contentType);\n }\n\n qq.extend(allHeaders, qq.isFunction(customHeaders) ? customHeaders(id) : customHeaders);\n qq.extend(allHeaders, onDemandHeaders);\n\n qq.each(allHeaders, function(name, val) {\n xhr.setRequestHeader(name, val);\n });\n }\n }\n\n function isResponseSuccessful(responseCode) {\n return qq.indexOf(options.successfulResponseCodes[options.method], responseCode) >= 0;\n }\n\n function prepareToSend(id, optXhr, addToPath, additionalParams, additionalQueryParams, additionalHeaders, payload) {\n requestData[id] = {\n addToPath: addToPath,\n additionalParams: additionalParams,\n additionalQueryParams: additionalQueryParams,\n additionalHeaders: additionalHeaders,\n payload: payload\n };\n\n var len = queue.push(id);\n\n // if too many active connections, wait...\n if (len <= options.maxConnections) {\n return sendRequest(id, optXhr);\n }\n }\n\n shouldParamsBeInQueryString = options.method === \"GET\" || options.method === \"DELETE\";\n\n qq.extend(this, {\n // Start the process of sending the request. The ID refers to the file associated with the request.\n initTransport: function(id) {\n var path, params, headers, payload, cacheBuster, additionalQueryParams;\n\n return {\n // Optionally specify the end of the endpoint path for the request.\n withPath: function(appendToPath) {\n path = appendToPath;\n return this;\n },\n\n // Optionally specify additional parameters to send along with the request.\n // These will be added to the query string for GET/DELETE requests or the payload\n // for POST/PUT requests. The Content-Type of the request will be used to determine\n // how these parameters should be formatted as well.\n withParams: function(additionalParams) {\n params = additionalParams;\n return this;\n },\n\n withQueryParams: function(_additionalQueryParams_) {\n additionalQueryParams = _additionalQueryParams_;\n return this;\n },\n\n // Optionally specify additional headers to send along with the request.\n withHeaders: function(additionalHeaders) {\n headers = additionalHeaders;\n return this;\n },\n\n // Optionally specify a payload/body for the request.\n withPayload: function(thePayload) {\n payload = thePayload;\n return this;\n },\n\n // Appends a cache buster (timestamp) to the request URL as a query parameter (only if GET or DELETE)\n withCacheBuster: function() {\n cacheBuster = true;\n return this;\n },\n\n // Send the constructed request.\n send: function(optXhr) {\n if (cacheBuster && qq.indexOf([\"GET\", \"DELETE\"], options.method) >= 0) {\n params.qqtimestamp = new Date().getTime();\n }\n\n return prepareToSend(id, optXhr, path, params, additionalQueryParams, headers, payload);\n }\n };\n },\n\n canceled: function(id) {\n dequeue(id);\n }\n });\n};\n","/* globals qq */\n/**\n * Common upload handler functions.\n *\n * @constructor\n */\nqq.UploadHandler = function(spec) {\n \"use strict\";\n\n var proxy = spec.proxy,\n fileState = {},\n onCancel = proxy.onCancel,\n getName = proxy.getName;\n\n qq.extend(this, {\n add: function(id, fileItem) {\n fileState[id] = fileItem;\n fileState[id].temp = {};\n },\n\n cancel: function(id) {\n var self = this,\n cancelFinalizationEffort = new qq.Promise(),\n onCancelRetVal = onCancel(id, getName(id), cancelFinalizationEffort);\n\n onCancelRetVal.then(function() {\n if (self.isValid(id)) {\n fileState[id].canceled = true;\n self.expunge(id);\n }\n cancelFinalizationEffort.success();\n });\n },\n\n expunge: function(id) {\n delete fileState[id];\n },\n\n getThirdPartyFileId: function(id) {\n return fileState[id].key;\n },\n\n isValid: function(id) {\n return fileState[id] !== undefined;\n },\n\n reset: function() {\n fileState = {};\n },\n\n _getFileState: function(id) {\n return fileState[id];\n },\n\n _setThirdPartyFileId: function(id, thirdPartyFileId) {\n fileState[id].key = thirdPartyFileId;\n },\n\n _wasCanceled: function(id) {\n return !!fileState[id].canceled;\n }\n });\n};\n","/*globals qq*/\n/**\n * Base upload handler module. Controls more specific handlers.\n *\n * @param o Options. Passed along to the specific handler submodule as well.\n * @param namespace [optional] Namespace for the specific handler.\n */\nqq.UploadHandlerController = function(o, namespace) {\n \"use strict\";\n\n var controller = this,\n chunkingPossible = false,\n concurrentChunkingPossible = false,\n chunking, preventRetryResponse, log, handler,\n\n options = {\n paramsStore: {},\n maxConnections: 3, // maximum number of concurrent uploads\n chunking: {\n enabled: false,\n multiple: {\n enabled: false\n }\n },\n log: function(str, level) {},\n onProgress: function(id, fileName, loaded, total) {},\n onComplete: function(id, fileName, response, xhr) {},\n onCancel: function(id, fileName) {},\n onUploadPrep: function(id) {}, // Called if non-trivial operations will be performed before onUpload\n onUpload: function(id, fileName) {},\n onUploadChunk: function(id, fileName, chunkData) {},\n onUploadChunkSuccess: function(id, chunkData, response, xhr) {},\n onAutoRetry: function(id, fileName, response, xhr) {},\n onResume: function(id, fileName, chunkData) {},\n onUuidChanged: function(id, newUuid) {},\n getName: function(id) {},\n setSize: function(id, newSize) {},\n isQueued: function(id) {},\n getIdsInProxyGroup: function(id) {},\n getIdsInBatch: function(id) {}\n },\n\n chunked = {\n // Called when each chunk has uploaded successfully\n done: function(id, chunkIdx, response, xhr) {\n var chunkData = handler._getChunkData(id, chunkIdx);\n\n handler._getFileState(id).attemptingResume = false;\n\n delete handler._getFileState(id).temp.chunkProgress[chunkIdx];\n handler._getFileState(id).loaded += chunkData.size;\n\n options.onUploadChunkSuccess(id, handler._getChunkDataForCallback(chunkData), response, xhr);\n },\n\n // Called when all chunks have been successfully uploaded and we want to ask the handler to perform any\n // logic associated with closing out the file, such as combining the chunks.\n finalize: function(id) {\n var size = options.getSize(id),\n name = options.getName(id);\n\n log(\"All chunks have been uploaded for \" + id + \" - finalizing....\");\n handler.finalizeChunks(id).then(\n function(response, xhr) {\n log(\"Finalize successful for \" + id);\n\n var normaizedResponse = upload.normalizeResponse(response, true);\n\n options.onProgress(id, name, size, size);\n handler._maybeDeletePersistedChunkData(id);\n upload.cleanup(id, normaizedResponse, xhr);\n },\n function(response, xhr) {\n var normaizedResponse = upload.normalizeResponse(response, false);\n\n log(\"Problem finalizing chunks for file ID \" + id + \" - \" + normaizedResponse.error, \"error\");\n\n if (normaizedResponse.reset) {\n chunked.reset(id);\n }\n\n if (!options.onAutoRetry(id, name, normaizedResponse, xhr)) {\n upload.cleanup(id, normaizedResponse, xhr);\n }\n }\n );\n },\n\n handleFailure: function(chunkIdx, id, response, xhr) {\n var name = options.getName(id);\n\n log(\"Chunked upload request failed for \" + id + \", chunk \" + chunkIdx);\n\n handler.clearCachedChunk(id, chunkIdx);\n\n var responseToReport = upload.normalizeResponse(response, false),\n inProgressIdx;\n\n if (responseToReport.reset) {\n chunked.reset(id);\n }\n else {\n inProgressIdx = qq.indexOf(handler._getFileState(id).chunking.inProgress, chunkIdx);\n if (inProgressIdx >= 0) {\n handler._getFileState(id).chunking.inProgress.splice(inProgressIdx, 1);\n handler._getFileState(id).chunking.remaining.unshift(chunkIdx);\n }\n }\n\n // We may have aborted all other in-progress chunks for this file due to a failure.\n // If so, ignore the failures associated with those aborts.\n if (!handler._getFileState(id).temp.ignoreFailure) {\n // If this chunk has failed, we want to ignore all other failures of currently in-progress\n // chunks since they will be explicitly aborted\n if (concurrentChunkingPossible) {\n handler._getFileState(id).temp.ignoreFailure = true;\n\n log(qq.format(\"Going to attempt to abort these chunks: {}. These are currently in-progress: {}.\", JSON.stringify(Object.keys(handler._getXhrs(id))), JSON.stringify(handler._getFileState(id).chunking.inProgress)));\n qq.each(handler._getXhrs(id), function(ckid, ckXhr) {\n log(qq.format(\"Attempting to abort file {}.{}. XHR readyState {}. \", id, ckid, ckXhr.readyState));\n ckXhr.abort();\n // Flag the transport, in case we are waiting for some other async operation\n // to complete before attempting to upload the chunk\n ckXhr._cancelled = true;\n });\n\n // We must indicate that all aborted chunks are no longer in progress\n handler.moveInProgressToRemaining(id);\n\n // Free up any connections used by these chunks, but don't allow any\n // other files to take up the connections (until we have exhausted all auto-retries)\n connectionManager.free(id, true);\n }\n\n if (!options.onAutoRetry(id, name, responseToReport, xhr)) {\n // If one chunk fails, abort all of the others to avoid odd race conditions that occur\n // if a chunk succeeds immediately after one fails before we have determined if the upload\n // is a failure or not.\n upload.cleanup(id, responseToReport, xhr);\n }\n }\n },\n\n hasMoreParts: function(id) {\n return !!handler._getFileState(id).chunking.remaining.length;\n },\n\n nextPart: function(id) {\n var nextIdx = handler._getFileState(id).chunking.remaining.shift();\n\n if (nextIdx >= handler._getTotalChunks(id)) {\n nextIdx = null;\n }\n\n return nextIdx;\n },\n\n reset: function(id) {\n log(\"Server or callback has ordered chunking effort to be restarted on next attempt for item ID \" + id, \"error\");\n\n handler._maybeDeletePersistedChunkData(id);\n handler.reevaluateChunking(id);\n handler._getFileState(id).loaded = 0;\n },\n\n sendNext: function(id) {\n var size = options.getSize(id),\n name = options.getName(id),\n chunkIdx = chunked.nextPart(id),\n chunkData = handler._getChunkData(id, chunkIdx),\n resuming = handler._getFileState(id).attemptingResume,\n inProgressChunks = handler._getFileState(id).chunking.inProgress || [];\n\n if (handler._getFileState(id).loaded == null) {\n handler._getFileState(id).loaded = 0;\n }\n\n // Don't follow-through with the resume attempt if the integrator returns false from onResume\n if (resuming && options.onResume(id, name, chunkData) === false) {\n chunked.reset(id);\n chunkIdx = chunked.nextPart(id);\n chunkData = handler._getChunkData(id, chunkIdx);\n resuming = false;\n }\n\n // If all chunks have already uploaded successfully, we must be re-attempting the finalize step.\n if (chunkIdx == null && inProgressChunks.length === 0) {\n chunked.finalize(id);\n }\n\n // Send the next chunk\n else {\n log(qq.format(\"Sending chunked upload request for item {}.{}, bytes {}-{} of {}.\", id, chunkIdx, chunkData.start + 1, chunkData.end, size));\n options.onUploadChunk(id, name, handler._getChunkDataForCallback(chunkData));\n inProgressChunks.push(chunkIdx);\n handler._getFileState(id).chunking.inProgress = inProgressChunks;\n\n if (concurrentChunkingPossible) {\n connectionManager.open(id, chunkIdx);\n }\n\n if (concurrentChunkingPossible && connectionManager.available() && handler._getFileState(id).chunking.remaining.length) {\n chunked.sendNext(id);\n }\n\n if (chunkData.blob.size === 0) {\n log(qq.format(\"Chunk {} for file {} will not be uploaded, zero sized chunk.\", chunkIdx, id), \"error\");\n chunked.handleFailure(chunkIdx, id, \"File is no longer available\", null);\n }\n else {\n handler.uploadChunk(id, chunkIdx, resuming).then(\n // upload chunk success\n function success(response, xhr) {\n log(\"Chunked upload request succeeded for \" + id + \", chunk \" + chunkIdx);\n\n handler.clearCachedChunk(id, chunkIdx);\n\n var inProgressChunks = handler._getFileState(id).chunking.inProgress || [],\n responseToReport = upload.normalizeResponse(response, true),\n inProgressChunkIdx = qq.indexOf(inProgressChunks, chunkIdx);\n\n log(qq.format(\"Chunk {} for file {} uploaded successfully.\", chunkIdx, id));\n\n chunked.done(id, chunkIdx, responseToReport, xhr);\n\n if (inProgressChunkIdx >= 0) {\n inProgressChunks.splice(inProgressChunkIdx, 1);\n }\n\n handler._maybePersistChunkedState(id);\n\n if (!chunked.hasMoreParts(id) && inProgressChunks.length === 0) {\n chunked.finalize(id);\n }\n else if (chunked.hasMoreParts(id)) {\n chunked.sendNext(id);\n }\n else {\n log(qq.format(\"File ID {} has no more chunks to send and these chunk indexes are still marked as in-progress: {}\", id, JSON.stringify(inProgressChunks)));\n }\n },\n\n // upload chunk failure\n function failure(response, xhr) {\n chunked.handleFailure(chunkIdx, id, response, xhr);\n }\n )\n .done(function() {\n handler.clearXhr(id, chunkIdx);\n });\n }\n }\n }\n },\n\n connectionManager = {\n _open: [],\n _openChunks: {},\n _waiting: [],\n\n available: function() {\n var max = options.maxConnections,\n openChunkEntriesCount = 0,\n openChunksCount = 0;\n\n qq.each(connectionManager._openChunks, function(fileId, openChunkIndexes) {\n openChunkEntriesCount++;\n openChunksCount += openChunkIndexes.length;\n });\n\n return max - (connectionManager._open.length - openChunkEntriesCount + openChunksCount);\n },\n\n /**\n * Removes element from queue, starts upload of next\n */\n free: function(id, dontAllowNext) {\n var allowNext = !dontAllowNext,\n waitingIndex = qq.indexOf(connectionManager._waiting, id),\n connectionsIndex = qq.indexOf(connectionManager._open, id),\n nextId;\n\n delete connectionManager._openChunks[id];\n\n if (upload.getProxyOrBlob(id) instanceof qq.BlobProxy) {\n log(\"Generated blob upload has ended for \" + id + \", disposing generated blob.\");\n delete handler._getFileState(id).file;\n }\n\n // If this file was not consuming a connection, it was just waiting, so remove it from the waiting array\n if (waitingIndex >= 0) {\n connectionManager._waiting.splice(waitingIndex, 1);\n }\n // If this file was consuming a connection, allow the next file to be uploaded\n else if (allowNext && connectionsIndex >= 0) {\n connectionManager._open.splice(connectionsIndex, 1);\n\n nextId = connectionManager._waiting.shift();\n if (nextId >= 0) {\n connectionManager._open.push(nextId);\n upload.start(nextId);\n }\n }\n },\n\n getWaitingOrConnected: function() {\n var waitingOrConnected = [];\n\n // Chunked files may have multiple connections open per chunk (if concurrent chunking is enabled)\n // We need to grab the file ID of any file that has at least one chunk consuming a connection.\n qq.each(connectionManager._openChunks, function(fileId, chunks) {\n if (chunks && chunks.length) {\n waitingOrConnected.push(parseInt(fileId));\n }\n });\n\n // For non-chunked files, only one connection will be consumed per file.\n // This is where we aggregate those file IDs.\n qq.each(connectionManager._open, function(idx, fileId) {\n if (!connectionManager._openChunks[fileId]) {\n waitingOrConnected.push(parseInt(fileId));\n }\n });\n\n // There may be files waiting for a connection.\n waitingOrConnected = waitingOrConnected.concat(connectionManager._waiting);\n\n return waitingOrConnected;\n },\n\n isUsingConnection: function(id) {\n return qq.indexOf(connectionManager._open, id) >= 0;\n },\n\n open: function(id, chunkIdx) {\n if (chunkIdx == null) {\n connectionManager._waiting.push(id);\n }\n\n if (connectionManager.available()) {\n if (chunkIdx == null) {\n connectionManager._waiting.pop();\n connectionManager._open.push(id);\n }\n else {\n (function() {\n var openChunksEntry = connectionManager._openChunks[id] || [];\n openChunksEntry.push(chunkIdx);\n connectionManager._openChunks[id] = openChunksEntry;\n }());\n }\n\n return true;\n }\n\n return false;\n },\n\n reset: function() {\n connectionManager._waiting = [];\n connectionManager._open = [];\n }\n },\n\n simple = {\n send: function(id, name) {\n handler._getFileState(id).loaded = 0;\n\n log(\"Sending simple upload request for \" + id);\n handler.uploadFile(id).then(\n function(response, optXhr) {\n log(\"Simple upload request succeeded for \" + id);\n\n var responseToReport = upload.normalizeResponse(response, true),\n size = options.getSize(id);\n\n options.onProgress(id, name, size, size);\n upload.maybeNewUuid(id, responseToReport);\n upload.cleanup(id, responseToReport, optXhr);\n },\n\n function(response, optXhr) {\n log(\"Simple upload request failed for \" + id);\n\n var responseToReport = upload.normalizeResponse(response, false);\n\n if (!options.onAutoRetry(id, name, responseToReport, optXhr)) {\n upload.cleanup(id, responseToReport, optXhr);\n }\n }\n );\n }\n },\n\n upload = {\n cancel: function(id) {\n log(\"Cancelling \" + id);\n options.paramsStore.remove(id);\n connectionManager.free(id);\n },\n\n cleanup: function(id, response, optXhr) {\n var name = options.getName(id);\n\n options.onComplete(id, name, response, optXhr);\n\n if (handler._getFileState(id)) {\n handler._clearXhrs && handler._clearXhrs(id);\n }\n\n connectionManager.free(id);\n },\n\n // Returns a qq.BlobProxy, or an actual File/Blob if no proxy is involved, or undefined\n // if none of these are available for the ID\n getProxyOrBlob: function(id) {\n return (handler.getProxy && handler.getProxy(id)) ||\n (handler.getFile && handler.getFile(id));\n },\n\n initHandler: function() {\n var handlerType = namespace ? qq[namespace] : qq.traditional,\n handlerModuleSubtype = qq.supportedFeatures.ajaxUploading ? \"Xhr\" : \"Form\";\n\n handler = new handlerType[handlerModuleSubtype + \"UploadHandler\"](\n options,\n {\n getDataByUuid: options.getDataByUuid,\n getName: options.getName,\n getSize: options.getSize,\n getUuid: options.getUuid,\n log: log,\n onCancel: options.onCancel,\n onProgress: options.onProgress,\n onUuidChanged: options.onUuidChanged\n }\n );\n\n if (handler._removeExpiredChunkingRecords) {\n handler._removeExpiredChunkingRecords();\n }\n },\n\n isDeferredEligibleForUpload: function(id) {\n return options.isQueued(id);\n },\n\n // For Blobs that are part of a group of generated images, along with a reference image,\n // this will ensure the blobs in the group are uploaded in the order they were triggered,\n // even if some async processing must be completed on one or more Blobs first.\n maybeDefer: function(id, blob) {\n // If we don't have a file/blob yet & no file/blob exists for this item, request it,\n // and then submit the upload to the specific handler once the blob is available.\n // ASSUMPTION: This condition will only ever be true if XHR uploading is supported.\n if (blob && !handler.getFile(id) && blob instanceof qq.BlobProxy) {\n\n // Blob creation may take some time, so the caller may want to update the\n // UI to indicate that an operation is in progress, even before the actual\n // upload begins and an onUpload callback is invoked.\n options.onUploadPrep(id);\n\n log(\"Attempting to generate a blob on-demand for \" + id);\n blob.create().then(function(generatedBlob) {\n log(\"Generated an on-demand blob for \" + id);\n\n // Update record associated with this file by providing the generated Blob\n handler.updateBlob(id, generatedBlob);\n\n // Propagate the size for this generated Blob\n options.setSize(id, generatedBlob.size);\n\n // Order handler to recalculate chunking possibility, if applicable\n handler.reevaluateChunking(id);\n\n upload.maybeSendDeferredFiles(id);\n },\n\n // Blob could not be generated. Fail the upload & attempt to prevent retries. Also bubble error message.\n function(errorMessage) {\n var errorResponse = {};\n\n if (errorMessage) {\n errorResponse.error = errorMessage;\n }\n\n log(qq.format(\"Failed to generate blob for ID {}. Error message: {}.\", id, errorMessage), \"error\");\n\n options.onComplete(id, options.getName(id), qq.extend(errorResponse, preventRetryResponse), null);\n upload.maybeSendDeferredFiles(id);\n connectionManager.free(id);\n });\n }\n else {\n return upload.maybeSendDeferredFiles(id);\n }\n\n return false;\n },\n\n // Upload any grouped blobs, in the proper order, that are ready to be uploaded\n maybeSendDeferredFiles: function(id) {\n var idsInGroup = options.getIdsInProxyGroup(id),\n uploadedThisId = false;\n\n if (idsInGroup && idsInGroup.length) {\n log(\"Maybe ready to upload proxy group file \" + id);\n\n qq.each(idsInGroup, function(idx, idInGroup) {\n if (upload.isDeferredEligibleForUpload(idInGroup) && !!handler.getFile(idInGroup)) {\n uploadedThisId = idInGroup === id;\n upload.now(idInGroup);\n }\n else if (upload.isDeferredEligibleForUpload(idInGroup)) {\n return false;\n }\n });\n }\n else {\n uploadedThisId = true;\n upload.now(id);\n }\n\n return uploadedThisId;\n },\n\n maybeNewUuid: function(id, response) {\n if (response.newUuid !== undefined) {\n options.onUuidChanged(id, response.newUuid);\n }\n },\n\n // The response coming from handler implementations may be in various formats.\n // Instead of hoping a promise nested 5 levels deep will always return an object\n // as its first param, let's just normalize the response here.\n normalizeResponse: function(originalResponse, successful) {\n var response = originalResponse;\n\n // The passed \"response\" param may not be a response at all.\n // It could be a string, detailing the error, for example.\n if (!qq.isObject(originalResponse)) {\n response = {};\n\n if (qq.isString(originalResponse) && !successful) {\n response.error = originalResponse;\n }\n }\n\n response.success = successful;\n\n return response;\n },\n\n now: function(id) {\n var name = options.getName(id);\n\n if (!controller.isValid(id)) {\n throw new qq.Error(id + \" is not a valid file ID to upload!\");\n }\n\n options.onUpload(id, name);\n\n if (chunkingPossible && handler._shouldChunkThisFile(id)) {\n chunked.sendNext(id);\n }\n else {\n simple.send(id, name);\n }\n },\n\n start: function(id) {\n var blobToUpload = upload.getProxyOrBlob(id);\n\n if (blobToUpload) {\n return upload.maybeDefer(id, blobToUpload);\n }\n else {\n upload.now(id);\n return true;\n }\n }\n };\n\n qq.extend(this, {\n /**\n * Adds file or file input to the queue\n **/\n add: function(id, file) {\n handler.add.apply(this, arguments);\n },\n\n /**\n * Sends the file identified by id\n */\n upload: function(id) {\n if (connectionManager.open(id)) {\n return upload.start(id);\n }\n return false;\n },\n\n retry: function(id) {\n // On retry, if concurrent chunking has been enabled, we may have aborted all other in-progress chunks\n // for a file when encountering a failed chunk upload. We then signaled the controller to ignore\n // all failures associated with these aborts. We are now retrying, so we don't want to ignore\n // any more failures at this point.\n if (concurrentChunkingPossible) {\n handler._getFileState(id).temp.ignoreFailure = false;\n }\n\n // If we are attempting to retry a file that is already consuming a connection, this is likely an auto-retry.\n // Just go ahead and ask the handler to upload again.\n if (connectionManager.isUsingConnection(id)) {\n return upload.start(id);\n }\n\n // If we are attempting to retry a file that is not currently consuming a connection,\n // this is likely a manual retry attempt. We will need to ensure a connection is available\n // before the retry commences.\n else {\n return controller.upload(id);\n }\n },\n\n /**\n * Cancels file upload by id\n */\n cancel: function(id) {\n var cancelRetVal = handler.cancel(id);\n\n if (qq.isGenericPromise(cancelRetVal)) {\n cancelRetVal.then(function() {\n upload.cancel(id);\n });\n }\n else if (cancelRetVal !== false) {\n upload.cancel(id);\n }\n },\n\n /**\n * Cancels all queued or in-progress uploads\n */\n cancelAll: function() {\n var waitingOrConnected = connectionManager.getWaitingOrConnected(),\n i;\n\n // ensure files are cancelled in reverse order which they were added\n // to avoid a flash of time where a queued file begins to upload before it is canceled\n if (waitingOrConnected.length) {\n for (i = waitingOrConnected.length - 1; i >= 0; i--) {\n controller.cancel(waitingOrConnected[i]);\n }\n }\n\n connectionManager.reset();\n },\n\n // Returns a File, Blob, or the Blob/File for the reference/parent file if the targeted blob is a proxy.\n // Undefined if no file record is available.\n getFile: function(id) {\n if (handler.getProxy && handler.getProxy(id)) {\n return handler.getProxy(id).referenceBlob;\n }\n\n return handler.getFile && handler.getFile(id);\n },\n\n // Returns true if the Blob associated with the ID is related to a proxy s\n isProxied: function(id) {\n return !!(handler.getProxy && handler.getProxy(id));\n },\n\n getInput: function(id) {\n if (handler.getInput) {\n return handler.getInput(id);\n }\n },\n\n reset: function() {\n log(\"Resetting upload handler\");\n controller.cancelAll();\n connectionManager.reset();\n handler.reset();\n },\n\n expunge: function(id) {\n if (controller.isValid(id)) {\n return handler.expunge(id);\n }\n },\n\n /**\n * Determine if the file exists.\n */\n isValid: function(id) {\n return handler.isValid(id);\n },\n\n getResumableFilesData: function() {\n if (handler.getResumableFilesData) {\n return handler.getResumableFilesData();\n }\n return [];\n },\n\n /**\n * This may or may not be implemented, depending on the handler. For handlers where a third-party ID is\n * available (such as the \"key\" for Amazon S3), this will return that value. Otherwise, the return value\n * will be undefined.\n *\n * @param id Internal file ID\n * @returns {*} Some identifier used by a 3rd-party service involved in the upload process\n */\n getThirdPartyFileId: function(id) {\n if (controller.isValid(id)) {\n return handler.getThirdPartyFileId(id);\n }\n },\n\n /**\n * Attempts to pause the associated upload if the specific handler supports this and the file is \"valid\".\n * @param id ID of the upload/file to pause\n * @returns {boolean} true if the upload was paused\n */\n pause: function(id) {\n if (controller.isResumable(id) && handler.pause && controller.isValid(id) && handler.pause(id)) {\n connectionManager.free(id);\n handler.moveInProgressToRemaining(id);\n return true;\n }\n return false;\n },\n\n // True if the file is eligible for pause/resume.\n isResumable: function(id) {\n return !!handler.isResumable && handler.isResumable(id);\n }\n });\n\n qq.extend(options, o);\n log = options.log;\n chunkingPossible = options.chunking.enabled && qq.supportedFeatures.chunking;\n concurrentChunkingPossible = chunkingPossible && options.chunking.concurrent.enabled;\n\n preventRetryResponse = (function() {\n var response = {};\n\n response[options.preventRetryParam] = true;\n\n return response;\n }());\n\n upload.initHandler();\n};\n","/*globals qq */\n/*jshint -W117 */\nqq.WindowReceiveMessage = function(o) {\n \"use strict\";\n\n var options = {\n log: function(message, level) {}\n },\n callbackWrapperDetachers = {};\n\n qq.extend(options, o);\n\n qq.extend(this, {\n receiveMessage: function(id, callback) {\n var onMessageCallbackWrapper = function(event) {\n callback(event.data);\n };\n\n if (window.postMessage) {\n callbackWrapperDetachers[id] = qq(window).attach(\"message\", onMessageCallbackWrapper);\n }\n else {\n log(\"iframe message passing not supported in this browser!\", \"error\");\n }\n },\n\n stopReceivingMessages: function(id) {\n if (window.postMessage) {\n var detacher = callbackWrapperDetachers[id];\n if (detacher) {\n detacher();\n }\n }\n }\n });\n};\n","/* globals qq */\n/**\n * Common APIs exposed to creators of upload via form/iframe handlers. This is reused and possibly overridden\n * in some cases by specific form upload handlers.\n *\n * @constructor\n */\nqq.FormUploadHandler = function(spec) {\n \"use strict\";\n\n var options = spec.options,\n handler = this,\n proxy = spec.proxy,\n formHandlerInstanceId = qq.getUniqueId(),\n onloadCallbacks = {},\n detachLoadEvents = {},\n postMessageCallbackTimers = {},\n isCors = options.isCors,\n inputName = options.inputName,\n getUuid = proxy.getUuid,\n log = proxy.log,\n corsMessageReceiver = new qq.WindowReceiveMessage({log: log});\n\n /**\n * Remove any trace of the file from the handler.\n *\n * @param id ID of the associated file\n */\n function expungeFile(id) {\n delete detachLoadEvents[id];\n\n // If we are dealing with CORS, we might still be waiting for a response from a loaded iframe.\n // In that case, terminate the timer waiting for a message from the loaded iframe\n // and stop listening for any more messages coming from this iframe.\n if (isCors) {\n clearTimeout(postMessageCallbackTimers[id]);\n delete postMessageCallbackTimers[id];\n corsMessageReceiver.stopReceivingMessages(id);\n }\n\n var iframe = document.getElementById(handler._getIframeName(id));\n if (iframe) {\n // To cancel request set src to something else. We use src=\"javascript:false;\"\n // because it doesn't trigger ie6 prompt on https\n /* jshint scripturl:true */\n iframe.setAttribute(\"src\", \"javascript:false;\");\n\n qq(iframe).remove();\n }\n }\n\n /**\n * @param iframeName `document`-unique Name of the associated iframe\n * @returns {*} ID of the associated file\n */\n function getFileIdForIframeName(iframeName) {\n return iframeName.split(\"_\")[0];\n }\n\n /**\n * Generates an iframe to be used as a target for upload-related form submits. This also adds the iframe\n * to the current `document`. Note that the iframe is hidden from view.\n *\n * @param name Name of the iframe.\n * @returns {HTMLIFrameElement} The created iframe\n */\n function initIframeForUpload(name) {\n var iframe = qq.toElement(\"\");\n\n iframe.setAttribute(\"id\", name);\n\n iframe.style.display = \"none\";\n document.body.appendChild(iframe);\n\n return iframe;\n }\n\n /**\n * If we are in CORS mode, we must listen for messages (containing the server response) from the associated\n * iframe, since we cannot directly parse the content of the iframe due to cross-origin restrictions.\n *\n * @param iframe Listen for messages on this iframe.\n * @param callback Invoke this callback with the message from the iframe.\n */\n function registerPostMessageCallback(iframe, callback) {\n var iframeName = iframe.id,\n fileId = getFileIdForIframeName(iframeName),\n uuid = getUuid(fileId);\n\n onloadCallbacks[uuid] = callback;\n\n // When the iframe has loaded (after the server responds to an upload request)\n // declare the attempt a failure if we don't receive a valid message shortly after the response comes in.\n detachLoadEvents[fileId] = qq(iframe).attach(\"load\", function() {\n if (handler.getInput(fileId)) {\n log(\"Received iframe load event for CORS upload request (iframe name \" + iframeName + \")\");\n\n postMessageCallbackTimers[iframeName] = setTimeout(function() {\n var errorMessage = \"No valid message received from loaded iframe for iframe name \" + iframeName;\n log(errorMessage, \"error\");\n callback({\n error: errorMessage\n });\n }, 1000);\n }\n });\n\n // Listen for messages coming from this iframe. When a message has been received, cancel the timer\n // that declares the upload a failure if a message is not received within a reasonable amount of time.\n corsMessageReceiver.receiveMessage(iframeName, function(message) {\n log(\"Received the following window message: '\" + message + \"'\");\n var fileId = getFileIdForIframeName(iframeName),\n response = handler._parseJsonResponse(message),\n uuid = response.uuid,\n onloadCallback;\n\n if (uuid && onloadCallbacks[uuid]) {\n log(\"Handling response for iframe name \" + iframeName);\n clearTimeout(postMessageCallbackTimers[iframeName]);\n delete postMessageCallbackTimers[iframeName];\n\n handler._detachLoadEvent(iframeName);\n\n onloadCallback = onloadCallbacks[uuid];\n\n delete onloadCallbacks[uuid];\n corsMessageReceiver.stopReceivingMessages(iframeName);\n onloadCallback(response);\n }\n else if (!uuid) {\n log(\"'\" + message + \"' does not contain a UUID - ignoring.\");\n }\n });\n }\n\n qq.extend(this, new qq.UploadHandler(spec));\n\n qq.override(this, function(super_) {\n return {\n /**\n * Adds File or Blob to the queue\n **/\n add: function(id, fileInput) {\n super_.add(id, {input: fileInput});\n\n fileInput.setAttribute(\"name\", inputName);\n\n // remove file input from DOM\n if (fileInput.parentNode) {\n qq(fileInput).remove();\n }\n },\n\n expunge: function(id) {\n expungeFile(id);\n super_.expunge(id);\n },\n\n isValid: function(id) {\n return super_.isValid(id) &&\n handler._getFileState(id).input !== undefined;\n }\n };\n });\n\n qq.extend(this, {\n getInput: function(id) {\n return handler._getFileState(id).input;\n },\n\n /**\n * This function either delegates to a more specific message handler if CORS is involved,\n * or simply registers a callback when the iframe has been loaded that invokes the passed callback\n * after determining if the content of the iframe is accessible.\n *\n * @param iframe Associated iframe\n * @param callback Callback to invoke after we have determined if the iframe content is accessible.\n */\n _attachLoadEvent: function(iframe, callback) {\n /*jslint eqeq: true*/\n var responseDescriptor;\n\n if (isCors) {\n registerPostMessageCallback(iframe, callback);\n }\n else {\n detachLoadEvents[iframe.id] = qq(iframe).attach(\"load\", function() {\n log(\"Received response for \" + iframe.id);\n\n // when we remove iframe from dom\n // the request stops, but in IE load\n // event fires\n if (!iframe.parentNode) {\n return;\n }\n\n try {\n // fixing Opera 10.53\n if (iframe.contentDocument &&\n iframe.contentDocument.body &&\n iframe.contentDocument.body.innerHTML == \"false\") {\n // In Opera event is fired second time\n // when body.innerHTML changed from false\n // to server response approx. after 1 sec\n // when we upload file with iframe\n return;\n }\n }\n catch (error) {\n //IE may throw an \"access is denied\" error when attempting to access contentDocument on the iframe in some cases\n log(\"Error when attempting to access iframe during handling of upload response (\" + error.message + \")\", \"error\");\n responseDescriptor = {success: false};\n }\n\n callback(responseDescriptor);\n });\n }\n },\n\n /**\n * Creates an iframe with a specific document-unique name.\n *\n * @param id ID of the associated file\n * @returns {HTMLIFrameElement}\n */\n _createIframe: function(id) {\n var iframeName = handler._getIframeName(id);\n\n return initIframeForUpload(iframeName);\n },\n\n /**\n * Called when we are no longer interested in being notified when an iframe has loaded.\n *\n * @param id Associated file ID\n */\n _detachLoadEvent: function(id) {\n if (detachLoadEvents[id] !== undefined) {\n detachLoadEvents[id]();\n delete detachLoadEvents[id];\n }\n },\n\n /**\n * @param fileId ID of the associated file\n * @returns {string} The `document`-unique name of the iframe\n */\n _getIframeName: function(fileId) {\n return fileId + \"_\" + formHandlerInstanceId;\n },\n\n /**\n * Generates a form element and appends it to the `document`. When the form is submitted, a specific iframe is targeted.\n * The name of the iframe is passed in as a property of the spec parameter, and must be unique in the `document`. Note\n * that the form is hidden from view.\n *\n * @param spec An object containing various properties to be used when constructing the form. Required properties are\n * currently: `method`, `endpoint`, `params`, `paramsInBody`, and `targetName`.\n * @returns {HTMLFormElement} The created form\n */\n _initFormForUpload: function(spec) {\n var method = spec.method,\n endpoint = spec.endpoint,\n params = spec.params,\n paramsInBody = spec.paramsInBody,\n targetName = spec.targetName,\n form = qq.toElement(\" \"),\n url = endpoint;\n\n if (paramsInBody) {\n qq.obj2Inputs(params, form);\n }\n else {\n url = qq.obj2url(params, endpoint);\n }\n\n form.setAttribute(\"action\", url);\n form.setAttribute(\"target\", targetName);\n form.style.display = \"none\";\n document.body.appendChild(form);\n\n return form;\n },\n\n /**\n * @param innerHtmlOrMessage JSON message\n * @returns {*} The parsed response, or an empty object if the response could not be parsed\n */\n _parseJsonResponse: function(innerHtmlOrMessage) {\n var response = {};\n\n try {\n response = qq.parseJson(innerHtmlOrMessage);\n }\n catch (error) {\n log(\"Error when attempting to parse iframe upload response (\" + error.message + \")\", \"error\");\n }\n\n return response;\n }\n });\n};\n","/* globals qq */\n/**\n * Common API exposed to creators of XHR handlers. This is reused and possibly overriding in some cases by specific\n * XHR upload handlers.\n *\n * @constructor\n */\nqq.XhrUploadHandler = function(spec) {\n \"use strict\";\n\n var handler = this,\n namespace = spec.options.namespace,\n proxy = spec.proxy,\n chunking = spec.options.chunking,\n resume = spec.options.resume,\n chunkFiles = chunking && spec.options.chunking.enabled && qq.supportedFeatures.chunking,\n resumeEnabled = resume && spec.options.resume.enabled && chunkFiles && qq.supportedFeatures.resume,\n getName = proxy.getName,\n getSize = proxy.getSize,\n getUuid = proxy.getUuid,\n getEndpoint = proxy.getEndpoint,\n getDataByUuid = proxy.getDataByUuid,\n onUuidChanged = proxy.onUuidChanged,\n onProgress = proxy.onProgress,\n log = proxy.log;\n\n function abort(id) {\n qq.each(handler._getXhrs(id), function(xhrId, xhr) {\n var ajaxRequester = handler._getAjaxRequester(id, xhrId);\n\n xhr.onreadystatechange = null;\n xhr.upload.onprogress = null;\n xhr.abort();\n ajaxRequester && ajaxRequester.canceled && ajaxRequester.canceled(id);\n });\n }\n\n qq.extend(this, new qq.UploadHandler(spec));\n\n qq.override(this, function(super_) {\n return {\n /**\n * Adds File or Blob to the queue\n **/\n add: function(id, blobOrProxy) {\n if (qq.isFile(blobOrProxy) || qq.isBlob(blobOrProxy)) {\n super_.add(id, {file: blobOrProxy});\n }\n else if (blobOrProxy instanceof qq.BlobProxy) {\n super_.add(id, {proxy: blobOrProxy});\n }\n else {\n throw new Error(\"Passed obj is not a File, Blob, or proxy\");\n }\n\n handler._initTempState(id);\n resumeEnabled && handler._maybePrepareForResume(id);\n },\n\n expunge: function(id) {\n abort(id);\n handler._maybeDeletePersistedChunkData(id);\n handler._clearXhrs(id);\n super_.expunge(id);\n }\n };\n });\n\n qq.extend(this, {\n // Clear the cached chunk `Blob` after we are done with it, just in case the `Blob` bytes are stored in memory.\n clearCachedChunk: function(id, chunkIdx) {\n delete handler._getFileState(id).temp.cachedChunks[chunkIdx];\n },\n\n clearXhr: function(id, chunkIdx) {\n var tempState = handler._getFileState(id).temp;\n\n if (tempState.xhrs) {\n delete tempState.xhrs[chunkIdx];\n }\n if (tempState.ajaxRequesters) {\n delete tempState.ajaxRequesters[chunkIdx];\n }\n },\n\n // Called when all chunks have been successfully uploaded. Expected promissory return type.\n // This defines the default behavior if nothing further is required when all chunks have been uploaded.\n finalizeChunks: function(id, responseParser) {\n var lastChunkIdx = handler._getTotalChunks(id) - 1,\n xhr = handler._getXhr(id, lastChunkIdx);\n\n if (responseParser) {\n return new qq.Promise().success(responseParser(xhr), xhr);\n }\n\n return new qq.Promise().success({}, xhr);\n },\n\n getFile: function(id) {\n return handler.isValid(id) && handler._getFileState(id).file;\n },\n\n getProxy: function(id) {\n return handler.isValid(id) && handler._getFileState(id).proxy;\n },\n\n /**\n * @returns {Array} Array of objects containing properties useful to integrators\n * when it is important to determine which files are potentially resumable.\n */\n getResumableFilesData: function() {\n var resumableFilesData = [];\n\n handler._iterateResumeRecords(function(key, uploadData) {\n handler.moveInProgressToRemaining(null, uploadData.chunking.inProgress, uploadData.chunking.remaining);\n\n var data = {\n name: uploadData.name,\n remaining: uploadData.chunking.remaining,\n size: uploadData.size,\n uuid: uploadData.uuid\n };\n\n if (uploadData.key) {\n data.key = uploadData.key;\n }\n\n resumableFilesData.push(data);\n });\n\n return resumableFilesData;\n },\n\n isResumable: function(id) {\n return !!chunking && handler.isValid(id) && !handler._getFileState(id).notResumable;\n },\n\n moveInProgressToRemaining: function(id, optInProgress, optRemaining) {\n var inProgress = optInProgress || handler._getFileState(id).chunking.inProgress,\n remaining = optRemaining || handler._getFileState(id).chunking.remaining;\n\n if (inProgress) {\n log(qq.format(\"Moving these chunks from in-progress {}, to remaining.\", JSON.stringify(inProgress)));\n inProgress.reverse();\n qq.each(inProgress, function(idx, chunkIdx) {\n remaining.unshift(chunkIdx);\n });\n inProgress.length = 0;\n }\n },\n\n pause: function(id) {\n if (handler.isValid(id)) {\n log(qq.format(\"Aborting XHR upload for {} '{}' due to pause instruction.\", id, getName(id)));\n handler._getFileState(id).paused = true;\n abort(id);\n return true;\n }\n },\n\n reevaluateChunking: function(id) {\n if (chunking && handler.isValid(id)) {\n var state = handler._getFileState(id),\n totalChunks,\n i;\n\n delete state.chunking;\n\n state.chunking = {};\n totalChunks = handler._getTotalChunks(id);\n if (totalChunks > 1 || chunking.mandatory) {\n state.chunking.enabled = true;\n state.chunking.parts = totalChunks;\n state.chunking.remaining = [];\n\n for (i = 0; i < totalChunks; i++) {\n state.chunking.remaining.push(i);\n }\n\n handler._initTempState(id);\n }\n else {\n state.chunking.enabled = false;\n }\n }\n },\n\n updateBlob: function(id, newBlob) {\n if (handler.isValid(id)) {\n handler._getFileState(id).file = newBlob;\n }\n },\n\n _clearXhrs: function(id) {\n var tempState = handler._getFileState(id).temp;\n\n qq.each(tempState.ajaxRequesters, function(chunkId) {\n delete tempState.ajaxRequesters[chunkId];\n });\n\n qq.each(tempState.xhrs, function(chunkId) {\n delete tempState.xhrs[chunkId];\n });\n },\n\n /**\n * Creates an XHR instance for this file and stores it in the fileState.\n *\n * @param id File ID\n * @param optChunkIdx The chunk index associated with this XHR, if applicable\n * @returns {XMLHttpRequest}\n */\n _createXhr: function(id, optChunkIdx) {\n return handler._registerXhr(id, optChunkIdx, qq.createXhrInstance());\n },\n\n _getAjaxRequester: function(id, optChunkIdx) {\n var chunkIdx = optChunkIdx == null ? -1 : optChunkIdx;\n return handler._getFileState(id).temp.ajaxRequesters[chunkIdx];\n },\n\n _getChunkData: function(id, chunkIndex) {\n var chunkSize = chunking.partSize,\n fileSize = getSize(id),\n fileOrBlob = handler.getFile(id),\n startBytes = chunkSize * chunkIndex,\n endBytes = startBytes + chunkSize >= fileSize ? fileSize : startBytes + chunkSize,\n totalChunks = handler._getTotalChunks(id),\n cachedChunks = this._getFileState(id).temp.cachedChunks,\n\n // To work around a Webkit GC bug, we must keep each chunk `Blob` in scope until we are done with it.\n // See https://github.com/Widen/fine-uploader/issues/937#issuecomment-41418760\n blob = cachedChunks[chunkIndex] || qq.sliceBlob(fileOrBlob, startBytes, endBytes);\n\n cachedChunks[chunkIndex] = blob;\n\n return {\n part: chunkIndex,\n start: startBytes,\n end: endBytes,\n count: totalChunks,\n blob: blob,\n size: endBytes - startBytes\n };\n },\n\n _getChunkDataForCallback: function(chunkData) {\n return {\n partIndex: chunkData.part,\n startByte: chunkData.start + 1,\n endByte: chunkData.end,\n totalParts: chunkData.count\n };\n },\n\n /**\n * @param id File ID\n * @returns {string} Identifier for this item that may appear in the browser's local storage\n */\n _getLocalStorageId: function(id) {\n var formatVersion = \"5.0\",\n name = getName(id),\n size = getSize(id),\n chunkSize = chunking.partSize,\n endpoint = getEndpoint(id);\n\n return qq.format(\"qq{}resume{}-{}-{}-{}-{}\", namespace, formatVersion, name, size, chunkSize, endpoint);\n },\n\n _getMimeType: function(id) {\n return handler.getFile(id).type;\n },\n\n _getPersistableData: function(id) {\n return handler._getFileState(id).chunking;\n },\n\n /**\n * @param id ID of the associated file\n * @returns {number} Number of parts this file can be divided into, or undefined if chunking is not supported in this UA\n */\n _getTotalChunks: function(id) {\n if (chunking) {\n var fileSize = getSize(id),\n chunkSize = chunking.partSize;\n\n return Math.ceil(fileSize / chunkSize);\n }\n },\n\n _getXhr: function(id, optChunkIdx) {\n var chunkIdx = optChunkIdx == null ? -1 : optChunkIdx;\n return handler._getFileState(id).temp.xhrs[chunkIdx];\n },\n\n _getXhrs: function(id) {\n return handler._getFileState(id).temp.xhrs;\n },\n\n // Iterates through all XHR handler-created resume records (in local storage),\n // invoking the passed callback and passing in the key and value of each local storage record.\n _iterateResumeRecords: function(callback) {\n if (resumeEnabled) {\n qq.each(localStorage, function(key, item) {\n if (key.indexOf(qq.format(\"qq{}resume\", namespace)) === 0) {\n var uploadData = JSON.parse(item);\n callback(key, uploadData);\n }\n });\n }\n },\n\n _initTempState: function(id) {\n handler._getFileState(id).temp = {\n ajaxRequesters: {},\n chunkProgress: {},\n xhrs: {},\n cachedChunks: {}\n };\n },\n\n _markNotResumable: function(id) {\n handler._getFileState(id).notResumable = true;\n },\n\n // Removes a chunked upload record from local storage, if possible.\n // Returns true if the item was removed, false otherwise.\n _maybeDeletePersistedChunkData: function(id) {\n var localStorageId;\n\n if (resumeEnabled && handler.isResumable(id)) {\n localStorageId = handler._getLocalStorageId(id);\n\n if (localStorageId && localStorage.getItem(localStorageId)) {\n localStorage.removeItem(localStorageId);\n return true;\n }\n }\n\n return false;\n },\n\n // If this is a resumable upload, grab the relevant data from storage and items in memory that track this upload\n // so we can pick up from where we left off.\n _maybePrepareForResume: function(id) {\n var state = handler._getFileState(id),\n localStorageId, persistedData;\n\n // Resume is enabled and possible and this is the first time we've tried to upload this file in this session,\n // so prepare for a resume attempt.\n if (resumeEnabled && state.key === undefined) {\n localStorageId = handler._getLocalStorageId(id);\n persistedData = localStorage.getItem(localStorageId);\n\n // If we found this item in local storage, maybe we should resume it.\n if (persistedData) {\n persistedData = JSON.parse(persistedData);\n\n // If we found a resume record but we have already handled this file in this session,\n // don't try to resume it & ensure we don't persist future check data\n if (getDataByUuid(persistedData.uuid)) {\n handler._markNotResumable(id);\n }\n else {\n log(qq.format(\"Identified file with ID {} and name of {} as resumable.\", id, getName(id)));\n\n onUuidChanged(id, persistedData.uuid);\n\n state.key = persistedData.key;\n state.chunking = persistedData.chunking;\n state.loaded = persistedData.loaded;\n state.attemptingResume = true;\n\n handler.moveInProgressToRemaining(id);\n }\n }\n }\n },\n\n // Persist any data needed to resume this upload in a new session.\n _maybePersistChunkedState: function(id) {\n var state = handler._getFileState(id),\n localStorageId, persistedData;\n\n // If local storage isn't supported by the browser, or if resume isn't enabled or possible, give up\n if (resumeEnabled && handler.isResumable(id)) {\n localStorageId = handler._getLocalStorageId(id);\n\n persistedData = {\n name: getName(id),\n size: getSize(id),\n uuid: getUuid(id),\n key: state.key,\n chunking: state.chunking,\n loaded: state.loaded,\n lastUpdated: Date.now()\n };\n\n try {\n localStorage.setItem(localStorageId, JSON.stringify(persistedData));\n }\n catch (error) {\n log(qq.format(\"Unable to save resume data for '{}' due to error: '{}'.\", id, error.toString()), \"warn\");\n }\n }\n },\n\n _registerProgressHandler: function(id, chunkIdx, chunkSize) {\n var xhr = handler._getXhr(id, chunkIdx),\n name = getName(id),\n progressCalculator = {\n simple: function(loaded, total) {\n var fileSize = getSize(id);\n\n if (loaded === total) {\n onProgress(id, name, fileSize, fileSize);\n }\n else {\n onProgress(id, name, (loaded >= fileSize ? fileSize - 1 : loaded), fileSize);\n }\n },\n\n chunked: function(loaded, total) {\n var chunkProgress = handler._getFileState(id).temp.chunkProgress,\n totalSuccessfullyLoadedForFile = handler._getFileState(id).loaded,\n loadedForRequest = loaded,\n totalForRequest = total,\n totalFileSize = getSize(id),\n estActualChunkLoaded = loadedForRequest - (totalForRequest - chunkSize),\n totalLoadedForFile = totalSuccessfullyLoadedForFile;\n\n chunkProgress[chunkIdx] = estActualChunkLoaded;\n\n qq.each(chunkProgress, function(chunkIdx, chunkLoaded) {\n totalLoadedForFile += chunkLoaded;\n });\n\n onProgress(id, name, totalLoadedForFile, totalFileSize);\n }\n };\n\n xhr.upload.onprogress = function(e) {\n if (e.lengthComputable) {\n /* jshint eqnull: true */\n var type = chunkSize == null ? \"simple\" : \"chunked\";\n progressCalculator[type](e.loaded, e.total);\n }\n };\n },\n\n /**\n * Registers an XHR transport instance created elsewhere.\n *\n * @param id ID of the associated file\n * @param optChunkIdx The chunk index associated with this XHR, if applicable\n * @param xhr XMLHttpRequest object instance\n * @param optAjaxRequester `qq.AjaxRequester` associated with this request, if applicable.\n * @returns {XMLHttpRequest}\n */\n _registerXhr: function(id, optChunkIdx, xhr, optAjaxRequester) {\n var xhrsId = optChunkIdx == null ? -1 : optChunkIdx,\n tempState = handler._getFileState(id).temp;\n\n tempState.xhrs = tempState.xhrs || {};\n tempState.ajaxRequesters = tempState.ajaxRequesters || {};\n\n tempState.xhrs[xhrsId] = xhr;\n\n if (optAjaxRequester) {\n tempState.ajaxRequesters[xhrsId] = optAjaxRequester;\n }\n\n return xhr;\n },\n\n // Deletes any local storage records that are \"expired\".\n _removeExpiredChunkingRecords: function() {\n var expirationDays = resume.recordsExpireIn;\n\n handler._iterateResumeRecords(function(key, uploadData) {\n var expirationDate = new Date(uploadData.lastUpdated);\n\n // transform updated date into expiration date\n expirationDate.setDate(expirationDate.getDate() + expirationDays);\n\n if (expirationDate.getTime() <= Date.now()) {\n log(\"Removing expired resume record with key \" + key);\n localStorage.removeItem(key);\n }\n });\n },\n\n /**\n * Determine if the associated file should be chunked.\n *\n * @param id ID of the associated file\n * @returns {*} true if chunking is enabled, possible, and the file can be split into more than 1 part\n */\n _shouldChunkThisFile: function(id) {\n var state = handler._getFileState(id);\n\n if (!state.chunking) {\n handler.reevaluateChunking(id);\n }\n\n return state.chunking.enabled;\n }\n });\n};\n","/*globals qq, XMLHttpRequest*/\nqq.DeleteFileAjaxRequester = function(o) {\n \"use strict\";\n\n var requester,\n options = {\n method: \"DELETE\",\n uuidParamName: \"qquuid\",\n endpointStore: {},\n maxConnections: 3,\n customHeaders: function(id) {return {};},\n paramsStore: {},\n cors: {\n expected: false,\n sendCredentials: false\n },\n log: function(str, level) {},\n onDelete: function(id) {},\n onDeleteComplete: function(id, xhrOrXdr, isError) {}\n };\n\n qq.extend(options, o);\n\n function getMandatedParams() {\n if (options.method.toUpperCase() === \"POST\") {\n return {\n _method: \"DELETE\"\n };\n }\n\n return {};\n }\n\n requester = qq.extend(this, new qq.AjaxRequester({\n acceptHeader: \"application/json\",\n validMethods: [\"POST\", \"DELETE\"],\n method: options.method,\n endpointStore: options.endpointStore,\n paramsStore: options.paramsStore,\n mandatedParams: getMandatedParams(),\n maxConnections: options.maxConnections,\n customHeaders: function(id) {\n return options.customHeaders.get(id);\n },\n log: options.log,\n onSend: options.onDelete,\n onComplete: options.onDeleteComplete,\n cors: options.cors\n }));\n\n qq.extend(this, {\n sendDelete: function(id, uuid, additionalMandatedParams) {\n var additionalOptions = additionalMandatedParams || {};\n\n options.log(\"Submitting delete file request for \" + id);\n\n if (options.method === \"DELETE\") {\n requester.initTransport(id)\n .withPath(uuid)\n .withParams(additionalOptions)\n .send();\n }\n else {\n additionalOptions[options.uuidParamName] = uuid;\n requester.initTransport(id)\n .withParams(additionalOptions)\n .send();\n }\n }\n });\n};\n","/*global qq, define */\n/*jshint strict:false,bitwise:false,nonew:false,asi:true,-W064,-W116,-W089 */\n/**\n * Mega pixel image rendering library for iOS6+\n *\n * Fixes iOS6+'s image file rendering issue for large size image (over mega-pixel),\n * which causes unexpected subsampling when drawing it in canvas.\n * By using this library, you can safely render the image with proper stretching.\n *\n * Copyright (c) 2012 Shinichi Tomita \n * Released under the MIT license\n *\n * Heavily modified by Widen for Fine Uploader\n */\n(function() {\n\n /**\n * Detect subsampling in loaded image.\n * In iOS, larger images than 2M pixels may be subsampled in rendering.\n */\n function detectSubsampling(img) {\n var iw = img.naturalWidth,\n ih = img.naturalHeight,\n canvas = document.createElement(\"canvas\"),\n ctx;\n\n if (iw * ih > 1024 * 1024) { // subsampling may happen over megapixel image\n canvas.width = canvas.height = 1;\n ctx = canvas.getContext(\"2d\");\n ctx.drawImage(img, -iw + 1, 0);\n // subsampled image becomes half smaller in rendering size.\n // check alpha channel value to confirm image is covering edge pixel or not.\n // if alpha value is 0 image is not covering, hence subsampled.\n return ctx.getImageData(0, 0, 1, 1).data[3] === 0;\n } else {\n return false;\n }\n }\n\n /**\n * Detecting vertical squash in loaded image.\n * Fixes a bug which squash image vertically while drawing into canvas for some images.\n */\n function detectVerticalSquash(img, iw, ih) {\n var canvas = document.createElement(\"canvas\"),\n sy = 0,\n ey = ih,\n py = ih,\n ctx, data, alpha, ratio;\n\n canvas.width = 1;\n canvas.height = ih;\n ctx = canvas.getContext(\"2d\");\n ctx.drawImage(img, 0, 0);\n data = ctx.getImageData(0, 0, 1, ih).data;\n\n // search image edge pixel position in case it is squashed vertically.\n while (py > sy) {\n alpha = data[(py - 1) * 4 + 3];\n if (alpha === 0) {\n ey = py;\n } else {\n sy = py;\n }\n py = (ey + sy) >> 1;\n }\n\n ratio = (py / ih);\n return (ratio === 0) ? 1 : ratio;\n }\n\n /**\n * Rendering image element (with resizing) and get its data URL\n */\n function renderImageToDataURL(img, blob, options, doSquash) {\n var canvas = document.createElement(\"canvas\"),\n mime = options.mime || \"image/jpeg\",\n promise = new qq.Promise();\n\n renderImageToCanvas(img, blob, canvas, options, doSquash)\n .then(function() {\n promise.success(\n canvas.toDataURL(mime, options.quality || 0.8)\n );\n });\n\n return promise;\n }\n\n function maybeCalculateDownsampledDimensions(spec) {\n var maxPixels = 5241000; //iOS specific value\n\n if (!qq.ios()) {\n throw new qq.Error(\"Downsampled dimensions can only be reliably calculated for iOS!\");\n }\n\n if (spec.origHeight * spec.origWidth > maxPixels) {\n return {\n newHeight: Math.round(Math.sqrt(maxPixels * (spec.origHeight / spec.origWidth))),\n newWidth: Math.round(Math.sqrt(maxPixels * (spec.origWidth / spec.origHeight)))\n };\n }\n }\n\n /**\n * Rendering image element (with resizing) into the canvas element\n */\n function renderImageToCanvas(img, blob, canvas, options, doSquash) {\n var iw = img.naturalWidth,\n ih = img.naturalHeight,\n width = options.width,\n height = options.height,\n ctx = canvas.getContext(\"2d\"),\n promise = new qq.Promise(),\n modifiedDimensions;\n\n ctx.save();\n\n if (options.resize) {\n return renderImageToCanvasWithCustomResizer({\n blob: blob,\n canvas: canvas,\n image: img,\n imageHeight: ih,\n imageWidth: iw,\n orientation: options.orientation,\n resize: options.resize,\n targetHeight: height,\n targetWidth: width\n });\n }\n\n if (!qq.supportedFeatures.unlimitedScaledImageSize) {\n modifiedDimensions = maybeCalculateDownsampledDimensions({\n origWidth: width,\n origHeight: height\n });\n\n if (modifiedDimensions) {\n qq.log(qq.format(\"Had to reduce dimensions due to device limitations from {}w / {}h to {}w / {}h\",\n width, height, modifiedDimensions.newWidth, modifiedDimensions.newHeight),\n \"warn\");\n\n width = modifiedDimensions.newWidth;\n height = modifiedDimensions.newHeight;\n }\n }\n\n transformCoordinate(canvas, width, height, options.orientation);\n\n // Fine Uploader specific: Save some CPU cycles if not using iOS\n // Assumption: This logic is only needed to overcome iOS image sampling issues\n if (qq.ios()) {\n (function() {\n if (detectSubsampling(img)) {\n iw /= 2;\n ih /= 2;\n }\n\n var d = 1024, // size of tiling canvas\n tmpCanvas = document.createElement(\"canvas\"),\n vertSquashRatio = doSquash ? detectVerticalSquash(img, iw, ih) : 1,\n dw = Math.ceil(d * width / iw),\n dh = Math.ceil(d * height / ih / vertSquashRatio),\n sy = 0,\n dy = 0,\n tmpCtx, sx, dx;\n\n tmpCanvas.width = tmpCanvas.height = d;\n tmpCtx = tmpCanvas.getContext(\"2d\");\n\n while (sy < ih) {\n sx = 0;\n dx = 0;\n while (sx < iw) {\n tmpCtx.clearRect(0, 0, d, d);\n tmpCtx.drawImage(img, -sx, -sy);\n ctx.drawImage(tmpCanvas, 0, 0, d, d, dx, dy, dw, dh);\n sx += d;\n dx += dw;\n }\n sy += d;\n dy += dh;\n }\n ctx.restore();\n tmpCanvas = tmpCtx = null;\n }());\n }\n else {\n ctx.drawImage(img, 0, 0, width, height);\n }\n\n canvas.qqImageRendered && canvas.qqImageRendered();\n promise.success();\n\n return promise;\n }\n\n function renderImageToCanvasWithCustomResizer(resizeInfo) {\n var blob = resizeInfo.blob,\n image = resizeInfo.image,\n imageHeight = resizeInfo.imageHeight,\n imageWidth = resizeInfo.imageWidth,\n orientation = resizeInfo.orientation,\n promise = new qq.Promise(),\n resize = resizeInfo.resize,\n sourceCanvas = document.createElement(\"canvas\"),\n sourceCanvasContext = sourceCanvas.getContext(\"2d\"),\n targetCanvas = resizeInfo.canvas,\n targetHeight = resizeInfo.targetHeight,\n targetWidth = resizeInfo.targetWidth;\n\n transformCoordinate(sourceCanvas, imageWidth, imageHeight, orientation);\n\n targetCanvas.height = targetHeight;\n targetCanvas.width = targetWidth;\n\n sourceCanvasContext.drawImage(image, 0, 0);\n\n resize({\n blob: blob,\n height: targetHeight,\n image: image,\n sourceCanvas: sourceCanvas,\n targetCanvas: targetCanvas,\n width: targetWidth\n })\n .then(\n function success() {\n targetCanvas.qqImageRendered && targetCanvas.qqImageRendered();\n promise.success();\n },\n promise.failure\n );\n\n return promise;\n }\n\n /**\n * Transform canvas coordination according to specified frame size and orientation\n * Orientation value is from EXIF tag\n */\n function transformCoordinate(canvas, width, height, orientation) {\n switch (orientation) {\n case 5:\n case 6:\n case 7:\n case 8:\n canvas.width = height;\n canvas.height = width;\n break;\n default:\n canvas.width = width;\n canvas.height = height;\n }\n var ctx = canvas.getContext(\"2d\");\n switch (orientation) {\n case 2:\n // horizontal flip\n ctx.translate(width, 0);\n ctx.scale(-1, 1);\n break;\n case 3:\n // 180 rotate left\n ctx.translate(width, height);\n ctx.rotate(Math.PI);\n break;\n case 4:\n // vertical flip\n ctx.translate(0, height);\n ctx.scale(1, -1);\n break;\n case 5:\n // vertical flip + 90 rotate right\n ctx.rotate(0.5 * Math.PI);\n ctx.scale(1, -1);\n break;\n case 6:\n // 90 rotate right\n ctx.rotate(0.5 * Math.PI);\n ctx.translate(0, -height);\n break;\n case 7:\n // horizontal flip + 90 rotate right\n ctx.rotate(0.5 * Math.PI);\n ctx.translate(width, -height);\n ctx.scale(-1, 1);\n break;\n case 8:\n // 90 rotate left\n ctx.rotate(-0.5 * Math.PI);\n ctx.translate(-width, 0);\n break;\n default:\n break;\n }\n }\n\n /**\n * MegaPixImage class\n */\n function MegaPixImage(srcImage, errorCallback) {\n var self = this;\n\n if (window.Blob && srcImage instanceof Blob) {\n (function() {\n var img = new Image(),\n URL = window.URL && window.URL.createObjectURL ? window.URL :\n window.webkitURL && window.webkitURL.createObjectURL ? window.webkitURL : null;\n if (!URL) { throw Error(\"No createObjectURL function found to create blob url\"); }\n img.src = URL.createObjectURL(srcImage);\n self.blob = srcImage;\n srcImage = img;\n }());\n }\n if (!srcImage.naturalWidth && !srcImage.naturalHeight) {\n srcImage.onload = function() {\n var listeners = self.imageLoadListeners;\n if (listeners) {\n self.imageLoadListeners = null;\n // IE11 doesn't reliably report actual image dimensions immediately after onload for small files,\n // so let's push this to the end of the UI thread queue.\n setTimeout(function() {\n for (var i = 0, len = listeners.length; i < len; i++) {\n listeners[i]();\n }\n }, 0);\n }\n };\n srcImage.onerror = errorCallback;\n this.imageLoadListeners = [];\n }\n this.srcImage = srcImage;\n }\n\n /**\n * Rendering megapix image into specified target element\n */\n MegaPixImage.prototype.render = function(target, options) {\n options = options || {};\n\n var self = this,\n imgWidth = this.srcImage.naturalWidth,\n imgHeight = this.srcImage.naturalHeight,\n width = options.width,\n height = options.height,\n maxWidth = options.maxWidth,\n maxHeight = options.maxHeight,\n doSquash = !this.blob || this.blob.type === \"image/jpeg\",\n tagName = target.tagName.toLowerCase(),\n opt;\n\n if (this.imageLoadListeners) {\n this.imageLoadListeners.push(function() { self.render(target, options); });\n return;\n }\n\n if (width && !height) {\n height = (imgHeight * width / imgWidth) << 0;\n } else if (height && !width) {\n width = (imgWidth * height / imgHeight) << 0;\n } else {\n width = imgWidth;\n height = imgHeight;\n }\n if (maxWidth && width > maxWidth) {\n width = maxWidth;\n height = (imgHeight * width / imgWidth) << 0;\n }\n if (maxHeight && height > maxHeight) {\n height = maxHeight;\n width = (imgWidth * height / imgHeight) << 0;\n }\n\n opt = { width: width, height: height },\n qq.each(options, function(optionsKey, optionsValue) {\n opt[optionsKey] = optionsValue;\n });\n\n if (tagName === \"img\") {\n (function() {\n var oldTargetSrc = target.src;\n renderImageToDataURL(self.srcImage, self.blob, opt, doSquash)\n .then(function(dataUri) {\n target.src = dataUri;\n oldTargetSrc === target.src && target.onload();\n });\n }());\n } else if (tagName === \"canvas\") {\n renderImageToCanvas(this.srcImage, this.blob, target, opt, doSquash);\n }\n if (typeof this.onrender === \"function\") {\n this.onrender(target);\n }\n };\n\n qq.MegaPixImage = MegaPixImage;\n})();\n","/*globals qq */\n/**\n * Draws a thumbnail of a Blob/File/URL onto an or .\n *\n * @constructor\n */\nqq.ImageGenerator = function(log) {\n \"use strict\";\n\n function isImg(el) {\n return el.tagName.toLowerCase() === \"img\";\n }\n\n function isCanvas(el) {\n return el.tagName.toLowerCase() === \"canvas\";\n }\n\n function isImgCorsSupported() {\n return new Image().crossOrigin !== undefined;\n }\n\n function isCanvasSupported() {\n var canvas = document.createElement(\"canvas\");\n\n return canvas.getContext && canvas.getContext(\"2d\");\n }\n\n // This is only meant to determine the MIME type of a renderable image file.\n // It is used to ensure images drawn from a URL that have transparent backgrounds\n // are rendered correctly, among other things.\n function determineMimeOfFileName(nameWithPath) {\n /*jshint -W015 */\n var pathSegments = nameWithPath.split(\"/\"),\n name = pathSegments[pathSegments.length - 1].split(\"?\")[0],\n extension = qq.getExtension(name);\n\n extension = extension && extension.toLowerCase();\n\n switch (extension) {\n case \"jpeg\":\n case \"jpg\":\n return \"image/jpeg\";\n case \"png\":\n return \"image/png\";\n case \"bmp\":\n return \"image/bmp\";\n case \"gif\":\n return \"image/gif\";\n case \"tiff\":\n case \"tif\":\n return \"image/tiff\";\n }\n }\n\n // This will likely not work correctly in IE8 and older.\n // It's only used as part of a formula to determine\n // if a canvas can be used to scale a server-hosted thumbnail.\n // If canvas isn't supported by the UA (IE8 and older)\n // this method should not even be called.\n function isCrossOrigin(url) {\n var targetAnchor = document.createElement(\"a\"),\n targetProtocol, targetHostname, targetPort;\n\n targetAnchor.href = url;\n\n targetProtocol = targetAnchor.protocol;\n targetPort = targetAnchor.port;\n targetHostname = targetAnchor.hostname;\n\n if (targetProtocol.toLowerCase() !== window.location.protocol.toLowerCase()) {\n return true;\n }\n\n if (targetHostname.toLowerCase() !== window.location.hostname.toLowerCase()) {\n return true;\n }\n\n // IE doesn't take ports into consideration when determining if two endpoints are same origin.\n if (targetPort !== window.location.port && !qq.ie()) {\n return true;\n }\n\n return false;\n }\n\n function registerImgLoadListeners(img, promise) {\n img.onload = function() {\n img.onload = null;\n img.onerror = null;\n promise.success(img);\n };\n\n img.onerror = function() {\n img.onload = null;\n img.onerror = null;\n log(\"Problem drawing thumbnail!\", \"error\");\n promise.failure(img, \"Problem drawing thumbnail!\");\n };\n }\n\n function registerCanvasDrawImageListener(canvas, promise) {\n // The image is drawn on the canvas by a third-party library,\n // and we want to know when this is completed. Since the library\n // may invoke drawImage many times in a loop, we need to be called\n // back when the image is fully rendered. So, we are expecting the\n // code that draws this image to follow a convention that involves a\n // function attached to the canvas instance be invoked when it is done.\n canvas.qqImageRendered = function() {\n promise.success(canvas);\n };\n }\n\n // Fulfills a `qq.Promise` when an image has been drawn onto the target,\n // whether that is a or an . The attempt is considered a\n // failure if the target is not an or a , or if the drawing\n // attempt was not successful.\n function registerThumbnailRenderedListener(imgOrCanvas, promise) {\n var registered = isImg(imgOrCanvas) || isCanvas(imgOrCanvas);\n\n if (isImg(imgOrCanvas)) {\n registerImgLoadListeners(imgOrCanvas, promise);\n }\n else if (isCanvas(imgOrCanvas)) {\n registerCanvasDrawImageListener(imgOrCanvas, promise);\n }\n else {\n promise.failure(imgOrCanvas);\n log(qq.format(\"Element container of type {} is not supported!\", imgOrCanvas.tagName), \"error\");\n }\n\n return registered;\n }\n\n // Draw a preview iff the current UA can natively display it.\n // Also rotate the image if necessary.\n function draw(fileOrBlob, container, options) {\n var drawPreview = new qq.Promise(),\n identifier = new qq.Identify(fileOrBlob, log),\n maxSize = options.maxSize,\n // jshint eqnull:true\n orient = options.orient == null ? true : options.orient,\n megapixErrorHandler = function() {\n container.onerror = null;\n container.onload = null;\n log(\"Could not render preview, file may be too large!\", \"error\");\n drawPreview.failure(container, \"Browser cannot render image!\");\n };\n\n identifier.isPreviewable().then(\n function(mime) {\n // If options explicitly specify that Orientation is not desired,\n // replace the orient task with a dummy promise that \"succeeds\" immediately.\n var dummyExif = {\n parse: function() {\n return new qq.Promise().success();\n }\n },\n exif = orient ? new qq.Exif(fileOrBlob, log) : dummyExif,\n mpImg = new qq.MegaPixImage(fileOrBlob, megapixErrorHandler);\n\n if (registerThumbnailRenderedListener(container, drawPreview)) {\n exif.parse().then(\n function(exif) {\n var orientation = exif && exif.Orientation;\n\n mpImg.render(container, {\n maxWidth: maxSize,\n maxHeight: maxSize,\n orientation: orientation,\n mime: mime,\n resize: options.customResizeFunction\n });\n },\n\n function(failureMsg) {\n log(qq.format(\"EXIF data could not be parsed ({}). Assuming orientation = 1.\", failureMsg));\n\n mpImg.render(container, {\n maxWidth: maxSize,\n maxHeight: maxSize,\n mime: mime,\n resize: options.customResizeFunction\n });\n }\n );\n }\n },\n\n function() {\n log(\"Not previewable\");\n drawPreview.failure(container, \"Not previewable\");\n }\n );\n\n return drawPreview;\n }\n\n function drawOnCanvasOrImgFromUrl(url, canvasOrImg, draw, maxSize, customResizeFunction) {\n var tempImg = new Image(),\n tempImgRender = new qq.Promise();\n\n registerThumbnailRenderedListener(tempImg, tempImgRender);\n\n if (isCrossOrigin(url)) {\n tempImg.crossOrigin = \"anonymous\";\n }\n\n tempImg.src = url;\n\n tempImgRender.then(\n function rendered() {\n registerThumbnailRenderedListener(canvasOrImg, draw);\n\n var mpImg = new qq.MegaPixImage(tempImg);\n mpImg.render(canvasOrImg, {\n maxWidth: maxSize,\n maxHeight: maxSize,\n mime: determineMimeOfFileName(url),\n resize: customResizeFunction\n });\n },\n\n draw.failure\n );\n }\n\n function drawOnImgFromUrlWithCssScaling(url, img, draw, maxSize) {\n registerThumbnailRenderedListener(img, draw);\n // NOTE: The fact that maxWidth/height is set on the thumbnail for scaled images\n // that must drop back to CSS is known and exploited by the templating module.\n // In this module, we pre-render \"waiting\" thumbs for all files immediately after they\n // are submitted, and we must be sure to pass any style associated with the \"waiting\" preview.\n qq(img).css({\n maxWidth: maxSize + \"px\",\n maxHeight: maxSize + \"px\"\n });\n\n img.src = url;\n }\n\n // Draw a (server-hosted) thumbnail given a URL.\n // This will optionally scale the thumbnail as well.\n // It attempts to use to scale, but will fall back\n // to max-width and max-height style properties if the UA\n // doesn't support canvas or if the images is cross-domain and\n // the UA doesn't support the crossorigin attribute on img tags,\n // which is required to scale a cross-origin image using &\n // then export it back to an .\n function drawFromUrl(url, container, options) {\n var draw = new qq.Promise(),\n scale = options.scale,\n maxSize = scale ? options.maxSize : null;\n\n // container is an img, scaling needed\n if (scale && isImg(container)) {\n // Iff canvas is available in this UA, try to use it for scaling.\n // Otherwise, fall back to CSS scaling\n if (isCanvasSupported()) {\n // Attempt to use for image scaling,\n // but we must fall back to scaling via CSS/styles\n // if this is a cross-origin image and the UA doesn't support CORS.\n if (isCrossOrigin(url) && !isImgCorsSupported()) {\n drawOnImgFromUrlWithCssScaling(url, container, draw, maxSize);\n }\n else {\n drawOnCanvasOrImgFromUrl(url, container, draw, maxSize);\n }\n }\n else {\n drawOnImgFromUrlWithCssScaling(url, container, draw, maxSize);\n }\n }\n // container is a canvas, scaling optional\n else if (isCanvas(container)) {\n drawOnCanvasOrImgFromUrl(url, container, draw, maxSize);\n }\n // container is an img & no scaling: just set the src attr to the passed url\n else if (registerThumbnailRenderedListener(container, draw)) {\n container.src = url;\n }\n\n return draw;\n }\n\n qq.extend(this, {\n /**\n * Generate a thumbnail. Depending on the arguments, this may either result in\n * a client-side rendering of an image (if a `Blob` is supplied) or a server-generated\n * image that may optionally be scaled client-side using or CSS/styles (as a fallback).\n *\n * @param fileBlobOrUrl a `File`, `Blob`, or a URL pointing to the image\n * @param container or to contain the preview\n * @param options possible properties include `maxSize` (int), `orient` (bool - default true), resize` (bool - default true), and `customResizeFunction`.\n * @returns qq.Promise fulfilled when the preview has been drawn, or the attempt has failed\n */\n generate: function(fileBlobOrUrl, container, options) {\n if (qq.isString(fileBlobOrUrl)) {\n log(\"Attempting to update thumbnail based on server response.\");\n return drawFromUrl(fileBlobOrUrl, container, options || {});\n }\n else {\n log(\"Attempting to draw client-side image preview.\");\n return draw(fileBlobOrUrl, container, options || {});\n }\n }\n });\n\n /**/\n this._testing = {};\n this._testing.isImg = isImg;\n this._testing.isCanvas = isCanvas;\n this._testing.isCrossOrigin = isCrossOrigin;\n this._testing.determineMimeOfFileName = determineMimeOfFileName;\n /* */\n};\n","/*globals qq */\n/**\n * EXIF image data parser. Currently only parses the Orientation tag value,\n * but this may be expanded to other tags in the future.\n *\n * @param fileOrBlob Attempt to parse EXIF data in this `Blob`\n * @constructor\n */\nqq.Exif = function(fileOrBlob, log) {\n \"use strict\";\n\n // Orientation is the only tag parsed here at this time.\n var TAG_IDS = [274],\n TAG_INFO = {\n 274: {\n name: \"Orientation\",\n bytes: 2\n }\n };\n\n // Convert a little endian (hex string) to big endian (decimal).\n function parseLittleEndian(hex) {\n var result = 0,\n pow = 0;\n\n while (hex.length > 0) {\n result += parseInt(hex.substring(0, 2), 16) * Math.pow(2, pow);\n hex = hex.substring(2, hex.length);\n pow += 8;\n }\n\n return result;\n }\n\n // Find the byte offset, of Application Segment 1 (EXIF).\n // External callers need not supply any arguments.\n function seekToApp1(offset, promise) {\n var theOffset = offset,\n thePromise = promise;\n if (theOffset === undefined) {\n theOffset = 2;\n thePromise = new qq.Promise();\n }\n\n qq.readBlobToHex(fileOrBlob, theOffset, 4).then(function(hex) {\n var match = /^ffe([0-9])/.exec(hex),\n segmentLength;\n\n if (match) {\n if (match[1] !== \"1\") {\n segmentLength = parseInt(hex.slice(4, 8), 16);\n seekToApp1(theOffset + segmentLength + 2, thePromise);\n }\n else {\n thePromise.success(theOffset);\n }\n }\n else {\n thePromise.failure(\"No EXIF header to be found!\");\n }\n });\n\n return thePromise;\n }\n\n // Find the byte offset of Application Segment 1 (EXIF) for valid JPEGs only.\n function getApp1Offset() {\n var promise = new qq.Promise();\n\n qq.readBlobToHex(fileOrBlob, 0, 6).then(function(hex) {\n if (hex.indexOf(\"ffd8\") !== 0) {\n promise.failure(\"Not a valid JPEG!\");\n }\n else {\n seekToApp1().then(function(offset) {\n promise.success(offset);\n },\n function(error) {\n promise.failure(error);\n });\n }\n });\n\n return promise;\n }\n\n // Determine the byte ordering of the EXIF header.\n function isLittleEndian(app1Start) {\n var promise = new qq.Promise();\n\n qq.readBlobToHex(fileOrBlob, app1Start + 10, 2).then(function(hex) {\n promise.success(hex === \"4949\");\n });\n\n return promise;\n }\n\n // Determine the number of directory entries in the EXIF header.\n function getDirEntryCount(app1Start, littleEndian) {\n var promise = new qq.Promise();\n\n qq.readBlobToHex(fileOrBlob, app1Start + 18, 2).then(function(hex) {\n if (littleEndian) {\n return promise.success(parseLittleEndian(hex));\n }\n else {\n promise.success(parseInt(hex, 16));\n }\n });\n\n return promise;\n }\n\n // Get the IFD portion of the EXIF header as a hex string.\n function getIfd(app1Start, dirEntries) {\n var offset = app1Start + 20,\n bytes = dirEntries * 12;\n\n return qq.readBlobToHex(fileOrBlob, offset, bytes);\n }\n\n // Obtain an array of all directory entries (as hex strings) in the EXIF header.\n function getDirEntries(ifdHex) {\n var entries = [],\n offset = 0;\n\n while (offset + 24 <= ifdHex.length) {\n entries.push(ifdHex.slice(offset, offset + 24));\n offset += 24;\n }\n\n return entries;\n }\n\n // Obtain values for all relevant tags and return them.\n function getTagValues(littleEndian, dirEntries) {\n var TAG_VAL_OFFSET = 16,\n tagsToFind = qq.extend([], TAG_IDS),\n vals = {};\n\n qq.each(dirEntries, function(idx, entry) {\n var idHex = entry.slice(0, 4),\n id = littleEndian ? parseLittleEndian(idHex) : parseInt(idHex, 16),\n tagsToFindIdx = tagsToFind.indexOf(id),\n tagValHex, tagName, tagValLength;\n\n if (tagsToFindIdx >= 0) {\n tagName = TAG_INFO[id].name;\n tagValLength = TAG_INFO[id].bytes;\n tagValHex = entry.slice(TAG_VAL_OFFSET, TAG_VAL_OFFSET + (tagValLength * 2));\n vals[tagName] = littleEndian ? parseLittleEndian(tagValHex) : parseInt(tagValHex, 16);\n\n tagsToFind.splice(tagsToFindIdx, 1);\n }\n\n if (tagsToFind.length === 0) {\n return false;\n }\n });\n\n return vals;\n }\n\n qq.extend(this, {\n /**\n * Attempt to parse the EXIF header for the `Blob` associated with this instance.\n *\n * @returns {qq.Promise} To be fulfilled when the parsing is complete.\n * If successful, the parsed EXIF header as an object will be included.\n */\n parse: function() {\n var parser = new qq.Promise(),\n onParseFailure = function(message) {\n log(qq.format(\"EXIF header parse failed: '{}' \", message));\n parser.failure(message);\n };\n\n getApp1Offset().then(function(app1Offset) {\n log(qq.format(\"Moving forward with EXIF header parsing for '{}'\", fileOrBlob.name === undefined ? \"blob\" : fileOrBlob.name));\n\n isLittleEndian(app1Offset).then(function(littleEndian) {\n\n log(qq.format(\"EXIF Byte order is {} endian\", littleEndian ? \"little\" : \"big\"));\n\n getDirEntryCount(app1Offset, littleEndian).then(function(dirEntryCount) {\n\n log(qq.format(\"Found {} APP1 directory entries\", dirEntryCount));\n\n getIfd(app1Offset, dirEntryCount).then(function(ifdHex) {\n var dirEntries = getDirEntries(ifdHex),\n tagValues = getTagValues(littleEndian, dirEntries);\n\n log(\"Successfully parsed some EXIF tags\");\n\n parser.success(tagValues);\n }, onParseFailure);\n }, onParseFailure);\n }, onParseFailure);\n }, onParseFailure);\n\n return parser;\n }\n });\n\n /**/\n this._testing = {};\n this._testing.parseLittleEndian = parseLittleEndian;\n /* */\n};\n","/*globals qq */\nqq.Identify = function(fileOrBlob, log) {\n \"use strict\";\n\n function isIdentifiable(magicBytes, questionableBytes) {\n var identifiable = false,\n magicBytesEntries = [].concat(magicBytes);\n\n qq.each(magicBytesEntries, function(idx, magicBytesArrayEntry) {\n if (questionableBytes.indexOf(magicBytesArrayEntry) === 0) {\n identifiable = true;\n return false;\n }\n });\n\n return identifiable;\n }\n\n qq.extend(this, {\n /**\n * Determines if a Blob can be displayed natively in the current browser. This is done by reading magic\n * bytes in the beginning of the file, so this is an asynchronous operation. Before we attempt to read the\n * file, we will examine the blob's type attribute to save CPU cycles.\n *\n * @returns {qq.Promise} Promise that is fulfilled when identification is complete.\n * If successful, the MIME string is passed to the success handler.\n */\n isPreviewable: function() {\n var self = this,\n identifier = new qq.Promise(),\n previewable = false,\n name = fileOrBlob.name === undefined ? \"blob\" : fileOrBlob.name;\n\n log(qq.format(\"Attempting to determine if {} can be rendered in this browser\", name));\n\n log(\"First pass: check type attribute of blob object.\");\n\n if (this.isPreviewableSync()) {\n log(\"Second pass: check for magic bytes in file header.\");\n\n qq.readBlobToHex(fileOrBlob, 0, 4).then(function(hex) {\n qq.each(self.PREVIEWABLE_MIME_TYPES, function(mime, bytes) {\n if (isIdentifiable(bytes, hex)) {\n // Safari is the only supported browser that can deal with TIFFs natively,\n // so, if this is a TIFF and the UA isn't Safari, declare this file \"non-previewable\".\n if (mime !== \"image/tiff\" || qq.supportedFeatures.tiffPreviews) {\n previewable = true;\n identifier.success(mime);\n }\n\n return false;\n }\n });\n\n log(qq.format(\"'{}' is {} able to be rendered in this browser\", name, previewable ? \"\" : \"NOT\"));\n\n if (!previewable) {\n identifier.failure();\n }\n },\n function() {\n log(\"Error reading file w/ name '\" + name + \"'. Not able to be rendered in this browser.\");\n identifier.failure();\n });\n }\n else {\n identifier.failure();\n }\n\n return identifier;\n },\n\n /**\n * Determines if a Blob can be displayed natively in the current browser. This is done by checking the\n * blob's type attribute. This is a synchronous operation, useful for situations where an asynchronous operation\n * would be challenging to support. Note that the blob's type property is not as accurate as reading the\n * file's magic bytes.\n *\n * @returns {Boolean} true if the blob can be rendered in the current browser\n */\n isPreviewableSync: function() {\n var fileMime = fileOrBlob.type,\n // Assumption: This will only ever be executed in browsers that support `Object.keys`.\n isRecognizedImage = qq.indexOf(Object.keys(this.PREVIEWABLE_MIME_TYPES), fileMime) >= 0,\n previewable = false,\n name = fileOrBlob.name === undefined ? \"blob\" : fileOrBlob.name;\n\n if (isRecognizedImage) {\n if (fileMime === \"image/tiff\") {\n previewable = qq.supportedFeatures.tiffPreviews;\n }\n else {\n previewable = true;\n }\n }\n\n !previewable && log(name + \" is not previewable in this browser per the blob's type attr\");\n\n return previewable;\n }\n });\n};\n\nqq.Identify.prototype.PREVIEWABLE_MIME_TYPES = {\n \"image/jpeg\": \"ffd8ff\",\n \"image/gif\": \"474946\",\n \"image/png\": \"89504e\",\n \"image/bmp\": \"424d\",\n \"image/tiff\": [\"49492a00\", \"4d4d002a\"]\n};\n","/*globals qq*/\n/**\n * Attempts to validate an image, wherever possible.\n *\n * @param blob File or Blob representing a user-selecting image.\n * @param log Uses this to post log messages to the console.\n * @constructor\n */\nqq.ImageValidation = function(blob, log) {\n \"use strict\";\n\n /**\n * @param limits Object with possible image-related limits to enforce.\n * @returns {boolean} true if at least one of the limits has a non-zero value\n */\n function hasNonZeroLimits(limits) {\n var atLeastOne = false;\n\n qq.each(limits, function(limit, value) {\n if (value > 0) {\n atLeastOne = true;\n return false;\n }\n });\n\n return atLeastOne;\n }\n\n /**\n * @returns {qq.Promise} The promise is a failure if we can't obtain the width & height.\n * Otherwise, `success` is called on the returned promise with an object containing\n * `width` and `height` properties.\n */\n function getWidthHeight() {\n var sizeDetermination = new qq.Promise();\n\n new qq.Identify(blob, log).isPreviewable().then(function() {\n var image = new Image(),\n url = window.URL && window.URL.createObjectURL ? window.URL :\n window.webkitURL && window.webkitURL.createObjectURL ? window.webkitURL :\n null;\n\n if (url) {\n image.onerror = function() {\n log(\"Cannot determine dimensions for image. May be too large.\", \"error\");\n sizeDetermination.failure();\n };\n\n image.onload = function() {\n sizeDetermination.success({\n width: this.width,\n height: this.height\n });\n };\n\n image.src = url.createObjectURL(blob);\n }\n else {\n log(\"No createObjectURL function available to generate image URL!\", \"error\");\n sizeDetermination.failure();\n }\n }, sizeDetermination.failure);\n\n return sizeDetermination;\n }\n\n /**\n *\n * @param limits Object with possible image-related limits to enforce.\n * @param dimensions Object containing `width` & `height` properties for the image to test.\n * @returns {String || undefined} The name of the failing limit. Undefined if no failing limits.\n */\n function getFailingLimit(limits, dimensions) {\n var failingLimit;\n\n qq.each(limits, function(limitName, limitValue) {\n if (limitValue > 0) {\n var limitMatcher = /(max|min)(Width|Height)/.exec(limitName),\n dimensionPropName = limitMatcher[2].charAt(0).toLowerCase() + limitMatcher[2].slice(1),\n actualValue = dimensions[dimensionPropName];\n\n /*jshint -W015*/\n switch (limitMatcher[1]) {\n case \"min\":\n if (actualValue < limitValue) {\n failingLimit = limitName;\n return false;\n }\n break;\n case \"max\":\n if (actualValue > limitValue) {\n failingLimit = limitName;\n return false;\n }\n break;\n }\n }\n });\n\n return failingLimit;\n }\n\n /**\n * Validate the associated blob.\n *\n * @param limits\n * @returns {qq.Promise} `success` is called on the promise is the image is valid or\n * if the blob is not an image, or if the image is not verifiable.\n * Otherwise, `failure` with the name of the failing limit.\n */\n this.validate = function(limits) {\n var validationEffort = new qq.Promise();\n\n log(\"Attempting to validate image.\");\n\n if (hasNonZeroLimits(limits)) {\n getWidthHeight().then(function(dimensions) {\n var failingLimit = getFailingLimit(limits, dimensions);\n\n if (failingLimit) {\n validationEffort.failure(failingLimit);\n }\n else {\n validationEffort.success();\n }\n }, validationEffort.success);\n }\n else {\n validationEffort.success();\n }\n\n return validationEffort;\n };\n};\n","/* globals qq */\n/**\n * Module used to control populating the initial list of files.\n *\n * @constructor\n */\nqq.Session = function(spec) {\n \"use strict\";\n\n var options = {\n endpoint: null,\n params: {},\n customHeaders: {},\n cors: {},\n addFileRecord: function(sessionData) {},\n log: function(message, level) {}\n };\n\n qq.extend(options, spec, true);\n\n function isJsonResponseValid(response) {\n if (qq.isArray(response)) {\n return true;\n }\n\n options.log(\"Session response is not an array.\", \"error\");\n }\n\n function handleFileItems(fileItems, success, xhrOrXdr, promise) {\n var someItemsIgnored = false;\n\n success = success && isJsonResponseValid(fileItems);\n\n if (success) {\n qq.each(fileItems, function(idx, fileItem) {\n /* jshint eqnull:true */\n if (fileItem.uuid == null) {\n someItemsIgnored = true;\n options.log(qq.format(\"Session response item {} did not include a valid UUID - ignoring.\", idx), \"error\");\n }\n else if (fileItem.name == null) {\n someItemsIgnored = true;\n options.log(qq.format(\"Session response item {} did not include a valid name - ignoring.\", idx), \"error\");\n }\n else {\n try {\n options.addFileRecord(fileItem);\n return true;\n }\n catch (err) {\n someItemsIgnored = true;\n options.log(err.message, \"error\");\n }\n }\n\n return false;\n });\n }\n\n promise[success && !someItemsIgnored ? \"success\" : \"failure\"](fileItems, xhrOrXdr);\n }\n\n // Initiate a call to the server that will be used to populate the initial file list.\n // Returns a `qq.Promise`.\n this.refresh = function() {\n /*jshint indent:false */\n var refreshEffort = new qq.Promise(),\n refreshCompleteCallback = function(response, success, xhrOrXdr) {\n handleFileItems(response, success, xhrOrXdr, refreshEffort);\n },\n requesterOptions = qq.extend({}, options),\n requester = new qq.SessionAjaxRequester(\n qq.extend(requesterOptions, {onComplete: refreshCompleteCallback})\n );\n\n requester.queryServer();\n\n return refreshEffort;\n };\n};\n","/*globals qq, XMLHttpRequest*/\n/**\n * Thin module used to send GET requests to the server, expecting information about session\n * data used to initialize an uploader instance.\n *\n * @param spec Various options used to influence the associated request.\n * @constructor\n */\nqq.SessionAjaxRequester = function(spec) {\n \"use strict\";\n\n var requester,\n options = {\n endpoint: null,\n customHeaders: {},\n params: {},\n cors: {\n expected: false,\n sendCredentials: false\n },\n onComplete: function(response, success, xhrOrXdr) {},\n log: function(str, level) {}\n };\n\n qq.extend(options, spec);\n\n function onComplete(id, xhrOrXdr, isError) {\n var response = null;\n\n /* jshint eqnull:true */\n if (xhrOrXdr.responseText != null) {\n try {\n response = qq.parseJson(xhrOrXdr.responseText);\n }\n catch (err) {\n options.log(\"Problem parsing session response: \" + err.message, \"error\");\n isError = true;\n }\n }\n\n options.onComplete(response, !isError, xhrOrXdr);\n }\n\n requester = qq.extend(this, new qq.AjaxRequester({\n acceptHeader: \"application/json\",\n validMethods: [\"GET\"],\n method: \"GET\",\n endpointStore: {\n get: function() {\n return options.endpoint;\n }\n },\n customHeaders: options.customHeaders,\n log: options.log,\n onComplete: onComplete,\n cors: options.cors\n }));\n\n qq.extend(this, {\n queryServer: function() {\n var params = qq.extend({}, options.params);\n\n options.log(\"Session query request.\");\n\n requester.initTransport(\"sessionRefresh\")\n .withParams(params)\n .withCacheBuster()\n .send();\n }\n });\n};\n","/* globals qq, ExifRestorer */\n/**\n * Controls generation of scaled images based on a reference image encapsulated in a `File` or `Blob`.\n * Scaled images are generated and converted to blobs on-demand.\n * Multiple scaled images per reference image with varying sizes and other properties are supported.\n *\n * @param spec Information about the scaled images to generate.\n * @param log Logger instance\n * @constructor\n */\nqq.Scaler = function(spec, log) {\n \"use strict\";\n\n var self = this,\n customResizeFunction = spec.customResizer,\n includeOriginal = spec.sendOriginal,\n orient = spec.orient,\n defaultType = spec.defaultType,\n defaultQuality = spec.defaultQuality / 100,\n failedToScaleText = spec.failureText,\n includeExif = spec.includeExif,\n sizes = this._getSortedSizes(spec.sizes);\n\n // Revealed API for instances of this module\n qq.extend(this, {\n // If no targeted sizes have been declared or if this browser doesn't support\n // client-side image preview generation, there is no scaling to do.\n enabled: qq.supportedFeatures.scaling && sizes.length > 0,\n\n getFileRecords: function(originalFileUuid, originalFileName, originalBlobOrBlobData) {\n var self = this,\n records = [],\n originalBlob = originalBlobOrBlobData.blob ? originalBlobOrBlobData.blob : originalBlobOrBlobData,\n identifier = new qq.Identify(originalBlob, log);\n\n // If the reference file cannot be rendered natively, we can't create scaled versions.\n if (identifier.isPreviewableSync()) {\n // Create records for each scaled version & add them to the records array, smallest first.\n qq.each(sizes, function(idx, sizeRecord) {\n var outputType = self._determineOutputType({\n defaultType: defaultType,\n requestedType: sizeRecord.type,\n refType: originalBlob.type\n });\n\n records.push({\n uuid: qq.getUniqueId(),\n name: self._getName(originalFileName, {\n name: sizeRecord.name,\n type: outputType,\n refType: originalBlob.type\n }),\n blob: new qq.BlobProxy(originalBlob,\n qq.bind(self._generateScaledImage, self, {\n customResizeFunction: customResizeFunction,\n maxSize: sizeRecord.maxSize,\n orient: orient,\n type: outputType,\n quality: defaultQuality,\n failedText: failedToScaleText,\n includeExif: includeExif,\n log: log\n }))\n });\n });\n\n records.push({\n uuid: originalFileUuid,\n name: originalFileName,\n size: originalBlob.size,\n blob: includeOriginal ? originalBlob : null\n });\n }\n else {\n records.push({\n uuid: originalFileUuid,\n name: originalFileName,\n size: originalBlob.size,\n blob: originalBlob\n });\n }\n\n return records;\n },\n\n handleNewFile: function(file, name, uuid, size, fileList, batchId, uuidParamName, api) {\n var self = this,\n buttonId = file.qqButtonId || (file.blob && file.blob.qqButtonId),\n scaledIds = [],\n originalId = null,\n addFileToHandler = api.addFileToHandler,\n uploadData = api.uploadData,\n paramsStore = api.paramsStore,\n proxyGroupId = qq.getUniqueId();\n\n qq.each(self.getFileRecords(uuid, name, file), function(idx, record) {\n var blobSize = record.size,\n id;\n\n if (record.blob instanceof qq.BlobProxy) {\n blobSize = -1;\n }\n\n id = uploadData.addFile({\n uuid: record.uuid,\n name: record.name,\n size: blobSize,\n batchId: batchId,\n proxyGroupId: proxyGroupId\n });\n\n if (record.blob instanceof qq.BlobProxy) {\n scaledIds.push(id);\n }\n else {\n originalId = id;\n }\n\n if (record.blob) {\n addFileToHandler(id, record.blob);\n fileList.push({id: id, file: record.blob});\n }\n else {\n uploadData.setStatus(id, qq.status.REJECTED);\n }\n });\n\n // If we are potentially uploading an original file and some scaled versions,\n // ensure the scaled versions include reference's to the parent's UUID and size\n // in their associated upload requests.\n if (originalId !== null) {\n qq.each(scaledIds, function(idx, scaledId) {\n var params = {\n qqparentuuid: uploadData.retrieve({id: originalId}).uuid,\n qqparentsize: uploadData.retrieve({id: originalId}).size\n };\n\n // Make sure the UUID for each scaled image is sent with the upload request,\n // to be consistent (since we may need to ensure it is sent for the original file as well).\n params[uuidParamName] = uploadData.retrieve({id: scaledId}).uuid;\n\n uploadData.setParentId(scaledId, originalId);\n paramsStore.addReadOnly(scaledId, params);\n });\n\n // If any scaled images are tied to this parent image, be SURE we send its UUID as an upload request\n // parameter as well.\n if (scaledIds.length) {\n (function() {\n var param = {};\n param[uuidParamName] = uploadData.retrieve({id: originalId}).uuid;\n paramsStore.addReadOnly(originalId, param);\n }());\n }\n }\n }\n });\n};\n\nqq.extend(qq.Scaler.prototype, {\n scaleImage: function(id, specs, api) {\n \"use strict\";\n\n if (!qq.supportedFeatures.scaling) {\n throw new qq.Error(\"Scaling is not supported in this browser!\");\n }\n\n var scalingEffort = new qq.Promise(),\n log = api.log,\n file = api.getFile(id),\n uploadData = api.uploadData.retrieve({id: id}),\n name = uploadData && uploadData.name,\n uuid = uploadData && uploadData.uuid,\n scalingOptions = {\n customResizer: specs.customResizer,\n sendOriginal: false,\n orient: specs.orient,\n defaultType: specs.type || null,\n defaultQuality: specs.quality,\n failedToScaleText: \"Unable to scale\",\n sizes: [{name: \"\", maxSize: specs.maxSize}]\n },\n scaler = new qq.Scaler(scalingOptions, log);\n\n if (!qq.Scaler || !qq.supportedFeatures.imagePreviews || !file) {\n scalingEffort.failure();\n\n log(\"Could not generate requested scaled image for \" + id + \". \" +\n \"Scaling is either not possible in this browser, or the file could not be located.\", \"error\");\n }\n else {\n (qq.bind(function() {\n // Assumption: There will never be more than one record\n var record = scaler.getFileRecords(uuid, name, file)[0];\n\n if (record && record.blob instanceof qq.BlobProxy) {\n record.blob.create().then(scalingEffort.success, scalingEffort.failure);\n }\n else {\n log(id + \" is not a scalable image!\", \"error\");\n scalingEffort.failure();\n }\n }, this)());\n }\n\n return scalingEffort;\n },\n\n // NOTE: We cannot reliably determine at this time if the UA supports a specific MIME type for the target format.\n // image/jpeg and image/png are the only safe choices at this time.\n _determineOutputType: function(spec) {\n \"use strict\";\n\n var requestedType = spec.requestedType,\n defaultType = spec.defaultType,\n referenceType = spec.refType;\n\n // If a default type and requested type have not been specified, this should be a\n // JPEG if the original type is a JPEG, otherwise, a PNG.\n if (!defaultType && !requestedType) {\n if (referenceType !== \"image/jpeg\") {\n return \"image/png\";\n }\n return referenceType;\n }\n\n // A specified default type is used when a requested type is not specified.\n if (!requestedType) {\n return defaultType;\n }\n\n // If requested type is specified, use it, as long as this recognized type is supported by the current UA\n if (qq.indexOf(Object.keys(qq.Identify.prototype.PREVIEWABLE_MIME_TYPES), requestedType) >= 0) {\n if (requestedType === \"image/tiff\") {\n return qq.supportedFeatures.tiffPreviews ? requestedType : defaultType;\n }\n\n return requestedType;\n }\n\n return defaultType;\n },\n\n // Get a file name for a generated scaled file record, based on the provided scaled image description\n _getName: function(originalName, scaledVersionProperties) {\n \"use strict\";\n\n var startOfExt = originalName.lastIndexOf(\".\"),\n versionType = scaledVersionProperties.type || \"image/png\",\n referenceType = scaledVersionProperties.refType,\n scaledName = \"\",\n scaledExt = qq.getExtension(originalName),\n nameAppendage = \"\";\n\n if (scaledVersionProperties.name && scaledVersionProperties.name.trim().length) {\n nameAppendage = \" (\" + scaledVersionProperties.name + \")\";\n }\n\n if (startOfExt >= 0) {\n scaledName = originalName.substr(0, startOfExt);\n\n if (referenceType !== versionType) {\n scaledExt = versionType.split(\"/\")[1];\n }\n\n scaledName += nameAppendage + \".\" + scaledExt;\n }\n else {\n scaledName = originalName + nameAppendage;\n }\n\n return scaledName;\n },\n\n // We want the smallest scaled file to be uploaded first\n _getSortedSizes: function(sizes) {\n \"use strict\";\n\n sizes = qq.extend([], sizes);\n\n return sizes.sort(function(a, b) {\n if (a.maxSize > b.maxSize) {\n return 1;\n }\n if (a.maxSize < b.maxSize) {\n return -1;\n }\n return 0;\n });\n },\n\n _generateScaledImage: function(spec, sourceFile) {\n \"use strict\";\n\n var self = this,\n customResizeFunction = spec.customResizeFunction,\n log = spec.log,\n maxSize = spec.maxSize,\n orient = spec.orient,\n type = spec.type,\n quality = spec.quality,\n failedText = spec.failedText,\n includeExif = spec.includeExif && sourceFile.type === \"image/jpeg\" && type === \"image/jpeg\",\n scalingEffort = new qq.Promise(),\n imageGenerator = new qq.ImageGenerator(log),\n canvas = document.createElement(\"canvas\");\n\n log(\"Attempting to generate scaled version for \" + sourceFile.name);\n\n imageGenerator.generate(sourceFile, canvas, {maxSize: maxSize, orient: orient, customResizeFunction: customResizeFunction}).then(function() {\n var scaledImageDataUri = canvas.toDataURL(type, quality),\n signalSuccess = function() {\n log(\"Success generating scaled version for \" + sourceFile.name);\n var blob = qq.dataUriToBlob(scaledImageDataUri);\n scalingEffort.success(blob);\n };\n\n if (includeExif) {\n self._insertExifHeader(sourceFile, scaledImageDataUri, log).then(function(scaledImageDataUriWithExif) {\n scaledImageDataUri = scaledImageDataUriWithExif;\n signalSuccess();\n },\n function() {\n log(\"Problem inserting EXIF header into scaled image. Using scaled image w/out EXIF data.\", \"error\");\n signalSuccess();\n });\n }\n else {\n signalSuccess();\n }\n }, function() {\n log(\"Failed attempt to generate scaled version for \" + sourceFile.name, \"error\");\n scalingEffort.failure(failedText);\n });\n\n return scalingEffort;\n },\n\n // Attempt to insert the original image's EXIF header into a scaled version.\n _insertExifHeader: function(originalImage, scaledImageDataUri, log) {\n \"use strict\";\n\n var reader = new FileReader(),\n insertionEffort = new qq.Promise(),\n originalImageDataUri = \"\";\n\n reader.onload = function() {\n originalImageDataUri = reader.result;\n insertionEffort.success(qq.ExifRestorer.restore(originalImageDataUri, scaledImageDataUri));\n };\n\n reader.onerror = function() {\n log(\"Problem reading \" + originalImage.name + \" during attempt to transfer EXIF data to scaled version.\", \"error\");\n insertionEffort.failure();\n };\n\n reader.readAsDataURL(originalImage);\n\n return insertionEffort;\n },\n\n _dataUriToBlob: function(dataUri) {\n \"use strict\";\n\n var byteString, mimeString, arrayBuffer, intArray;\n\n // convert base64 to raw binary data held in a string\n if (dataUri.split(\",\")[0].indexOf(\"base64\") >= 0) {\n byteString = atob(dataUri.split(\",\")[1]);\n }\n else {\n byteString = decodeURI(dataUri.split(\",\")[1]);\n }\n\n // extract the MIME\n mimeString = dataUri.split(\",\")[0]\n .split(\":\")[1]\n .split(\";\")[0];\n\n // write the bytes of the binary string to an ArrayBuffer\n arrayBuffer = new ArrayBuffer(byteString.length);\n intArray = new Uint8Array(arrayBuffer);\n qq.each(byteString, function(idx, character) {\n intArray[idx] = character.charCodeAt(0);\n });\n\n return this._createBlob(arrayBuffer, mimeString);\n },\n\n _createBlob: function(data, mime) {\n \"use strict\";\n\n var BlobBuilder = window.BlobBuilder ||\n window.WebKitBlobBuilder ||\n window.MozBlobBuilder ||\n window.MSBlobBuilder,\n blobBuilder = BlobBuilder && new BlobBuilder();\n\n if (blobBuilder) {\n blobBuilder.append(data);\n return blobBuilder.getBlob(mime);\n }\n else {\n return new Blob([data], {type: mime});\n }\n }\n});\n","//Based on MinifyJpeg\n//http://elicon.blog57.fc2.com/blog-entry-206.html\n\nqq.ExifRestorer = (function()\n{\n \n\tvar ExifRestorer = {};\n\t \n ExifRestorer.KEY_STR = \"ABCDEFGHIJKLMNOP\" +\n \"QRSTUVWXYZabcdef\" +\n \"ghijklmnopqrstuv\" +\n \"wxyz0123456789+/\" +\n \"=\";\n\n ExifRestorer.encode64 = function(input)\n {\n var output = \"\",\n chr1, chr2, chr3 = \"\",\n enc1, enc2, enc3, enc4 = \"\",\n i = 0;\n\n do {\n chr1 = input[i++];\n chr2 = input[i++];\n chr3 = input[i++];\n\n enc1 = chr1 >> 2;\n enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);\n enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);\n enc4 = chr3 & 63;\n\n if (isNaN(chr2)) {\n enc3 = enc4 = 64;\n } else if (isNaN(chr3)) {\n enc4 = 64;\n }\n\n output = output +\n this.KEY_STR.charAt(enc1) +\n this.KEY_STR.charAt(enc2) +\n this.KEY_STR.charAt(enc3) +\n this.KEY_STR.charAt(enc4);\n chr1 = chr2 = chr3 = \"\";\n enc1 = enc2 = enc3 = enc4 = \"\";\n } while (i < input.length);\n\n return output;\n };\n \n ExifRestorer.restore = function(origFileBase64, resizedFileBase64)\n {\n var expectedBase64Header = \"data:image/jpeg;base64,\";\n\n if (!origFileBase64.match(expectedBase64Header))\n {\n \treturn resizedFileBase64;\n } \n \n var rawImage = this.decode64(origFileBase64.replace(expectedBase64Header, \"\"));\n var segments = this.slice2Segments(rawImage);\n \n var image = this.exifManipulation(resizedFileBase64, segments);\n \n return expectedBase64Header + this.encode64(image);\n \n };\n\n\n ExifRestorer.exifManipulation = function(resizedFileBase64, segments)\n {\n var exifArray = this.getExifArray(segments),\n newImageArray = this.insertExif(resizedFileBase64, exifArray),\n aBuffer = new Uint8Array(newImageArray);\n\n return aBuffer;\n };\n\n\n ExifRestorer.getExifArray = function(segments)\n {\n var seg;\n for (var x = 0; x < segments.length; x++)\n {\n seg = segments[x];\n if (seg[0] == 255 & seg[1] == 225) //(ff e1)\n {\n return seg;\n }\n }\n return [];\n };\n\n\n ExifRestorer.insertExif = function(resizedFileBase64, exifArray)\n {\n var imageData = resizedFileBase64.replace(\"data:image/jpeg;base64,\", \"\"),\n buf = this.decode64(imageData),\n separatePoint = buf.indexOf(255,3),\n mae = buf.slice(0, separatePoint),\n ato = buf.slice(separatePoint),\n array = mae;\n\n array = array.concat(exifArray);\n array = array.concat(ato);\n return array;\n };\n\n\n \n ExifRestorer.slice2Segments = function(rawImageArray)\n {\n var head = 0,\n segments = [];\n\n while (1)\n {\n if (rawImageArray[head] == 255 & rawImageArray[head + 1] == 218){break;}\n if (rawImageArray[head] == 255 & rawImageArray[head + 1] == 216)\n {\n head += 2;\n }\n else\n {\n var length = rawImageArray[head + 2] * 256 + rawImageArray[head + 3],\n endPoint = head + length + 2,\n seg = rawImageArray.slice(head, endPoint);\n segments.push(seg);\n head = endPoint;\n }\n if (head > rawImageArray.length){break;}\n }\n\n return segments;\n };\n\n\n \n ExifRestorer.decode64 = function(input) \n {\n var output = \"\",\n chr1, chr2, chr3 = \"\",\n enc1, enc2, enc3, enc4 = \"\",\n i = 0,\n buf = [];\n\n // remove all characters that are not A-Z, a-z, 0-9, +, /, or =\n var base64test = /[^A-Za-z0-9\\+\\/\\=]/g;\n if (base64test.exec(input)) {\n throw new Error(\"There were invalid base64 characters in the input text. \" +\n \"Valid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='\");\n }\n input = input.replace(/[^A-Za-z0-9\\+\\/\\=]/g, \"\");\n\n do {\n enc1 = this.KEY_STR.indexOf(input.charAt(i++));\n enc2 = this.KEY_STR.indexOf(input.charAt(i++));\n enc3 = this.KEY_STR.indexOf(input.charAt(i++));\n enc4 = this.KEY_STR.indexOf(input.charAt(i++));\n\n chr1 = (enc1 << 2) | (enc2 >> 4);\n chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);\n chr3 = ((enc3 & 3) << 6) | enc4;\n\n buf.push(chr1);\n\n if (enc3 != 64) {\n buf.push(chr2);\n }\n if (enc4 != 64) {\n buf.push(chr3);\n }\n\n chr1 = chr2 = chr3 = \"\";\n enc1 = enc2 = enc3 = enc4 = \"\";\n\n } while (i < input.length);\n\n return buf;\n };\n\n \n return ExifRestorer;\n})();\n","/* globals qq */\n/**\n * Keeps a running tally of total upload progress for a batch of files.\n *\n * @param callback Invoked when total progress changes, passing calculated total loaded & total size values.\n * @param getSize Function that returns the size of a file given its ID\n * @constructor\n */\nqq.TotalProgress = function(callback, getSize) {\n \"use strict\";\n\n var perFileProgress = {},\n totalLoaded = 0,\n totalSize = 0,\n\n lastLoadedSent = -1,\n lastTotalSent = -1,\n callbackProxy = function(loaded, total) {\n if (loaded !== lastLoadedSent || total !== lastTotalSent) {\n callback(loaded, total);\n }\n\n lastLoadedSent = loaded;\n lastTotalSent = total;\n },\n\n /**\n * @param failed Array of file IDs that have failed\n * @param retryable Array of file IDs that are retryable\n * @returns true if none of the failed files are eligible for retry\n */\n noRetryableFiles = function(failed, retryable) {\n var none = true;\n\n qq.each(failed, function(idx, failedId) {\n if (qq.indexOf(retryable, failedId) >= 0) {\n none = false;\n return false;\n }\n });\n\n return none;\n },\n\n onCancel = function(id) {\n updateTotalProgress(id, -1, -1);\n delete perFileProgress[id];\n },\n\n onAllComplete = function(successful, failed, retryable) {\n if (failed.length === 0 || noRetryableFiles(failed, retryable)) {\n callbackProxy(totalSize, totalSize);\n this.reset();\n }\n },\n\n onNew = function(id) {\n var size = getSize(id);\n\n // We might not know the size yet, such as for blob proxies\n if (size > 0) {\n updateTotalProgress(id, 0, size);\n perFileProgress[id] = {loaded: 0, total: size};\n }\n },\n\n /**\n * Invokes the callback with the current total progress of all files in the batch. Called whenever it may\n * be appropriate to re-calculate and disseminate this data.\n *\n * @param id ID of a file that has changed in some important way\n * @param newLoaded New loaded value for this file. -1 if this value should no longer be part of calculations\n * @param newTotal New total size of the file. -1 if this value should no longer be part of calculations\n */\n updateTotalProgress = function(id, newLoaded, newTotal) {\n var oldLoaded = perFileProgress[id] ? perFileProgress[id].loaded : 0,\n oldTotal = perFileProgress[id] ? perFileProgress[id].total : 0;\n\n if (newLoaded === -1 && newTotal === -1) {\n totalLoaded -= oldLoaded;\n totalSize -= oldTotal;\n }\n else {\n if (newLoaded) {\n totalLoaded += newLoaded - oldLoaded;\n }\n if (newTotal) {\n totalSize += newTotal - oldTotal;\n }\n }\n\n callbackProxy(totalLoaded, totalSize);\n };\n\n qq.extend(this, {\n // Called when a batch of files has completed uploading.\n onAllComplete: onAllComplete,\n\n // Called when the status of a file has changed.\n onStatusChange: function(id, oldStatus, newStatus) {\n if (newStatus === qq.status.CANCELED || newStatus === qq.status.REJECTED) {\n onCancel(id);\n }\n else if (newStatus === qq.status.SUBMITTING) {\n onNew(id);\n }\n },\n\n // Called whenever the upload progress of an individual file has changed.\n onIndividualProgress: function(id, loaded, total) {\n updateTotalProgress(id, loaded, total);\n perFileProgress[id] = {loaded: loaded, total: total};\n },\n\n // Called whenever the total size of a file has changed, such as when the size of a generated blob is known.\n onNewSize: function(id) {\n onNew(id);\n },\n\n reset: function() {\n perFileProgress = {};\n totalLoaded = 0;\n totalSize = 0;\n }\n });\n};\n","/*globals qq*/\nqq.PasteSupport = function(o) {\n \"use strict\";\n\n var options, detachPasteHandler;\n\n options = {\n targetElement: null,\n callbacks: {\n log: function(message, level) {},\n pasteReceived: function(blob) {}\n }\n };\n\n function isImage(item) {\n return item.type &&\n item.type.indexOf(\"image/\") === 0;\n }\n\n function registerPasteHandler() {\n detachPasteHandler = qq(options.targetElement).attach(\"paste\", function(event) {\n var clipboardData = event.clipboardData;\n\n if (clipboardData) {\n qq.each(clipboardData.items, function(idx, item) {\n if (isImage(item)) {\n var blob = item.getAsFile();\n options.callbacks.pasteReceived(blob);\n }\n });\n }\n });\n }\n\n function unregisterPasteHandler() {\n if (detachPasteHandler) {\n detachPasteHandler();\n }\n }\n\n qq.extend(options, o);\n registerPasteHandler();\n\n qq.extend(this, {\n reset: function() {\n unregisterPasteHandler();\n }\n });\n};\n","/* globals qq */\n/**\n * Module that handles support for existing forms.\n *\n * @param options Options passed from the integrator-supplied options related to form support.\n * @param startUpload Callback to invoke when files \"stored\" should be uploaded.\n * @param log Proxy for the logger\n * @constructor\n */\nqq.FormSupport = function(options, startUpload, log) {\n \"use strict\";\n var self = this,\n interceptSubmit = options.interceptSubmit,\n formEl = options.element,\n autoUpload = options.autoUpload;\n\n // Available on the public API associated with this module.\n qq.extend(this, {\n // To be used by the caller to determine if the endpoint will be determined by some processing\n // that occurs in this module, such as if the form has an action attribute.\n // Ignore if `attachToForm === false`.\n newEndpoint: null,\n\n // To be used by the caller to determine if auto uploading should be allowed.\n // Ignore if `attachToForm === false`.\n newAutoUpload: autoUpload,\n\n // true if a form was detected and is being tracked by this module\n attachedToForm: false,\n\n // Returns an object with names and values for all valid form elements associated with the attached form.\n getFormInputsAsObject: function() {\n /* jshint eqnull:true */\n if (formEl == null) {\n return null;\n }\n\n return self._form2Obj(formEl);\n }\n });\n\n // If the form contains an action attribute, this should be the new upload endpoint.\n function determineNewEndpoint(formEl) {\n if (formEl.getAttribute(\"action\")) {\n self.newEndpoint = formEl.getAttribute(\"action\");\n }\n }\n\n // Return true only if the form is valid, or if we cannot make this determination.\n // If the form is invalid, ensure invalid field(s) are highlighted in the UI.\n function validateForm(formEl, nativeSubmit) {\n if (formEl.checkValidity && !formEl.checkValidity()) {\n log(\"Form did not pass validation checks - will not upload.\", \"error\");\n nativeSubmit();\n }\n else {\n return true;\n }\n }\n\n // Intercept form submit attempts, unless the integrator has told us not to do this.\n function maybeUploadOnSubmit(formEl) {\n var nativeSubmit = formEl.submit;\n\n // Intercept and squelch submit events.\n qq(formEl).attach(\"submit\", function(event) {\n event = event || window.event;\n\n if (event.preventDefault) {\n event.preventDefault();\n }\n else {\n event.returnValue = false;\n }\n\n validateForm(formEl, nativeSubmit) && startUpload();\n });\n\n // The form's `submit()` function may be called instead (i.e. via jQuery.submit()).\n // Intercept that too.\n formEl.submit = function() {\n validateForm(formEl, nativeSubmit) && startUpload();\n };\n }\n\n // If the element value passed from the uploader is a string, assume it is an element ID - select it.\n // The rest of the code in this module depends on this being an HTMLElement.\n function determineFormEl(formEl) {\n if (formEl) {\n if (qq.isString(formEl)) {\n formEl = document.getElementById(formEl);\n }\n\n if (formEl) {\n log(\"Attaching to form element.\");\n determineNewEndpoint(formEl);\n interceptSubmit && maybeUploadOnSubmit(formEl);\n }\n }\n\n return formEl;\n }\n\n formEl = determineFormEl(formEl);\n this.attachedToForm = !!formEl;\n};\n\nqq.extend(qq.FormSupport.prototype, {\n // Converts all relevant form fields to key/value pairs. This is meant to mimic the data a browser will\n // construct from a given form when the form is submitted.\n _form2Obj: function(form) {\n \"use strict\";\n var obj = {},\n notIrrelevantType = function(type) {\n var irrelevantTypes = [\n \"button\",\n \"image\",\n \"reset\",\n \"submit\"\n ];\n\n return qq.indexOf(irrelevantTypes, type.toLowerCase()) < 0;\n },\n radioOrCheckbox = function(type) {\n return qq.indexOf([\"checkbox\", \"radio\"], type.toLowerCase()) >= 0;\n },\n ignoreValue = function(el) {\n if (radioOrCheckbox(el.type) && !el.checked) {\n return true;\n }\n\n return el.disabled && el.type.toLowerCase() !== \"hidden\";\n },\n selectValue = function(select) {\n var value = null;\n\n qq.each(qq(select).children(), function(idx, child) {\n if (child.tagName.toLowerCase() === \"option\" && child.selected) {\n value = child.value;\n return false;\n }\n });\n\n return value;\n };\n\n qq.each(form.elements, function(idx, el) {\n if ((qq.isInput(el, true) || el.tagName.toLowerCase() === \"textarea\") &&\n notIrrelevantType(el.type) &&\n !ignoreValue(el)) {\n\n obj[el.name] = el.value;\n }\n else if (el.tagName.toLowerCase() === \"select\" && !ignoreValue(el)) {\n var value = selectValue(el);\n\n if (value !== null) {\n obj[el.name] = value;\n }\n }\n });\n\n return obj;\n }\n});\n","/*globals qq*/\n/**\n * Upload handler used that assumes the current user agent does not have any support for the\n * File API, and, therefore, makes use of iframes and forms to submit the files directly to\n * a generic server.\n *\n * @param options Options passed from the base handler\n * @param proxy Callbacks & methods used to query for or push out data/changes\n */\nqq.traditional = qq.traditional || {};\nqq.traditional.FormUploadHandler = function(options, proxy) {\n \"use strict\";\n\n var handler = this,\n getName = proxy.getName,\n getUuid = proxy.getUuid,\n log = proxy.log;\n\n /**\n * Returns json object received by iframe from server.\n */\n function getIframeContentJson(id, iframe) {\n /*jshint evil: true*/\n\n var response, doc, innerHtml;\n\n //IE may throw an \"access is denied\" error when attempting to access contentDocument on the iframe in some cases\n try {\n // iframe.contentWindow.document - for IE<7\n doc = iframe.contentDocument || iframe.contentWindow.document;\n innerHtml = doc.body.innerHTML;\n\n log(\"converting iframe's innerHTML to JSON\");\n log(\"innerHTML = \" + innerHtml);\n //plain text response may be wrapped in tag\n if (innerHtml && innerHtml.match(/^ 1 && !options.allowMultipleItems) {\n options.callbacks.processingDroppedFilesComplete([]);\n options.callbacks.dropError(\"tooManyFilesError\", \"\");\n uploadDropZone.dropDisabled(false);\n handleDataTransferPromise.failure();\n }\n else {\n droppedFiles = [];\n\n if (qq.isFolderDropSupported(dataTransfer)) {\n qq.each(dataTransfer.items, function(idx, item) {\n var entry = item.webkitGetAsEntry();\n\n if (entry) {\n //due to a bug in Chrome's File System API impl - #149735\n if (entry.isFile) {\n droppedFiles.push(item.getAsFile());\n }\n\n else {\n pendingFolderPromises.push(traverseFileTree(entry).done(function() {\n pendingFolderPromises.pop();\n if (pendingFolderPromises.length === 0) {\n handleDataTransferPromise.success();\n }\n }));\n }\n }\n });\n }\n else {\n droppedFiles = dataTransfer.files;\n }\n\n if (pendingFolderPromises.length === 0) {\n handleDataTransferPromise.success();\n }\n }\n\n return handleDataTransferPromise;\n }\n\n function setupDropzone(dropArea) {\n var dropZone = new qq.UploadDropZone({\n HIDE_ZONES_EVENT_NAME: HIDE_ZONES_EVENT_NAME,\n element: dropArea,\n onEnter: function(e) {\n qq(dropArea).addClass(options.classes.dropActive);\n e.stopPropagation();\n },\n onLeaveNotDescendants: function(e) {\n qq(dropArea).removeClass(options.classes.dropActive);\n },\n onDrop: function(e) {\n handleDataTransfer(e.dataTransfer, dropZone).then(\n function() {\n uploadDroppedFiles(droppedFiles, dropZone);\n },\n function() {\n options.callbacks.dropLog(\"Drop event DataTransfer parsing failed. No files will be uploaded.\", \"error\");\n }\n );\n }\n });\n\n disposeSupport.addDisposer(function() {\n dropZone.dispose();\n });\n\n qq(dropArea).hasAttribute(HIDE_BEFORE_ENTER_ATTR) && qq(dropArea).hide();\n\n uploadDropZones.push(dropZone);\n\n return dropZone;\n }\n\n function isFileDrag(dragEvent) {\n var fileDrag;\n\n qq.each(dragEvent.dataTransfer.types, function(key, val) {\n if (val === \"Files\") {\n fileDrag = true;\n return false;\n }\n });\n\n return fileDrag;\n }\n\n // Attempt to determine when the file has left the document. It is not always possible to detect this\n // in all cases, but it is generally possible in all browsers, with a few exceptions.\n //\n // Exceptions:\n // * IE10+ & Safari: We can't detect a file leaving the document if the Explorer window housing the file\n // overlays the browser window.\n // * IE10+: If the file is dragged out of the window too quickly, IE does not set the expected values of the\n // event's X & Y properties.\n function leavingDocumentOut(e) {\n if (qq.firefox()) {\n return !e.relatedTarget;\n }\n\n if (qq.safari()) {\n return e.x < 0 || e.y < 0;\n }\n\n return e.x === 0 && e.y === 0;\n }\n\n function setupDragDrop() {\n var dropZones = options.dropZoneElements,\n\n maybeHideDropZones = function() {\n setTimeout(function() {\n qq.each(dropZones, function(idx, dropZone) {\n qq(dropZone).hasAttribute(HIDE_BEFORE_ENTER_ATTR) && qq(dropZone).hide();\n qq(dropZone).removeClass(options.classes.dropActive);\n });\n }, 10);\n };\n\n qq.each(dropZones, function(idx, dropZone) {\n var uploadDropZone = setupDropzone(dropZone);\n\n // IE <= 9 does not support the File API used for drag+drop uploads\n if (dropZones.length && qq.supportedFeatures.fileDrop) {\n disposeSupport.attach(document, \"dragenter\", function(e) {\n if (!uploadDropZone.dropDisabled() && isFileDrag(e)) {\n qq.each(dropZones, function(idx, dropZone) {\n // We can't apply styles to non-HTMLElements, since they lack the `style` property.\n // Also, if the drop zone isn't initially hidden, let's not mess with `style.display`.\n if (dropZone instanceof HTMLElement &&\n qq(dropZone).hasAttribute(HIDE_BEFORE_ENTER_ATTR)) {\n\n qq(dropZone).css({display: \"block\"});\n }\n });\n }\n });\n }\n });\n\n disposeSupport.attach(document, \"dragleave\", function(e) {\n if (leavingDocumentOut(e)) {\n maybeHideDropZones();\n }\n });\n\n // Just in case we were not able to detect when a dragged file has left the document,\n // hide all relevant drop zones the next time the mouse enters the document.\n // Note that mouse events such as this one are not fired during drag operations.\n disposeSupport.attach(qq(document).children()[0], \"mouseenter\", function(e) {\n maybeHideDropZones();\n });\n\n disposeSupport.attach(document, \"drop\", function(e) {\n e.preventDefault();\n maybeHideDropZones();\n });\n\n disposeSupport.attach(document, HIDE_ZONES_EVENT_NAME, maybeHideDropZones);\n }\n\n setupDragDrop();\n\n qq.extend(this, {\n setupExtraDropzone: function(element) {\n options.dropZoneElements.push(element);\n setupDropzone(element);\n },\n\n removeDropzone: function(element) {\n var i,\n dzs = options.dropZoneElements;\n\n for (i in dzs) {\n if (dzs[i] === element) {\n return dzs.splice(i, 1);\n }\n }\n },\n\n dispose: function() {\n disposeSupport.dispose();\n qq.each(uploadDropZones, function(idx, dropZone) {\n dropZone.dispose();\n });\n }\n });\n};\n\nqq.DragAndDrop.callbacks = function() {\n \"use strict\";\n\n return {\n processingDroppedFiles: function() {},\n processingDroppedFilesComplete: function(files, targetEl) {},\n dropError: function(code, errorSpecifics) {\n qq.log(\"Drag & drop error code '\" + code + \" with these specifics: '\" + errorSpecifics + \"'\", \"error\");\n },\n dropLog: function(message, level) {\n qq.log(message, level);\n }\n };\n};\n\nqq.UploadDropZone = function(o) {\n \"use strict\";\n\n var disposeSupport = new qq.DisposeSupport(),\n options, element, preventDrop, dropOutsideDisabled;\n\n options = {\n element: null,\n onEnter: function(e) {},\n onLeave: function(e) {},\n // is not fired when leaving element by hovering descendants\n onLeaveNotDescendants: function(e) {},\n onDrop: function(e) {}\n };\n\n qq.extend(options, o);\n element = options.element;\n\n function dragoverShouldBeCanceled() {\n return qq.safari() || (qq.firefox() && qq.windows());\n }\n\n function disableDropOutside(e) {\n // run only once for all instances\n if (!dropOutsideDisabled) {\n\n // for these cases we need to catch onDrop to reset dropArea\n if (dragoverShouldBeCanceled) {\n disposeSupport.attach(document, \"dragover\", function(e) {\n e.preventDefault();\n });\n } else {\n disposeSupport.attach(document, \"dragover\", function(e) {\n if (e.dataTransfer) {\n e.dataTransfer.dropEffect = \"none\";\n e.preventDefault();\n }\n });\n }\n\n dropOutsideDisabled = true;\n }\n }\n\n function isValidFileDrag(e) {\n // e.dataTransfer currently causing IE errors\n // IE9 does NOT support file API, so drag-and-drop is not possible\n if (!qq.supportedFeatures.fileDrop) {\n return false;\n }\n\n var effectTest, dt = e.dataTransfer,\n // do not check dt.types.contains in webkit, because it crashes safari 4\n isSafari = qq.safari();\n\n // dt.effectAllowed is none in Safari 5\n // dt.types.contains check is for firefox\n\n // dt.effectAllowed crashes IE 11 & 10 when files have been dragged from\n // the filesystem\n effectTest = qq.ie() && qq.supportedFeatures.fileDrop ? true : dt.effectAllowed !== \"none\";\n return dt && effectTest && (dt.files || (!isSafari && dt.types.contains && dt.types.contains(\"Files\")));\n }\n\n function isOrSetDropDisabled(isDisabled) {\n if (isDisabled !== undefined) {\n preventDrop = isDisabled;\n }\n return preventDrop;\n }\n\n function triggerHidezonesEvent() {\n var hideZonesEvent;\n\n function triggerUsingOldApi() {\n hideZonesEvent = document.createEvent(\"Event\");\n hideZonesEvent.initEvent(options.HIDE_ZONES_EVENT_NAME, true, true);\n }\n\n if (window.CustomEvent) {\n try {\n hideZonesEvent = new CustomEvent(options.HIDE_ZONES_EVENT_NAME);\n }\n catch (err) {\n triggerUsingOldApi();\n }\n }\n else {\n triggerUsingOldApi();\n }\n\n document.dispatchEvent(hideZonesEvent);\n }\n\n function attachEvents() {\n disposeSupport.attach(element, \"dragover\", function(e) {\n if (!isValidFileDrag(e)) {\n return;\n }\n\n // dt.effectAllowed crashes IE 11 & 10 when files have been dragged from\n // the filesystem\n var effect = qq.ie() && qq.supportedFeatures.fileDrop ? null : e.dataTransfer.effectAllowed;\n if (effect === \"move\" || effect === \"linkMove\") {\n e.dataTransfer.dropEffect = \"move\"; // for FF (only move allowed)\n } else {\n e.dataTransfer.dropEffect = \"copy\"; // for Chrome\n }\n\n e.stopPropagation();\n e.preventDefault();\n });\n\n disposeSupport.attach(element, \"dragenter\", function(e) {\n if (!isOrSetDropDisabled()) {\n if (!isValidFileDrag(e)) {\n return;\n }\n options.onEnter(e);\n }\n });\n\n disposeSupport.attach(element, \"dragleave\", function(e) {\n if (!isValidFileDrag(e)) {\n return;\n }\n\n options.onLeave(e);\n\n var relatedTarget = document.elementFromPoint(e.clientX, e.clientY);\n // do not fire when moving a mouse over a descendant\n if (qq(this).contains(relatedTarget)) {\n return;\n }\n\n options.onLeaveNotDescendants(e);\n });\n\n disposeSupport.attach(element, \"drop\", function(e) {\n if (!isOrSetDropDisabled()) {\n if (!isValidFileDrag(e)) {\n return;\n }\n\n e.preventDefault();\n e.stopPropagation();\n options.onDrop(e);\n\n triggerHidezonesEvent();\n }\n });\n }\n\n disableDropOutside();\n attachEvents();\n\n qq.extend(this, {\n dropDisabled: function(isDisabled) {\n return isOrSetDropDisabled(isDisabled);\n },\n\n dispose: function() {\n disposeSupport.dispose();\n },\n\n getElement: function() {\n return element;\n }\n });\n};\n","/*globals qq */\n/**\n * Defines the public API for FineUploader mode.\n */\n(function() {\n \"use strict\";\n\n qq.uiPublicApi = {\n addInitialFiles: function(cannedFileList) {\n this._parent.prototype.addInitialFiles.apply(this, arguments);\n this._templating.addCacheToDom();\n },\n\n clearStoredFiles: function() {\n this._parent.prototype.clearStoredFiles.apply(this, arguments);\n this._templating.clearFiles();\n },\n\n addExtraDropzone: function(element) {\n this._dnd && this._dnd.setupExtraDropzone(element);\n },\n\n removeExtraDropzone: function(element) {\n if (this._dnd) {\n return this._dnd.removeDropzone(element);\n }\n },\n\n getItemByFileId: function(id) {\n if (!this._templating.isHiddenForever(id)) {\n return this._templating.getFileContainer(id);\n }\n },\n\n reset: function() {\n this._parent.prototype.reset.apply(this, arguments);\n this._templating.reset();\n\n if (!this._options.button && this._templating.getButton()) {\n this._defaultButtonId = this._createUploadButton({\n element: this._templating.getButton(),\n title: this._options.text.fileInputTitle\n }).getButtonId();\n }\n\n if (this._dnd) {\n this._dnd.dispose();\n this._dnd = this._setupDragAndDrop();\n }\n\n this._totalFilesInBatch = 0;\n this._filesInBatchAddedToUi = 0;\n\n this._setupClickAndEditEventHandlers();\n },\n\n setName: function(id, newName) {\n var formattedFilename = this._options.formatFileName(newName);\n\n this._parent.prototype.setName.apply(this, arguments);\n this._templating.updateFilename(id, formattedFilename);\n },\n\n pauseUpload: function(id) {\n var paused = this._parent.prototype.pauseUpload.apply(this, arguments);\n\n paused && this._templating.uploadPaused(id);\n return paused;\n },\n\n continueUpload: function(id) {\n var continued = this._parent.prototype.continueUpload.apply(this, arguments);\n\n continued && this._templating.uploadContinued(id);\n return continued;\n },\n\n getId: function(fileContainerOrChildEl) {\n return this._templating.getFileId(fileContainerOrChildEl);\n },\n\n getDropTarget: function(fileId) {\n var file = this.getFile(fileId);\n\n return file.qqDropTarget;\n }\n };\n\n /**\n * Defines the private (internal) API for FineUploader mode.\n */\n qq.uiPrivateApi = {\n _getButton: function(buttonId) {\n var button = this._parent.prototype._getButton.apply(this, arguments);\n\n if (!button) {\n if (buttonId === this._defaultButtonId) {\n button = this._templating.getButton();\n }\n }\n\n return button;\n },\n\n _removeFileItem: function(fileId) {\n this._templating.removeFile(fileId);\n },\n\n _setupClickAndEditEventHandlers: function() {\n this._fileButtonsClickHandler = qq.FileButtonsClickHandler && this._bindFileButtonsClickEvent();\n\n // A better approach would be to check specifically for focusin event support by querying the DOM API,\n // but the DOMFocusIn event is not exposed as a property, so we have to resort to UA string sniffing.\n this._focusinEventSupported = !qq.firefox();\n\n if (this._isEditFilenameEnabled())\n {\n this._filenameClickHandler = this._bindFilenameClickEvent();\n this._filenameInputFocusInHandler = this._bindFilenameInputFocusInEvent();\n this._filenameInputFocusHandler = this._bindFilenameInputFocusEvent();\n }\n },\n\n _setupDragAndDrop: function() {\n var self = this,\n dropZoneElements = this._options.dragAndDrop.extraDropzones,\n templating = this._templating,\n defaultDropZone = templating.getDropZone();\n\n defaultDropZone && dropZoneElements.push(defaultDropZone);\n\n return new qq.DragAndDrop({\n dropZoneElements: dropZoneElements,\n allowMultipleItems: this._options.multiple,\n classes: {\n dropActive: this._options.classes.dropActive\n },\n callbacks: {\n processingDroppedFiles: function() {\n templating.showDropProcessing();\n },\n processingDroppedFilesComplete: function(files, targetEl) {\n templating.hideDropProcessing();\n\n qq.each(files, function(idx, file) {\n file.qqDropTarget = targetEl;\n });\n\n if (files.length) {\n self.addFiles(files, null, null);\n }\n },\n dropError: function(code, errorData) {\n self._itemError(code, errorData);\n },\n dropLog: function(message, level) {\n self.log(message, level);\n }\n }\n });\n },\n\n _bindFileButtonsClickEvent: function() {\n var self = this;\n\n return new qq.FileButtonsClickHandler({\n templating: this._templating,\n\n log: function(message, lvl) {\n self.log(message, lvl);\n },\n\n onDeleteFile: function(fileId) {\n self.deleteFile(fileId);\n },\n\n onCancel: function(fileId) {\n self.cancel(fileId);\n },\n\n onRetry: function(fileId) {\n self.retry(fileId);\n },\n\n onPause: function(fileId) {\n self.pauseUpload(fileId);\n },\n\n onContinue: function(fileId) {\n self.continueUpload(fileId);\n },\n\n onGetName: function(fileId) {\n return self.getName(fileId);\n }\n });\n },\n\n _isEditFilenameEnabled: function() {\n /*jshint -W014 */\n return this._templating.isEditFilenamePossible()\n && !this._options.autoUpload\n && qq.FilenameClickHandler\n && qq.FilenameInputFocusHandler\n && qq.FilenameInputFocusHandler;\n },\n\n _filenameEditHandler: function() {\n var self = this,\n templating = this._templating;\n\n return {\n templating: templating,\n log: function(message, lvl) {\n self.log(message, lvl);\n },\n onGetUploadStatus: function(fileId) {\n return self.getUploads({id: fileId}).status;\n },\n onGetName: function(fileId) {\n return self.getName(fileId);\n },\n onSetName: function(id, newName) {\n self.setName(id, newName);\n },\n onEditingStatusChange: function(id, isEditing) {\n var qqInput = qq(templating.getEditInput(id)),\n qqFileContainer = qq(templating.getFileContainer(id));\n\n if (isEditing) {\n qqInput.addClass(\"qq-editing\");\n templating.hideFilename(id);\n templating.hideEditIcon(id);\n }\n else {\n qqInput.removeClass(\"qq-editing\");\n templating.showFilename(id);\n templating.showEditIcon(id);\n }\n\n // Force IE8 and older to repaint\n qqFileContainer.addClass(\"qq-temp\").removeClass(\"qq-temp\");\n }\n };\n },\n\n _onUploadStatusChange: function(id, oldStatus, newStatus) {\n this._parent.prototype._onUploadStatusChange.apply(this, arguments);\n\n if (this._isEditFilenameEnabled()) {\n // Status for a file exists before it has been added to the DOM, so we must be careful here.\n if (this._templating.getFileContainer(id) && newStatus !== qq.status.SUBMITTED) {\n this._templating.markFilenameEditable(id);\n this._templating.hideEditIcon(id);\n }\n }\n\n if (oldStatus === qq.status.UPLOAD_RETRYING && newStatus === qq.status.UPLOADING) {\n this._templating.hideRetry(id);\n this._templating.setStatusText(id);\n qq(this._templating.getFileContainer(id)).removeClass(this._classes.retrying);\n }\n else if (newStatus === qq.status.UPLOAD_FAILED) {\n this._templating.hidePause(id);\n }\n },\n\n _bindFilenameInputFocusInEvent: function() {\n var spec = qq.extend({}, this._filenameEditHandler());\n\n return new qq.FilenameInputFocusInHandler(spec);\n },\n\n _bindFilenameInputFocusEvent: function() {\n var spec = qq.extend({}, this._filenameEditHandler());\n\n return new qq.FilenameInputFocusHandler(spec);\n },\n\n _bindFilenameClickEvent: function() {\n var spec = qq.extend({}, this._filenameEditHandler());\n\n return new qq.FilenameClickHandler(spec);\n },\n\n _storeForLater: function(id) {\n this._parent.prototype._storeForLater.apply(this, arguments);\n this._templating.hideSpinner(id);\n },\n\n _onAllComplete: function(successful, failed) {\n this._parent.prototype._onAllComplete.apply(this, arguments);\n this._templating.resetTotalProgress();\n },\n\n _onSubmit: function(id, name) {\n var file = this.getFile(id);\n\n if (file && file.qqPath && this._options.dragAndDrop.reportDirectoryPaths) {\n this._paramsStore.addReadOnly(id, {\n qqpath: file.qqPath\n });\n }\n\n this._parent.prototype._onSubmit.apply(this, arguments);\n this._addToList(id, name);\n },\n\n // The file item has been added to the DOM.\n _onSubmitted: function(id) {\n // If the edit filename feature is enabled, mark the filename element as \"editable\" and the associated edit icon\n if (this._isEditFilenameEnabled()) {\n this._templating.markFilenameEditable(id);\n this._templating.showEditIcon(id);\n\n // If the focusin event is not supported, we must add a focus handler to the newly create edit filename text input\n if (!this._focusinEventSupported) {\n this._filenameInputFocusHandler.addHandler(this._templating.getEditInput(id));\n }\n }\n },\n\n // Update the progress bar & percentage as the file is uploaded\n _onProgress: function(id, name, loaded, total) {\n this._parent.prototype._onProgress.apply(this, arguments);\n\n this._templating.updateProgress(id, loaded, total);\n\n if (total === 0 || Math.round(loaded / total * 100) === 100) {\n this._templating.hideCancel(id);\n this._templating.hidePause(id);\n this._templating.hideProgress(id);\n this._templating.setStatusText(id, this._options.text.waitingForResponse);\n\n // If ~last byte was sent, display total file size\n this._displayFileSize(id);\n }\n else {\n // If still uploading, display percentage - total size is actually the total request(s) size\n this._displayFileSize(id, loaded, total);\n }\n },\n\n _onTotalProgress: function(loaded, total) {\n this._parent.prototype._onTotalProgress.apply(this, arguments);\n this._templating.updateTotalProgress(loaded, total);\n },\n\n _onComplete: function(id, name, result, xhr) {\n var parentRetVal = this._parent.prototype._onComplete.apply(this, arguments),\n templating = this._templating,\n fileContainer = templating.getFileContainer(id),\n self = this;\n\n function completeUpload(result) {\n // If this file is not represented in the templating module, perhaps it was hidden intentionally.\n // If so, don't perform any UI-related tasks related to this file.\n if (!fileContainer) {\n return;\n }\n\n templating.setStatusText(id);\n\n qq(fileContainer).removeClass(self._classes.retrying);\n templating.hideProgress(id);\n\n if (self.getUploads({id: id}).status !== qq.status.UPLOAD_FAILED) {\n templating.hideCancel(id);\n }\n templating.hideSpinner(id);\n\n if (result.success) {\n self._markFileAsSuccessful(id);\n }\n else {\n qq(fileContainer).addClass(self._classes.fail);\n templating.showCancel(id);\n\n if (templating.isRetryPossible() && !self._preventRetries[id]) {\n qq(fileContainer).addClass(self._classes.retryable);\n templating.showRetry(id);\n }\n self._controlFailureTextDisplay(id, result);\n }\n }\n\n // The parent may need to perform some async operation before we can accurately determine the status of the upload.\n if (parentRetVal instanceof qq.Promise) {\n parentRetVal.done(function(newResult) {\n completeUpload(newResult);\n });\n\n }\n else {\n completeUpload(result);\n }\n\n return parentRetVal;\n },\n\n _markFileAsSuccessful: function(id) {\n var templating = this._templating;\n\n if (this._isDeletePossible()) {\n templating.showDeleteButton(id);\n }\n\n qq(templating.getFileContainer(id)).addClass(this._classes.success);\n\n this._maybeUpdateThumbnail(id);\n },\n\n _onUploadPrep: function(id) {\n this._parent.prototype._onUploadPrep.apply(this, arguments);\n this._templating.showSpinner(id);\n },\n\n _onUpload: function(id, name) {\n var parentRetVal = this._parent.prototype._onUpload.apply(this, arguments);\n\n this._templating.showSpinner(id);\n\n return parentRetVal;\n },\n\n _onUploadChunk: function(id, chunkData) {\n this._parent.prototype._onUploadChunk.apply(this, arguments);\n\n // Only display the pause button if we have finished uploading at least one chunk\n // & this file can be resumed\n if (chunkData.partIndex > 0 && this._handler.isResumable(id)) {\n this._templating.allowPause(id);\n }\n },\n\n _onCancel: function(id, name) {\n this._parent.prototype._onCancel.apply(this, arguments);\n this._removeFileItem(id);\n\n if (this._getNotFinished() === 0) {\n this._templating.resetTotalProgress();\n }\n },\n\n _onBeforeAutoRetry: function(id) {\n var retryNumForDisplay, maxAuto, retryNote;\n\n this._parent.prototype._onBeforeAutoRetry.apply(this, arguments);\n\n this._showCancelLink(id);\n\n if (this._options.retry.showAutoRetryNote) {\n retryNumForDisplay = this._autoRetries[id];\n maxAuto = this._options.retry.maxAutoAttempts;\n\n retryNote = this._options.retry.autoRetryNote.replace(/\\{retryNum\\}/g, retryNumForDisplay);\n retryNote = retryNote.replace(/\\{maxAuto\\}/g, maxAuto);\n\n this._templating.setStatusText(id, retryNote);\n qq(this._templating.getFileContainer(id)).addClass(this._classes.retrying);\n }\n },\n\n //return false if we should not attempt the requested retry\n _onBeforeManualRetry: function(id) {\n if (this._parent.prototype._onBeforeManualRetry.apply(this, arguments)) {\n this._templating.resetProgress(id);\n qq(this._templating.getFileContainer(id)).removeClass(this._classes.fail);\n this._templating.setStatusText(id);\n this._templating.showSpinner(id);\n this._showCancelLink(id);\n return true;\n }\n else {\n qq(this._templating.getFileContainer(id)).addClass(this._classes.retryable);\n this._templating.showRetry(id);\n return false;\n }\n },\n\n _onSubmitDelete: function(id) {\n var onSuccessCallback = qq.bind(this._onSubmitDeleteSuccess, this);\n\n this._parent.prototype._onSubmitDelete.call(this, id, onSuccessCallback);\n },\n\n _onSubmitDeleteSuccess: function(id, uuid, additionalMandatedParams) {\n if (this._options.deleteFile.forceConfirm) {\n this._showDeleteConfirm.apply(this, arguments);\n }\n else {\n this._sendDeleteRequest.apply(this, arguments);\n }\n },\n\n _onDeleteComplete: function(id, xhr, isError) {\n this._parent.prototype._onDeleteComplete.apply(this, arguments);\n\n this._templating.hideSpinner(id);\n\n if (isError) {\n this._templating.setStatusText(id, this._options.deleteFile.deletingFailedText);\n this._templating.showDeleteButton(id);\n }\n else {\n this._removeFileItem(id);\n }\n },\n\n _sendDeleteRequest: function(id, uuid, additionalMandatedParams) {\n this._templating.hideDeleteButton(id);\n this._templating.showSpinner(id);\n this._templating.setStatusText(id, this._options.deleteFile.deletingStatusText);\n this._deleteHandler.sendDelete.apply(this, arguments);\n },\n\n _showDeleteConfirm: function(id, uuid, mandatedParams) {\n /*jshint -W004 */\n var fileName = this.getName(id),\n confirmMessage = this._options.deleteFile.confirmMessage.replace(/\\{filename\\}/g, fileName),\n uuid = this.getUuid(id),\n deleteRequestArgs = arguments,\n self = this,\n retVal;\n\n retVal = this._options.showConfirm(confirmMessage);\n\n if (qq.isGenericPromise(retVal)) {\n retVal.then(function() {\n self._sendDeleteRequest.apply(self, deleteRequestArgs);\n });\n }\n else if (retVal !== false) {\n self._sendDeleteRequest.apply(self, deleteRequestArgs);\n }\n },\n\n _addToList: function(id, name, canned) {\n var prependData,\n prependIndex = 0,\n dontDisplay = this._handler.isProxied(id) && this._options.scaling.hideScaled,\n record;\n\n if (this._options.display.prependFiles) {\n if (this._totalFilesInBatch > 1 && this._filesInBatchAddedToUi > 0) {\n prependIndex = this._filesInBatchAddedToUi - 1;\n }\n\n prependData = {\n index: prependIndex\n };\n }\n\n if (!canned) {\n if (this._options.disableCancelForFormUploads && !qq.supportedFeatures.ajaxUploading) {\n this._templating.disableCancel();\n }\n\n // Cancel all existing (previous) files and clear the list if this file is not part of\n // a scaled file group that has already been accepted, or if this file is not part of\n // a scaled file group at all.\n if (!this._options.multiple) {\n record = this.getUploads({id: id});\n\n this._handledProxyGroup = this._handledProxyGroup || record.proxyGroupId;\n\n if (record.proxyGroupId !== this._handledProxyGroup || !record.proxyGroupId) {\n this._handler.cancelAll();\n this._clearList();\n this._handledProxyGroup = null;\n }\n }\n }\n\n if (canned) {\n this._templating.addFileToCache(id, this._options.formatFileName(name), prependData, dontDisplay);\n this._templating.updateThumbnail(id, this._thumbnailUrls[id], true, this._options.thumbnails.customResizer);\n }\n else {\n this._templating.addFile(id, this._options.formatFileName(name), prependData, dontDisplay);\n this._templating.generatePreview(id, this.getFile(id), this._options.thumbnails.customResizer);\n }\n\n this._filesInBatchAddedToUi += 1;\n\n if (canned ||\n (this._options.display.fileSizeOnSubmit && qq.supportedFeatures.ajaxUploading)) {\n\n this._displayFileSize(id);\n }\n },\n\n _clearList: function() {\n this._templating.clearFiles();\n this.clearStoredFiles();\n },\n\n _displayFileSize: function(id, loadedSize, totalSize) {\n var size = this.getSize(id),\n sizeForDisplay = this._formatSize(size);\n\n if (size >= 0) {\n if (loadedSize !== undefined && totalSize !== undefined) {\n sizeForDisplay = this._formatProgress(loadedSize, totalSize);\n }\n\n this._templating.updateSize(id, sizeForDisplay);\n }\n },\n\n _formatProgress: function(uploadedSize, totalSize) {\n var message = this._options.text.formatProgress;\n function r(name, replacement) { message = message.replace(name, replacement); }\n\n r(\"{percent}\", Math.round(uploadedSize / totalSize * 100));\n r(\"{total_size}\", this._formatSize(totalSize));\n return message;\n },\n\n _controlFailureTextDisplay: function(id, response) {\n var mode, responseProperty, failureReason;\n\n mode = this._options.failedUploadTextDisplay.mode;\n responseProperty = this._options.failedUploadTextDisplay.responseProperty;\n\n if (mode === \"custom\") {\n failureReason = response[responseProperty];\n if (!failureReason) {\n failureReason = this._options.text.failUpload;\n }\n\n this._templating.setStatusText(id, failureReason);\n\n if (this._options.failedUploadTextDisplay.enableTooltip) {\n this._showTooltip(id, failureReason);\n }\n }\n else if (mode === \"default\") {\n this._templating.setStatusText(id, this._options.text.failUpload);\n }\n else if (mode !== \"none\") {\n this.log(\"failedUploadTextDisplay.mode value of '\" + mode + \"' is not valid\", \"warn\");\n }\n },\n\n _showTooltip: function(id, text) {\n this._templating.getFileContainer(id).title = text;\n },\n\n _showCancelLink: function(id) {\n if (!this._options.disableCancelForFormUploads || qq.supportedFeatures.ajaxUploading) {\n this._templating.showCancel(id);\n }\n },\n\n _itemError: function(code, name, item) {\n var message = this._parent.prototype._itemError.apply(this, arguments);\n this._options.showMessage(message);\n },\n\n _batchError: function(message) {\n this._parent.prototype._batchError.apply(this, arguments);\n this._options.showMessage(message);\n },\n\n _setupPastePrompt: function() {\n var self = this;\n\n this._options.callbacks.onPasteReceived = function() {\n var message = self._options.paste.namePromptMessage,\n defaultVal = self._options.paste.defaultName;\n\n return self._options.showPrompt(message, defaultVal);\n };\n },\n\n _fileOrBlobRejected: function(id, name) {\n this._totalFilesInBatch -= 1;\n this._parent.prototype._fileOrBlobRejected.apply(this, arguments);\n },\n\n _prepareItemsForUpload: function(items, params, endpoint) {\n this._totalFilesInBatch = items.length;\n this._filesInBatchAddedToUi = 0;\n this._parent.prototype._prepareItemsForUpload.apply(this, arguments);\n },\n\n _maybeUpdateThumbnail: function(fileId) {\n var thumbnailUrl = this._thumbnailUrls[fileId],\n fileStatus = this.getUploads({id: fileId}).status;\n\n if (fileStatus !== qq.status.DELETED &&\n (thumbnailUrl ||\n this._options.thumbnails.placeholders.waitUntilResponse ||\n !qq.supportedFeatures.imagePreviews)) {\n\n // This will replace the \"waiting\" placeholder with a \"preview not available\" placeholder\n // if called with a null thumbnailUrl.\n this._templating.updateThumbnail(fileId, thumbnailUrl, this._options.thumbnails.customResizer);\n }\n },\n\n _addCannedFile: function(sessionData) {\n var id = this._parent.prototype._addCannedFile.apply(this, arguments);\n\n this._addToList(id, this.getName(id), true);\n this._templating.hideSpinner(id);\n this._templating.hideCancel(id);\n this._markFileAsSuccessful(id);\n\n return id;\n },\n\n _setSize: function(id, newSize) {\n this._parent.prototype._setSize.apply(this, arguments);\n\n this._templating.updateSize(id, this._formatSize(newSize));\n },\n\n _sessionRequestComplete: function() {\n this._templating.addCacheToDom();\n this._parent.prototype._sessionRequestComplete.apply(this, arguments);\n }\n };\n}());\n","/*globals qq */\n/**\n * This defines FineUploader mode, which is a default UI w/ drag & drop uploading.\n */\nqq.FineUploader = function(o, namespace) {\n \"use strict\";\n\n var self = this;\n\n // By default this should inherit instance data from FineUploaderBasic, but this can be overridden\n // if the (internal) caller defines a different parent. The parent is also used by\n // the private and public API functions that need to delegate to a parent function.\n this._parent = namespace ? qq[namespace].FineUploaderBasic : qq.FineUploaderBasic;\n this._parent.apply(this, arguments);\n\n // Options provided by FineUploader mode\n qq.extend(this._options, {\n element: null,\n\n button: null,\n\n listElement: null,\n\n dragAndDrop: {\n extraDropzones: [],\n reportDirectoryPaths: false\n },\n\n text: {\n formatProgress: \"{percent}% of {total_size}\",\n failUpload: \"Upload failed\",\n waitingForResponse: \"Processing...\",\n paused: \"Paused\"\n },\n\n template: \"qq-template\",\n\n classes: {\n retrying: \"qq-upload-retrying\",\n retryable: \"qq-upload-retryable\",\n success: \"qq-upload-success\",\n fail: \"qq-upload-fail\",\n editable: \"qq-editable\",\n hide: \"qq-hide\",\n dropActive: \"qq-upload-drop-area-active\"\n },\n\n failedUploadTextDisplay: {\n mode: \"default\", //default, custom, or none\n responseProperty: \"error\",\n enableTooltip: true\n },\n\n messages: {\n tooManyFilesError: \"You may only drop one file\",\n unsupportedBrowser: \"Unrecoverable error - this browser does not permit file uploading of any kind.\"\n },\n\n retry: {\n showAutoRetryNote: true,\n autoRetryNote: \"Retrying {retryNum}/{maxAuto}...\"\n },\n\n deleteFile: {\n forceConfirm: false,\n confirmMessage: \"Are you sure you want to delete {filename}?\",\n deletingStatusText: \"Deleting...\",\n deletingFailedText: \"Delete failed\"\n\n },\n\n display: {\n fileSizeOnSubmit: false,\n prependFiles: false\n },\n\n paste: {\n promptForName: false,\n namePromptMessage: \"Please name this image\"\n },\n\n thumbnails: {\n customResizer: null,\n maxCount: 0,\n placeholders: {\n waitUntilResponse: false,\n notAvailablePath: null,\n waitingPath: null\n },\n timeBetweenThumbs: 750\n },\n\n scaling: {\n hideScaled: false\n },\n\n showMessage: function(message) {\n if (self._templating.hasDialog(\"alert\")) {\n return self._templating.showDialog(\"alert\", message);\n }\n else {\n setTimeout(function() {\n window.alert(message);\n }, 0);\n }\n },\n\n showConfirm: function(message) {\n if (self._templating.hasDialog(\"confirm\")) {\n return self._templating.showDialog(\"confirm\", message);\n }\n else {\n return window.confirm(message);\n }\n },\n\n showPrompt: function(message, defaultValue) {\n if (self._templating.hasDialog(\"prompt\")) {\n return self._templating.showDialog(\"prompt\", message, defaultValue);\n }\n else {\n return window.prompt(message, defaultValue);\n }\n }\n }, true);\n\n // Replace any default options with user defined ones\n qq.extend(this._options, o, true);\n\n this._templating = new qq.Templating({\n log: qq.bind(this.log, this),\n templateIdOrEl: this._options.template,\n containerEl: this._options.element,\n fileContainerEl: this._options.listElement,\n button: this._options.button,\n imageGenerator: this._imageGenerator,\n classes: {\n hide: this._options.classes.hide,\n editable: this._options.classes.editable\n },\n limits: {\n maxThumbs: this._options.thumbnails.maxCount,\n timeBetweenThumbs: this._options.thumbnails.timeBetweenThumbs\n },\n placeholders: {\n waitUntilUpdate: this._options.thumbnails.placeholders.waitUntilResponse,\n thumbnailNotAvailable: this._options.thumbnails.placeholders.notAvailablePath,\n waitingForThumbnail: this._options.thumbnails.placeholders.waitingPath\n },\n text: this._options.text\n });\n\n if (this._options.workarounds.ios8SafariUploads && qq.ios800() && qq.iosSafari()) {\n this._templating.renderFailure(this._options.messages.unsupportedBrowserIos8Safari);\n }\n else if (!qq.supportedFeatures.uploading || (this._options.cors.expected && !qq.supportedFeatures.uploadCors)) {\n this._templating.renderFailure(this._options.messages.unsupportedBrowser);\n }\n else {\n this._wrapCallbacks();\n\n this._templating.render();\n\n this._classes = this._options.classes;\n\n if (!this._options.button && this._templating.getButton()) {\n this._defaultButtonId = this._createUploadButton({\n element: this._templating.getButton(),\n title: this._options.text.fileInputTitle\n }).getButtonId();\n }\n\n this._setupClickAndEditEventHandlers();\n\n if (qq.DragAndDrop && qq.supportedFeatures.fileDrop) {\n this._dnd = this._setupDragAndDrop();\n }\n\n if (this._options.paste.targetElement && this._options.paste.promptForName) {\n if (qq.PasteSupport) {\n this._setupPastePrompt();\n }\n else {\n this.log(\"Paste support module not found.\", \"error\");\n }\n }\n\n this._totalFilesInBatch = 0;\n this._filesInBatchAddedToUi = 0;\n }\n};\n\n// Inherit the base public & private API methods\nqq.extend(qq.FineUploader.prototype, qq.basePublicApi);\nqq.extend(qq.FineUploader.prototype, qq.basePrivateApi);\n\n// Add the FineUploader/default UI public & private UI methods, which may override some base methods.\nqq.extend(qq.FineUploader.prototype, qq.uiPublicApi);\nqq.extend(qq.FineUploader.prototype, qq.uiPrivateApi);\n","/* globals qq */\n/* jshint -W065 */\n/**\n * Module responsible for rendering all Fine Uploader UI templates. This module also asserts at least\n * a limited amount of control over the template elements after they are added to the DOM.\n * Wherever possible, this module asserts total control over template elements present in the DOM.\n *\n * @param spec Specification object used to control various templating behaviors\n * @constructor\n */\nqq.Templating = function(spec) {\n \"use strict\";\n\n var FILE_ID_ATTR = \"qq-file-id\",\n FILE_CLASS_PREFIX = \"qq-file-id-\",\n THUMBNAIL_MAX_SIZE_ATTR = \"qq-max-size\",\n THUMBNAIL_SERVER_SCALE_ATTR = \"qq-server-scale\",\n // This variable is duplicated in the DnD module since it can function as a standalone as well\n HIDE_DROPZONE_ATTR = \"qq-hide-dropzone\",\n DROPZPONE_TEXT_ATTR = \"qq-drop-area-text\",\n IN_PROGRESS_CLASS = \"qq-in-progress\",\n HIDDEN_FOREVER_CLASS = \"qq-hidden-forever\",\n fileBatch = {\n content: document.createDocumentFragment(),\n map: {}\n },\n isCancelDisabled = false,\n generatedThumbnails = 0,\n thumbnailQueueMonitorRunning = false,\n thumbGenerationQueue = [],\n thumbnailMaxSize = -1,\n options = {\n log: null,\n limits: {\n maxThumbs: 0,\n timeBetweenThumbs: 750\n },\n templateIdOrEl: \"qq-template\",\n containerEl: null,\n fileContainerEl: null,\n button: null,\n imageGenerator: null,\n classes: {\n hide: \"qq-hide\",\n editable: \"qq-editable\"\n },\n placeholders: {\n waitUntilUpdate: false,\n thumbnailNotAvailable: null,\n waitingForThumbnail: null\n },\n text: {\n paused: \"Paused\"\n }\n },\n selectorClasses = {\n button: \"qq-upload-button-selector\",\n alertDialog: \"qq-alert-dialog-selector\",\n dialogCancelButton: \"qq-cancel-button-selector\",\n confirmDialog: \"qq-confirm-dialog-selector\",\n dialogMessage: \"qq-dialog-message-selector\",\n dialogOkButton: \"qq-ok-button-selector\",\n promptDialog: \"qq-prompt-dialog-selector\",\n uploader: \"qq-uploader-selector\",\n drop: \"qq-upload-drop-area-selector\",\n list: \"qq-upload-list-selector\",\n progressBarContainer: \"qq-progress-bar-container-selector\",\n progressBar: \"qq-progress-bar-selector\",\n totalProgressBarContainer: \"qq-total-progress-bar-container-selector\",\n totalProgressBar: \"qq-total-progress-bar-selector\",\n file: \"qq-upload-file-selector\",\n spinner: \"qq-upload-spinner-selector\",\n size: \"qq-upload-size-selector\",\n cancel: \"qq-upload-cancel-selector\",\n pause: \"qq-upload-pause-selector\",\n continueButton: \"qq-upload-continue-selector\",\n deleteButton: \"qq-upload-delete-selector\",\n retry: \"qq-upload-retry-selector\",\n statusText: \"qq-upload-status-text-selector\",\n editFilenameInput: \"qq-edit-filename-selector\",\n editNameIcon: \"qq-edit-filename-icon-selector\",\n dropText: \"qq-upload-drop-area-text-selector\",\n dropProcessing: \"qq-drop-processing-selector\",\n dropProcessingSpinner: \"qq-drop-processing-spinner-selector\",\n thumbnail: \"qq-thumbnail-selector\"\n },\n previewGeneration = {},\n cachedThumbnailNotAvailableImg = new qq.Promise(),\n cachedWaitingForThumbnailImg = new qq.Promise(),\n log,\n isEditElementsExist,\n isRetryElementExist,\n templateHtml,\n container,\n fileList,\n showThumbnails,\n serverScale,\n\n // During initialization of the templating module we should cache any\n // placeholder images so we can quickly swap them into the file list on demand.\n // Any placeholder images that cannot be loaded/found are simply ignored.\n cacheThumbnailPlaceholders = function() {\n var notAvailableUrl = options.placeholders.thumbnailNotAvailable,\n waitingUrl = options.placeholders.waitingForThumbnail,\n spec = {\n maxSize: thumbnailMaxSize,\n scale: serverScale\n };\n\n if (showThumbnails) {\n if (notAvailableUrl) {\n options.imageGenerator.generate(notAvailableUrl, new Image(), spec).then(\n function(updatedImg) {\n cachedThumbnailNotAvailableImg.success(updatedImg);\n },\n function() {\n cachedThumbnailNotAvailableImg.failure();\n log(\"Problem loading 'not available' placeholder image at \" + notAvailableUrl, \"error\");\n }\n );\n }\n else {\n cachedThumbnailNotAvailableImg.failure();\n }\n\n if (waitingUrl) {\n options.imageGenerator.generate(waitingUrl, new Image(), spec).then(\n function(updatedImg) {\n cachedWaitingForThumbnailImg.success(updatedImg);\n },\n function() {\n cachedWaitingForThumbnailImg.failure();\n log(\"Problem loading 'waiting for thumbnail' placeholder image at \" + waitingUrl, \"error\");\n }\n );\n }\n else {\n cachedWaitingForThumbnailImg.failure();\n }\n }\n },\n\n // Displays a \"waiting for thumbnail\" type placeholder image\n // iff we were able to load it during initialization of the templating module.\n displayWaitingImg = function(thumbnail) {\n var waitingImgPlacement = new qq.Promise();\n\n cachedWaitingForThumbnailImg.then(function(img) {\n maybeScalePlaceholderViaCss(img, thumbnail);\n /* jshint eqnull:true */\n if (!thumbnail.src) {\n thumbnail.src = img.src;\n thumbnail.onload = function() {\n thumbnail.onload = null;\n show(thumbnail);\n waitingImgPlacement.success();\n };\n }\n else {\n waitingImgPlacement.success();\n }\n }, function() {\n // In some browsers (such as IE9 and older) an img w/out a src attribute\n // are displayed as \"broken\" images, so we should just hide the img tag\n // if we aren't going to display the \"waiting\" placeholder.\n hide(thumbnail);\n waitingImgPlacement.success();\n });\n\n return waitingImgPlacement;\n },\n\n generateNewPreview = function(id, blob, spec) {\n var thumbnail = getThumbnail(id);\n\n log(\"Generating new thumbnail for \" + id);\n blob.qqThumbnailId = id;\n\n return options.imageGenerator.generate(blob, thumbnail, spec).then(\n function() {\n generatedThumbnails++;\n show(thumbnail);\n previewGeneration[id].success();\n },\n function() {\n previewGeneration[id].failure();\n\n // Display the \"not available\" placeholder img only if we are\n // not expecting a thumbnail at a later point, such as in a server response.\n if (!options.placeholders.waitUntilUpdate) {\n maybeSetDisplayNotAvailableImg(id, thumbnail);\n }\n });\n },\n\n generateNextQueuedPreview = function() {\n if (thumbGenerationQueue.length) {\n thumbnailQueueMonitorRunning = true;\n\n var queuedThumbRequest = thumbGenerationQueue.shift();\n\n if (queuedThumbRequest.update) {\n processUpdateQueuedPreviewRequest(queuedThumbRequest);\n }\n else {\n processNewQueuedPreviewRequest(queuedThumbRequest);\n }\n }\n else {\n thumbnailQueueMonitorRunning = false;\n }\n },\n\n getCancel = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.cancel);\n },\n\n getContinue = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.continueButton);\n },\n\n getDialog = function(type) {\n return getTemplateEl(container, selectorClasses[type + \"Dialog\"]);\n },\n\n getDelete = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.deleteButton);\n },\n\n getDropProcessing = function() {\n return getTemplateEl(container, selectorClasses.dropProcessing);\n },\n\n getEditIcon = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.editNameIcon);\n },\n\n getFile = function(id) {\n return fileBatch.map[id] || qq(fileList).getFirstByClass(FILE_CLASS_PREFIX + id);\n },\n\n getFilename = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.file);\n },\n\n getPause = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.pause);\n },\n\n getProgress = function(id) {\n /* jshint eqnull:true */\n // Total progress bar\n if (id == null) {\n return getTemplateEl(container, selectorClasses.totalProgressBarContainer) ||\n getTemplateEl(container, selectorClasses.totalProgressBar);\n }\n\n // Per-file progress bar\n return getTemplateEl(getFile(id), selectorClasses.progressBarContainer) ||\n getTemplateEl(getFile(id), selectorClasses.progressBar);\n },\n\n getRetry = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.retry);\n },\n\n getSize = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.size);\n },\n\n getSpinner = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.spinner);\n },\n\n getTemplateEl = function(context, cssClass) {\n return context && qq(context).getFirstByClass(cssClass);\n },\n\n getThumbnail = function(id) {\n return showThumbnails && getTemplateEl(getFile(id), selectorClasses.thumbnail);\n },\n\n hide = function(el) {\n el && qq(el).addClass(options.classes.hide);\n },\n\n // Ensures a placeholder image does not exceed any max size specified\n // via `style` attribute properties iff was not used to scale\n // the placeholder AND the target doesn't already have these `style` attribute properties set.\n maybeScalePlaceholderViaCss = function(placeholder, thumbnail) {\n var maxWidth = placeholder.style.maxWidth,\n maxHeight = placeholder.style.maxHeight;\n\n if (maxHeight && maxWidth && !thumbnail.style.maxWidth && !thumbnail.style.maxHeight) {\n qq(thumbnail).css({\n maxWidth: maxWidth,\n maxHeight: maxHeight\n });\n }\n },\n\n // Displays a \"thumbnail not available\" type placeholder image\n // iff we were able to load this placeholder during initialization\n // of the templating module or after preview generation has failed.\n maybeSetDisplayNotAvailableImg = function(id, thumbnail) {\n var previewing = previewGeneration[id] || new qq.Promise().failure(),\n notAvailableImgPlacement = new qq.Promise();\n\n cachedThumbnailNotAvailableImg.then(function(img) {\n previewing.then(\n function() {\n notAvailableImgPlacement.success();\n },\n function() {\n maybeScalePlaceholderViaCss(img, thumbnail);\n\n thumbnail.onload = function() {\n thumbnail.onload = null;\n notAvailableImgPlacement.success();\n };\n\n thumbnail.src = img.src;\n show(thumbnail);\n }\n );\n });\n\n return notAvailableImgPlacement;\n },\n\n /**\n * Grabs the HTML from the script tag holding the template markup. This function will also adjust\n * some internally-tracked state variables based on the contents of the template.\n * The template is filtered so that irrelevant elements (such as the drop zone if DnD is not supported)\n * are omitted from the DOM. Useful errors will be thrown if the template cannot be parsed.\n *\n * @returns {{template: *, fileTemplate: *}} HTML for the top-level file items templates\n */\n parseAndGetTemplate = function() {\n var scriptEl,\n scriptHtml,\n fileListNode,\n tempTemplateEl,\n fileListHtml,\n defaultButton,\n dropArea,\n thumbnail,\n dropProcessing,\n dropTextEl,\n uploaderEl;\n\n log(\"Parsing template\");\n\n /*jshint -W116*/\n if (options.templateIdOrEl == null) {\n throw new Error(\"You MUST specify either a template element or ID!\");\n }\n\n // Grab the contents of the script tag holding the template.\n if (qq.isString(options.templateIdOrEl)) {\n scriptEl = document.getElementById(options.templateIdOrEl);\n\n if (scriptEl === null) {\n throw new Error(qq.format(\"Cannot find template script at ID '{}'!\", options.templateIdOrEl));\n }\n\n scriptHtml = scriptEl.innerHTML;\n }\n else {\n if (options.templateIdOrEl.innerHTML === undefined) {\n throw new Error(\"You have specified an invalid value for the template option! \" +\n \"It must be an ID or an Element.\");\n }\n\n scriptHtml = options.templateIdOrEl.innerHTML;\n }\n\n scriptHtml = qq.trimStr(scriptHtml);\n tempTemplateEl = document.createElement(\"div\");\n tempTemplateEl.appendChild(qq.toElement(scriptHtml));\n uploaderEl = qq(tempTemplateEl).getFirstByClass(selectorClasses.uploader);\n\n // Don't include the default template button in the DOM\n // if an alternate button container has been specified.\n if (options.button) {\n defaultButton = qq(tempTemplateEl).getFirstByClass(selectorClasses.button);\n if (defaultButton) {\n qq(defaultButton).remove();\n }\n }\n\n // Omit the drop processing element from the DOM if DnD is not supported by the UA,\n // or the drag and drop module is not found.\n // NOTE: We are consciously not removing the drop zone if the UA doesn't support DnD\n // to support layouts where the drop zone is also a container for visible elements,\n // such as the file list.\n if (!qq.DragAndDrop || !qq.supportedFeatures.fileDrop) {\n dropProcessing = qq(tempTemplateEl).getFirstByClass(selectorClasses.dropProcessing);\n if (dropProcessing) {\n qq(dropProcessing).remove();\n }\n }\n\n dropArea = qq(tempTemplateEl).getFirstByClass(selectorClasses.drop);\n\n // If DnD is not available then remove\n // it from the DOM as well.\n if (dropArea && !qq.DragAndDrop) {\n log(\"DnD module unavailable.\", \"info\");\n qq(dropArea).remove();\n }\n\n if (!qq.supportedFeatures.fileDrop) {\n // don't display any \"drop files to upload\" background text\n uploaderEl.removeAttribute(DROPZPONE_TEXT_ATTR);\n\n if (dropArea && qq(dropArea).hasAttribute(HIDE_DROPZONE_ATTR)) {\n // If there is a drop area defined in the template, and the current UA doesn't support DnD,\n // and the drop area is marked as \"hide before enter\", ensure it is hidden as the DnD module\n // will not do this (since we will not be loading the DnD module)\n qq(dropArea).css({\n display: \"none\"\n });\n }\n }\n else if (qq(uploaderEl).hasAttribute(DROPZPONE_TEXT_ATTR) && dropArea) {\n dropTextEl = qq(dropArea).getFirstByClass(selectorClasses.dropText);\n dropTextEl && qq(dropTextEl).remove();\n }\n\n // Ensure the `showThumbnails` flag is only set if the thumbnail element\n // is present in the template AND the current UA is capable of generating client-side previews.\n thumbnail = qq(tempTemplateEl).getFirstByClass(selectorClasses.thumbnail);\n if (!showThumbnails) {\n thumbnail && qq(thumbnail).remove();\n }\n else if (thumbnail) {\n thumbnailMaxSize = parseInt(thumbnail.getAttribute(THUMBNAIL_MAX_SIZE_ATTR));\n // Only enforce max size if the attr value is non-zero\n thumbnailMaxSize = thumbnailMaxSize > 0 ? thumbnailMaxSize : null;\n\n serverScale = qq(thumbnail).hasAttribute(THUMBNAIL_SERVER_SCALE_ATTR);\n }\n showThumbnails = showThumbnails && thumbnail;\n\n isEditElementsExist = qq(tempTemplateEl).getByClass(selectorClasses.editFilenameInput).length > 0;\n isRetryElementExist = qq(tempTemplateEl).getByClass(selectorClasses.retry).length > 0;\n\n fileListNode = qq(tempTemplateEl).getFirstByClass(selectorClasses.list);\n /*jshint -W116*/\n if (fileListNode == null) {\n throw new Error(\"Could not find the file list container in the template!\");\n }\n\n fileListHtml = fileListNode.innerHTML;\n fileListNode.innerHTML = \"\";\n\n // We must call `createElement` in IE8 in order to target and hide any via CSS\n if (tempTemplateEl.getElementsByTagName(\"DIALOG\").length) {\n document.createElement(\"dialog\");\n }\n\n log(\"Template parsing complete\");\n\n return {\n template: qq.trimStr(tempTemplateEl.innerHTML),\n fileTemplate: qq.trimStr(fileListHtml)\n };\n },\n\n prependFile = function(el, index, fileList) {\n var parentEl = fileList,\n beforeEl = parentEl.firstChild;\n\n if (index > 0) {\n beforeEl = qq(parentEl).children()[index].nextSibling;\n\n }\n\n parentEl.insertBefore(el, beforeEl);\n },\n\n processNewQueuedPreviewRequest = function(queuedThumbRequest) {\n var id = queuedThumbRequest.id,\n optFileOrBlob = queuedThumbRequest.optFileOrBlob,\n relatedThumbnailId = optFileOrBlob && optFileOrBlob.qqThumbnailId,\n thumbnail = getThumbnail(id),\n spec = {\n customResizeFunction: queuedThumbRequest.customResizeFunction,\n maxSize: thumbnailMaxSize,\n orient: true,\n scale: true\n };\n\n if (qq.supportedFeatures.imagePreviews) {\n if (thumbnail) {\n if (options.limits.maxThumbs && options.limits.maxThumbs <= generatedThumbnails) {\n maybeSetDisplayNotAvailableImg(id, thumbnail);\n generateNextQueuedPreview();\n }\n else {\n displayWaitingImg(thumbnail).done(function() {\n previewGeneration[id] = new qq.Promise();\n\n previewGeneration[id].done(function() {\n setTimeout(generateNextQueuedPreview, options.limits.timeBetweenThumbs);\n });\n\n /* jshint eqnull: true */\n // If we've already generated an for this file, use the one that exists,\n // don't waste resources generating a new one.\n if (relatedThumbnailId != null) {\n useCachedPreview(id, relatedThumbnailId);\n }\n else {\n generateNewPreview(id, optFileOrBlob, spec);\n }\n });\n }\n }\n // File element in template may have been removed, so move on to next item in queue\n else {\n generateNextQueuedPreview();\n }\n }\n else if (thumbnail) {\n displayWaitingImg(thumbnail);\n generateNextQueuedPreview();\n }\n },\n\n processUpdateQueuedPreviewRequest = function(queuedThumbRequest) {\n var id = queuedThumbRequest.id,\n thumbnailUrl = queuedThumbRequest.thumbnailUrl,\n showWaitingImg = queuedThumbRequest.showWaitingImg,\n thumbnail = getThumbnail(id),\n spec = {\n customResizeFunction: queuedThumbRequest.customResizeFunction,\n scale: serverScale,\n maxSize: thumbnailMaxSize\n };\n\n if (thumbnail) {\n if (thumbnailUrl) {\n if (options.limits.maxThumbs && options.limits.maxThumbs <= generatedThumbnails) {\n maybeSetDisplayNotAvailableImg(id, thumbnail);\n generateNextQueuedPreview();\n }\n else {\n if (showWaitingImg) {\n displayWaitingImg(thumbnail);\n }\n\n return options.imageGenerator.generate(thumbnailUrl, thumbnail, spec).then(\n function() {\n show(thumbnail);\n generatedThumbnails++;\n setTimeout(generateNextQueuedPreview, options.limits.timeBetweenThumbs);\n },\n\n function() {\n maybeSetDisplayNotAvailableImg(id, thumbnail);\n setTimeout(generateNextQueuedPreview, options.limits.timeBetweenThumbs);\n }\n );\n }\n }\n else {\n maybeSetDisplayNotAvailableImg(id, thumbnail);\n generateNextQueuedPreview();\n }\n }\n },\n\n setProgressBarWidth = function(id, percent) {\n var bar = getProgress(id),\n /* jshint eqnull:true */\n progressBarSelector = id == null ? selectorClasses.totalProgressBar : selectorClasses.progressBar;\n\n if (bar && !qq(bar).hasClass(progressBarSelector)) {\n bar = qq(bar).getFirstByClass(progressBarSelector);\n }\n\n if (bar) {\n qq(bar).css({width: percent + \"%\"});\n bar.setAttribute(\"aria-valuenow\", percent);\n }\n },\n\n show = function(el) {\n el && qq(el).removeClass(options.classes.hide);\n },\n\n useCachedPreview = function(targetThumbnailId, cachedThumbnailId) {\n var targetThumbnail = getThumbnail(targetThumbnailId),\n cachedThumbnail = getThumbnail(cachedThumbnailId);\n\n log(qq.format(\"ID {} is the same file as ID {}. Will use generated thumbnail from ID {} instead.\", targetThumbnailId, cachedThumbnailId, cachedThumbnailId));\n\n // Generation of the related thumbnail may still be in progress, so, wait until it is done.\n previewGeneration[cachedThumbnailId].then(function() {\n generatedThumbnails++;\n previewGeneration[targetThumbnailId].success();\n log(qq.format(\"Now using previously generated thumbnail created for ID {} on ID {}.\", cachedThumbnailId, targetThumbnailId));\n targetThumbnail.src = cachedThumbnail.src;\n show(targetThumbnail);\n },\n function() {\n previewGeneration[targetThumbnailId].failure();\n if (!options.placeholders.waitUntilUpdate) {\n maybeSetDisplayNotAvailableImg(targetThumbnailId, targetThumbnail);\n }\n });\n };\n\n qq.extend(options, spec);\n log = options.log;\n\n // No need to worry about conserving CPU or memory on older browsers,\n // since there is no ability to preview, and thumbnail display is primitive and quick.\n if (!qq.supportedFeatures.imagePreviews) {\n options.limits.timeBetweenThumbs = 0;\n options.limits.maxThumbs = 0;\n }\n\n container = options.containerEl;\n showThumbnails = options.imageGenerator !== undefined;\n templateHtml = parseAndGetTemplate();\n\n cacheThumbnailPlaceholders();\n\n qq.extend(this, {\n render: function() {\n log(\"Rendering template in DOM.\");\n\n generatedThumbnails = 0;\n\n container.innerHTML = templateHtml.template;\n hide(getDropProcessing());\n this.hideTotalProgress();\n fileList = options.fileContainerEl || getTemplateEl(container, selectorClasses.list);\n\n log(\"Template rendering complete\");\n },\n\n renderFailure: function(message) {\n var cantRenderEl = qq.toElement(message);\n container.innerHTML = \"\";\n container.appendChild(cantRenderEl);\n },\n\n reset: function() {\n this.render();\n },\n\n clearFiles: function() {\n fileList.innerHTML = \"\";\n },\n\n disableCancel: function() {\n isCancelDisabled = true;\n },\n\n addFile: function(id, name, prependInfo, hideForever, batch) {\n var fileEl = qq.toElement(templateHtml.fileTemplate),\n fileNameEl = getTemplateEl(fileEl, selectorClasses.file),\n uploaderEl = getTemplateEl(container, selectorClasses.uploader),\n fileContainer = batch ? fileBatch.content : fileList,\n thumb;\n\n if (batch) {\n fileBatch.map[id] = fileEl;\n }\n\n qq(fileEl).addClass(FILE_CLASS_PREFIX + id);\n uploaderEl.removeAttribute(DROPZPONE_TEXT_ATTR);\n\n if (fileNameEl) {\n qq(fileNameEl).setText(name);\n fileNameEl.setAttribute(\"title\", name);\n }\n\n fileEl.setAttribute(FILE_ID_ATTR, id);\n\n if (prependInfo) {\n prependFile(fileEl, prependInfo.index, fileContainer);\n }\n else {\n fileContainer.appendChild(fileEl);\n }\n\n if (hideForever) {\n fileEl.style.display = \"none\";\n qq(fileEl).addClass(HIDDEN_FOREVER_CLASS);\n }\n else {\n hide(getProgress(id));\n hide(getSize(id));\n hide(getDelete(id));\n hide(getRetry(id));\n hide(getPause(id));\n hide(getContinue(id));\n\n if (isCancelDisabled) {\n this.hideCancel(id);\n }\n\n thumb = getThumbnail(id);\n if (thumb && !thumb.src) {\n cachedWaitingForThumbnailImg.then(function(waitingImg) {\n thumb.src = waitingImg.src;\n if (waitingImg.style.maxHeight && waitingImg.style.maxWidth) {\n qq(thumb).css({\n maxHeight: waitingImg.style.maxHeight,\n maxWidth: waitingImg.style.maxWidth\n });\n }\n\n show(thumb);\n });\n }\n }\n },\n\n addFileToCache: function(id, name, prependInfo, hideForever) {\n this.addFile(id, name, prependInfo, hideForever, true);\n },\n\n addCacheToDom: function() {\n fileList.appendChild(fileBatch.content);\n fileBatch.content = document.createDocumentFragment();\n fileBatch.map = {};\n },\n\n removeFile: function(id) {\n qq(getFile(id)).remove();\n },\n\n getFileId: function(el) {\n var currentNode = el;\n\n if (currentNode) {\n /*jshint -W116*/\n while (currentNode.getAttribute(FILE_ID_ATTR) == null) {\n currentNode = currentNode.parentNode;\n }\n\n return parseInt(currentNode.getAttribute(FILE_ID_ATTR));\n }\n },\n\n getFileList: function() {\n return fileList;\n },\n\n markFilenameEditable: function(id) {\n var filename = getFilename(id);\n\n filename && qq(filename).addClass(options.classes.editable);\n },\n\n updateFilename: function(id, name) {\n var filenameEl = getFilename(id);\n\n if (filenameEl) {\n qq(filenameEl).setText(name);\n filenameEl.setAttribute(\"title\", name);\n }\n },\n\n hideFilename: function(id) {\n hide(getFilename(id));\n },\n\n showFilename: function(id) {\n show(getFilename(id));\n },\n\n isFileName: function(el) {\n return qq(el).hasClass(selectorClasses.file);\n },\n\n getButton: function() {\n return options.button || getTemplateEl(container, selectorClasses.button);\n },\n\n hideDropProcessing: function() {\n hide(getDropProcessing());\n },\n\n showDropProcessing: function() {\n show(getDropProcessing());\n },\n\n getDropZone: function() {\n return getTemplateEl(container, selectorClasses.drop);\n },\n\n isEditFilenamePossible: function() {\n return isEditElementsExist;\n },\n\n hideRetry: function(id) {\n hide(getRetry(id));\n },\n\n isRetryPossible: function() {\n return isRetryElementExist;\n },\n\n showRetry: function(id) {\n show(getRetry(id));\n },\n\n getFileContainer: function(id) {\n return getFile(id);\n },\n\n showEditIcon: function(id) {\n var icon = getEditIcon(id);\n\n icon && qq(icon).addClass(options.classes.editable);\n },\n\n isHiddenForever: function(id) {\n return qq(getFile(id)).hasClass(HIDDEN_FOREVER_CLASS);\n },\n\n hideEditIcon: function(id) {\n var icon = getEditIcon(id);\n\n icon && qq(icon).removeClass(options.classes.editable);\n },\n\n isEditIcon: function(el) {\n return qq(el).hasClass(selectorClasses.editNameIcon, true);\n },\n\n getEditInput: function(id) {\n return getTemplateEl(getFile(id), selectorClasses.editFilenameInput);\n },\n\n isEditInput: function(el) {\n return qq(el).hasClass(selectorClasses.editFilenameInput, true);\n },\n\n updateProgress: function(id, loaded, total) {\n var bar = getProgress(id),\n percent;\n\n if (bar && total > 0) {\n percent = Math.round(loaded / total * 100);\n\n if (percent === 100) {\n hide(bar);\n }\n else {\n show(bar);\n }\n\n setProgressBarWidth(id, percent);\n }\n },\n\n updateTotalProgress: function(loaded, total) {\n this.updateProgress(null, loaded, total);\n },\n\n hideProgress: function(id) {\n var bar = getProgress(id);\n\n bar && hide(bar);\n },\n\n hideTotalProgress: function() {\n this.hideProgress();\n },\n\n resetProgress: function(id) {\n setProgressBarWidth(id, 0);\n this.hideTotalProgress(id);\n },\n\n resetTotalProgress: function() {\n this.resetProgress();\n },\n\n showCancel: function(id) {\n if (!isCancelDisabled) {\n var cancel = getCancel(id);\n\n cancel && qq(cancel).removeClass(options.classes.hide);\n }\n },\n\n hideCancel: function(id) {\n hide(getCancel(id));\n },\n\n isCancel: function(el) {\n return qq(el).hasClass(selectorClasses.cancel, true);\n },\n\n allowPause: function(id) {\n show(getPause(id));\n hide(getContinue(id));\n },\n\n uploadPaused: function(id) {\n this.setStatusText(id, options.text.paused);\n this.allowContinueButton(id);\n hide(getSpinner(id));\n },\n\n hidePause: function(id) {\n hide(getPause(id));\n },\n\n isPause: function(el) {\n return qq(el).hasClass(selectorClasses.pause, true);\n },\n\n isContinueButton: function(el) {\n return qq(el).hasClass(selectorClasses.continueButton, true);\n },\n\n allowContinueButton: function(id) {\n show(getContinue(id));\n hide(getPause(id));\n },\n\n uploadContinued: function(id) {\n this.setStatusText(id, \"\");\n this.allowPause(id);\n show(getSpinner(id));\n },\n\n showDeleteButton: function(id) {\n show(getDelete(id));\n },\n\n hideDeleteButton: function(id) {\n hide(getDelete(id));\n },\n\n isDeleteButton: function(el) {\n return qq(el).hasClass(selectorClasses.deleteButton, true);\n },\n\n isRetry: function(el) {\n return qq(el).hasClass(selectorClasses.retry, true);\n },\n\n updateSize: function(id, text) {\n var size = getSize(id);\n\n if (size) {\n show(size);\n qq(size).setText(text);\n }\n },\n\n setStatusText: function(id, text) {\n var textEl = getTemplateEl(getFile(id), selectorClasses.statusText);\n\n if (textEl) {\n /*jshint -W116*/\n if (text == null) {\n qq(textEl).clearText();\n }\n else {\n qq(textEl).setText(text);\n }\n }\n },\n\n hideSpinner: function(id) {\n qq(getFile(id)).removeClass(IN_PROGRESS_CLASS);\n hide(getSpinner(id));\n },\n\n showSpinner: function(id) {\n qq(getFile(id)).addClass(IN_PROGRESS_CLASS);\n show(getSpinner(id));\n },\n\n generatePreview: function(id, optFileOrBlob, customResizeFunction) {\n if (!this.isHiddenForever(id)) {\n thumbGenerationQueue.push({id: id, customResizeFunction: customResizeFunction, optFileOrBlob: optFileOrBlob});\n !thumbnailQueueMonitorRunning && generateNextQueuedPreview();\n }\n },\n\n updateThumbnail: function(id, thumbnailUrl, showWaitingImg, customResizeFunction) {\n if (!this.isHiddenForever(id)) {\n thumbGenerationQueue.push({customResizeFunction: customResizeFunction, update: true, id: id, thumbnailUrl: thumbnailUrl, showWaitingImg: showWaitingImg});\n !thumbnailQueueMonitorRunning && generateNextQueuedPreview();\n }\n },\n\n hasDialog: function(type) {\n return qq.supportedFeatures.dialogElement && !!getDialog(type);\n },\n\n showDialog: function(type, message, defaultValue) {\n var dialog = getDialog(type),\n messageEl = getTemplateEl(dialog, selectorClasses.dialogMessage),\n inputEl = dialog.getElementsByTagName(\"INPUT\")[0],\n cancelBtn = getTemplateEl(dialog, selectorClasses.dialogCancelButton),\n okBtn = getTemplateEl(dialog, selectorClasses.dialogOkButton),\n promise = new qq.Promise(),\n\n closeHandler = function() {\n cancelBtn.removeEventListener(\"click\", cancelClickHandler);\n okBtn && okBtn.removeEventListener(\"click\", okClickHandler);\n promise.failure();\n },\n\n cancelClickHandler = function() {\n cancelBtn.removeEventListener(\"click\", cancelClickHandler);\n dialog.close();\n },\n\n okClickHandler = function() {\n dialog.removeEventListener(\"close\", closeHandler);\n okBtn.removeEventListener(\"click\", okClickHandler);\n dialog.close();\n\n promise.success(inputEl && inputEl.value);\n };\n\n dialog.addEventListener(\"close\", closeHandler);\n cancelBtn.addEventListener(\"click\", cancelClickHandler);\n okBtn && okBtn.addEventListener(\"click\", okClickHandler);\n\n if (inputEl) {\n inputEl.value = defaultValue;\n }\n messageEl.textContent = message;\n\n dialog.showModal();\n\n return promise;\n }\n });\n};\n","/*globals qq */\n// Base handler for UI (FineUploader mode) events.\n// Some more specific handlers inherit from this one.\nqq.UiEventHandler = function(s, protectedApi) {\n \"use strict\";\n\n var disposer = new qq.DisposeSupport(),\n spec = {\n eventType: \"click\",\n attachTo: null,\n onHandled: function(target, event) {}\n };\n\n // This makes up the \"public\" API methods that will be accessible\n // to instances constructing a base or child handler\n qq.extend(this, {\n addHandler: function(element) {\n addHandler(element);\n },\n\n dispose: function() {\n disposer.dispose();\n }\n });\n\n function addHandler(element) {\n disposer.attach(element, spec.eventType, function(event) {\n // Only in IE: the `event` is a property of the `window`.\n event = event || window.event;\n\n // On older browsers, we must check the `srcElement` instead of the `target`.\n var target = event.target || event.srcElement;\n\n spec.onHandled(target, event);\n });\n }\n\n // These make up the \"protected\" API methods that children of this base handler will utilize.\n qq.extend(protectedApi, {\n getFileIdFromItem: function(item) {\n return item.qqFileId;\n },\n\n getDisposeSupport: function() {\n return disposer;\n }\n });\n\n qq.extend(spec, s);\n\n if (spec.attachTo) {\n addHandler(spec.attachTo);\n }\n};\n","/* global qq */\nqq.FileButtonsClickHandler = function(s) {\n \"use strict\";\n\n var inheritedInternalApi = {},\n spec = {\n templating: null,\n log: function(message, lvl) {},\n onDeleteFile: function(fileId) {},\n onCancel: function(fileId) {},\n onRetry: function(fileId) {},\n onPause: function(fileId) {},\n onContinue: function(fileId) {},\n onGetName: function(fileId) {}\n },\n buttonHandlers = {\n cancel: function(id) { spec.onCancel(id); },\n retry: function(id) { spec.onRetry(id); },\n deleteButton: function(id) { spec.onDeleteFile(id); },\n pause: function(id) { spec.onPause(id); },\n continueButton: function(id) { spec.onContinue(id); }\n };\n\n function examineEvent(target, event) {\n qq.each(buttonHandlers, function(buttonType, handler) {\n var firstLetterCapButtonType = buttonType.charAt(0).toUpperCase() + buttonType.slice(1),\n fileId;\n\n if (spec.templating[\"is\" + firstLetterCapButtonType](target)) {\n fileId = spec.templating.getFileId(target);\n qq.preventDefault(event);\n spec.log(qq.format(\"Detected valid file button click event on file '{}', ID: {}.\", spec.onGetName(fileId), fileId));\n handler(fileId);\n return false;\n }\n });\n }\n\n qq.extend(spec, s);\n\n spec.eventType = \"click\";\n spec.onHandled = examineEvent;\n spec.attachTo = spec.templating.getFileList();\n\n qq.extend(this, new qq.UiEventHandler(spec, inheritedInternalApi));\n};\n","/*globals qq */\n// Child of FilenameEditHandler. Used to detect click events on filename display elements.\nqq.FilenameClickHandler = function(s) {\n \"use strict\";\n\n var inheritedInternalApi = {},\n spec = {\n templating: null,\n log: function(message, lvl) {},\n classes: {\n file: \"qq-upload-file\",\n editNameIcon: \"qq-edit-filename-icon\"\n },\n onGetUploadStatus: function(fileId) {},\n onGetName: function(fileId) {}\n };\n\n qq.extend(spec, s);\n\n // This will be called by the parent handler when a `click` event is received on the list element.\n function examineEvent(target, event) {\n if (spec.templating.isFileName(target) || spec.templating.isEditIcon(target)) {\n var fileId = spec.templating.getFileId(target),\n status = spec.onGetUploadStatus(fileId);\n\n // We only allow users to change filenames of files that have been submitted but not yet uploaded.\n if (status === qq.status.SUBMITTED) {\n spec.log(qq.format(\"Detected valid filename click event on file '{}', ID: {}.\", spec.onGetName(fileId), fileId));\n qq.preventDefault(event);\n\n inheritedInternalApi.handleFilenameEdit(fileId, target, true);\n }\n }\n }\n\n spec.eventType = \"click\";\n spec.onHandled = examineEvent;\n\n qq.extend(this, new qq.FilenameEditHandler(spec, inheritedInternalApi));\n};\n","/*globals qq */\n// Child of FilenameEditHandler. Used to detect focusin events on file edit input elements.\nqq.FilenameInputFocusInHandler = function(s, inheritedInternalApi) {\n \"use strict\";\n\n var spec = {\n templating: null,\n onGetUploadStatus: function(fileId) {},\n log: function(message, lvl) {}\n };\n\n if (!inheritedInternalApi) {\n inheritedInternalApi = {};\n }\n\n // This will be called by the parent handler when a `focusin` event is received on the list element.\n function handleInputFocus(target, event) {\n if (spec.templating.isEditInput(target)) {\n var fileId = spec.templating.getFileId(target),\n status = spec.onGetUploadStatus(fileId);\n\n if (status === qq.status.SUBMITTED) {\n spec.log(qq.format(\"Detected valid filename input focus event on file '{}', ID: {}.\", spec.onGetName(fileId), fileId));\n inheritedInternalApi.handleFilenameEdit(fileId, target);\n }\n }\n }\n\n spec.eventType = \"focusin\";\n spec.onHandled = handleInputFocus;\n\n qq.extend(spec, s);\n qq.extend(this, new qq.FilenameEditHandler(spec, inheritedInternalApi));\n};\n","/*globals qq */\n/**\n * Child of FilenameInputFocusInHandler. Used to detect focus events on file edit input elements. This child module is only\n * needed for UAs that do not support the focusin event. Currently, only Firefox lacks this event.\n *\n * @param spec Overrides for default specifications\n */\nqq.FilenameInputFocusHandler = function(spec) {\n \"use strict\";\n\n spec.eventType = \"focus\";\n spec.attachTo = null;\n\n qq.extend(this, new qq.FilenameInputFocusInHandler(spec, {}));\n};\n","/*globals qq */\n// Handles edit-related events on a file item (FineUploader mode). This is meant to be a parent handler.\n// Children will delegate to this handler when specific edit-related actions are detected.\nqq.FilenameEditHandler = function(s, inheritedInternalApi) {\n \"use strict\";\n\n var spec = {\n templating: null,\n log: function(message, lvl) {},\n onGetUploadStatus: function(fileId) {},\n onGetName: function(fileId) {},\n onSetName: function(fileId, newName) {},\n onEditingStatusChange: function(fileId, isEditing) {}\n };\n\n function getFilenameSansExtension(fileId) {\n var filenameSansExt = spec.onGetName(fileId),\n extIdx = filenameSansExt.lastIndexOf(\".\");\n\n if (extIdx > 0) {\n filenameSansExt = filenameSansExt.substr(0, extIdx);\n }\n\n return filenameSansExt;\n }\n\n function getOriginalExtension(fileId) {\n var origName = spec.onGetName(fileId);\n return qq.getExtension(origName);\n }\n\n // Callback iff the name has been changed\n function handleNameUpdate(newFilenameInputEl, fileId) {\n var newName = newFilenameInputEl.value,\n origExtension;\n\n if (newName !== undefined && qq.trimStr(newName).length > 0) {\n origExtension = getOriginalExtension(fileId);\n\n if (origExtension !== undefined) {\n newName = newName + \".\" + origExtension;\n }\n\n spec.onSetName(fileId, newName);\n }\n\n spec.onEditingStatusChange(fileId, false);\n }\n\n // The name has been updated if the filename edit input loses focus.\n function registerInputBlurHandler(inputEl, fileId) {\n inheritedInternalApi.getDisposeSupport().attach(inputEl, \"blur\", function() {\n handleNameUpdate(inputEl, fileId);\n });\n }\n\n // The name has been updated if the user presses enter.\n function registerInputEnterKeyHandler(inputEl, fileId) {\n inheritedInternalApi.getDisposeSupport().attach(inputEl, \"keyup\", function(event) {\n\n var code = event.keyCode || event.which;\n\n if (code === 13) {\n handleNameUpdate(inputEl, fileId);\n }\n });\n }\n\n qq.extend(spec, s);\n\n spec.attachTo = spec.templating.getFileList();\n\n qq.extend(this, new qq.UiEventHandler(spec, inheritedInternalApi));\n\n qq.extend(inheritedInternalApi, {\n handleFilenameEdit: function(id, target, focusInput) {\n var newFilenameInputEl = spec.templating.getEditInput(id);\n\n spec.onEditingStatusChange(id, true);\n\n newFilenameInputEl.value = getFilenameSansExtension(id);\n\n if (focusInput) {\n newFilenameInputEl.focus();\n }\n\n registerInputBlurHandler(newFilenameInputEl, id);\n registerInputEnterKeyHandler(newFilenameInputEl, id);\n }\n });\n};\n"]}
\ No newline at end of file
+{"version":3,"sources":["?","../client/js/jquery-plugin.js","../client/js/jquery-dnd.js","../client/js/util.js","../client/js/export.js","../client/js/error/error.js","../client/js/version.js","../client/js/features.js","../client/js/promise.js","../client/js/blob-proxy.js","../client/js/button.js","../client/js/upload-data.js","../client/js/uploader.basic.api.js","../client/js/uploader.basic.js","../client/js/ajax.requester.js","../client/js/upload-handler/upload.handler.js","../client/js/upload-handler/upload.handler.controller.js","../client/js/window.receive.message.js","../client/js/upload-handler/form.upload.handler.js","../client/js/upload-handler/xhr.upload.handler.js","../client/js/deletefile.ajax.requester.js","../client/js/image-support/megapix-image.js","../client/js/image-support/image.js","../client/js/image-support/exif.js","../client/js/identify.js","../client/js/image-support/validation.image.js","../client/js/session.js","../client/js/session.ajax.requester.js","../client/js/image-support/scaler.js","../client/js/third-party/ExifRestorer.js","../client/js/total-progress.js","../client/js/paste.js","../client/js/form-support.js","../client/js/traditional/traditional.form.upload.handler.js","../client/js/traditional/traditional.xhr.upload.handler.js","../client/js/traditional/all-chunks-done.ajax.requester.js","../client/js/dnd.js","../client/js/uploader.api.js","../client/js/uploader.js","../client/js/templating.js","../client/js/ui.handler.events.js","../client/js/ui.handler.click.filebuttons.js","../client/js/ui.handler.click.filename.js","../client/js/ui.handler.focusin.filenameinput.js","../client/js/ui.handler.focus.filenameinput.js","../client/js/ui.handler.edit.filename.js"],"names":["global","$","init","options","xformedOpts","transformVariables","newUploaderInstance","getNewUploaderInstance","uploader","addCallbacks","$el","params","uploaderType","pluginOption","namespace","charAt","toUpperCase","slice","toLowerCase","qq","FineUploader","dataStore","key","val","data","undefined","instanceToStore","option","optionVal","transformedOpts","callbacks","each","_options","prop","nonJqueryCallback","name","callbackEventTarget","exec","substring","nonJqueryCallbackRetVal","jqueryEventCallbackRetVal","originalArgs","Array","prototype","call","arguments","transformedArgs","idx","arg","push","maybeWrapInJquery","apply","this","triggerHandler","error","log","message","source","dest","xformed","arrayVals","element","inArray","pluginOptions","isPlainObject","isArray","arrayVal","arrayObjDest","merge","isValidCommand","command","type","match","delegateCommand","retVal","xformedArgs","origArgs","transformedVal","nodeType","cloneNode","fn","fineUploader","optionsOrCommand","self","selfArgs","retVals","index","el","length","jQuery","dropZoneElements","dnd","DragAndDrop","func","$callbackEl","args","fineUploaderDnd","hide","style","display","attach","addEventListener","attachEvent","detach","removeEventListener","detachEvent","contains","descendant","compareDocumentPosition","insertBefore","elementB","parentNode","remove","removeChild","css","styles","Error","opacity","filter","Math","round","extend","hasClass","considerParent","re","RegExp","test","className","addClass","removeClass","replace","getByClass","first","candidates","result","querySelector","querySelectorAll","getElementsByTagName","getFirstByClass","children","child","firstChild","nextSibling","setText","text","innerText","textContent","clearText","hasAttribute","attrName","attrVal","getAttribute","canvasToBlob","canvas","mime","quality","dataUriToBlob","toDataURL","dataUri","arrayBuffer","byteString","intArray","mimeString","createBlob","BlobBuilder","window","WebKitBlobBuilder","MozBlobBuilder","MSBlobBuilder","blobBuilder","append","getBlob","Blob","split","indexOf","atob","decodeURI","ArrayBuffer","Uint8Array","character","charCodeAt","level","console","isObject","variable","Object","toString","isFunction","value","buffer","constructor","isItemList","maybeItemList","isNodeList","maybeNodeList","item","namedItem","isString","maybeString","trimStr","string","String","trim","format","str","newStr","nextIdxToReplace","isFile","maybeFile","File","isFileList","maybeFileList","FileList","isFileOrInput","maybeFileOrInput","isInput","maybeInput","notFile","evaluateType","normalizedType","HTMLInputElement","tagName","isBlob","maybeBlob","isXhrUploadSupported","input","document","createElement","multiple","FormData","createXhrInstance","upload","XMLHttpRequest","ActiveXObject","isFolderDropSupported","dataTransfer","items","webkitGetAsEntry","isFileChunkingSupported","androidStock","webkitSlice","mozSlice","sliceBlob","fileOrBlob","start","end","arrayBufferToHex","bytesAsHex","bytes","byt","byteAsHexStr","readBlobToHex","blob","startOffset","initialBlob","fileReader","FileReader","promise","Promise","onload","success","onerror","failure","readAsArrayBuffer","second","extendNested","override","target","sourceFn","super_","srcPropName","srcPropVal","arr","elt","from","len","hasOwnProperty","getUniqueId","c","r","random","ie","navigator","userAgent","ie7","ie8","ie10","ie11","edge","safari","vendor","chrome","opera","firefox","windows","platform","android","ios6","ios","ios7","ios8","ios800","iosChrome","iosSafari","iosSafariWebView","preventDefault","e","returnValue","toElement","div","html","innerHTML","iterableItem","callback","keyOrIndex","Storage","getItem","bind","oldFunc","context","newArgs","concat","obj2url","obj","temp","prefixDone","uristrings","prefix","add","nextObj","i","nextTemp","encodeURIComponent","join","obj2FormData","formData","arrayKeyName","obj2Inputs","form","setAttribute","appendChild","parseJson","json","JSON","parse","eval","getExtension","filename","extIdx","lastIndexOf","substr","getFilename","blobOrFileInput","fileName","DisposeSupport","disposers","dispose","disposer","shift","addDisposer","disposeFunction","define","amd","module","exports","version","supportedFeatures","testSupportsFileInputElement","tempInput","supported","disabled","ex","isChrome14OrHigher","isCrossOriginXhrSupported","withCredentials","isXdrSupported","XDomainRequest","isCrossOriginAjaxSupported","isFolderSelectionSupported","webkitdirectory","isLocalStorageSupported","localStorage","setItem","isDragAndDropSupported","span","supportsUploading","supportsUploadingBlobs","supportsFileDrop","supportsAjaxFileUploading","supportsFolderDrop","supportsChunking","supportsResume","supportsUploadViaPaste","supportsUploadCors","supportsDeleteFileXdr","supportsDeleteFileCorsXhr","supportsDeleteFileCors","supportsFolderSelection","supportsImagePreviews","supportsUploadProgress","postMessage","ajaxUploading","blobUploading","canDetermineSize","chunking","deleteFileCors","deleteFileCorsXdr","deleteFileCorsXhr","dialogElement","HTMLDialogElement","fileDrop","folderDrop","folderSelection","imagePreviews","imageValidation","itemSizeValidation","pause","progressBar","resume","scaling","tiffPreviews","unlimitedScaledImageSize","uploading","uploadCors","uploadCustomHeaders","uploadNonMultipart","uploadViaPaste","isGenericPromise","maybePromise","then","successArgs","failureArgs","successCallbacks","failureCallbacks","doneCallbacks","state","onSuccess","onFailure","done","BlobProxy","referenceBlob","onCreate","create","UploadButton","o","createInput","BUTTON_ID_ATTR_NAME","buttonId","title","setMultiple","folders","acceptFiles","position","right","top","fontFamily","fontSize","margin","padding","cursor","height","disposeSupport","onChange","hoverClass","focusClass","ios8BrowserCrashWorkaround","overflow","direction","getInput","getButtonId","isMultiple","optInput","removeAttribute","setAcceptFiles","reset","UploadData","uploaderProxy","getDataByIds","idOrIds","entries","id","getDataByUuids","uuids","uuid","byUuid","getDataByStatus","status","statusResults","statuses","statusEnum","statusResultIndexes","byStatus","dataIndex","byProxyGroupId","byBatchId","addFile","spec","SUBMITTING","originalName","size","file","batchId","proxyGroupId","onBeforeStatusChange","onStatusChange","retrieve","optionalFilter","removeFileRef","record","setStatus","newStatus","oldStatus","byStatusOldStatusIndex","splice","uuidChanged","newUuid","oldUuid","updateName","newName","updateSize","newSize","setParentId","targetId","parentId","getIdsInProxyGroup","getIdsInBatch","SUBMITTED","REJECTED","QUEUED","CANCELED","PAUSED","UPLOADING","UPLOAD_FINALIZING","UPLOAD_RETRYING","UPLOAD_SUCCESSFUL","UPLOAD_FAILED","DELETE_FAILED","DELETING","DELETED","basePublicApi","addBlobs","blobDataOrArray","endpoint","addFiles","addInitialFiles","cannedFileList","cannedFile","_addCannedFile","_maybeHandleIos8SafariWorkaround","_storedIds","_currentBatchId","processBlob","_handleNewFile","blobs","defaultName","verifiedFiles","processBlobData","blobData","processCanvas","processCanvasData","canvasData","normalizedQuality","processFileOrInput","fileOrInput","files","normalizeData","fileContainer","_prepareItemsForUpload","cancel","uploadData","_uploadData","getName","_handler","cancelAll","storedIdsCopy","storedFileId","clearStoredFiles","continueUpload","enabled","_uploadFile","deleteFile","_onSubmitDelete","doesExist","fileOrBlobId","isValid","drawThumbnail","fileId","imgOrCanvas","maxSize","fromServer","customResizeFunction","fileOrUrl","promiseToReturn","_imageGenerator","_thumbnailUrls","scale","getFile","container","generate","modifiedContainer","reason","getButton","_getButton","_buttonIdsForFileIds","getEndpoint","_endpointStore","get","uploadDataRecord","getInProgress","getParentId","uploadDataEntry","getUploads","getResumableFilesData","getSize","getNetUploads","_netUploaded","getRemainingAllowedItems","allowedItems","_currentItemLimit","_netUploadedOrQueued","getUuid","isResumable","hasResumeRecord","debug","pauseUpload","expunge","_autoRetries","_retryTimeouts","_preventRetries","_buttons","button","_paramsStore","_pasteHandler","session","refreshOnReset","_refreshSessionData","_succeededSinceLastAllComplete","_failedSinceLastAllComplete","_totalProgress","_customResumeDataStore","retry","_manualRetry","scaleImage","specs","Scaler","setCustomHeaders","headers","_customHeadersStore","set","setCustomResumeData","setDeleteFileCustomHeaders","_deleteFileCustomHeadersStore","setDeleteFileEndpoint","_deleteFileEndpointStore","setDeleteFileParams","_deleteFileParamsStore","setEndpoint","setForm","elementOrId","_updateFormSupportAndParams","setItemLimit","newItemLimit","setName","setParams","setUuid","_onDeleteComplete","errorMessage","uploadStoredFiles","_itemError","_uploadStoredFiles","basePrivateApi","sessionData","deleteFileEndpoint","deleteFileParams","thumbnailUrl","_annotateWithButtonId","associatedInput","qqButtonId","_getButtonId","_batchError","onError","_createDeleteHandler","DeleteFileAjaxRequester","method","maxConnections","uuidParamName","request","uuidName","customHeaders","paramsStore","endpointStore","cors","onDelete","_onDelete","onDeleteComplete","xhrOrXdr","isError","_createPasteHandler","PasteSupport","targetElement","paste","pasteReceived","_handleCheckedCallback","onPasteReceived","_handlePasteSuccess","identifier","_createStore","initialValue","_readOnlyValues_","store","catchall","perIdReadOnlyValues","readOnlyValues","copy","orig","getReadOnlyValues","includeReadOnlyValues","existing","values","addReadOnly","_createUploadDataTracker","_onUploadStatusChange","_maybeAllComplete","setTimeout","_createUploadButton","allowMultiple","workarounds","iosEmptyVideos","_isAllowedExtension","allowedExtensions","accept","validation","classes","buttonFocus","buttonHover","ios8BrowserCrash","inputName","_onInputChange","fileInputTitle","_disposeSupport","_createUploadHandler","additionalOptions","lastOnProgress","preventRetryParam","preventRetryResponseProperty","onProgress","loaded","total","_onProgress","onComplete","xhr","_onComplete","onCancel","cancelFinalizationEffort","_onCancel","onUploadPrep","_onUploadPrep","onUpload","_onUpload","onUploadResult","onUploadChunk","chunkData","_onUploadChunk","onUploadChunkResult","partIndex","onUploadChunkSuccess","_onUploadChunkSuccess","onResume","customResumeData","onAutoRetry","responseJSON","_onAutoRetry","onUuidChanged","setSize","_setSize","getDataByUuid","isQueued","isInProgress","getCustomResumeData","_getCustomResumeData","UploadHandlerController","_fileOrBlobRejected","_formatSize","sizeSymbols","max","toFixed","_generateExtraButtonSpecs","_extraButtonSpecs","extraButtons","extraButtonOptionEntry","extraButtonSpec","_initExtraButton","extraButtonsSpec","_defaultButtonId","buttonOrFileInputOrFile","inputs","fileInput","fileBlobOrInput","_getNotFinished","_getValidationBase","_getValidationDescriptor","fileWrapper","_getValidationDescriptors","fileWrappers","fileDescriptors","_handleCameraAccess","camera","optionRoot","details","callbackRetVal","successParam","newFileWrapperList","actualFile","handler","_customNewFileHandler","_handleNewFileGeneric","addFileToHandler","_trackButton","fileList","extSuppliedName","extension","_handleDeleteSuccess","_handleDeleteFailed","_initFormSupportAndParams","_formSupport","FormSupport","attachedToForm","getFormInputsAsObject","autoUpload","newAutoUpload","newEndpoint","_isDeletePossible","expected","allowXdr","allowed","valid","allowedExt","extRegex","code","maybeNameOrNames","replacement","extensionsForMessage","placeholderMatch","messages","names","validationBase","allowedExtension","formatFileName","sizeLimit","minSizeLimit","placeholder","_onBeforeManualRetry","notFinished","_onAllComplete","ios8SafariUploads","alert","unsupportedBrowserIos8Safari","_maybeParseAndSendUploadError","response","errorReason","defaultResponseError","_maybeProcessNextItemAfterOnValidateCallback","validItem","stopOnFirstInvalidFile","validationDescriptor","onValidate","_onValidateCallbackSuccess","_onValidateCallbackFailure","successful","failed","onAllComplete","_shouldAutoRetry","retryWaitPeriod","autoAttemptDelay","_onBeforeAutoRetry","itemLimit","onManualRetry","clearTimeout","storedItemIndex","fileIndex","onIndividualProgress","_onSubmit","_onSubmitCallbackSuccess","_onSubmitted","onSubmitted","_storeForLater","onSuccessCallback","additionalMandatedParams","adjustedOnSuccessCallback","onSubmitDelete","_deleteHandler","sendDelete","_onTotalProgress","onTotalProgress","enableAuto","_onValidateBatchCallbackFailure","_onValidateBatchCallbackSuccess","validationDescriptors","proposedNetFilesUploadedOrQueued","tooManyItemsError","nextIndex","_validateFileOrBlobData","_upload","onValidateBatch","_preventLeaveInProgress","event","onLeave","Session","_session","addFileRecord","refresh","_sessionRequestComplete","onSessionRequestComplete","onNewSize","maxAutoAttempts","formElementOrId","onSubmit","idToUpload","stillSubmitting","validityChecker","allowEmpty","ImageValidation","validate","image","errorCode","_wrapCallbacks","safeCallback","errorMsg","exception","callbackName","callbackFunc","FineUploaderBasic","disableCancelForFormUploads","warnBeforeUnload","filenameParam","forceMultipart","omitDefaultParams","paramsInBody","requireSuccessJson","totalFileSizeName","maxHeight","maxWidth","minHeight","minWidth","maybeXhr","maybeXhrOrXdr","attemptNumber","fileOrBlobData","typeError","sizeError","minSizeError","emptyError","noFilesError","maxHeightImageError","maxWidthImageError","minHeightImageError","minWidthImageError","retryFailTooManyItems","concurrent","mandatory","paramNames","partByteOffset","chunkSize","totalFileSize","totalParts","partSize","jsonPayload","resetOnStatus","recordsExpireIn","resuming","customKeys","fileOrBlobName","sendCredentials","interceptSubmit","customResizer","sendOriginal","orient","defaultType","defaultQuality","failureText","includeExif","sizes","ImageGenerator","_scaler","handleNewFile","TotalProgress","entry","AjaxRequester","isSimpleMethod","containsNonSimpleHeaders","containsNonSimple","header","isXdr","getCorsAjaxTransport","ontimeout","onprogress","getXhrOrXdr","suppliedXhr","requestData","dequeue","nextId","queue","sendRequest","xdrError","isResponseSuccessful","getParams","onDemandParams","additionalParams","mandatedParams","optXhr","url","payload","onSend","createUrl","additionalQueryParams","getXdrLoadHandler","getXdrErrorHandler","onreadystatechange","getXhrReadyStateChangeHandler","registerForUploadProgress","open","setHeaders","send","shouldParamsBeInQueryString","contentType","stringify","addToPath","readyState","lengthComputable","onDemandHeaders","additionalHeaders","allHeaders","acceptHeader","setRequestHeader","allowXRequestedWithAndCacheControl","responseCode","successfulResponseCodes","prepareToSend","validMethods","DELETE","PATCH","POST","PUT","GET","initTransport","path","cacheBuster","withPath","appendToPath","withParams","withQueryParams","_additionalQueryParams_","withHeaders","withPayload","thePayload","withCacheBuster","qqtimestamp","Date","getTime","canceled","UploadHandler","proxy","fileState","fileItem","getThirdPartyFileId","_getFileState","_setThirdPartyFileId","thirdPartyFileId","_wasCanceled","preventRetryResponse","controller","chunkingPossible","concurrentChunkingPossible","chunked","chunkIdx","_getChunkData","attemptingResume","chunkProgress","_getChunkDataForCallback","finalize","finalizeChunks","normaizedResponse","normalizeResponse","_maybeDeletePersistedChunkData","cleanup","normalizedResponse","handleFailure","clearCachedChunk","inProgressIdx","responseToReport","inProgressChunksArray","inProgress","remaining","unshift","ignoreFailure","keys","_getXhrs","ckid","ckXhr","abort","_cancelled","moveInProgressToRemaining","connectionManager","free","hasMoreParts","nextPart","nextIdx","_getTotalChunks","reevaluateChunking","sendNext","inProgressChunks","available","requestOverrides","uploadChunkData","overrides","uploadChunk","inProgressChunkIdx","_maybePersistChunkedState","clearXhr","_open","_openChunks","_waiting","openChunkEntriesCount","openChunksCount","openChunkIndexes","dontAllowNext","allowNext","waitingIndex","connectionsIndex","getProxyOrBlob","getWaitingOrConnected","waitingOrConnected","chunks","parseInt","isUsingConnection","pop","openChunksEntry","simple","uploadFile","maybeNewUuid","_clearXhrs","getProxy","initHandler","traditional","onFinalizing","_removeExpiredChunkingRecords","isDeferredEligibleForUpload","maybeDefer","generatedBlob","updateBlob","maybeSendDeferredFiles","errorResponse","idsInGroup","uploadedThisId","idInGroup","now","originalResponse","_shouldChunkThisFile","blobToUpload","cancelRetVal","isProxied","_getLocalStorageId","isAttemptingResume","WindowReceiveMessage","callbackWrapperDetachers","receiveMessage","onMessageCallbackWrapper","stopReceivingMessages","detacher","FormUploadHandler","expungeFile","detachLoadEvents","isCors","postMessageCallbackTimers","corsMessageReceiver","iframe","getElementById","_getIframeName","getFileIdForIframeName","iframeName","initIframeForUpload","body","registerPostMessageCallback","onloadCallbacks","onloadCallback","_parseJsonResponse","_detachLoadEvent","formHandlerInstanceId","_attachLoadEvent","responseDescriptor","contentDocument","_createIframe","_initFormForUpload","targetName","innerHtmlOrMessage","XhrUploadHandler","xhrId","ajaxRequester","_getAjaxRequester","getChunkSize","chunkFiles","resumeEnabled","blobOrProxy","_initTempState","_maybePrepareForResume","cachedChunks","tempState","xhrs","ajaxRequesters","responseParser","lastChunkIdx","_getXhr","resumableFilesData","_iterateResumeRecords","notResumable","optInProgress","optRemaining","chunkingState","reverse","paused","totalChunks","parts","newBlob","chunkId","_createXhr","optChunkIdx","_registerXhr","chunkIndex","fileSize","startBytes","endBytes","part","count","startByte","endByte","localStorageId","forEach","_getMimeType","_getPersistableData","ceil","_markNotResumable","removeItem","persistedData","lastUpdated","_registerProgressHandler","progressCalculator","totalSuccessfullyLoadedForFile","loadedForRequest","totalForRequest","estActualChunkLoaded","totalLoadedForFile","chunkLoaded","optAjaxRequester","xhrsId","expirationDays","expirationDate","setDate","getDate","getMandatedParams","_method","requester","detectSubsampling","img","ctx","iw","naturalWidth","ih","naturalHeight","width","getContext","drawImage","getImageData","detectVerticalSquash","alpha","ratio","sy","ey","py","renderImageToDataURL","doSquash","renderImageToCanvas","maybeCalculateDownsampledDimensions","origHeight","origWidth","newHeight","sqrt","newWidth","modifiedDimensions","save","resize","renderImageToCanvasWithCustomResizer","imageHeight","imageWidth","orientation","targetHeight","targetWidth","transformCoordinate","tmpCtx","sx","dx","d","tmpCanvas","vertSquashRatio","dw","dh","dy","clearRect","restore","qqImageRendered","resizeInfo","sourceCanvas","sourceCanvasContext","targetCanvas","translate","rotate","PI","MegaPixImage","srcImage","errorCallback","Image","URL","createObjectURL","webkitURL","src","listeners","imageLoadListeners","render","opt","imgWidth","imgHeight","optionsKey","optionsValue","oldTargetSrc","onrender","isImg","isCanvas","isImgCorsSupported","crossOrigin","isCanvasSupported","determineMimeOfFileName","nameWithPath","pathSegments","isCrossOrigin","targetProtocol","targetHostname","targetPort","targetAnchor","href","protocol","port","hostname","location","registerImgLoadListeners","registerCanvasDrawImageListener","registerThumbnailRenderedListener","registered","draw","drawPreview","Identify","megapixErrorHandler","isPreviewable","dummyExif","exif","Exif","mpImg","Orientation","failureMsg","drawOnCanvasOrImgFromUrl","canvasOrImg","tempImg","tempImgRender","drawOnImgFromUrlWithCssScaling","drawFromUrl","fileBlobOrUrl","_testing","parseLittleEndian","hex","pow","seekToApp1","offset","theOffset","thePromise","segmentLength","getApp1Offset","isLittleEndian","app1Start","getDirEntryCount","littleEndian","getIfd","dirEntries","getDirEntries","ifdHex","getTagValues","tagsToFind","TAG_IDS","vals","tagValHex","tagValLength","idHex","tagsToFindIdx","TAG_INFO","274","parser","onParseFailure","app1Offset","dirEntryCount","tagValues","isIdentifiable","magicBytes","questionableBytes","identifiable","magicBytesEntries","magicBytesArrayEntry","previewable","isPreviewableSync","PREVIEWABLE_MIME_TYPES","fileMime","isRecognizedImage","image/jpeg","image/gif","image/png","image/bmp","image/tiff","hasNonZeroLimits","limits","atLeastOne","limit","getWidthHeight","sizeDetermination","getFailingLimit","dimensions","failingLimit","limitName","limitValue","limitMatcher","dimensionPropName","actualValue","validationEffort","isJsonResponseValid","handleFileItems","fileItems","someItemsIgnored","err","refreshEffort","refreshCompleteCallback","requesterOptions","SessionAjaxRequester","queryServer","responseText","includeOriginal","failedToScaleText","_getSortedSizes","getFileRecords","originalFileUuid","originalFileName","originalBlobOrBlobData","records","originalBlob","sizeRecord","outputType","_determineOutputType","requestedType","refType","_getName","_generateScaledImage","failedText","api","scaledIds","originalId","blobSize","scaledId","qqparentuuid","qqparentsize","param","scalingEffort","scalingOptions","scaler","referenceType","scaledVersionProperties","startOfExt","versionType","scaledName","scaledExt","nameAppendage","sort","a","b","sourceFile","imageGenerator","scaledImageDataUri","signalSuccess","_insertExifHeader","scaledImageDataUriWithExif","originalImage","reader","insertionEffort","originalImageDataUri","ExifRestorer","readAsDataURL","_dataUriToBlob","_createBlob","KEY_STR","encode64","chr1","chr2","enc1","enc2","enc3","output","chr3","enc4","isNaN","origFileBase64","resizedFileBase64","rawImage","decode64","segments","slice2Segments","exifManipulation","exifArray","getExifArray","newImageArray","insertExif","seg","x","imageData","buf","separatePoint","mae","ato","array","rawImageArray","head","endPoint","perFileProgress","totalLoaded","totalSize","lastLoadedSent","lastTotalSent","callbackProxy","noRetryableFiles","retryable","none","failedId","updateTotalProgress","onNew","newLoaded","newTotal","oldLoaded","oldTotal","isImage","registerPasteHandler","detachPasteHandler","clipboardData","getAsFile","unregisterPasteHandler","startUpload","determineNewEndpoint","formEl","validateForm","nativeSubmit","checkValidity","maybeUploadOnSubmit","submit","determineFormEl","_form2Obj","notIrrelevantType","irrelevantTypes","radioOrCheckbox","ignoreValue","checked","selectValue","select","selected","elements","getIframeContentJson","doc","innerHtml","contentWindow","nodeValue","createForm","responseFromMessage","multipart","addChunkingSpecificParams","allChunksDoneRequester","AllChunksDoneAjaxRequester","createReadyStateChangedHandler","onUploadOrChunkComplete","getChunksCompleteParams","isErrorUploadResponse","parseResponse","sendChunksCompleteRequest","complete","setParamsAndGetEntityToSend","entityToSendParams","xhrOverrides","customParams","defaultParams","xhrOverrideParams","setUploadHeaders","headersOptions","headerOverrides","headerName","headerValue","extraHeaders","uploadChunkParams","toSend","promises","endpointHandler","uploadDroppedFiles","uploadDropZone","filesAsArray","dropLog","dropDisabled","processingDroppedFilesComplete","getElement","traverseFileTree","parseEntryPromise","qqPath","extractDirectoryPath","droppedFiles","fileError","fullPath","isDirectory","getFilesInDirectory","entriesLeft","indexOfNameInFullPath","accumEntries","existingPromise","dirReader","createReader","readEntries","newEntries","handleDataTransfer","pendingFolderPromises","handleDataTransferPromise","processingDroppedFiles","allowMultipleItems","dropError","setupDropzone","dropArea","dropZone","UploadDropZone","HIDE_ZONES_EVENT_NAME","onEnter","dropActive","stopPropagation","onLeaveNotDescendants","onDrop","uploadDropZones","isFileDrag","dragEvent","fileDrag","types","leavingDocumentOut","y","setupDragDrop","dropZones","maybeHideDropZones","HTMLElement","setupExtraDropzone","removeDropzone","dzs","targetEl","errorSpecifics","dragoverShouldBeCanceled","disableDropOutside","dropOutsideDisabled","dropEffect","isValidFileDrag","effectTest","dt","isSafari","effectAllowed","includes","isOrSetDropDisabled","isDisabled","preventDrop","triggerHidezonesEvent","triggerUsingOldApi","hideZonesEvent","createEvent","initEvent","CustomEvent","dispatchEvent","attachEvents","effect","relatedTarget","elementFromPoint","clientX","clientY","uiPublicApi","_parent","_templating","addCacheToDom","clearFiles","addExtraDropzone","_dnd","removeExtraDropzone","getItemByFileId","isHiddenForever","getFileContainer","_setupDragAndDrop","_totalFilesInBatch","_filesInBatchAddedToUi","_setupClickAndEditEventHandlers","formattedFilename","updateFilename","uploadPaused","continued","uploadContinued","getId","fileContainerOrChildEl","getFileId","getDropTarget","qqDropTarget","uiPrivateApi","_removeFileItem","removeFile","_fileButtonsClickHandler","FileButtonsClickHandler","_bindFileButtonsClickEvent","_focusinEventSupported","_isEditFilenameEnabled","_filenameClickHandler","_bindFilenameClickEvent","_filenameInputFocusInHandler","_bindFilenameInputFocusInEvent","_filenameInputFocusHandler","_bindFilenameInputFocusEvent","dragAndDrop","extraDropzones","templating","defaultDropZone","getDropZone","showDropProcessing","hideDropProcessing","errorData","lvl","onDeleteFile","onRetry","onPause","onContinue","onGetName","isEditFilenamePossible","FilenameClickHandler","FilenameInputFocusHandler","_filenameEditHandler","onGetUploadStatus","onSetName","onEditingStatusChange","isEditing","qqInput","getEditInput","qqFileContainer","hideFilename","hideEditIcon","showFilename","showEditIcon","markFilenameEditable","hideRetry","setStatusText","_classes","retrying","hidePause","FilenameInputFocusInHandler","hideSpinner","resetTotalProgress","reportDirectoryPaths","qqpath","_addToList","addHandler","updateProgress","hideCancel","hideProgress","waitingForResponse","_displayFileSize","completeUpload","_markFileAsSuccessful","fail","showCancel","isRetryPossible","showRetry","_controlFailureTextDisplay","parentRetVal","newResult","showDeleteButton","_maybeUpdateThumbnail","showSpinner","allowPause","retryNumForDisplay","maxAuto","retryNote","_showCancelLink","showAutoRetryNote","autoRetryNote","resetProgress","_onSubmitDeleteSuccess","forceConfirm","_showDeleteConfirm","_sendDeleteRequest","deletingFailedText","hideDeleteButton","deletingStatusText","confirmMessage","deleteRequestArgs","showConfirm","canned","prependData","prependIndex","dontDisplay","hideScaled","prependFiles","disableCancel","_handledProxyGroup","_clearList","addFileToCache","updateThumbnail","thumbnails","generatePreview","fileSizeOnSubmit","loadedSize","sizeForDisplay","_formatProgress","uploadedSize","formatProgress","mode","responseProperty","failureReason","failedUploadTextDisplay","failUpload","enableTooltip","_showTooltip","showMessage","_setupPastePrompt","namePromptMessage","defaultVal","showPrompt","placeholders","waitUntilResponse","listElement","template","editable","tooManyFilesError","unsupportedBrowser","promptForName","maxCount","notAvailablePath","waitingPath","timeBetweenThumbs","hasDialog","showDialog","confirm","defaultValue","prompt","Templating","templateIdOrEl","containerEl","fileContainerEl","maxThumbs","waitUntilUpdate","thumbnailNotAvailable","waitingForThumbnail","renderFailure","isEditElementsExist","isRetryElementExist","templateDom","showThumbnails","serverScale","fileBatch","content","createDocumentFragment","map","isCancelDisabled","generatedThumbnails","thumbnailQueueMonitorRunning","thumbGenerationQueue","thumbnailMaxSize","selectorClasses","alertDialog","dialogCancelButton","confirmDialog","dialogMessage","dialogOkButton","promptDialog","drop","list","progressBarContainer","totalProgressBarContainer","totalProgressBar","spinner","continueButton","deleteButton","statusText","editFilenameInput","editNameIcon","dropText","dropProcessing","dropProcessingSpinner","thumbnail","previewGeneration","cachedThumbnailNotAvailableImg","cachedWaitingForThumbnailImg","cacheThumbnailPlaceholders","notAvailableUrl","waitingUrl","updatedImg","displayWaitingImg","waitingImgPlacement","maybeScalePlaceholderViaCss","show","generateNewPreview","getThumbnail","qqThumbnailId","maybeSetDisplayNotAvailableImg","generateNextQueuedPreview","queuedThumbRequest","update","processUpdateQueuedPreviewRequest","processNewQueuedPreviewRequest","getCancel","getTemplateEl","getContinue","getDialog","getDelete","getDropProcessing","getEditIcon","getPause","getProgress","getRetry","getSpinner","cssClass","previewing","notAvailableImgPlacement","parseAndGetTemplate","scriptEl","scriptHtml","fileListNode","tempTemplateEl","fileListEl","defaultButton","dropTextEl","uploaderEl","fileTemplate","prependFile","parentEl","beforeEl","optFileOrBlob","relatedThumbnailId","useCachedPreview","showWaitingImg","setProgressBarWidth","percent","bar","progressBarSelector","targetThumbnailId","cachedThumbnailId","targetThumbnail","cachedThumbnail","hideTotalProgress","cantRenderEl","prependInfo","hideForever","batch","thumb","fileEl","fileNameEl","waitingImg","currentNode","getFileList","filenameEl","isFileName","icon","isEditIcon","isEditInput","isCancel","allowContinueButton","isPause","isContinueButton","isDeleteButton","isRetry","textEl","dialog","messageEl","inputEl","cancelBtn","okBtn","closeHandler","cancelClickHandler","okClickHandler","close","showModal","UiEventHandler","s","protectedApi","eventType","srcElement","onHandled","attachTo","getFileIdFromItem","qqFileId","getDisposeSupport","examineEvent","buttonHandlers","buttonType","firstLetterCapButtonType","inheritedInternalApi","handleFilenameEdit","FilenameEditHandler","handleInputFocus","getFilenameSansExtension","filenameSansExt","getOriginalExtension","origName","handleNameUpdate","newFilenameInputEl","origExtension","registerInputBlurHandler","registerInputEnterKeyHandler","keyCode","which","focusInput","focus"],"mappings":"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","file":"jquery.fine-uploader.min.js","sourcesContent":[null,"/*globals jQuery, qq*/\n(function($) {\n \"use strict\";\n var $el,\n pluginOptions = [\"uploaderType\", \"endpointType\"];\n\n function init(options) {\n var xformedOpts = transformVariables(options || {}),\n newUploaderInstance = getNewUploaderInstance(xformedOpts);\n\n uploader(newUploaderInstance);\n addCallbacks(xformedOpts, newUploaderInstance);\n\n return $el;\n }\n\n function getNewUploaderInstance(params) {\n var uploaderType = pluginOption(\"uploaderType\"),\n namespace = pluginOption(\"endpointType\");\n\n // If the integrator has defined a specific type of uploader to load, use that, otherwise assume `qq.FineUploader`\n if (uploaderType) {\n // We can determine the correct constructor function to invoke by combining \"FineUploader\"\n // with the upper camel cased `uploaderType` value.\n uploaderType = uploaderType.charAt(0).toUpperCase() + uploaderType.slice(1).toLowerCase();\n\n if (namespace) {\n return new qq[namespace][\"FineUploader\" + uploaderType](params);\n }\n\n return new qq[\"FineUploader\" + uploaderType](params);\n }\n else {\n if (namespace) {\n return new qq[namespace].FineUploader(params);\n }\n\n return new qq.FineUploader(params);\n }\n }\n\n function dataStore(key, val) {\n var data = $el.data(\"fineuploader\");\n\n if (val) {\n if (data === undefined) {\n data = {};\n }\n data[key] = val;\n $el.data(\"fineuploader\", data);\n }\n else {\n if (data === undefined) {\n return null;\n }\n return data[key];\n }\n }\n\n //the underlying Fine Uploader instance is stored in jQuery's data stored, associated with the element\n // tied to this instance of the plug-in\n function uploader(instanceToStore) {\n return dataStore(\"uploader\", instanceToStore);\n }\n\n function pluginOption(option, optionVal) {\n return dataStore(option, optionVal);\n }\n\n // Implement all callbacks defined in Fine Uploader as functions that trigger appropriately names events and\n // return the result of executing the bound handler back to Fine Uploader\n function addCallbacks(transformedOpts, newUploaderInstance) {\n var callbacks = transformedOpts.callbacks = {};\n\n $.each(newUploaderInstance._options.callbacks, function(prop, nonJqueryCallback) {\n var name, callbackEventTarget;\n\n name = /^on(\\w+)/.exec(prop)[1];\n name = name.substring(0, 1).toLowerCase() + name.substring(1);\n callbackEventTarget = $el;\n\n callbacks[prop] = function() {\n var originalArgs = Array.prototype.slice.call(arguments),\n transformedArgs = [],\n nonJqueryCallbackRetVal, jqueryEventCallbackRetVal;\n\n $.each(originalArgs, function(idx, arg) {\n transformedArgs.push(maybeWrapInJquery(arg));\n });\n\n nonJqueryCallbackRetVal = nonJqueryCallback.apply(this, originalArgs);\n\n try {\n jqueryEventCallbackRetVal = callbackEventTarget.triggerHandler(name, transformedArgs);\n }\n catch (error) {\n qq.log(\"Caught error in Fine Uploader jQuery event handler: \" + error.message, \"error\");\n }\n\n /*jshint -W116*/\n if (nonJqueryCallbackRetVal != null) {\n return nonJqueryCallbackRetVal;\n }\n return jqueryEventCallbackRetVal;\n };\n });\n\n newUploaderInstance._options.callbacks = callbacks;\n }\n\n //transform jQuery objects into HTMLElements, and pass along all other option properties\n function transformVariables(source, dest) {\n var xformed, arrayVals;\n\n if (dest === undefined) {\n if (source.uploaderType !== \"basic\") {\n xformed = { element: $el[0] };\n }\n else {\n xformed = {};\n }\n }\n else {\n xformed = dest;\n }\n\n $.each(source, function(prop, val) {\n if ($.inArray(prop, pluginOptions) >= 0) {\n pluginOption(prop, val);\n }\n else if (val instanceof $) {\n xformed[prop] = val[0];\n }\n else if ($.isPlainObject(val)) {\n xformed[prop] = {};\n transformVariables(val, xformed[prop]);\n }\n else if ($.isArray(val)) {\n arrayVals = [];\n $.each(val, function(idx, arrayVal) {\n var arrayObjDest = {};\n\n if (arrayVal instanceof $) {\n $.merge(arrayVals, arrayVal);\n }\n else if ($.isPlainObject(arrayVal)) {\n transformVariables(arrayVal, arrayObjDest);\n arrayVals.push(arrayObjDest);\n }\n else {\n arrayVals.push(arrayVal);\n }\n });\n xformed[prop] = arrayVals;\n }\n else {\n xformed[prop] = val;\n }\n });\n\n if (dest === undefined) {\n return xformed;\n }\n }\n\n function isValidCommand(command) {\n return $.type(command) === \"string\" &&\n !command.match(/^_/) && //enforce private methods convention\n uploader()[command] !== undefined;\n }\n\n // Assuming we have already verified that this is a valid command, call the associated function in the underlying\n // Fine Uploader instance (passing along the arguments from the caller) and return the result of the call back to the caller\n function delegateCommand(command) {\n var xformedArgs = [],\n origArgs = Array.prototype.slice.call(arguments, 1),\n retVal;\n\n transformVariables(origArgs, xformedArgs);\n\n retVal = uploader()[command].apply(uploader(), xformedArgs);\n\n return maybeWrapInJquery(retVal);\n }\n\n // If the value is an `HTMLElement` or `HTMLDocument`, wrap it in a `jQuery` object\n function maybeWrapInJquery(val) {\n var transformedVal = val;\n\n // If the command is returning an `HTMLElement` or `HTMLDocument`, wrap it in a `jQuery` object\n /*jshint -W116*/\n if (val != null && typeof val === \"object\" &&\n (val.nodeType === 1 || val.nodeType === 9) && val.cloneNode) {\n\n transformedVal = $(val);\n }\n\n return transformedVal;\n }\n\n $.fn.fineUploader = function(optionsOrCommand) {\n var self = this, selfArgs = arguments, retVals = [];\n\n this.each(function(index, el) {\n $el = $(el);\n\n if (uploader() && isValidCommand(optionsOrCommand)) {\n retVals.push(delegateCommand.apply(self, selfArgs));\n\n if (self.length === 1) {\n return false;\n }\n }\n else if (typeof optionsOrCommand === \"object\" || !optionsOrCommand) {\n init.apply(self, selfArgs);\n }\n else {\n $.error(\"Method \" + optionsOrCommand + \" does not exist on jQuery.fineUploader\");\n }\n });\n\n if (retVals.length === 1) {\n return retVals[0];\n }\n else if (retVals.length > 1) {\n return retVals;\n }\n\n return this;\n };\n\n}(jQuery));\n","/*globals jQuery, qq*/\n(function($) {\n \"use strict\";\n var rootDataKey = \"fineUploaderDnd\",\n $el;\n\n function init(options) {\n if (!options) {\n options = {};\n }\n\n options.dropZoneElements = [$el];\n var xformedOpts = transformVariables(options);\n addCallbacks(xformedOpts);\n dnd(new qq.DragAndDrop(xformedOpts));\n\n return $el;\n }\n\n function dataStore(key, val) {\n var data = $el.data(rootDataKey);\n\n if (val) {\n if (data === undefined) {\n data = {};\n }\n data[key] = val;\n $el.data(rootDataKey, data);\n }\n else {\n if (data === undefined) {\n return null;\n }\n return data[key];\n }\n }\n\n function dnd(instanceToStore) {\n return dataStore(\"dndInstance\", instanceToStore);\n }\n\n function addCallbacks(transformedOpts) {\n var callbacks = transformedOpts.callbacks = {};\n\n $.each(new qq.DragAndDrop.callbacks(), function(prop, func) {\n var name = prop,\n $callbackEl;\n\n $callbackEl = $el;\n\n callbacks[prop] = function() {\n var args = Array.prototype.slice.call(arguments),\n jqueryHandlerResult = $callbackEl.triggerHandler(name, args);\n\n return jqueryHandlerResult;\n };\n });\n }\n\n //transform jQuery objects into HTMLElements, and pass along all other option properties\n function transformVariables(source, dest) {\n var xformed, arrayVals;\n\n if (dest === undefined) {\n xformed = {};\n }\n else {\n xformed = dest;\n }\n\n $.each(source, function(prop, val) {\n if (val instanceof $) {\n xformed[prop] = val[0];\n }\n else if ($.isPlainObject(val)) {\n xformed[prop] = {};\n transformVariables(val, xformed[prop]);\n }\n else if ($.isArray(val)) {\n arrayVals = [];\n $.each(val, function(idx, arrayVal) {\n if (arrayVal instanceof $) {\n $.merge(arrayVals, arrayVal);\n }\n else {\n arrayVals.push(arrayVal);\n }\n });\n xformed[prop] = arrayVals;\n }\n else {\n xformed[prop] = val;\n }\n });\n\n if (dest === undefined) {\n return xformed;\n }\n }\n\n function isValidCommand(command) {\n return $.type(command) === \"string\" &&\n command === \"dispose\" &&\n dnd()[command] !== undefined;\n }\n\n function delegateCommand(command) {\n var xformedArgs = [], origArgs = Array.prototype.slice.call(arguments, 1);\n transformVariables(origArgs, xformedArgs);\n return dnd()[command].apply(dnd(), xformedArgs);\n }\n\n $.fn.fineUploaderDnd = function(optionsOrCommand) {\n var self = this, selfArgs = arguments, retVals = [];\n\n this.each(function(index, el) {\n $el = $(el);\n\n if (dnd() && isValidCommand(optionsOrCommand)) {\n retVals.push(delegateCommand.apply(self, selfArgs));\n\n if (self.length === 1) {\n return false;\n }\n }\n else if (typeof optionsOrCommand === \"object\" || !optionsOrCommand) {\n init.apply(self, selfArgs);\n }\n else {\n $.error(\"Method \" + optionsOrCommand + \" does not exist in Fine Uploader's DnD module.\");\n }\n });\n\n if (retVals.length === 1) {\n return retVals[0];\n }\n else if (retVals.length > 1) {\n return retVals;\n }\n\n return this;\n };\n\n}(jQuery));\n","/*globals window, navigator, document, FormData, File, HTMLInputElement, XMLHttpRequest, Blob, Storage, ActiveXObject */\n/* jshint -W079 */\nvar qq = function(element) {\n \"use strict\";\n\n return {\n hide: function() {\n element.style.display = \"none\";\n return this;\n },\n\n /** Returns the function which detaches attached event */\n attach: function(type, fn) {\n if (element.addEventListener) {\n element.addEventListener(type, fn, false);\n } else if (element.attachEvent) {\n element.attachEvent(\"on\" + type, fn);\n }\n return function() {\n qq(element).detach(type, fn);\n };\n },\n\n detach: function(type, fn) {\n if (element.removeEventListener) {\n element.removeEventListener(type, fn, false);\n } else if (element.attachEvent) {\n element.detachEvent(\"on\" + type, fn);\n }\n return this;\n },\n\n contains: function(descendant) {\n // The [W3C spec](http://www.w3.org/TR/domcore/#dom-node-contains)\n // says a `null` (or ostensibly `undefined`) parameter\n // passed into `Node.contains` should result in a false return value.\n // IE7 throws an exception if the parameter is `undefined` though.\n if (!descendant) {\n return false;\n }\n\n // compareposition returns false in this case\n if (element === descendant) {\n return true;\n }\n\n if (element.contains) {\n return element.contains(descendant);\n } else {\n /*jslint bitwise: true*/\n return !!(descendant.compareDocumentPosition(element) & 8);\n }\n },\n\n /**\n * Insert this element before elementB.\n */\n insertBefore: function(elementB) {\n elementB.parentNode.insertBefore(element, elementB);\n return this;\n },\n\n remove: function() {\n element.parentNode.removeChild(element);\n return this;\n },\n\n /**\n * Sets styles for an element.\n * Fixes opacity in IE6-8.\n */\n css: function(styles) {\n /*jshint eqnull: true*/\n if (element.style == null) {\n throw new qq.Error(\"Can't apply style to node as it is not on the HTMLElement prototype chain!\");\n }\n\n /*jshint -W116*/\n if (styles.opacity != null) {\n if (typeof element.style.opacity !== \"string\" && typeof (element.filters) !== \"undefined\") {\n styles.filter = \"alpha(opacity=\" + Math.round(100 * styles.opacity) + \")\";\n }\n }\n qq.extend(element.style, styles);\n\n return this;\n },\n\n hasClass: function(name, considerParent) {\n var re = new RegExp(\"(^| )\" + name + \"( |$)\");\n return re.test(element.className) || !!(considerParent && re.test(element.parentNode.className));\n },\n\n addClass: function(name) {\n if (!qq(element).hasClass(name)) {\n element.className += \" \" + name;\n }\n return this;\n },\n\n removeClass: function(name) {\n var re = new RegExp(\"(^| )\" + name + \"( |$)\");\n element.className = element.className.replace(re, \" \").replace(/^\\s+|\\s+$/g, \"\");\n return this;\n },\n\n getByClass: function(className, first) {\n var candidates,\n result = [];\n\n if (first && element.querySelector) {\n return element.querySelector(\".\" + className);\n }\n else if (element.querySelectorAll) {\n return element.querySelectorAll(\".\" + className);\n }\n\n candidates = element.getElementsByTagName(\"*\");\n\n qq.each(candidates, function(idx, val) {\n if (qq(val).hasClass(className)) {\n result.push(val);\n }\n });\n return first ? result[0] : result;\n },\n\n getFirstByClass: function(className) {\n return qq(element).getByClass(className, true);\n },\n\n children: function() {\n var children = [],\n child = element.firstChild;\n\n while (child) {\n if (child.nodeType === 1) {\n children.push(child);\n }\n child = child.nextSibling;\n }\n\n return children;\n },\n\n setText: function(text) {\n element.innerText = text;\n element.textContent = text;\n return this;\n },\n\n clearText: function() {\n return qq(element).setText(\"\");\n },\n\n // Returns true if the attribute exists on the element\n // AND the value of the attribute is NOT \"false\" (case-insensitive)\n hasAttribute: function(attrName) {\n var attrVal;\n\n if (element.hasAttribute) {\n\n if (!element.hasAttribute(attrName)) {\n return false;\n }\n\n /*jshint -W116*/\n return (/^false$/i).exec(element.getAttribute(attrName)) == null;\n }\n else {\n attrVal = element[attrName];\n\n if (attrVal === undefined) {\n return false;\n }\n\n /*jshint -W116*/\n return (/^false$/i).exec(attrVal) == null;\n }\n }\n };\n};\n\n(function() {\n \"use strict\";\n\n qq.canvasToBlob = function(canvas, mime, quality) {\n return qq.dataUriToBlob(canvas.toDataURL(mime, quality));\n };\n\n qq.dataUriToBlob = function(dataUri) {\n var arrayBuffer, byteString,\n createBlob = function(data, mime) {\n var BlobBuilder = window.BlobBuilder ||\n window.WebKitBlobBuilder ||\n window.MozBlobBuilder ||\n window.MSBlobBuilder,\n blobBuilder = BlobBuilder && new BlobBuilder();\n\n if (blobBuilder) {\n blobBuilder.append(data);\n return blobBuilder.getBlob(mime);\n }\n else {\n return new Blob([data], {type: mime});\n }\n },\n intArray, mimeString;\n\n // convert base64 to raw binary data held in a string\n if (dataUri.split(\",\")[0].indexOf(\"base64\") >= 0) {\n byteString = atob(dataUri.split(\",\")[1]);\n }\n else {\n byteString = decodeURI(dataUri.split(\",\")[1]);\n }\n\n // extract the MIME\n mimeString = dataUri.split(\",\")[0]\n .split(\":\")[1]\n .split(\";\")[0];\n\n // write the bytes of the binary string to an ArrayBuffer\n arrayBuffer = new ArrayBuffer(byteString.length);\n intArray = new Uint8Array(arrayBuffer);\n qq.each(byteString, function(idx, character) {\n intArray[idx] = character.charCodeAt(0);\n });\n\n return createBlob(arrayBuffer, mimeString);\n };\n\n qq.log = function(message, level) {\n if (window.console) {\n if (!level || level === \"info\") {\n window.console.log(message);\n }\n else\n {\n if (window.console[level]) {\n window.console[level](message);\n }\n else {\n window.console.log(\"<\" + level + \"> \" + message);\n }\n }\n }\n };\n\n qq.isObject = function(variable) {\n return variable && !variable.nodeType && Object.prototype.toString.call(variable) === \"[object Object]\";\n };\n\n qq.isFunction = function(variable) {\n return typeof (variable) === \"function\";\n };\n\n /**\n * Check the type of a value. Is it an \"array\"?\n *\n * @param value value to test.\n * @returns true if the value is an array or associated with an `ArrayBuffer`\n */\n qq.isArray = function(value) {\n return Object.prototype.toString.call(value) === \"[object Array]\" ||\n (value && window.ArrayBuffer && value.buffer && value.buffer.constructor === ArrayBuffer);\n };\n\n // Looks for an object on a `DataTransfer` object that is associated with drop events when utilizing the Filesystem API.\n qq.isItemList = function(maybeItemList) {\n return Object.prototype.toString.call(maybeItemList) === \"[object DataTransferItemList]\";\n };\n\n // Looks for an object on a `NodeList` or an `HTMLCollection`|`HTMLFormElement`|`HTMLSelectElement`\n // object that is associated with collections of Nodes.\n qq.isNodeList = function(maybeNodeList) {\n return Object.prototype.toString.call(maybeNodeList) === \"[object NodeList]\" ||\n // If `HTMLCollection` is the actual type of the object, we must determine this\n // by checking for expected properties/methods on the object\n (maybeNodeList.item && maybeNodeList.namedItem);\n };\n\n qq.isString = function(maybeString) {\n return Object.prototype.toString.call(maybeString) === \"[object String]\";\n };\n\n qq.trimStr = function(string) {\n if (String.prototype.trim) {\n return string.trim();\n }\n\n return string.replace(/^\\s+|\\s+$/g, \"\");\n };\n\n /**\n * @param str String to format.\n * @returns {string} A string, swapping argument values with the associated occurrence of {} in the passed string.\n */\n qq.format = function(str) {\n\n var args = Array.prototype.slice.call(arguments, 1),\n newStr = str,\n nextIdxToReplace = newStr.indexOf(\"{}\");\n\n qq.each(args, function(idx, val) {\n var strBefore = newStr.substring(0, nextIdxToReplace),\n strAfter = newStr.substring(nextIdxToReplace + 2);\n\n newStr = strBefore + val + strAfter;\n nextIdxToReplace = newStr.indexOf(\"{}\", nextIdxToReplace + val.length);\n\n // End the loop if we have run out of tokens (when the arguments exceed the # of tokens)\n if (nextIdxToReplace < 0) {\n return false;\n }\n });\n\n return newStr;\n };\n\n qq.isFile = function(maybeFile) {\n return window.File && Object.prototype.toString.call(maybeFile) === \"[object File]\";\n };\n\n qq.isFileList = function(maybeFileList) {\n return window.FileList && Object.prototype.toString.call(maybeFileList) === \"[object FileList]\";\n };\n\n qq.isFileOrInput = function(maybeFileOrInput) {\n return qq.isFile(maybeFileOrInput) || qq.isInput(maybeFileOrInput);\n };\n\n qq.isInput = function(maybeInput, notFile) {\n var evaluateType = function(type) {\n var normalizedType = type.toLowerCase();\n\n if (notFile) {\n return normalizedType !== \"file\";\n }\n\n return normalizedType === \"file\";\n };\n\n if (window.HTMLInputElement) {\n if (Object.prototype.toString.call(maybeInput) === \"[object HTMLInputElement]\") {\n if (maybeInput.type && evaluateType(maybeInput.type)) {\n return true;\n }\n }\n }\n if (maybeInput.tagName) {\n if (maybeInput.tagName.toLowerCase() === \"input\") {\n if (maybeInput.type && evaluateType(maybeInput.type)) {\n return true;\n }\n }\n }\n\n return false;\n };\n\n qq.isBlob = function(maybeBlob) {\n if (window.Blob && Object.prototype.toString.call(maybeBlob) === \"[object Blob]\") {\n return true;\n }\n };\n\n qq.isXhrUploadSupported = function() {\n var input = document.createElement(\"input\");\n input.type = \"file\";\n\n return (\n input.multiple !== undefined &&\n typeof File !== \"undefined\" &&\n typeof FormData !== \"undefined\" &&\n typeof (qq.createXhrInstance()).upload !== \"undefined\");\n };\n\n // Fall back to ActiveX is native XHR is disabled (possible in any version of IE).\n qq.createXhrInstance = function() {\n if (window.XMLHttpRequest) {\n return new XMLHttpRequest();\n }\n\n try {\n return new ActiveXObject(\"MSXML2.XMLHTTP.3.0\");\n }\n catch (error) {\n qq.log(\"Neither XHR or ActiveX are supported!\", \"error\");\n return null;\n }\n };\n\n qq.isFolderDropSupported = function(dataTransfer) {\n return dataTransfer.items &&\n dataTransfer.items.length > 0 &&\n dataTransfer.items[0].webkitGetAsEntry;\n };\n\n qq.isFileChunkingSupported = function() {\n return !qq.androidStock() && //Android's stock browser cannot upload Blobs correctly\n qq.isXhrUploadSupported() &&\n (File.prototype.slice !== undefined || File.prototype.webkitSlice !== undefined || File.prototype.mozSlice !== undefined);\n };\n\n qq.sliceBlob = function(fileOrBlob, start, end) {\n var slicer = fileOrBlob.slice || fileOrBlob.mozSlice || fileOrBlob.webkitSlice;\n\n return slicer.call(fileOrBlob, start, end);\n };\n\n qq.arrayBufferToHex = function(buffer) {\n var bytesAsHex = \"\",\n bytes = new Uint8Array(buffer);\n\n qq.each(bytes, function(idx, byt) {\n var byteAsHexStr = byt.toString(16);\n\n if (byteAsHexStr.length < 2) {\n byteAsHexStr = \"0\" + byteAsHexStr;\n }\n\n bytesAsHex += byteAsHexStr;\n });\n\n return bytesAsHex;\n };\n\n qq.readBlobToHex = function(blob, startOffset, length) {\n var initialBlob = qq.sliceBlob(blob, startOffset, startOffset + length),\n fileReader = new FileReader(),\n promise = new qq.Promise();\n\n fileReader.onload = function() {\n promise.success(qq.arrayBufferToHex(fileReader.result));\n };\n\n fileReader.onerror = promise.failure;\n\n fileReader.readAsArrayBuffer(initialBlob);\n\n return promise;\n };\n\n qq.extend = function(first, second, extendNested) {\n qq.each(second, function(prop, val) {\n if (extendNested && qq.isObject(val)) {\n if (first[prop] === undefined) {\n first[prop] = {};\n }\n qq.extend(first[prop], val, true);\n }\n else {\n first[prop] = val;\n }\n });\n\n return first;\n };\n\n /**\n * Allow properties in one object to override properties in another,\n * keeping track of the original values from the target object.\n *\n * Note that the pre-overriden properties to be overriden by the source will be passed into the `sourceFn` when it is invoked.\n *\n * @param target Update properties in this object from some source\n * @param sourceFn A function that, when invoked, will return properties that will replace properties with the same name in the target.\n * @returns {object} The target object\n */\n qq.override = function(target, sourceFn) {\n var super_ = {},\n source = sourceFn(super_);\n\n qq.each(source, function(srcPropName, srcPropVal) {\n if (target[srcPropName] !== undefined) {\n super_[srcPropName] = target[srcPropName];\n }\n\n target[srcPropName] = srcPropVal;\n });\n\n return target;\n };\n\n /**\n * Searches for a given element (elt) in the array, returns -1 if it is not present.\n */\n qq.indexOf = function(arr, elt, from) {\n if (arr.indexOf) {\n return arr.indexOf(elt, from);\n }\n\n from = from || 0;\n var len = arr.length;\n\n if (from < 0) {\n from += len;\n }\n\n for (; from < len; from += 1) {\n if (arr.hasOwnProperty(from) && arr[from] === elt) {\n return from;\n }\n }\n return -1;\n };\n\n //this is a version 4 UUID\n qq.getUniqueId = function() {\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, function(c) {\n /*jslint eqeq: true, bitwise: true*/\n var r = Math.random() * 16 | 0, v = c == \"x\" ? r : (r & 0x3 | 0x8);\n return v.toString(16);\n });\n };\n\n //\n // Browsers and platforms detection\n qq.ie = function() {\n return navigator.userAgent.indexOf(\"MSIE\") !== -1 ||\n navigator.userAgent.indexOf(\"Trident\") !== -1;\n };\n\n qq.ie7 = function() {\n return navigator.userAgent.indexOf(\"MSIE 7\") !== -1;\n };\n\n qq.ie8 = function() {\n return navigator.userAgent.indexOf(\"MSIE 8\") !== -1;\n };\n\n qq.ie10 = function() {\n return navigator.userAgent.indexOf(\"MSIE 10\") !== -1;\n };\n\n qq.ie11 = function() {\n return qq.ie() && navigator.userAgent.indexOf(\"rv:11\") !== -1;\n };\n\n qq.edge = function() {\n return navigator.userAgent.indexOf(\"Edge\") >= 0;\n };\n\n qq.safari = function() {\n return navigator.vendor !== undefined && navigator.vendor.indexOf(\"Apple\") !== -1;\n };\n\n qq.chrome = function() {\n return navigator.vendor !== undefined && navigator.vendor.indexOf(\"Google\") !== -1;\n };\n\n qq.opera = function() {\n return navigator.vendor !== undefined && navigator.vendor.indexOf(\"Opera\") !== -1;\n };\n\n qq.firefox = function() {\n return (!qq.edge() && !qq.ie11() && navigator.userAgent.indexOf(\"Mozilla\") !== -1 && navigator.vendor !== undefined && navigator.vendor === \"\");\n };\n\n qq.windows = function() {\n return navigator.platform === \"Win32\";\n };\n\n qq.android = function() {\n return navigator.userAgent.toLowerCase().indexOf(\"android\") !== -1;\n };\n\n // We need to identify the Android stock browser via the UA string to work around various bugs in this browser,\n // such as the one that prevents a `Blob` from being uploaded.\n qq.androidStock = function() {\n return qq.android() && navigator.userAgent.toLowerCase().indexOf(\"chrome\") < 0;\n };\n\n qq.ios6 = function() {\n return qq.ios() && navigator.userAgent.indexOf(\" OS 6_\") !== -1;\n };\n\n qq.ios7 = function() {\n return qq.ios() && navigator.userAgent.indexOf(\" OS 7_\") !== -1;\n };\n\n qq.ios8 = function() {\n return qq.ios() && navigator.userAgent.indexOf(\" OS 8_\") !== -1;\n };\n\n // iOS 8.0.0\n qq.ios800 = function() {\n return qq.ios() && navigator.userAgent.indexOf(\" OS 8_0 \") !== -1;\n };\n\n qq.ios = function() {\n /*jshint -W014 */\n return navigator.userAgent.indexOf(\"iPad\") !== -1\n || navigator.userAgent.indexOf(\"iPod\") !== -1\n || navigator.userAgent.indexOf(\"iPhone\") !== -1;\n };\n\n qq.iosChrome = function() {\n return qq.ios() && navigator.userAgent.indexOf(\"CriOS\") !== -1;\n };\n\n qq.iosSafari = function() {\n return qq.ios() && !qq.iosChrome() && navigator.userAgent.indexOf(\"Safari\") !== -1;\n };\n\n qq.iosSafariWebView = function() {\n return qq.ios() && !qq.iosChrome() && !qq.iosSafari();\n };\n\n //\n // Events\n\n qq.preventDefault = function(e) {\n if (e.preventDefault) {\n e.preventDefault();\n } else {\n e.returnValue = false;\n }\n };\n\n /**\n * Creates and returns element from html string\n * Uses innerHTML to create an element\n */\n qq.toElement = (function() {\n var div = document.createElement(\"div\");\n return function(html) {\n div.innerHTML = html;\n var element = div.firstChild;\n div.removeChild(element);\n return element;\n };\n }());\n\n //key and value are passed to callback for each entry in the iterable item\n qq.each = function(iterableItem, callback) {\n var keyOrIndex, retVal;\n\n if (iterableItem) {\n // Iterate through [`Storage`](http://www.w3.org/TR/webstorage/#the-storage-interface) items\n if (window.Storage && iterableItem.constructor === window.Storage) {\n for (keyOrIndex = 0; keyOrIndex < iterableItem.length; keyOrIndex++) {\n retVal = callback(iterableItem.key(keyOrIndex), iterableItem.getItem(iterableItem.key(keyOrIndex)));\n if (retVal === false) {\n break;\n }\n }\n }\n // `DataTransferItemList` & `NodeList` objects are array-like and should be treated as arrays\n // when iterating over items inside the object.\n else if (qq.isArray(iterableItem) || qq.isItemList(iterableItem) || qq.isNodeList(iterableItem)) {\n for (keyOrIndex = 0; keyOrIndex < iterableItem.length; keyOrIndex++) {\n retVal = callback(keyOrIndex, iterableItem[keyOrIndex]);\n if (retVal === false) {\n break;\n }\n }\n }\n else if (qq.isString(iterableItem)) {\n for (keyOrIndex = 0; keyOrIndex < iterableItem.length; keyOrIndex++) {\n retVal = callback(keyOrIndex, iterableItem.charAt(keyOrIndex));\n if (retVal === false) {\n break;\n }\n }\n }\n else {\n for (keyOrIndex in iterableItem) {\n if (Object.prototype.hasOwnProperty.call(iterableItem, keyOrIndex)) {\n retVal = callback(keyOrIndex, iterableItem[keyOrIndex]);\n if (retVal === false) {\n break;\n }\n }\n }\n }\n }\n };\n\n //include any args that should be passed to the new function after the context arg\n qq.bind = function(oldFunc, context) {\n if (qq.isFunction(oldFunc)) {\n var args = Array.prototype.slice.call(arguments, 2);\n\n return function() {\n var newArgs = qq.extend([], args);\n if (arguments.length) {\n newArgs = newArgs.concat(Array.prototype.slice.call(arguments));\n }\n return oldFunc.apply(context, newArgs);\n };\n }\n\n throw new Error(\"first parameter must be a function!\");\n };\n\n /**\n * obj2url() takes a json-object as argument and generates\n * a querystring. pretty much like jQuery.param()\n *\n * how to use:\n *\n * `qq.obj2url({a:'b',c:'d'},'http://any.url/upload?otherParam=value');`\n *\n * will result in:\n *\n * `http://any.url/upload?otherParam=value&a=b&c=d`\n *\n * @param Object JSON-Object\n * @param String current querystring-part\n * @return String encoded querystring\n */\n qq.obj2url = function(obj, temp, prefixDone) {\n /*jshint laxbreak: true*/\n var uristrings = [],\n prefix = \"&\",\n add = function(nextObj, i) {\n var nextTemp = temp\n ? (/\\[\\]$/.test(temp)) // prevent double-encoding\n ? temp\n : temp + \"[\" + i + \"]\"\n : i;\n if ((nextTemp !== \"undefined\") && (i !== \"undefined\")) {\n uristrings.push(\n (typeof nextObj === \"object\")\n ? qq.obj2url(nextObj, nextTemp, true)\n : (Object.prototype.toString.call(nextObj) === \"[object Function]\")\n ? encodeURIComponent(nextTemp) + \"=\" + encodeURIComponent(nextObj())\n : encodeURIComponent(nextTemp) + \"=\" + encodeURIComponent(nextObj)\n );\n }\n };\n\n if (!prefixDone && temp) {\n prefix = (/\\?/.test(temp)) ? (/\\?$/.test(temp)) ? \"\" : \"&\" : \"?\";\n uristrings.push(temp);\n uristrings.push(qq.obj2url(obj));\n } else if ((Object.prototype.toString.call(obj) === \"[object Array]\") && (typeof obj !== \"undefined\")) {\n qq.each(obj, function(idx, val) {\n add(val, idx);\n });\n } else if ((typeof obj !== \"undefined\") && (obj !== null) && (typeof obj === \"object\")) {\n qq.each(obj, function(prop, val) {\n add(val, prop);\n });\n } else {\n uristrings.push(encodeURIComponent(temp) + \"=\" + encodeURIComponent(obj));\n }\n\n if (temp) {\n return uristrings.join(prefix);\n } else {\n return uristrings.join(prefix)\n .replace(/^&/, \"\")\n .replace(/%20/g, \"+\");\n }\n };\n\n qq.obj2FormData = function(obj, formData, arrayKeyName) {\n if (!formData) {\n formData = new FormData();\n }\n\n qq.each(obj, function(key, val) {\n key = arrayKeyName ? arrayKeyName + \"[\" + key + \"]\" : key;\n\n if (qq.isObject(val)) {\n qq.obj2FormData(val, formData, key);\n }\n else if (qq.isFunction(val)) {\n formData.append(key, val());\n }\n else {\n formData.append(key, val);\n }\n });\n\n return formData;\n };\n\n qq.obj2Inputs = function(obj, form) {\n var input;\n\n if (!form) {\n form = document.createElement(\"form\");\n }\n\n qq.obj2FormData(obj, {\n append: function(key, val) {\n input = document.createElement(\"input\");\n input.setAttribute(\"name\", key);\n input.setAttribute(\"value\", val);\n form.appendChild(input);\n }\n });\n\n return form;\n };\n\n /**\n * Not recommended for use outside of Fine Uploader since this falls back to an unchecked eval if JSON.parse is not\n * implemented. For a more secure JSON.parse polyfill, use Douglas Crockford's json2.js.\n */\n qq.parseJson = function(json) {\n /*jshint evil: true*/\n if (window.JSON && qq.isFunction(JSON.parse)) {\n return JSON.parse(json);\n } else {\n return eval(\"(\" + json + \")\");\n }\n };\n\n /**\n * Retrieve the extension of a file, if it exists.\n *\n * @param filename\n * @returns {string || undefined}\n */\n qq.getExtension = function(filename) {\n var extIdx = filename.lastIndexOf(\".\") + 1;\n\n if (extIdx > 0) {\n return filename.substr(extIdx, filename.length - extIdx);\n }\n };\n\n qq.getFilename = function(blobOrFileInput) {\n /*jslint regexp: true*/\n\n if (qq.isInput(blobOrFileInput)) {\n // get input value and remove path to normalize\n return blobOrFileInput.value.replace(/.*(\\/|\\\\)/, \"\");\n }\n else if (qq.isFile(blobOrFileInput)) {\n if (blobOrFileInput.fileName !== null && blobOrFileInput.fileName !== undefined) {\n return blobOrFileInput.fileName;\n }\n }\n\n return blobOrFileInput.name;\n };\n\n /**\n * A generic module which supports object disposing in dispose() method.\n * */\n qq.DisposeSupport = function() {\n var disposers = [];\n\n return {\n /** Run all registered disposers */\n dispose: function() {\n var disposer;\n do {\n disposer = disposers.shift();\n if (disposer) {\n disposer();\n }\n }\n while (disposer);\n },\n\n /** Attach event handler and register de-attacher as a disposer */\n attach: function() {\n var args = arguments;\n /*jslint undef:true*/\n this.addDisposer(qq(args[0]).attach.apply(this, Array.prototype.slice.call(arguments, 1)));\n },\n\n /** Add disposer to the collection */\n addDisposer: function(disposeFunction) {\n disposers.push(disposeFunction);\n }\n };\n };\n}());\n","/* globals define, module, global, qq */\n(function() {\n \"use strict\";\n if (typeof define === \"function\" && define.amd) {\n define(function() {\n return qq;\n });\n }\n else if (typeof module !== \"undefined\" && module.exports) {\n module.exports = qq;\n }\n else {\n global.qq = qq;\n }\n}());\n","/* globals qq */\n/**\n * Fine Uploader top-level Error container. Inherits from `Error`.\n */\n(function() {\n \"use strict\";\n\n qq.Error = function(message) {\n this.message = \"[Fine Uploader \" + qq.version + \"] \" + message;\n };\n\n qq.Error.prototype = new Error();\n}());\n","/*global qq */\nqq.version = \"5.16.2\";\n","/* globals qq */\nqq.supportedFeatures = (function() {\n \"use strict\";\n\n var supportsUploading,\n supportsUploadingBlobs,\n supportsFileDrop,\n supportsAjaxFileUploading,\n supportsFolderDrop,\n supportsChunking,\n supportsResume,\n supportsUploadViaPaste,\n supportsUploadCors,\n supportsDeleteFileXdr,\n supportsDeleteFileCorsXhr,\n supportsDeleteFileCors,\n supportsFolderSelection,\n supportsImagePreviews,\n supportsUploadProgress;\n\n function testSupportsFileInputElement() {\n var supported = true,\n tempInput;\n\n try {\n tempInput = document.createElement(\"input\");\n tempInput.type = \"file\";\n qq(tempInput).hide();\n\n if (tempInput.disabled) {\n supported = false;\n }\n }\n catch (ex) {\n supported = false;\n }\n\n return supported;\n }\n\n //only way to test for complete Clipboard API support at this time\n function isChrome14OrHigher() {\n return (qq.chrome() || qq.opera()) &&\n navigator.userAgent.match(/Chrome\\/[1][4-9]|Chrome\\/[2-9][0-9]/) !== undefined;\n }\n\n //Ensure we can send cross-origin `XMLHttpRequest`s\n function isCrossOriginXhrSupported() {\n if (window.XMLHttpRequest) {\n var xhr = qq.createXhrInstance();\n\n //Commonly accepted test for XHR CORS support.\n return xhr.withCredentials !== undefined;\n }\n\n return false;\n }\n\n //Test for (terrible) cross-origin ajax transport fallback for IE9 and IE8\n function isXdrSupported() {\n return window.XDomainRequest !== undefined;\n }\n\n // CORS Ajax requests are supported if it is either possible to send credentialed `XMLHttpRequest`s,\n // or if `XDomainRequest` is an available alternative.\n function isCrossOriginAjaxSupported() {\n if (isCrossOriginXhrSupported()) {\n return true;\n }\n\n return isXdrSupported();\n }\n\n function isFolderSelectionSupported() {\n // We know that folder selection is only supported in Chrome via this proprietary attribute for now\n return document.createElement(\"input\").webkitdirectory !== undefined;\n }\n\n function isLocalStorageSupported() {\n try {\n return !!window.localStorage &&\n // unpatched versions of IE10/11 have buggy impls of localStorage where setItem is a string\n qq.isFunction(window.localStorage.setItem);\n }\n catch (error) {\n // probably caught a security exception, so no localStorage for you\n return false;\n }\n }\n\n function isDragAndDropSupported() {\n var span = document.createElement(\"span\");\n\n return (\"draggable\" in span || (\"ondragstart\" in span && \"ondrop\" in span)) &&\n !qq.android() && !qq.ios();\n }\n\n supportsUploading = testSupportsFileInputElement();\n\n supportsAjaxFileUploading = supportsUploading && qq.isXhrUploadSupported();\n\n supportsUploadingBlobs = supportsAjaxFileUploading && !qq.androidStock();\n\n supportsFileDrop = supportsAjaxFileUploading && isDragAndDropSupported();\n\n // adapted from https://stackoverflow.com/a/23278460/486979\n supportsFolderDrop = supportsFileDrop && (function() {\n var input = document.createElement(\"input\");\n\n input.type = \"file\";\n return !!(\"webkitdirectory\" in (input || document.querySelectorAll(\"input[type=file]\")[0]));\n }());\n\n supportsChunking = supportsAjaxFileUploading && qq.isFileChunkingSupported();\n\n supportsResume = supportsAjaxFileUploading && supportsChunking && isLocalStorageSupported();\n\n supportsUploadViaPaste = supportsAjaxFileUploading && isChrome14OrHigher();\n\n supportsUploadCors = supportsUploading && (window.postMessage !== undefined || supportsAjaxFileUploading);\n\n supportsDeleteFileCorsXhr = isCrossOriginXhrSupported();\n\n supportsDeleteFileXdr = isXdrSupported();\n\n supportsDeleteFileCors = isCrossOriginAjaxSupported();\n\n supportsFolderSelection = isFolderSelectionSupported();\n\n supportsImagePreviews = supportsAjaxFileUploading && window.FileReader !== undefined;\n\n supportsUploadProgress = (function() {\n if (supportsAjaxFileUploading) {\n return !qq.androidStock() && !qq.iosChrome();\n }\n return false;\n }());\n\n return {\n ajaxUploading: supportsAjaxFileUploading,\n blobUploading: supportsUploadingBlobs,\n canDetermineSize: supportsAjaxFileUploading,\n chunking: supportsChunking,\n deleteFileCors: supportsDeleteFileCors,\n deleteFileCorsXdr: supportsDeleteFileXdr, //NOTE: will also return true in IE10, where XDR is also supported\n deleteFileCorsXhr: supportsDeleteFileCorsXhr,\n dialogElement: !!window.HTMLDialogElement,\n fileDrop: supportsFileDrop,\n folderDrop: supportsFolderDrop,\n folderSelection: supportsFolderSelection,\n imagePreviews: supportsImagePreviews,\n imageValidation: supportsImagePreviews,\n itemSizeValidation: supportsAjaxFileUploading,\n pause: supportsChunking,\n progressBar: supportsUploadProgress,\n resume: supportsResume,\n scaling: supportsImagePreviews && supportsUploadingBlobs,\n tiffPreviews: qq.safari(), // Not the best solution, but simple and probably accurate enough (for now)\n unlimitedScaledImageSize: !qq.ios(), // false simply indicates that there is some known limit\n uploading: supportsUploading,\n uploadCors: supportsUploadCors,\n uploadCustomHeaders: supportsAjaxFileUploading,\n uploadNonMultipart: supportsAjaxFileUploading,\n uploadViaPaste: supportsUploadViaPaste\n };\n\n}());\n","/*globals qq*/\n\n// Is the passed object a promise instance?\nqq.isGenericPromise = function(maybePromise) {\n \"use strict\";\n return !!(maybePromise && maybePromise.then && qq.isFunction(maybePromise.then));\n};\n\nqq.Promise = function() {\n \"use strict\";\n\n var successArgs, failureArgs,\n successCallbacks = [],\n failureCallbacks = [],\n doneCallbacks = [],\n state = 0;\n\n qq.extend(this, {\n then: function(onSuccess, onFailure) {\n if (state === 0) {\n if (onSuccess) {\n successCallbacks.push(onSuccess);\n }\n if (onFailure) {\n failureCallbacks.push(onFailure);\n }\n }\n else if (state === -1) {\n onFailure && onFailure.apply(null, failureArgs);\n }\n else if (onSuccess) {\n onSuccess.apply(null, successArgs);\n }\n\n return this;\n },\n\n done: function(callback) {\n if (state === 0) {\n doneCallbacks.push(callback);\n }\n else {\n callback.apply(null, failureArgs === undefined ? successArgs : failureArgs);\n }\n\n return this;\n },\n\n success: function() {\n state = 1;\n successArgs = arguments;\n\n if (successCallbacks.length) {\n qq.each(successCallbacks, function(idx, callback) {\n callback.apply(null, successArgs);\n });\n }\n\n if (doneCallbacks.length) {\n qq.each(doneCallbacks, function(idx, callback) {\n callback.apply(null, successArgs);\n });\n }\n\n return this;\n },\n\n failure: function() {\n state = -1;\n failureArgs = arguments;\n\n if (failureCallbacks.length) {\n qq.each(failureCallbacks, function(idx, callback) {\n callback.apply(null, failureArgs);\n });\n }\n\n if (doneCallbacks.length) {\n qq.each(doneCallbacks, function(idx, callback) {\n callback.apply(null, failureArgs);\n });\n }\n\n return this;\n }\n });\n};\n","/* globals qq */\n/**\n * Placeholder for a Blob that will be generated on-demand.\n *\n * @param referenceBlob Parent of the generated blob\n * @param onCreate Function to invoke when the blob must be created. Must be promissory.\n * @constructor\n */\nqq.BlobProxy = function(referenceBlob, onCreate) {\n \"use strict\";\n\n qq.extend(this, {\n referenceBlob: referenceBlob,\n\n create: function() {\n return onCreate(referenceBlob);\n }\n });\n};\n","/*globals qq*/\n\n/**\n * This module represents an upload or \"Select File(s)\" button. It's job is to embed an opaque ` `\n * element as a child of a provided \"container\" element. This \"container\" element (`options.element`) is used to provide\n * a custom style for the ` ` element. The ability to change the style of the container element is also\n * provided here by adding CSS classes to the container on hover/focus.\n *\n * TODO Eliminate the mouseover and mouseout event handlers since the :hover CSS pseudo-class should now be\n * available on all supported browsers.\n *\n * @param o Options to override the default values\n */\nqq.UploadButton = function(o) {\n \"use strict\";\n\n var self = this,\n\n disposeSupport = new qq.DisposeSupport(),\n\n options = {\n // Corresponds to the `accept` attribute on the associated ` `\n acceptFiles: null,\n\n // \"Container\" element\n element: null,\n\n focusClass: \"qq-upload-button-focus\",\n\n // A true value allows folders to be selected, if supported by the UA\n folders: false,\n\n // **This option will be removed** in the future as the :hover CSS pseudo-class is available on all supported browsers\n hoverClass: \"qq-upload-button-hover\",\n\n ios8BrowserCrashWorkaround: false,\n\n // If true adds `multiple` attribute to ` `\n multiple: false,\n\n // `name` attribute of ` `\n name: \"qqfile\",\n\n // Called when the browser invokes the onchange handler on the ` `\n onChange: function(input) {},\n\n title: null\n },\n input, buttonId;\n\n // Overrides any of the default option values with any option values passed in during construction.\n qq.extend(options, o);\n\n buttonId = qq.getUniqueId();\n\n // Embed an opaque ` ` element as a child of `options.element`.\n function createInput() {\n var input = document.createElement(\"input\");\n\n input.setAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME, buttonId);\n input.setAttribute(\"title\", options.title);\n\n self.setMultiple(options.multiple, input);\n\n if (options.folders && qq.supportedFeatures.folderSelection) {\n // selecting directories is only possible in Chrome now, via a vendor-specific prefixed attribute\n input.setAttribute(\"webkitdirectory\", \"\");\n }\n\n if (options.acceptFiles) {\n input.setAttribute(\"accept\", options.acceptFiles);\n }\n\n input.setAttribute(\"type\", \"file\");\n input.setAttribute(\"name\", options.name);\n\n qq(input).css({\n position: \"absolute\",\n // in Opera only 'browse' button\n // is clickable and it is located at\n // the right side of the input\n right: 0,\n top: 0,\n fontFamily: \"Arial\",\n // It's especially important to make this an arbitrarily large value\n // to ensure the rendered input button in IE takes up the entire\n // space of the container element. Otherwise, the left side of the\n // button will require a double-click to invoke the file chooser.\n // In other browsers, this might cause other issues, so a large font-size\n // is only used in IE. There is a bug in IE8 where the opacity style is ignored\n // in some cases when the font-size is large. So, this workaround is not applied\n // to IE8.\n fontSize: qq.ie() && !qq.ie8() ? \"3500px\" : \"118px\",\n margin: 0,\n padding: 0,\n cursor: \"pointer\",\n opacity: 0\n });\n\n // Setting the file input's height to 100% in IE7 causes\n // most of the visible button to be unclickable.\n !qq.ie7() && qq(input).css({height: \"100%\"});\n\n options.element.appendChild(input);\n\n disposeSupport.attach(input, \"change\", function() {\n options.onChange(input);\n });\n\n // **These event handlers will be removed** in the future as the :hover CSS pseudo-class is available on all supported browsers\n disposeSupport.attach(input, \"mouseover\", function() {\n qq(options.element).addClass(options.hoverClass);\n });\n disposeSupport.attach(input, \"mouseout\", function() {\n qq(options.element).removeClass(options.hoverClass);\n });\n\n disposeSupport.attach(input, \"focus\", function() {\n qq(options.element).addClass(options.focusClass);\n });\n disposeSupport.attach(input, \"blur\", function() {\n qq(options.element).removeClass(options.focusClass);\n });\n\n return input;\n }\n\n // Make button suitable container for input\n qq(options.element).css({\n position: \"relative\",\n overflow: \"hidden\",\n // Make sure browse button is in the right side in Internet Explorer\n direction: \"ltr\"\n });\n\n // Exposed API\n qq.extend(this, {\n getInput: function() {\n return input;\n },\n\n getButtonId: function() {\n return buttonId;\n },\n\n setMultiple: function(isMultiple, optInput) {\n var input = optInput || this.getInput();\n\n // Temporary workaround for bug in in iOS8 UIWebView that causes the browser to crash\n // before the file chooser appears if the file input doesn't contain a multiple attribute.\n // See #1283.\n if (options.ios8BrowserCrashWorkaround && qq.ios8() && (qq.iosChrome() || qq.iosSafariWebView())) {\n input.setAttribute(\"multiple\", \"\");\n }\n\n else {\n if (isMultiple) {\n input.setAttribute(\"multiple\", \"\");\n }\n else {\n input.removeAttribute(\"multiple\");\n }\n }\n },\n\n setAcceptFiles: function(acceptFiles) {\n if (acceptFiles !== options.acceptFiles) {\n input.setAttribute(\"accept\", acceptFiles);\n }\n },\n\n reset: function() {\n if (input.parentNode) {\n qq(input).remove();\n }\n\n qq(options.element).removeClass(options.focusClass);\n input = null;\n input = createInput();\n }\n });\n\n input = createInput();\n};\n\nqq.UploadButton.BUTTON_ID_ATTR_NAME = \"qq-button-id\";\n","/*globals qq */\nqq.UploadData = function(uploaderProxy) {\n \"use strict\";\n\n var data = [],\n byUuid = {},\n byStatus = {},\n byProxyGroupId = {},\n byBatchId = {};\n\n function getDataByIds(idOrIds) {\n if (qq.isArray(idOrIds)) {\n var entries = [];\n\n qq.each(idOrIds, function(idx, id) {\n entries.push(data[id]);\n });\n\n return entries;\n }\n\n return data[idOrIds];\n }\n\n function getDataByUuids(uuids) {\n if (qq.isArray(uuids)) {\n var entries = [];\n\n qq.each(uuids, function(idx, uuid) {\n entries.push(data[byUuid[uuid]]);\n });\n\n return entries;\n }\n\n return data[byUuid[uuids]];\n }\n\n function getDataByStatus(status) {\n var statusResults = [],\n statuses = [].concat(status);\n\n qq.each(statuses, function(index, statusEnum) {\n var statusResultIndexes = byStatus[statusEnum];\n\n if (statusResultIndexes !== undefined) {\n qq.each(statusResultIndexes, function(i, dataIndex) {\n statusResults.push(data[dataIndex]);\n });\n }\n });\n\n return statusResults;\n }\n\n qq.extend(this, {\n /**\n * Adds a new file to the data cache for tracking purposes.\n *\n * @param spec Data that describes this file. Possible properties are:\n *\n * - uuid: Initial UUID for this file.\n * - name: Initial name of this file.\n * - size: Size of this file, omit if this cannot be determined\n * - status: Initial `qq.status` for this file. Omit for `qq.status.SUBMITTING`.\n * - batchId: ID of the batch this file belongs to\n * - proxyGroupId: ID of the proxy group associated with this file\n * - onBeforeStatusChange(fileId): callback that is executed before the status change is broadcast\n *\n * @returns {number} Internal ID for this file.\n */\n addFile: function(spec) {\n var status = spec.status || qq.status.SUBMITTING,\n id = data.push({\n name: spec.name,\n originalName: spec.name,\n uuid: spec.uuid,\n size: spec.size == null ? -1 : spec.size,\n status: status,\n file: spec.file\n }) - 1;\n\n if (spec.batchId) {\n data[id].batchId = spec.batchId;\n\n if (byBatchId[spec.batchId] === undefined) {\n byBatchId[spec.batchId] = [];\n }\n byBatchId[spec.batchId].push(id);\n }\n\n if (spec.proxyGroupId) {\n data[id].proxyGroupId = spec.proxyGroupId;\n\n if (byProxyGroupId[spec.proxyGroupId] === undefined) {\n byProxyGroupId[spec.proxyGroupId] = [];\n }\n byProxyGroupId[spec.proxyGroupId].push(id);\n }\n\n data[id].id = id;\n byUuid[spec.uuid] = id;\n\n if (byStatus[status] === undefined) {\n byStatus[status] = [];\n }\n byStatus[status].push(id);\n\n spec.onBeforeStatusChange && spec.onBeforeStatusChange(id);\n uploaderProxy.onStatusChange(id, null, status);\n\n return id;\n },\n\n retrieve: function(optionalFilter) {\n if (qq.isObject(optionalFilter) && data.length) {\n if (optionalFilter.id !== undefined) {\n return getDataByIds(optionalFilter.id);\n }\n\n else if (optionalFilter.uuid !== undefined) {\n return getDataByUuids(optionalFilter.uuid);\n }\n\n else if (optionalFilter.status) {\n return getDataByStatus(optionalFilter.status);\n }\n }\n else {\n return qq.extend([], data, true);\n }\n },\n\n removeFileRef: function(id) {\n var record = getDataByIds(id);\n\n if (record) {\n delete record.file;\n }\n },\n\n reset: function() {\n data = [];\n byUuid = {};\n byStatus = {};\n byBatchId = {};\n },\n\n setStatus: function(id, newStatus) {\n var oldStatus = data[id].status,\n byStatusOldStatusIndex = qq.indexOf(byStatus[oldStatus], id);\n\n byStatus[oldStatus].splice(byStatusOldStatusIndex, 1);\n\n data[id].status = newStatus;\n\n if (byStatus[newStatus] === undefined) {\n byStatus[newStatus] = [];\n }\n byStatus[newStatus].push(id);\n\n uploaderProxy.onStatusChange(id, oldStatus, newStatus);\n },\n\n uuidChanged: function(id, newUuid) {\n var oldUuid = data[id].uuid;\n\n data[id].uuid = newUuid;\n byUuid[newUuid] = id;\n delete byUuid[oldUuid];\n },\n\n updateName: function(id, newName) {\n data[id].name = newName;\n },\n\n updateSize: function(id, newSize) {\n data[id].size = newSize;\n },\n\n // Only applicable if this file has a parent that we may want to reference later.\n setParentId: function(targetId, parentId) {\n data[targetId].parentId = parentId;\n },\n\n getIdsInProxyGroup: function(id) {\n var proxyGroupId = data[id].proxyGroupId;\n\n if (proxyGroupId) {\n return byProxyGroupId[proxyGroupId];\n }\n return [];\n },\n\n getIdsInBatch: function(id) {\n var batchId = data[id].batchId;\n\n return byBatchId[batchId];\n }\n });\n};\n\nqq.status = {\n SUBMITTING: \"submitting\",\n SUBMITTED: \"submitted\",\n REJECTED: \"rejected\",\n QUEUED: \"queued\",\n CANCELED: \"canceled\",\n PAUSED: \"paused\",\n UPLOADING: \"uploading\",\n UPLOAD_FINALIZING: \"upload finalizing\",\n UPLOAD_RETRYING: \"retrying upload\",\n UPLOAD_SUCCESSFUL: \"upload successful\",\n UPLOAD_FAILED: \"upload failed\",\n DELETE_FAILED: \"delete failed\",\n DELETING: \"deleting\",\n DELETED: \"deleted\"\n};\n","/*globals qq*/\n/**\n * Defines the public API for FineUploaderBasic mode.\n */\n(function() {\n \"use strict\";\n\n qq.basePublicApi = {\n // DEPRECATED - TODO REMOVE IN NEXT MAJOR RELEASE (replaced by addFiles)\n addBlobs: function(blobDataOrArray, params, endpoint) {\n this.addFiles(blobDataOrArray, params, endpoint);\n },\n\n addInitialFiles: function(cannedFileList) {\n var self = this;\n\n qq.each(cannedFileList, function(index, cannedFile) {\n self._addCannedFile(cannedFile);\n });\n },\n\n addFiles: function(data, params, endpoint) {\n this._maybeHandleIos8SafariWorkaround();\n\n var batchId = this._storedIds.length === 0 ? qq.getUniqueId() : this._currentBatchId,\n\n processBlob = qq.bind(function(blob) {\n this._handleNewFile({\n blob: blob,\n name: this._options.blobs.defaultName\n }, batchId, verifiedFiles);\n }, this),\n\n processBlobData = qq.bind(function(blobData) {\n this._handleNewFile(blobData, batchId, verifiedFiles);\n }, this),\n\n processCanvas = qq.bind(function(canvas) {\n var blob = qq.canvasToBlob(canvas);\n\n this._handleNewFile({\n blob: blob,\n name: this._options.blobs.defaultName + \".png\"\n }, batchId, verifiedFiles);\n }, this),\n\n processCanvasData = qq.bind(function(canvasData) {\n var normalizedQuality = canvasData.quality && canvasData.quality / 100,\n blob = qq.canvasToBlob(canvasData.canvas, canvasData.type, normalizedQuality);\n\n this._handleNewFile({\n blob: blob,\n name: canvasData.name\n }, batchId, verifiedFiles);\n }, this),\n\n processFileOrInput = qq.bind(function(fileOrInput) {\n if (qq.isInput(fileOrInput) && qq.supportedFeatures.ajaxUploading) {\n var files = Array.prototype.slice.call(fileOrInput.files),\n self = this;\n\n qq.each(files, function(idx, file) {\n self._handleNewFile(file, batchId, verifiedFiles);\n });\n }\n else {\n this._handleNewFile(fileOrInput, batchId, verifiedFiles);\n }\n }, this),\n\n normalizeData = function() {\n if (qq.isFileList(data)) {\n data = Array.prototype.slice.call(data);\n }\n data = [].concat(data);\n },\n\n self = this,\n verifiedFiles = [];\n\n this._currentBatchId = batchId;\n\n if (data) {\n normalizeData();\n\n qq.each(data, function(idx, fileContainer) {\n if (qq.isFileOrInput(fileContainer)) {\n processFileOrInput(fileContainer);\n }\n else if (qq.isBlob(fileContainer)) {\n processBlob(fileContainer);\n }\n else if (qq.isObject(fileContainer)) {\n if (fileContainer.blob && fileContainer.name) {\n processBlobData(fileContainer);\n }\n else if (fileContainer.canvas && fileContainer.name) {\n processCanvasData(fileContainer);\n }\n }\n else if (fileContainer.tagName && fileContainer.tagName.toLowerCase() === \"canvas\") {\n processCanvas(fileContainer);\n }\n else {\n self.log(fileContainer + \" is not a valid file container! Ignoring!\", \"warn\");\n }\n });\n\n this.log(\"Received \" + verifiedFiles.length + \" files.\");\n this._prepareItemsForUpload(verifiedFiles, params, endpoint);\n }\n },\n\n cancel: function(id) {\n var uploadData = this._uploadData.retrieve({id: id});\n\n if (uploadData && uploadData.status === qq.status.UPLOAD_FINALIZING) {\n this.log(qq.format(\"Ignoring cancel for file ID {} ({}). Finalizing upload.\", id, this.getName(id)), \"error\");\n }\n else {\n this._handler.cancel(id);\n }\n },\n\n cancelAll: function() {\n var storedIdsCopy = [],\n self = this;\n\n qq.extend(storedIdsCopy, this._storedIds);\n qq.each(storedIdsCopy, function(idx, storedFileId) {\n self.cancel(storedFileId);\n });\n\n this._handler.cancelAll();\n },\n\n clearStoredFiles: function() {\n this._storedIds = [];\n },\n\n continueUpload: function(id) {\n var uploadData = this._uploadData.retrieve({id: id});\n\n if (!qq.supportedFeatures.pause || !this._options.chunking.enabled) {\n return false;\n }\n\n if (uploadData.status === qq.status.PAUSED) {\n this.log(qq.format(\"Paused file ID {} ({}) will be continued. Not paused.\", id, this.getName(id)));\n this._uploadFile(id);\n return true;\n }\n else {\n this.log(qq.format(\"Ignoring continue for file ID {} ({}). Not paused.\", id, this.getName(id)), \"error\");\n }\n\n return false;\n },\n\n deleteFile: function(id) {\n return this._onSubmitDelete(id);\n },\n\n // TODO document?\n doesExist: function(fileOrBlobId) {\n return this._handler.isValid(fileOrBlobId);\n },\n\n // Generate a variable size thumbnail on an img or canvas,\n // returning a promise that is fulfilled when the attempt completes.\n // Thumbnail can either be based off of a URL for an image returned\n // by the server in the upload response, or the associated `Blob`.\n drawThumbnail: function(fileId, imgOrCanvas, maxSize, fromServer, customResizeFunction) {\n var promiseToReturn = new qq.Promise(),\n fileOrUrl, options;\n\n if (this._imageGenerator) {\n fileOrUrl = this._thumbnailUrls[fileId];\n options = {\n customResizeFunction: customResizeFunction,\n maxSize: maxSize > 0 ? maxSize : null,\n scale: maxSize > 0\n };\n\n // If client-side preview generation is possible\n // and we are not specifically looking for the image URl returned by the server...\n if (!fromServer && qq.supportedFeatures.imagePreviews) {\n fileOrUrl = this.getFile(fileId);\n }\n\n /* jshint eqeqeq:false,eqnull:true */\n if (fileOrUrl == null) {\n promiseToReturn.failure({container: imgOrCanvas, error: \"File or URL not found.\"});\n }\n else {\n this._imageGenerator.generate(fileOrUrl, imgOrCanvas, options).then(\n function success(modifiedContainer) {\n promiseToReturn.success(modifiedContainer);\n },\n\n function failure(container, reason) {\n promiseToReturn.failure({container: container, error: reason || \"Problem generating thumbnail\"});\n }\n );\n }\n }\n else {\n promiseToReturn.failure({container: imgOrCanvas, error: \"Missing image generator module\"});\n }\n\n return promiseToReturn;\n },\n\n getButton: function(fileId) {\n return this._getButton(this._buttonIdsForFileIds[fileId]);\n },\n\n getEndpoint: function(fileId) {\n return this._endpointStore.get(fileId);\n },\n\n getFile: function(fileOrBlobId) {\n var file = this._handler.getFile(fileOrBlobId);\n var uploadDataRecord;\n\n if (!file) {\n uploadDataRecord = this._uploadData.retrieve({id: fileOrBlobId});\n\n if (uploadDataRecord) {\n file = uploadDataRecord.file;\n }\n }\n\n return file || null;\n },\n\n getInProgress: function() {\n return this._uploadData.retrieve({\n status: [\n qq.status.UPLOADING,\n qq.status.UPLOAD_RETRYING,\n qq.status.QUEUED\n ]\n }).length;\n },\n\n getName: function(id) {\n return this._uploadData.retrieve({id: id}).name;\n },\n\n // Parent ID for a specific file, or null if this is the parent, or if it has no parent.\n getParentId: function(id) {\n var uploadDataEntry = this.getUploads({id: id}),\n parentId = null;\n\n if (uploadDataEntry) {\n if (uploadDataEntry.parentId !== undefined) {\n parentId = uploadDataEntry.parentId;\n }\n }\n\n return parentId;\n },\n\n getResumableFilesData: function() {\n return this._handler.getResumableFilesData();\n },\n\n getSize: function(id) {\n return this._uploadData.retrieve({id: id}).size;\n },\n\n getNetUploads: function() {\n return this._netUploaded;\n },\n\n getRemainingAllowedItems: function() {\n var allowedItems = this._currentItemLimit;\n\n if (allowedItems > 0) {\n return allowedItems - this._netUploadedOrQueued;\n }\n\n return null;\n },\n\n getUploads: function(optionalFilter) {\n return this._uploadData.retrieve(optionalFilter);\n },\n\n getUuid: function(id) {\n return this._uploadData.retrieve({id: id}).uuid;\n },\n\n isResumable: function(id) {\n return this._handler.hasResumeRecord(id);\n },\n\n log: function(str, level) {\n if (this._options.debug && (!level || level === \"info\")) {\n qq.log(\"[Fine Uploader \" + qq.version + \"] \" + str);\n }\n else if (level && level !== \"info\") {\n qq.log(\"[Fine Uploader \" + qq.version + \"] \" + str, level);\n\n }\n },\n\n pauseUpload: function(id) {\n var uploadData = this._uploadData.retrieve({id: id});\n\n if (!qq.supportedFeatures.pause || !this._options.chunking.enabled) {\n return false;\n }\n\n // Pause only really makes sense if the file is uploading or retrying\n if (qq.indexOf([qq.status.UPLOADING, qq.status.UPLOAD_RETRYING], uploadData.status) >= 0) {\n if (this._handler.pause(id)) {\n this._uploadData.setStatus(id, qq.status.PAUSED);\n return true;\n }\n else {\n this.log(qq.format(\"Unable to pause file ID {} ({}).\", id, this.getName(id)), \"error\");\n }\n }\n else {\n this.log(qq.format(\"Ignoring pause for file ID {} ({}). Not in progress.\", id, this.getName(id)), \"error\");\n }\n\n return false;\n },\n\n removeFileRef: function(id) {\n this._handler.expunge(id);\n this._uploadData.removeFileRef(id);\n },\n\n reset: function() {\n this.log(\"Resetting uploader...\");\n\n this._handler.reset();\n this._storedIds = [];\n this._autoRetries = [];\n this._retryTimeouts = [];\n this._preventRetries = [];\n this._thumbnailUrls = [];\n\n qq.each(this._buttons, function(idx, button) {\n button.reset();\n });\n\n this._paramsStore.reset();\n this._endpointStore.reset();\n this._netUploadedOrQueued = 0;\n this._netUploaded = 0;\n this._uploadData.reset();\n this._buttonIdsForFileIds = [];\n\n this._pasteHandler && this._pasteHandler.reset();\n this._options.session.refreshOnReset && this._refreshSessionData();\n\n this._succeededSinceLastAllComplete = [];\n this._failedSinceLastAllComplete = [];\n\n this._totalProgress && this._totalProgress.reset();\n\n this._customResumeDataStore.reset();\n },\n\n retry: function(id) {\n return this._manualRetry(id);\n },\n\n scaleImage: function(id, specs) {\n var self = this;\n\n return qq.Scaler.prototype.scaleImage(id, specs, {\n log: qq.bind(self.log, self),\n getFile: qq.bind(self.getFile, self),\n uploadData: self._uploadData\n });\n },\n\n setCustomHeaders: function(headers, id) {\n this._customHeadersStore.set(headers, id);\n },\n\n setCustomResumeData: function(id, data) {\n this._customResumeDataStore.set(data, id);\n },\n\n setDeleteFileCustomHeaders: function(headers, id) {\n this._deleteFileCustomHeadersStore.set(headers, id);\n },\n\n setDeleteFileEndpoint: function(endpoint, id) {\n this._deleteFileEndpointStore.set(endpoint, id);\n },\n\n setDeleteFileParams: function(params, id) {\n this._deleteFileParamsStore.set(params, id);\n },\n\n // Re-sets the default endpoint, an endpoint for a specific file, or an endpoint for a specific button\n setEndpoint: function(endpoint, id) {\n this._endpointStore.set(endpoint, id);\n },\n\n setForm: function(elementOrId) {\n this._updateFormSupportAndParams(elementOrId);\n },\n\n setItemLimit: function(newItemLimit) {\n this._currentItemLimit = newItemLimit;\n },\n\n setName: function(id, newName) {\n this._uploadData.updateName(id, newName);\n },\n\n setParams: function(params, id) {\n this._paramsStore.set(params, id);\n },\n\n setUuid: function(id, newUuid) {\n return this._uploadData.uuidChanged(id, newUuid);\n },\n\n /**\n * Expose the internal status of a file id to the public api for manual state changes\n * @public\n *\n * @param {Number} id,\n * @param {String} newStatus\n *\n * @todo Implement the remaining methods\n */\n setStatus: function(id, newStatus) {\n var fileRecord = this.getUploads({id: id});\n if (!fileRecord) {\n throw new qq.Error(id + \" is not a valid file ID.\");\n }\n\n switch (newStatus) {\n case qq.status.DELETED:\n this._onDeleteComplete(id, null, false);\n break;\n case qq.status.DELETE_FAILED:\n this._onDeleteComplete(id, null, true);\n break;\n default:\n var errorMessage = \"Method setStatus called on '\" + name + \"' not implemented yet for \" + newStatus;\n this.log(errorMessage);\n throw new qq.Error(errorMessage);\n }\n },\n\n uploadStoredFiles: function() {\n if (this._storedIds.length === 0) {\n this._itemError(\"noFilesError\");\n }\n else {\n this._uploadStoredFiles();\n }\n }\n };\n\n /**\n * Defines the private (internal) API for FineUploaderBasic mode.\n */\n qq.basePrivateApi = {\n // Updates internal state with a file record (not backed by a live file). Returns the assigned ID.\n _addCannedFile: function(sessionData) {\n var self = this;\n\n return this._uploadData.addFile({\n uuid: sessionData.uuid,\n name: sessionData.name,\n size: sessionData.size,\n status: qq.status.UPLOAD_SUCCESSFUL,\n onBeforeStatusChange: function(id) {\n sessionData.deleteFileEndpoint && self.setDeleteFileEndpoint(sessionData.deleteFileEndpoint, id);\n sessionData.deleteFileParams && self.setDeleteFileParams(sessionData.deleteFileParams, id);\n\n if (sessionData.thumbnailUrl) {\n self._thumbnailUrls[id] = sessionData.thumbnailUrl;\n }\n\n self._netUploaded++;\n self._netUploadedOrQueued++;\n }\n });\n },\n\n _annotateWithButtonId: function(file, associatedInput) {\n if (qq.isFile(file)) {\n file.qqButtonId = this._getButtonId(associatedInput);\n }\n },\n\n _batchError: function(message) {\n this._options.callbacks.onError(null, null, message, undefined);\n },\n\n _createDeleteHandler: function() {\n var self = this;\n\n return new qq.DeleteFileAjaxRequester({\n method: this._options.deleteFile.method.toUpperCase(),\n maxConnections: this._options.maxConnections,\n uuidParamName: this._options.request.uuidName,\n customHeaders: this._deleteFileCustomHeadersStore,\n paramsStore: this._deleteFileParamsStore,\n endpointStore: this._deleteFileEndpointStore,\n cors: this._options.cors,\n log: qq.bind(self.log, self),\n onDelete: function(id) {\n self._onDelete(id);\n self._options.callbacks.onDelete(id);\n },\n onDeleteComplete: function(id, xhrOrXdr, isError) {\n self._onDeleteComplete(id, xhrOrXdr, isError);\n self._options.callbacks.onDeleteComplete(id, xhrOrXdr, isError);\n }\n\n });\n },\n\n _createPasteHandler: function() {\n var self = this;\n\n return new qq.PasteSupport({\n targetElement: this._options.paste.targetElement,\n callbacks: {\n log: qq.bind(self.log, self),\n pasteReceived: function(blob) {\n self._handleCheckedCallback({\n name: \"onPasteReceived\",\n callback: qq.bind(self._options.callbacks.onPasteReceived, self, blob),\n onSuccess: qq.bind(self._handlePasteSuccess, self, blob),\n identifier: \"pasted image\"\n });\n }\n }\n });\n },\n\n _createStore: function(initialValue, _readOnlyValues_) {\n var store = {},\n catchall = initialValue,\n perIdReadOnlyValues = {},\n readOnlyValues = _readOnlyValues_,\n copy = function(orig) {\n if (qq.isObject(orig)) {\n return qq.extend({}, orig);\n }\n return orig;\n },\n getReadOnlyValues = function() {\n if (qq.isFunction(readOnlyValues)) {\n return readOnlyValues();\n }\n return readOnlyValues;\n },\n includeReadOnlyValues = function(id, existing) {\n if (readOnlyValues && qq.isObject(existing)) {\n qq.extend(existing, getReadOnlyValues());\n }\n\n if (perIdReadOnlyValues[id]) {\n qq.extend(existing, perIdReadOnlyValues[id]);\n }\n };\n\n return {\n set: function(val, id) {\n /*jshint eqeqeq: true, eqnull: true*/\n if (id == null) {\n store = {};\n catchall = copy(val);\n }\n else {\n store[id] = copy(val);\n }\n },\n\n get: function(id) {\n var values;\n\n /*jshint eqeqeq: true, eqnull: true*/\n if (id != null && store[id]) {\n values = store[id];\n }\n else {\n values = copy(catchall);\n }\n\n includeReadOnlyValues(id, values);\n\n return copy(values);\n },\n\n addReadOnly: function(id, values) {\n // Only applicable to Object stores\n if (qq.isObject(store)) {\n // If null ID, apply readonly values to all files\n if (id === null) {\n if (qq.isFunction(values)) {\n readOnlyValues = values;\n }\n else {\n readOnlyValues = readOnlyValues || {};\n qq.extend(readOnlyValues, values);\n }\n }\n else {\n perIdReadOnlyValues[id] = perIdReadOnlyValues[id] || {};\n qq.extend(perIdReadOnlyValues[id], values);\n }\n }\n },\n\n remove: function(fileId) {\n return delete store[fileId];\n },\n\n reset: function() {\n store = {};\n perIdReadOnlyValues = {};\n catchall = initialValue;\n }\n };\n },\n\n _createUploadDataTracker: function() {\n var self = this;\n\n return new qq.UploadData({\n getName: function(id) {\n return self.getName(id);\n },\n getUuid: function(id) {\n return self.getUuid(id);\n },\n getSize: function(id) {\n return self.getSize(id);\n },\n onStatusChange: function(id, oldStatus, newStatus) {\n self._onUploadStatusChange(id, oldStatus, newStatus);\n self._options.callbacks.onStatusChange(id, oldStatus, newStatus);\n self._maybeAllComplete(id, newStatus);\n\n if (self._totalProgress) {\n setTimeout(function() {\n self._totalProgress.onStatusChange(id, oldStatus, newStatus);\n }, 0);\n }\n }\n });\n },\n\n /**\n * Generate a tracked upload button.\n *\n * @param spec Object containing a required `element` property\n * along with optional `multiple`, `accept`, and `folders`.\n * @returns {qq.UploadButton}\n * @private\n */\n _createUploadButton: function(spec) {\n var self = this,\n acceptFiles = spec.accept || this._options.validation.acceptFiles,\n allowedExtensions = spec.allowedExtensions || this._options.validation.allowedExtensions,\n button;\n\n function allowMultiple() {\n if (qq.supportedFeatures.ajaxUploading) {\n // Workaround for bug in iOS7+ (see #1039)\n if (self._options.workarounds.iosEmptyVideos &&\n qq.ios() &&\n !qq.ios6() &&\n self._isAllowedExtension(allowedExtensions, \".mov\")) {\n\n return false;\n }\n\n if (spec.multiple === undefined) {\n return self._options.multiple;\n }\n\n return spec.multiple;\n }\n\n return false;\n }\n\n button = new qq.UploadButton({\n acceptFiles: acceptFiles,\n element: spec.element,\n focusClass: this._options.classes.buttonFocus,\n folders: spec.folders,\n hoverClass: this._options.classes.buttonHover,\n ios8BrowserCrashWorkaround: this._options.workarounds.ios8BrowserCrash,\n multiple: allowMultiple(),\n name: this._options.request.inputName,\n onChange: function(input) {\n self._onInputChange(input);\n },\n title: spec.title == null ? this._options.text.fileInputTitle : spec.title\n });\n\n this._disposeSupport.addDisposer(function() {\n button.dispose();\n });\n\n self._buttons.push(button);\n\n return button;\n },\n\n _createUploadHandler: function(additionalOptions, namespace) {\n var self = this,\n lastOnProgress = {},\n options = {\n debug: this._options.debug,\n maxConnections: this._options.maxConnections,\n cors: this._options.cors,\n paramsStore: this._paramsStore,\n endpointStore: this._endpointStore,\n chunking: this._options.chunking,\n resume: this._options.resume,\n blobs: this._options.blobs,\n log: qq.bind(self.log, self),\n preventRetryParam: this._options.retry.preventRetryResponseProperty,\n onProgress: function(id, name, loaded, total) {\n if (loaded < 0 || total < 0) {\n return;\n }\n\n if (lastOnProgress[id]) {\n if (lastOnProgress[id].loaded !== loaded || lastOnProgress[id].total !== total) {\n self._onProgress(id, name, loaded, total);\n self._options.callbacks.onProgress(id, name, loaded, total);\n }\n }\n else {\n self._onProgress(id, name, loaded, total);\n self._options.callbacks.onProgress(id, name, loaded, total);\n }\n\n lastOnProgress[id] = {loaded: loaded, total: total};\n\n },\n onComplete: function(id, name, result, xhr) {\n delete lastOnProgress[id];\n\n var status = self.getUploads({id: id}).status,\n retVal;\n\n // This is to deal with some observed cases where the XHR readyStateChange handler is\n // invoked by the browser multiple times for the same XHR instance with the same state\n // readyState value. Higher level: don't invoke complete-related code if we've already\n // done this.\n if (status === qq.status.UPLOAD_SUCCESSFUL || status === qq.status.UPLOAD_FAILED) {\n return;\n }\n\n retVal = self._onComplete(id, name, result, xhr);\n\n // If the internal `_onComplete` handler returns a promise, don't invoke the `onComplete` callback\n // until the promise has been fulfilled.\n if (retVal instanceof qq.Promise) {\n retVal.done(function() {\n self._options.callbacks.onComplete(id, name, result, xhr);\n });\n }\n else {\n self._options.callbacks.onComplete(id, name, result, xhr);\n }\n },\n onCancel: function(id, name, cancelFinalizationEffort) {\n var promise = new qq.Promise();\n\n self._handleCheckedCallback({\n name: \"onCancel\",\n callback: qq.bind(self._options.callbacks.onCancel, self, id, name),\n onFailure: promise.failure,\n onSuccess: function() {\n cancelFinalizationEffort.then(function() {\n self._onCancel(id, name);\n });\n\n promise.success();\n },\n identifier: id\n });\n\n return promise;\n },\n onUploadPrep: qq.bind(this._onUploadPrep, this),\n onUpload: function(id, name) {\n self._onUpload(id, name);\n var onUploadResult = self._options.callbacks.onUpload(id, name);\n\n if (qq.isGenericPromise(onUploadResult)) {\n self.log(qq.format(\"onUpload for {} returned a Promise - waiting for resolution.\", id));\n return onUploadResult;\n }\n\n return new qq.Promise().success();\n },\n onUploadChunk: function(id, name, chunkData) {\n self._onUploadChunk(id, chunkData);\n var onUploadChunkResult = self._options.callbacks.onUploadChunk(id, name, chunkData);\n\n if (qq.isGenericPromise(onUploadChunkResult)) {\n self.log(qq.format(\"onUploadChunk for {}.{} returned a Promise - waiting for resolution.\", id, chunkData.partIndex));\n return onUploadChunkResult;\n }\n\n return new qq.Promise().success();\n },\n onUploadChunkSuccess: function(id, chunkData, result, xhr) {\n self._onUploadChunkSuccess(id, chunkData);\n self._options.callbacks.onUploadChunkSuccess.apply(self, arguments);\n },\n onResume: function(id, name, chunkData, customResumeData) {\n return self._options.callbacks.onResume(id, name, chunkData, customResumeData);\n },\n onAutoRetry: function(id, name, responseJSON, xhr) {\n return self._onAutoRetry.apply(self, arguments);\n },\n onUuidChanged: function(id, newUuid) {\n self.log(\"Server requested UUID change from '\" + self.getUuid(id) + \"' to '\" + newUuid + \"'\");\n self.setUuid(id, newUuid);\n },\n getName: qq.bind(self.getName, self),\n getUuid: qq.bind(self.getUuid, self),\n getSize: qq.bind(self.getSize, self),\n setSize: qq.bind(self._setSize, self),\n getDataByUuid: function(uuid) {\n return self.getUploads({uuid: uuid});\n },\n isQueued: function(id) {\n var status = self.getUploads({id: id}).status;\n return status === qq.status.QUEUED ||\n status === qq.status.SUBMITTED ||\n status === qq.status.UPLOAD_RETRYING ||\n status === qq.status.PAUSED;\n },\n getIdsInProxyGroup: self._uploadData.getIdsInProxyGroup,\n getIdsInBatch: self._uploadData.getIdsInBatch,\n isInProgress: function(id) {\n return self.getUploads({id: id}).status === qq.status.UPLOADING;\n },\n getCustomResumeData: qq.bind(self._getCustomResumeData, self),\n setStatus: function(id, status) {\n self._uploadData.setStatus(id, status);\n }\n };\n\n qq.each(this._options.request, function(prop, val) {\n options[prop] = val;\n });\n\n options.customHeaders = this._customHeadersStore;\n\n if (additionalOptions) {\n qq.each(additionalOptions, function(key, val) {\n options[key] = val;\n });\n }\n\n return new qq.UploadHandlerController(options, namespace);\n },\n\n _fileOrBlobRejected: function(id) {\n this._netUploadedOrQueued--;\n this._uploadData.setStatus(id, qq.status.REJECTED);\n },\n\n _formatSize: function(bytes) {\n if (bytes === 0) {\n return bytes + this._options.text.sizeSymbols[0];\n }\n var i = -1;\n do {\n bytes = bytes / 1000;\n i++;\n } while (bytes > 999);\n\n return Math.max(bytes, 0.1).toFixed(1) + this._options.text.sizeSymbols[i];\n },\n\n // Creates an internal object that tracks various properties of each extra button,\n // and then actually creates the extra button.\n _generateExtraButtonSpecs: function() {\n var self = this;\n\n this._extraButtonSpecs = {};\n\n qq.each(this._options.extraButtons, function(idx, extraButtonOptionEntry) {\n var multiple = extraButtonOptionEntry.multiple,\n validation = qq.extend({}, self._options.validation, true),\n extraButtonSpec = qq.extend({}, extraButtonOptionEntry);\n\n if (multiple === undefined) {\n multiple = self._options.multiple;\n }\n\n if (extraButtonSpec.validation) {\n qq.extend(validation, extraButtonOptionEntry.validation, true);\n }\n\n qq.extend(extraButtonSpec, {\n multiple: multiple,\n validation: validation\n }, true);\n\n self._initExtraButton(extraButtonSpec);\n });\n },\n\n _getButton: function(buttonId) {\n var extraButtonsSpec = this._extraButtonSpecs[buttonId];\n\n if (extraButtonsSpec) {\n return extraButtonsSpec.element;\n }\n else if (buttonId === this._defaultButtonId) {\n return this._options.button;\n }\n },\n\n /**\n * Gets the internally used tracking ID for a button.\n *\n * @param buttonOrFileInputOrFile `File`, ` `, or a button container element\n * @returns {*} The button's ID, or undefined if no ID is recoverable\n * @private\n */\n _getButtonId: function(buttonOrFileInputOrFile) {\n var inputs, fileInput,\n fileBlobOrInput = buttonOrFileInputOrFile;\n\n // We want the reference file/blob here if this is a proxy (a file that will be generated on-demand later)\n if (fileBlobOrInput instanceof qq.BlobProxy) {\n fileBlobOrInput = fileBlobOrInput.referenceBlob;\n }\n\n // If the item is a `Blob` it will never be associated with a button or drop zone.\n if (fileBlobOrInput && !qq.isBlob(fileBlobOrInput)) {\n if (qq.isFile(fileBlobOrInput)) {\n return fileBlobOrInput.qqButtonId;\n }\n else if (fileBlobOrInput.tagName.toLowerCase() === \"input\" &&\n fileBlobOrInput.type.toLowerCase() === \"file\") {\n\n return fileBlobOrInput.getAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME);\n }\n\n inputs = fileBlobOrInput.getElementsByTagName(\"input\");\n\n qq.each(inputs, function(idx, input) {\n if (input.getAttribute(\"type\") === \"file\") {\n fileInput = input;\n return false;\n }\n });\n\n if (fileInput) {\n return fileInput.getAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME);\n }\n }\n },\n\n _getCustomResumeData: function(fileId) {\n return this._customResumeDataStore.get(fileId);\n },\n\n _getNotFinished: function() {\n return this._uploadData.retrieve({\n status: [\n qq.status.UPLOADING,\n qq.status.UPLOAD_RETRYING,\n qq.status.QUEUED,\n qq.status.SUBMITTING,\n qq.status.SUBMITTED,\n qq.status.PAUSED\n ]\n }).length;\n },\n\n // Get the validation options for this button. Could be the default validation option\n // or a specific one assigned to this particular button.\n _getValidationBase: function(buttonId) {\n var extraButtonSpec = this._extraButtonSpecs[buttonId];\n\n return extraButtonSpec ? extraButtonSpec.validation : this._options.validation;\n },\n\n _getValidationDescriptor: function(fileWrapper) {\n if (fileWrapper.file instanceof qq.BlobProxy) {\n return {\n name: qq.getFilename(fileWrapper.file.referenceBlob),\n size: fileWrapper.file.referenceBlob.size\n };\n }\n\n return {\n name: this.getUploads({id: fileWrapper.id}).name,\n size: this.getUploads({id: fileWrapper.id}).size\n };\n },\n\n _getValidationDescriptors: function(fileWrappers) {\n var self = this,\n fileDescriptors = [];\n\n qq.each(fileWrappers, function(idx, fileWrapper) {\n fileDescriptors.push(self._getValidationDescriptor(fileWrapper));\n });\n\n return fileDescriptors;\n },\n\n // Allows camera access on either the default or an extra button for iOS devices.\n _handleCameraAccess: function() {\n if (this._options.camera.ios && qq.ios()) {\n var acceptIosCamera = \"image/*;capture=camera\",\n button = this._options.camera.button,\n buttonId = button ? this._getButtonId(button) : this._defaultButtonId,\n optionRoot = this._options;\n\n // If we are not targeting the default button, it is an \"extra\" button\n if (buttonId && buttonId !== this._defaultButtonId) {\n optionRoot = this._extraButtonSpecs[buttonId];\n }\n\n // Camera access won't work in iOS if the `multiple` attribute is present on the file input\n optionRoot.multiple = false;\n\n // update the options\n if (optionRoot.validation.acceptFiles === null) {\n optionRoot.validation.acceptFiles = acceptIosCamera;\n }\n else {\n optionRoot.validation.acceptFiles += \",\" + acceptIosCamera;\n }\n\n // update the already-created button\n qq.each(this._buttons, function(idx, button) {\n if (button.getButtonId() === buttonId) {\n button.setMultiple(optionRoot.multiple);\n button.setAcceptFiles(optionRoot.acceptFiles);\n\n return false;\n }\n });\n }\n },\n\n _handleCheckedCallback: function(details) {\n var self = this,\n callbackRetVal = details.callback();\n\n if (qq.isGenericPromise(callbackRetVal)) {\n this.log(details.name + \" - waiting for \" + details.name + \" promise to be fulfilled for \" + details.identifier);\n return callbackRetVal.then(\n function(successParam) {\n self.log(details.name + \" promise success for \" + details.identifier);\n details.onSuccess(successParam);\n },\n function() {\n if (details.onFailure) {\n self.log(details.name + \" promise failure for \" + details.identifier);\n details.onFailure();\n }\n else {\n self.log(details.name + \" promise failure for \" + details.identifier);\n }\n });\n }\n\n if (callbackRetVal !== false) {\n details.onSuccess(callbackRetVal);\n }\n else {\n if (details.onFailure) {\n this.log(details.name + \" - return value was 'false' for \" + details.identifier + \". Invoking failure callback.\");\n details.onFailure();\n }\n else {\n this.log(details.name + \" - return value was 'false' for \" + details.identifier + \". Will not proceed.\");\n }\n }\n\n return callbackRetVal;\n },\n\n // Updates internal state when a new file has been received, and adds it along with its ID to a passed array.\n _handleNewFile: function(file, batchId, newFileWrapperList) {\n var self = this,\n uuid = qq.getUniqueId(),\n size = -1,\n name = qq.getFilename(file),\n actualFile = file.blob || file,\n handler = this._customNewFileHandler ?\n this._customNewFileHandler :\n qq.bind(self._handleNewFileGeneric, self);\n\n if (!qq.isInput(actualFile) && actualFile.size >= 0) {\n size = actualFile.size;\n }\n\n handler(actualFile, name, uuid, size, newFileWrapperList, batchId, this._options.request.uuidName, {\n uploadData: self._uploadData,\n paramsStore: self._paramsStore,\n addFileToHandler: function(id, file) {\n self._handler.add(id, file);\n self._netUploadedOrQueued++;\n self._trackButton(id);\n }\n });\n },\n\n _handleNewFileGeneric: function(file, name, uuid, size, fileList, batchId) {\n var id = this._uploadData.addFile({\n uuid: uuid,\n name: name,\n size: size,\n batchId: batchId,\n file: file\n });\n\n this._handler.add(id, file);\n\n this._trackButton(id);\n\n this._netUploadedOrQueued++;\n\n fileList.push({id: id, file: file});\n },\n\n _handlePasteSuccess: function(blob, extSuppliedName) {\n var extension = blob.type.split(\"/\")[1],\n name = extSuppliedName;\n\n /*jshint eqeqeq: true, eqnull: true*/\n if (name == null) {\n name = this._options.paste.defaultName;\n }\n\n name += \".\" + extension;\n\n this.addFiles({\n name: name,\n blob: blob\n });\n },\n\n _handleDeleteSuccess: function(id) {\n if (this.getUploads({id: id}).status !== qq.status.DELETED) {\n var name = this.getName(id);\n\n this._netUploadedOrQueued--;\n this._netUploaded--;\n this._handler.expunge(id);\n this._uploadData.setStatus(id, qq.status.DELETED);\n this.log(\"Delete request for '\" + name + \"' has succeeded.\");\n }\n },\n\n _handleDeleteFailed: function(id, xhrOrXdr) {\n var name = this.getName(id);\n\n this._uploadData.setStatus(id, qq.status.DELETE_FAILED);\n this.log(\"Delete request for '\" + name + \"' has failed.\", \"error\");\n\n // Check first if xhrOrXdr is actually passed or valid\n // For error reporting, we only have access to the response status if this is not\n // an `XDomainRequest`.\n if (!xhrOrXdr || xhrOrXdr.withCredentials === undefined) {\n this._options.callbacks.onError(id, name, \"Delete request failed\", xhrOrXdr);\n }\n else {\n this._options.callbacks.onError(id, name, \"Delete request failed with response code \" + xhrOrXdr.status, xhrOrXdr);\n }\n },\n\n // Creates an extra button element\n _initExtraButton: function(spec) {\n var button = this._createUploadButton({\n accept: spec.validation.acceptFiles,\n allowedExtensions: spec.validation.allowedExtensions,\n element: spec.element,\n folders: spec.folders,\n multiple: spec.multiple,\n title: spec.fileInputTitle\n });\n\n this._extraButtonSpecs[button.getButtonId()] = spec;\n },\n\n _initFormSupportAndParams: function() {\n this._formSupport = qq.FormSupport && new qq.FormSupport(\n this._options.form, qq.bind(this.uploadStoredFiles, this), qq.bind(this.log, this)\n );\n\n if (this._formSupport && this._formSupport.attachedToForm) {\n this._paramsStore = this._createStore(\n this._options.request.params, this._formSupport.getFormInputsAsObject\n );\n\n this._options.autoUpload = this._formSupport.newAutoUpload;\n if (this._formSupport.newEndpoint) {\n this._options.request.endpoint = this._formSupport.newEndpoint;\n }\n }\n else {\n this._paramsStore = this._createStore(this._options.request.params);\n }\n },\n\n _isDeletePossible: function() {\n if (!qq.DeleteFileAjaxRequester || !this._options.deleteFile.enabled) {\n return false;\n }\n\n if (this._options.cors.expected) {\n if (qq.supportedFeatures.deleteFileCorsXhr) {\n return true;\n }\n\n if (qq.supportedFeatures.deleteFileCorsXdr && this._options.cors.allowXdr) {\n return true;\n }\n\n return false;\n }\n\n return true;\n },\n\n _isAllowedExtension: function(allowed, fileName) {\n var valid = false;\n\n if (!allowed.length) {\n return true;\n }\n\n qq.each(allowed, function(idx, allowedExt) {\n /**\n * If an argument is not a string, ignore it. Added when a possible issue with MooTools hijacking the\n * `allowedExtensions` array was discovered. See case #735 in the issue tracker for more details.\n */\n if (qq.isString(allowedExt)) {\n /*jshint eqeqeq: true, eqnull: true*/\n var extRegex = new RegExp(\"\\\\.\" + allowedExt + \"$\", \"i\");\n\n if (fileName.match(extRegex) != null) {\n valid = true;\n return false;\n }\n }\n });\n\n return valid;\n },\n\n /**\n * Constructs and returns a message that describes an item/file error. Also calls `onError` callback.\n *\n * @param code REQUIRED - a code that corresponds to a stock message describing this type of error\n * @param maybeNameOrNames names of the items that have failed, if applicable\n * @param item `File`, `Blob`, or ` `\n * @private\n */\n _itemError: function(code, maybeNameOrNames, item) {\n var message = this._options.messages[code],\n allowedExtensions = [],\n names = [].concat(maybeNameOrNames),\n name = names[0],\n buttonId = this._getButtonId(item),\n validationBase = this._getValidationBase(buttonId),\n extensionsForMessage, placeholderMatch;\n\n function r(name, replacement) { message = message.replace(name, replacement); }\n\n qq.each(validationBase.allowedExtensions, function(idx, allowedExtension) {\n /**\n * If an argument is not a string, ignore it. Added when a possible issue with MooTools hijacking the\n * `allowedExtensions` array was discovered. See case #735 in the issue tracker for more details.\n */\n if (qq.isString(allowedExtension)) {\n allowedExtensions.push(allowedExtension);\n }\n });\n\n extensionsForMessage = allowedExtensions.join(\", \").toLowerCase();\n\n r(\"{file}\", this._options.formatFileName(name));\n r(\"{extensions}\", extensionsForMessage);\n r(\"{sizeLimit}\", this._formatSize(validationBase.sizeLimit));\n r(\"{minSizeLimit}\", this._formatSize(validationBase.minSizeLimit));\n\n placeholderMatch = message.match(/(\\{\\w+\\})/g);\n if (placeholderMatch !== null) {\n qq.each(placeholderMatch, function(idx, placeholder) {\n r(placeholder, names[idx]);\n });\n }\n\n this._options.callbacks.onError(null, name, message, undefined);\n\n return message;\n },\n\n /**\n * Conditionally orders a manual retry of a failed upload.\n *\n * @param id File ID of the failed upload\n * @param callback Optional callback to invoke if a retry is prudent.\n * In lieu of asking the upload handler to retry.\n * @returns {boolean} true if a manual retry will occur\n * @private\n */\n _manualRetry: function(id, callback) {\n if (this._onBeforeManualRetry(id)) {\n this._netUploadedOrQueued++;\n this._uploadData.setStatus(id, qq.status.UPLOAD_RETRYING);\n\n if (callback) {\n callback(id);\n }\n else {\n this._handler.retry(id);\n }\n\n return true;\n }\n },\n\n _maybeAllComplete: function(id, status) {\n var self = this,\n notFinished = this._getNotFinished();\n\n if (status === qq.status.UPLOAD_SUCCESSFUL) {\n this._succeededSinceLastAllComplete.push(id);\n }\n else if (status === qq.status.UPLOAD_FAILED) {\n this._failedSinceLastAllComplete.push(id);\n }\n\n if (notFinished === 0 &&\n (this._succeededSinceLastAllComplete.length || this._failedSinceLastAllComplete.length)) {\n // Attempt to ensure onAllComplete is not invoked before other callbacks, such as onCancel & onComplete\n setTimeout(function() {\n self._onAllComplete(self._succeededSinceLastAllComplete, self._failedSinceLastAllComplete);\n }, 0);\n }\n },\n\n _maybeHandleIos8SafariWorkaround: function() {\n var self = this;\n\n if (this._options.workarounds.ios8SafariUploads && qq.ios800() && qq.iosSafari()) {\n setTimeout(function() {\n window.alert(self._options.messages.unsupportedBrowserIos8Safari);\n }, 0);\n throw new qq.Error(this._options.messages.unsupportedBrowserIos8Safari);\n }\n },\n\n _maybeParseAndSendUploadError: function(id, name, response, xhr) {\n // Assuming no one will actually set the response code to something other than 200\n // and still set 'success' to true...\n if (!response.success) {\n if (xhr && xhr.status !== 200 && !response.error) {\n this._options.callbacks.onError(id, name, \"XHR returned response code \" + xhr.status, xhr);\n }\n else {\n var errorReason = response.error ? response.error : this._options.text.defaultResponseError;\n this._options.callbacks.onError(id, name, errorReason, xhr);\n }\n }\n },\n\n _maybeProcessNextItemAfterOnValidateCallback: function(validItem, items, index, params, endpoint) {\n var self = this;\n\n if (items.length > index) {\n if (validItem || !this._options.validation.stopOnFirstInvalidFile) {\n //use setTimeout to prevent a stack overflow with a large number of files in the batch & non-promissory callbacks\n setTimeout(function() {\n var validationDescriptor = self._getValidationDescriptor(items[index]),\n buttonId = self._getButtonId(items[index].file),\n button = self._getButton(buttonId);\n\n self._handleCheckedCallback({\n name: \"onValidate\",\n callback: qq.bind(self._options.callbacks.onValidate, self, validationDescriptor, button),\n onSuccess: qq.bind(self._onValidateCallbackSuccess, self, items, index, params, endpoint),\n onFailure: qq.bind(self._onValidateCallbackFailure, self, items, index, params, endpoint),\n identifier: \"Item '\" + validationDescriptor.name + \"', size: \" + validationDescriptor.size\n });\n }, 0);\n }\n else if (!validItem) {\n for (; index < items.length; index++) {\n self._fileOrBlobRejected(items[index].id);\n }\n }\n }\n },\n\n _onAllComplete: function(successful, failed) {\n this._totalProgress && this._totalProgress.onAllComplete(successful, failed, this._preventRetries);\n\n this._options.callbacks.onAllComplete(qq.extend([], successful), qq.extend([], failed));\n\n this._succeededSinceLastAllComplete = [];\n this._failedSinceLastAllComplete = [];\n },\n\n /**\n * Attempt to automatically retry a failed upload.\n *\n * @param id The file ID of the failed upload\n * @param name The name of the file associated with the failed upload\n * @param responseJSON Response from the server, parsed into a javascript object\n * @param xhr Ajax transport used to send the failed request\n * @param callback Optional callback to be invoked if a retry is prudent.\n * Invoked in lieu of asking the upload handler to retry.\n * @returns {boolean} true if an auto-retry will occur\n * @private\n */\n _onAutoRetry: function(id, name, responseJSON, xhr, callback) {\n var self = this;\n\n self._preventRetries[id] = responseJSON[self._options.retry.preventRetryResponseProperty];\n\n if (self._shouldAutoRetry(id)) {\n var retryWaitPeriod = self._options.retry.autoAttemptDelay * 1000;\n\n self._maybeParseAndSendUploadError.apply(self, arguments);\n self._options.callbacks.onAutoRetry(id, name, self._autoRetries[id]);\n self._onBeforeAutoRetry(id, name);\n\n self._uploadData.setStatus(id, qq.status.UPLOAD_RETRYING);\n self._retryTimeouts[id] = setTimeout(function() {\n self.log(\"Starting retry for \" + name + \"...\");\n\n if (callback) {\n callback(id);\n }\n else {\n self._handler.retry(id);\n }\n }, retryWaitPeriod);\n\n return true;\n }\n },\n\n _onBeforeAutoRetry: function(id, name) {\n this.log(\"Waiting \" + this._options.retry.autoAttemptDelay + \" seconds before retrying \" + name + \"...\");\n },\n\n //return false if we should not attempt the requested retry\n _onBeforeManualRetry: function(id) {\n var itemLimit = this._currentItemLimit,\n fileName;\n\n if (this._preventRetries[id]) {\n this.log(\"Retries are forbidden for id \" + id, \"warn\");\n return false;\n }\n else if (this._handler.isValid(id)) {\n fileName = this.getName(id);\n\n if (this._options.callbacks.onManualRetry(id, fileName) === false) {\n return false;\n }\n\n if (itemLimit > 0 && this._netUploadedOrQueued + 1 > itemLimit) {\n this._itemError(\"retryFailTooManyItems\");\n return false;\n }\n\n this.log(\"Retrying upload for '\" + fileName + \"' (id: \" + id + \")...\");\n return true;\n }\n else {\n this.log(\"'\" + id + \"' is not a valid file ID\", \"error\");\n return false;\n }\n },\n\n _onCancel: function(id, name) {\n this._netUploadedOrQueued--;\n\n clearTimeout(this._retryTimeouts[id]);\n\n var storedItemIndex = qq.indexOf(this._storedIds, id);\n if (!this._options.autoUpload && storedItemIndex >= 0) {\n this._storedIds.splice(storedItemIndex, 1);\n }\n\n this._uploadData.setStatus(id, qq.status.CANCELED);\n },\n\n _onComplete: function(id, name, result, xhr) {\n if (!result.success) {\n this._netUploadedOrQueued--;\n this._uploadData.setStatus(id, qq.status.UPLOAD_FAILED);\n\n if (result[this._options.retry.preventRetryResponseProperty] === true) {\n this._preventRetries[id] = true;\n }\n }\n else {\n if (result.thumbnailUrl) {\n this._thumbnailUrls[id] = result.thumbnailUrl;\n }\n\n this._netUploaded++;\n this._uploadData.setStatus(id, qq.status.UPLOAD_SUCCESSFUL);\n }\n\n this._maybeParseAndSendUploadError(id, name, result, xhr);\n\n return result.success ? true : false;\n },\n\n _onDelete: function(id) {\n this._uploadData.setStatus(id, qq.status.DELETING);\n },\n\n _onDeleteComplete: function(id, xhrOrXdr, isError) {\n var name = this.getName(id);\n\n if (isError) {\n this._handleDeleteFailed(id, xhrOrXdr);\n }\n else {\n this._handleDeleteSuccess(id);\n }\n },\n\n _onInputChange: function(input) {\n var fileIndex;\n\n if (qq.supportedFeatures.ajaxUploading) {\n for (fileIndex = 0; fileIndex < input.files.length; fileIndex++) {\n this._annotateWithButtonId(input.files[fileIndex], input);\n }\n\n this.addFiles(input.files);\n }\n // Android 2.3.x will fire `onchange` even if no file has been selected\n else if (input.value.length > 0) {\n this.addFiles(input);\n }\n\n qq.each(this._buttons, function(idx, button) {\n button.reset();\n });\n },\n\n _onProgress: function(id, name, loaded, total) {\n this._totalProgress && this._totalProgress.onIndividualProgress(id, loaded, total);\n },\n\n _onSubmit: function(id, name) {\n //nothing to do yet in core uploader\n },\n\n _onSubmitCallbackSuccess: function(id, name) {\n this._onSubmit.apply(this, arguments);\n this._uploadData.setStatus(id, qq.status.SUBMITTED);\n this._onSubmitted.apply(this, arguments);\n\n if (this._options.autoUpload) {\n this._options.callbacks.onSubmitted.apply(this, arguments);\n this._uploadFile(id);\n }\n else {\n this._storeForLater(id);\n this._options.callbacks.onSubmitted.apply(this, arguments);\n }\n },\n\n _onSubmitDelete: function(id, onSuccessCallback, additionalMandatedParams) {\n var uuid = this.getUuid(id),\n adjustedOnSuccessCallback;\n\n if (onSuccessCallback) {\n adjustedOnSuccessCallback = qq.bind(onSuccessCallback, this, id, uuid, additionalMandatedParams);\n }\n\n if (this._isDeletePossible()) {\n this._handleCheckedCallback({\n name: \"onSubmitDelete\",\n callback: qq.bind(this._options.callbacks.onSubmitDelete, this, id),\n onSuccess: adjustedOnSuccessCallback ||\n qq.bind(this._deleteHandler.sendDelete, this, id, uuid, additionalMandatedParams),\n identifier: id\n });\n return true;\n }\n else {\n this.log(\"Delete request ignored for ID \" + id + \", delete feature is disabled or request not possible \" +\n \"due to CORS on a user agent that does not support pre-flighting.\", \"warn\");\n return false;\n }\n },\n\n _onSubmitted: function(id) {\n //nothing to do in the base uploader\n },\n\n _onTotalProgress: function(loaded, total) {\n this._options.callbacks.onTotalProgress(loaded, total);\n },\n\n _onUploadPrep: function(id) {\n // nothing to do in the core uploader for now\n },\n\n _onUpload: function(id, name) {\n this._uploadData.setStatus(id, qq.status.UPLOADING);\n },\n\n _onUploadChunk: function(id, chunkData) {\n //nothing to do in the base uploader\n },\n\n _onUploadChunkSuccess: function(id, chunkData) {\n if (!this._preventRetries[id] && this._options.retry.enableAuto) {\n this._autoRetries[id] = 0;\n }\n },\n\n _onUploadStatusChange: function(id, oldStatus, newStatus) {\n // Make sure a \"queued\" retry attempt is canceled if the upload has been paused\n if (newStatus === qq.status.PAUSED) {\n clearTimeout(this._retryTimeouts[id]);\n }\n },\n\n _onValidateBatchCallbackFailure: function(fileWrappers) {\n var self = this;\n\n qq.each(fileWrappers, function(idx, fileWrapper) {\n self._fileOrBlobRejected(fileWrapper.id);\n });\n },\n\n _onValidateBatchCallbackSuccess: function(validationDescriptors, items, params, endpoint, button) {\n var errorMessage,\n itemLimit = this._currentItemLimit,\n proposedNetFilesUploadedOrQueued = this._netUploadedOrQueued;\n\n if (itemLimit === 0 || proposedNetFilesUploadedOrQueued <= itemLimit) {\n if (items.length > 0) {\n this._handleCheckedCallback({\n name: \"onValidate\",\n callback: qq.bind(this._options.callbacks.onValidate, this, validationDescriptors[0], button),\n onSuccess: qq.bind(this._onValidateCallbackSuccess, this, items, 0, params, endpoint),\n onFailure: qq.bind(this._onValidateCallbackFailure, this, items, 0, params, endpoint),\n identifier: \"Item '\" + items[0].file.name + \"', size: \" + items[0].file.size\n });\n }\n else {\n this._itemError(\"noFilesError\");\n }\n }\n else {\n this._onValidateBatchCallbackFailure(items);\n errorMessage = this._options.messages.tooManyItemsError\n .replace(/\\{netItems\\}/g, proposedNetFilesUploadedOrQueued)\n .replace(/\\{itemLimit\\}/g, itemLimit);\n this._batchError(errorMessage);\n }\n },\n\n _onValidateCallbackFailure: function(items, index, params, endpoint) {\n var nextIndex = index + 1;\n\n this._fileOrBlobRejected(items[index].id, items[index].file.name);\n\n this._maybeProcessNextItemAfterOnValidateCallback(false, items, nextIndex, params, endpoint);\n },\n\n _onValidateCallbackSuccess: function(items, index, params, endpoint) {\n var self = this,\n nextIndex = index + 1,\n validationDescriptor = this._getValidationDescriptor(items[index]);\n\n this._validateFileOrBlobData(items[index], validationDescriptor)\n .then(\n function() {\n self._upload(items[index].id, params, endpoint);\n self._maybeProcessNextItemAfterOnValidateCallback(true, items, nextIndex, params, endpoint);\n },\n function() {\n self._maybeProcessNextItemAfterOnValidateCallback(false, items, nextIndex, params, endpoint);\n }\n );\n },\n\n _prepareItemsForUpload: function(items, params, endpoint) {\n if (items.length === 0) {\n this._itemError(\"noFilesError\");\n return;\n }\n\n var validationDescriptors = this._getValidationDescriptors(items),\n buttonId = this._getButtonId(items[0].file),\n button = this._getButton(buttonId);\n\n this._handleCheckedCallback({\n name: \"onValidateBatch\",\n callback: qq.bind(this._options.callbacks.onValidateBatch, this, validationDescriptors, button),\n onSuccess: qq.bind(this._onValidateBatchCallbackSuccess, this, validationDescriptors, items, params, endpoint, button),\n onFailure: qq.bind(this._onValidateBatchCallbackFailure, this, items),\n identifier: \"batch validation\"\n });\n },\n\n _preventLeaveInProgress: function() {\n var self = this;\n\n this._disposeSupport.attach(window, \"beforeunload\", function(e) {\n if (self.getInProgress()) {\n e = e || window.event;\n // for ie, ff\n e.returnValue = self._options.messages.onLeave;\n // for webkit\n return self._options.messages.onLeave;\n }\n });\n },\n\n // Attempts to refresh session data only if the `qq.Session` module exists\n // and a session endpoint has been specified. The `onSessionRequestComplete`\n // callback will be invoked once the refresh is complete.\n _refreshSessionData: function() {\n var self = this,\n options = this._options.session;\n\n /* jshint eqnull:true */\n if (qq.Session && this._options.session.endpoint != null) {\n if (!this._session) {\n qq.extend(options, {cors: this._options.cors});\n\n options.log = qq.bind(this.log, this);\n options.addFileRecord = qq.bind(this._addCannedFile, this);\n\n this._session = new qq.Session(options);\n }\n\n setTimeout(function() {\n self._session.refresh().then(function(response, xhrOrXdr) {\n self._sessionRequestComplete();\n self._options.callbacks.onSessionRequestComplete(response, true, xhrOrXdr);\n\n }, function(response, xhrOrXdr) {\n\n self._options.callbacks.onSessionRequestComplete(response, false, xhrOrXdr);\n });\n }, 0);\n }\n },\n\n _sessionRequestComplete: function() {},\n\n _setSize: function(id, newSize) {\n this._uploadData.updateSize(id, newSize);\n this._totalProgress && this._totalProgress.onNewSize(id);\n },\n\n _shouldAutoRetry: function(id) {\n var uploadData = this._uploadData.retrieve({id: id});\n\n /*jshint laxbreak: true */\n if (!this._preventRetries[id]\n && this._options.retry.enableAuto\n && uploadData.status !== qq.status.PAUSED) {\n\n if (this._autoRetries[id] === undefined) {\n this._autoRetries[id] = 0;\n }\n\n if (this._autoRetries[id] < this._options.retry.maxAutoAttempts) {\n this._autoRetries[id] += 1;\n return true;\n }\n }\n\n return false;\n },\n\n _storeForLater: function(id) {\n this._storedIds.push(id);\n },\n\n // Maps a file with the button that was used to select it.\n _trackButton: function(id) {\n var buttonId;\n\n if (qq.supportedFeatures.ajaxUploading) {\n buttonId = this._handler.getFile(id).qqButtonId;\n }\n else {\n buttonId = this._getButtonId(this._handler.getInput(id));\n }\n\n if (buttonId) {\n this._buttonIdsForFileIds[id] = buttonId;\n }\n },\n\n _updateFormSupportAndParams: function(formElementOrId) {\n this._options.form.element = formElementOrId;\n\n this._formSupport = qq.FormSupport && new qq.FormSupport(\n this._options.form, qq.bind(this.uploadStoredFiles, this), qq.bind(this.log, this)\n );\n\n if (this._formSupport && this._formSupport.attachedToForm) {\n this._paramsStore.addReadOnly(null, this._formSupport.getFormInputsAsObject);\n\n this._options.autoUpload = this._formSupport.newAutoUpload;\n if (this._formSupport.newEndpoint) {\n this.setEndpoint(this._formSupport.newEndpoint);\n }\n }\n },\n\n _upload: function(id, params, endpoint) {\n var name = this.getName(id);\n\n if (params) {\n this.setParams(params, id);\n }\n\n if (endpoint) {\n this.setEndpoint(endpoint, id);\n }\n\n this._handleCheckedCallback({\n name: \"onSubmit\",\n callback: qq.bind(this._options.callbacks.onSubmit, this, id, name),\n onSuccess: qq.bind(this._onSubmitCallbackSuccess, this, id, name),\n onFailure: qq.bind(this._fileOrBlobRejected, this, id, name),\n identifier: id\n });\n },\n\n _uploadFile: function(id) {\n if (!this._handler.upload(id)) {\n this._uploadData.setStatus(id, qq.status.QUEUED);\n }\n },\n\n _uploadStoredFiles: function() {\n var idToUpload, stillSubmitting,\n self = this;\n\n while (this._storedIds.length) {\n idToUpload = this._storedIds.shift();\n this._uploadFile(idToUpload);\n }\n\n // If we are still waiting for some files to clear validation, attempt to upload these again in a bit\n stillSubmitting = this.getUploads({status: qq.status.SUBMITTING}).length;\n if (stillSubmitting) {\n qq.log(\"Still waiting for \" + stillSubmitting + \" files to clear submit queue. Will re-parse stored IDs array shortly.\");\n setTimeout(function() {\n self._uploadStoredFiles();\n }, 1000);\n }\n },\n\n /**\n * Performs some internal validation checks on an item, defined in the `validation` option.\n *\n * @param fileWrapper Wrapper containing a `file` along with an `id`\n * @param validationDescriptor Normalized information about the item (`size`, `name`).\n * @returns qq.Promise with appropriate callbacks invoked depending on the validity of the file\n * @private\n */\n _validateFileOrBlobData: function(fileWrapper, validationDescriptor) {\n var self = this,\n file = (function() {\n if (fileWrapper.file instanceof qq.BlobProxy) {\n return fileWrapper.file.referenceBlob;\n }\n return fileWrapper.file;\n }()),\n name = validationDescriptor.name,\n size = validationDescriptor.size,\n buttonId = this._getButtonId(fileWrapper.file),\n validationBase = this._getValidationBase(buttonId),\n validityChecker = new qq.Promise();\n\n validityChecker.then(\n function() {},\n function() {\n self._fileOrBlobRejected(fileWrapper.id, name);\n });\n\n if (qq.isFileOrInput(file) && !this._isAllowedExtension(validationBase.allowedExtensions, name)) {\n this._itemError(\"typeError\", name, file);\n return validityChecker.failure();\n }\n\n if (!this._options.validation.allowEmpty && size === 0) {\n this._itemError(\"emptyError\", name, file);\n return validityChecker.failure();\n }\n\n if (size > 0 && validationBase.sizeLimit && size > validationBase.sizeLimit) {\n this._itemError(\"sizeError\", name, file);\n return validityChecker.failure();\n }\n\n if (size > 0 && size < validationBase.minSizeLimit) {\n this._itemError(\"minSizeError\", name, file);\n return validityChecker.failure();\n }\n\n if (qq.ImageValidation && qq.supportedFeatures.imagePreviews && qq.isFile(file)) {\n new qq.ImageValidation(file, qq.bind(self.log, self)).validate(validationBase.image).then(\n validityChecker.success,\n function(errorCode) {\n self._itemError(errorCode + \"ImageError\", name, file);\n validityChecker.failure();\n }\n );\n }\n else {\n validityChecker.success();\n }\n\n return validityChecker;\n },\n\n _wrapCallbacks: function() {\n var self, safeCallback, prop;\n\n self = this;\n\n safeCallback = function(name, callback, args) {\n var errorMsg;\n\n try {\n return callback.apply(self, args);\n }\n catch (exception) {\n errorMsg = exception.message || exception.toString();\n self.log(\"Caught exception in '\" + name + \"' callback - \" + errorMsg, \"error\");\n }\n };\n\n /* jshint forin: false, loopfunc: true */\n for (prop in this._options.callbacks) {\n (function() {\n var callbackName, callbackFunc;\n callbackName = prop;\n callbackFunc = self._options.callbacks[callbackName];\n self._options.callbacks[callbackName] = function() {\n return safeCallback(callbackName, callbackFunc, arguments);\n };\n }());\n }\n }\n };\n}());\n","/*globals qq*/\n(function() {\n \"use strict\";\n\n qq.FineUploaderBasic = function(o) {\n var self = this;\n\n // These options define FineUploaderBasic mode.\n this._options = {\n debug: false,\n button: null,\n multiple: true,\n maxConnections: 3,\n disableCancelForFormUploads: false,\n autoUpload: true,\n warnBeforeUnload: true,\n\n request: {\n customHeaders: {},\n endpoint: \"/server/upload\",\n filenameParam: \"qqfilename\",\n forceMultipart: true,\n inputName: \"qqfile\",\n method: \"POST\",\n omitDefaultParams: false,\n params: {},\n paramsInBody: true,\n requireSuccessJson: true,\n totalFileSizeName: \"qqtotalfilesize\",\n uuidName: \"qquuid\"\n },\n\n validation: {\n allowedExtensions: [],\n sizeLimit: 0,\n minSizeLimit: 0,\n itemLimit: 0,\n stopOnFirstInvalidFile: true,\n acceptFiles: null,\n image: {\n maxHeight: 0,\n maxWidth: 0,\n minHeight: 0,\n minWidth: 0\n },\n allowEmpty: false\n },\n\n callbacks: {\n onSubmit: function(id, name) {},\n onSubmitted: function(id, name) {},\n onComplete: function(id, name, responseJSON, maybeXhr) {},\n onAllComplete: function(successful, failed) {},\n onCancel: function(id, name) {},\n onUpload: function(id, name) {},\n onUploadChunk: function(id, name, chunkData) {},\n onUploadChunkSuccess: function(id, chunkData, responseJSON, xhr) {},\n onResume: function(id, fileName, chunkData, customResumeData) {},\n onProgress: function(id, name, loaded, total) {},\n onTotalProgress: function(loaded, total) {},\n onError: function(id, name, reason, maybeXhrOrXdr) {},\n onAutoRetry: function(id, name, attemptNumber) {},\n onManualRetry: function(id, name) {},\n onValidateBatch: function(fileOrBlobData) {},\n onValidate: function(fileOrBlobData) {},\n onSubmitDelete: function(id) {},\n onDelete: function(id) {},\n onDeleteComplete: function(id, xhrOrXdr, isError) {},\n onPasteReceived: function(blob) {},\n onStatusChange: function(id, oldStatus, newStatus) {},\n onSessionRequestComplete: function(response, success, xhrOrXdr) {}\n },\n\n messages: {\n typeError: \"{file} has an invalid extension. Valid extension(s): {extensions}.\",\n sizeError: \"{file} is too large, maximum file size is {sizeLimit}.\",\n minSizeError: \"{file} is too small, minimum file size is {minSizeLimit}.\",\n emptyError: \"{file} is empty, please select files again without it.\",\n noFilesError: \"No files to upload.\",\n tooManyItemsError: \"Too many items ({netItems}) would be uploaded. Item limit is {itemLimit}.\",\n maxHeightImageError: \"Image is too tall.\",\n maxWidthImageError: \"Image is too wide.\",\n minHeightImageError: \"Image is not tall enough.\",\n minWidthImageError: \"Image is not wide enough.\",\n retryFailTooManyItems: \"Retry failed - you have reached your file limit.\",\n onLeave: \"The files are being uploaded, if you leave now the upload will be canceled.\",\n unsupportedBrowserIos8Safari: \"Unrecoverable error - this browser does not permit file uploading of any kind due to serious bugs in iOS8 Safari. Please use iOS8 Chrome until Apple fixes these issues.\"\n },\n\n retry: {\n enableAuto: false,\n maxAutoAttempts: 3,\n autoAttemptDelay: 5,\n preventRetryResponseProperty: \"preventRetry\"\n },\n\n classes: {\n buttonHover: \"qq-upload-button-hover\",\n buttonFocus: \"qq-upload-button-focus\"\n },\n\n chunking: {\n enabled: false,\n concurrent: {\n enabled: false\n },\n mandatory: false,\n paramNames: {\n partIndex: \"qqpartindex\",\n partByteOffset: \"qqpartbyteoffset\",\n chunkSize: \"qqchunksize\",\n totalFileSize: \"qqtotalfilesize\",\n totalParts: \"qqtotalparts\"\n },\n partSize: function(id) {\n return 2000000;\n },\n // only relevant for traditional endpoints, only required when concurrent.enabled === true\n success: {\n endpoint: null,\n\n headers: function(id) {\n return null;\n },\n\n jsonPayload: false,\n\n method: \"POST\",\n\n params: function(id) {\n return null;\n },\n\n resetOnStatus: []\n }\n },\n\n resume: {\n enabled: false,\n recordsExpireIn: 7, //days\n paramNames: {\n resuming: \"qqresume\"\n },\n customKeys: function(fileId) {\n return [];\n }\n },\n\n formatFileName: function(fileOrBlobName) {\n return fileOrBlobName;\n },\n\n text: {\n defaultResponseError: \"Upload failure reason unknown\",\n fileInputTitle: \"file input\",\n sizeSymbols: [\"kB\", \"MB\", \"GB\", \"TB\", \"PB\", \"EB\"]\n },\n\n deleteFile: {\n enabled: false,\n method: \"DELETE\",\n endpoint: \"/server/upload\",\n customHeaders: {},\n params: {}\n },\n\n cors: {\n expected: false,\n sendCredentials: false,\n allowXdr: false\n },\n\n blobs: {\n defaultName: \"misc_data\"\n },\n\n paste: {\n targetElement: null,\n defaultName: \"pasted_image\"\n },\n\n camera: {\n ios: false,\n\n // if ios is true: button is null means target the default button, otherwise target the button specified\n button: null\n },\n\n // This refers to additional upload buttons to be handled by Fine Uploader.\n // Each element is an object, containing `element` as the only required\n // property. The `element` must be a container that will ultimately\n // contain an invisible ` ` created by Fine Uploader.\n // Optional properties of each object include `multiple`, `validation`,\n // and `folders`.\n extraButtons: [],\n\n // Depends on the session module. Used to query the server for an initial file list\n // during initialization and optionally after a `reset`.\n session: {\n endpoint: null,\n params: {},\n customHeaders: {},\n refreshOnReset: true\n },\n\n // Send parameters associated with an existing form along with the files\n form: {\n // Element ID, HTMLElement, or null\n element: \"qq-form\",\n\n // Overrides the base `autoUpload`, unless `element` is null.\n autoUpload: false,\n\n // true = upload files on form submission (and squelch submit event)\n interceptSubmit: true\n },\n\n // scale images client side, upload a new file for each scaled version\n scaling: {\n customResizer: null,\n\n // send the original file as well\n sendOriginal: true,\n\n // fox orientation for scaled images\n orient: true,\n\n // If null, scaled image type will match reference image type. This value will be referred to\n // for any size record that does not specific a type.\n defaultType: null,\n\n defaultQuality: 80,\n\n failureText: \"Failed to scale\",\n\n includeExif: false,\n\n // metadata about each requested scaled version\n sizes: []\n },\n\n workarounds: {\n iosEmptyVideos: true,\n ios8SafariUploads: true,\n ios8BrowserCrash: false\n }\n };\n\n // Replace any default options with user defined ones\n qq.extend(this._options, o, true);\n\n this._buttons = [];\n this._extraButtonSpecs = {};\n this._buttonIdsForFileIds = [];\n\n this._wrapCallbacks();\n this._disposeSupport = new qq.DisposeSupport();\n\n this._storedIds = [];\n this._autoRetries = [];\n this._retryTimeouts = [];\n this._preventRetries = [];\n this._thumbnailUrls = [];\n\n this._netUploadedOrQueued = 0;\n this._netUploaded = 0;\n this._uploadData = this._createUploadDataTracker();\n\n this._initFormSupportAndParams();\n\n this._customHeadersStore = this._createStore(this._options.request.customHeaders);\n this._deleteFileCustomHeadersStore = this._createStore(this._options.deleteFile.customHeaders);\n\n this._deleteFileParamsStore = this._createStore(this._options.deleteFile.params);\n\n this._endpointStore = this._createStore(this._options.request.endpoint);\n this._deleteFileEndpointStore = this._createStore(this._options.deleteFile.endpoint);\n\n this._handler = this._createUploadHandler();\n\n this._deleteHandler = qq.DeleteFileAjaxRequester && this._createDeleteHandler();\n\n if (this._options.button) {\n this._defaultButtonId = this._createUploadButton({\n element: this._options.button,\n title: this._options.text.fileInputTitle\n }).getButtonId();\n }\n\n this._generateExtraButtonSpecs();\n\n this._handleCameraAccess();\n\n if (this._options.paste.targetElement) {\n if (qq.PasteSupport) {\n this._pasteHandler = this._createPasteHandler();\n }\n else {\n this.log(\"Paste support module not found\", \"error\");\n }\n }\n\n this._options.warnBeforeUnload && this._preventLeaveInProgress();\n\n this._imageGenerator = qq.ImageGenerator && new qq.ImageGenerator(qq.bind(this.log, this));\n this._refreshSessionData();\n\n this._succeededSinceLastAllComplete = [];\n this._failedSinceLastAllComplete = [];\n\n this._scaler = (qq.Scaler && new qq.Scaler(this._options.scaling, qq.bind(this.log, this))) || {};\n if (this._scaler.enabled) {\n this._customNewFileHandler = qq.bind(this._scaler.handleNewFile, this._scaler);\n }\n\n if (qq.TotalProgress && qq.supportedFeatures.progressBar) {\n this._totalProgress = new qq.TotalProgress(\n qq.bind(this._onTotalProgress, this),\n\n function(id) {\n var entry = self._uploadData.retrieve({id: id});\n return (entry && entry.size) || 0;\n }\n );\n }\n\n this._currentItemLimit = this._options.validation.itemLimit;\n\n this._customResumeDataStore = this._createStore();\n };\n\n // Define the private & public API methods.\n qq.FineUploaderBasic.prototype = qq.basePublicApi;\n qq.extend(qq.FineUploaderBasic.prototype, qq.basePrivateApi);\n}());\n","/*globals qq, XDomainRequest*/\n/** Generic class for sending non-upload ajax requests and handling the associated responses **/\nqq.AjaxRequester = function(o) {\n \"use strict\";\n\n var log, shouldParamsBeInQueryString,\n queue = [],\n requestData = {},\n options = {\n acceptHeader: null,\n validMethods: [\"PATCH\", \"POST\", \"PUT\"],\n method: \"POST\",\n contentType: \"application/x-www-form-urlencoded\",\n maxConnections: 3,\n customHeaders: {},\n endpointStore: {},\n paramsStore: {},\n mandatedParams: {},\n allowXRequestedWithAndCacheControl: true,\n successfulResponseCodes: {\n DELETE: [200, 202, 204],\n PATCH: [200, 201, 202, 203, 204],\n POST: [200, 201, 202, 203, 204],\n PUT: [200, 201, 202, 203, 204],\n GET: [200]\n },\n cors: {\n expected: false,\n sendCredentials: false\n },\n log: function(str, level) {},\n onSend: function(id) {},\n onComplete: function(id, xhrOrXdr, isError) {},\n onProgress: null\n };\n\n qq.extend(options, o);\n log = options.log;\n\n if (qq.indexOf(options.validMethods, options.method) < 0) {\n throw new Error(\"'\" + options.method + \"' is not a supported method for this type of request!\");\n }\n\n // [Simple methods](http://www.w3.org/TR/cors/#simple-method)\n // are defined by the W3C in the CORS spec as a list of methods that, in part,\n // make a CORS request eligible to be exempt from preflighting.\n function isSimpleMethod() {\n return qq.indexOf([\"GET\", \"POST\", \"HEAD\"], options.method) >= 0;\n }\n\n // [Simple headers](http://www.w3.org/TR/cors/#simple-header)\n // are defined by the W3C in the CORS spec as a list of headers that, in part,\n // make a CORS request eligible to be exempt from preflighting.\n function containsNonSimpleHeaders(headers) {\n var containsNonSimple = false;\n\n qq.each(containsNonSimple, function(idx, header) {\n if (qq.indexOf([\"Accept\", \"Accept-Language\", \"Content-Language\", \"Content-Type\"], header) < 0) {\n containsNonSimple = true;\n return false;\n }\n });\n\n return containsNonSimple;\n }\n\n function isXdr(xhr) {\n //The `withCredentials` test is a commonly accepted way to determine if XHR supports CORS.\n return options.cors.expected && xhr.withCredentials === undefined;\n }\n\n // Returns either a new `XMLHttpRequest` or `XDomainRequest` instance.\n function getCorsAjaxTransport() {\n var xhrOrXdr;\n\n if (window.XMLHttpRequest || window.ActiveXObject) {\n xhrOrXdr = qq.createXhrInstance();\n\n if (xhrOrXdr.withCredentials === undefined) {\n xhrOrXdr = new XDomainRequest();\n // Workaround for XDR bug in IE9 - https://social.msdn.microsoft.com/Forums/ie/en-US/30ef3add-767c-4436-b8a9-f1ca19b4812e/ie9-rtm-xdomainrequest-issued-requests-may-abort-if-all-event-handlers-not-specified?forum=iewebdevelopment\n xhrOrXdr.onload = function() {};\n xhrOrXdr.onerror = function() {};\n xhrOrXdr.ontimeout = function() {};\n xhrOrXdr.onprogress = function() {};\n }\n }\n\n return xhrOrXdr;\n }\n\n // Returns either a new XHR/XDR instance, or an existing one for the associated `File` or `Blob`.\n function getXhrOrXdr(id, suppliedXhr) {\n var xhrOrXdr = requestData[id] && requestData[id].xhr;\n\n if (!xhrOrXdr) {\n if (suppliedXhr) {\n xhrOrXdr = suppliedXhr;\n }\n else {\n if (options.cors.expected) {\n xhrOrXdr = getCorsAjaxTransport();\n }\n else {\n xhrOrXdr = qq.createXhrInstance();\n }\n }\n\n requestData[id].xhr = xhrOrXdr;\n }\n\n return xhrOrXdr;\n }\n\n // Removes element from queue, sends next request\n function dequeue(id) {\n var i = qq.indexOf(queue, id),\n max = options.maxConnections,\n nextId;\n\n delete requestData[id];\n queue.splice(i, 1);\n\n if (queue.length >= max && i < max) {\n nextId = queue[max - 1];\n sendRequest(nextId);\n }\n }\n\n function onComplete(id, xdrError) {\n var xhr = getXhrOrXdr(id),\n method = options.method,\n isError = xdrError === true;\n\n dequeue(id);\n\n if (isError) {\n log(method + \" request for \" + id + \" has failed\", \"error\");\n }\n else if (!isXdr(xhr) && !isResponseSuccessful(xhr.status)) {\n isError = true;\n log(method + \" request for \" + id + \" has failed - response code \" + xhr.status, \"error\");\n }\n\n options.onComplete(id, xhr, isError);\n }\n\n function getParams(id) {\n var onDemandParams = requestData[id].additionalParams,\n mandatedParams = options.mandatedParams,\n params;\n\n if (options.paramsStore.get) {\n params = options.paramsStore.get(id);\n }\n\n if (onDemandParams) {\n qq.each(onDemandParams, function(name, val) {\n params = params || {};\n params[name] = val;\n });\n }\n\n if (mandatedParams) {\n qq.each(mandatedParams, function(name, val) {\n params = params || {};\n params[name] = val;\n });\n }\n\n return params;\n }\n\n function sendRequest(id, optXhr) {\n var xhr = getXhrOrXdr(id, optXhr),\n method = options.method,\n params = getParams(id),\n payload = requestData[id].payload,\n url;\n\n options.onSend(id);\n\n url = createUrl(id, params, requestData[id].additionalQueryParams);\n\n // XDR and XHR status detection APIs differ a bit.\n if (isXdr(xhr)) {\n xhr.onload = getXdrLoadHandler(id);\n xhr.onerror = getXdrErrorHandler(id);\n }\n else {\n xhr.onreadystatechange = getXhrReadyStateChangeHandler(id);\n }\n\n registerForUploadProgress(id);\n\n // The last parameter is assumed to be ignored if we are actually using `XDomainRequest`.\n xhr.open(method, url, true);\n\n // Instruct the transport to send cookies along with the CORS request,\n // unless we are using `XDomainRequest`, which is not capable of this.\n if (options.cors.expected && options.cors.sendCredentials && !isXdr(xhr)) {\n xhr.withCredentials = true;\n }\n\n setHeaders(id);\n\n log(\"Sending \" + method + \" request for \" + id);\n\n if (payload) {\n xhr.send(payload);\n }\n else if (shouldParamsBeInQueryString || !params) {\n xhr.send();\n }\n else if (params && options.contentType && options.contentType.toLowerCase().indexOf(\"application/x-www-form-urlencoded\") >= 0) {\n xhr.send(qq.obj2url(params, \"\"));\n }\n else if (params && options.contentType && options.contentType.toLowerCase().indexOf(\"application/json\") >= 0) {\n xhr.send(JSON.stringify(params));\n }\n else {\n xhr.send(params);\n }\n\n return xhr;\n }\n\n function createUrl(id, params, additionalQueryParams) {\n var endpoint = options.endpointStore.get(id),\n addToPath = requestData[id].addToPath;\n\n /*jshint -W116,-W041 */\n if (addToPath != undefined) {\n endpoint += \"/\" + addToPath;\n }\n\n if (shouldParamsBeInQueryString && params) {\n endpoint = qq.obj2url(params, endpoint);\n }\n\n if (additionalQueryParams) {\n endpoint = qq.obj2url(additionalQueryParams, endpoint);\n }\n\n return endpoint;\n }\n\n // Invoked by the UA to indicate a number of possible states that describe\n // a live `XMLHttpRequest` transport.\n function getXhrReadyStateChangeHandler(id) {\n return function() {\n if (getXhrOrXdr(id).readyState === 4) {\n onComplete(id);\n }\n };\n }\n\n function registerForUploadProgress(id) {\n var onProgress = options.onProgress;\n\n if (onProgress) {\n getXhrOrXdr(id).upload.onprogress = function(e) {\n if (e.lengthComputable) {\n onProgress(id, e.loaded, e.total);\n }\n };\n }\n }\n\n // This will be called by IE to indicate **success** for an associated\n // `XDomainRequest` transported request.\n function getXdrLoadHandler(id) {\n return function() {\n onComplete(id);\n };\n }\n\n // This will be called by IE to indicate **failure** for an associated\n // `XDomainRequest` transported request.\n function getXdrErrorHandler(id) {\n return function() {\n onComplete(id, true);\n };\n }\n\n function setHeaders(id) {\n var xhr = getXhrOrXdr(id),\n customHeaders = options.customHeaders,\n onDemandHeaders = requestData[id].additionalHeaders || {},\n method = options.method,\n allHeaders = {};\n\n // If XDomainRequest is being used, we can't set headers, so just ignore this block.\n if (!isXdr(xhr)) {\n options.acceptHeader && xhr.setRequestHeader(\"Accept\", options.acceptHeader);\n\n // Only attempt to add X-Requested-With & Cache-Control if permitted\n if (options.allowXRequestedWithAndCacheControl) {\n // Do not add X-Requested-With & Cache-Control if this is a cross-origin request\n // OR the cross-origin request contains a non-simple method or header.\n // This is done to ensure a preflight is not triggered exclusively based on the\n // addition of these 2 non-simple headers.\n if (!options.cors.expected || (!isSimpleMethod() || containsNonSimpleHeaders(customHeaders))) {\n xhr.setRequestHeader(\"X-Requested-With\", \"XMLHttpRequest\");\n xhr.setRequestHeader(\"Cache-Control\", \"no-cache\");\n }\n }\n\n if (options.contentType && (method === \"POST\" || method === \"PUT\")) {\n xhr.setRequestHeader(\"Content-Type\", options.contentType);\n }\n\n qq.extend(allHeaders, qq.isFunction(customHeaders) ? customHeaders(id) : customHeaders);\n qq.extend(allHeaders, onDemandHeaders);\n\n qq.each(allHeaders, function(name, val) {\n xhr.setRequestHeader(name, val);\n });\n }\n }\n\n function isResponseSuccessful(responseCode) {\n return qq.indexOf(options.successfulResponseCodes[options.method], responseCode) >= 0;\n }\n\n function prepareToSend(id, optXhr, addToPath, additionalParams, additionalQueryParams, additionalHeaders, payload) {\n requestData[id] = {\n addToPath: addToPath,\n additionalParams: additionalParams,\n additionalQueryParams: additionalQueryParams,\n additionalHeaders: additionalHeaders,\n payload: payload\n };\n\n var len = queue.push(id);\n\n // if too many active connections, wait...\n if (len <= options.maxConnections) {\n return sendRequest(id, optXhr);\n }\n }\n\n shouldParamsBeInQueryString = options.method === \"GET\" || options.method === \"DELETE\";\n\n qq.extend(this, {\n // Start the process of sending the request. The ID refers to the file associated with the request.\n initTransport: function(id) {\n var path, params, headers, payload, cacheBuster, additionalQueryParams;\n\n return {\n // Optionally specify the end of the endpoint path for the request.\n withPath: function(appendToPath) {\n path = appendToPath;\n return this;\n },\n\n // Optionally specify additional parameters to send along with the request.\n // These will be added to the query string for GET/DELETE requests or the payload\n // for POST/PUT requests. The Content-Type of the request will be used to determine\n // how these parameters should be formatted as well.\n withParams: function(additionalParams) {\n params = additionalParams;\n return this;\n },\n\n withQueryParams: function(_additionalQueryParams_) {\n additionalQueryParams = _additionalQueryParams_;\n return this;\n },\n\n // Optionally specify additional headers to send along with the request.\n withHeaders: function(additionalHeaders) {\n headers = additionalHeaders;\n return this;\n },\n\n // Optionally specify a payload/body for the request.\n withPayload: function(thePayload) {\n payload = thePayload;\n return this;\n },\n\n // Appends a cache buster (timestamp) to the request URL as a query parameter (only if GET or DELETE)\n withCacheBuster: function() {\n cacheBuster = true;\n return this;\n },\n\n // Send the constructed request.\n send: function(optXhr) {\n if (cacheBuster && qq.indexOf([\"GET\", \"DELETE\"], options.method) >= 0) {\n params.qqtimestamp = new Date().getTime();\n }\n\n return prepareToSend(id, optXhr, path, params, additionalQueryParams, headers, payload);\n }\n };\n },\n\n canceled: function(id) {\n dequeue(id);\n }\n });\n};\n","/* globals qq */\n/**\n * Common upload handler functions.\n *\n * @constructor\n */\nqq.UploadHandler = function(spec) {\n \"use strict\";\n\n var proxy = spec.proxy,\n fileState = {},\n onCancel = proxy.onCancel,\n getName = proxy.getName;\n\n qq.extend(this, {\n add: function(id, fileItem) {\n fileState[id] = fileItem;\n fileState[id].temp = {};\n },\n\n cancel: function(id) {\n var self = this,\n cancelFinalizationEffort = new qq.Promise(),\n onCancelRetVal = onCancel(id, getName(id), cancelFinalizationEffort);\n\n onCancelRetVal.then(function() {\n if (self.isValid(id)) {\n fileState[id].canceled = true;\n self.expunge(id);\n }\n cancelFinalizationEffort.success();\n });\n },\n\n expunge: function(id) {\n delete fileState[id];\n },\n\n getThirdPartyFileId: function(id) {\n return fileState[id].key;\n },\n\n isValid: function(id) {\n return fileState[id] !== undefined;\n },\n\n reset: function() {\n fileState = {};\n },\n\n _getFileState: function(id) {\n return fileState[id];\n },\n\n _setThirdPartyFileId: function(id, thirdPartyFileId) {\n fileState[id].key = thirdPartyFileId;\n },\n\n _wasCanceled: function(id) {\n return !!fileState[id].canceled;\n }\n });\n};\n","/*globals qq*/\n/**\n * Base upload handler module. Controls more specific handlers.\n *\n * @param o Options. Passed along to the specific handler submodule as well.\n * @param namespace [optional] Namespace for the specific handler.\n */\nqq.UploadHandlerController = function(o, namespace) {\n \"use strict\";\n\n var controller = this,\n chunkingPossible = false,\n concurrentChunkingPossible = false,\n chunking, preventRetryResponse, log, handler,\n\n options = {\n paramsStore: {},\n maxConnections: 3, // maximum number of concurrent uploads\n chunking: {\n enabled: false,\n multiple: {\n enabled: false\n }\n },\n log: function(str, level) {},\n onProgress: function(id, fileName, loaded, total) {},\n onComplete: function(id, fileName, response, xhr) {},\n onCancel: function(id, fileName) {},\n onUploadPrep: function(id) {}, // Called if non-trivial operations will be performed before onUpload\n onUpload: function(id, fileName) {},\n onUploadChunk: function(id, fileName, chunkData) {},\n onUploadChunkSuccess: function(id, chunkData, response, xhr) {},\n onAutoRetry: function(id, fileName, response, xhr) {},\n onResume: function(id, fileName, chunkData, customResumeData) {},\n onUuidChanged: function(id, newUuid) {},\n getName: function(id) {},\n setSize: function(id, newSize) {},\n isQueued: function(id) {},\n getIdsInProxyGroup: function(id) {},\n getIdsInBatch: function(id) {},\n isInProgress: function(id) {}\n },\n\n chunked = {\n // Called when each chunk has uploaded successfully\n done: function(id, chunkIdx, response, xhr) {\n var chunkData = handler._getChunkData(id, chunkIdx);\n\n handler._getFileState(id).attemptingResume = false;\n\n delete handler._getFileState(id).temp.chunkProgress[chunkIdx];\n handler._getFileState(id).loaded += chunkData.size;\n\n options.onUploadChunkSuccess(id, handler._getChunkDataForCallback(chunkData), response, xhr);\n },\n\n // Called when all chunks have been successfully uploaded and we want to ask the handler to perform any\n // logic associated with closing out the file, such as combining the chunks.\n finalize: function(id) {\n var size = options.getSize(id),\n name = options.getName(id);\n\n log(\"All chunks have been uploaded for \" + id + \" - finalizing....\");\n handler.finalizeChunks(id).then(\n function(response, xhr) {\n log(\"Finalize successful for \" + id);\n\n var normaizedResponse = upload.normalizeResponse(response, true);\n\n options.onProgress(id, name, size, size);\n handler._maybeDeletePersistedChunkData(id);\n upload.cleanup(id, normaizedResponse, xhr);\n },\n function(response, xhr) {\n var normalizedResponse = upload.normalizeResponse(response, false);\n\n log(\"Problem finalizing chunks for file ID \" + id + \" - \" + normalizedResponse.error, \"error\");\n\n if (\n normalizedResponse.reset ||\n (xhr && options.chunking.success.resetOnStatus.indexOf(xhr.status) >= 0)\n ) {\n chunked.reset(id);\n }\n\n if (!options.onAutoRetry(id, name, normalizedResponse, xhr)) {\n upload.cleanup(id, normalizedResponse, xhr);\n }\n }\n );\n },\n\n handleFailure: function(chunkIdx, id, response, xhr) {\n var name = options.getName(id);\n\n log(\"Chunked upload request failed for \" + id + \", chunk \" + chunkIdx);\n\n handler.clearCachedChunk(id, chunkIdx);\n\n var responseToReport = upload.normalizeResponse(response, false),\n inProgressIdx;\n\n if (responseToReport.reset) {\n chunked.reset(id);\n }\n else {\n var inProgressChunksArray = handler._getFileState(id).chunking.inProgress;\n\n inProgressIdx = inProgressChunksArray ? qq.indexOf(inProgressChunksArray, chunkIdx) : -1;\n if (inProgressIdx >= 0) {\n handler._getFileState(id).chunking.inProgress.splice(inProgressIdx, 1);\n handler._getFileState(id).chunking.remaining.unshift(chunkIdx);\n }\n }\n\n // We may have aborted all other in-progress chunks for this file due to a failure.\n // If so, ignore the failures associated with those aborts.\n if (!handler._getFileState(id).temp.ignoreFailure) {\n // If this chunk has failed, we want to ignore all other failures of currently in-progress\n // chunks since they will be explicitly aborted\n if (concurrentChunkingPossible) {\n handler._getFileState(id).temp.ignoreFailure = true;\n\n log(qq.format(\"Going to attempt to abort these chunks: {}. These are currently in-progress: {}.\", JSON.stringify(Object.keys(handler._getXhrs(id))), JSON.stringify(handler._getFileState(id).chunking.inProgress)));\n qq.each(handler._getXhrs(id), function(ckid, ckXhr) {\n log(qq.format(\"Attempting to abort file {}.{}. XHR readyState {}. \", id, ckid, ckXhr.readyState));\n ckXhr.abort();\n // Flag the transport, in case we are waiting for some other async operation\n // to complete before attempting to upload the chunk\n ckXhr._cancelled = true;\n });\n\n // We must indicate that all aborted chunks are no longer in progress\n handler.moveInProgressToRemaining(id);\n\n // Free up any connections used by these chunks, but don't allow any\n // other files to take up the connections (until we have exhausted all auto-retries)\n connectionManager.free(id, true);\n }\n\n if (!options.onAutoRetry(id, name, responseToReport, xhr)) {\n // If one chunk fails, abort all of the others to avoid odd race conditions that occur\n // if a chunk succeeds immediately after one fails before we have determined if the upload\n // is a failure or not.\n upload.cleanup(id, responseToReport, xhr);\n }\n }\n },\n\n hasMoreParts: function(id) {\n return !!handler._getFileState(id).chunking.remaining.length;\n },\n\n nextPart: function(id) {\n var nextIdx = handler._getFileState(id).chunking.remaining.shift();\n\n if (nextIdx >= handler._getTotalChunks(id)) {\n nextIdx = null;\n }\n\n return nextIdx;\n },\n\n reset: function(id) {\n log(\"Server or callback has ordered chunking effort to be restarted on next attempt for item ID \" + id, \"error\");\n\n handler._maybeDeletePersistedChunkData(id);\n handler.reevaluateChunking(id);\n handler._getFileState(id).loaded = 0;\n handler._getFileState(id).attemptingResume = false;\n },\n\n sendNext: function(id) {\n var size = options.getSize(id),\n name = options.getName(id),\n chunkIdx = chunked.nextPart(id),\n chunkData = handler._getChunkData(id, chunkIdx),\n fileState = handler._getFileState(id),\n resuming = fileState.attemptingResume,\n inProgressChunks = fileState.chunking.inProgress || [];\n\n if (fileState.loaded == null) {\n fileState.loaded = 0;\n }\n\n // Don't follow-through with the resume attempt if the integrator returns false from onResume\n if (resuming && options.onResume(id, name, chunkData, fileState.customResumeData) === false) {\n chunked.reset(id);\n chunkIdx = chunked.nextPart(id);\n chunkData = handler._getChunkData(id, chunkIdx);\n resuming = false;\n }\n\n // If all chunks have already uploaded successfully, we must be re-attempting the finalize step.\n if (chunkIdx == null && inProgressChunks.length === 0) {\n chunked.finalize(id);\n }\n\n // Send the next chunk\n else {\n inProgressChunks.push(chunkIdx);\n handler._getFileState(id).chunking.inProgress = inProgressChunks;\n\n if (concurrentChunkingPossible) {\n connectionManager.open(id, chunkIdx);\n }\n\n if (concurrentChunkingPossible && connectionManager.available() && handler._getFileState(id).chunking.remaining.length) {\n chunked.sendNext(id);\n }\n\n if (chunkData.blob.size === 0) {\n log(qq.format(\"Chunk {} for file {} will not be uploaded, zero sized chunk.\", chunkIdx, id), \"error\");\n chunked.handleFailure(chunkIdx, id, \"File is no longer available\", null);\n }\n\n var onUploadChunkPromise = options.onUploadChunk(id, name, handler._getChunkDataForCallback(chunkData));\n\n onUploadChunkPromise.then(\n function(requestOverrides) {\n if (!options.isInProgress(id)) {\n log(qq.format(\"Not sending chunked upload request for item {}.{} - no longer in progress.\", id, chunkIdx));\n }\n else {\n log(qq.format(\"Sending chunked upload request for item {}.{}, bytes {}-{} of {}.\", id, chunkIdx, chunkData.start + 1, chunkData.end, size));\n\n var uploadChunkData = {\n chunkIdx: chunkIdx,\n id: id,\n overrides: requestOverrides,\n resuming: resuming\n };\n\n handler.uploadChunk(uploadChunkData).then(\n // upload chunk success\n function success(response, xhr) {\n log(\"Chunked upload request succeeded for \" + id + \", chunk \" + chunkIdx);\n\n handler.clearCachedChunk(id, chunkIdx);\n\n var inProgressChunks = handler._getFileState(id).chunking.inProgress || [],\n responseToReport = upload.normalizeResponse(response, true),\n inProgressChunkIdx = qq.indexOf(inProgressChunks, chunkIdx);\n\n log(qq.format(\"Chunk {} for file {} uploaded successfully.\", chunkIdx, id));\n\n chunked.done(id, chunkIdx, responseToReport, xhr);\n\n if (inProgressChunkIdx >= 0) {\n inProgressChunks.splice(inProgressChunkIdx, 1);\n }\n\n handler._maybePersistChunkedState(id);\n\n if (!chunked.hasMoreParts(id) && inProgressChunks.length === 0) {\n chunked.finalize(id);\n }\n else if (chunked.hasMoreParts(id)) {\n chunked.sendNext(id);\n }\n else {\n log(qq.format(\"File ID {} has no more chunks to send and these chunk indexes are still marked as in-progress: {}\", id, JSON.stringify(inProgressChunks)));\n }\n },\n\n // upload chunk failure\n function failure(response, xhr) {\n chunked.handleFailure(chunkIdx, id, response, xhr);\n }\n )\n .done(function () {\n handler.clearXhr(id, chunkIdx);\n });\n }\n },\n\n function(error) {\n chunked.handleFailure(chunkIdx, id, error, null);\n }\n );\n }\n }\n },\n\n connectionManager = {\n _open: [],\n _openChunks: {},\n _waiting: [],\n\n available: function() {\n var max = options.maxConnections,\n openChunkEntriesCount = 0,\n openChunksCount = 0;\n\n qq.each(connectionManager._openChunks, function(fileId, openChunkIndexes) {\n openChunkEntriesCount++;\n openChunksCount += openChunkIndexes.length;\n });\n\n return max - (connectionManager._open.length - openChunkEntriesCount + openChunksCount);\n },\n\n /**\n * Removes element from queue, starts upload of next\n */\n free: function(id, dontAllowNext) {\n var allowNext = !dontAllowNext,\n waitingIndex = qq.indexOf(connectionManager._waiting, id),\n connectionsIndex = qq.indexOf(connectionManager._open, id),\n nextId;\n\n delete connectionManager._openChunks[id];\n\n if (upload.getProxyOrBlob(id) instanceof qq.BlobProxy) {\n log(\"Generated blob upload has ended for \" + id + \", disposing generated blob.\");\n delete handler._getFileState(id).file;\n }\n\n // If this file was not consuming a connection, it was just waiting, so remove it from the waiting array\n if (waitingIndex >= 0) {\n connectionManager._waiting.splice(waitingIndex, 1);\n }\n // If this file was consuming a connection, allow the next file to be uploaded\n else if (allowNext && connectionsIndex >= 0) {\n connectionManager._open.splice(connectionsIndex, 1);\n\n nextId = connectionManager._waiting.shift();\n if (nextId >= 0) {\n connectionManager._open.push(nextId);\n upload.start(nextId);\n }\n }\n },\n\n getWaitingOrConnected: function() {\n var waitingOrConnected = [];\n\n // Chunked files may have multiple connections open per chunk (if concurrent chunking is enabled)\n // We need to grab the file ID of any file that has at least one chunk consuming a connection.\n qq.each(connectionManager._openChunks, function(fileId, chunks) {\n if (chunks && chunks.length) {\n waitingOrConnected.push(parseInt(fileId));\n }\n });\n\n // For non-chunked files, only one connection will be consumed per file.\n // This is where we aggregate those file IDs.\n qq.each(connectionManager._open, function(idx, fileId) {\n if (!connectionManager._openChunks[fileId]) {\n waitingOrConnected.push(parseInt(fileId));\n }\n });\n\n // There may be files waiting for a connection.\n waitingOrConnected = waitingOrConnected.concat(connectionManager._waiting);\n\n return waitingOrConnected;\n },\n\n isUsingConnection: function(id) {\n return qq.indexOf(connectionManager._open, id) >= 0;\n },\n\n open: function(id, chunkIdx) {\n if (chunkIdx == null) {\n connectionManager._waiting.push(id);\n }\n\n if (connectionManager.available()) {\n if (chunkIdx == null) {\n connectionManager._waiting.pop();\n connectionManager._open.push(id);\n }\n else {\n (function() {\n var openChunksEntry = connectionManager._openChunks[id] || [];\n openChunksEntry.push(chunkIdx);\n connectionManager._openChunks[id] = openChunksEntry;\n }());\n }\n\n return true;\n }\n\n return false;\n },\n\n reset: function() {\n connectionManager._waiting = [];\n connectionManager._open = [];\n }\n },\n\n simple = {\n send: function(id, name) {\n var fileState = handler._getFileState(id);\n\n if (!fileState) {\n log(\"Ignoring send request as this upload may have been cancelled, File ID \" + id, \"warn\");\n return;\n }\n\n fileState.loaded = 0;\n\n log(\"Sending simple upload request for \" + id);\n handler.uploadFile(id).then(\n function(response, optXhr) {\n log(\"Simple upload request succeeded for \" + id);\n\n var responseToReport = upload.normalizeResponse(response, true),\n size = options.getSize(id);\n\n options.onProgress(id, name, size, size);\n upload.maybeNewUuid(id, responseToReport);\n upload.cleanup(id, responseToReport, optXhr);\n },\n\n function(response, optXhr) {\n log(\"Simple upload request failed for \" + id);\n\n var responseToReport = upload.normalizeResponse(response, false);\n\n if (!options.onAutoRetry(id, name, responseToReport, optXhr)) {\n upload.cleanup(id, responseToReport, optXhr);\n }\n }\n );\n }\n },\n\n upload = {\n cancel: function(id) {\n log(\"Cancelling \" + id);\n options.paramsStore.remove(id);\n connectionManager.free(id);\n },\n\n cleanup: function(id, response, optXhr) {\n var name = options.getName(id);\n\n options.onComplete(id, name, response, optXhr);\n\n if (handler._getFileState(id)) {\n handler._clearXhrs && handler._clearXhrs(id);\n }\n\n connectionManager.free(id);\n },\n\n // Returns a qq.BlobProxy, or an actual File/Blob if no proxy is involved, or undefined\n // if none of these are available for the ID\n getProxyOrBlob: function(id) {\n return (handler.getProxy && handler.getProxy(id)) ||\n (handler.getFile && handler.getFile(id));\n },\n\n initHandler: function() {\n var handlerType = namespace ? qq[namespace] : qq.traditional,\n handlerModuleSubtype = qq.supportedFeatures.ajaxUploading ? \"Xhr\" : \"Form\";\n\n handler = new handlerType[handlerModuleSubtype + \"UploadHandler\"](\n options,\n {\n getCustomResumeData: options.getCustomResumeData,\n getDataByUuid: options.getDataByUuid,\n getName: options.getName,\n getSize: options.getSize,\n getUuid: options.getUuid,\n log: log,\n onCancel: options.onCancel,\n onProgress: options.onProgress,\n onUuidChanged: options.onUuidChanged,\n onFinalizing: function(id) {\n options.setStatus(id, qq.status.UPLOAD_FINALIZING);\n }\n }\n );\n\n if (handler._removeExpiredChunkingRecords) {\n handler._removeExpiredChunkingRecords();\n }\n },\n\n isDeferredEligibleForUpload: function(id) {\n return options.isQueued(id);\n },\n\n // For Blobs that are part of a group of generated images, along with a reference image,\n // this will ensure the blobs in the group are uploaded in the order they were triggered,\n // even if some async processing must be completed on one or more Blobs first.\n maybeDefer: function(id, blob) {\n // If we don't have a file/blob yet & no file/blob exists for this item, request it,\n // and then submit the upload to the specific handler once the blob is available.\n // ASSUMPTION: This condition will only ever be true if XHR uploading is supported.\n if (blob && !handler.getFile(id) && blob instanceof qq.BlobProxy) {\n\n // Blob creation may take some time, so the caller may want to update the\n // UI to indicate that an operation is in progress, even before the actual\n // upload begins and an onUpload callback is invoked.\n options.onUploadPrep(id);\n\n log(\"Attempting to generate a blob on-demand for \" + id);\n blob.create().then(function(generatedBlob) {\n log(\"Generated an on-demand blob for \" + id);\n\n // Update record associated with this file by providing the generated Blob\n handler.updateBlob(id, generatedBlob);\n\n // Propagate the size for this generated Blob\n options.setSize(id, generatedBlob.size);\n\n // Order handler to recalculate chunking possibility, if applicable\n handler.reevaluateChunking(id);\n\n upload.maybeSendDeferredFiles(id);\n },\n\n // Blob could not be generated. Fail the upload & attempt to prevent retries. Also bubble error message.\n function(errorMessage) {\n var errorResponse = {};\n\n if (errorMessage) {\n errorResponse.error = errorMessage;\n }\n\n log(qq.format(\"Failed to generate blob for ID {}. Error message: {}.\", id, errorMessage), \"error\");\n\n options.onComplete(id, options.getName(id), qq.extend(errorResponse, preventRetryResponse), null);\n upload.maybeSendDeferredFiles(id);\n connectionManager.free(id);\n });\n }\n else {\n return upload.maybeSendDeferredFiles(id);\n }\n\n return false;\n },\n\n // Upload any grouped blobs, in the proper order, that are ready to be uploaded\n maybeSendDeferredFiles: function(id) {\n var idsInGroup = options.getIdsInProxyGroup(id),\n uploadedThisId = false;\n\n if (idsInGroup && idsInGroup.length) {\n log(\"Maybe ready to upload proxy group file \" + id);\n\n qq.each(idsInGroup, function(idx, idInGroup) {\n if (upload.isDeferredEligibleForUpload(idInGroup) && !!handler.getFile(idInGroup)) {\n uploadedThisId = idInGroup === id;\n upload.now(idInGroup);\n }\n else if (upload.isDeferredEligibleForUpload(idInGroup)) {\n return false;\n }\n });\n }\n else {\n uploadedThisId = true;\n upload.now(id);\n }\n\n return uploadedThisId;\n },\n\n maybeNewUuid: function(id, response) {\n if (response.newUuid !== undefined) {\n options.onUuidChanged(id, response.newUuid);\n }\n },\n\n // The response coming from handler implementations may be in various formats.\n // Instead of hoping a promise nested 5 levels deep will always return an object\n // as its first param, let's just normalize the response here.\n normalizeResponse: function(originalResponse, successful) {\n var response = originalResponse;\n\n // The passed \"response\" param may not be a response at all.\n // It could be a string, detailing the error, for example.\n if (!qq.isObject(originalResponse)) {\n response = {};\n\n if (qq.isString(originalResponse) && !successful) {\n response.error = originalResponse;\n }\n }\n\n response.success = successful;\n\n return response;\n },\n\n now: function(id) {\n var name = options.getName(id);\n\n if (!controller.isValid(id)) {\n throw new qq.Error(id + \" is not a valid file ID to upload!\");\n }\n\n options.onUpload(id, name).then(\n function(response) {\n if (response && response.pause) {\n options.setStatus(id, qq.status.PAUSED);\n handler.pause(id);\n connectionManager.free(id);\n }\n else {\n if (chunkingPossible && handler._shouldChunkThisFile(id)) {\n chunked.sendNext(id);\n }\n else {\n simple.send(id, name);\n }\n }\n },\n\n function(error) {\n error = error || {};\n\n log(id + \" upload start aborted due to rejected onUpload Promise - details: \" + error, \"error\");\n\n if (!options.onAutoRetry(id, name, error.responseJSON || {})) {\n var response = upload.normalizeResponse(error.responseJSON, false);\n upload.cleanup(id, response);\n }\n }\n );\n },\n\n start: function(id) {\n var blobToUpload = upload.getProxyOrBlob(id);\n\n if (blobToUpload) {\n return upload.maybeDefer(id, blobToUpload);\n }\n else {\n upload.now(id);\n return true;\n }\n }\n };\n\n qq.extend(this, {\n /**\n * Adds file or file input to the queue\n **/\n add: function(id, file) {\n handler.add.apply(this, arguments);\n },\n\n /**\n * Sends the file identified by id\n */\n upload: function(id) {\n if (connectionManager.open(id)) {\n return upload.start(id);\n }\n return false;\n },\n\n retry: function(id) {\n // On retry, if concurrent chunking has been enabled, we may have aborted all other in-progress chunks\n // for a file when encountering a failed chunk upload. We then signaled the controller to ignore\n // all failures associated with these aborts. We are now retrying, so we don't want to ignore\n // any more failures at this point.\n if (concurrentChunkingPossible) {\n handler._getFileState(id).temp.ignoreFailure = false;\n }\n\n // If we are attempting to retry a file that is already consuming a connection, this is likely an auto-retry.\n // Just go ahead and ask the handler to upload again.\n if (connectionManager.isUsingConnection(id)) {\n return upload.start(id);\n }\n\n // If we are attempting to retry a file that is not currently consuming a connection,\n // this is likely a manual retry attempt. We will need to ensure a connection is available\n // before the retry commences.\n else {\n return controller.upload(id);\n }\n },\n\n /**\n * Cancels file upload by id\n */\n cancel: function(id) {\n var cancelRetVal = handler.cancel(id);\n\n if (qq.isGenericPromise(cancelRetVal)) {\n cancelRetVal.then(function() {\n upload.cancel(id);\n });\n }\n else if (cancelRetVal !== false) {\n upload.cancel(id);\n }\n },\n\n /**\n * Cancels all queued or in-progress uploads\n */\n cancelAll: function() {\n var waitingOrConnected = connectionManager.getWaitingOrConnected(),\n i;\n\n // ensure files are cancelled in reverse order which they were added\n // to avoid a flash of time where a queued file begins to upload before it is canceled\n if (waitingOrConnected.length) {\n for (i = waitingOrConnected.length - 1; i >= 0; i--) {\n controller.cancel(waitingOrConnected[i]);\n }\n }\n\n connectionManager.reset();\n },\n\n // Returns a File, Blob, or the Blob/File for the reference/parent file if the targeted blob is a proxy.\n // Undefined if no file record is available.\n getFile: function(id) {\n if (handler.getProxy && handler.getProxy(id)) {\n return handler.getProxy(id).referenceBlob;\n }\n\n return handler.getFile && handler.getFile(id);\n },\n\n // Returns true if the Blob associated with the ID is related to a proxy s\n isProxied: function(id) {\n return !!(handler.getProxy && handler.getProxy(id));\n },\n\n getInput: function(id) {\n if (handler.getInput) {\n return handler.getInput(id);\n }\n },\n\n reset: function() {\n log(\"Resetting upload handler\");\n controller.cancelAll();\n connectionManager.reset();\n handler.reset();\n },\n\n expunge: function(id) {\n if (controller.isValid(id)) {\n return handler.expunge(id);\n }\n },\n\n /**\n * Determine if the file exists.\n */\n isValid: function(id) {\n return handler.isValid(id);\n },\n\n hasResumeRecord: function(id) {\n var key = handler.isValid(id) &&\n handler._getLocalStorageId &&\n handler._getLocalStorageId(id);\n\n if (key) {\n return !!localStorage.getItem(key);\n }\n\n return false;\n },\n\n getResumableFilesData: function() {\n if (handler.getResumableFilesData) {\n return handler.getResumableFilesData();\n }\n return [];\n },\n\n /**\n * This may or may not be implemented, depending on the handler. For handlers where a third-party ID is\n * available (such as the \"key\" for Amazon S3), this will return that value. Otherwise, the return value\n * will be undefined.\n *\n * @param id Internal file ID\n * @returns {*} Some identifier used by a 3rd-party service involved in the upload process\n */\n getThirdPartyFileId: function(id) {\n if (controller.isValid(id)) {\n return handler.getThirdPartyFileId(id);\n }\n },\n\n /**\n * Attempts to pause the associated upload if the specific handler supports this and the file is \"valid\".\n * @param id ID of the upload/file to pause\n * @returns {boolean} true if the upload was paused\n */\n pause: function(id) {\n if (controller.isResumable(id) && handler.pause && controller.isValid(id) && handler.pause(id)) {\n connectionManager.free(id);\n handler.moveInProgressToRemaining(id);\n return true;\n }\n return false;\n },\n\n isAttemptingResume: function(id) {\n return !!handler.isAttemptingResume && handler.isAttemptingResume(id);\n },\n\n // True if the file is eligible for pause/resume.\n isResumable: function(id) {\n return !!handler.isResumable && handler.isResumable(id);\n }\n });\n\n qq.extend(options, o);\n log = options.log;\n chunkingPossible = options.chunking.enabled && qq.supportedFeatures.chunking;\n concurrentChunkingPossible = chunkingPossible && options.chunking.concurrent.enabled;\n\n preventRetryResponse = (function() {\n var response = {};\n\n response[options.preventRetryParam] = true;\n\n return response;\n }());\n\n upload.initHandler();\n};\n","/*globals qq */\n/*jshint -W117 */\nqq.WindowReceiveMessage = function(o) {\n \"use strict\";\n\n var options = {\n log: function(message, level) {}\n },\n callbackWrapperDetachers = {};\n\n qq.extend(options, o);\n\n qq.extend(this, {\n receiveMessage: function(id, callback) {\n var onMessageCallbackWrapper = function(event) {\n callback(event.data);\n };\n\n if (window.postMessage) {\n callbackWrapperDetachers[id] = qq(window).attach(\"message\", onMessageCallbackWrapper);\n }\n else {\n log(\"iframe message passing not supported in this browser!\", \"error\");\n }\n },\n\n stopReceivingMessages: function(id) {\n if (window.postMessage) {\n var detacher = callbackWrapperDetachers[id];\n if (detacher) {\n detacher();\n }\n }\n }\n });\n};\n","/* globals qq */\n/**\n * Common APIs exposed to creators of upload via form/iframe handlers. This is reused and possibly overridden\n * in some cases by specific form upload handlers.\n *\n * @constructor\n */\nqq.FormUploadHandler = function(spec) {\n \"use strict\";\n\n var options = spec.options,\n handler = this,\n proxy = spec.proxy,\n formHandlerInstanceId = qq.getUniqueId(),\n onloadCallbacks = {},\n detachLoadEvents = {},\n postMessageCallbackTimers = {},\n isCors = options.isCors,\n inputName = options.inputName,\n getUuid = proxy.getUuid,\n log = proxy.log,\n corsMessageReceiver = new qq.WindowReceiveMessage({log: log});\n\n /**\n * Remove any trace of the file from the handler.\n *\n * @param id ID of the associated file\n */\n function expungeFile(id) {\n delete detachLoadEvents[id];\n\n // If we are dealing with CORS, we might still be waiting for a response from a loaded iframe.\n // In that case, terminate the timer waiting for a message from the loaded iframe\n // and stop listening for any more messages coming from this iframe.\n if (isCors) {\n clearTimeout(postMessageCallbackTimers[id]);\n delete postMessageCallbackTimers[id];\n corsMessageReceiver.stopReceivingMessages(id);\n }\n\n var iframe = document.getElementById(handler._getIframeName(id));\n if (iframe) {\n // To cancel request set src to something else. We use src=\"javascript:false;\"\n // because it doesn't trigger ie6 prompt on https\n /* jshint scripturl:true */\n iframe.setAttribute(\"src\", \"javascript:false;\");\n\n qq(iframe).remove();\n }\n }\n\n /**\n * @param iframeName `document`-unique Name of the associated iframe\n * @returns {*} ID of the associated file\n */\n function getFileIdForIframeName(iframeName) {\n return iframeName.split(\"_\")[0];\n }\n\n /**\n * Generates an iframe to be used as a target for upload-related form submits. This also adds the iframe\n * to the current `document`. Note that the iframe is hidden from view.\n *\n * @param name Name of the iframe.\n * @returns {HTMLIFrameElement} The created iframe\n */\n function initIframeForUpload(name) {\n var iframe = qq.toElement(\"\");\n\n iframe.setAttribute(\"id\", name);\n\n iframe.style.display = \"none\";\n document.body.appendChild(iframe);\n\n return iframe;\n }\n\n /**\n * If we are in CORS mode, we must listen for messages (containing the server response) from the associated\n * iframe, since we cannot directly parse the content of the iframe due to cross-origin restrictions.\n *\n * @param iframe Listen for messages on this iframe.\n * @param callback Invoke this callback with the message from the iframe.\n */\n function registerPostMessageCallback(iframe, callback) {\n var iframeName = iframe.id,\n fileId = getFileIdForIframeName(iframeName),\n uuid = getUuid(fileId);\n\n onloadCallbacks[uuid] = callback;\n\n // When the iframe has loaded (after the server responds to an upload request)\n // declare the attempt a failure if we don't receive a valid message shortly after the response comes in.\n detachLoadEvents[fileId] = qq(iframe).attach(\"load\", function() {\n if (handler.getInput(fileId)) {\n log(\"Received iframe load event for CORS upload request (iframe name \" + iframeName + \")\");\n\n postMessageCallbackTimers[iframeName] = setTimeout(function() {\n var errorMessage = \"No valid message received from loaded iframe for iframe name \" + iframeName;\n log(errorMessage, \"error\");\n callback({\n error: errorMessage\n });\n }, 1000);\n }\n });\n\n // Listen for messages coming from this iframe. When a message has been received, cancel the timer\n // that declares the upload a failure if a message is not received within a reasonable amount of time.\n corsMessageReceiver.receiveMessage(iframeName, function(message) {\n log(\"Received the following window message: '\" + message + \"'\");\n var fileId = getFileIdForIframeName(iframeName),\n response = handler._parseJsonResponse(message),\n uuid = response.uuid,\n onloadCallback;\n\n if (uuid && onloadCallbacks[uuid]) {\n log(\"Handling response for iframe name \" + iframeName);\n clearTimeout(postMessageCallbackTimers[iframeName]);\n delete postMessageCallbackTimers[iframeName];\n\n handler._detachLoadEvent(iframeName);\n\n onloadCallback = onloadCallbacks[uuid];\n\n delete onloadCallbacks[uuid];\n corsMessageReceiver.stopReceivingMessages(iframeName);\n onloadCallback(response);\n }\n else if (!uuid) {\n log(\"'\" + message + \"' does not contain a UUID - ignoring.\");\n }\n });\n }\n\n qq.extend(this, new qq.UploadHandler(spec));\n\n qq.override(this, function(super_) {\n return {\n /**\n * Adds File or Blob to the queue\n **/\n add: function(id, fileInput) {\n super_.add(id, {input: fileInput});\n\n fileInput.setAttribute(\"name\", inputName);\n\n // remove file input from DOM\n if (fileInput.parentNode) {\n qq(fileInput).remove();\n }\n },\n\n expunge: function(id) {\n expungeFile(id);\n super_.expunge(id);\n },\n\n isValid: function(id) {\n return super_.isValid(id) &&\n handler._getFileState(id).input !== undefined;\n }\n };\n });\n\n qq.extend(this, {\n getInput: function(id) {\n return handler._getFileState(id).input;\n },\n\n /**\n * This function either delegates to a more specific message handler if CORS is involved,\n * or simply registers a callback when the iframe has been loaded that invokes the passed callback\n * after determining if the content of the iframe is accessible.\n *\n * @param iframe Associated iframe\n * @param callback Callback to invoke after we have determined if the iframe content is accessible.\n */\n _attachLoadEvent: function(iframe, callback) {\n /*jslint eqeq: true*/\n var responseDescriptor;\n\n if (isCors) {\n registerPostMessageCallback(iframe, callback);\n }\n else {\n detachLoadEvents[iframe.id] = qq(iframe).attach(\"load\", function() {\n log(\"Received response for \" + iframe.id);\n\n // when we remove iframe from dom\n // the request stops, but in IE load\n // event fires\n if (!iframe.parentNode) {\n return;\n }\n\n try {\n // fixing Opera 10.53\n if (iframe.contentDocument &&\n iframe.contentDocument.body &&\n iframe.contentDocument.body.innerHTML == \"false\") {\n // In Opera event is fired second time\n // when body.innerHTML changed from false\n // to server response approx. after 1 sec\n // when we upload file with iframe\n return;\n }\n }\n catch (error) {\n //IE may throw an \"access is denied\" error when attempting to access contentDocument on the iframe in some cases\n log(\"Error when attempting to access iframe during handling of upload response (\" + error.message + \")\", \"error\");\n responseDescriptor = {success: false};\n }\n\n callback(responseDescriptor);\n });\n }\n },\n\n /**\n * Creates an iframe with a specific document-unique name.\n *\n * @param id ID of the associated file\n * @returns {HTMLIFrameElement}\n */\n _createIframe: function(id) {\n var iframeName = handler._getIframeName(id);\n\n return initIframeForUpload(iframeName);\n },\n\n /**\n * Called when we are no longer interested in being notified when an iframe has loaded.\n *\n * @param id Associated file ID\n */\n _detachLoadEvent: function(id) {\n if (detachLoadEvents[id] !== undefined) {\n detachLoadEvents[id]();\n delete detachLoadEvents[id];\n }\n },\n\n /**\n * @param fileId ID of the associated file\n * @returns {string} The `document`-unique name of the iframe\n */\n _getIframeName: function(fileId) {\n return fileId + \"_\" + formHandlerInstanceId;\n },\n\n /**\n * Generates a form element and appends it to the `document`. When the form is submitted, a specific iframe is targeted.\n * The name of the iframe is passed in as a property of the spec parameter, and must be unique in the `document`. Note\n * that the form is hidden from view.\n *\n * @param spec An object containing various properties to be used when constructing the form. Required properties are\n * currently: `method`, `endpoint`, `params`, `paramsInBody`, and `targetName`.\n * @returns {HTMLFormElement} The created form\n */\n _initFormForUpload: function(spec) {\n var method = spec.method,\n endpoint = spec.endpoint,\n params = spec.params,\n paramsInBody = spec.paramsInBody,\n targetName = spec.targetName,\n form = qq.toElement(\"\"),\n url = endpoint;\n\n if (paramsInBody) {\n qq.obj2Inputs(params, form);\n }\n else {\n url = qq.obj2url(params, endpoint);\n }\n\n form.setAttribute(\"action\", url);\n form.setAttribute(\"target\", targetName);\n form.style.display = \"none\";\n document.body.appendChild(form);\n\n return form;\n },\n\n /**\n * @param innerHtmlOrMessage JSON message\n * @returns {*} The parsed response, or an empty object if the response could not be parsed\n */\n _parseJsonResponse: function(innerHtmlOrMessage) {\n var response = {};\n\n try {\n response = qq.parseJson(innerHtmlOrMessage);\n }\n catch (error) {\n log(\"Error when attempting to parse iframe upload response (\" + error.message + \")\", \"error\");\n }\n\n return response;\n }\n });\n};\n","/* globals qq */\n/**\n * Common API exposed to creators of XHR handlers. This is reused and possibly overriding in some cases by specific\n * XHR upload handlers.\n *\n * @constructor\n */\nqq.XhrUploadHandler = function(spec) {\n \"use strict\";\n\n var handler = this,\n namespace = spec.options.namespace,\n proxy = spec.proxy,\n chunking = spec.options.chunking,\n getChunkSize = function(id) {\n var fileState = handler._getFileState(id);\n\n if (fileState.chunkSize) {\n return fileState.chunkSize;\n }\n\n else {\n var chunkSize = chunking.partSize;\n\n if (qq.isFunction(chunkSize)) {\n chunkSize = chunkSize(id, getSize(id));\n }\n\n fileState.chunkSize = chunkSize;\n return chunkSize;\n }\n },\n resume = spec.options.resume,\n chunkFiles = chunking && spec.options.chunking.enabled && qq.supportedFeatures.chunking,\n resumeEnabled = resume && spec.options.resume.enabled && chunkFiles && qq.supportedFeatures.resume,\n getName = proxy.getName,\n getSize = proxy.getSize,\n getUuid = proxy.getUuid,\n getEndpoint = proxy.getEndpoint,\n getDataByUuid = proxy.getDataByUuid,\n onUuidChanged = proxy.onUuidChanged,\n onProgress = proxy.onProgress,\n log = proxy.log,\n getCustomResumeData = proxy.getCustomResumeData;\n\n function abort(id) {\n qq.each(handler._getXhrs(id), function(xhrId, xhr) {\n var ajaxRequester = handler._getAjaxRequester(id, xhrId);\n\n xhr.onreadystatechange = null;\n xhr.upload.onprogress = null;\n xhr.abort();\n ajaxRequester && ajaxRequester.canceled && ajaxRequester.canceled(id);\n });\n }\n\n qq.extend(this, new qq.UploadHandler(spec));\n\n qq.override(this, function(super_) {\n return {\n /**\n * Adds File or Blob to the queue\n **/\n add: function(id, blobOrProxy) {\n if (qq.isFile(blobOrProxy) || qq.isBlob(blobOrProxy)) {\n super_.add(id, {file: blobOrProxy});\n }\n else if (blobOrProxy instanceof qq.BlobProxy) {\n super_.add(id, {proxy: blobOrProxy});\n }\n else {\n throw new Error(\"Passed obj is not a File, Blob, or proxy\");\n }\n\n handler._initTempState(id);\n resumeEnabled && handler._maybePrepareForResume(id);\n },\n\n expunge: function(id) {\n abort(id);\n handler._maybeDeletePersistedChunkData(id);\n handler._clearXhrs(id);\n super_.expunge(id);\n }\n };\n });\n\n qq.extend(this, {\n // Clear the cached chunk `Blob` after we are done with it, just in case the `Blob` bytes are stored in memory.\n clearCachedChunk: function(id, chunkIdx) {\n var fileState = handler._getFileState(id);\n\n if (fileState) {\n delete fileState.temp.cachedChunks[chunkIdx];\n }\n },\n\n clearXhr: function(id, chunkIdx) {\n var tempState = handler._getFileState(id).temp;\n\n if (tempState.xhrs) {\n delete tempState.xhrs[chunkIdx];\n }\n if (tempState.ajaxRequesters) {\n delete tempState.ajaxRequesters[chunkIdx];\n }\n },\n\n // Called when all chunks have been successfully uploaded. Expected promissory return type.\n // This defines the default behavior if nothing further is required when all chunks have been uploaded.\n finalizeChunks: function(id, responseParser) {\n var lastChunkIdx = handler._getTotalChunks(id) - 1,\n xhr = handler._getXhr(id, lastChunkIdx);\n\n if (responseParser) {\n return new qq.Promise().success(responseParser(xhr), xhr);\n }\n\n return new qq.Promise().success({}, xhr);\n },\n\n getFile: function(id) {\n return handler.isValid(id) && handler._getFileState(id).file;\n },\n\n getProxy: function(id) {\n return handler.isValid(id) && handler._getFileState(id).proxy;\n },\n\n /**\n * @returns {Array} Array of objects containing properties useful to integrators\n * when it is important to determine which files are potentially resumable.\n */\n getResumableFilesData: function() {\n var resumableFilesData = [];\n\n handler._iterateResumeRecords(function(key, uploadData) {\n handler.moveInProgressToRemaining(null, uploadData.chunking.inProgress, uploadData.chunking.remaining);\n\n var data = {\n name: uploadData.name,\n remaining: uploadData.chunking.remaining,\n size: uploadData.size,\n uuid: uploadData.uuid\n };\n\n if (uploadData.key) {\n data.key = uploadData.key;\n }\n\n if (uploadData.customResumeData) {\n data.customResumeData = uploadData.customResumeData;\n }\n\n resumableFilesData.push(data);\n });\n\n return resumableFilesData;\n },\n\n isAttemptingResume: function(id) {\n return handler._getFileState(id).attemptingResume;\n },\n\n isResumable: function(id) {\n return !!chunking && handler.isValid(id) &&\n !handler._getFileState(id).notResumable;\n },\n\n moveInProgressToRemaining: function(id, optInProgress, optRemaining) {\n var fileState = handler._getFileState(id) || {},\n chunkingState = fileState.chunking || {},\n inProgress = optInProgress || chunkingState.inProgress,\n remaining = optRemaining || chunkingState.remaining;\n\n if (inProgress) {\n log(qq.format(\"Moving these chunks from in-progress {}, to remaining.\", JSON.stringify(inProgress)));\n inProgress.reverse();\n qq.each(inProgress, function(idx, chunkIdx) {\n remaining.unshift(chunkIdx);\n });\n inProgress.length = 0;\n }\n },\n\n pause: function(id) {\n if (handler.isValid(id)) {\n log(qq.format(\"Aborting XHR upload for {} '{}' due to pause instruction.\", id, getName(id)));\n handler._getFileState(id).paused = true;\n abort(id);\n return true;\n }\n },\n\n reevaluateChunking: function(id) {\n if (chunking && handler.isValid(id)) {\n var state = handler._getFileState(id),\n totalChunks,\n i;\n\n delete state.chunking;\n\n state.chunking = {};\n totalChunks = handler._getTotalChunks(id);\n if (totalChunks > 1 || chunking.mandatory) {\n state.chunking.enabled = true;\n state.chunking.parts = totalChunks;\n state.chunking.remaining = [];\n\n for (i = 0; i < totalChunks; i++) {\n state.chunking.remaining.push(i);\n }\n\n handler._initTempState(id);\n }\n else {\n state.chunking.enabled = false;\n }\n }\n },\n\n updateBlob: function(id, newBlob) {\n if (handler.isValid(id)) {\n handler._getFileState(id).file = newBlob;\n }\n },\n\n _clearXhrs: function(id) {\n var tempState = handler._getFileState(id).temp;\n\n qq.each(tempState.ajaxRequesters, function(chunkId) {\n delete tempState.ajaxRequesters[chunkId];\n });\n\n qq.each(tempState.xhrs, function(chunkId) {\n delete tempState.xhrs[chunkId];\n });\n },\n\n /**\n * Creates an XHR instance for this file and stores it in the fileState.\n *\n * @param id File ID\n * @param optChunkIdx The chunk index associated with this XHR, if applicable\n * @returns {XMLHttpRequest}\n */\n _createXhr: function(id, optChunkIdx) {\n return handler._registerXhr(id, optChunkIdx, qq.createXhrInstance());\n },\n\n _getAjaxRequester: function(id, optChunkIdx) {\n var chunkIdx = optChunkIdx == null ? -1 : optChunkIdx;\n return handler._getFileState(id).temp.ajaxRequesters[chunkIdx];\n },\n\n _getChunkData: function(id, chunkIndex) {\n var chunkSize = getChunkSize(id),\n fileSize = getSize(id),\n fileOrBlob = handler.getFile(id),\n startBytes = chunkSize * chunkIndex,\n endBytes = startBytes + chunkSize >= fileSize ? fileSize : startBytes + chunkSize,\n totalChunks = handler._getTotalChunks(id),\n cachedChunks = this._getFileState(id).temp.cachedChunks,\n\n // To work around a Webkit GC bug, we must keep each chunk `Blob` in scope until we are done with it.\n // See https://github.com/FineUploader/fine-uploader/issues/937#issuecomment-41418760\n blob = cachedChunks[chunkIndex] || qq.sliceBlob(fileOrBlob, startBytes, endBytes);\n\n cachedChunks[chunkIndex] = blob;\n\n return {\n part: chunkIndex,\n start: startBytes,\n end: endBytes,\n count: totalChunks,\n blob: blob,\n size: endBytes - startBytes\n };\n },\n\n _getChunkDataForCallback: function(chunkData) {\n return {\n partIndex: chunkData.part,\n startByte: chunkData.start + 1,\n endByte: chunkData.end,\n totalParts: chunkData.count\n };\n },\n\n /**\n * @param id File ID\n * @returns {string} Identifier for this item that may appear in the browser's local storage\n */\n _getLocalStorageId: function(id) {\n var formatVersion = \"5.0\",\n name = getName(id),\n size = getSize(id),\n chunkSize = getChunkSize(id),\n endpoint = getEndpoint(id),\n customKeys = resume.customKeys(id),\n localStorageId = qq.format(\"qq{}resume{}-{}-{}-{}-{}\", namespace, formatVersion, name, size, chunkSize, endpoint);\n\n customKeys.forEach(function(key) {\n localStorageId += \"-\" + key;\n });\n\n return localStorageId;\n },\n\n _getMimeType: function(id) {\n return handler.getFile(id).type;\n },\n\n _getPersistableData: function(id) {\n return handler._getFileState(id).chunking;\n },\n\n /**\n * @param id ID of the associated file\n * @returns {number} Number of parts this file can be divided into, or undefined if chunking is not supported in this UA\n */\n _getTotalChunks: function(id) {\n if (chunking) {\n var fileSize = getSize(id),\n chunkSize = getChunkSize(id);\n\n return Math.ceil(fileSize / chunkSize);\n }\n },\n\n _getXhr: function(id, optChunkIdx) {\n var chunkIdx = optChunkIdx == null ? -1 : optChunkIdx;\n return handler._getFileState(id).temp.xhrs[chunkIdx];\n },\n\n _getXhrs: function(id) {\n return handler._getFileState(id).temp.xhrs;\n },\n\n // Iterates through all XHR handler-created resume records (in local storage),\n // invoking the passed callback and passing in the key and value of each local storage record.\n _iterateResumeRecords: function(callback) {\n if (resumeEnabled) {\n qq.each(localStorage, function(key, item) {\n if (key.indexOf(qq.format(\"qq{}resume\", namespace)) === 0) {\n var uploadData = JSON.parse(item);\n callback(key, uploadData);\n }\n });\n }\n },\n\n _initTempState: function(id) {\n handler._getFileState(id).temp = {\n ajaxRequesters: {},\n chunkProgress: {},\n xhrs: {},\n cachedChunks: {}\n };\n },\n\n _markNotResumable: function(id) {\n handler._getFileState(id).notResumable = true;\n },\n\n // Removes a chunked upload record from local storage, if possible.\n // Returns true if the item was removed, false otherwise.\n _maybeDeletePersistedChunkData: function(id) {\n var localStorageId;\n\n if (resumeEnabled && handler.isResumable(id)) {\n localStorageId = handler._getLocalStorageId(id);\n\n if (localStorageId && localStorage.getItem(localStorageId)) {\n localStorage.removeItem(localStorageId);\n return true;\n }\n }\n\n return false;\n },\n\n // If this is a resumable upload, grab the relevant data from storage and items in memory that track this upload\n // so we can pick up from where we left off.\n _maybePrepareForResume: function(id) {\n var state = handler._getFileState(id),\n localStorageId, persistedData;\n\n // Resume is enabled and possible and this is the first time we've tried to upload this file in this session,\n // so prepare for a resume attempt.\n if (resumeEnabled && state.key === undefined) {\n localStorageId = handler._getLocalStorageId(id);\n persistedData = localStorage.getItem(localStorageId);\n\n // If we found this item in local storage, maybe we should resume it.\n if (persistedData) {\n persistedData = JSON.parse(persistedData);\n\n // If we found a resume record but we have already handled this file in this session,\n // don't try to resume it & ensure we don't persist future check data\n if (getDataByUuid(persistedData.uuid)) {\n handler._markNotResumable(id);\n }\n else {\n log(qq.format(\"Identified file with ID {} and name of {} as resumable.\", id, getName(id)));\n\n onUuidChanged(id, persistedData.uuid);\n\n state.key = persistedData.key;\n state.chunking = persistedData.chunking;\n state.loaded = persistedData.loaded;\n state.customResumeData = persistedData.customResumeData;\n state.attemptingResume = true;\n\n handler.moveInProgressToRemaining(id);\n }\n }\n }\n },\n\n // Persist any data needed to resume this upload in a new session.\n _maybePersistChunkedState: function(id) {\n var state = handler._getFileState(id),\n localStorageId, persistedData;\n\n // If local storage isn't supported by the browser, or if resume isn't enabled or possible, give up\n if (resumeEnabled && handler.isResumable(id)) {\n var customResumeData = getCustomResumeData(id);\n\n localStorageId = handler._getLocalStorageId(id);\n\n persistedData = {\n name: getName(id),\n size: getSize(id),\n uuid: getUuid(id),\n key: state.key,\n chunking: state.chunking,\n loaded: state.loaded,\n lastUpdated: Date.now(),\n };\n\n if (customResumeData) {\n persistedData.customResumeData = customResumeData;\n }\n\n try {\n localStorage.setItem(localStorageId, JSON.stringify(persistedData));\n }\n catch (error) {\n log(qq.format(\"Unable to save resume data for '{}' due to error: '{}'.\", id, error.toString()), \"warn\");\n }\n }\n },\n\n _registerProgressHandler: function(id, chunkIdx, chunkSize) {\n var xhr = handler._getXhr(id, chunkIdx),\n name = getName(id),\n progressCalculator = {\n simple: function(loaded, total) {\n var fileSize = getSize(id);\n\n if (loaded === total) {\n onProgress(id, name, fileSize, fileSize);\n }\n else {\n onProgress(id, name, (loaded >= fileSize ? fileSize - 1 : loaded), fileSize);\n }\n },\n\n chunked: function(loaded, total) {\n var chunkProgress = handler._getFileState(id).temp.chunkProgress,\n totalSuccessfullyLoadedForFile = handler._getFileState(id).loaded,\n loadedForRequest = loaded,\n totalForRequest = total,\n totalFileSize = getSize(id),\n estActualChunkLoaded = loadedForRequest - (totalForRequest - chunkSize),\n totalLoadedForFile = totalSuccessfullyLoadedForFile;\n\n chunkProgress[chunkIdx] = estActualChunkLoaded;\n\n qq.each(chunkProgress, function(chunkIdx, chunkLoaded) {\n totalLoadedForFile += chunkLoaded;\n });\n\n onProgress(id, name, totalLoadedForFile, totalFileSize);\n }\n };\n\n xhr.upload.onprogress = function(e) {\n if (e.lengthComputable) {\n /* jshint eqnull: true */\n var type = chunkSize == null ? \"simple\" : \"chunked\";\n progressCalculator[type](e.loaded, e.total);\n }\n };\n },\n\n /**\n * Registers an XHR transport instance created elsewhere.\n *\n * @param id ID of the associated file\n * @param optChunkIdx The chunk index associated with this XHR, if applicable\n * @param xhr XMLHttpRequest object instance\n * @param optAjaxRequester `qq.AjaxRequester` associated with this request, if applicable.\n * @returns {XMLHttpRequest}\n */\n _registerXhr: function(id, optChunkIdx, xhr, optAjaxRequester) {\n var xhrsId = optChunkIdx == null ? -1 : optChunkIdx,\n tempState = handler._getFileState(id).temp;\n\n tempState.xhrs = tempState.xhrs || {};\n tempState.ajaxRequesters = tempState.ajaxRequesters || {};\n\n tempState.xhrs[xhrsId] = xhr;\n\n if (optAjaxRequester) {\n tempState.ajaxRequesters[xhrsId] = optAjaxRequester;\n }\n\n return xhr;\n },\n\n // Deletes any local storage records that are \"expired\".\n _removeExpiredChunkingRecords: function() {\n var expirationDays = resume.recordsExpireIn;\n\n handler._iterateResumeRecords(function(key, uploadData) {\n var expirationDate = new Date(uploadData.lastUpdated);\n\n // transform updated date into expiration date\n expirationDate.setDate(expirationDate.getDate() + expirationDays);\n\n if (expirationDate.getTime() <= Date.now()) {\n log(\"Removing expired resume record with key \" + key);\n localStorage.removeItem(key);\n }\n });\n },\n\n /**\n * Determine if the associated file should be chunked.\n *\n * @param id ID of the associated file\n * @returns {*} true if chunking is enabled, possible, and the file can be split into more than 1 part\n */\n _shouldChunkThisFile: function(id) {\n var state = handler._getFileState(id);\n\n // file may no longer be available if it was recently cancelled\n if (state) {\n if (!state.chunking) {\n handler.reevaluateChunking(id);\n }\n\n return state.chunking.enabled;\n }\n }\n });\n};\n","/*globals qq, XMLHttpRequest*/\nqq.DeleteFileAjaxRequester = function(o) {\n \"use strict\";\n\n var requester,\n options = {\n method: \"DELETE\",\n uuidParamName: \"qquuid\",\n endpointStore: {},\n maxConnections: 3,\n customHeaders: function(id) {return {};},\n paramsStore: {},\n cors: {\n expected: false,\n sendCredentials: false\n },\n log: function(str, level) {},\n onDelete: function(id) {},\n onDeleteComplete: function(id, xhrOrXdr, isError) {}\n };\n\n qq.extend(options, o);\n\n function getMandatedParams() {\n if (options.method.toUpperCase() === \"POST\") {\n return {\n _method: \"DELETE\"\n };\n }\n\n return {};\n }\n\n requester = qq.extend(this, new qq.AjaxRequester({\n acceptHeader: \"application/json\",\n validMethods: [\"POST\", \"DELETE\"],\n method: options.method,\n endpointStore: options.endpointStore,\n paramsStore: options.paramsStore,\n mandatedParams: getMandatedParams(),\n maxConnections: options.maxConnections,\n customHeaders: function(id) {\n return options.customHeaders.get(id);\n },\n log: options.log,\n onSend: options.onDelete,\n onComplete: options.onDeleteComplete,\n cors: options.cors\n }));\n\n qq.extend(this, {\n sendDelete: function(id, uuid, additionalMandatedParams) {\n var additionalOptions = additionalMandatedParams || {};\n\n options.log(\"Submitting delete file request for \" + id);\n\n if (options.method === \"DELETE\") {\n requester.initTransport(id)\n .withPath(uuid)\n .withParams(additionalOptions)\n .send();\n }\n else {\n additionalOptions[options.uuidParamName] = uuid;\n requester.initTransport(id)\n .withParams(additionalOptions)\n .send();\n }\n }\n });\n};\n","/*global qq, define */\n/*jshint strict:false,bitwise:false,nonew:false,asi:true,-W064,-W116,-W089 */\n/**\n * Mega pixel image rendering library for iOS6+\n *\n * Fixes iOS6+'s image file rendering issue for large size image (over mega-pixel),\n * which causes unexpected subsampling when drawing it in canvas.\n * By using this library, you can safely render the image with proper stretching.\n *\n * Copyright (c) 2012 Shinichi Tomita \n * Released under the MIT license\n *\n * Heavily modified by Widen for Fine Uploader\n */\n(function() {\n\n /**\n * Detect subsampling in loaded image.\n * In iOS, larger images than 2M pixels may be subsampled in rendering.\n */\n function detectSubsampling(img) {\n var iw = img.naturalWidth,\n ih = img.naturalHeight,\n canvas = document.createElement(\"canvas\"),\n ctx;\n\n if (iw * ih > 1024 * 1024) { // subsampling may happen over megapixel image\n canvas.width = canvas.height = 1;\n ctx = canvas.getContext(\"2d\");\n ctx.drawImage(img, -iw + 1, 0);\n // subsampled image becomes half smaller in rendering size.\n // check alpha channel value to confirm image is covering edge pixel or not.\n // if alpha value is 0 image is not covering, hence subsampled.\n return ctx.getImageData(0, 0, 1, 1).data[3] === 0;\n } else {\n return false;\n }\n }\n\n /**\n * Detecting vertical squash in loaded image.\n * Fixes a bug which squash image vertically while drawing into canvas for some images.\n */\n function detectVerticalSquash(img, iw, ih) {\n var canvas = document.createElement(\"canvas\"),\n sy = 0,\n ey = ih,\n py = ih,\n ctx, data, alpha, ratio;\n\n canvas.width = 1;\n canvas.height = ih;\n ctx = canvas.getContext(\"2d\");\n ctx.drawImage(img, 0, 0);\n data = ctx.getImageData(0, 0, 1, ih).data;\n\n // search image edge pixel position in case it is squashed vertically.\n while (py > sy) {\n alpha = data[(py - 1) * 4 + 3];\n if (alpha === 0) {\n ey = py;\n } else {\n sy = py;\n }\n py = (ey + sy) >> 1;\n }\n\n ratio = (py / ih);\n return (ratio === 0) ? 1 : ratio;\n }\n\n /**\n * Rendering image element (with resizing) and get its data URL\n */\n function renderImageToDataURL(img, blob, options, doSquash) {\n var canvas = document.createElement(\"canvas\"),\n mime = options.mime || \"image/jpeg\",\n promise = new qq.Promise();\n\n renderImageToCanvas(img, blob, canvas, options, doSquash)\n .then(function() {\n promise.success(\n canvas.toDataURL(mime, options.quality || 0.8)\n );\n });\n\n return promise;\n }\n\n function maybeCalculateDownsampledDimensions(spec) {\n var maxPixels = 5241000; //iOS specific value\n\n if (!qq.ios()) {\n throw new qq.Error(\"Downsampled dimensions can only be reliably calculated for iOS!\");\n }\n\n if (spec.origHeight * spec.origWidth > maxPixels) {\n return {\n newHeight: Math.round(Math.sqrt(maxPixels * (spec.origHeight / spec.origWidth))),\n newWidth: Math.round(Math.sqrt(maxPixels * (spec.origWidth / spec.origHeight)))\n };\n }\n }\n\n /**\n * Rendering image element (with resizing) into the canvas element\n */\n function renderImageToCanvas(img, blob, canvas, options, doSquash) {\n var iw = img.naturalWidth,\n ih = img.naturalHeight,\n width = options.width,\n height = options.height,\n ctx = canvas.getContext(\"2d\"),\n promise = new qq.Promise(),\n modifiedDimensions;\n\n ctx.save();\n\n if (options.resize) {\n return renderImageToCanvasWithCustomResizer({\n blob: blob,\n canvas: canvas,\n image: img,\n imageHeight: ih,\n imageWidth: iw,\n orientation: options.orientation,\n resize: options.resize,\n targetHeight: height,\n targetWidth: width\n });\n }\n\n if (!qq.supportedFeatures.unlimitedScaledImageSize) {\n modifiedDimensions = maybeCalculateDownsampledDimensions({\n origWidth: width,\n origHeight: height\n });\n\n if (modifiedDimensions) {\n qq.log(qq.format(\"Had to reduce dimensions due to device limitations from {}w / {}h to {}w / {}h\",\n width, height, modifiedDimensions.newWidth, modifiedDimensions.newHeight),\n \"warn\");\n\n width = modifiedDimensions.newWidth;\n height = modifiedDimensions.newHeight;\n }\n }\n\n transformCoordinate(canvas, width, height, options.orientation);\n\n // Fine Uploader specific: Save some CPU cycles if not using iOS\n // Assumption: This logic is only needed to overcome iOS image sampling issues\n if (qq.ios()) {\n (function() {\n if (detectSubsampling(img)) {\n iw /= 2;\n ih /= 2;\n }\n\n var d = 1024, // size of tiling canvas\n tmpCanvas = document.createElement(\"canvas\"),\n vertSquashRatio = doSquash ? detectVerticalSquash(img, iw, ih) : 1,\n dw = Math.ceil(d * width / iw),\n dh = Math.ceil(d * height / ih / vertSquashRatio),\n sy = 0,\n dy = 0,\n tmpCtx, sx, dx;\n\n tmpCanvas.width = tmpCanvas.height = d;\n tmpCtx = tmpCanvas.getContext(\"2d\");\n\n while (sy < ih) {\n sx = 0;\n dx = 0;\n while (sx < iw) {\n tmpCtx.clearRect(0, 0, d, d);\n tmpCtx.drawImage(img, -sx, -sy);\n ctx.drawImage(tmpCanvas, 0, 0, d, d, dx, dy, dw, dh);\n sx += d;\n dx += dw;\n }\n sy += d;\n dy += dh;\n }\n ctx.restore();\n tmpCanvas = tmpCtx = null;\n }());\n }\n else {\n ctx.drawImage(img, 0, 0, width, height);\n }\n\n canvas.qqImageRendered && canvas.qqImageRendered();\n promise.success();\n\n return promise;\n }\n\n function renderImageToCanvasWithCustomResizer(resizeInfo) {\n var blob = resizeInfo.blob,\n image = resizeInfo.image,\n imageHeight = resizeInfo.imageHeight,\n imageWidth = resizeInfo.imageWidth,\n orientation = resizeInfo.orientation,\n promise = new qq.Promise(),\n resize = resizeInfo.resize,\n sourceCanvas = document.createElement(\"canvas\"),\n sourceCanvasContext = sourceCanvas.getContext(\"2d\"),\n targetCanvas = resizeInfo.canvas,\n targetHeight = resizeInfo.targetHeight,\n targetWidth = resizeInfo.targetWidth;\n\n transformCoordinate(sourceCanvas, imageWidth, imageHeight, orientation);\n\n targetCanvas.height = targetHeight;\n targetCanvas.width = targetWidth;\n\n sourceCanvasContext.drawImage(image, 0, 0);\n\n resize({\n blob: blob,\n height: targetHeight,\n image: image,\n sourceCanvas: sourceCanvas,\n targetCanvas: targetCanvas,\n width: targetWidth\n })\n .then(\n function success() {\n targetCanvas.qqImageRendered && targetCanvas.qqImageRendered();\n promise.success();\n },\n promise.failure\n );\n\n return promise;\n }\n\n /**\n * Transform canvas coordination according to specified frame size and orientation\n * Orientation value is from EXIF tag\n */\n function transformCoordinate(canvas, width, height, orientation) {\n switch (orientation) {\n case 5:\n case 6:\n case 7:\n case 8:\n canvas.width = height;\n canvas.height = width;\n break;\n default:\n canvas.width = width;\n canvas.height = height;\n }\n var ctx = canvas.getContext(\"2d\");\n switch (orientation) {\n case 2:\n // horizontal flip\n ctx.translate(width, 0);\n ctx.scale(-1, 1);\n break;\n case 3:\n // 180 rotate left\n ctx.translate(width, height);\n ctx.rotate(Math.PI);\n break;\n case 4:\n // vertical flip\n ctx.translate(0, height);\n ctx.scale(1, -1);\n break;\n case 5:\n // vertical flip + 90 rotate right\n ctx.rotate(0.5 * Math.PI);\n ctx.scale(1, -1);\n break;\n case 6:\n // 90 rotate right\n ctx.rotate(0.5 * Math.PI);\n ctx.translate(0, -height);\n break;\n case 7:\n // horizontal flip + 90 rotate right\n ctx.rotate(0.5 * Math.PI);\n ctx.translate(width, -height);\n ctx.scale(-1, 1);\n break;\n case 8:\n // 90 rotate left\n ctx.rotate(-0.5 * Math.PI);\n ctx.translate(-width, 0);\n break;\n default:\n break;\n }\n }\n\n /**\n * MegaPixImage class\n */\n function MegaPixImage(srcImage, errorCallback) {\n var self = this;\n\n if (window.Blob && srcImage instanceof Blob) {\n (function() {\n var img = new Image(),\n URL = window.URL && window.URL.createObjectURL ? window.URL :\n window.webkitURL && window.webkitURL.createObjectURL ? window.webkitURL : null;\n if (!URL) { throw Error(\"No createObjectURL function found to create blob url\"); }\n img.src = URL.createObjectURL(srcImage);\n self.blob = srcImage;\n srcImage = img;\n }());\n }\n if (!srcImage.naturalWidth && !srcImage.naturalHeight) {\n srcImage.onload = function() {\n var listeners = self.imageLoadListeners;\n if (listeners) {\n self.imageLoadListeners = null;\n // IE11 doesn't reliably report actual image dimensions immediately after onload for small files,\n // so let's push this to the end of the UI thread queue.\n setTimeout(function() {\n for (var i = 0, len = listeners.length; i < len; i++) {\n listeners[i]();\n }\n }, 0);\n }\n };\n srcImage.onerror = errorCallback;\n this.imageLoadListeners = [];\n }\n this.srcImage = srcImage;\n }\n\n /**\n * Rendering megapix image into specified target element\n */\n MegaPixImage.prototype.render = function(target, options) {\n options = options || {};\n\n var self = this,\n imgWidth = this.srcImage.naturalWidth,\n imgHeight = this.srcImage.naturalHeight,\n width = options.width,\n height = options.height,\n maxWidth = options.maxWidth,\n maxHeight = options.maxHeight,\n doSquash = !this.blob || this.blob.type === \"image/jpeg\",\n tagName = target.tagName.toLowerCase(),\n opt;\n\n if (this.imageLoadListeners) {\n this.imageLoadListeners.push(function() { self.render(target, options); });\n return;\n }\n\n if (width && !height) {\n height = (imgHeight * width / imgWidth) << 0;\n } else if (height && !width) {\n width = (imgWidth * height / imgHeight) << 0;\n } else {\n width = imgWidth;\n height = imgHeight;\n }\n if (maxWidth && width > maxWidth) {\n width = maxWidth;\n height = (imgHeight * width / imgWidth) << 0;\n }\n if (maxHeight && height > maxHeight) {\n height = maxHeight;\n width = (imgWidth * height / imgHeight) << 0;\n }\n\n opt = { width: width, height: height },\n qq.each(options, function(optionsKey, optionsValue) {\n opt[optionsKey] = optionsValue;\n });\n\n if (tagName === \"img\") {\n (function() {\n var oldTargetSrc = target.src;\n renderImageToDataURL(self.srcImage, self.blob, opt, doSquash)\n .then(function(dataUri) {\n target.src = dataUri;\n oldTargetSrc === target.src && target.onload();\n });\n }());\n } else if (tagName === \"canvas\") {\n renderImageToCanvas(this.srcImage, this.blob, target, opt, doSquash);\n }\n if (typeof this.onrender === \"function\") {\n this.onrender(target);\n }\n };\n\n qq.MegaPixImage = MegaPixImage;\n})();\n","/*globals qq */\n/**\n * Draws a thumbnail of a Blob/File/URL onto an or .\n *\n * @constructor\n */\nqq.ImageGenerator = function(log) {\n \"use strict\";\n\n function isImg(el) {\n return el.tagName.toLowerCase() === \"img\";\n }\n\n function isCanvas(el) {\n return el.tagName.toLowerCase() === \"canvas\";\n }\n\n function isImgCorsSupported() {\n return new Image().crossOrigin !== undefined;\n }\n\n function isCanvasSupported() {\n var canvas = document.createElement(\"canvas\");\n\n return canvas.getContext && canvas.getContext(\"2d\");\n }\n\n // This is only meant to determine the MIME type of a renderable image file.\n // It is used to ensure images drawn from a URL that have transparent backgrounds\n // are rendered correctly, among other things.\n function determineMimeOfFileName(nameWithPath) {\n /*jshint -W015 */\n var pathSegments = nameWithPath.split(\"/\"),\n name = pathSegments[pathSegments.length - 1].split(\"?\")[0],\n extension = qq.getExtension(name);\n\n extension = extension && extension.toLowerCase();\n\n switch (extension) {\n case \"jpeg\":\n case \"jpg\":\n return \"image/jpeg\";\n case \"png\":\n return \"image/png\";\n case \"bmp\":\n return \"image/bmp\";\n case \"gif\":\n return \"image/gif\";\n case \"tiff\":\n case \"tif\":\n return \"image/tiff\";\n }\n }\n\n // This will likely not work correctly in IE8 and older.\n // It's only used as part of a formula to determine\n // if a canvas can be used to scale a server-hosted thumbnail.\n // If canvas isn't supported by the UA (IE8 and older)\n // this method should not even be called.\n function isCrossOrigin(url) {\n var targetAnchor = document.createElement(\"a\"),\n targetProtocol, targetHostname, targetPort;\n\n targetAnchor.href = url;\n\n targetProtocol = targetAnchor.protocol;\n targetPort = targetAnchor.port;\n targetHostname = targetAnchor.hostname;\n\n if (targetProtocol.toLowerCase() !== window.location.protocol.toLowerCase()) {\n return true;\n }\n\n if (targetHostname.toLowerCase() !== window.location.hostname.toLowerCase()) {\n return true;\n }\n\n // IE doesn't take ports into consideration when determining if two endpoints are same origin.\n if (targetPort !== window.location.port && !qq.ie()) {\n return true;\n }\n\n return false;\n }\n\n function registerImgLoadListeners(img, promise) {\n img.onload = function() {\n img.onload = null;\n img.onerror = null;\n promise.success(img);\n };\n\n img.onerror = function() {\n img.onload = null;\n img.onerror = null;\n log(\"Problem drawing thumbnail!\", \"error\");\n promise.failure(img, \"Problem drawing thumbnail!\");\n };\n }\n\n function registerCanvasDrawImageListener(canvas, promise) {\n // The image is drawn on the canvas by a third-party library,\n // and we want to know when this is completed. Since the library\n // may invoke drawImage many times in a loop, we need to be called\n // back when the image is fully rendered. So, we are expecting the\n // code that draws this image to follow a convention that involves a\n // function attached to the canvas instance be invoked when it is done.\n canvas.qqImageRendered = function() {\n promise.success(canvas);\n };\n }\n\n // Fulfills a `qq.Promise` when an image has been drawn onto the target,\n // whether that is a or an . The attempt is considered a\n // failure if the target is not an or a , or if the drawing\n // attempt was not successful.\n function registerThumbnailRenderedListener(imgOrCanvas, promise) {\n var registered = isImg(imgOrCanvas) || isCanvas(imgOrCanvas);\n\n if (isImg(imgOrCanvas)) {\n registerImgLoadListeners(imgOrCanvas, promise);\n }\n else if (isCanvas(imgOrCanvas)) {\n registerCanvasDrawImageListener(imgOrCanvas, promise);\n }\n else {\n promise.failure(imgOrCanvas);\n log(qq.format(\"Element container of type {} is not supported!\", imgOrCanvas.tagName), \"error\");\n }\n\n return registered;\n }\n\n // Draw a preview iff the current UA can natively display it.\n // Also rotate the image if necessary.\n function draw(fileOrBlob, container, options) {\n var drawPreview = new qq.Promise(),\n identifier = new qq.Identify(fileOrBlob, log),\n maxSize = options.maxSize,\n // jshint eqnull:true\n orient = options.orient == null ? true : options.orient,\n megapixErrorHandler = function() {\n container.onerror = null;\n container.onload = null;\n log(\"Could not render preview, file may be too large!\", \"error\");\n drawPreview.failure(container, \"Browser cannot render image!\");\n };\n\n identifier.isPreviewable().then(\n function(mime) {\n // If options explicitly specify that Orientation is not desired,\n // replace the orient task with a dummy promise that \"succeeds\" immediately.\n var dummyExif = {\n parse: function() {\n return new qq.Promise().success();\n }\n },\n exif = orient ? new qq.Exif(fileOrBlob, log) : dummyExif,\n mpImg = new qq.MegaPixImage(fileOrBlob, megapixErrorHandler);\n\n if (registerThumbnailRenderedListener(container, drawPreview)) {\n exif.parse().then(\n function(exif) {\n var orientation = exif && exif.Orientation;\n\n mpImg.render(container, {\n maxWidth: maxSize,\n maxHeight: maxSize,\n orientation: orientation,\n mime: mime,\n resize: options.customResizeFunction\n });\n },\n\n function(failureMsg) {\n log(qq.format(\"EXIF data could not be parsed ({}). Assuming orientation = 1.\", failureMsg));\n\n mpImg.render(container, {\n maxWidth: maxSize,\n maxHeight: maxSize,\n mime: mime,\n resize: options.customResizeFunction\n });\n }\n );\n }\n },\n\n function() {\n log(\"Not previewable\");\n drawPreview.failure(container, \"Not previewable\");\n }\n );\n\n return drawPreview;\n }\n\n function drawOnCanvasOrImgFromUrl(url, canvasOrImg, draw, maxSize, customResizeFunction) {\n var tempImg = new Image(),\n tempImgRender = new qq.Promise();\n\n registerThumbnailRenderedListener(tempImg, tempImgRender);\n\n if (isCrossOrigin(url)) {\n tempImg.crossOrigin = \"anonymous\";\n }\n\n tempImg.src = url;\n\n tempImgRender.then(\n function rendered() {\n registerThumbnailRenderedListener(canvasOrImg, draw);\n\n var mpImg = new qq.MegaPixImage(tempImg);\n mpImg.render(canvasOrImg, {\n maxWidth: maxSize,\n maxHeight: maxSize,\n mime: determineMimeOfFileName(url),\n resize: customResizeFunction\n });\n },\n\n draw.failure\n );\n }\n\n function drawOnImgFromUrlWithCssScaling(url, img, draw, maxSize) {\n registerThumbnailRenderedListener(img, draw);\n // NOTE: The fact that maxWidth/height is set on the thumbnail for scaled images\n // that must drop back to CSS is known and exploited by the templating module.\n // In this module, we pre-render \"waiting\" thumbs for all files immediately after they\n // are submitted, and we must be sure to pass any style associated with the \"waiting\" preview.\n qq(img).css({\n maxWidth: maxSize + \"px\",\n maxHeight: maxSize + \"px\"\n });\n\n img.src = url;\n }\n\n // Draw a (server-hosted) thumbnail given a URL.\n // This will optionally scale the thumbnail as well.\n // It attempts to use to scale, but will fall back\n // to max-width and max-height style properties if the UA\n // doesn't support canvas or if the images is cross-domain and\n // the UA doesn't support the crossorigin attribute on img tags,\n // which is required to scale a cross-origin image using &\n // then export it back to an .\n function drawFromUrl(url, container, options) {\n var draw = new qq.Promise(),\n scale = options.scale,\n maxSize = scale ? options.maxSize : null;\n\n // container is an img, scaling needed\n if (scale && isImg(container)) {\n // Iff canvas is available in this UA, try to use it for scaling.\n // Otherwise, fall back to CSS scaling\n if (isCanvasSupported()) {\n // Attempt to use for image scaling,\n // but we must fall back to scaling via CSS/styles\n // if this is a cross-origin image and the UA doesn't support CORS.\n if (isCrossOrigin(url) && !isImgCorsSupported()) {\n drawOnImgFromUrlWithCssScaling(url, container, draw, maxSize);\n }\n else {\n drawOnCanvasOrImgFromUrl(url, container, draw, maxSize);\n }\n }\n else {\n drawOnImgFromUrlWithCssScaling(url, container, draw, maxSize);\n }\n }\n // container is a canvas, scaling optional\n else if (isCanvas(container)) {\n drawOnCanvasOrImgFromUrl(url, container, draw, maxSize);\n }\n // container is an img & no scaling: just set the src attr to the passed url\n else if (registerThumbnailRenderedListener(container, draw)) {\n container.src = url;\n }\n\n return draw;\n }\n\n qq.extend(this, {\n /**\n * Generate a thumbnail. Depending on the arguments, this may either result in\n * a client-side rendering of an image (if a `Blob` is supplied) or a server-generated\n * image that may optionally be scaled client-side using or CSS/styles (as a fallback).\n *\n * @param fileBlobOrUrl a `File`, `Blob`, or a URL pointing to the image\n * @param container or to contain the preview\n * @param options possible properties include `maxSize` (int), `orient` (bool - default true), resize` (bool - default true), and `customResizeFunction`.\n * @returns qq.Promise fulfilled when the preview has been drawn, or the attempt has failed\n */\n generate: function(fileBlobOrUrl, container, options) {\n if (qq.isString(fileBlobOrUrl)) {\n log(\"Attempting to update thumbnail based on server response.\");\n return drawFromUrl(fileBlobOrUrl, container, options || {});\n }\n else {\n log(\"Attempting to draw client-side image preview.\");\n return draw(fileBlobOrUrl, container, options || {});\n }\n }\n });\n\n /**/\n this._testing = {};\n this._testing.isImg = isImg;\n this._testing.isCanvas = isCanvas;\n this._testing.isCrossOrigin = isCrossOrigin;\n this._testing.determineMimeOfFileName = determineMimeOfFileName;\n /* */\n};\n","/*globals qq */\n/**\n * EXIF image data parser. Currently only parses the Orientation tag value,\n * but this may be expanded to other tags in the future.\n *\n * @param fileOrBlob Attempt to parse EXIF data in this `Blob`\n * @constructor\n */\nqq.Exif = function(fileOrBlob, log) {\n \"use strict\";\n\n // Orientation is the only tag parsed here at this time.\n var TAG_IDS = [274],\n TAG_INFO = {\n 274: {\n name: \"Orientation\",\n bytes: 2\n }\n };\n\n // Convert a little endian (hex string) to big endian (decimal).\n function parseLittleEndian(hex) {\n var result = 0,\n pow = 0;\n\n while (hex.length > 0) {\n result += parseInt(hex.substring(0, 2), 16) * Math.pow(2, pow);\n hex = hex.substring(2, hex.length);\n pow += 8;\n }\n\n return result;\n }\n\n // Find the byte offset, of Application Segment 1 (EXIF).\n // External callers need not supply any arguments.\n function seekToApp1(offset, promise) {\n var theOffset = offset,\n thePromise = promise;\n if (theOffset === undefined) {\n theOffset = 2;\n thePromise = new qq.Promise();\n }\n\n qq.readBlobToHex(fileOrBlob, theOffset, 4).then(function(hex) {\n var match = /^ffe([0-9])/.exec(hex),\n segmentLength;\n\n if (match) {\n if (match[1] !== \"1\") {\n segmentLength = parseInt(hex.slice(4, 8), 16);\n seekToApp1(theOffset + segmentLength + 2, thePromise);\n }\n else {\n thePromise.success(theOffset);\n }\n }\n else {\n thePromise.failure(\"No EXIF header to be found!\");\n }\n });\n\n return thePromise;\n }\n\n // Find the byte offset of Application Segment 1 (EXIF) for valid JPEGs only.\n function getApp1Offset() {\n var promise = new qq.Promise();\n\n qq.readBlobToHex(fileOrBlob, 0, 6).then(function(hex) {\n if (hex.indexOf(\"ffd8\") !== 0) {\n promise.failure(\"Not a valid JPEG!\");\n }\n else {\n seekToApp1().then(function(offset) {\n promise.success(offset);\n },\n function(error) {\n promise.failure(error);\n });\n }\n });\n\n return promise;\n }\n\n // Determine the byte ordering of the EXIF header.\n function isLittleEndian(app1Start) {\n var promise = new qq.Promise();\n\n qq.readBlobToHex(fileOrBlob, app1Start + 10, 2).then(function(hex) {\n promise.success(hex === \"4949\");\n });\n\n return promise;\n }\n\n // Determine the number of directory entries in the EXIF header.\n function getDirEntryCount(app1Start, littleEndian) {\n var promise = new qq.Promise();\n\n qq.readBlobToHex(fileOrBlob, app1Start + 18, 2).then(function(hex) {\n if (littleEndian) {\n return promise.success(parseLittleEndian(hex));\n }\n else {\n promise.success(parseInt(hex, 16));\n }\n });\n\n return promise;\n }\n\n // Get the IFD portion of the EXIF header as a hex string.\n function getIfd(app1Start, dirEntries) {\n var offset = app1Start + 20,\n bytes = dirEntries * 12;\n\n return qq.readBlobToHex(fileOrBlob, offset, bytes);\n }\n\n // Obtain an array of all directory entries (as hex strings) in the EXIF header.\n function getDirEntries(ifdHex) {\n var entries = [],\n offset = 0;\n\n while (offset + 24 <= ifdHex.length) {\n entries.push(ifdHex.slice(offset, offset + 24));\n offset += 24;\n }\n\n return entries;\n }\n\n // Obtain values for all relevant tags and return them.\n function getTagValues(littleEndian, dirEntries) {\n var TAG_VAL_OFFSET = 16,\n tagsToFind = qq.extend([], TAG_IDS),\n vals = {};\n\n qq.each(dirEntries, function(idx, entry) {\n var idHex = entry.slice(0, 4),\n id = littleEndian ? parseLittleEndian(idHex) : parseInt(idHex, 16),\n tagsToFindIdx = tagsToFind.indexOf(id),\n tagValHex, tagName, tagValLength;\n\n if (tagsToFindIdx >= 0) {\n tagName = TAG_INFO[id].name;\n tagValLength = TAG_INFO[id].bytes;\n tagValHex = entry.slice(TAG_VAL_OFFSET, TAG_VAL_OFFSET + (tagValLength * 2));\n vals[tagName] = littleEndian ? parseLittleEndian(tagValHex) : parseInt(tagValHex, 16);\n\n tagsToFind.splice(tagsToFindIdx, 1);\n }\n\n if (tagsToFind.length === 0) {\n return false;\n }\n });\n\n return vals;\n }\n\n qq.extend(this, {\n /**\n * Attempt to parse the EXIF header for the `Blob` associated with this instance.\n *\n * @returns {qq.Promise} To be fulfilled when the parsing is complete.\n * If successful, the parsed EXIF header as an object will be included.\n */\n parse: function() {\n var parser = new qq.Promise(),\n onParseFailure = function(message) {\n log(qq.format(\"EXIF header parse failed: '{}' \", message));\n parser.failure(message);\n };\n\n getApp1Offset().then(function(app1Offset) {\n log(qq.format(\"Moving forward with EXIF header parsing for '{}'\", fileOrBlob.name === undefined ? \"blob\" : fileOrBlob.name));\n\n isLittleEndian(app1Offset).then(function(littleEndian) {\n\n log(qq.format(\"EXIF Byte order is {} endian\", littleEndian ? \"little\" : \"big\"));\n\n getDirEntryCount(app1Offset, littleEndian).then(function(dirEntryCount) {\n\n log(qq.format(\"Found {} APP1 directory entries\", dirEntryCount));\n\n getIfd(app1Offset, dirEntryCount).then(function(ifdHex) {\n var dirEntries = getDirEntries(ifdHex),\n tagValues = getTagValues(littleEndian, dirEntries);\n\n log(\"Successfully parsed some EXIF tags\");\n\n parser.success(tagValues);\n }, onParseFailure);\n }, onParseFailure);\n }, onParseFailure);\n }, onParseFailure);\n\n return parser;\n }\n });\n\n /**/\n this._testing = {};\n this._testing.parseLittleEndian = parseLittleEndian;\n /* */\n};\n","/*globals qq */\nqq.Identify = function(fileOrBlob, log) {\n \"use strict\";\n\n function isIdentifiable(magicBytes, questionableBytes) {\n var identifiable = false,\n magicBytesEntries = [].concat(magicBytes);\n\n qq.each(magicBytesEntries, function(idx, magicBytesArrayEntry) {\n if (questionableBytes.indexOf(magicBytesArrayEntry) === 0) {\n identifiable = true;\n return false;\n }\n });\n\n return identifiable;\n }\n\n qq.extend(this, {\n /**\n * Determines if a Blob can be displayed natively in the current browser. This is done by reading magic\n * bytes in the beginning of the file, so this is an asynchronous operation. Before we attempt to read the\n * file, we will examine the blob's type attribute to save CPU cycles.\n *\n * @returns {qq.Promise} Promise that is fulfilled when identification is complete.\n * If successful, the MIME string is passed to the success handler.\n */\n isPreviewable: function() {\n var self = this,\n identifier = new qq.Promise(),\n previewable = false,\n name = fileOrBlob.name === undefined ? \"blob\" : fileOrBlob.name;\n\n log(qq.format(\"Attempting to determine if {} can be rendered in this browser\", name));\n\n log(\"First pass: check type attribute of blob object.\");\n\n if (this.isPreviewableSync()) {\n log(\"Second pass: check for magic bytes in file header.\");\n\n qq.readBlobToHex(fileOrBlob, 0, 4).then(function(hex) {\n qq.each(self.PREVIEWABLE_MIME_TYPES, function(mime, bytes) {\n if (isIdentifiable(bytes, hex)) {\n // Safari is the only supported browser that can deal with TIFFs natively,\n // so, if this is a TIFF and the UA isn't Safari, declare this file \"non-previewable\".\n if (mime !== \"image/tiff\" || qq.supportedFeatures.tiffPreviews) {\n previewable = true;\n identifier.success(mime);\n }\n\n return false;\n }\n });\n\n log(qq.format(\"'{}' is {} able to be rendered in this browser\", name, previewable ? \"\" : \"NOT\"));\n\n if (!previewable) {\n identifier.failure();\n }\n },\n function() {\n log(\"Error reading file w/ name '\" + name + \"'. Not able to be rendered in this browser.\");\n identifier.failure();\n });\n }\n else {\n identifier.failure();\n }\n\n return identifier;\n },\n\n /**\n * Determines if a Blob can be displayed natively in the current browser. This is done by checking the\n * blob's type attribute. This is a synchronous operation, useful for situations where an asynchronous operation\n * would be challenging to support. Note that the blob's type property is not as accurate as reading the\n * file's magic bytes.\n *\n * @returns {Boolean} true if the blob can be rendered in the current browser\n */\n isPreviewableSync: function() {\n var fileMime = fileOrBlob.type,\n // Assumption: This will only ever be executed in browsers that support `Object.keys`.\n isRecognizedImage = qq.indexOf(Object.keys(this.PREVIEWABLE_MIME_TYPES), fileMime) >= 0,\n previewable = false,\n name = fileOrBlob.name === undefined ? \"blob\" : fileOrBlob.name;\n\n if (isRecognizedImage) {\n if (fileMime === \"image/tiff\") {\n previewable = qq.supportedFeatures.tiffPreviews;\n }\n else {\n previewable = true;\n }\n }\n\n !previewable && log(name + \" is not previewable in this browser per the blob's type attr\");\n\n return previewable;\n }\n });\n};\n\nqq.Identify.prototype.PREVIEWABLE_MIME_TYPES = {\n \"image/jpeg\": \"ffd8ff\",\n \"image/gif\": \"474946\",\n \"image/png\": \"89504e\",\n \"image/bmp\": \"424d\",\n \"image/tiff\": [\"49492a00\", \"4d4d002a\"]\n};\n","/*globals qq*/\n/**\n * Attempts to validate an image, wherever possible.\n *\n * @param blob File or Blob representing a user-selecting image.\n * @param log Uses this to post log messages to the console.\n * @constructor\n */\nqq.ImageValidation = function(blob, log) {\n \"use strict\";\n\n /**\n * @param limits Object with possible image-related limits to enforce.\n * @returns {boolean} true if at least one of the limits has a non-zero value\n */\n function hasNonZeroLimits(limits) {\n var atLeastOne = false;\n\n qq.each(limits, function(limit, value) {\n if (value > 0) {\n atLeastOne = true;\n return false;\n }\n });\n\n return atLeastOne;\n }\n\n /**\n * @returns {qq.Promise} The promise is a failure if we can't obtain the width & height.\n * Otherwise, `success` is called on the returned promise with an object containing\n * `width` and `height` properties.\n */\n function getWidthHeight() {\n var sizeDetermination = new qq.Promise();\n\n new qq.Identify(blob, log).isPreviewable().then(function() {\n var image = new Image(),\n url = window.URL && window.URL.createObjectURL ? window.URL :\n window.webkitURL && window.webkitURL.createObjectURL ? window.webkitURL :\n null;\n\n if (url) {\n image.onerror = function() {\n log(\"Cannot determine dimensions for image. May be too large.\", \"error\");\n sizeDetermination.failure();\n };\n\n image.onload = function() {\n sizeDetermination.success({\n width: this.width,\n height: this.height\n });\n };\n\n image.src = url.createObjectURL(blob);\n }\n else {\n log(\"No createObjectURL function available to generate image URL!\", \"error\");\n sizeDetermination.failure();\n }\n }, sizeDetermination.failure);\n\n return sizeDetermination;\n }\n\n /**\n *\n * @param limits Object with possible image-related limits to enforce.\n * @param dimensions Object containing `width` & `height` properties for the image to test.\n * @returns {String || undefined} The name of the failing limit. Undefined if no failing limits.\n */\n function getFailingLimit(limits, dimensions) {\n var failingLimit;\n\n qq.each(limits, function(limitName, limitValue) {\n if (limitValue > 0) {\n var limitMatcher = /(max|min)(Width|Height)/.exec(limitName),\n dimensionPropName = limitMatcher[2].charAt(0).toLowerCase() + limitMatcher[2].slice(1),\n actualValue = dimensions[dimensionPropName];\n\n /*jshint -W015*/\n switch (limitMatcher[1]) {\n case \"min\":\n if (actualValue < limitValue) {\n failingLimit = limitName;\n return false;\n }\n break;\n case \"max\":\n if (actualValue > limitValue) {\n failingLimit = limitName;\n return false;\n }\n break;\n }\n }\n });\n\n return failingLimit;\n }\n\n /**\n * Validate the associated blob.\n *\n * @param limits\n * @returns {qq.Promise} `success` is called on the promise is the image is valid or\n * if the blob is not an image, or if the image is not verifiable.\n * Otherwise, `failure` with the name of the failing limit.\n */\n this.validate = function(limits) {\n var validationEffort = new qq.Promise();\n\n log(\"Attempting to validate image.\");\n\n if (hasNonZeroLimits(limits)) {\n getWidthHeight().then(function(dimensions) {\n var failingLimit = getFailingLimit(limits, dimensions);\n\n if (failingLimit) {\n validationEffort.failure(failingLimit);\n }\n else {\n validationEffort.success();\n }\n }, validationEffort.success);\n }\n else {\n validationEffort.success();\n }\n\n return validationEffort;\n };\n};\n","/* globals qq */\n/**\n * Module used to control populating the initial list of files.\n *\n * @constructor\n */\nqq.Session = function(spec) {\n \"use strict\";\n\n var options = {\n endpoint: null,\n params: {},\n customHeaders: {},\n cors: {},\n addFileRecord: function(sessionData) {},\n log: function(message, level) {}\n };\n\n qq.extend(options, spec, true);\n\n function isJsonResponseValid(response) {\n if (qq.isArray(response)) {\n return true;\n }\n\n options.log(\"Session response is not an array.\", \"error\");\n }\n\n function handleFileItems(fileItems, success, xhrOrXdr, promise) {\n var someItemsIgnored = false;\n\n success = success && isJsonResponseValid(fileItems);\n\n if (success) {\n qq.each(fileItems, function(idx, fileItem) {\n /* jshint eqnull:true */\n if (fileItem.uuid == null) {\n someItemsIgnored = true;\n options.log(qq.format(\"Session response item {} did not include a valid UUID - ignoring.\", idx), \"error\");\n }\n else if (fileItem.name == null) {\n someItemsIgnored = true;\n options.log(qq.format(\"Session response item {} did not include a valid name - ignoring.\", idx), \"error\");\n }\n else {\n try {\n options.addFileRecord(fileItem);\n return true;\n }\n catch (err) {\n someItemsIgnored = true;\n options.log(err.message, \"error\");\n }\n }\n\n return false;\n });\n }\n\n promise[success && !someItemsIgnored ? \"success\" : \"failure\"](fileItems, xhrOrXdr);\n }\n\n // Initiate a call to the server that will be used to populate the initial file list.\n // Returns a `qq.Promise`.\n this.refresh = function() {\n /*jshint indent:false */\n var refreshEffort = new qq.Promise(),\n refreshCompleteCallback = function(response, success, xhrOrXdr) {\n handleFileItems(response, success, xhrOrXdr, refreshEffort);\n },\n requesterOptions = qq.extend({}, options),\n requester = new qq.SessionAjaxRequester(\n qq.extend(requesterOptions, {onComplete: refreshCompleteCallback})\n );\n\n requester.queryServer();\n\n return refreshEffort;\n };\n};\n","/*globals qq, XMLHttpRequest*/\n/**\n * Thin module used to send GET requests to the server, expecting information about session\n * data used to initialize an uploader instance.\n *\n * @param spec Various options used to influence the associated request.\n * @constructor\n */\nqq.SessionAjaxRequester = function(spec) {\n \"use strict\";\n\n var requester,\n options = {\n endpoint: null,\n customHeaders: {},\n params: {},\n cors: {\n expected: false,\n sendCredentials: false\n },\n onComplete: function(response, success, xhrOrXdr) {},\n log: function(str, level) {}\n };\n\n qq.extend(options, spec);\n\n function onComplete(id, xhrOrXdr, isError) {\n var response = null;\n\n /* jshint eqnull:true */\n if (xhrOrXdr.responseText != null) {\n try {\n response = qq.parseJson(xhrOrXdr.responseText);\n }\n catch (err) {\n options.log(\"Problem parsing session response: \" + err.message, \"error\");\n isError = true;\n }\n }\n\n options.onComplete(response, !isError, xhrOrXdr);\n }\n\n requester = qq.extend(this, new qq.AjaxRequester({\n acceptHeader: \"application/json\",\n validMethods: [\"GET\"],\n method: \"GET\",\n endpointStore: {\n get: function() {\n return options.endpoint;\n }\n },\n customHeaders: options.customHeaders,\n log: options.log,\n onComplete: onComplete,\n cors: options.cors\n }));\n\n qq.extend(this, {\n queryServer: function() {\n var params = qq.extend({}, options.params);\n\n options.log(\"Session query request.\");\n\n requester.initTransport(\"sessionRefresh\")\n .withParams(params)\n .withCacheBuster()\n .send();\n }\n });\n};\n","/* globals qq, ExifRestorer */\n/**\n * Controls generation of scaled images based on a reference image encapsulated in a `File` or `Blob`.\n * Scaled images are generated and converted to blobs on-demand.\n * Multiple scaled images per reference image with varying sizes and other properties are supported.\n *\n * @param spec Information about the scaled images to generate.\n * @param log Logger instance\n * @constructor\n */\nqq.Scaler = function(spec, log) {\n \"use strict\";\n\n var self = this,\n customResizeFunction = spec.customResizer,\n includeOriginal = spec.sendOriginal,\n orient = spec.orient,\n defaultType = spec.defaultType,\n defaultQuality = spec.defaultQuality / 100,\n failedToScaleText = spec.failureText,\n includeExif = spec.includeExif,\n sizes = this._getSortedSizes(spec.sizes);\n\n // Revealed API for instances of this module\n qq.extend(this, {\n // If no targeted sizes have been declared or if this browser doesn't support\n // client-side image preview generation, there is no scaling to do.\n enabled: qq.supportedFeatures.scaling && sizes.length > 0,\n\n getFileRecords: function(originalFileUuid, originalFileName, originalBlobOrBlobData) {\n var self = this,\n records = [],\n originalBlob = originalBlobOrBlobData.blob ? originalBlobOrBlobData.blob : originalBlobOrBlobData,\n identifier = new qq.Identify(originalBlob, log);\n\n // If the reference file cannot be rendered natively, we can't create scaled versions.\n if (identifier.isPreviewableSync()) {\n // Create records for each scaled version & add them to the records array, smallest first.\n qq.each(sizes, function(idx, sizeRecord) {\n var outputType = self._determineOutputType({\n defaultType: defaultType,\n requestedType: sizeRecord.type,\n refType: originalBlob.type\n });\n\n records.push({\n uuid: qq.getUniqueId(),\n name: self._getName(originalFileName, {\n name: sizeRecord.name,\n type: outputType,\n refType: originalBlob.type\n }),\n blob: new qq.BlobProxy(originalBlob,\n qq.bind(self._generateScaledImage, self, {\n customResizeFunction: customResizeFunction,\n maxSize: sizeRecord.maxSize,\n orient: orient,\n type: outputType,\n quality: defaultQuality,\n failedText: failedToScaleText,\n includeExif: includeExif,\n log: log\n }))\n });\n });\n\n records.push({\n uuid: originalFileUuid,\n name: originalFileName,\n size: originalBlob.size,\n blob: includeOriginal ? originalBlob : null\n });\n }\n else {\n records.push({\n uuid: originalFileUuid,\n name: originalFileName,\n size: originalBlob.size,\n blob: originalBlob\n });\n }\n\n return records;\n },\n\n handleNewFile: function(file, name, uuid, size, fileList, batchId, uuidParamName, api) {\n var self = this,\n buttonId = file.qqButtonId || (file.blob && file.blob.qqButtonId),\n scaledIds = [],\n originalId = null,\n addFileToHandler = api.addFileToHandler,\n uploadData = api.uploadData,\n paramsStore = api.paramsStore,\n proxyGroupId = qq.getUniqueId();\n\n qq.each(self.getFileRecords(uuid, name, file), function(idx, record) {\n var blobSize = record.size,\n id;\n\n if (record.blob instanceof qq.BlobProxy) {\n blobSize = -1;\n }\n\n id = uploadData.addFile({\n uuid: record.uuid,\n name: record.name,\n size: blobSize,\n batchId: batchId,\n proxyGroupId: proxyGroupId\n });\n\n if (record.blob instanceof qq.BlobProxy) {\n scaledIds.push(id);\n }\n else {\n originalId = id;\n }\n\n if (record.blob) {\n addFileToHandler(id, record.blob);\n fileList.push({id: id, file: record.blob});\n }\n else {\n uploadData.setStatus(id, qq.status.REJECTED);\n }\n });\n\n // If we are potentially uploading an original file and some scaled versions,\n // ensure the scaled versions include reference's to the parent's UUID and size\n // in their associated upload requests.\n if (originalId !== null) {\n qq.each(scaledIds, function(idx, scaledId) {\n var params = {\n qqparentuuid: uploadData.retrieve({id: originalId}).uuid,\n qqparentsize: uploadData.retrieve({id: originalId}).size\n };\n\n // Make sure the UUID for each scaled image is sent with the upload request,\n // to be consistent (since we may need to ensure it is sent for the original file as well).\n params[uuidParamName] = uploadData.retrieve({id: scaledId}).uuid;\n\n uploadData.setParentId(scaledId, originalId);\n paramsStore.addReadOnly(scaledId, params);\n });\n\n // If any scaled images are tied to this parent image, be SURE we send its UUID as an upload request\n // parameter as well.\n if (scaledIds.length) {\n (function() {\n var param = {};\n param[uuidParamName] = uploadData.retrieve({id: originalId}).uuid;\n paramsStore.addReadOnly(originalId, param);\n }());\n }\n }\n }\n });\n};\n\nqq.extend(qq.Scaler.prototype, {\n scaleImage: function(id, specs, api) {\n \"use strict\";\n\n if (!qq.supportedFeatures.scaling) {\n throw new qq.Error(\"Scaling is not supported in this browser!\");\n }\n\n var scalingEffort = new qq.Promise(),\n log = api.log,\n file = api.getFile(id),\n uploadData = api.uploadData.retrieve({id: id}),\n name = uploadData && uploadData.name,\n uuid = uploadData && uploadData.uuid,\n scalingOptions = {\n customResizer: specs.customResizer,\n sendOriginal: false,\n orient: specs.orient,\n defaultType: specs.type || null,\n defaultQuality: specs.quality,\n failedToScaleText: \"Unable to scale\",\n sizes: [{name: \"\", maxSize: specs.maxSize}]\n },\n scaler = new qq.Scaler(scalingOptions, log);\n\n if (!qq.Scaler || !qq.supportedFeatures.imagePreviews || !file) {\n scalingEffort.failure();\n\n log(\"Could not generate requested scaled image for \" + id + \". \" +\n \"Scaling is either not possible in this browser, or the file could not be located.\", \"error\");\n }\n else {\n (qq.bind(function() {\n // Assumption: There will never be more than one record\n var record = scaler.getFileRecords(uuid, name, file)[0];\n\n if (record && record.blob instanceof qq.BlobProxy) {\n record.blob.create().then(scalingEffort.success, scalingEffort.failure);\n }\n else {\n log(id + \" is not a scalable image!\", \"error\");\n scalingEffort.failure();\n }\n }, this)());\n }\n\n return scalingEffort;\n },\n\n // NOTE: We cannot reliably determine at this time if the UA supports a specific MIME type for the target format.\n // image/jpeg and image/png are the only safe choices at this time.\n _determineOutputType: function(spec) {\n \"use strict\";\n\n var requestedType = spec.requestedType,\n defaultType = spec.defaultType,\n referenceType = spec.refType;\n\n // If a default type and requested type have not been specified, this should be a\n // JPEG if the original type is a JPEG, otherwise, a PNG.\n if (!defaultType && !requestedType) {\n if (referenceType !== \"image/jpeg\") {\n return \"image/png\";\n }\n return referenceType;\n }\n\n // A specified default type is used when a requested type is not specified.\n if (!requestedType) {\n return defaultType;\n }\n\n // If requested type is specified, use it, as long as this recognized type is supported by the current UA\n if (qq.indexOf(Object.keys(qq.Identify.prototype.PREVIEWABLE_MIME_TYPES), requestedType) >= 0) {\n if (requestedType === \"image/tiff\") {\n return qq.supportedFeatures.tiffPreviews ? requestedType : defaultType;\n }\n\n return requestedType;\n }\n\n return defaultType;\n },\n\n // Get a file name for a generated scaled file record, based on the provided scaled image description\n _getName: function(originalName, scaledVersionProperties) {\n \"use strict\";\n\n var startOfExt = originalName.lastIndexOf(\".\"),\n versionType = scaledVersionProperties.type || \"image/png\",\n referenceType = scaledVersionProperties.refType,\n scaledName = \"\",\n scaledExt = qq.getExtension(originalName),\n nameAppendage = \"\";\n\n if (scaledVersionProperties.name && scaledVersionProperties.name.trim().length) {\n nameAppendage = \" (\" + scaledVersionProperties.name + \")\";\n }\n\n if (startOfExt >= 0) {\n scaledName = originalName.substr(0, startOfExt);\n\n if (referenceType !== versionType) {\n scaledExt = versionType.split(\"/\")[1];\n }\n\n scaledName += nameAppendage + \".\" + scaledExt;\n }\n else {\n scaledName = originalName + nameAppendage;\n }\n\n return scaledName;\n },\n\n // We want the smallest scaled file to be uploaded first\n _getSortedSizes: function(sizes) {\n \"use strict\";\n\n sizes = qq.extend([], sizes);\n\n return sizes.sort(function(a, b) {\n if (a.maxSize > b.maxSize) {\n return 1;\n }\n if (a.maxSize < b.maxSize) {\n return -1;\n }\n return 0;\n });\n },\n\n _generateScaledImage: function(spec, sourceFile) {\n \"use strict\";\n\n var self = this,\n customResizeFunction = spec.customResizeFunction,\n log = spec.log,\n maxSize = spec.maxSize,\n orient = spec.orient,\n type = spec.type,\n quality = spec.quality,\n failedText = spec.failedText,\n includeExif = spec.includeExif && sourceFile.type === \"image/jpeg\" && type === \"image/jpeg\",\n scalingEffort = new qq.Promise(),\n imageGenerator = new qq.ImageGenerator(log),\n canvas = document.createElement(\"canvas\");\n\n log(\"Attempting to generate scaled version for \" + sourceFile.name);\n\n imageGenerator.generate(sourceFile, canvas, {maxSize: maxSize, orient: orient, customResizeFunction: customResizeFunction}).then(function() {\n var scaledImageDataUri = canvas.toDataURL(type, quality),\n signalSuccess = function() {\n log(\"Success generating scaled version for \" + sourceFile.name);\n var blob = qq.dataUriToBlob(scaledImageDataUri);\n scalingEffort.success(blob);\n };\n\n if (includeExif) {\n self._insertExifHeader(sourceFile, scaledImageDataUri, log).then(function(scaledImageDataUriWithExif) {\n scaledImageDataUri = scaledImageDataUriWithExif;\n signalSuccess();\n },\n function() {\n log(\"Problem inserting EXIF header into scaled image. Using scaled image w/out EXIF data.\", \"error\");\n signalSuccess();\n });\n }\n else {\n signalSuccess();\n }\n }, function() {\n log(\"Failed attempt to generate scaled version for \" + sourceFile.name, \"error\");\n scalingEffort.failure(failedText);\n });\n\n return scalingEffort;\n },\n\n // Attempt to insert the original image's EXIF header into a scaled version.\n _insertExifHeader: function(originalImage, scaledImageDataUri, log) {\n \"use strict\";\n\n var reader = new FileReader(),\n insertionEffort = new qq.Promise(),\n originalImageDataUri = \"\";\n\n reader.onload = function() {\n originalImageDataUri = reader.result;\n insertionEffort.success(qq.ExifRestorer.restore(originalImageDataUri, scaledImageDataUri));\n };\n\n reader.onerror = function() {\n log(\"Problem reading \" + originalImage.name + \" during attempt to transfer EXIF data to scaled version.\", \"error\");\n insertionEffort.failure();\n };\n\n reader.readAsDataURL(originalImage);\n\n return insertionEffort;\n },\n\n _dataUriToBlob: function(dataUri) {\n \"use strict\";\n\n var byteString, mimeString, arrayBuffer, intArray;\n\n // convert base64 to raw binary data held in a string\n if (dataUri.split(\",\")[0].indexOf(\"base64\") >= 0) {\n byteString = atob(dataUri.split(\",\")[1]);\n }\n else {\n byteString = decodeURI(dataUri.split(\",\")[1]);\n }\n\n // extract the MIME\n mimeString = dataUri.split(\",\")[0]\n .split(\":\")[1]\n .split(\";\")[0];\n\n // write the bytes of the binary string to an ArrayBuffer\n arrayBuffer = new ArrayBuffer(byteString.length);\n intArray = new Uint8Array(arrayBuffer);\n qq.each(byteString, function(idx, character) {\n intArray[idx] = character.charCodeAt(0);\n });\n\n return this._createBlob(arrayBuffer, mimeString);\n },\n\n _createBlob: function(data, mime) {\n \"use strict\";\n\n var BlobBuilder = window.BlobBuilder ||\n window.WebKitBlobBuilder ||\n window.MozBlobBuilder ||\n window.MSBlobBuilder,\n blobBuilder = BlobBuilder && new BlobBuilder();\n\n if (blobBuilder) {\n blobBuilder.append(data);\n return blobBuilder.getBlob(mime);\n }\n else {\n return new Blob([data], {type: mime});\n }\n }\n});\n","//Based on MinifyJpeg\n//http://elicon.blog57.fc2.com/blog-entry-206.html\n\nqq.ExifRestorer = (function()\n{\n \n\tvar ExifRestorer = {};\n\t \n ExifRestorer.KEY_STR = \"ABCDEFGHIJKLMNOP\" +\n \"QRSTUVWXYZabcdef\" +\n \"ghijklmnopqrstuv\" +\n \"wxyz0123456789+/\" +\n \"=\";\n\n ExifRestorer.encode64 = function(input)\n {\n var output = \"\",\n chr1, chr2, chr3 = \"\",\n enc1, enc2, enc3, enc4 = \"\",\n i = 0;\n\n do {\n chr1 = input[i++];\n chr2 = input[i++];\n chr3 = input[i++];\n\n enc1 = chr1 >> 2;\n enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);\n enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);\n enc4 = chr3 & 63;\n\n if (isNaN(chr2)) {\n enc3 = enc4 = 64;\n } else if (isNaN(chr3)) {\n enc4 = 64;\n }\n\n output = output +\n this.KEY_STR.charAt(enc1) +\n this.KEY_STR.charAt(enc2) +\n this.KEY_STR.charAt(enc3) +\n this.KEY_STR.charAt(enc4);\n chr1 = chr2 = chr3 = \"\";\n enc1 = enc2 = enc3 = enc4 = \"\";\n } while (i < input.length);\n\n return output;\n };\n \n ExifRestorer.restore = function(origFileBase64, resizedFileBase64)\n {\n var expectedBase64Header = \"data:image/jpeg;base64,\";\n\n if (!origFileBase64.match(expectedBase64Header))\n {\n \treturn resizedFileBase64;\n } \n \n var rawImage = this.decode64(origFileBase64.replace(expectedBase64Header, \"\"));\n var segments = this.slice2Segments(rawImage);\n \n var image = this.exifManipulation(resizedFileBase64, segments);\n \n return expectedBase64Header + this.encode64(image);\n \n };\n\n\n ExifRestorer.exifManipulation = function(resizedFileBase64, segments)\n {\n var exifArray = this.getExifArray(segments),\n newImageArray = this.insertExif(resizedFileBase64, exifArray),\n aBuffer = new Uint8Array(newImageArray);\n\n return aBuffer;\n };\n\n\n ExifRestorer.getExifArray = function(segments)\n {\n var seg;\n for (var x = 0; x < segments.length; x++)\n {\n seg = segments[x];\n if (seg[0] == 255 & seg[1] == 225) //(ff e1)\n {\n return seg;\n }\n }\n return [];\n };\n\n\n ExifRestorer.insertExif = function(resizedFileBase64, exifArray)\n {\n var imageData = resizedFileBase64.replace(\"data:image/jpeg;base64,\", \"\"),\n buf = this.decode64(imageData),\n separatePoint = buf.indexOf(255,3),\n mae = buf.slice(0, separatePoint),\n ato = buf.slice(separatePoint),\n array = mae;\n\n array = array.concat(exifArray);\n array = array.concat(ato);\n return array;\n };\n\n\n \n ExifRestorer.slice2Segments = function(rawImageArray)\n {\n var head = 0,\n segments = [];\n\n while (1)\n {\n if (rawImageArray[head] == 255 & rawImageArray[head + 1] == 218){break;}\n if (rawImageArray[head] == 255 & rawImageArray[head + 1] == 216)\n {\n head += 2;\n }\n else\n {\n var length = rawImageArray[head + 2] * 256 + rawImageArray[head + 3],\n endPoint = head + length + 2,\n seg = rawImageArray.slice(head, endPoint);\n segments.push(seg);\n head = endPoint;\n }\n if (head > rawImageArray.length){break;}\n }\n\n return segments;\n };\n\n\n \n ExifRestorer.decode64 = function(input) \n {\n var output = \"\",\n chr1, chr2, chr3 = \"\",\n enc1, enc2, enc3, enc4 = \"\",\n i = 0,\n buf = [];\n\n // remove all characters that are not A-Z, a-z, 0-9, +, /, or =\n var base64test = /[^A-Za-z0-9\\+\\/\\=]/g;\n if (base64test.exec(input)) {\n throw new Error(\"There were invalid base64 characters in the input text. \" +\n \"Valid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='\");\n }\n input = input.replace(/[^A-Za-z0-9\\+\\/\\=]/g, \"\");\n\n do {\n enc1 = this.KEY_STR.indexOf(input.charAt(i++));\n enc2 = this.KEY_STR.indexOf(input.charAt(i++));\n enc3 = this.KEY_STR.indexOf(input.charAt(i++));\n enc4 = this.KEY_STR.indexOf(input.charAt(i++));\n\n chr1 = (enc1 << 2) | (enc2 >> 4);\n chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);\n chr3 = ((enc3 & 3) << 6) | enc4;\n\n buf.push(chr1);\n\n if (enc3 != 64) {\n buf.push(chr2);\n }\n if (enc4 != 64) {\n buf.push(chr3);\n }\n\n chr1 = chr2 = chr3 = \"\";\n enc1 = enc2 = enc3 = enc4 = \"\";\n\n } while (i < input.length);\n\n return buf;\n };\n\n \n return ExifRestorer;\n})();\n","/* globals qq */\n/**\n * Keeps a running tally of total upload progress for a batch of files.\n *\n * @param callback Invoked when total progress changes, passing calculated total loaded & total size values.\n * @param getSize Function that returns the size of a file given its ID\n * @constructor\n */\nqq.TotalProgress = function(callback, getSize) {\n \"use strict\";\n\n var perFileProgress = {},\n totalLoaded = 0,\n totalSize = 0,\n\n lastLoadedSent = -1,\n lastTotalSent = -1,\n callbackProxy = function(loaded, total) {\n if (loaded !== lastLoadedSent || total !== lastTotalSent) {\n callback(loaded, total);\n }\n\n lastLoadedSent = loaded;\n lastTotalSent = total;\n },\n\n /**\n * @param failed Array of file IDs that have failed\n * @param retryable Array of file IDs that are retryable\n * @returns true if none of the failed files are eligible for retry\n */\n noRetryableFiles = function(failed, retryable) {\n var none = true;\n\n qq.each(failed, function(idx, failedId) {\n if (qq.indexOf(retryable, failedId) >= 0) {\n none = false;\n return false;\n }\n });\n\n return none;\n },\n\n onCancel = function(id) {\n updateTotalProgress(id, -1, -1);\n delete perFileProgress[id];\n },\n\n onAllComplete = function(successful, failed, retryable) {\n if (failed.length === 0 || noRetryableFiles(failed, retryable)) {\n callbackProxy(totalSize, totalSize);\n this.reset();\n }\n },\n\n onNew = function(id) {\n var size = getSize(id);\n\n // We might not know the size yet, such as for blob proxies\n if (size > 0) {\n updateTotalProgress(id, 0, size);\n perFileProgress[id] = {loaded: 0, total: size};\n }\n },\n\n /**\n * Invokes the callback with the current total progress of all files in the batch. Called whenever it may\n * be appropriate to re-calculate and disseminate this data.\n *\n * @param id ID of a file that has changed in some important way\n * @param newLoaded New loaded value for this file. -1 if this value should no longer be part of calculations\n * @param newTotal New total size of the file. -1 if this value should no longer be part of calculations\n */\n updateTotalProgress = function(id, newLoaded, newTotal) {\n var oldLoaded = perFileProgress[id] ? perFileProgress[id].loaded : 0,\n oldTotal = perFileProgress[id] ? perFileProgress[id].total : 0;\n\n if (newLoaded === -1 && newTotal === -1) {\n totalLoaded -= oldLoaded;\n totalSize -= oldTotal;\n }\n else {\n if (newLoaded) {\n totalLoaded += newLoaded - oldLoaded;\n }\n if (newTotal) {\n totalSize += newTotal - oldTotal;\n }\n }\n\n callbackProxy(totalLoaded, totalSize);\n };\n\n qq.extend(this, {\n // Called when a batch of files has completed uploading.\n onAllComplete: onAllComplete,\n\n // Called when the status of a file has changed.\n onStatusChange: function(id, oldStatus, newStatus) {\n if (newStatus === qq.status.CANCELED || newStatus === qq.status.REJECTED) {\n onCancel(id);\n }\n else if (newStatus === qq.status.SUBMITTING) {\n onNew(id);\n }\n },\n\n // Called whenever the upload progress of an individual file has changed.\n onIndividualProgress: function(id, loaded, total) {\n updateTotalProgress(id, loaded, total);\n perFileProgress[id] = {loaded: loaded, total: total};\n },\n\n // Called whenever the total size of a file has changed, such as when the size of a generated blob is known.\n onNewSize: function(id) {\n onNew(id);\n },\n\n reset: function() {\n perFileProgress = {};\n totalLoaded = 0;\n totalSize = 0;\n }\n });\n};\n","/*globals qq*/\nqq.PasteSupport = function(o) {\n \"use strict\";\n\n var options, detachPasteHandler;\n\n options = {\n targetElement: null,\n callbacks: {\n log: function(message, level) {},\n pasteReceived: function(blob) {}\n }\n };\n\n function isImage(item) {\n return item.type &&\n item.type.indexOf(\"image/\") === 0;\n }\n\n function registerPasteHandler() {\n detachPasteHandler = qq(options.targetElement).attach(\"paste\", function(event) {\n var clipboardData = event.clipboardData;\n\n if (clipboardData) {\n qq.each(clipboardData.items, function(idx, item) {\n if (isImage(item)) {\n var blob = item.getAsFile();\n options.callbacks.pasteReceived(blob);\n }\n });\n }\n });\n }\n\n function unregisterPasteHandler() {\n if (detachPasteHandler) {\n detachPasteHandler();\n }\n }\n\n qq.extend(options, o);\n registerPasteHandler();\n\n qq.extend(this, {\n reset: function() {\n unregisterPasteHandler();\n }\n });\n};\n","/* globals qq */\n/**\n * Module that handles support for existing forms.\n *\n * @param options Options passed from the integrator-supplied options related to form support.\n * @param startUpload Callback to invoke when files \"stored\" should be uploaded.\n * @param log Proxy for the logger\n * @constructor\n */\nqq.FormSupport = function(options, startUpload, log) {\n \"use strict\";\n var self = this,\n interceptSubmit = options.interceptSubmit,\n formEl = options.element,\n autoUpload = options.autoUpload;\n\n // Available on the public API associated with this module.\n qq.extend(this, {\n // To be used by the caller to determine if the endpoint will be determined by some processing\n // that occurs in this module, such as if the form has an action attribute.\n // Ignore if `attachToForm === false`.\n newEndpoint: null,\n\n // To be used by the caller to determine if auto uploading should be allowed.\n // Ignore if `attachToForm === false`.\n newAutoUpload: autoUpload,\n\n // true if a form was detected and is being tracked by this module\n attachedToForm: false,\n\n // Returns an object with names and values for all valid form elements associated with the attached form.\n getFormInputsAsObject: function() {\n /* jshint eqnull:true */\n if (formEl == null) {\n return null;\n }\n\n return self._form2Obj(formEl);\n }\n });\n\n // If the form contains an action attribute, this should be the new upload endpoint.\n function determineNewEndpoint(formEl) {\n if (formEl.getAttribute(\"action\")) {\n self.newEndpoint = formEl.getAttribute(\"action\");\n }\n }\n\n // Return true only if the form is valid, or if we cannot make this determination.\n // If the form is invalid, ensure invalid field(s) are highlighted in the UI.\n function validateForm(formEl, nativeSubmit) {\n if (formEl.checkValidity && !formEl.checkValidity()) {\n log(\"Form did not pass validation checks - will not upload.\", \"error\");\n nativeSubmit();\n }\n else {\n return true;\n }\n }\n\n // Intercept form submit attempts, unless the integrator has told us not to do this.\n function maybeUploadOnSubmit(formEl) {\n var nativeSubmit = formEl.submit;\n\n // Intercept and squelch submit events.\n qq(formEl).attach(\"submit\", function(event) {\n event = event || window.event;\n\n if (event.preventDefault) {\n event.preventDefault();\n }\n else {\n event.returnValue = false;\n }\n\n validateForm(formEl, nativeSubmit) && startUpload();\n });\n\n // The form's `submit()` function may be called instead (i.e. via jQuery.submit()).\n // Intercept that too.\n formEl.submit = function() {\n validateForm(formEl, nativeSubmit) && startUpload();\n };\n }\n\n // If the element value passed from the uploader is a string, assume it is an element ID - select it.\n // The rest of the code in this module depends on this being an HTMLElement.\n function determineFormEl(formEl) {\n if (formEl) {\n if (qq.isString(formEl)) {\n formEl = document.getElementById(formEl);\n }\n\n if (formEl) {\n log(\"Attaching to form element.\");\n determineNewEndpoint(formEl);\n interceptSubmit && maybeUploadOnSubmit(formEl);\n }\n }\n\n return formEl;\n }\n\n formEl = determineFormEl(formEl);\n this.attachedToForm = !!formEl;\n};\n\nqq.extend(qq.FormSupport.prototype, {\n // Converts all relevant form fields to key/value pairs. This is meant to mimic the data a browser will\n // construct from a given form when the form is submitted.\n _form2Obj: function(form) {\n \"use strict\";\n var obj = {},\n notIrrelevantType = function(type) {\n var irrelevantTypes = [\n \"button\",\n \"image\",\n \"reset\",\n \"submit\"\n ];\n\n return qq.indexOf(irrelevantTypes, type.toLowerCase()) < 0;\n },\n radioOrCheckbox = function(type) {\n return qq.indexOf([\"checkbox\", \"radio\"], type.toLowerCase()) >= 0;\n },\n ignoreValue = function(el) {\n if (radioOrCheckbox(el.type) && !el.checked) {\n return true;\n }\n\n return el.disabled && el.type.toLowerCase() !== \"hidden\";\n },\n selectValue = function(select) {\n var value = null;\n\n qq.each(qq(select).children(), function(idx, child) {\n if (child.tagName.toLowerCase() === \"option\" && child.selected) {\n value = child.value;\n return false;\n }\n });\n\n return value;\n };\n\n qq.each(form.elements, function(idx, el) {\n if ((qq.isInput(el, true) || el.tagName.toLowerCase() === \"textarea\") &&\n notIrrelevantType(el.type) &&\n !ignoreValue(el)) {\n\n obj[el.name] = el.value;\n }\n else if (el.tagName.toLowerCase() === \"select\" && !ignoreValue(el)) {\n var value = selectValue(el);\n\n if (value !== null) {\n obj[el.name] = value;\n }\n }\n });\n\n return obj;\n }\n});\n","/*globals qq*/\n/**\n * Upload handler used that assumes the current user agent does not have any support for the\n * File API, and, therefore, makes use of iframes and forms to submit the files directly to\n * a generic server.\n *\n * @param options Options passed from the base handler\n * @param proxy Callbacks & methods used to query for or push out data/changes\n */\nqq.traditional = qq.traditional || {};\nqq.traditional.FormUploadHandler = function(options, proxy) {\n \"use strict\";\n\n var handler = this,\n getName = proxy.getName,\n getUuid = proxy.getUuid,\n log = proxy.log;\n\n /**\n * Returns json object received by iframe from server.\n */\n function getIframeContentJson(id, iframe) {\n /*jshint evil: true*/\n\n var response, doc, innerHtml;\n\n //IE may throw an \"access is denied\" error when attempting to access contentDocument on the iframe in some cases\n try {\n // iframe.contentWindow.document - for IE<7\n doc = iframe.contentDocument || iframe.contentWindow.document;\n innerHtml = doc.body.innerHTML;\n\n log(\"converting iframe's innerHTML to JSON\");\n log(\"innerHTML = \" + innerHtml);\n //plain text response may be wrapped in tag\n if (innerHtml && innerHtml.match(/^ 1 && !options.allowMultipleItems) {\n options.callbacks.processingDroppedFilesComplete([]);\n options.callbacks.dropError(\"tooManyFilesError\", \"\");\n uploadDropZone.dropDisabled(false);\n handleDataTransferPromise.failure();\n }\n else {\n droppedFiles = [];\n\n if (qq.isFolderDropSupported(dataTransfer)) {\n qq.each(dataTransfer.items, function(idx, item) {\n var entry = item.webkitGetAsEntry();\n\n if (entry) {\n //due to a bug in Chrome's File System API impl - #149735\n if (entry.isFile) {\n droppedFiles.push(item.getAsFile());\n }\n\n else {\n pendingFolderPromises.push(traverseFileTree(entry).done(function() {\n pendingFolderPromises.pop();\n if (pendingFolderPromises.length === 0) {\n handleDataTransferPromise.success();\n }\n }));\n }\n }\n });\n }\n else {\n droppedFiles = dataTransfer.files;\n }\n\n if (pendingFolderPromises.length === 0) {\n handleDataTransferPromise.success();\n }\n }\n\n return handleDataTransferPromise;\n }\n\n function setupDropzone(dropArea) {\n var dropZone = new qq.UploadDropZone({\n HIDE_ZONES_EVENT_NAME: HIDE_ZONES_EVENT_NAME,\n element: dropArea,\n onEnter: function(e) {\n qq(dropArea).addClass(options.classes.dropActive);\n e.stopPropagation();\n },\n onLeaveNotDescendants: function(e) {\n qq(dropArea).removeClass(options.classes.dropActive);\n },\n onDrop: function(e) {\n handleDataTransfer(e.dataTransfer, dropZone).then(\n function() {\n uploadDroppedFiles(droppedFiles, dropZone);\n },\n function() {\n options.callbacks.dropLog(\"Drop event DataTransfer parsing failed. No files will be uploaded.\", \"error\");\n }\n );\n }\n });\n\n disposeSupport.addDisposer(function() {\n dropZone.dispose();\n });\n\n qq(dropArea).hasAttribute(HIDE_BEFORE_ENTER_ATTR) && qq(dropArea).hide();\n\n uploadDropZones.push(dropZone);\n\n return dropZone;\n }\n\n function isFileDrag(dragEvent) {\n var fileDrag;\n\n qq.each(dragEvent.dataTransfer.types, function(key, val) {\n if (val === \"Files\") {\n fileDrag = true;\n return false;\n }\n });\n\n return fileDrag;\n }\n\n // Attempt to determine when the file has left the document. It is not always possible to detect this\n // in all cases, but it is generally possible in all browsers, with a few exceptions.\n //\n // Exceptions:\n // * IE10+ & Safari: We can't detect a file leaving the document if the Explorer window housing the file\n // overlays the browser window.\n // * IE10+: If the file is dragged out of the window too quickly, IE does not set the expected values of the\n // event's X & Y properties.\n function leavingDocumentOut(e) {\n if (qq.safari()) {\n return e.x < 0 || e.y < 0;\n }\n\n return e.x === 0 && e.y === 0;\n }\n\n function setupDragDrop() {\n var dropZones = options.dropZoneElements,\n\n maybeHideDropZones = function() {\n setTimeout(function() {\n qq.each(dropZones, function(idx, dropZone) {\n qq(dropZone).hasAttribute(HIDE_BEFORE_ENTER_ATTR) && qq(dropZone).hide();\n qq(dropZone).removeClass(options.classes.dropActive);\n });\n }, 10);\n };\n\n qq.each(dropZones, function(idx, dropZone) {\n var uploadDropZone = setupDropzone(dropZone);\n\n // IE <= 9 does not support the File API used for drag+drop uploads\n if (dropZones.length && qq.supportedFeatures.fileDrop) {\n disposeSupport.attach(document, \"dragenter\", function(e) {\n if (!uploadDropZone.dropDisabled() && isFileDrag(e)) {\n qq.each(dropZones, function(idx, dropZone) {\n // We can't apply styles to non-HTMLElements, since they lack the `style` property.\n // Also, if the drop zone isn't initially hidden, let's not mess with `style.display`.\n if (dropZone instanceof HTMLElement &&\n qq(dropZone).hasAttribute(HIDE_BEFORE_ENTER_ATTR)) {\n\n qq(dropZone).css({display: \"block\"});\n }\n });\n }\n });\n }\n });\n\n disposeSupport.attach(document, \"dragleave\", function(e) {\n if (leavingDocumentOut(e)) {\n maybeHideDropZones();\n }\n });\n\n // Just in case we were not able to detect when a dragged file has left the document,\n // hide all relevant drop zones the next time the mouse enters the document.\n // Note that mouse events such as this one are not fired during drag operations.\n disposeSupport.attach(qq(document).children()[0], \"mouseenter\", function(e) {\n maybeHideDropZones();\n });\n\n disposeSupport.attach(document, \"drop\", function(e) {\n if (isFileDrag(e)) {\n e.preventDefault();\n maybeHideDropZones();\n }\n });\n\n disposeSupport.attach(document, HIDE_ZONES_EVENT_NAME, maybeHideDropZones);\n }\n\n setupDragDrop();\n\n qq.extend(this, {\n setupExtraDropzone: function(element) {\n options.dropZoneElements.push(element);\n setupDropzone(element);\n },\n\n removeDropzone: function(element) {\n var i,\n dzs = options.dropZoneElements;\n\n for (i in dzs) {\n if (dzs[i] === element) {\n return dzs.splice(i, 1);\n }\n }\n },\n\n dispose: function() {\n disposeSupport.dispose();\n qq.each(uploadDropZones, function(idx, dropZone) {\n dropZone.dispose();\n });\n }\n });\n\n this._testing = {};\n this._testing.extractDirectoryPath = extractDirectoryPath;\n};\n\nqq.DragAndDrop.callbacks = function() {\n \"use strict\";\n\n return {\n processingDroppedFiles: function() {},\n processingDroppedFilesComplete: function(files, targetEl) {},\n dropError: function(code, errorSpecifics) {\n qq.log(\"Drag & drop error code '\" + code + \" with these specifics: '\" + errorSpecifics + \"'\", \"error\");\n },\n dropLog: function(message, level) {\n qq.log(message, level);\n }\n };\n};\n\nqq.UploadDropZone = function(o) {\n \"use strict\";\n\n var disposeSupport = new qq.DisposeSupport(),\n options, element, preventDrop, dropOutsideDisabled;\n\n options = {\n element: null,\n onEnter: function(e) {},\n onLeave: function(e) {},\n // is not fired when leaving element by hovering descendants\n onLeaveNotDescendants: function(e) {},\n onDrop: function(e) {}\n };\n\n qq.extend(options, o);\n element = options.element;\n\n function dragoverShouldBeCanceled() {\n return qq.safari() || (qq.firefox() && qq.windows());\n }\n\n function disableDropOutside(e) {\n // run only once for all instances\n if (!dropOutsideDisabled) {\n\n // for these cases we need to catch onDrop to reset dropArea\n if (dragoverShouldBeCanceled) {\n disposeSupport.attach(document, \"dragover\", function(e) {\n e.preventDefault();\n });\n } else {\n disposeSupport.attach(document, \"dragover\", function(e) {\n if (e.dataTransfer) {\n e.dataTransfer.dropEffect = \"none\";\n e.preventDefault();\n }\n });\n }\n\n dropOutsideDisabled = true;\n }\n }\n\n function isValidFileDrag(e) {\n // e.dataTransfer currently causing IE errors\n // IE9 does NOT support file API, so drag-and-drop is not possible\n if (!qq.supportedFeatures.fileDrop) {\n return false;\n }\n\n var effectTest, dt = e.dataTransfer,\n // do not check dt.types.contains in webkit, because it crashes safari 4\n isSafari = qq.safari();\n\n // dt.effectAllowed is none in Safari 5\n\n // dt.effectAllowed crashes IE 11 & 10 when files have been dragged from\n // the filesystem\n effectTest = qq.ie() && qq.supportedFeatures.fileDrop ? true : dt.effectAllowed !== \"none\";\n return dt && effectTest &&\n (\n (dt.files && dt.files.length) || // Valid for drop events with files\n (!isSafari && dt.types.contains && dt.types.contains(\"Files\")) || // Valid in Chrome/Firefox\n (dt.types.includes && dt.types.includes(\"Files\")) // Valid in IE\n );\n }\n\n function isOrSetDropDisabled(isDisabled) {\n if (isDisabled !== undefined) {\n preventDrop = isDisabled;\n }\n return preventDrop;\n }\n\n function triggerHidezonesEvent() {\n var hideZonesEvent;\n\n function triggerUsingOldApi() {\n hideZonesEvent = document.createEvent(\"Event\");\n hideZonesEvent.initEvent(options.HIDE_ZONES_EVENT_NAME, true, true);\n }\n\n if (window.CustomEvent) {\n try {\n hideZonesEvent = new CustomEvent(options.HIDE_ZONES_EVENT_NAME);\n }\n catch (err) {\n triggerUsingOldApi();\n }\n }\n else {\n triggerUsingOldApi();\n }\n\n document.dispatchEvent(hideZonesEvent);\n }\n\n function attachEvents() {\n disposeSupport.attach(element, \"dragover\", function(e) {\n if (!isValidFileDrag(e)) {\n return;\n }\n\n // dt.effectAllowed crashes IE 11 & 10 when files have been dragged from\n // the filesystem\n var effect = qq.ie() && qq.supportedFeatures.fileDrop ? null : e.dataTransfer.effectAllowed;\n if (effect === \"move\" || effect === \"linkMove\") {\n e.dataTransfer.dropEffect = \"move\"; // for FF (only move allowed)\n } else {\n e.dataTransfer.dropEffect = \"copy\"; // for Chrome\n }\n\n e.stopPropagation();\n e.preventDefault();\n });\n\n disposeSupport.attach(element, \"dragenter\", function(e) {\n if (!isOrSetDropDisabled()) {\n if (!isValidFileDrag(e)) {\n return;\n }\n options.onEnter(e);\n }\n });\n\n disposeSupport.attach(element, \"dragleave\", function(e) {\n if (!isValidFileDrag(e)) {\n return;\n }\n\n options.onLeave(e);\n\n var relatedTarget = document.elementFromPoint(e.clientX, e.clientY);\n // do not fire when moving a mouse over a descendant\n if (qq(this).contains(relatedTarget)) {\n return;\n }\n\n options.onLeaveNotDescendants(e);\n });\n\n disposeSupport.attach(element, \"drop\", function(e) {\n if (!isOrSetDropDisabled()) {\n if (!isValidFileDrag(e)) {\n return;\n }\n\n e.preventDefault();\n e.stopPropagation();\n options.onDrop(e);\n\n triggerHidezonesEvent();\n }\n });\n }\n\n disableDropOutside();\n attachEvents();\n\n qq.extend(this, {\n dropDisabled: function(isDisabled) {\n return isOrSetDropDisabled(isDisabled);\n },\n\n dispose: function() {\n disposeSupport.dispose();\n },\n\n getElement: function() {\n return element;\n }\n });\n\n this._testing = {};\n this._testing.isValidFileDrag = isValidFileDrag;\n};\n","/*globals qq */\n/**\n * Defines the public API for FineUploader mode.\n */\n(function() {\n \"use strict\";\n\n qq.uiPublicApi = {\n addInitialFiles: function(cannedFileList) {\n this._parent.prototype.addInitialFiles.apply(this, arguments);\n this._templating.addCacheToDom();\n },\n\n clearStoredFiles: function() {\n this._parent.prototype.clearStoredFiles.apply(this, arguments);\n this._templating.clearFiles();\n },\n\n addExtraDropzone: function(element) {\n this._dnd && this._dnd.setupExtraDropzone(element);\n },\n\n removeExtraDropzone: function(element) {\n if (this._dnd) {\n return this._dnd.removeDropzone(element);\n }\n },\n\n getItemByFileId: function(id) {\n if (!this._templating.isHiddenForever(id)) {\n return this._templating.getFileContainer(id);\n }\n },\n\n reset: function() {\n this._parent.prototype.reset.apply(this, arguments);\n this._templating.reset();\n\n if (!this._options.button && this._templating.getButton()) {\n this._defaultButtonId = this._createUploadButton({\n element: this._templating.getButton(),\n title: this._options.text.fileInputTitle\n }).getButtonId();\n }\n\n if (this._dnd) {\n this._dnd.dispose();\n this._dnd = this._setupDragAndDrop();\n }\n\n this._totalFilesInBatch = 0;\n this._filesInBatchAddedToUi = 0;\n\n this._setupClickAndEditEventHandlers();\n },\n\n setName: function(id, newName) {\n var formattedFilename = this._options.formatFileName(newName);\n\n this._parent.prototype.setName.apply(this, arguments);\n this._templating.updateFilename(id, formattedFilename);\n },\n\n pauseUpload: function(id) {\n var paused = this._parent.prototype.pauseUpload.apply(this, arguments);\n\n paused && this._templating.uploadPaused(id);\n return paused;\n },\n\n continueUpload: function(id) {\n var continued = this._parent.prototype.continueUpload.apply(this, arguments);\n\n continued && this._templating.uploadContinued(id);\n return continued;\n },\n\n getId: function(fileContainerOrChildEl) {\n return this._templating.getFileId(fileContainerOrChildEl);\n },\n\n getDropTarget: function(fileId) {\n var file = this.getFile(fileId);\n\n return file.qqDropTarget;\n }\n };\n\n /**\n * Defines the private (internal) API for FineUploader mode.\n */\n qq.uiPrivateApi = {\n _getButton: function(buttonId) {\n var button = this._parent.prototype._getButton.apply(this, arguments);\n\n if (!button) {\n if (buttonId === this._defaultButtonId) {\n button = this._templating.getButton();\n }\n }\n\n return button;\n },\n\n _removeFileItem: function(fileId) {\n this._templating.removeFile(fileId);\n },\n\n _setupClickAndEditEventHandlers: function() {\n this._fileButtonsClickHandler = qq.FileButtonsClickHandler && this._bindFileButtonsClickEvent();\n\n // A better approach would be to check specifically for focusin event support by querying the DOM API,\n // but the DOMFocusIn event is not exposed as a property, so we have to resort to UA string sniffing.\n this._focusinEventSupported = !qq.firefox();\n\n if (this._isEditFilenameEnabled())\n {\n this._filenameClickHandler = this._bindFilenameClickEvent();\n this._filenameInputFocusInHandler = this._bindFilenameInputFocusInEvent();\n this._filenameInputFocusHandler = this._bindFilenameInputFocusEvent();\n }\n },\n\n _setupDragAndDrop: function() {\n var self = this,\n dropZoneElements = this._options.dragAndDrop.extraDropzones,\n templating = this._templating,\n defaultDropZone = templating.getDropZone();\n\n defaultDropZone && dropZoneElements.push(defaultDropZone);\n\n return new qq.DragAndDrop({\n dropZoneElements: dropZoneElements,\n allowMultipleItems: this._options.multiple,\n classes: {\n dropActive: this._options.classes.dropActive\n },\n callbacks: {\n processingDroppedFiles: function() {\n templating.showDropProcessing();\n },\n processingDroppedFilesComplete: function(files, targetEl) {\n templating.hideDropProcessing();\n\n qq.each(files, function(idx, file) {\n file.qqDropTarget = targetEl;\n });\n\n if (files.length) {\n self.addFiles(files, null, null);\n }\n },\n dropError: function(code, errorData) {\n self._itemError(code, errorData);\n },\n dropLog: function(message, level) {\n self.log(message, level);\n }\n }\n });\n },\n\n _bindFileButtonsClickEvent: function() {\n var self = this;\n\n return new qq.FileButtonsClickHandler({\n templating: this._templating,\n\n log: function(message, lvl) {\n self.log(message, lvl);\n },\n\n onDeleteFile: function(fileId) {\n self.deleteFile(fileId);\n },\n\n onCancel: function(fileId) {\n self.cancel(fileId);\n },\n\n onRetry: function(fileId) {\n self.retry(fileId);\n },\n\n onPause: function(fileId) {\n self.pauseUpload(fileId);\n },\n\n onContinue: function(fileId) {\n self.continueUpload(fileId);\n },\n\n onGetName: function(fileId) {\n return self.getName(fileId);\n }\n });\n },\n\n _isEditFilenameEnabled: function() {\n /*jshint -W014 */\n return this._templating.isEditFilenamePossible()\n && !this._options.autoUpload\n && qq.FilenameClickHandler\n && qq.FilenameInputFocusHandler\n && qq.FilenameInputFocusHandler;\n },\n\n _filenameEditHandler: function() {\n var self = this,\n templating = this._templating;\n\n return {\n templating: templating,\n log: function(message, lvl) {\n self.log(message, lvl);\n },\n onGetUploadStatus: function(fileId) {\n return self.getUploads({id: fileId}).status;\n },\n onGetName: function(fileId) {\n return self.getName(fileId);\n },\n onSetName: function(id, newName) {\n self.setName(id, newName);\n },\n onEditingStatusChange: function(id, isEditing) {\n var qqInput = qq(templating.getEditInput(id)),\n qqFileContainer = qq(templating.getFileContainer(id));\n\n if (isEditing) {\n qqInput.addClass(\"qq-editing\");\n templating.hideFilename(id);\n templating.hideEditIcon(id);\n }\n else {\n qqInput.removeClass(\"qq-editing\");\n templating.showFilename(id);\n templating.showEditIcon(id);\n }\n\n // Force IE8 and older to repaint\n qqFileContainer.addClass(\"qq-temp\").removeClass(\"qq-temp\");\n }\n };\n },\n\n _onUploadStatusChange: function(id, oldStatus, newStatus) {\n this._parent.prototype._onUploadStatusChange.apply(this, arguments);\n\n if (this._isEditFilenameEnabled()) {\n // Status for a file exists before it has been added to the DOM, so we must be careful here.\n if (this._templating.getFileContainer(id) && newStatus !== qq.status.SUBMITTED) {\n this._templating.markFilenameEditable(id);\n this._templating.hideEditIcon(id);\n }\n }\n\n if (oldStatus === qq.status.UPLOAD_RETRYING && newStatus === qq.status.UPLOADING) {\n this._templating.hideRetry(id);\n this._templating.setStatusText(id);\n qq(this._templating.getFileContainer(id)).removeClass(this._classes.retrying);\n }\n else if (newStatus === qq.status.UPLOAD_FAILED) {\n this._templating.hidePause(id);\n }\n },\n\n _bindFilenameInputFocusInEvent: function() {\n var spec = qq.extend({}, this._filenameEditHandler());\n\n return new qq.FilenameInputFocusInHandler(spec);\n },\n\n _bindFilenameInputFocusEvent: function() {\n var spec = qq.extend({}, this._filenameEditHandler());\n\n return new qq.FilenameInputFocusHandler(spec);\n },\n\n _bindFilenameClickEvent: function() {\n var spec = qq.extend({}, this._filenameEditHandler());\n\n return new qq.FilenameClickHandler(spec);\n },\n\n _storeForLater: function(id) {\n this._parent.prototype._storeForLater.apply(this, arguments);\n this._templating.hideSpinner(id);\n },\n\n _onAllComplete: function(successful, failed) {\n this._parent.prototype._onAllComplete.apply(this, arguments);\n this._templating.resetTotalProgress();\n },\n\n _onSubmit: function(id, name) {\n var file = this.getFile(id);\n\n if (file && file.qqPath && this._options.dragAndDrop.reportDirectoryPaths) {\n this._paramsStore.addReadOnly(id, {\n qqpath: file.qqPath\n });\n }\n\n this._parent.prototype._onSubmit.apply(this, arguments);\n this._addToList(id, name);\n },\n\n // The file item has been added to the DOM.\n _onSubmitted: function(id) {\n // If the edit filename feature is enabled, mark the filename element as \"editable\" and the associated edit icon\n if (this._isEditFilenameEnabled()) {\n this._templating.markFilenameEditable(id);\n this._templating.showEditIcon(id);\n\n // If the focusin event is not supported, we must add a focus handler to the newly create edit filename text input\n if (!this._focusinEventSupported) {\n this._filenameInputFocusHandler.addHandler(this._templating.getEditInput(id));\n }\n }\n },\n\n // Update the progress bar & percentage as the file is uploaded\n _onProgress: function(id, name, loaded, total) {\n this._parent.prototype._onProgress.apply(this, arguments);\n\n this._templating.updateProgress(id, loaded, total);\n\n if (total === 0 || Math.round(loaded / total * 100) === 100) {\n this._templating.hideCancel(id);\n this._templating.hidePause(id);\n this._templating.hideProgress(id);\n this._templating.setStatusText(id, this._options.text.waitingForResponse);\n\n // If ~last byte was sent, display total file size\n this._displayFileSize(id);\n }\n else {\n // If still uploading, display percentage - total size is actually the total request(s) size\n this._displayFileSize(id, loaded, total);\n }\n },\n\n _onTotalProgress: function(loaded, total) {\n this._parent.prototype._onTotalProgress.apply(this, arguments);\n this._templating.updateTotalProgress(loaded, total);\n },\n\n _onComplete: function(id, name, result, xhr) {\n var parentRetVal = this._parent.prototype._onComplete.apply(this, arguments),\n templating = this._templating,\n fileContainer = templating.getFileContainer(id),\n self = this;\n\n function completeUpload(result) {\n // If this file is not represented in the templating module, perhaps it was hidden intentionally.\n // If so, don't perform any UI-related tasks related to this file.\n if (!fileContainer) {\n return;\n }\n\n templating.setStatusText(id);\n\n qq(fileContainer).removeClass(self._classes.retrying);\n templating.hideProgress(id);\n\n if (self.getUploads({id: id}).status !== qq.status.UPLOAD_FAILED) {\n templating.hideCancel(id);\n }\n templating.hideSpinner(id);\n\n if (result.success) {\n self._markFileAsSuccessful(id);\n }\n else {\n qq(fileContainer).addClass(self._classes.fail);\n templating.showCancel(id);\n\n if (templating.isRetryPossible() && !self._preventRetries[id]) {\n qq(fileContainer).addClass(self._classes.retryable);\n templating.showRetry(id);\n }\n self._controlFailureTextDisplay(id, result);\n }\n }\n\n // The parent may need to perform some async operation before we can accurately determine the status of the upload.\n if (parentRetVal instanceof qq.Promise) {\n parentRetVal.done(function(newResult) {\n completeUpload(newResult);\n });\n\n }\n else {\n completeUpload(result);\n }\n\n return parentRetVal;\n },\n\n _markFileAsSuccessful: function(id) {\n var templating = this._templating;\n\n if (this._isDeletePossible()) {\n templating.showDeleteButton(id);\n }\n\n qq(templating.getFileContainer(id)).addClass(this._classes.success);\n\n this._maybeUpdateThumbnail(id);\n },\n\n _onUploadPrep: function(id) {\n this._parent.prototype._onUploadPrep.apply(this, arguments);\n this._templating.showSpinner(id);\n },\n\n _onUpload: function(id, name) {\n var parentRetVal = this._parent.prototype._onUpload.apply(this, arguments);\n\n this._templating.showSpinner(id);\n\n return parentRetVal;\n },\n\n _onUploadChunk: function(id, chunkData) {\n this._parent.prototype._onUploadChunk.apply(this, arguments);\n\n // Only display the pause button if we have finished uploading at least one chunk\n // & this file can be resumed\n if (chunkData.partIndex > 0 && this._handler.isResumable(id)) {\n this._templating.allowPause(id);\n }\n },\n\n _onCancel: function(id, name) {\n this._parent.prototype._onCancel.apply(this, arguments);\n this._removeFileItem(id);\n\n if (this._getNotFinished() === 0) {\n this._templating.resetTotalProgress();\n }\n },\n\n _onBeforeAutoRetry: function(id) {\n var retryNumForDisplay, maxAuto, retryNote;\n\n this._parent.prototype._onBeforeAutoRetry.apply(this, arguments);\n\n this._showCancelLink(id);\n\n if (this._options.retry.showAutoRetryNote) {\n retryNumForDisplay = this._autoRetries[id];\n maxAuto = this._options.retry.maxAutoAttempts;\n\n retryNote = this._options.retry.autoRetryNote.replace(/\\{retryNum\\}/g, retryNumForDisplay);\n retryNote = retryNote.replace(/\\{maxAuto\\}/g, maxAuto);\n\n this._templating.setStatusText(id, retryNote);\n qq(this._templating.getFileContainer(id)).addClass(this._classes.retrying);\n }\n },\n\n //return false if we should not attempt the requested retry\n _onBeforeManualRetry: function(id) {\n if (this._parent.prototype._onBeforeManualRetry.apply(this, arguments)) {\n this._templating.resetProgress(id);\n qq(this._templating.getFileContainer(id)).removeClass(this._classes.fail);\n this._templating.setStatusText(id);\n this._templating.showSpinner(id);\n this._showCancelLink(id);\n return true;\n }\n else {\n qq(this._templating.getFileContainer(id)).addClass(this._classes.retryable);\n this._templating.showRetry(id);\n return false;\n }\n },\n\n _onSubmitDelete: function(id) {\n var onSuccessCallback = qq.bind(this._onSubmitDeleteSuccess, this);\n\n this._parent.prototype._onSubmitDelete.call(this, id, onSuccessCallback);\n },\n\n _onSubmitDeleteSuccess: function(id, uuid, additionalMandatedParams) {\n if (this._options.deleteFile.forceConfirm) {\n this._showDeleteConfirm.apply(this, arguments);\n }\n else {\n this._sendDeleteRequest.apply(this, arguments);\n }\n },\n\n _onDeleteComplete: function(id, xhr, isError) {\n this._parent.prototype._onDeleteComplete.apply(this, arguments);\n\n this._templating.hideSpinner(id);\n\n if (isError) {\n this._templating.setStatusText(id, this._options.deleteFile.deletingFailedText);\n this._templating.showDeleteButton(id);\n }\n else {\n this._removeFileItem(id);\n }\n },\n\n _sendDeleteRequest: function(id, uuid, additionalMandatedParams) {\n this._templating.hideDeleteButton(id);\n this._templating.showSpinner(id);\n this._templating.setStatusText(id, this._options.deleteFile.deletingStatusText);\n this._deleteHandler.sendDelete.apply(this, arguments);\n },\n\n _showDeleteConfirm: function(id, uuid, mandatedParams) {\n /*jshint -W004 */\n var fileName = this.getName(id),\n confirmMessage = this._options.deleteFile.confirmMessage.replace(/\\{filename\\}/g, fileName),\n uuid = this.getUuid(id),\n deleteRequestArgs = arguments,\n self = this,\n retVal;\n\n retVal = this._options.showConfirm(confirmMessage);\n\n if (qq.isGenericPromise(retVal)) {\n retVal.then(function() {\n self._sendDeleteRequest.apply(self, deleteRequestArgs);\n });\n }\n else if (retVal !== false) {\n self._sendDeleteRequest.apply(self, deleteRequestArgs);\n }\n },\n\n _addToList: function(id, name, canned) {\n var prependData,\n prependIndex = 0,\n dontDisplay = this._handler.isProxied(id) && this._options.scaling.hideScaled,\n record;\n\n if (this._options.display.prependFiles) {\n if (this._totalFilesInBatch > 1 && this._filesInBatchAddedToUi > 0) {\n prependIndex = this._filesInBatchAddedToUi - 1;\n }\n\n prependData = {\n index: prependIndex\n };\n }\n\n if (!canned) {\n if (this._options.disableCancelForFormUploads && !qq.supportedFeatures.ajaxUploading) {\n this._templating.disableCancel();\n }\n\n // Cancel all existing (previous) files and clear the list if this file is not part of\n // a scaled file group that has already been accepted, or if this file is not part of\n // a scaled file group at all.\n if (!this._options.multiple) {\n record = this.getUploads({id: id});\n\n this._handledProxyGroup = this._handledProxyGroup || record.proxyGroupId;\n\n if (record.proxyGroupId !== this._handledProxyGroup || !record.proxyGroupId) {\n this._handler.cancelAll();\n this._clearList();\n this._handledProxyGroup = null;\n }\n }\n }\n\n if (canned) {\n this._templating.addFileToCache(id, this._options.formatFileName(name), prependData, dontDisplay);\n this._templating.updateThumbnail(id, this._thumbnailUrls[id], true, this._options.thumbnails.customResizer);\n }\n else {\n this._templating.addFile(id, this._options.formatFileName(name), prependData, dontDisplay);\n this._templating.generatePreview(id, this.getFile(id), this._options.thumbnails.customResizer);\n }\n\n this._filesInBatchAddedToUi += 1;\n\n if (canned ||\n (this._options.display.fileSizeOnSubmit && qq.supportedFeatures.ajaxUploading)) {\n\n this._displayFileSize(id);\n }\n },\n\n _clearList: function() {\n this._templating.clearFiles();\n this.clearStoredFiles();\n },\n\n _displayFileSize: function(id, loadedSize, totalSize) {\n var size = this.getSize(id),\n sizeForDisplay = this._formatSize(size);\n\n if (size >= 0) {\n if (loadedSize !== undefined && totalSize !== undefined) {\n sizeForDisplay = this._formatProgress(loadedSize, totalSize);\n }\n\n this._templating.updateSize(id, sizeForDisplay);\n }\n },\n\n _formatProgress: function(uploadedSize, totalSize) {\n var message = this._options.text.formatProgress;\n function r(name, replacement) { message = message.replace(name, replacement); }\n\n r(\"{percent}\", Math.round(uploadedSize / totalSize * 100));\n r(\"{total_size}\", this._formatSize(totalSize));\n return message;\n },\n\n _controlFailureTextDisplay: function(id, response) {\n var mode, responseProperty, failureReason;\n\n mode = this._options.failedUploadTextDisplay.mode;\n responseProperty = this._options.failedUploadTextDisplay.responseProperty;\n\n if (mode === \"custom\") {\n failureReason = response[responseProperty];\n if (!failureReason) {\n failureReason = this._options.text.failUpload;\n }\n\n this._templating.setStatusText(id, failureReason);\n\n if (this._options.failedUploadTextDisplay.enableTooltip) {\n this._showTooltip(id, failureReason);\n }\n }\n else if (mode === \"default\") {\n this._templating.setStatusText(id, this._options.text.failUpload);\n }\n else if (mode !== \"none\") {\n this.log(\"failedUploadTextDisplay.mode value of '\" + mode + \"' is not valid\", \"warn\");\n }\n },\n\n _showTooltip: function(id, text) {\n this._templating.getFileContainer(id).title = text;\n },\n\n _showCancelLink: function(id) {\n if (!this._options.disableCancelForFormUploads || qq.supportedFeatures.ajaxUploading) {\n this._templating.showCancel(id);\n }\n },\n\n _itemError: function(code, name, item) {\n var message = this._parent.prototype._itemError.apply(this, arguments);\n this._options.showMessage(message);\n },\n\n _batchError: function(message) {\n this._parent.prototype._batchError.apply(this, arguments);\n this._options.showMessage(message);\n },\n\n _setupPastePrompt: function() {\n var self = this;\n\n this._options.callbacks.onPasteReceived = function() {\n var message = self._options.paste.namePromptMessage,\n defaultVal = self._options.paste.defaultName;\n\n return self._options.showPrompt(message, defaultVal);\n };\n },\n\n _fileOrBlobRejected: function(id, name) {\n this._totalFilesInBatch -= 1;\n this._parent.prototype._fileOrBlobRejected.apply(this, arguments);\n },\n\n _prepareItemsForUpload: function(items, params, endpoint) {\n this._totalFilesInBatch = items.length;\n this._filesInBatchAddedToUi = 0;\n this._parent.prototype._prepareItemsForUpload.apply(this, arguments);\n },\n\n _maybeUpdateThumbnail: function(fileId) {\n var thumbnailUrl = this._thumbnailUrls[fileId],\n fileStatus = this.getUploads({id: fileId}).status;\n\n if (fileStatus !== qq.status.DELETED &&\n (thumbnailUrl ||\n this._options.thumbnails.placeholders.waitUntilResponse ||\n !qq.supportedFeatures.imagePreviews)) {\n\n // This will replace the \"waiting\" placeholder with a \"preview not available\" placeholder\n // if called with a null thumbnailUrl.\n this._templating.updateThumbnail(fileId, thumbnailUrl, this._options.thumbnails.customResizer);\n }\n },\n\n _addCannedFile: function(sessionData) {\n var id = this._parent.prototype._addCannedFile.apply(this, arguments);\n\n this._addToList(id, this.getName(id), true);\n this._templating.hideSpinner(id);\n this._templating.hideCancel(id);\n this._markFileAsSuccessful(id);\n\n return id;\n },\n\n _setSize: function(id, newSize) {\n this._parent.prototype._setSize.apply(this, arguments);\n\n this._templating.updateSize(id, this._formatSize(newSize));\n },\n\n _sessionRequestComplete: function() {\n this._templating.addCacheToDom();\n this._parent.prototype._sessionRequestComplete.apply(this, arguments);\n }\n };\n}());\n","/*globals qq */\n/**\n * This defines FineUploader mode, which is a default UI w/ drag & drop uploading.\n */\nqq.FineUploader = function(o, namespace) {\n \"use strict\";\n\n var self = this;\n\n // By default this should inherit instance data from FineUploaderBasic, but this can be overridden\n // if the (internal) caller defines a different parent. The parent is also used by\n // the private and public API functions that need to delegate to a parent function.\n this._parent = namespace ? qq[namespace].FineUploaderBasic : qq.FineUploaderBasic;\n this._parent.apply(this, arguments);\n\n // Options provided by FineUploader mode\n qq.extend(this._options, {\n element: null,\n\n button: null,\n\n listElement: null,\n\n dragAndDrop: {\n extraDropzones: [],\n reportDirectoryPaths: false\n },\n\n text: {\n formatProgress: \"{percent}% of {total_size}\",\n failUpload: \"Upload failed\",\n waitingForResponse: \"Processing...\",\n paused: \"Paused\"\n },\n\n template: \"qq-template\",\n\n classes: {\n retrying: \"qq-upload-retrying\",\n retryable: \"qq-upload-retryable\",\n success: \"qq-upload-success\",\n fail: \"qq-upload-fail\",\n editable: \"qq-editable\",\n hide: \"qq-hide\",\n dropActive: \"qq-upload-drop-area-active\"\n },\n\n failedUploadTextDisplay: {\n mode: \"default\", //default, custom, or none\n responseProperty: \"error\",\n enableTooltip: true\n },\n\n messages: {\n tooManyFilesError: \"You may only drop one file\",\n unsupportedBrowser: \"Unrecoverable error - this browser does not permit file uploading of any kind.\"\n },\n\n retry: {\n showAutoRetryNote: true,\n autoRetryNote: \"Retrying {retryNum}/{maxAuto}...\"\n },\n\n deleteFile: {\n forceConfirm: false,\n confirmMessage: \"Are you sure you want to delete {filename}?\",\n deletingStatusText: \"Deleting...\",\n deletingFailedText: \"Delete failed\"\n\n },\n\n display: {\n fileSizeOnSubmit: false,\n prependFiles: false\n },\n\n paste: {\n promptForName: false,\n namePromptMessage: \"Please name this image\"\n },\n\n thumbnails: {\n customResizer: null,\n maxCount: 0,\n placeholders: {\n waitUntilResponse: false,\n notAvailablePath: null,\n waitingPath: null\n },\n timeBetweenThumbs: 750\n },\n\n scaling: {\n hideScaled: false\n },\n\n showMessage: function(message) {\n if (self._templating.hasDialog(\"alert\")) {\n return self._templating.showDialog(\"alert\", message);\n }\n else {\n setTimeout(function() {\n window.alert(message);\n }, 0);\n }\n },\n\n showConfirm: function(message) {\n if (self._templating.hasDialog(\"confirm\")) {\n return self._templating.showDialog(\"confirm\", message);\n }\n else {\n return window.confirm(message);\n }\n },\n\n showPrompt: function(message, defaultValue) {\n if (self._templating.hasDialog(\"prompt\")) {\n return self._templating.showDialog(\"prompt\", message, defaultValue);\n }\n else {\n return window.prompt(message, defaultValue);\n }\n }\n }, true);\n\n // Replace any default options with user defined ones\n qq.extend(this._options, o, true);\n\n this._templating = new qq.Templating({\n log: qq.bind(this.log, this),\n templateIdOrEl: this._options.template,\n containerEl: this._options.element,\n fileContainerEl: this._options.listElement,\n button: this._options.button,\n imageGenerator: this._imageGenerator,\n classes: {\n hide: this._options.classes.hide,\n editable: this._options.classes.editable\n },\n limits: {\n maxThumbs: this._options.thumbnails.maxCount,\n timeBetweenThumbs: this._options.thumbnails.timeBetweenThumbs\n },\n placeholders: {\n waitUntilUpdate: this._options.thumbnails.placeholders.waitUntilResponse,\n thumbnailNotAvailable: this._options.thumbnails.placeholders.notAvailablePath,\n waitingForThumbnail: this._options.thumbnails.placeholders.waitingPath\n },\n text: this._options.text\n });\n\n if (this._options.workarounds.ios8SafariUploads && qq.ios800() && qq.iosSafari()) {\n this._templating.renderFailure(this._options.messages.unsupportedBrowserIos8Safari);\n }\n else if (!qq.supportedFeatures.uploading || (this._options.cors.expected && !qq.supportedFeatures.uploadCors)) {\n this._templating.renderFailure(this._options.messages.unsupportedBrowser);\n }\n else {\n this._wrapCallbacks();\n\n this._templating.render();\n\n this._classes = this._options.classes;\n\n if (!this._options.button && this._templating.getButton()) {\n this._defaultButtonId = this._createUploadButton({\n element: this._templating.getButton(),\n title: this._options.text.fileInputTitle\n }).getButtonId();\n }\n\n this._setupClickAndEditEventHandlers();\n\n if (qq.DragAndDrop && qq.supportedFeatures.fileDrop) {\n this._dnd = this._setupDragAndDrop();\n }\n\n if (this._options.paste.targetElement && this._options.paste.promptForName) {\n if (qq.PasteSupport) {\n this._setupPastePrompt();\n }\n else {\n this.log(\"Paste support module not found.\", \"error\");\n }\n }\n\n this._totalFilesInBatch = 0;\n this._filesInBatchAddedToUi = 0;\n }\n};\n\n// Inherit the base public & private API methods\nqq.extend(qq.FineUploader.prototype, qq.basePublicApi);\nqq.extend(qq.FineUploader.prototype, qq.basePrivateApi);\n\n// Add the FineUploader/default UI public & private UI methods, which may override some base methods.\nqq.extend(qq.FineUploader.prototype, qq.uiPublicApi);\nqq.extend(qq.FineUploader.prototype, qq.uiPrivateApi);\n","/* globals qq */\n/* jshint -W065 */\n/**\n * Module responsible for rendering all Fine Uploader UI templates. This module also asserts at least\n * a limited amount of control over the template elements after they are added to the DOM.\n * Wherever possible, this module asserts total control over template elements present in the DOM.\n *\n * @param spec Specification object used to control various templating behaviors\n * @constructor\n */\nqq.Templating = function(spec) {\n \"use strict\";\n\n var FILE_ID_ATTR = \"qq-file-id\",\n FILE_CLASS_PREFIX = \"qq-file-id-\",\n THUMBNAIL_MAX_SIZE_ATTR = \"qq-max-size\",\n THUMBNAIL_SERVER_SCALE_ATTR = \"qq-server-scale\",\n // This variable is duplicated in the DnD module since it can function as a standalone as well\n HIDE_DROPZONE_ATTR = \"qq-hide-dropzone\",\n DROPZPONE_TEXT_ATTR = \"qq-drop-area-text\",\n IN_PROGRESS_CLASS = \"qq-in-progress\",\n HIDDEN_FOREVER_CLASS = \"qq-hidden-forever\",\n fileBatch = {\n content: document.createDocumentFragment(),\n map: {}\n },\n isCancelDisabled = false,\n generatedThumbnails = 0,\n thumbnailQueueMonitorRunning = false,\n thumbGenerationQueue = [],\n thumbnailMaxSize = -1,\n options = {\n log: null,\n limits: {\n maxThumbs: 0,\n timeBetweenThumbs: 750\n },\n templateIdOrEl: \"qq-template\",\n containerEl: null,\n fileContainerEl: null,\n button: null,\n imageGenerator: null,\n classes: {\n hide: \"qq-hide\",\n editable: \"qq-editable\"\n },\n placeholders: {\n waitUntilUpdate: false,\n thumbnailNotAvailable: null,\n waitingForThumbnail: null\n },\n text: {\n paused: \"Paused\"\n }\n },\n selectorClasses = {\n button: \"qq-upload-button-selector\",\n alertDialog: \"qq-alert-dialog-selector\",\n dialogCancelButton: \"qq-cancel-button-selector\",\n confirmDialog: \"qq-confirm-dialog-selector\",\n dialogMessage: \"qq-dialog-message-selector\",\n dialogOkButton: \"qq-ok-button-selector\",\n promptDialog: \"qq-prompt-dialog-selector\",\n uploader: \"qq-uploader-selector\",\n drop: \"qq-upload-drop-area-selector\",\n list: \"qq-upload-list-selector\",\n progressBarContainer: \"qq-progress-bar-container-selector\",\n progressBar: \"qq-progress-bar-selector\",\n totalProgressBarContainer: \"qq-total-progress-bar-container-selector\",\n totalProgressBar: \"qq-total-progress-bar-selector\",\n file: \"qq-upload-file-selector\",\n spinner: \"qq-upload-spinner-selector\",\n size: \"qq-upload-size-selector\",\n cancel: \"qq-upload-cancel-selector\",\n pause: \"qq-upload-pause-selector\",\n continueButton: \"qq-upload-continue-selector\",\n deleteButton: \"qq-upload-delete-selector\",\n retry: \"qq-upload-retry-selector\",\n statusText: \"qq-upload-status-text-selector\",\n editFilenameInput: \"qq-edit-filename-selector\",\n editNameIcon: \"qq-edit-filename-icon-selector\",\n dropText: \"qq-upload-drop-area-text-selector\",\n dropProcessing: \"qq-drop-processing-selector\",\n dropProcessingSpinner: \"qq-drop-processing-spinner-selector\",\n thumbnail: \"qq-thumbnail-selector\"\n },\n previewGeneration = {},\n cachedThumbnailNotAvailableImg = new qq.Promise(),\n cachedWaitingForThumbnailImg = new qq.Promise(),\n log,\n isEditElementsExist,\n isRetryElementExist,\n templateDom,\n container,\n fileList,\n showThumbnails,\n serverScale,\n\n // During initialization of the templating module we should cache any\n // placeholder images so we can quickly swap them into the file list on demand.\n // Any placeholder images that cannot be loaded/found are simply ignored.\n cacheThumbnailPlaceholders = function() {\n var notAvailableUrl = options.placeholders.thumbnailNotAvailable,\n waitingUrl = options.placeholders.waitingForThumbnail,\n spec = {\n maxSize: thumbnailMaxSize,\n scale: serverScale\n };\n\n if (showThumbnails) {\n if (notAvailableUrl) {\n options.imageGenerator.generate(notAvailableUrl, new Image(), spec).then(\n function(updatedImg) {\n cachedThumbnailNotAvailableImg.success(updatedImg);\n },\n function() {\n cachedThumbnailNotAvailableImg.failure();\n log(\"Problem loading 'not available' placeholder image at \" + notAvailableUrl, \"error\");\n }\n );\n }\n else {\n cachedThumbnailNotAvailableImg.failure();\n }\n\n if (waitingUrl) {\n options.imageGenerator.generate(waitingUrl, new Image(), spec).then(\n function(updatedImg) {\n cachedWaitingForThumbnailImg.success(updatedImg);\n },\n function() {\n cachedWaitingForThumbnailImg.failure();\n log(\"Problem loading 'waiting for thumbnail' placeholder image at \" + waitingUrl, \"error\");\n }\n );\n }\n else {\n cachedWaitingForThumbnailImg.failure();\n }\n }\n },\n\n // Displays a \"waiting for thumbnail\" type placeholder image\n // iff we were able to load it during initialization of the templating module.\n displayWaitingImg = function(thumbnail) {\n var waitingImgPlacement = new qq.Promise();\n\n cachedWaitingForThumbnailImg.then(function(img) {\n maybeScalePlaceholderViaCss(img, thumbnail);\n /* jshint eqnull:true */\n if (!thumbnail.src) {\n thumbnail.src = img.src;\n thumbnail.onload = function() {\n thumbnail.onload = null;\n show(thumbnail);\n waitingImgPlacement.success();\n };\n }\n else {\n waitingImgPlacement.success();\n }\n }, function() {\n // In some browsers (such as IE9 and older) an img w/out a src attribute\n // are displayed as \"broken\" images, so we should just hide the img tag\n // if we aren't going to display the \"waiting\" placeholder.\n hide(thumbnail);\n waitingImgPlacement.success();\n });\n\n return waitingImgPlacement;\n },\n\n generateNewPreview = function(id, blob, spec) {\n var thumbnail = getThumbnail(id);\n\n log(\"Generating new thumbnail for \" + id);\n blob.qqThumbnailId = id;\n\n return options.imageGenerator.generate(blob, thumbnail, spec).then(\n function() {\n generatedThumbnails++;\n show(thumbnail);\n previewGeneration[id].success();\n },\n function() {\n previewGeneration[id].failure();\n\n // Display the \"not available\" placeholder img only if we are\n // not expecting a thumbnail at a later point, such as in a server response.\n if (!options.placeholders.waitUntilUpdate) {\n maybeSetDisplayNotAvailableImg(id, thumbnail);\n }\n });\n },\n\n generateNextQueuedPreview = function() {\n if (thumbGenerationQueue.length) {\n thumbnailQueueMonitorRunning = true;\n\n var queuedThumbRequest = thumbGenerationQueue.shift();\n\n if (queuedThumbRequest.update) {\n processUpdateQueuedPreviewRequest(queuedThumbRequest);\n }\n else {\n processNewQueuedPreviewRequest(queuedThumbRequest);\n }\n }\n else {\n thumbnailQueueMonitorRunning = false;\n }\n },\n\n getCancel = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.cancel);\n },\n\n getContinue = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.continueButton);\n },\n\n getDialog = function(type) {\n return getTemplateEl(container, selectorClasses[type + \"Dialog\"]);\n },\n\n getDelete = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.deleteButton);\n },\n\n getDropProcessing = function() {\n return getTemplateEl(container, selectorClasses.dropProcessing);\n },\n\n getEditIcon = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.editNameIcon);\n },\n\n getFile = function(id) {\n return fileBatch.map[id] || qq(fileList).getFirstByClass(FILE_CLASS_PREFIX + id);\n },\n\n getFilename = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.file);\n },\n\n getPause = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.pause);\n },\n\n getProgress = function(id) {\n /* jshint eqnull:true */\n // Total progress bar\n if (id == null) {\n return getTemplateEl(container, selectorClasses.totalProgressBarContainer) ||\n getTemplateEl(container, selectorClasses.totalProgressBar);\n }\n\n // Per-file progress bar\n return getTemplateEl(getFile(id), selectorClasses.progressBarContainer) ||\n getTemplateEl(getFile(id), selectorClasses.progressBar);\n },\n\n getRetry = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.retry);\n },\n\n getSize = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.size);\n },\n\n getSpinner = function(id) {\n return getTemplateEl(getFile(id), selectorClasses.spinner);\n },\n\n getTemplateEl = function(context, cssClass) {\n return context && qq(context).getFirstByClass(cssClass);\n },\n\n getThumbnail = function(id) {\n return showThumbnails && getTemplateEl(getFile(id), selectorClasses.thumbnail);\n },\n\n hide = function(el) {\n el && qq(el).addClass(options.classes.hide);\n },\n\n // Ensures a placeholder image does not exceed any max size specified\n // via `style` attribute properties iff was not used to scale\n // the placeholder AND the target doesn't already have these `style` attribute properties set.\n maybeScalePlaceholderViaCss = function(placeholder, thumbnail) {\n var maxWidth = placeholder.style.maxWidth,\n maxHeight = placeholder.style.maxHeight;\n\n if (maxHeight && maxWidth && !thumbnail.style.maxWidth && !thumbnail.style.maxHeight) {\n qq(thumbnail).css({\n maxWidth: maxWidth,\n maxHeight: maxHeight\n });\n }\n },\n\n // Displays a \"thumbnail not available\" type placeholder image\n // iff we were able to load this placeholder during initialization\n // of the templating module or after preview generation has failed.\n maybeSetDisplayNotAvailableImg = function(id, thumbnail) {\n var previewing = previewGeneration[id] || new qq.Promise().failure(),\n notAvailableImgPlacement = new qq.Promise();\n\n cachedThumbnailNotAvailableImg.then(function(img) {\n previewing.then(\n function() {\n notAvailableImgPlacement.success();\n },\n function() {\n maybeScalePlaceholderViaCss(img, thumbnail);\n\n thumbnail.onload = function() {\n thumbnail.onload = null;\n notAvailableImgPlacement.success();\n };\n\n thumbnail.src = img.src;\n show(thumbnail);\n }\n );\n });\n\n return notAvailableImgPlacement;\n },\n\n /**\n * Grabs the HTML from the script tag holding the template markup. This function will also adjust\n * some internally-tracked state variables based on the contents of the template.\n * The template is filtered so that irrelevant elements (such as the drop zone if DnD is not supported)\n * are omitted from the DOM. Useful errors will be thrown if the template cannot be parsed.\n *\n * @returns {{template: *, fileTemplate: *}} HTML for the top-level file items templates\n */\n parseAndGetTemplate = function() {\n var scriptEl,\n scriptHtml,\n fileListNode,\n tempTemplateEl,\n fileListEl,\n defaultButton,\n dropArea,\n thumbnail,\n dropProcessing,\n dropTextEl,\n uploaderEl;\n\n log(\"Parsing template\");\n\n /*jshint -W116*/\n if (options.templateIdOrEl == null) {\n throw new Error(\"You MUST specify either a template element or ID!\");\n }\n\n // Grab the contents of the script tag holding the template.\n if (qq.isString(options.templateIdOrEl)) {\n scriptEl = document.getElementById(options.templateIdOrEl);\n\n if (scriptEl === null) {\n throw new Error(qq.format(\"Cannot find template script at ID '{}'!\", options.templateIdOrEl));\n }\n\n scriptHtml = scriptEl.innerHTML;\n }\n else {\n if (options.templateIdOrEl.innerHTML === undefined) {\n throw new Error(\"You have specified an invalid value for the template option! \" +\n \"It must be an ID or an Element.\");\n }\n\n scriptHtml = options.templateIdOrEl.innerHTML;\n }\n\n scriptHtml = qq.trimStr(scriptHtml);\n tempTemplateEl = document.createElement(\"div\");\n tempTemplateEl.appendChild(qq.toElement(scriptHtml));\n uploaderEl = qq(tempTemplateEl).getFirstByClass(selectorClasses.uploader);\n\n // Don't include the default template button in the DOM\n // if an alternate button container has been specified.\n if (options.button) {\n defaultButton = qq(tempTemplateEl).getFirstByClass(selectorClasses.button);\n if (defaultButton) {\n qq(defaultButton).remove();\n }\n }\n\n // Omit the drop processing element from the DOM if DnD is not supported by the UA,\n // or the drag and drop module is not found.\n // NOTE: We are consciously not removing the drop zone if the UA doesn't support DnD\n // to support layouts where the drop zone is also a container for visible elements,\n // such as the file list.\n if (!qq.DragAndDrop || !qq.supportedFeatures.fileDrop) {\n dropProcessing = qq(tempTemplateEl).getFirstByClass(selectorClasses.dropProcessing);\n if (dropProcessing) {\n qq(dropProcessing).remove();\n }\n }\n\n dropArea = qq(tempTemplateEl).getFirstByClass(selectorClasses.drop);\n\n // If DnD is not available then remove\n // it from the DOM as well.\n if (dropArea && !qq.DragAndDrop) {\n log(\"DnD module unavailable.\", \"info\");\n qq(dropArea).remove();\n }\n\n if (!qq.supportedFeatures.fileDrop) {\n // don't display any \"drop files to upload\" background text\n uploaderEl.removeAttribute(DROPZPONE_TEXT_ATTR);\n\n if (dropArea && qq(dropArea).hasAttribute(HIDE_DROPZONE_ATTR)) {\n // If there is a drop area defined in the template, and the current UA doesn't support DnD,\n // and the drop area is marked as \"hide before enter\", ensure it is hidden as the DnD module\n // will not do this (since we will not be loading the DnD module)\n qq(dropArea).css({\n display: \"none\"\n });\n }\n }\n else if (qq(uploaderEl).hasAttribute(DROPZPONE_TEXT_ATTR) && dropArea) {\n dropTextEl = qq(dropArea).getFirstByClass(selectorClasses.dropText);\n dropTextEl && qq(dropTextEl).remove();\n }\n\n // Ensure the `showThumbnails` flag is only set if the thumbnail element\n // is present in the template AND the current UA is capable of generating client-side previews.\n thumbnail = qq(tempTemplateEl).getFirstByClass(selectorClasses.thumbnail);\n if (!showThumbnails) {\n thumbnail && qq(thumbnail).remove();\n }\n else if (thumbnail) {\n thumbnailMaxSize = parseInt(thumbnail.getAttribute(THUMBNAIL_MAX_SIZE_ATTR));\n // Only enforce max size if the attr value is non-zero\n thumbnailMaxSize = thumbnailMaxSize > 0 ? thumbnailMaxSize : null;\n\n serverScale = qq(thumbnail).hasAttribute(THUMBNAIL_SERVER_SCALE_ATTR);\n }\n showThumbnails = showThumbnails && thumbnail;\n\n isEditElementsExist = qq(tempTemplateEl).getByClass(selectorClasses.editFilenameInput).length > 0;\n isRetryElementExist = qq(tempTemplateEl).getByClass(selectorClasses.retry).length > 0;\n\n fileListNode = qq(tempTemplateEl).getFirstByClass(selectorClasses.list);\n /*jshint -W116*/\n if (fileListNode == null) {\n throw new Error(\"Could not find the file list container in the template!\");\n }\n\n fileListEl = fileListNode.children[0].cloneNode(true);\n fileListNode.innerHTML = \"\";\n\n // We must call `createElement` in IE8 in order to target and hide any via CSS\n if (tempTemplateEl.getElementsByTagName(\"DIALOG\").length) {\n document.createElement(\"dialog\");\n }\n\n log(\"Template parsing complete\");\n\n return {\n template: tempTemplateEl,\n fileTemplate: fileListEl\n };\n },\n\n prependFile = function(el, index, fileList) {\n var parentEl = fileList,\n beforeEl = parentEl.firstChild;\n\n if (index > 0) {\n beforeEl = qq(parentEl).children()[index].nextSibling;\n\n }\n\n parentEl.insertBefore(el, beforeEl);\n },\n\n processNewQueuedPreviewRequest = function(queuedThumbRequest) {\n var id = queuedThumbRequest.id,\n optFileOrBlob = queuedThumbRequest.optFileOrBlob,\n relatedThumbnailId = optFileOrBlob && optFileOrBlob.qqThumbnailId,\n thumbnail = getThumbnail(id),\n spec = {\n customResizeFunction: queuedThumbRequest.customResizeFunction,\n maxSize: thumbnailMaxSize,\n orient: true,\n scale: true\n };\n\n if (qq.supportedFeatures.imagePreviews) {\n if (thumbnail) {\n if (options.limits.maxThumbs && options.limits.maxThumbs <= generatedThumbnails) {\n maybeSetDisplayNotAvailableImg(id, thumbnail);\n generateNextQueuedPreview();\n }\n else {\n displayWaitingImg(thumbnail).done(function() {\n previewGeneration[id] = new qq.Promise();\n\n previewGeneration[id].done(function() {\n setTimeout(generateNextQueuedPreview, options.limits.timeBetweenThumbs);\n });\n\n /* jshint eqnull: true */\n // If we've already generated an for this file, use the one that exists,\n // don't waste resources generating a new one.\n if (relatedThumbnailId != null) {\n useCachedPreview(id, relatedThumbnailId);\n }\n else {\n generateNewPreview(id, optFileOrBlob, spec);\n }\n });\n }\n }\n // File element in template may have been removed, so move on to next item in queue\n else {\n generateNextQueuedPreview();\n }\n }\n else if (thumbnail) {\n displayWaitingImg(thumbnail);\n generateNextQueuedPreview();\n }\n },\n\n processUpdateQueuedPreviewRequest = function(queuedThumbRequest) {\n var id = queuedThumbRequest.id,\n thumbnailUrl = queuedThumbRequest.thumbnailUrl,\n showWaitingImg = queuedThumbRequest.showWaitingImg,\n thumbnail = getThumbnail(id),\n spec = {\n customResizeFunction: queuedThumbRequest.customResizeFunction,\n scale: serverScale,\n maxSize: thumbnailMaxSize\n };\n\n if (thumbnail) {\n if (thumbnailUrl) {\n if (options.limits.maxThumbs && options.limits.maxThumbs <= generatedThumbnails) {\n maybeSetDisplayNotAvailableImg(id, thumbnail);\n generateNextQueuedPreview();\n }\n else {\n if (showWaitingImg) {\n displayWaitingImg(thumbnail);\n }\n\n return options.imageGenerator.generate(thumbnailUrl, thumbnail, spec).then(\n function() {\n show(thumbnail);\n generatedThumbnails++;\n setTimeout(generateNextQueuedPreview, options.limits.timeBetweenThumbs);\n },\n\n function() {\n maybeSetDisplayNotAvailableImg(id, thumbnail);\n setTimeout(generateNextQueuedPreview, options.limits.timeBetweenThumbs);\n }\n );\n }\n }\n else {\n maybeSetDisplayNotAvailableImg(id, thumbnail);\n generateNextQueuedPreview();\n }\n }\n },\n\n setProgressBarWidth = function(id, percent) {\n var bar = getProgress(id),\n /* jshint eqnull:true */\n progressBarSelector = id == null ? selectorClasses.totalProgressBar : selectorClasses.progressBar;\n\n if (bar && !qq(bar).hasClass(progressBarSelector)) {\n bar = qq(bar).getFirstByClass(progressBarSelector);\n }\n\n if (bar) {\n qq(bar).css({width: percent + \"%\"});\n bar.setAttribute(\"aria-valuenow\", percent);\n }\n },\n\n show = function(el) {\n el && qq(el).removeClass(options.classes.hide);\n },\n\n useCachedPreview = function(targetThumbnailId, cachedThumbnailId) {\n var targetThumbnail = getThumbnail(targetThumbnailId),\n cachedThumbnail = getThumbnail(cachedThumbnailId);\n\n log(qq.format(\"ID {} is the same file as ID {}. Will use generated thumbnail from ID {} instead.\", targetThumbnailId, cachedThumbnailId, cachedThumbnailId));\n\n // Generation of the related thumbnail may still be in progress, so, wait until it is done.\n previewGeneration[cachedThumbnailId].then(function() {\n generatedThumbnails++;\n previewGeneration[targetThumbnailId].success();\n log(qq.format(\"Now using previously generated thumbnail created for ID {} on ID {}.\", cachedThumbnailId, targetThumbnailId));\n targetThumbnail.src = cachedThumbnail.src;\n show(targetThumbnail);\n },\n function() {\n previewGeneration[targetThumbnailId].failure();\n if (!options.placeholders.waitUntilUpdate) {\n maybeSetDisplayNotAvailableImg(targetThumbnailId, targetThumbnail);\n }\n });\n };\n\n qq.extend(options, spec);\n log = options.log;\n\n // No need to worry about conserving CPU or memory on older browsers,\n // since there is no ability to preview, and thumbnail display is primitive and quick.\n if (!qq.supportedFeatures.imagePreviews) {\n options.limits.timeBetweenThumbs = 0;\n options.limits.maxThumbs = 0;\n }\n\n container = options.containerEl;\n showThumbnails = options.imageGenerator !== undefined;\n templateDom = parseAndGetTemplate();\n\n cacheThumbnailPlaceholders();\n\n qq.extend(this, {\n render: function() {\n log(\"Rendering template in DOM.\");\n\n generatedThumbnails = 0;\n\n container.appendChild(templateDom.template.cloneNode(true));\n hide(getDropProcessing());\n this.hideTotalProgress();\n fileList = options.fileContainerEl || getTemplateEl(container, selectorClasses.list);\n\n log(\"Template rendering complete\");\n },\n\n renderFailure: function(message) {\n var cantRenderEl = qq.toElement(message);\n container.innerHTML = \"\";\n container.appendChild(cantRenderEl);\n },\n\n reset: function() {\n container.innerHTML = \"\";\n this.render();\n },\n\n clearFiles: function() {\n fileList.innerHTML = \"\";\n },\n\n disableCancel: function() {\n isCancelDisabled = true;\n },\n\n addFile: function(id, name, prependInfo, hideForever, batch) {\n var fileEl = templateDom.fileTemplate.cloneNode(true),\n fileNameEl = getTemplateEl(fileEl, selectorClasses.file),\n uploaderEl = getTemplateEl(container, selectorClasses.uploader),\n fileContainer = batch ? fileBatch.content : fileList,\n thumb;\n\n if (batch) {\n fileBatch.map[id] = fileEl;\n }\n\n qq(fileEl).addClass(FILE_CLASS_PREFIX + id);\n uploaderEl.removeAttribute(DROPZPONE_TEXT_ATTR);\n\n if (fileNameEl) {\n qq(fileNameEl).setText(name);\n fileNameEl.setAttribute(\"title\", name);\n }\n\n fileEl.setAttribute(FILE_ID_ATTR, id);\n\n if (prependInfo) {\n prependFile(fileEl, prependInfo.index, fileContainer);\n }\n else {\n fileContainer.appendChild(fileEl);\n }\n\n if (hideForever) {\n fileEl.style.display = \"none\";\n qq(fileEl).addClass(HIDDEN_FOREVER_CLASS);\n }\n else {\n hide(getProgress(id));\n hide(getSize(id));\n hide(getDelete(id));\n hide(getRetry(id));\n hide(getPause(id));\n hide(getContinue(id));\n\n if (isCancelDisabled) {\n this.hideCancel(id);\n }\n\n thumb = getThumbnail(id);\n if (thumb && !thumb.src) {\n cachedWaitingForThumbnailImg.then(function(waitingImg) {\n thumb.src = waitingImg.src;\n if (waitingImg.style.maxHeight && waitingImg.style.maxWidth) {\n qq(thumb).css({\n maxHeight: waitingImg.style.maxHeight,\n maxWidth: waitingImg.style.maxWidth\n });\n }\n\n show(thumb);\n });\n }\n }\n },\n\n addFileToCache: function(id, name, prependInfo, hideForever) {\n this.addFile(id, name, prependInfo, hideForever, true);\n },\n\n addCacheToDom: function() {\n fileList.appendChild(fileBatch.content);\n fileBatch.content = document.createDocumentFragment();\n fileBatch.map = {};\n },\n\n removeFile: function(id) {\n qq(getFile(id)).remove();\n },\n\n getFileId: function(el) {\n var currentNode = el;\n\n if (currentNode) {\n /*jshint -W116*/\n while (currentNode.getAttribute(FILE_ID_ATTR) == null) {\n currentNode = currentNode.parentNode;\n }\n\n return parseInt(currentNode.getAttribute(FILE_ID_ATTR));\n }\n },\n\n getFileList: function() {\n return fileList;\n },\n\n markFilenameEditable: function(id) {\n var filename = getFilename(id);\n\n filename && qq(filename).addClass(options.classes.editable);\n },\n\n updateFilename: function(id, name) {\n var filenameEl = getFilename(id);\n\n if (filenameEl) {\n qq(filenameEl).setText(name);\n filenameEl.setAttribute(\"title\", name);\n }\n },\n\n hideFilename: function(id) {\n hide(getFilename(id));\n },\n\n showFilename: function(id) {\n show(getFilename(id));\n },\n\n isFileName: function(el) {\n return qq(el).hasClass(selectorClasses.file);\n },\n\n getButton: function() {\n return options.button || getTemplateEl(container, selectorClasses.button);\n },\n\n hideDropProcessing: function() {\n hide(getDropProcessing());\n },\n\n showDropProcessing: function() {\n show(getDropProcessing());\n },\n\n getDropZone: function() {\n return getTemplateEl(container, selectorClasses.drop);\n },\n\n isEditFilenamePossible: function() {\n return isEditElementsExist;\n },\n\n hideRetry: function(id) {\n hide(getRetry(id));\n },\n\n isRetryPossible: function() {\n return isRetryElementExist;\n },\n\n showRetry: function(id) {\n show(getRetry(id));\n },\n\n getFileContainer: function(id) {\n return getFile(id);\n },\n\n showEditIcon: function(id) {\n var icon = getEditIcon(id);\n\n icon && qq(icon).addClass(options.classes.editable);\n },\n\n isHiddenForever: function(id) {\n return qq(getFile(id)).hasClass(HIDDEN_FOREVER_CLASS);\n },\n\n hideEditIcon: function(id) {\n var icon = getEditIcon(id);\n\n icon && qq(icon).removeClass(options.classes.editable);\n },\n\n isEditIcon: function(el) {\n return qq(el).hasClass(selectorClasses.editNameIcon, true);\n },\n\n getEditInput: function(id) {\n return getTemplateEl(getFile(id), selectorClasses.editFilenameInput);\n },\n\n isEditInput: function(el) {\n return qq(el).hasClass(selectorClasses.editFilenameInput, true);\n },\n\n updateProgress: function(id, loaded, total) {\n var bar = getProgress(id),\n percent;\n\n if (bar && total > 0) {\n percent = Math.round(loaded / total * 100);\n\n if (percent === 100) {\n hide(bar);\n }\n else {\n show(bar);\n }\n\n setProgressBarWidth(id, percent);\n }\n },\n\n updateTotalProgress: function(loaded, total) {\n this.updateProgress(null, loaded, total);\n },\n\n hideProgress: function(id) {\n var bar = getProgress(id);\n\n bar && hide(bar);\n },\n\n hideTotalProgress: function() {\n this.hideProgress();\n },\n\n resetProgress: function(id) {\n setProgressBarWidth(id, 0);\n this.hideTotalProgress(id);\n },\n\n resetTotalProgress: function() {\n this.resetProgress();\n },\n\n showCancel: function(id) {\n if (!isCancelDisabled) {\n var cancel = getCancel(id);\n\n cancel && qq(cancel).removeClass(options.classes.hide);\n }\n },\n\n hideCancel: function(id) {\n hide(getCancel(id));\n },\n\n isCancel: function(el) {\n return qq(el).hasClass(selectorClasses.cancel, true);\n },\n\n allowPause: function(id) {\n show(getPause(id));\n hide(getContinue(id));\n },\n\n uploadPaused: function(id) {\n this.setStatusText(id, options.text.paused);\n this.allowContinueButton(id);\n hide(getSpinner(id));\n },\n\n hidePause: function(id) {\n hide(getPause(id));\n },\n\n isPause: function(el) {\n return qq(el).hasClass(selectorClasses.pause, true);\n },\n\n isContinueButton: function(el) {\n return qq(el).hasClass(selectorClasses.continueButton, true);\n },\n\n allowContinueButton: function(id) {\n show(getContinue(id));\n hide(getPause(id));\n },\n\n uploadContinued: function(id) {\n this.setStatusText(id, \"\");\n this.allowPause(id);\n show(getSpinner(id));\n },\n\n showDeleteButton: function(id) {\n show(getDelete(id));\n },\n\n hideDeleteButton: function(id) {\n hide(getDelete(id));\n },\n\n isDeleteButton: function(el) {\n return qq(el).hasClass(selectorClasses.deleteButton, true);\n },\n\n isRetry: function(el) {\n return qq(el).hasClass(selectorClasses.retry, true);\n },\n\n updateSize: function(id, text) {\n var size = getSize(id);\n\n if (size) {\n show(size);\n qq(size).setText(text);\n }\n },\n\n setStatusText: function(id, text) {\n var textEl = getTemplateEl(getFile(id), selectorClasses.statusText);\n\n if (textEl) {\n /*jshint -W116*/\n if (text == null) {\n qq(textEl).clearText();\n }\n else {\n qq(textEl).setText(text);\n }\n }\n },\n\n hideSpinner: function(id) {\n qq(getFile(id)).removeClass(IN_PROGRESS_CLASS);\n hide(getSpinner(id));\n },\n\n showSpinner: function(id) {\n qq(getFile(id)).addClass(IN_PROGRESS_CLASS);\n show(getSpinner(id));\n },\n\n generatePreview: function(id, optFileOrBlob, customResizeFunction) {\n if (!this.isHiddenForever(id)) {\n thumbGenerationQueue.push({id: id, customResizeFunction: customResizeFunction, optFileOrBlob: optFileOrBlob});\n !thumbnailQueueMonitorRunning && generateNextQueuedPreview();\n }\n },\n\n updateThumbnail: function(id, thumbnailUrl, showWaitingImg, customResizeFunction) {\n if (!this.isHiddenForever(id)) {\n thumbGenerationQueue.push({customResizeFunction: customResizeFunction, update: true, id: id, thumbnailUrl: thumbnailUrl, showWaitingImg: showWaitingImg});\n !thumbnailQueueMonitorRunning && generateNextQueuedPreview();\n }\n },\n\n hasDialog: function(type) {\n return qq.supportedFeatures.dialogElement && !!getDialog(type);\n },\n\n showDialog: function(type, message, defaultValue) {\n var dialog = getDialog(type),\n messageEl = getTemplateEl(dialog, selectorClasses.dialogMessage),\n inputEl = dialog.getElementsByTagName(\"INPUT\")[0],\n cancelBtn = getTemplateEl(dialog, selectorClasses.dialogCancelButton),\n okBtn = getTemplateEl(dialog, selectorClasses.dialogOkButton),\n promise = new qq.Promise(),\n\n closeHandler = function() {\n cancelBtn.removeEventListener(\"click\", cancelClickHandler);\n okBtn && okBtn.removeEventListener(\"click\", okClickHandler);\n promise.failure();\n },\n\n cancelClickHandler = function() {\n cancelBtn.removeEventListener(\"click\", cancelClickHandler);\n dialog.close();\n },\n\n okClickHandler = function() {\n dialog.removeEventListener(\"close\", closeHandler);\n okBtn.removeEventListener(\"click\", okClickHandler);\n dialog.close();\n\n promise.success(inputEl && inputEl.value);\n };\n\n dialog.addEventListener(\"close\", closeHandler);\n cancelBtn.addEventListener(\"click\", cancelClickHandler);\n okBtn && okBtn.addEventListener(\"click\", okClickHandler);\n\n if (inputEl) {\n inputEl.value = defaultValue;\n }\n messageEl.textContent = message;\n\n dialog.showModal();\n\n return promise;\n }\n });\n};\n","/*globals qq */\n// Base handler for UI (FineUploader mode) events.\n// Some more specific handlers inherit from this one.\nqq.UiEventHandler = function(s, protectedApi) {\n \"use strict\";\n\n var disposer = new qq.DisposeSupport(),\n spec = {\n eventType: \"click\",\n attachTo: null,\n onHandled: function(target, event) {}\n };\n\n // This makes up the \"public\" API methods that will be accessible\n // to instances constructing a base or child handler\n qq.extend(this, {\n addHandler: function(element) {\n addHandler(element);\n },\n\n dispose: function() {\n disposer.dispose();\n }\n });\n\n function addHandler(element) {\n disposer.attach(element, spec.eventType, function(event) {\n // Only in IE: the `event` is a property of the `window`.\n event = event || window.event;\n\n // On older browsers, we must check the `srcElement` instead of the `target`.\n var target = event.target || event.srcElement;\n\n spec.onHandled(target, event);\n });\n }\n\n // These make up the \"protected\" API methods that children of this base handler will utilize.\n qq.extend(protectedApi, {\n getFileIdFromItem: function(item) {\n return item.qqFileId;\n },\n\n getDisposeSupport: function() {\n return disposer;\n }\n });\n\n qq.extend(spec, s);\n\n if (spec.attachTo) {\n addHandler(spec.attachTo);\n }\n};\n","/* global qq */\nqq.FileButtonsClickHandler = function(s) {\n \"use strict\";\n\n var inheritedInternalApi = {},\n spec = {\n templating: null,\n log: function(message, lvl) {},\n onDeleteFile: function(fileId) {},\n onCancel: function(fileId) {},\n onRetry: function(fileId) {},\n onPause: function(fileId) {},\n onContinue: function(fileId) {},\n onGetName: function(fileId) {}\n },\n buttonHandlers = {\n cancel: function(id) { spec.onCancel(id); },\n retry: function(id) { spec.onRetry(id); },\n deleteButton: function(id) { spec.onDeleteFile(id); },\n pause: function(id) { spec.onPause(id); },\n continueButton: function(id) { spec.onContinue(id); }\n };\n\n function examineEvent(target, event) {\n qq.each(buttonHandlers, function(buttonType, handler) {\n var firstLetterCapButtonType = buttonType.charAt(0).toUpperCase() + buttonType.slice(1),\n fileId;\n\n if (spec.templating[\"is\" + firstLetterCapButtonType](target)) {\n fileId = spec.templating.getFileId(target);\n qq.preventDefault(event);\n spec.log(qq.format(\"Detected valid file button click event on file '{}', ID: {}.\", spec.onGetName(fileId), fileId));\n handler(fileId);\n return false;\n }\n });\n }\n\n qq.extend(spec, s);\n\n spec.eventType = \"click\";\n spec.onHandled = examineEvent;\n spec.attachTo = spec.templating.getFileList();\n\n qq.extend(this, new qq.UiEventHandler(spec, inheritedInternalApi));\n};\n","/*globals qq */\n// Child of FilenameEditHandler. Used to detect click events on filename display elements.\nqq.FilenameClickHandler = function(s) {\n \"use strict\";\n\n var inheritedInternalApi = {},\n spec = {\n templating: null,\n log: function(message, lvl) {},\n classes: {\n file: \"qq-upload-file\",\n editNameIcon: \"qq-edit-filename-icon\"\n },\n onGetUploadStatus: function(fileId) {},\n onGetName: function(fileId) {}\n };\n\n qq.extend(spec, s);\n\n // This will be called by the parent handler when a `click` event is received on the list element.\n function examineEvent(target, event) {\n if (spec.templating.isFileName(target) || spec.templating.isEditIcon(target)) {\n var fileId = spec.templating.getFileId(target),\n status = spec.onGetUploadStatus(fileId);\n\n // We only allow users to change filenames of files that have been submitted but not yet uploaded.\n if (status === qq.status.SUBMITTED) {\n spec.log(qq.format(\"Detected valid filename click event on file '{}', ID: {}.\", spec.onGetName(fileId), fileId));\n qq.preventDefault(event);\n\n inheritedInternalApi.handleFilenameEdit(fileId, target, true);\n }\n }\n }\n\n spec.eventType = \"click\";\n spec.onHandled = examineEvent;\n\n qq.extend(this, new qq.FilenameEditHandler(spec, inheritedInternalApi));\n};\n","/*globals qq */\n// Child of FilenameEditHandler. Used to detect focusin events on file edit input elements.\nqq.FilenameInputFocusInHandler = function(s, inheritedInternalApi) {\n \"use strict\";\n\n var spec = {\n templating: null,\n onGetUploadStatus: function(fileId) {},\n log: function(message, lvl) {}\n };\n\n if (!inheritedInternalApi) {\n inheritedInternalApi = {};\n }\n\n // This will be called by the parent handler when a `focusin` event is received on the list element.\n function handleInputFocus(target, event) {\n if (spec.templating.isEditInput(target)) {\n var fileId = spec.templating.getFileId(target),\n status = spec.onGetUploadStatus(fileId);\n\n if (status === qq.status.SUBMITTED) {\n spec.log(qq.format(\"Detected valid filename input focus event on file '{}', ID: {}.\", spec.onGetName(fileId), fileId));\n inheritedInternalApi.handleFilenameEdit(fileId, target);\n }\n }\n }\n\n spec.eventType = \"focusin\";\n spec.onHandled = handleInputFocus;\n\n qq.extend(spec, s);\n qq.extend(this, new qq.FilenameEditHandler(spec, inheritedInternalApi));\n};\n","/*globals qq */\n/**\n * Child of FilenameInputFocusInHandler. Used to detect focus events on file edit input elements. This child module is only\n * needed for UAs that do not support the focusin event. Currently, only Firefox lacks this event.\n *\n * @param spec Overrides for default specifications\n */\nqq.FilenameInputFocusHandler = function(spec) {\n \"use strict\";\n\n spec.eventType = \"focus\";\n spec.attachTo = null;\n\n qq.extend(this, new qq.FilenameInputFocusInHandler(spec, {}));\n};\n","/*globals qq */\n// Handles edit-related events on a file item (FineUploader mode). This is meant to be a parent handler.\n// Children will delegate to this handler when specific edit-related actions are detected.\nqq.FilenameEditHandler = function(s, inheritedInternalApi) {\n \"use strict\";\n\n var spec = {\n templating: null,\n log: function(message, lvl) {},\n onGetUploadStatus: function(fileId) {},\n onGetName: function(fileId) {},\n onSetName: function(fileId, newName) {},\n onEditingStatusChange: function(fileId, isEditing) {}\n };\n\n function getFilenameSansExtension(fileId) {\n var filenameSansExt = spec.onGetName(fileId),\n extIdx = filenameSansExt.lastIndexOf(\".\");\n\n if (extIdx > 0) {\n filenameSansExt = filenameSansExt.substr(0, extIdx);\n }\n\n return filenameSansExt;\n }\n\n function getOriginalExtension(fileId) {\n var origName = spec.onGetName(fileId);\n return qq.getExtension(origName);\n }\n\n // Callback iff the name has been changed\n function handleNameUpdate(newFilenameInputEl, fileId) {\n var newName = newFilenameInputEl.value,\n origExtension;\n\n if (newName !== undefined && qq.trimStr(newName).length > 0) {\n origExtension = getOriginalExtension(fileId);\n\n if (origExtension !== undefined) {\n newName = newName + \".\" + origExtension;\n }\n\n spec.onSetName(fileId, newName);\n }\n\n spec.onEditingStatusChange(fileId, false);\n }\n\n // The name has been updated if the filename edit input loses focus.\n function registerInputBlurHandler(inputEl, fileId) {\n inheritedInternalApi.getDisposeSupport().attach(inputEl, \"blur\", function() {\n handleNameUpdate(inputEl, fileId);\n });\n }\n\n // The name has been updated if the user presses enter.\n function registerInputEnterKeyHandler(inputEl, fileId) {\n inheritedInternalApi.getDisposeSupport().attach(inputEl, \"keyup\", function(event) {\n\n var code = event.keyCode || event.which;\n\n if (code === 13) {\n handleNameUpdate(inputEl, fileId);\n }\n });\n }\n\n qq.extend(spec, s);\n\n spec.attachTo = spec.templating.getFileList();\n\n qq.extend(this, new qq.UiEventHandler(spec, inheritedInternalApi));\n\n qq.extend(inheritedInternalApi, {\n handleFilenameEdit: function(id, target, focusInput) {\n var newFilenameInputEl = spec.templating.getEditInput(id);\n\n spec.onEditingStatusChange(id, true);\n\n newFilenameInputEl.value = getFilenameSansExtension(id);\n\n if (focusInput) {\n newFilenameInputEl.focus();\n }\n\n registerInputBlurHandler(newFilenameInputEl, id);\n registerInputEnterKeyHandler(newFilenameInputEl, id);\n }\n });\n};\n"]}
\ No newline at end of file
diff --git a/styles/bootstrap/jquery/jquery.min.js b/styles/bootstrap/jquery/jquery.min.js
index f65cf1dc4..e83647587 100644
--- a/styles/bootstrap/jquery/jquery.min.js
+++ b/styles/bootstrap/jquery/jquery.min.js
@@ -1,2 +1,5 @@
-/*! jQuery v1.8.2 jquery.com | jquery.org/license */
-(function(a,b){function G(a){var b=F[a]={};return p.each(a.split(s),function(a,c){b[c]=!0}),b}function J(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(I,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:+d+""===d?+d:H.test(d)?p.parseJSON(d):d}catch(f){}p.data(a,c,d)}else d=b}return d}function K(a){var b;for(b in a){if(b==="data"&&p.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function ba(){return!1}function bb(){return!0}function bh(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function bi(a,b){do a=a[b];while(a&&a.nodeType!==1);return a}function bj(a,b,c){b=b||0;if(p.isFunction(b))return p.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return p.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=p.grep(a,function(a){return a.nodeType===1});if(be.test(b))return p.filter(b,d,!c);b=p.filter(b,d)}return p.grep(a,function(a,d){return p.inArray(a,b)>=0===c})}function bk(a){var b=bl.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function bC(a,b){return a.getElementsByTagName(b)[0]||a.appendChild(a.ownerDocument.createElement(b))}function bD(a,b){if(b.nodeType!==1||!p.hasData(a))return;var c,d,e,f=p._data(a),g=p._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;d").appendTo(e.body),c=b.css("display");b.remove();if(c==="none"||c===""){bI=e.body.appendChild(bI||p.extend(e.createElement("iframe"),{frameBorder:0,width:0,height:0}));if(!bJ||!bI.createElement)bJ=(bI.contentWindow||bI.contentDocument).document,bJ.write(""),bJ.close();b=bJ.body.appendChild(bJ.createElement(a)),c=bH(b,"display"),e.body.removeChild(bI)}return bS[a]=c,c}function ci(a,b,c,d){var e;if(p.isArray(b))p.each(b,function(b,e){c||ce.test(a)?d(a,e):ci(a+"["+(typeof e=="object"?b:"")+"]",e,c,d)});else if(!c&&p.type(b)==="object")for(e in b)ci(a+"["+e+"]",b[e],c,d);else d(a,b)}function cz(a){return function(b,c){typeof b!="string"&&(c=b,b="*");var d,e,f,g=b.toLowerCase().split(s),h=0,i=g.length;if(p.isFunction(c))for(;h)[^>]*$|#([\w\-]*)$)/,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^[\],:{}\s]*$/,x=/(?:^|:|,)(?:\s*\[)+/g,y=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,z=/"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,A=/^-ms-/,B=/-([\da-z])/gi,C=function(a,b){return(b+"").toUpperCase()},D=function(){e.addEventListener?(e.removeEventListener("DOMContentLoaded",D,!1),p.ready()):e.readyState==="complete"&&(e.detachEvent("onreadystatechange",D),p.ready())},E={};p.fn=p.prototype={constructor:p,init:function(a,c,d){var f,g,h,i;if(!a)return this;if(a.nodeType)return this.context=this[0]=a,this.length=1,this;if(typeof a=="string"){a.charAt(0)==="<"&&a.charAt(a.length-1)===">"&&a.length>=3?f=[null,a,null]:f=u.exec(a);if(f&&(f[1]||!c)){if(f[1])return c=c instanceof p?c[0]:c,i=c&&c.nodeType?c.ownerDocument||c:e,a=p.parseHTML(f[1],i,!0),v.test(f[1])&&p.isPlainObject(c)&&this.attr.call(a,c,!0),p.merge(this,a);g=e.getElementById(f[2]);if(g&&g.parentNode){if(g.id!==f[2])return d.find(a);this.length=1,this[0]=g}return this.context=e,this.selector=a,this}return!c||c.jquery?(c||d).find(a):this.constructor(c).find(a)}return p.isFunction(a)?d.ready(a):(a.selector!==b&&(this.selector=a.selector,this.context=a.context),p.makeArray(a,this))},selector:"",jquery:"1.8.2",length:0,size:function(){return this.length},toArray:function(){return k.call(this)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=p.merge(this.constructor(),a);return d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")"),d},each:function(a,b){return p.each(this,a,b)},ready:function(a){return p.ready.promise().done(a),this},eq:function(a){return a=+a,a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(k.apply(this,arguments),"slice",k.call(arguments).join(","))},map:function(a){return this.pushStack(p.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:j,sort:[].sort,splice:[].splice},p.fn.init.prototype=p.fn,p.extend=p.fn.extend=function(){var a,c,d,e,f,g,h=arguments[0]||{},i=1,j=arguments.length,k=!1;typeof h=="boolean"&&(k=h,h=arguments[1]||{},i=2),typeof h!="object"&&!p.isFunction(h)&&(h={}),j===i&&(h=this,--i);for(;i0)return;d.resolveWith(e,[p]),p.fn.trigger&&p(e).trigger("ready").off("ready")},isFunction:function(a){return p.type(a)==="function"},isArray:Array.isArray||function(a){return p.type(a)==="array"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):E[m.call(a)]||"object"},isPlainObject:function(a){if(!a||p.type(a)!=="object"||a.nodeType||p.isWindow(a))return!1;try{if(a.constructor&&!n.call(a,"constructor")&&!n.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||n.call(a,d)},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},error:function(a){throw new Error(a)},parseHTML:function(a,b,c){var d;return!a||typeof a!="string"?null:(typeof b=="boolean"&&(c=b,b=0),b=b||e,(d=v.exec(a))?[b.createElement(d[1])]:(d=p.buildFragment([a],b,c?null:[]),p.merge([],(d.cacheable?p.clone(d.fragment):d.fragment).childNodes)))},parseJSON:function(b){if(!b||typeof b!="string")return null;b=p.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(w.test(b.replace(y,"@").replace(z,"]").replace(x,"")))return(new Function("return "+b))();p.error("Invalid JSON: "+b)},parseXML:function(c){var d,e;if(!c||typeof c!="string")return null;try{a.DOMParser?(e=new DOMParser,d=e.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(f){d=b}return(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&p.error("Invalid XML: "+c),d},noop:function(){},globalEval:function(b){b&&r.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(A,"ms-").replace(B,C)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,c,d){var e,f=0,g=a.length,h=g===b||p.isFunction(a);if(d){if(h){for(e in a)if(c.apply(a[e],d)===!1)break}else for(;f0&&a[0]&&a[i-1]||i===0||p.isArray(a));if(j)for(;h-1)i.splice(c,1),e&&(c<=g&&g--,c<=h&&h--)}),this},has:function(a){return p.inArray(a,i)>-1},empty:function(){return i=[],this},disable:function(){return i=j=c=b,this},disabled:function(){return!i},lock:function(){return j=b,c||l.disable(),this},locked:function(){return!j},fireWith:function(a,b){return b=b||[],b=[a,b.slice?b.slice():b],i&&(!d||j)&&(e?j.push(b):k(b)),this},fire:function(){return l.fireWith(this,arguments),this},fired:function(){return!!d}};return l},p.extend({Deferred:function(a){var b=[["resolve","done",p.Callbacks("once memory"),"resolved"],["reject","fail",p.Callbacks("once memory"),"rejected"],["notify","progress",p.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return p.Deferred(function(c){p.each(b,function(b,d){var f=d[0],g=a[b];e[d[1]](p.isFunction(g)?function(){var a=g.apply(this,arguments);a&&p.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f+"With"](this===e?c:this,[a])}:c[f])}),a=null}).promise()},promise:function(a){return a!=null?p.extend(a,d):d}},e={};return d.pipe=d.then,p.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[a^1][2].disable,b[2][2].lock),e[f[0]]=g.fire,e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=k.call(arguments),d=c.length,e=d!==1||a&&p.isFunction(a.promise)?d:0,f=e===1?a:p.Deferred(),g=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?k.call(arguments):d,c===h?f.notifyWith(b,c):--e||f.resolveWith(b,c)}},h,i,j;if(d>1){h=new Array(d),i=new Array(d),j=new Array(d);for(;ba ",c=n.getElementsByTagName("*"),d=n.getElementsByTagName("a")[0],d.style.cssText="top:1px;float:left;opacity:.5";if(!c||!c.length)return{};f=e.createElement("select"),g=f.appendChild(e.createElement("option")),h=n.getElementsByTagName("input")[0],b={leadingWhitespace:n.firstChild.nodeType===3,tbody:!n.getElementsByTagName("tbody").length,htmlSerialize:!!n.getElementsByTagName("link").length,style:/top/.test(d.getAttribute("style")),hrefNormalized:d.getAttribute("href")==="/a",opacity:/^0.5/.test(d.style.opacity),cssFloat:!!d.style.cssFloat,checkOn:h.value==="on",optSelected:g.selected,getSetAttribute:n.className!=="t",enctype:!!e.createElement("form").enctype,html5Clone:e.createElement("nav").cloneNode(!0).outerHTML!=="<:nav>",boxModel:e.compatMode==="CSS1Compat",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},h.checked=!0,b.noCloneChecked=h.cloneNode(!0).checked,f.disabled=!0,b.optDisabled=!g.disabled;try{delete n.test}catch(o){b.deleteExpando=!1}!n.addEventListener&&n.attachEvent&&n.fireEvent&&(n.attachEvent("onclick",m=function(){b.noCloneEvent=!1}),n.cloneNode(!0).fireEvent("onclick"),n.detachEvent("onclick",m)),h=e.createElement("input"),h.value="t",h.setAttribute("type","radio"),b.radioValue=h.value==="t",h.setAttribute("checked","checked"),h.setAttribute("name","t"),n.appendChild(h),i=e.createDocumentFragment(),i.appendChild(n.lastChild),b.checkClone=i.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=h.checked,i.removeChild(h),i.appendChild(n);if(n.attachEvent)for(k in{submit:!0,change:!0,focusin:!0})j="on"+k,l=j in n,l||(n.setAttribute(j,"return;"),l=typeof n[j]=="function"),b[k+"Bubbles"]=l;return p(function(){var c,d,f,g,h="padding:0;margin:0;border:0;display:block;overflow:hidden;",i=e.getElementsByTagName("body")[0];if(!i)return;c=e.createElement("div"),c.style.cssText="visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px",i.insertBefore(c,i.firstChild),d=e.createElement("div"),c.appendChild(d),d.innerHTML="",f=d.getElementsByTagName("td"),f[0].style.cssText="padding:0;margin:0;border:0;display:none",l=f[0].offsetHeight===0,f[0].style.display="",f[1].style.display="none",b.reliableHiddenOffsets=l&&f[0].offsetHeight===0,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",b.boxSizing=d.offsetWidth===4,b.doesNotIncludeMarginInBodyOffset=i.offsetTop!==1,a.getComputedStyle&&(b.pixelPosition=(a.getComputedStyle(d,null)||{}).top!=="1%",b.boxSizingReliable=(a.getComputedStyle(d,null)||{width:"4px"}).width==="4px",g=e.createElement("div"),g.style.cssText=d.style.cssText=h,g.style.marginRight=g.style.width="0",d.style.width="1px",d.appendChild(g),b.reliableMarginRight=!parseFloat((a.getComputedStyle(g,null)||{}).marginRight)),typeof d.style.zoom!="undefined"&&(d.innerHTML="",d.style.cssText=h+"width:1px;padding:1px;display:inline;zoom:1",b.inlineBlockNeedsLayout=d.offsetWidth===3,d.style.display="block",d.style.overflow="visible",d.innerHTML="
",d.firstChild.style.width="5px",b.shrinkWrapBlocks=d.offsetWidth!==3,c.style.zoom=1),i.removeChild(c),c=d=f=g=null}),i.removeChild(n),c=d=f=g=h=i=n=null,b}();var H=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,I=/([A-Z])/g;p.extend({cache:{},deletedIds:[],uuid:0,expando:"jQuery"+(p.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){return a=a.nodeType?p.cache[a[p.expando]]:a[p.expando],!!a&&!K(a)},data:function(a,c,d,e){if(!p.acceptData(a))return;var f,g,h=p.expando,i=typeof c=="string",j=a.nodeType,k=j?p.cache:a,l=j?a[h]:a[h]&&h;if((!l||!k[l]||!e&&!k[l].data)&&i&&d===b)return;l||(j?a[h]=l=p.deletedIds.pop()||p.guid++:l=h),k[l]||(k[l]={},j||(k[l].toJSON=p.noop));if(typeof c=="object"||typeof c=="function")e?k[l]=p.extend(k[l],c):k[l].data=p.extend(k[l].data,c);return f=k[l],e||(f.data||(f.data={}),f=f.data),d!==b&&(f[p.camelCase(c)]=d),i?(g=f[c],g==null&&(g=f[p.camelCase(c)])):g=f,g},removeData:function(a,b,c){if(!p.acceptData(a))return;var d,e,f,g=a.nodeType,h=g?p.cache:a,i=g?a[p.expando]:p.expando;if(!h[i])return;if(b){d=c?h[i]:h[i].data;if(d){p.isArray(b)||(b in d?b=[b]:(b=p.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,f=b.length;e1,null,!1))},removeData:function(a){return this.each(function(){p.removeData(this,a)})}}),p.extend({queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=p._data(a,b),c&&(!d||p.isArray(c)?d=p._data(a,b,p.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||"fx";var c=p.queue(a,b),d=c.length,e=c.shift(),f=p._queueHooks(a,b),g=function(){p.dequeue(a,b)};e==="inprogress"&&(e=c.shift(),d--),e&&(b==="fx"&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return p._data(a,c)||p._data(a,c,{empty:p.Callbacks("once memory").add(function(){p.removeData(a,b+"queue",!0),p.removeData(a,c,!0)})})}}),p.fn.extend({queue:function(a,c){var d=2;return typeof a!="string"&&(c=a,a="fx",d--),arguments.length1)},removeAttr:function(a){return this.each(function(){p.removeAttr(this,a)})},prop:function(a,b){return p.access(this,p.prop,a,b,arguments.length>1)},removeProp:function(a){return a=p.propFix[a]||a,this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,f,g,h;if(p.isFunction(a))return this.each(function(b){p(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(s);for(c=0,d=this.length;c=0)d=d.replace(" "+c[f]+" "," ");e.className=a?p.trim(d):""}}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";return p.isFunction(a)?this.each(function(c){p(this).toggleClass(a.call(this,c,this.className,b),b)}):this.each(function(){if(c==="string"){var e,f=0,g=p(this),h=b,i=a.split(s);while(e=i[f++])h=d?h:!g.hasClass(e),g[h?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&p._data(this,"__className__",this.className),this.className=this.className||a===!1?"":p._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c=0)return!0;return!1},val:function(a){var c,d,e,f=this[0];if(!arguments.length){if(f)return c=p.valHooks[f.type]||p.valHooks[f.nodeName.toLowerCase()],c&&"get"in c&&(d=c.get(f,"value"))!==b?d:(d=f.value,typeof d=="string"?d.replace(P,""):d==null?"":d);return}return e=p.isFunction(a),this.each(function(d){var f,g=p(this);if(this.nodeType!==1)return;e?f=a.call(this,d,g.val()):f=a,f==null?f="":typeof f=="number"?f+="":p.isArray(f)&&(f=p.map(f,function(a){return a==null?"":a+""})),c=p.valHooks[this.type]||p.valHooks[this.nodeName.toLowerCase()];if(!c||!("set"in c)||c.set(this,f,"value")===b)this.value=f})}}),p.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,f=a.selectedIndex,g=[],h=a.options,i=a.type==="select-one";if(f<0)return null;c=i?f:0,d=i?f+1:h.length;for(;c=0}),c.length||(a.selectedIndex=-1),c}}},attrFn:{},attr:function(a,c,d,e){var f,g,h,i=a.nodeType;if(!a||i===3||i===8||i===2)return;if(e&&p.isFunction(p.fn[c]))return p(a)[c](d);if(typeof a.getAttribute=="undefined")return p.prop(a,c,d);h=i!==1||!p.isXMLDoc(a),h&&(c=c.toLowerCase(),g=p.attrHooks[c]||(T.test(c)?M:L));if(d!==b){if(d===null){p.removeAttr(a,c);return}return g&&"set"in g&&h&&(f=g.set(a,d,c))!==b?f:(a.setAttribute(c,d+""),d)}return g&&"get"in g&&h&&(f=g.get(a,c))!==null?f:(f=a.getAttribute(c),f===null?b:f)},removeAttr:function(a,b){var c,d,e,f,g=0;if(b&&a.nodeType===1){d=b.split(s);for(;g=0}})});var V=/^(?:textarea|input|select)$/i,W=/^([^\.]*|)(?:\.(.+)|)$/,X=/(?:^|\s)hover(\.\S+|)\b/,Y=/^key/,Z=/^(?:mouse|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=function(a){return p.event.special.hover?a:a.replace(X,"mouseenter$1 mouseleave$1")};p.event={add:function(a,c,d,e,f){var g,h,i,j,k,l,m,n,o,q,r;if(a.nodeType===3||a.nodeType===8||!c||!d||!(g=p._data(a)))return;d.handler&&(o=d,d=o.handler,f=o.selector),d.guid||(d.guid=p.guid++),i=g.events,i||(g.events=i={}),h=g.handle,h||(g.handle=h=function(a){return typeof p!="undefined"&&(!a||p.event.triggered!==a.type)?p.event.dispatch.apply(h.elem,arguments):b},h.elem=a),c=p.trim(_(c)).split(" ");for(j=0;j=0&&(s=s.slice(0,-1),i=!0),s.indexOf(".")>=0&&(t=s.split("."),s=t.shift(),t.sort());if((!f||p.event.customEvent[s])&&!p.event.global[s])return;c=typeof c=="object"?c[p.expando]?c:new p.Event(s,c):new p.Event(s),c.type=s,c.isTrigger=!0,c.exclusive=i,c.namespace=t.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+t.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,m=s.indexOf(":")<0?"on"+s:"";if(!f){h=p.cache;for(j in h)h[j].events&&h[j].events[s]&&p.event.trigger(c,d,h[j].handle.elem,!0);return}c.result=b,c.target||(c.target=f),d=d!=null?p.makeArray(d):[],d.unshift(c),n=p.event.special[s]||{};if(n.trigger&&n.trigger.apply(f,d)===!1)return;q=[[f,n.bindType||s]];if(!g&&!n.noBubble&&!p.isWindow(f)){r=n.delegateType||s,k=$.test(r+s)?f:f.parentNode;for(l=f;k;k=k.parentNode)q.push([k,r]),l=k;l===(f.ownerDocument||e)&&q.push([l.defaultView||l.parentWindow||a,r])}for(j=0;j=0:p.find(m,this,null,[f]).length),h[m]&&j.push(l);j.length&&u.push({elem:f,matches:j})}o.length>q&&u.push({elem:this,matches:o.slice(q)});for(d=0;d0?this.on(b,null,a,c):this.trigger(b)},Y.test(b)&&(p.event.fixHooks[b]=p.event.keyHooks),Z.test(b)&&(p.event.fixHooks[b]=p.event.mouseHooks)}),function(a,b){function bc(a,b,c,d){c=c||[],b=b||r;var e,f,i,j,k=b.nodeType;if(!a||typeof a!="string")return c;if(k!==1&&k!==9)return[];i=g(b);if(!i&&!d)if(e=P.exec(a))if(j=e[1]){if(k===9){f=b.getElementById(j);if(!f||!f.parentNode)return c;if(f.id===j)return c.push(f),c}else if(b.ownerDocument&&(f=b.ownerDocument.getElementById(j))&&h(b,f)&&f.id===j)return c.push(f),c}else{if(e[2])return w.apply(c,x.call(b.getElementsByTagName(a),0)),c;if((j=e[3])&&_&&b.getElementsByClassName)return w.apply(c,x.call(b.getElementsByClassName(j),0)),c}return bp(a.replace(L,"$1"),b,c,d,i)}function bd(a){return function(b){var c=b.nodeName.toLowerCase();return c==="input"&&b.type===a}}function be(a){return function(b){var c=b.nodeName.toLowerCase();return(c==="input"||c==="button")&&b.type===a}}function bf(a){return z(function(b){return b=+b,z(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function bg(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}function bh(a,b){var c,d,f,g,h,i,j,k=C[o][a];if(k)return b?0:k.slice(0);h=a,i=[],j=e.preFilter;while(h){if(!c||(d=M.exec(h)))d&&(h=h.slice(d[0].length)),i.push(f=[]);c=!1;if(d=N.exec(h))f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=d[0].replace(L," ");for(g in e.filter)(d=W[g].exec(h))&&(!j[g]||(d=j[g](d,r,!0)))&&(f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=g,c.matches=d);if(!c)break}return b?h.length:h?bc.error(a):C(a,i).slice(0)}function bi(a,b,d){var e=b.dir,f=d&&b.dir==="parentNode",g=u++;return b.first?function(b,c,d){while(b=b[e])if(f||b.nodeType===1)return a(b,c,d)}:function(b,d,h){if(!h){var i,j=t+" "+g+" ",k=j+c;while(b=b[e])if(f||b.nodeType===1){if((i=b[o])===k)return b.sizset;if(typeof i=="string"&&i.indexOf(j)===0){if(b.sizset)return b}else{b[o]=k;if(a(b,d,h))return b.sizset=!0,b;b.sizset=!1}}}else while(b=b[e])if(f||b.nodeType===1)if(a(b,d,h))return b}}function bj(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function bk(a,b,c,d,e){var f,g=[],h=0,i=a.length,j=b!=null;for(;h-1},h,!0),m=[function(a,c,d){return!g&&(d||c!==l)||((b=c).nodeType?j(a,c,d):k(a,c,d))}];for(;i1&&bj(m),i>1&&a.slice(0,i-1).join("").replace(L,"$1"),c,i0,f=a.length>0,g=function(h,i,j,k,m){var n,o,p,q=[],s=0,u="0",x=h&&[],y=m!=null,z=l,A=h||f&&e.find.TAG("*",m&&i.parentNode||i),B=t+=z==null?1:Math.E;y&&(l=i!==r&&i,c=g.el);for(;(n=A[u])!=null;u++){if(f&&n){for(o=0;p=a[o];o++)if(p(n,i,j)){k.push(n);break}y&&(t=B,c=++g.el)}d&&((n=!p&&n)&&s--,h&&x.push(n))}s+=u;if(d&&u!==s){for(o=0;p=b[o];o++)p(x,q,i,j);if(h){if(s>0)while(u--)!x[u]&&!q[u]&&(q[u]=v.call(k));q=bk(q)}w.apply(k,q),y&&!h&&q.length>0&&s+b.length>1&&bc.uniqueSort(k)}return y&&(t=B,l=z),x};return g.el=0,d?z(g):g}function bo(a,b,c,d){var e=0,f=b.length;for(;e