1100 lines
No EOL
46 KiB
JavaScript
1100 lines
No EOL
46 KiB
JavaScript
// Fine Uploader 5.16.2 - MIT licensed. http://fineuploader.com
|
|
(function(global) {
|
|
var qq = function(element) {
|
|
"use strict";
|
|
return {
|
|
hide: function() {
|
|
element.style.display = "none";
|
|
return this;
|
|
},
|
|
attach: function(type, fn) {
|
|
if (element.addEventListener) {
|
|
element.addEventListener(type, fn, false);
|
|
} else if (element.attachEvent) {
|
|
element.attachEvent("on" + type, fn);
|
|
}
|
|
return function() {
|
|
qq(element).detach(type, fn);
|
|
};
|
|
},
|
|
detach: function(type, fn) {
|
|
if (element.removeEventListener) {
|
|
element.removeEventListener(type, fn, false);
|
|
} else if (element.attachEvent) {
|
|
element.detachEvent("on" + type, fn);
|
|
}
|
|
return this;
|
|
},
|
|
contains: function(descendant) {
|
|
if (!descendant) {
|
|
return false;
|
|
}
|
|
if (element === descendant) {
|
|
return true;
|
|
}
|
|
if (element.contains) {
|
|
return element.contains(descendant);
|
|
} else {
|
|
return !!(descendant.compareDocumentPosition(element) & 8);
|
|
}
|
|
},
|
|
insertBefore: function(elementB) {
|
|
elementB.parentNode.insertBefore(element, elementB);
|
|
return this;
|
|
},
|
|
remove: function() {
|
|
element.parentNode.removeChild(element);
|
|
return this;
|
|
},
|
|
css: function(styles) {
|
|
if (element.style == null) {
|
|
throw new qq.Error("Can't apply style to node as it is not on the HTMLElement prototype chain!");
|
|
}
|
|
if (styles.opacity != null) {
|
|
if (typeof element.style.opacity !== "string" && typeof element.filters !== "undefined") {
|
|
styles.filter = "alpha(opacity=" + Math.round(100 * styles.opacity) + ")";
|
|
}
|
|
}
|
|
qq.extend(element.style, styles);
|
|
return this;
|
|
},
|
|
hasClass: function(name, considerParent) {
|
|
var re = new RegExp("(^| )" + name + "( |$)");
|
|
return re.test(element.className) || !!(considerParent && re.test(element.parentNode.className));
|
|
},
|
|
addClass: function(name) {
|
|
if (!qq(element).hasClass(name)) {
|
|
element.className += " " + name;
|
|
}
|
|
return this;
|
|
},
|
|
removeClass: function(name) {
|
|
var re = new RegExp("(^| )" + name + "( |$)");
|
|
element.className = element.className.replace(re, " ").replace(/^\s+|\s+$/g, "");
|
|
return this;
|
|
},
|
|
getByClass: function(className, first) {
|
|
var candidates, result = [];
|
|
if (first && element.querySelector) {
|
|
return element.querySelector("." + className);
|
|
} else if (element.querySelectorAll) {
|
|
return element.querySelectorAll("." + className);
|
|
}
|
|
candidates = element.getElementsByTagName("*");
|
|
qq.each(candidates, function(idx, val) {
|
|
if (qq(val).hasClass(className)) {
|
|
result.push(val);
|
|
}
|
|
});
|
|
return first ? result[0] : result;
|
|
},
|
|
getFirstByClass: function(className) {
|
|
return qq(element).getByClass(className, true);
|
|
},
|
|
children: function() {
|
|
var children = [], child = element.firstChild;
|
|
while (child) {
|
|
if (child.nodeType === 1) {
|
|
children.push(child);
|
|
}
|
|
child = child.nextSibling;
|
|
}
|
|
return children;
|
|
},
|
|
setText: function(text) {
|
|
element.innerText = text;
|
|
element.textContent = text;
|
|
return this;
|
|
},
|
|
clearText: function() {
|
|
return qq(element).setText("");
|
|
},
|
|
hasAttribute: function(attrName) {
|
|
var attrVal;
|
|
if (element.hasAttribute) {
|
|
if (!element.hasAttribute(attrName)) {
|
|
return false;
|
|
}
|
|
return /^false$/i.exec(element.getAttribute(attrName)) == null;
|
|
} else {
|
|
attrVal = element[attrName];
|
|
if (attrVal === undefined) {
|
|
return false;
|
|
}
|
|
return /^false$/i.exec(attrVal) == null;
|
|
}
|
|
}
|
|
};
|
|
};
|
|
(function() {
|
|
"use strict";
|
|
qq.canvasToBlob = function(canvas, mime, quality) {
|
|
return qq.dataUriToBlob(canvas.toDataURL(mime, quality));
|
|
};
|
|
qq.dataUriToBlob = function(dataUri) {
|
|
var arrayBuffer, byteString, createBlob = function(data, mime) {
|
|
var BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder, blobBuilder = BlobBuilder && new BlobBuilder();
|
|
if (blobBuilder) {
|
|
blobBuilder.append(data);
|
|
return blobBuilder.getBlob(mime);
|
|
} else {
|
|
return new Blob([ data ], {
|
|
type: mime
|
|
});
|
|
}
|
|
}, intArray, mimeString;
|
|
if (dataUri.split(",")[0].indexOf("base64") >= 0) {
|
|
byteString = atob(dataUri.split(",")[1]);
|
|
} else {
|
|
byteString = decodeURI(dataUri.split(",")[1]);
|
|
}
|
|
mimeString = dataUri.split(",")[0].split(":")[1].split(";")[0];
|
|
arrayBuffer = new ArrayBuffer(byteString.length);
|
|
intArray = new Uint8Array(arrayBuffer);
|
|
qq.each(byteString, function(idx, character) {
|
|
intArray[idx] = character.charCodeAt(0);
|
|
});
|
|
return createBlob(arrayBuffer, mimeString);
|
|
};
|
|
qq.log = function(message, level) {
|
|
if (window.console) {
|
|
if (!level || level === "info") {
|
|
window.console.log(message);
|
|
} else {
|
|
if (window.console[level]) {
|
|
window.console[level](message);
|
|
} else {
|
|
window.console.log("<" + level + "> " + message);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
qq.isObject = function(variable) {
|
|
return variable && !variable.nodeType && Object.prototype.toString.call(variable) === "[object Object]";
|
|
};
|
|
qq.isFunction = function(variable) {
|
|
return typeof variable === "function";
|
|
};
|
|
qq.isArray = function(value) {
|
|
return Object.prototype.toString.call(value) === "[object Array]" || value && window.ArrayBuffer && value.buffer && value.buffer.constructor === ArrayBuffer;
|
|
};
|
|
qq.isItemList = function(maybeItemList) {
|
|
return Object.prototype.toString.call(maybeItemList) === "[object DataTransferItemList]";
|
|
};
|
|
qq.isNodeList = function(maybeNodeList) {
|
|
return Object.prototype.toString.call(maybeNodeList) === "[object NodeList]" || maybeNodeList.item && maybeNodeList.namedItem;
|
|
};
|
|
qq.isString = function(maybeString) {
|
|
return Object.prototype.toString.call(maybeString) === "[object String]";
|
|
};
|
|
qq.trimStr = function(string) {
|
|
if (String.prototype.trim) {
|
|
return string.trim();
|
|
}
|
|
return string.replace(/^\s+|\s+$/g, "");
|
|
};
|
|
qq.format = function(str) {
|
|
var args = Array.prototype.slice.call(arguments, 1), newStr = str, nextIdxToReplace = newStr.indexOf("{}");
|
|
qq.each(args, function(idx, val) {
|
|
var strBefore = newStr.substring(0, nextIdxToReplace), strAfter = newStr.substring(nextIdxToReplace + 2);
|
|
newStr = strBefore + val + strAfter;
|
|
nextIdxToReplace = newStr.indexOf("{}", nextIdxToReplace + val.length);
|
|
if (nextIdxToReplace < 0) {
|
|
return false;
|
|
}
|
|
});
|
|
return newStr;
|
|
};
|
|
qq.isFile = function(maybeFile) {
|
|
return window.File && Object.prototype.toString.call(maybeFile) === "[object File]";
|
|
};
|
|
qq.isFileList = function(maybeFileList) {
|
|
return window.FileList && Object.prototype.toString.call(maybeFileList) === "[object FileList]";
|
|
};
|
|
qq.isFileOrInput = function(maybeFileOrInput) {
|
|
return qq.isFile(maybeFileOrInput) || qq.isInput(maybeFileOrInput);
|
|
};
|
|
qq.isInput = function(maybeInput, notFile) {
|
|
var evaluateType = function(type) {
|
|
var normalizedType = type.toLowerCase();
|
|
if (notFile) {
|
|
return normalizedType !== "file";
|
|
}
|
|
return normalizedType === "file";
|
|
};
|
|
if (window.HTMLInputElement) {
|
|
if (Object.prototype.toString.call(maybeInput) === "[object HTMLInputElement]") {
|
|
if (maybeInput.type && evaluateType(maybeInput.type)) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
if (maybeInput.tagName) {
|
|
if (maybeInput.tagName.toLowerCase() === "input") {
|
|
if (maybeInput.type && evaluateType(maybeInput.type)) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
};
|
|
qq.isBlob = function(maybeBlob) {
|
|
if (window.Blob && Object.prototype.toString.call(maybeBlob) === "[object Blob]") {
|
|
return true;
|
|
}
|
|
};
|
|
qq.isXhrUploadSupported = function() {
|
|
var input = document.createElement("input");
|
|
input.type = "file";
|
|
return input.multiple !== undefined && typeof File !== "undefined" && typeof FormData !== "undefined" && typeof qq.createXhrInstance().upload !== "undefined";
|
|
};
|
|
qq.createXhrInstance = function() {
|
|
if (window.XMLHttpRequest) {
|
|
return new XMLHttpRequest();
|
|
}
|
|
try {
|
|
return new ActiveXObject("MSXML2.XMLHTTP.3.0");
|
|
} catch (error) {
|
|
qq.log("Neither XHR or ActiveX are supported!", "error");
|
|
return null;
|
|
}
|
|
};
|
|
qq.isFolderDropSupported = function(dataTransfer) {
|
|
return dataTransfer.items && dataTransfer.items.length > 0 && dataTransfer.items[0].webkitGetAsEntry;
|
|
};
|
|
qq.isFileChunkingSupported = function() {
|
|
return !qq.androidStock() && qq.isXhrUploadSupported() && (File.prototype.slice !== undefined || File.prototype.webkitSlice !== undefined || File.prototype.mozSlice !== undefined);
|
|
};
|
|
qq.sliceBlob = function(fileOrBlob, start, end) {
|
|
var slicer = fileOrBlob.slice || fileOrBlob.mozSlice || fileOrBlob.webkitSlice;
|
|
return slicer.call(fileOrBlob, start, end);
|
|
};
|
|
qq.arrayBufferToHex = function(buffer) {
|
|
var bytesAsHex = "", bytes = new Uint8Array(buffer);
|
|
qq.each(bytes, function(idx, byt) {
|
|
var byteAsHexStr = byt.toString(16);
|
|
if (byteAsHexStr.length < 2) {
|
|
byteAsHexStr = "0" + byteAsHexStr;
|
|
}
|
|
bytesAsHex += byteAsHexStr;
|
|
});
|
|
return bytesAsHex;
|
|
};
|
|
qq.readBlobToHex = function(blob, startOffset, length) {
|
|
var initialBlob = qq.sliceBlob(blob, startOffset, startOffset + length), fileReader = new FileReader(), promise = new qq.Promise();
|
|
fileReader.onload = function() {
|
|
promise.success(qq.arrayBufferToHex(fileReader.result));
|
|
};
|
|
fileReader.onerror = promise.failure;
|
|
fileReader.readAsArrayBuffer(initialBlob);
|
|
return promise;
|
|
};
|
|
qq.extend = function(first, second, extendNested) {
|
|
qq.each(second, function(prop, val) {
|
|
if (extendNested && qq.isObject(val)) {
|
|
if (first[prop] === undefined) {
|
|
first[prop] = {};
|
|
}
|
|
qq.extend(first[prop], val, true);
|
|
} else {
|
|
first[prop] = val;
|
|
}
|
|
});
|
|
return first;
|
|
};
|
|
qq.override = function(target, sourceFn) {
|
|
var super_ = {}, source = sourceFn(super_);
|
|
qq.each(source, function(srcPropName, srcPropVal) {
|
|
if (target[srcPropName] !== undefined) {
|
|
super_[srcPropName] = target[srcPropName];
|
|
}
|
|
target[srcPropName] = srcPropVal;
|
|
});
|
|
return target;
|
|
};
|
|
qq.indexOf = function(arr, elt, from) {
|
|
if (arr.indexOf) {
|
|
return arr.indexOf(elt, from);
|
|
}
|
|
from = from || 0;
|
|
var len = arr.length;
|
|
if (from < 0) {
|
|
from += len;
|
|
}
|
|
for (;from < len; from += 1) {
|
|
if (arr.hasOwnProperty(from) && arr[from] === elt) {
|
|
return from;
|
|
}
|
|
}
|
|
return -1;
|
|
};
|
|
qq.getUniqueId = function() {
|
|
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
|
|
var r = Math.random() * 16 | 0, v = c == "x" ? r : r & 3 | 8;
|
|
return v.toString(16);
|
|
});
|
|
};
|
|
qq.ie = function() {
|
|
return navigator.userAgent.indexOf("MSIE") !== -1 || navigator.userAgent.indexOf("Trident") !== -1;
|
|
};
|
|
qq.ie7 = function() {
|
|
return navigator.userAgent.indexOf("MSIE 7") !== -1;
|
|
};
|
|
qq.ie8 = function() {
|
|
return navigator.userAgent.indexOf("MSIE 8") !== -1;
|
|
};
|
|
qq.ie10 = function() {
|
|
return navigator.userAgent.indexOf("MSIE 10") !== -1;
|
|
};
|
|
qq.ie11 = function() {
|
|
return qq.ie() && navigator.userAgent.indexOf("rv:11") !== -1;
|
|
};
|
|
qq.edge = function() {
|
|
return navigator.userAgent.indexOf("Edge") >= 0;
|
|
};
|
|
qq.safari = function() {
|
|
return navigator.vendor !== undefined && navigator.vendor.indexOf("Apple") !== -1;
|
|
};
|
|
qq.chrome = function() {
|
|
return navigator.vendor !== undefined && navigator.vendor.indexOf("Google") !== -1;
|
|
};
|
|
qq.opera = function() {
|
|
return navigator.vendor !== undefined && navigator.vendor.indexOf("Opera") !== -1;
|
|
};
|
|
qq.firefox = function() {
|
|
return !qq.edge() && !qq.ie11() && navigator.userAgent.indexOf("Mozilla") !== -1 && navigator.vendor !== undefined && navigator.vendor === "";
|
|
};
|
|
qq.windows = function() {
|
|
return navigator.platform === "Win32";
|
|
};
|
|
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) {
|
|
if (e.preventDefault) {
|
|
e.preventDefault();
|
|
} else {
|
|
e.returnValue = false;
|
|
}
|
|
};
|
|
qq.toElement = function() {
|
|
var div = document.createElement("div");
|
|
return function(html) {
|
|
div.innerHTML = html;
|
|
var element = div.firstChild;
|
|
div.removeChild(element);
|
|
return element;
|
|
};
|
|
}();
|
|
qq.each = function(iterableItem, callback) {
|
|
var keyOrIndex, retVal;
|
|
if (iterableItem) {
|
|
if (window.Storage && iterableItem.constructor === window.Storage) {
|
|
for (keyOrIndex = 0; keyOrIndex < iterableItem.length; keyOrIndex++) {
|
|
retVal = callback(iterableItem.key(keyOrIndex), iterableItem.getItem(iterableItem.key(keyOrIndex)));
|
|
if (retVal === false) {
|
|
break;
|
|
}
|
|
}
|
|
} else if (qq.isArray(iterableItem) || qq.isItemList(iterableItem) || qq.isNodeList(iterableItem)) {
|
|
for (keyOrIndex = 0; keyOrIndex < iterableItem.length; keyOrIndex++) {
|
|
retVal = callback(keyOrIndex, iterableItem[keyOrIndex]);
|
|
if (retVal === false) {
|
|
break;
|
|
}
|
|
}
|
|
} else if (qq.isString(iterableItem)) {
|
|
for (keyOrIndex = 0; keyOrIndex < iterableItem.length; keyOrIndex++) {
|
|
retVal = callback(keyOrIndex, iterableItem.charAt(keyOrIndex));
|
|
if (retVal === false) {
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
for (keyOrIndex in iterableItem) {
|
|
if (Object.prototype.hasOwnProperty.call(iterableItem, keyOrIndex)) {
|
|
retVal = callback(keyOrIndex, iterableItem[keyOrIndex]);
|
|
if (retVal === false) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
qq.bind = function(oldFunc, context) {
|
|
if (qq.isFunction(oldFunc)) {
|
|
var args = Array.prototype.slice.call(arguments, 2);
|
|
return function() {
|
|
var newArgs = qq.extend([], args);
|
|
if (arguments.length) {
|
|
newArgs = newArgs.concat(Array.prototype.slice.call(arguments));
|
|
}
|
|
return oldFunc.apply(context, newArgs);
|
|
};
|
|
}
|
|
throw new Error("first parameter must be a function!");
|
|
};
|
|
qq.obj2url = function(obj, temp, prefixDone) {
|
|
var uristrings = [], prefix = "&", add = function(nextObj, i) {
|
|
var nextTemp = temp ? /\[\]$/.test(temp) ? temp : temp + "[" + i + "]" : i;
|
|
if (nextTemp !== "undefined" && i !== "undefined") {
|
|
uristrings.push(typeof nextObj === "object" ? qq.obj2url(nextObj, nextTemp, true) : Object.prototype.toString.call(nextObj) === "[object Function]" ? encodeURIComponent(nextTemp) + "=" + encodeURIComponent(nextObj()) : encodeURIComponent(nextTemp) + "=" + encodeURIComponent(nextObj));
|
|
}
|
|
};
|
|
if (!prefixDone && temp) {
|
|
prefix = /\?/.test(temp) ? /\?$/.test(temp) ? "" : "&" : "?";
|
|
uristrings.push(temp);
|
|
uristrings.push(qq.obj2url(obj));
|
|
} else if (Object.prototype.toString.call(obj) === "[object Array]" && typeof obj !== "undefined") {
|
|
qq.each(obj, function(idx, val) {
|
|
add(val, idx);
|
|
});
|
|
} else if (typeof obj !== "undefined" && obj !== null && typeof obj === "object") {
|
|
qq.each(obj, function(prop, val) {
|
|
add(val, prop);
|
|
});
|
|
} else {
|
|
uristrings.push(encodeURIComponent(temp) + "=" + encodeURIComponent(obj));
|
|
}
|
|
if (temp) {
|
|
return uristrings.join(prefix);
|
|
} else {
|
|
return uristrings.join(prefix).replace(/^&/, "").replace(/%20/g, "+");
|
|
}
|
|
};
|
|
qq.obj2FormData = function(obj, formData, arrayKeyName) {
|
|
if (!formData) {
|
|
formData = new FormData();
|
|
}
|
|
qq.each(obj, function(key, val) {
|
|
key = arrayKeyName ? arrayKeyName + "[" + key + "]" : key;
|
|
if (qq.isObject(val)) {
|
|
qq.obj2FormData(val, formData, key);
|
|
} else if (qq.isFunction(val)) {
|
|
formData.append(key, val());
|
|
} else {
|
|
formData.append(key, val);
|
|
}
|
|
});
|
|
return formData;
|
|
};
|
|
qq.obj2Inputs = function(obj, form) {
|
|
var input;
|
|
if (!form) {
|
|
form = document.createElement("form");
|
|
}
|
|
qq.obj2FormData(obj, {
|
|
append: function(key, val) {
|
|
input = document.createElement("input");
|
|
input.setAttribute("name", key);
|
|
input.setAttribute("value", val);
|
|
form.appendChild(input);
|
|
}
|
|
});
|
|
return form;
|
|
};
|
|
qq.parseJson = function(json) {
|
|
if (window.JSON && qq.isFunction(JSON.parse)) {
|
|
return JSON.parse(json);
|
|
} else {
|
|
return eval("(" + json + ")");
|
|
}
|
|
};
|
|
qq.getExtension = function(filename) {
|
|
var extIdx = filename.lastIndexOf(".") + 1;
|
|
if (extIdx > 0) {
|
|
return filename.substr(extIdx, filename.length - extIdx);
|
|
}
|
|
};
|
|
qq.getFilename = function(blobOrFileInput) {
|
|
if (qq.isInput(blobOrFileInput)) {
|
|
return blobOrFileInput.value.replace(/.*(\/|\\)/, "");
|
|
} else if (qq.isFile(blobOrFileInput)) {
|
|
if (blobOrFileInput.fileName !== null && blobOrFileInput.fileName !== undefined) {
|
|
return blobOrFileInput.fileName;
|
|
}
|
|
}
|
|
return blobOrFileInput.name;
|
|
};
|
|
qq.DisposeSupport = function() {
|
|
var disposers = [];
|
|
return {
|
|
dispose: function() {
|
|
var disposer;
|
|
do {
|
|
disposer = disposers.shift();
|
|
if (disposer) {
|
|
disposer();
|
|
}
|
|
} while (disposer);
|
|
},
|
|
attach: function() {
|
|
var args = arguments;
|
|
this.addDisposer(qq(args[0]).attach.apply(this, Array.prototype.slice.call(arguments, 1)));
|
|
},
|
|
addDisposer: function(disposeFunction) {
|
|
disposers.push(disposeFunction);
|
|
}
|
|
};
|
|
};
|
|
})();
|
|
(function() {
|
|
"use strict";
|
|
if (typeof define === "function" && define.amd) {
|
|
define(function() {
|
|
return qq;
|
|
});
|
|
} else if (typeof module !== "undefined" && module.exports) {
|
|
module.exports = qq;
|
|
} else {
|
|
global.qq = qq;
|
|
}
|
|
})();
|
|
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;
|
|
function testSupportsFileInputElement() {
|
|
var supported = true, tempInput;
|
|
try {
|
|
tempInput = document.createElement("input");
|
|
tempInput.type = "file";
|
|
qq(tempInput).hide();
|
|
if (tempInput.disabled) {
|
|
supported = false;
|
|
}
|
|
} catch (ex) {
|
|
supported = false;
|
|
}
|
|
return supported;
|
|
}
|
|
function isChrome14OrHigher() {
|
|
return (qq.chrome() || qq.opera()) && navigator.userAgent.match(/Chrome\/[1][4-9]|Chrome\/[2-9][0-9]/) !== undefined;
|
|
}
|
|
function isCrossOriginXhrSupported() {
|
|
if (window.XMLHttpRequest) {
|
|
var xhr = qq.createXhrInstance();
|
|
return xhr.withCredentials !== undefined;
|
|
}
|
|
return false;
|
|
}
|
|
function isXdrSupported() {
|
|
return window.XDomainRequest !== undefined;
|
|
}
|
|
function isCrossOriginAjaxSupported() {
|
|
if (isCrossOriginXhrSupported()) {
|
|
return true;
|
|
}
|
|
return isXdrSupported();
|
|
}
|
|
function isFolderSelectionSupported() {
|
|
return document.createElement("input").webkitdirectory !== undefined;
|
|
}
|
|
function isLocalStorageSupported() {
|
|
try {
|
|
return !!window.localStorage && qq.isFunction(window.localStorage.setItem);
|
|
} catch (error) {
|
|
return false;
|
|
}
|
|
}
|
|
function isDragAndDropSupported() {
|
|
var span = document.createElement("span");
|
|
return ("draggable" in span || "ondragstart" in span && "ondrop" in span) && !qq.android() && !qq.ios();
|
|
}
|
|
supportsUploading = testSupportsFileInputElement();
|
|
supportsAjaxFileUploading = supportsUploading && qq.isXhrUploadSupported();
|
|
supportsUploadingBlobs = supportsAjaxFileUploading && !qq.androidStock();
|
|
supportsFileDrop = supportsAjaxFileUploading && isDragAndDropSupported();
|
|
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();
|
|
supportsUploadCors = supportsUploading && (window.postMessage !== undefined || supportsAjaxFileUploading);
|
|
supportsDeleteFileCorsXhr = isCrossOriginXhrSupported();
|
|
supportsDeleteFileXdr = isXdrSupported();
|
|
supportsDeleteFileCors = isCrossOriginAjaxSupported();
|
|
supportsFolderSelection = isFolderSelectionSupported();
|
|
supportsImagePreviews = supportsAjaxFileUploading && window.FileReader !== undefined;
|
|
supportsUploadProgress = function() {
|
|
if (supportsAjaxFileUploading) {
|
|
return !qq.androidStock() && !qq.iosChrome();
|
|
}
|
|
return false;
|
|
}();
|
|
return {
|
|
ajaxUploading: supportsAjaxFileUploading,
|
|
blobUploading: supportsUploadingBlobs,
|
|
canDetermineSize: supportsAjaxFileUploading,
|
|
chunking: supportsChunking,
|
|
deleteFileCors: supportsDeleteFileCors,
|
|
deleteFileCorsXdr: supportsDeleteFileXdr,
|
|
deleteFileCorsXhr: supportsDeleteFileCorsXhr,
|
|
dialogElement: !!window.HTMLDialogElement,
|
|
fileDrop: supportsFileDrop,
|
|
folderDrop: supportsFolderDrop,
|
|
folderSelection: supportsFolderSelection,
|
|
imagePreviews: supportsImagePreviews,
|
|
imageValidation: supportsImagePreviews,
|
|
itemSizeValidation: supportsAjaxFileUploading,
|
|
pause: supportsChunking,
|
|
progressBar: supportsUploadProgress,
|
|
resume: supportsResume,
|
|
scaling: supportsImagePreviews && supportsUploadingBlobs,
|
|
tiffPreviews: qq.safari(),
|
|
unlimitedScaledImageSize: !qq.ios(),
|
|
uploading: supportsUploading,
|
|
uploadCors: supportsUploadCors,
|
|
uploadCustomHeaders: supportsAjaxFileUploading,
|
|
uploadNonMultipart: supportsAjaxFileUploading,
|
|
uploadViaPaste: supportsUploadViaPaste
|
|
};
|
|
}();
|
|
qq.isGenericPromise = function(maybePromise) {
|
|
"use strict";
|
|
return !!(maybePromise && maybePromise.then && qq.isFunction(maybePromise.then));
|
|
};
|
|
qq.Promise = function() {
|
|
"use strict";
|
|
var successArgs, failureArgs, successCallbacks = [], failureCallbacks = [], doneCallbacks = [], state = 0;
|
|
qq.extend(this, {
|
|
then: function(onSuccess, onFailure) {
|
|
if (state === 0) {
|
|
if (onSuccess) {
|
|
successCallbacks.push(onSuccess);
|
|
}
|
|
if (onFailure) {
|
|
failureCallbacks.push(onFailure);
|
|
}
|
|
} else if (state === -1) {
|
|
onFailure && onFailure.apply(null, failureArgs);
|
|
} else if (onSuccess) {
|
|
onSuccess.apply(null, successArgs);
|
|
}
|
|
return this;
|
|
},
|
|
done: function(callback) {
|
|
if (state === 0) {
|
|
doneCallbacks.push(callback);
|
|
} else {
|
|
callback.apply(null, failureArgs === undefined ? successArgs : failureArgs);
|
|
}
|
|
return this;
|
|
},
|
|
success: function() {
|
|
state = 1;
|
|
successArgs = arguments;
|
|
if (successCallbacks.length) {
|
|
qq.each(successCallbacks, function(idx, callback) {
|
|
callback.apply(null, successArgs);
|
|
});
|
|
}
|
|
if (doneCallbacks.length) {
|
|
qq.each(doneCallbacks, function(idx, callback) {
|
|
callback.apply(null, successArgs);
|
|
});
|
|
}
|
|
return this;
|
|
},
|
|
failure: function() {
|
|
state = -1;
|
|
failureArgs = arguments;
|
|
if (failureCallbacks.length) {
|
|
qq.each(failureCallbacks, function(idx, callback) {
|
|
callback.apply(null, failureArgs);
|
|
});
|
|
}
|
|
if (doneCallbacks.length) {
|
|
qq.each(doneCallbacks, function(idx, callback) {
|
|
callback.apply(null, failureArgs);
|
|
});
|
|
}
|
|
return this;
|
|
}
|
|
});
|
|
};
|
|
qq.DragAndDrop = function(o) {
|
|
"use strict";
|
|
var options, HIDE_ZONES_EVENT_NAME = "qq-hidezones", HIDE_BEFORE_ENTER_ATTR = "qq-hide-dropzone", uploadDropZones = [], droppedFiles = [], disposeSupport = new qq.DisposeSupport();
|
|
options = {
|
|
dropZoneElements: [],
|
|
allowMultipleItems: true,
|
|
classes: {
|
|
dropActive: null
|
|
},
|
|
callbacks: new qq.DragAndDrop.callbacks()
|
|
};
|
|
qq.extend(options, o, true);
|
|
function uploadDroppedFiles(files, uploadDropZone) {
|
|
var filesAsArray = Array.prototype.slice.call(files);
|
|
options.callbacks.dropLog("Grabbed " + files.length + " dropped files.");
|
|
uploadDropZone.dropDisabled(false);
|
|
options.callbacks.processingDroppedFilesComplete(filesAsArray, uploadDropZone.getElement());
|
|
}
|
|
function traverseFileTree(entry) {
|
|
var parseEntryPromise = new qq.Promise();
|
|
if (entry.isFile) {
|
|
entry.file(function(file) {
|
|
file.qqPath = extractDirectoryPath(entry);
|
|
droppedFiles.push(file);
|
|
parseEntryPromise.success();
|
|
}, function(fileError) {
|
|
options.callbacks.dropLog("Problem parsing '" + entry.fullPath + "'. FileError code " + fileError.code + ".", "error");
|
|
parseEntryPromise.failure();
|
|
});
|
|
} else if (entry.isDirectory) {
|
|
getFilesInDirectory(entry).then(function allEntriesRead(entries) {
|
|
var entriesLeft = entries.length;
|
|
qq.each(entries, function(idx, entry) {
|
|
traverseFileTree(entry).done(function() {
|
|
entriesLeft -= 1;
|
|
if (entriesLeft === 0) {
|
|
parseEntryPromise.success();
|
|
}
|
|
});
|
|
});
|
|
if (!entries.length) {
|
|
parseEntryPromise.success();
|
|
}
|
|
}, function readFailure(fileError) {
|
|
options.callbacks.dropLog("Problem parsing '" + entry.fullPath + "'. FileError code " + fileError.code + ".", "error");
|
|
parseEntryPromise.failure();
|
|
});
|
|
}
|
|
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) {
|
|
var newEntries = accumEntries ? accumEntries.concat(entries) : entries;
|
|
if (entries.length) {
|
|
setTimeout(function() {
|
|
getFilesInDirectory(entry, dirReader, newEntries, promise);
|
|
}, 0);
|
|
} else {
|
|
promise.success(newEntries);
|
|
}
|
|
}, promise.failure);
|
|
return promise;
|
|
}
|
|
function handleDataTransfer(dataTransfer, uploadDropZone) {
|
|
var pendingFolderPromises = [], handleDataTransferPromise = new qq.Promise();
|
|
options.callbacks.processingDroppedFiles();
|
|
uploadDropZone.dropDisabled(true);
|
|
if (dataTransfer.files.length > 1 && !options.allowMultipleItems) {
|
|
options.callbacks.processingDroppedFilesComplete([]);
|
|
options.callbacks.dropError("tooManyFilesError", "");
|
|
uploadDropZone.dropDisabled(false);
|
|
handleDataTransferPromise.failure();
|
|
} else {
|
|
droppedFiles = [];
|
|
if (qq.isFolderDropSupported(dataTransfer)) {
|
|
qq.each(dataTransfer.items, function(idx, item) {
|
|
var entry = item.webkitGetAsEntry();
|
|
if (entry) {
|
|
if (entry.isFile) {
|
|
droppedFiles.push(item.getAsFile());
|
|
} else {
|
|
pendingFolderPromises.push(traverseFileTree(entry).done(function() {
|
|
pendingFolderPromises.pop();
|
|
if (pendingFolderPromises.length === 0) {
|
|
handleDataTransferPromise.success();
|
|
}
|
|
}));
|
|
}
|
|
}
|
|
});
|
|
} else {
|
|
droppedFiles = dataTransfer.files;
|
|
}
|
|
if (pendingFolderPromises.length === 0) {
|
|
handleDataTransferPromise.success();
|
|
}
|
|
}
|
|
return handleDataTransferPromise;
|
|
}
|
|
function setupDropzone(dropArea) {
|
|
var dropZone = new qq.UploadDropZone({
|
|
HIDE_ZONES_EVENT_NAME: HIDE_ZONES_EVENT_NAME,
|
|
element: dropArea,
|
|
onEnter: function(e) {
|
|
qq(dropArea).addClass(options.classes.dropActive);
|
|
e.stopPropagation();
|
|
},
|
|
onLeaveNotDescendants: function(e) {
|
|
qq(dropArea).removeClass(options.classes.dropActive);
|
|
},
|
|
onDrop: function(e) {
|
|
handleDataTransfer(e.dataTransfer, dropZone).then(function() {
|
|
uploadDroppedFiles(droppedFiles, dropZone);
|
|
}, function() {
|
|
options.callbacks.dropLog("Drop event DataTransfer parsing failed. No files will be uploaded.", "error");
|
|
});
|
|
}
|
|
});
|
|
disposeSupport.addDisposer(function() {
|
|
dropZone.dispose();
|
|
});
|
|
qq(dropArea).hasAttribute(HIDE_BEFORE_ENTER_ATTR) && qq(dropArea).hide();
|
|
uploadDropZones.push(dropZone);
|
|
return dropZone;
|
|
}
|
|
function isFileDrag(dragEvent) {
|
|
var fileDrag;
|
|
qq.each(dragEvent.dataTransfer.types, function(key, val) {
|
|
if (val === "Files") {
|
|
fileDrag = true;
|
|
return false;
|
|
}
|
|
});
|
|
return fileDrag;
|
|
}
|
|
function leavingDocumentOut(e) {
|
|
if (qq.safari()) {
|
|
return e.x < 0 || e.y < 0;
|
|
}
|
|
return e.x === 0 && e.y === 0;
|
|
}
|
|
function setupDragDrop() {
|
|
var dropZones = options.dropZoneElements, maybeHideDropZones = function() {
|
|
setTimeout(function() {
|
|
qq.each(dropZones, function(idx, dropZone) {
|
|
qq(dropZone).hasAttribute(HIDE_BEFORE_ENTER_ATTR) && qq(dropZone).hide();
|
|
qq(dropZone).removeClass(options.classes.dropActive);
|
|
});
|
|
}, 10);
|
|
};
|
|
qq.each(dropZones, function(idx, dropZone) {
|
|
var uploadDropZone = setupDropzone(dropZone);
|
|
if (dropZones.length && qq.supportedFeatures.fileDrop) {
|
|
disposeSupport.attach(document, "dragenter", function(e) {
|
|
if (!uploadDropZone.dropDisabled() && isFileDrag(e)) {
|
|
qq.each(dropZones, function(idx, dropZone) {
|
|
if (dropZone instanceof HTMLElement && qq(dropZone).hasAttribute(HIDE_BEFORE_ENTER_ATTR)) {
|
|
qq(dropZone).css({
|
|
display: "block"
|
|
});
|
|
}
|
|
});
|
|
}
|
|
});
|
|
}
|
|
});
|
|
disposeSupport.attach(document, "dragleave", function(e) {
|
|
if (leavingDocumentOut(e)) {
|
|
maybeHideDropZones();
|
|
}
|
|
});
|
|
disposeSupport.attach(qq(document).children()[0], "mouseenter", function(e) {
|
|
maybeHideDropZones();
|
|
});
|
|
disposeSupport.attach(document, "drop", function(e) {
|
|
if (isFileDrag(e)) {
|
|
e.preventDefault();
|
|
maybeHideDropZones();
|
|
}
|
|
});
|
|
disposeSupport.attach(document, HIDE_ZONES_EVENT_NAME, maybeHideDropZones);
|
|
}
|
|
setupDragDrop();
|
|
qq.extend(this, {
|
|
setupExtraDropzone: function(element) {
|
|
options.dropZoneElements.push(element);
|
|
setupDropzone(element);
|
|
},
|
|
removeDropzone: function(element) {
|
|
var i, dzs = options.dropZoneElements;
|
|
for (i in dzs) {
|
|
if (dzs[i] === element) {
|
|
return dzs.splice(i, 1);
|
|
}
|
|
}
|
|
},
|
|
dispose: function() {
|
|
disposeSupport.dispose();
|
|
qq.each(uploadDropZones, function(idx, dropZone) {
|
|
dropZone.dispose();
|
|
});
|
|
}
|
|
});
|
|
this._testing = {};
|
|
this._testing.extractDirectoryPath = extractDirectoryPath;
|
|
};
|
|
qq.DragAndDrop.callbacks = function() {
|
|
"use strict";
|
|
return {
|
|
processingDroppedFiles: function() {},
|
|
processingDroppedFilesComplete: function(files, targetEl) {},
|
|
dropError: function(code, errorSpecifics) {
|
|
qq.log("Drag & drop error code '" + code + " with these specifics: '" + errorSpecifics + "'", "error");
|
|
},
|
|
dropLog: function(message, level) {
|
|
qq.log(message, level);
|
|
}
|
|
};
|
|
};
|
|
qq.UploadDropZone = function(o) {
|
|
"use strict";
|
|
var disposeSupport = new qq.DisposeSupport(), options, element, preventDrop, dropOutsideDisabled;
|
|
options = {
|
|
element: null,
|
|
onEnter: function(e) {},
|
|
onLeave: function(e) {},
|
|
onLeaveNotDescendants: function(e) {},
|
|
onDrop: function(e) {}
|
|
};
|
|
qq.extend(options, o);
|
|
element = options.element;
|
|
function dragoverShouldBeCanceled() {
|
|
return qq.safari() || qq.firefox() && qq.windows();
|
|
}
|
|
function disableDropOutside(e) {
|
|
if (!dropOutsideDisabled) {
|
|
if (dragoverShouldBeCanceled) {
|
|
disposeSupport.attach(document, "dragover", function(e) {
|
|
e.preventDefault();
|
|
});
|
|
} else {
|
|
disposeSupport.attach(document, "dragover", function(e) {
|
|
if (e.dataTransfer) {
|
|
e.dataTransfer.dropEffect = "none";
|
|
e.preventDefault();
|
|
}
|
|
});
|
|
}
|
|
dropOutsideDisabled = true;
|
|
}
|
|
}
|
|
function isValidFileDrag(e) {
|
|
if (!qq.supportedFeatures.fileDrop) {
|
|
return false;
|
|
}
|
|
var effectTest, dt = e.dataTransfer, isSafari = qq.safari();
|
|
effectTest = qq.ie() && qq.supportedFeatures.fileDrop ? true : dt.effectAllowed !== "none";
|
|
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) {
|
|
preventDrop = isDisabled;
|
|
}
|
|
return preventDrop;
|
|
}
|
|
function triggerHidezonesEvent() {
|
|
var hideZonesEvent;
|
|
function triggerUsingOldApi() {
|
|
hideZonesEvent = document.createEvent("Event");
|
|
hideZonesEvent.initEvent(options.HIDE_ZONES_EVENT_NAME, true, true);
|
|
}
|
|
if (window.CustomEvent) {
|
|
try {
|
|
hideZonesEvent = new CustomEvent(options.HIDE_ZONES_EVENT_NAME);
|
|
} catch (err) {
|
|
triggerUsingOldApi();
|
|
}
|
|
} else {
|
|
triggerUsingOldApi();
|
|
}
|
|
document.dispatchEvent(hideZonesEvent);
|
|
}
|
|
function attachEvents() {
|
|
disposeSupport.attach(element, "dragover", function(e) {
|
|
if (!isValidFileDrag(e)) {
|
|
return;
|
|
}
|
|
var effect = qq.ie() && qq.supportedFeatures.fileDrop ? null : e.dataTransfer.effectAllowed;
|
|
if (effect === "move" || effect === "linkMove") {
|
|
e.dataTransfer.dropEffect = "move";
|
|
} else {
|
|
e.dataTransfer.dropEffect = "copy";
|
|
}
|
|
e.stopPropagation();
|
|
e.preventDefault();
|
|
});
|
|
disposeSupport.attach(element, "dragenter", function(e) {
|
|
if (!isOrSetDropDisabled()) {
|
|
if (!isValidFileDrag(e)) {
|
|
return;
|
|
}
|
|
options.onEnter(e);
|
|
}
|
|
});
|
|
disposeSupport.attach(element, "dragleave", function(e) {
|
|
if (!isValidFileDrag(e)) {
|
|
return;
|
|
}
|
|
options.onLeave(e);
|
|
var relatedTarget = document.elementFromPoint(e.clientX, e.clientY);
|
|
if (qq(this).contains(relatedTarget)) {
|
|
return;
|
|
}
|
|
options.onLeaveNotDescendants(e);
|
|
});
|
|
disposeSupport.attach(element, "drop", function(e) {
|
|
if (!isOrSetDropDisabled()) {
|
|
if (!isValidFileDrag(e)) {
|
|
return;
|
|
}
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
options.onDrop(e);
|
|
triggerHidezonesEvent();
|
|
}
|
|
});
|
|
}
|
|
disableDropOutside();
|
|
attachEvents();
|
|
qq.extend(this, {
|
|
dropDisabled: function(isDisabled) {
|
|
return isOrSetDropDisabled(isDisabled);
|
|
},
|
|
dispose: function() {
|
|
disposeSupport.dispose();
|
|
},
|
|
getElement: function() {
|
|
return element;
|
|
}
|
|
});
|
|
this._testing = {};
|
|
this._testing.isValidFileDrag = isValidFileDrag;
|
|
};
|
|
})(window);
|
|
//# sourceMappingURL=dnd.js.map
|