diff --git a/README.md b/README.md
index a527493de..9fc16828e 100644
--- a/README.md
+++ b/README.md
@@ -80,26 +80,27 @@ Things might work in Edge 18, Firefox 50-62 and Chrome 54-68 due to one polyfill
* Removed momentjs (localization still used)
* Removed opentip (use CSS)
* Removed non-community (aka Prem/Premium/License) code
+* Modified Jua.js to be without jQuery
|js/* |1.14.0 |native |
|----------- |--------: |--------: |
|admin.js |2.130.942 | 963.702 |
-|app.js |4.184.455 |2.626.779 |
+|app.js |4.184.455 |2.626.733 |
|boot.js | 671.522 | 43.824 |
-|libs.js | 647.614 | 315.759 |
+|libs.js | 647.614 | 313.912 |
|polyfills.js | 325.834 | 0 |
-|TOTAL |7.960.367 |3.950.064 |
+|TOTAL |7.960.367 |3.948.171 |
|js/min/* |1.14.0 |native |gzip 1.14 |gzip |brotli |
|--------------- |--------: |--------: |--------: |--------: |--------: |
|admin.min.js | 252.147 | 130.802 | 73.657 | 37.916 | 32.474 |
-|app.min.js | 511.202 | 354.515 |140.462 | 93.408 | 74.849 |
+|app.min.js | 511.202 | 354.471 |140.462 | 93.386 | 74.944 |
|boot.min.js | 66.007 | 5.564 | 22.567 | 2.327 | 1.989 |
-|libs.min.js | 572.545 | 299.283 |176.720 | 92.510 | 81.659 |
+|libs.min.js | 572.545 | 297.403 |176.720 | 92.006 | 81.186 |
|polyfills.min.js | 32.452 | 0 | 11.312 | 0 | 0 |
-|TOTAL |1.434.353 | 790.164 |424.718 |226.161 |190.971 |
+|TOTAL |1.434.353 | 788.240 |424.718 |225.635 |190.593 |
-644.189 bytes (198.557 gzip) is not much, but it feels faster.
+646.113 bytes (199.083 gzip) is not much, but it feels faster.
### CSS changes
diff --git a/dev/Settings/User/Themes.js b/dev/Settings/User/Themes.js
index 1d5f1f72d..01beb9285 100644
--- a/dev/Settings/User/Themes.js
+++ b/dev/Settings/User/Themes.js
@@ -86,13 +86,12 @@ class ThemesUserSettings {
initUploader() {
if (this.background.uploaderButton() && this.capaUserBackground()) {
const oJua = new Jua({
- 'action': uploadBackground(),
- 'name': 'uploader',
- 'queueSize': 1,
- 'multipleSizeLimit': 1,
- 'disableDragAndDrop': true,
- 'disableMultiple': true,
- 'clickElement': this.background.uploaderButton()
+ action: uploadBackground(),
+ name: 'uploader',
+ queueSize: 1,
+ multipleSizeLimit: 1,
+ disableMultiple: true,
+ clickElement: this.background.uploaderButton()
});
oJua
diff --git a/dev/View/Popup/Compose.js b/dev/View/Popup/Compose.js
index 157b20b66..1c6ae7fcf 100644
--- a/dev/View/Popup/Compose.js
+++ b/dev/View/Popup/Compose.js
@@ -1182,12 +1182,12 @@ class ComposePopupView extends AbstractViewNext {
const uploadCache = {},
attachmentSizeLimit = pInt(Settings.settingsGet('AttachmentLimit')),
oJua = new Jua({
- 'action': upload(),
- 'name': 'uploader',
- 'queueSize': 2,
- 'multipleSizeLimit': 50,
- 'clickElement': this.composeUploaderButton(),
- 'dragAndDropElement': this.composeUploaderDropPlace()
+ action: upload(),
+ name: 'uploader',
+ queueSize: 2,
+ multipleSizeLimit: 50,
+ clickElement: this.composeUploaderButton(),
+ dragAndDropElement: this.composeUploaderDropPlace()
});
if (oJua) {
diff --git a/dev/View/Popup/Contacts.js b/dev/View/Popup/Contacts.js
index 589bd1b3f..b44faeb95 100644
--- a/dev/View/Popup/Contacts.js
+++ b/dev/View/Popup/Contacts.js
@@ -416,14 +416,13 @@ class ContactsPopupView extends AbstractViewNext {
initUploader() {
if (this.importUploaderButton()) {
const j = new Jua({
- 'action': uploadContacts(),
- 'name': 'uploader',
- 'queueSize': 1,
- 'multipleSizeLimit': 1,
- 'disableDragAndDrop': true,
- 'disableMultiple': true,
- 'disableDocumentDropPrevent': true,
- 'clickElement': this.importUploaderButton()
+ action: uploadContacts(),
+ name: 'uploader',
+ queueSize: 1,
+ multipleSizeLimit: 1,
+ disableMultiple: true,
+ disableDocumentDropPrevent: true,
+ clickElement: this.importUploaderButton()
});
if (j) {
diff --git a/vendors/jua/jua.js b/vendors/jua/jua.js
index e4127dc25..316e45a20 100644
--- a/vendors/jua/jua.js
+++ b/vendors/jua/jua.js
@@ -2,11 +2,9 @@
(()=>{
'use strict';
- var
- iDefLimit = 20,
- $ = jQuery;
-
const
+ doc = document,
+ iDefLimit = 20,
defined = v => undefined !== v,
/**
* @param {*} aItems
@@ -18,16 +16,14 @@
{
if (aItems && aItems.length)
{
- var
- iInputLimit = 0,
+ iLimit = defined(iLimit) ? parseInt(iLimit || 0, 10) : iDefLimit;
+ let
+ iInputLimit = iLimit,
oFile = null,
- bUseLimit = false,
+ bUseLimit = 0 < iLimit,
bCallLimit = false
;
- iLimit = defined(iLimit) ? parseInt(iLimit || 0, 10) : iDefLimit;
- iInputLimit = iLimit;
- bUseLimit = 0 < iLimit;
Array.from(aItems).forEach(oItem => {
if (oItem)
{
@@ -45,75 +41,12 @@
});
}
},
- /**
- * @param {number=} iLen
- * @return {string}
- */
- fakeMd5 = iLen =>
- {
- var
- sResult = '',
- sLine = '0123456789abcdefghijklmnopqrstuvwxyz'
- ;
- iLen = defined(iLen) ? parseInt(iLen || 0, 10) : 32;
-
- while (iLen--)
- sResult += sLine.substr(Math.round(Math.random() * 36), 1);
-
- return sResult;
- };
-
- var Utils = {
- /**
- * @param {*} oParent
- * @param {*} oDescendant
- *
- * @return {boolean}
- */
- contains : (oParent, oDescendant) =>
- {
- if (oParent && oDescendant)
- {
- if (oParent === oDescendant)
- {
- return true;
- }
- if (oParent.contains)
- {
- return oParent.contains(oDescendant);
- }
- /*jshint bitwise: false*/
- return oDescendant.compareDocumentPosition ?
- !!(oDescendant.compareDocumentPosition(oParent) & 8) : false;
- /*jshint bitwise: true*/
- }
-
- return false;
- },
-
- mainClearTimeout : iTimer =>
- {
- if (0 < iTimer)
- {
- clearTimeout(iTimer);
- }
-
- iTimer = 0;
- },
-
- /**
- * @param {Event} oEvent
- * @return {?Event}
- */
- getEvent : oEvent =>
- {
- oEvent = (oEvent && (oEvent.originalEvent ?
- oEvent.originalEvent : oEvent)) || window.event;
-
- return oEvent.dataTransfer ? oEvent : null;
+ addEventListeners = (element, obj) => {
+ Object.entries(obj).forEach(([key, value]) => element.addEventListener(key, value));
},
+ Utils = {
/**
* @param {Object} oValues
* @param {string} sKey
@@ -122,28 +55,13 @@
*/
getValue : (oValues, sKey, mDefault) => (!oValues || !sKey || !defined(oValues[sKey])) ? mDefault : oValues[sKey],
- /**
- * @param {Function} fFunction
- * @param {Object=} oScope
- * @return {Function}
- */
- scopeBind : (fFunction, oScope) => (...args) => {
- return fFunction.apply(defined(oScope) ? oScope : null,
- Array.prototype.slice.call(args));
- },
-
- /**
- * @return {string}
- */
- getNewUid : () => 'jua-uid-' + fakeMd5(16) + '-' + (new Date()).getTime().toString(),
-
/**
* @param {*} oFile
* @return {Object}
*/
getDataFromFile : oFile =>
{
- var
+ let
sFileName = defined(oFile.fileName) ? oFile.fileName : (defined(oFile.name) ? oFile.name : null),
iSize = defined(oFile.fileSize) ? oFile.fileSize : (defined(oFile.size) ? oFile.size : null),
sType = defined(oFile.type) ? oFile.type : null
@@ -168,116 +86,18 @@
};
},
- /**
- * @param {*} oInput
- * @param {Function} fFileCallback
- * @param {number=} iLimit = 20
- * @param {Function=} fLimitCallback
- */
- getDataFromInput : (oInput, fFileCallback, iLimit, fLimitCallback) =>
- {
- var aFiles = oInput && 0 < oInput.files.length ? oInput.files : null;
- if (aFiles)
- {
- getDataFromFiles(aFiles, fFileCallback, iLimit, fLimitCallback);
- }
- else
- {
- fFileCallback({
- 'FileName': oInput.value.split('\\').pop().split('/').pop(),
- 'Size': null,
- 'Type': null,
- 'Folder': '',
- 'File' : null
- });
- }
- },
-
eventContainsFiles : oEvent =>
{
- var bResult = false;
- if (oEvent && oEvent.dataTransfer && oEvent.dataTransfer.types && oEvent.dataTransfer.types.length)
- {
- var
- iIindex = 0,
- iLen = oEvent.dataTransfer.types.length
- ;
-
- for (; iIindex < iLen; iIindex++)
- {
- if (oEvent.dataTransfer.types[iIindex].toLowerCase() === 'files')
- {
- bResult = true;
- break;
+ if (oEvent.dataTransfer && oEvent.dataTransfer.types && oEvent.dataTransfer.types.length) {
+ let index = oEvent.dataTransfer.types.length;
+ while (index--) {
+ if (oEvent.dataTransfer.types[index].toLowerCase() === 'files') {
+ return true;
}
}
}
-
- return bResult;
- },
-
- /**
- * @param {Event} oEvent
- * @param {Function} fFileCallback
- * @param {number=} iLimit = 20
- * @param {Function=} fLimitCallback
- */
- getDataFromDragEvent : (oEvent, fFileCallback, iLimit, fLimitCallback) =>
- {
- var aFiles = null;
-
- oEvent = Utils.getEvent(oEvent);
- if (oEvent && Utils.eventContainsFiles(oEvent))
- {
- aFiles = (Utils.getValue(oEvent, 'files', null) || (oEvent.dataTransfer ?
- Utils.getValue(oEvent.dataTransfer, 'files', null) : null));
-
- getDataFromFiles(aFiles, fFileCallback, iLimit, fLimitCallback);
- }
- },
-
- createNextLabel : () =>
- {
- return $('').css({
- 'opacity': 0
- });
- },
-
- createNextInput : () => $(''),
-
- /**
- * @param {string=} sName
- * @param {boolean=} bMultiple = true
- * @return {?Object}
- */
- getNewInput : (sName, bMultiple) =>
- {
- sName = defined(sName) ? sName.toString() : '';
-
- var oLocal = Utils.createNextInput();
- if (0 < sName.length)
- {
- oLocal.attr('name', sName);
- }
-
- if (defined(bMultiple) ? bMultiple : true)
- {
- oLocal.prop('multiple', true);
- }
-
- return oLocal;
- },
-
- /**
- * @param {?} mStringOrFunction
- * @param {Array=} aFunctionParams
- * @return {string}
- */
- getStringOrCallFunction : (mStringOrFunction, aFunctionParams) => $.isFunction(mStringOrFunction) ?
- mStringOrFunction.apply(null, Array.isArray(aFunctionParams) ? aFunctionParams : []).toString() :
- mStringOrFunction.toString()
+ return false;
+ }
};
@@ -319,7 +139,7 @@
try
{
- var
+ const
self = this,
oXhr = new XMLHttpRequest(),
oFormData = new FormData(),
@@ -347,7 +167,7 @@
{
if (fCompleteFunction)
{
- var
+ let
bResult = false,
oResult = null
;
@@ -389,9 +209,9 @@
oFormData.append('jua-post-type', 'ajax');
oFormData.append(Utils.getValue(this.oOptions, 'name', 'juaFile'), oFileInfo['File']);
- $.each(aHidden, function (sKey, sValue) {
- oFormData.append(sKey, Utils.getStringOrCallFunction(sValue, [oFileInfo]));
- });
+ Object.entries(aHidden).forEach(([key, value]) =>
+ oFormData.append(key, (typeof value === "function" ? value(oFileInfo) : value).toString())
+ );
oXhr.send(oFormData);
@@ -408,40 +228,43 @@
generateNewInput(oClickElement)
{
- var
- self = this,
- oLabel = null,
- oInput = null
- ;
-
if (oClickElement)
{
- oInput = Utils.getNewInput('', !Utils.getValue(this.oOptions, 'disableMultiple', false));
- oLabel = Utils.createNextLabel();
- oLabel.append(oInput);
+ const self = this,
+ oLabel = doc.createElement('label'),
+ oInput = oLabel.appendChild(doc.createElement('input'));
- $(oClickElement).append(oLabel);
+ oInput.type = 'file';
+ oInput.tabIndex = -1;
+ oInput.style.cssText = 'position:absolute;left:-9999px;';
+ oInput.multiple = !Utils.getValue(self.oOptions, 'disableMultiple', false);
- oInput
- .on('click', function () {
- var fOn = self.oJua.getEvent('onDialog');
- if (fOn)
- {
- fOn();
- }
- })
- .on('change', function () {
- Utils.getDataFromInput(this, oFile => {
- self.oJua.addNewFile(oFile);
- self.generateNewInput(oClickElement);
+ oLabel.style.cssText = 'position:absolute;background-color:#fff;right:0;top:0;left:0;bottom:0;margin:0;padding:0;cursor:pointer;opacity:0';
- setTimeout(() => oLabel.remove(), 10);
- },
+ oClickElement.append(oLabel);
+
+ oInput.addEventListener('input', () => {
+ const fFileCallback = oFile => {
+ self.oJua.addNewFile(oFile);
+ self.generateNewInput(oClickElement);
+
+ setTimeout(() => oLabel.remove(), 10);
+ };
+ if (oInput.files && oInput.files.length) {
+ getDataFromFiles(oInput.files, fFileCallback,
Utils.getValue(self.oOptions, 'multipleSizeLimit', iDefLimit),
self.oJua.getEvent('onLimitReached')
);
- })
- ;
+ } else {
+ fFileCallback({
+ 'FileName': oInput.value.split('\\').pop().split('/').pop(),
+ 'Size': null,
+ 'Type': null,
+ 'Folder': '',
+ 'File' : null
+ });
+ }
+ });
}
}
@@ -490,7 +313,7 @@
function queue(a) {
function l() {
if (g && d < a) {
- var b = g,
+ let b = g,
c = b[0],
f = Array.prototype.slice.call(b, 1),
m = b.index;
@@ -502,7 +325,7 @@
c.apply(null, f)
}
}
- var c = {},
+ let c = {},
d = 0,
e = 0,
f = -1,
@@ -511,7 +334,7 @@
k = ()=>{};
return arguments.length < 1 && (a = Infinity), c.defer = function () {
if (!i) {
- var a = arguments;
+ let a = arguments;
a.index = ++f, h ? (h.next = a, h = h.next) : g = h = a, ++e, l()
}
return c
@@ -530,251 +353,159 @@
{
oOptions = defined(oOptions) ? oOptions : {};
- var
- self = this,
-
- $ = jQuery
- ;
-
- self.bEnableDnD = true;
+ const self = this;
self.oEvents = {
- 'onDialog': null,
- 'onSelect': null,
- 'onStart': null,
- 'onComplete': null,
- 'onCompleteAll': null,
- 'onProgress': null,
- 'onDragEnter': null,
- 'onDragLeave': null,
- 'onDrop': null,
- 'onBodyDragEnter': null,
- 'onBodyDragLeave': null,
- 'onLimitReached': null
+ onSelect: null,
+ onStart: null,
+ onComplete: null,
+ onProgress: null,
+ onDragEnter: null,
+ onDragLeave: null,
+ onBodyDragEnter: null,
+ onBodyDragLeave: null,
+ onLimitReached: null
};
self.oOptions = {
- 'action': '',
- 'name': '',
- 'hidden': {},
- 'queueSize': 10,
- 'clickElement': false,
- 'dragAndDropElement': false,
- 'dragAndDropBodyElement': false,
- 'disableDragAndDrop': false,
- 'disableMultiple': false,
- 'disableDocumentDropPrevent': false,
- 'multipleSizeLimit': 50
+ action: '',
+ name: '',
+ hidden: {},
+ queueSize: 10,
+ clickElement: false,
+ dragAndDropElement: false,
+ dragAndDropBodyElement: false,
+ disableMultiple: false,
+ disableDocumentDropPrevent: false,
+ multipleSizeLimit: 50
};
- Object.entries(oOptions).forEach(([key, value])=>self.oOptions[key]=value);
+ Object.entries(oOptions).forEach(([key, value]) => self.oOptions[key] = value);
self.oQueue = queue(parseInt(Utils.getValue(self.oOptions, 'queueSize', 10) || 0, 10));
- if (self.runEvent('onCompleteAll'))
- {
- self.oQueue.await(function () {
- self.runEvent('onCompleteAll');
- });
- }
self.oDriver = new AjaxDriver(self, self.oOptions);
- self.oClickElement = Utils.getValue(self.oOptions, 'clickElement', null);
-
- if (self.oClickElement)
- {
- $(self.oClickElement).css({
- 'position': 'relative',
- 'overflow': 'hidden'
- });
-
- if ('inline' === $(this.oClickElement).css('display'))
- {
- $(this.oClickElement).css('display', 'inline-block');
+ const el = Utils.getValue(self.oOptions, 'clickElement', null);
+ if (el) {
+ el.style.position = 'relative';
+ el.style.overflow = 'hidden';
+ if ('inline' === el.style.display) {
+ el.style.display = 'inline-block';
}
- this.oDriver.generateNewInput(this.oClickElement);
+ this.oDriver.generateNewInput(el);
}
if (Utils.getValue(this.oOptions, 'dragAndDropElement', false))
{
- (function (self) {
- var
- $doc = $(document),
- oBigDropZone = $(Utils.getValue(self.oOptions, 'dragAndDropBodyElement', false) || $doc),
- oDragAndDropElement = Utils.getValue(self.oOptions, 'dragAndDropElement', false),
- fHandleDragOver = function (oEvent) {
- if (self.bEnableDnD && oEvent)
+ let
+ oBigDropZone = Utils.getValue(self.oOptions, 'dragAndDropBodyElement', false) || doc,
+ oDragAndDropElement = Utils.getValue(self.oOptions, 'dragAndDropElement', false);
+
+ if (oDragAndDropElement)
+ {
+ if (!Utils.getValue(self.oOptions, 'disableDocumentDropPrevent', false))
+ {
+ doc.addEventListener('dragover', oEvent => {
+ if (Utils.eventContainsFiles(oEvent))
{
- oEvent = Utils.getEvent(oEvent);
- if (oEvent && oEvent.dataTransfer && Utils.eventContainsFiles(oEvent))
+ try
{
- try
- {
- var sEffect = oEvent.dataTransfer.effectAllowed;
+ oEvent.dataTransfer.dropEffect = 'none';
+ oEvent.preventDefault();
+ }
+ catch (oExc) {}
+ }
+ });
+ }
- Utils.mainClearTimeout(self.iDocTimer);
+ if (oBigDropZone)
+ {
+ addEventListeners(oBigDropZone, {
+ dragover: () => self.docTimer.clear(),
+ dragenter: oEvent => {
+ if (Utils.eventContainsFiles(oEvent))
+ {
+ self.docTimer.clear();
+ oEvent.preventDefault();
- oEvent.dataTransfer.dropEffect = (sEffect === 'move' || sEffect === 'linkMove') ? 'move' : 'copy';
+ self.runEvent('onBodyDragEnter', [oEvent]);
+ }
+ },
+ dragleave: oEvent =>
+ oEvent.dataTransfer && self.docTimer.start(() => self.runEvent('onBodyDragLeave', [oEvent])),
+ drop: oEvent => {
+ if (oEvent.dataTransfer) {
+ let bFiles = Utils.eventContainsFiles(oEvent);
+ bFiles && oEvent.preventDefault();
- oEvent.stopPropagation();
- oEvent.preventDefault();
+ self.runEvent('onBodyDragLeave', [oEvent]);
- oBigDropZone.trigger('dragover', oEvent);
- }
- catch (oExc) {}
+ return !bFiles;
+ }
+
+ return false;
+ }
+ });
+ }
+
+ addEventListeners(oDragAndDropElement, {
+ dragenter: oEvent => {
+ if (Utils.eventContainsFiles(oEvent)) {
+ self.docTimer.clear();
+
+ oEvent.preventDefault();
+ self.runEvent('onDragEnter', [oDragAndDropElement, oEvent]);
+ }
+ },
+ dragover: oEvent => {
+ if (Utils.eventContainsFiles(oEvent)) {
+ try
+ {
+ let sEffect = oEvent.dataTransfer.effectAllowed;
+
+ self.docTimer.clear();
+
+ oEvent.dataTransfer.dropEffect = (sEffect === 'move' || sEffect === 'linkMove') ? 'move' : 'copy';
+
+ oEvent.stopPropagation();
+ oEvent.preventDefault();
+
+ oBigDropZone && oBigDropZone.dispatchEvent(oEvent);
+ }
+ catch (oExc) {}
+ }
+ },
+ dragleave: oEvent => {
+ if (oEvent.dataTransfer) {
+ let oRelatedTarget = doc.elementFromPoint(oEvent.clientX, oEvent.clientY);
+ if (!oRelatedTarget || !oDragAndDropElement.contains(oRelatedTarget)) {
+ self.docTimer.clear();
+ self.runEvent('onDragLeave', [oDragAndDropElement, oEvent]);
}
}
},
- fHandleDrop = function (oEvent) {
- if (self.bEnableDnD && oEvent)
- {
- oEvent = Utils.getEvent(oEvent);
- if (oEvent && Utils.eventContainsFiles(oEvent))
- {
- oEvent.preventDefault();
+ drop: oEvent => {
+ if (Utils.eventContainsFiles(oEvent)) {
+ oEvent.preventDefault();
- Utils.getDataFromDragEvent(oEvent, function (oFile) {
- if (oFile)
- {
- self.runEvent('onDrop', [oFile, oEvent]);
- self.addNewFile(oFile);
- Utils.mainClearTimeout(self.iDocTimer);
- }
- },
- Utils.getValue(self.oOptions, 'multipleSizeLimit', iDefLimit),
- self.getEvent('onLimitReached')
- );
- }
+ getDataFromFiles(
+ Utils.getValue(oEvent, 'files', null) || Utils.getValue(oEvent.dataTransfer, 'files', null),
+ oFile => {
+ if (oFile) {
+ self.addNewFile(oFile);
+ self.docTimer.clear();
+ }
+ },
+ Utils.getValue(self.oOptions, 'multipleSizeLimit', iDefLimit),
+ self.getEvent('onLimitReached')
+ );
}
self.runEvent('onDragLeave', [oEvent]);
- },
- fHandleDragEnter = function (oEvent) {
- if (self.bEnableDnD && oEvent)
- {
- oEvent = Utils.getEvent(oEvent);
- if (oEvent && Utils.eventContainsFiles(oEvent))
- {
- Utils.mainClearTimeout(self.iDocTimer);
-
- oEvent.preventDefault();
- self.runEvent('onDragEnter', [oDragAndDropElement, oEvent]);
- }
- }
- },
- fHandleDragLeave = function (oEvent) {
- if (self.bEnableDnD && oEvent)
- {
- oEvent = Utils.getEvent(oEvent);
- if (oEvent)
- {
- var oRelatedTarget = document['elementFromPoint'] ? document['elementFromPoint'](oEvent['clientX'], oEvent['clientY']) : null;
- if (oRelatedTarget && Utils.contains(this, oRelatedTarget))
- {
- return;
- }
-
- Utils.mainClearTimeout(self.iDocTimer);
- self.runEvent('onDragLeave', [oDragAndDropElement, oEvent]);
- }
-
- return;
- }
}
- ;
-
- if (oDragAndDropElement)
- {
- if (!Utils.getValue(self.oOptions, 'disableDocumentDropPrevent', false))
- {
- $doc.on('dragover', function (oEvent) {
- if (self.bEnableDnD && oEvent)
- {
- oEvent = Utils.getEvent(oEvent);
- if (oEvent && oEvent.dataTransfer && Utils.eventContainsFiles(oEvent))
- {
- try
- {
- oEvent.dataTransfer.dropEffect = 'none';
- oEvent.preventDefault();
- }
- catch (oExc) {}
- }
- }
- });
- }
-
- if (oBigDropZone && oBigDropZone[0])
- {
- oBigDropZone
- .on('dragover', function (oEvent) {
- if (self.bEnableDnD && oEvent)
- {
- Utils.mainClearTimeout(self.iDocTimer);
- }
- })
- .on('dragenter', function (oEvent) {
- if (self.bEnableDnD && oEvent)
- {
- oEvent = Utils.getEvent(oEvent);
- if (oEvent && Utils.eventContainsFiles(oEvent))
- {
- Utils.mainClearTimeout(self.iDocTimer);
- oEvent.preventDefault();
-
- self.runEvent('onBodyDragEnter', [oEvent]);
- }
- }
- })
- .on('dragleave', function (oEvent) {
- if (self.bEnableDnD && oEvent)
- {
- oEvent = Utils.getEvent(oEvent);
- if (oEvent)
- {
- Utils.mainClearTimeout(self.iDocTimer);
- self.iDocTimer = setTimeout(function () {
- self.runEvent('onBodyDragLeave', [oEvent]);
- }, 200);
- }
- }
- })
- .on('drop', function (oEvent) {
- if (self.bEnableDnD && oEvent)
- {
- oEvent = Utils.getEvent(oEvent);
- if (oEvent)
- {
- var bFiles = Utils.eventContainsFiles(oEvent);
- if (bFiles)
- {
- oEvent.preventDefault();
- }
-
- self.runEvent('onBodyDragLeave', [oEvent]);
-
- return !bFiles;
- }
- }
-
- return false;
- })
- ;
- }
-
- $(oDragAndDropElement)
- .on('dragenter', fHandleDragEnter)
- .on('dragover', fHandleDragOver)
- .on('dragleave', fHandleDragLeave)
- .on('drop', fHandleDrop)
- ;
- }
-
- }(self));
- }
- else
- {
- self.bEnableDnD = false;
+ });
+ }
}
}
@@ -816,20 +547,19 @@
this.oDriver.cancel(sUid);
}
- /**
- * @param {boolean} bEnabled
- */
- setDragAndDropEnabledStatus(bEnabled)
- {
- this.bEnableDnD = !!bEnabled;
- }
-
/**
* @param {Object} oFileInfo
*/
addNewFile(oFileInfo)
{
- this.addFile(Utils.getNewUid(), oFileInfo);
+ let iLen = 16,
+ fakeMd5 = '',
+ sLine = '0123456789abcdefghijklmnopqrstuvwxyz';
+
+ while (iLen--)
+ fakeMd5 += sLine.substr(Math.round(Math.random() * 36), 1);
+
+ this.addFile('jua-uid-' + fakeMd5 + '-' + (new Date()).getTime().toString(), oFileInfo);
}
/**
@@ -838,11 +568,11 @@
*/
addFile(sUid, oFileInfo)
{
- var fOnSelect = this.getEvent('onSelect');
+ const fOnSelect = this.getEvent('onSelect');
if (oFileInfo && (!fOnSelect || (false !== fOnSelect(sUid, oFileInfo))))
{
this.oDriver.regTaskUid(sUid);
- this.oQueue.defer(Utils.scopeBind(this.oDriver.uploadTask, this.oDriver), sUid, oFileInfo);
+ this.oQueue.defer((...args) => this.oDriver.uploadTask(...args), sUid, oFileInfo);
}
else
{
@@ -851,15 +581,19 @@
}
}
- /**
- * @type {boolean}
- */
- Jua.prototype.bEnableDnD = true;
-
/**
* @type {number}
*/
- Jua.prototype.iDocTimer = 0;
+ Jua.prototype.docTimer = {
+ start: function(fn){
+ this.clear();
+ this.timer = setTimeout(fn, 200);
+ },
+ clear: function(){
+ this.timer && clearTimeout(this.timer);
+ this.timer = 0;
+ }
+ };
/**
* @type {Object}
diff --git a/vendors/jua/jua.min.js b/vendors/jua/jua.min.js
index 45e1022fb..54fc3fef9 100644
--- a/vendors/jua/jua.min.js
+++ b/vendors/jua/jua.min.js
@@ -1,2 +1,2 @@
/* RainLoop Webmail (c) RainLoop Team | MIT */
-(()=>{"use strict";var e=20,t=jQuery;const n=e=>void 0!==e,o=(t,o,i,r)=>{if(t&&t.length){var l,u,s=null,p=!1;i=n(i)?parseInt(i||0,10):e,l=i,u=0{e&&(!u||0<=--i?(s=a.getDataFromFile(e))&&o(s):u&&!p&&0>i&&r&&(p=!0,r(l)))})}};var a={contains:(e,t)=>!(!e||!t)&&(e===t||(e.contains?e.contains(t):!!t.compareDocumentPosition&&!!(8&t.compareDocumentPosition(e)))),mainClearTimeout:e=>{0(e=e&&(e.originalEvent?e.originalEvent:e)||window.event).dataTransfer?e:null,getValue:(e,t,o)=>e&&t&&n(e[t])?e[t]:o,scopeBind:(e,t)=>(...o)=>e.apply(n(t)?t:null,Array.prototype.slice.call(o)),getNewUid:()=>"jua-uid-"+(e=>{var t="";for(e=n(e)?parseInt(e||0,10):32;e--;)t+="0123456789abcdefghijklmnopqrstuvwxyz".substr(Math.round(36*Math.random()),1);return t})(16)+"-"+(new Date).getTime().toString(),getDataFromFile:e=>{var t=n(e.fileName)?e.fileName:n(e.name)?e.name:null,o=n(e.fileSize)?e.fileSize:n(e.size)?e.size:null,a=n(e.type)?e.type:null;return"/"===t.charAt(0)&&(t=t.substr(1)),a||0!==o?{FileName:t,Size:o,Type:a,Folder:"",File:e}:null},getDataFromInput:(e,t,n,a)=>{var i=e&&0{var t=!1;if(e&&e.dataTransfer&&e.dataTransfer.types&&e.dataTransfer.types.length)for(var n=0,o=e.dataTransfer.types.length;n{var r=null;(e=a.getEvent(e))&&a.eventContainsFiles(e)&&(r=a.getValue(e,"files",null)||(e.dataTransfer?a.getValue(e.dataTransfer,"files",null):null),o(r,t,n,i))},createNextLabel:()=>t('').css({opacity:0}),createNextInput:()=>t(''),getNewInput:(e,t)=>{e=n(e)?e.toString():"";var o=a.createNextInput();return 0t.isFunction(e)?e.apply(null,Array.isArray(n)?n:[]).toString():e.toString()};class i{constructor(e,t){this.oXhrs={},this.oUids={},this.oJua=e,this.oOptions=t}regTaskUid(e){this.oUids[e]=!0}uploadTask(e,o,i){if(!1===this.oUids[e]||!o||!o.File)return i(null,e),!1;try{var r=this,l=new XMLHttpRequest,u=new FormData,s=a.getValue(this.oOptions,"action",""),p=a.getValue(this.oOptions,"hidden",{}),c=this.oJua.getEvent("onStart"),d=this.oJua.getEvent("onComplete"),g=this.oJua.getEvent("onProgress");return l.open("POST",s,!0),g&&l.upload&&(l.upload.onprogress=function(t){t&&t.lengthComputable&&n(t.loaded)&&n(t.total)&&g(e,t.loaded,t.total)}),l.onreadystatechange=function(){if(4===l.readyState&&200===l.status){if(d){var t=!1,o=null;try{o=JSON.parse(l.responseText),t=!0}catch(e){o=null}d(e,t,o)}n(r.oXhrs[e])&&(r.oXhrs[e]=null),i(null,e)}else 4===l.readyState&&(d(e,!1,null),i(null,e))},c&&c(e),u.append("jua-post-type","ajax"),u.append(a.getValue(this.oOptions,"name","juaFile"),o.File),t.each(p,function(e,t){u.append(e,a.getStringOrCallFunction(t,[o]))}),l.send(u),this.oXhrs[e]=l,!0}catch(e){}return i(null,e),!1}generateNewInput(n){var o=this,i=null,r=null;n&&(r=a.getNewInput("",!a.getValue(this.oOptions,"disableMultiple",!1)),(i=a.createNextLabel()).append(r),t(n).append(i),r.on("click",function(){var e=o.oJua.getEvent("onDialog");e&&e()}).on("change",function(){a.getDataFromInput(this,e=>{o.oJua.addNewFile(e),o.generateNewInput(n),setTimeout(()=>i.remove(),10)},a.getValue(o.oOptions,"multipleSizeLimit",e),o.oJua.getEvent("onLimitReached"))}))}cancel(e){if(this.oUids[e]=!1,this.oXhrs[e]){try{this.oXhrs[e].abort&&this.oXhrs[e].abort()}catch(e){}this.oXhrs[e]=null}}}i.prototype.oXhrs={},i.prototype.oUids={},i.prototype.oJua=null,i.prototype.oOptions={};class r{constructor(t){t=n(t)?t:{};var o=this,r=jQuery;o.bEnableDnD=!0,o.oEvents={onDialog:null,onSelect:null,onStart:null,onComplete:null,onCompleteAll:null,onProgress:null,onDragEnter:null,onDragLeave:null,onDrop:null,onBodyDragEnter:null,onBodyDragLeave:null,onLimitReached:null},o.oOptions={action:"",name:"",hidden:{},queueSize:10,clickElement:!1,dragAndDropElement:!1,dragAndDropBodyElement:!1,disableDragAndDrop:!1,disableMultiple:!1,disableDocumentDropPrevent:!1,multipleSizeLimit:50},Object.entries(t).forEach(([e,t])=>o.oOptions[e]=t),o.oQueue=function(e){function t(){if(n&&i{};return arguments.length<1&&(e=1/0),a.defer=function(){if(!u){var e=arguments;e.index=++l,o?(o.next=e,o=o.next):n=o=e,++r,t()}return a},a.await=function(e){return p=e,r||p(u,s),a},a}(parseInt(a.getValue(o.oOptions,"queueSize",10)||0,10)),o.runEvent("onCompleteAll")&&o.oQueue.await(function(){o.runEvent("onCompleteAll")}),o.oDriver=new i(o,o.oOptions),o.oClickElement=a.getValue(o.oOptions,"clickElement",null),o.oClickElement&&(r(o.oClickElement).css({position:"relative",overflow:"hidden"}),"inline"===r(this.oClickElement).css("display")&&r(this.oClickElement).css("display","inline-block"),this.oDriver.generateNewInput(this.oClickElement)),a.getValue(this.oOptions,"dragAndDropElement",!1)?function(t){var n=r(document),o=r(a.getValue(t.oOptions,"dragAndDropBodyElement",!1)||n),i=a.getValue(t.oOptions,"dragAndDropElement",!1);i&&(a.getValue(t.oOptions,"disableDocumentDropPrevent",!1)||n.on("dragover",function(e){if(t.bEnableDnD&&e&&(e=a.getEvent(e))&&e.dataTransfer&&a.eventContainsFiles(e))try{e.dataTransfer.dropEffect="none",e.preventDefault()}catch(e){}}),o&&o[0]&&o.on("dragover",function(e){t.bEnableDnD&&e&&a.mainClearTimeout(t.iDocTimer)}).on("dragenter",function(e){t.bEnableDnD&&e&&(e=a.getEvent(e))&&a.eventContainsFiles(e)&&(a.mainClearTimeout(t.iDocTimer),e.preventDefault(),t.runEvent("onBodyDragEnter",[e]))}).on("dragleave",function(e){t.bEnableDnD&&e&&(e=a.getEvent(e))&&(a.mainClearTimeout(t.iDocTimer),t.iDocTimer=setTimeout(function(){t.runEvent("onBodyDragLeave",[e])},200))}).on("drop",function(e){if(t.bEnableDnD&&e&&(e=a.getEvent(e))){var n=a.eventContainsFiles(e);return n&&e.preventDefault(),t.runEvent("onBodyDragLeave",[e]),!n}return!1}),r(i).on("dragenter",function(e){t.bEnableDnD&&e&&(e=a.getEvent(e))&&a.eventContainsFiles(e)&&(a.mainClearTimeout(t.iDocTimer),e.preventDefault(),t.runEvent("onDragEnter",[i,e]))}).on("dragover",function(e){if(t.bEnableDnD&&e&&(e=a.getEvent(e))&&e.dataTransfer&&a.eventContainsFiles(e))try{var n=e.dataTransfer.effectAllowed;a.mainClearTimeout(t.iDocTimer),e.dataTransfer.dropEffect="move"===n||"linkMove"===n?"move":"copy",e.stopPropagation(),e.preventDefault(),o.trigger("dragover",e)}catch(e){}}).on("dragleave",function(e){if(t.bEnableDnD&&e&&(e=a.getEvent(e))){var n=document.elementFromPoint?document.elementFromPoint(e.clientX,e.clientY):null;if(n&&a.contains(this,n))return;a.mainClearTimeout(t.iDocTimer),t.runEvent("onDragLeave",[i,e])}}).on("drop",function(n){t.bEnableDnD&&n&&(n=a.getEvent(n))&&a.eventContainsFiles(n)&&(n.preventDefault(),a.getDataFromDragEvent(n,function(e){e&&(t.runEvent("onDrop",[e,n]),t.addNewFile(e),a.mainClearTimeout(t.iDocTimer))},a.getValue(t.oOptions,"multipleSizeLimit",e),t.getEvent("onLimitReached"))),t.runEvent("onDragLeave",[n])}))}(o):o.bEnableDnD=!1}on(e,t){return this.oEvents[e]=t,this}runEvent(e,t){this.oEvents[e]&&this.oEvents[e].apply(null,t||[])}getEvent(e){return this.oEvents[e]||null}cancel(e){this.oDriver.cancel(e)}setDragAndDropEnabledStatus(e){this.bEnableDnD=!!e}addNewFile(e){this.addFile(a.getNewUid(),e)}addFile(e,t){var n=this.getEvent("onSelect");!t||n&&!1===n(e,t)?this.oDriver.cancel(e):(this.oDriver.regTaskUid(e),this.oQueue.defer(a.scopeBind(this.oDriver.uploadTask,this.oDriver),e,t))}}r.prototype.bEnableDnD=!0,r.prototype.iDocTimer=0,r.prototype.oOptions={},r.prototype.oEvents={},r.prototype.oQueue=null,r.prototype.oDriver=null,window.Jua=r})();
+(()=>{"use strict";const e=document,t=20,n=e=>void 0!==e,o=(e,o,l,i)=>{if(e&&e.length){let a=l=n(l)?parseInt(l||0,10):t,s=null,u=0{e&&(!u||0<=--l?(s=r.getDataFromFile(e))&&o(s):u&&!p&&0>l&&i&&(p=!0,i(a)))})}},l=(e,t)=>{Object.entries(t).forEach(([t,n])=>e.addEventListener(t,n))},r={getValue:(e,t,o)=>e&&t&&n(e[t])?e[t]:o,getDataFromFile:e=>{let t=n(e.fileName)?e.fileName:n(e.name)?e.name:null,o=n(e.fileSize)?e.fileSize:n(e.size)?e.size:null,l=n(e.type)?e.type:null;return"/"===t.charAt(0)&&(t=t.substr(1)),l||0!==o?{FileName:t,Size:o,Type:l,Folder:"",File:e}:null},eventContainsFiles:e=>{if(e.dataTransfer&&e.dataTransfer.types&&e.dataTransfer.types.length){let t=e.dataTransfer.types.length;for(;t--;)if("files"===e.dataTransfer.types[t].toLowerCase())return!0}return!1}};class i{constructor(e,t){this.oXhrs={},this.oUids={},this.oJua=e,this.oOptions=t}regTaskUid(e){this.oUids[e]=!0}uploadTask(e,t,o){if(!1===this.oUids[e]||!t||!t.File)return o(null,e),!1;try{const l=this,i=new XMLHttpRequest,a=new FormData,s=r.getValue(this.oOptions,"action",""),u=r.getValue(this.oOptions,"hidden",{}),p=this.oJua.getEvent("onStart"),d=this.oJua.getEvent("onComplete"),c=this.oJua.getEvent("onProgress");return i.open("POST",s,!0),c&&i.upload&&(i.upload.onprogress=function(t){t&&t.lengthComputable&&n(t.loaded)&&n(t.total)&&c(e,t.loaded,t.total)}),i.onreadystatechange=function(){if(4===i.readyState&&200===i.status){if(d){let t=!1,n=null;try{n=JSON.parse(i.responseText),t=!0}catch(e){n=null}d(e,t,n)}n(l.oXhrs[e])&&(l.oXhrs[e]=null),o(null,e)}else 4===i.readyState&&(d(e,!1,null),o(null,e))},p&&p(e),a.append("jua-post-type","ajax"),a.append(r.getValue(this.oOptions,"name","juaFile"),t.File),Object.entries(u).forEach(([e,n])=>a.append(e,("function"==typeof n?n(t):n).toString())),i.send(a),this.oXhrs[e]=i,!0}catch(e){}return o(null,e),!1}generateNewInput(n){if(n){const l=this,i=e.createElement("label"),a=i.appendChild(e.createElement("input"));a.type="file",a.tabIndex=-1,a.style.cssText="position:absolute;left:-9999px;",a.multiple=!r.getValue(l.oOptions,"disableMultiple",!1),i.style.cssText="position:absolute;background-color:#fff;right:0;top:0;left:0;bottom:0;margin:0;padding:0;cursor:pointer;opacity:0",n.append(i),a.addEventListener("input",()=>{const e=e=>{l.oJua.addNewFile(e),l.generateNewInput(n),setTimeout(()=>i.remove(),10)};a.files&&a.files.length?o(a.files,e,r.getValue(l.oOptions,"multipleSizeLimit",t),l.oJua.getEvent("onLimitReached")):e({FileName:a.value.split("\\").pop().split("/").pop(),Size:null,Type:null,Folder:"",File:null})})}}cancel(e){if(this.oUids[e]=!1,this.oXhrs[e]){try{this.oXhrs[e].abort&&this.oXhrs[e].abort()}catch(e){}this.oXhrs[e]=null}}}function a(e){let t,n,o={},l=0,r=0,i=-1,a=null,s=[],u=()=>{};return arguments.length<1&&(e=1/0),o.defer=function(){if(!a){let e=arguments;e.index=++i,n?(n.next=e,n=n.next):t=n=e,++r,function o(){if(t&&lu.oOptions[e]=t),u.oQueue=a(parseInt(r.getValue(u.oOptions,"queueSize",10)||0,10)),u.oDriver=new i(u,u.oOptions);const p=r.getValue(u.oOptions,"clickElement",null);if(p&&(p.style.position="relative",p.style.overflow="hidden","inline"===p.style.display&&(p.style.display="inline-block"),this.oDriver.generateNewInput(p)),r.getValue(this.oOptions,"dragAndDropElement",!1)){let n=r.getValue(u.oOptions,"dragAndDropBodyElement",!1)||e,i=r.getValue(u.oOptions,"dragAndDropElement",!1);i&&(r.getValue(u.oOptions,"disableDocumentDropPrevent",!1)||e.addEventListener("dragover",e=>{if(r.eventContainsFiles(e))try{e.dataTransfer.dropEffect="none",e.preventDefault()}catch(e){}}),n&&l(n,{dragover:()=>u.docTimer.clear(),dragenter:e=>{r.eventContainsFiles(e)&&(u.docTimer.clear(),e.preventDefault(),u.runEvent("onBodyDragEnter",[e]))},dragleave:e=>e.dataTransfer&&u.docTimer.start(()=>u.runEvent("onBodyDragLeave",[e])),drop:e=>{if(e.dataTransfer){let t=r.eventContainsFiles(e);return t&&e.preventDefault(),u.runEvent("onBodyDragLeave",[e]),!t}return!1}}),l(i,{dragenter:e=>{r.eventContainsFiles(e)&&(u.docTimer.clear(),e.preventDefault(),u.runEvent("onDragEnter",[i,e]))},dragover:e=>{if(r.eventContainsFiles(e))try{let t=e.dataTransfer.effectAllowed;u.docTimer.clear(),e.dataTransfer.dropEffect="move"===t||"linkMove"===t?"move":"copy",e.stopPropagation(),e.preventDefault(),n&&n.dispatchEvent(e)}catch(e){}},dragleave:t=>{if(t.dataTransfer){let n=e.elementFromPoint(t.clientX,t.clientY);n&&i.contains(n)||(u.docTimer.clear(),u.runEvent("onDragLeave",[i,t]))}},drop:e=>{r.eventContainsFiles(e)&&(e.preventDefault(),o(r.getValue(e,"files",null)||r.getValue(e.dataTransfer,"files",null),e=>{e&&(u.addNewFile(e),u.docTimer.clear())},r.getValue(u.oOptions,"multipleSizeLimit",t),u.getEvent("onLimitReached"))),u.runEvent("onDragLeave",[e])}}))}}on(e,t){return this.oEvents[e]=t,this}runEvent(e,t){this.oEvents[e]&&this.oEvents[e].apply(null,t||[])}getEvent(e){return this.oEvents[e]||null}cancel(e){this.oDriver.cancel(e)}addNewFile(e){let t=16,n="";for(;t--;)n+="0123456789abcdefghijklmnopqrstuvwxyz".substr(Math.round(36*Math.random()),1);this.addFile("jua-uid-"+n+"-"+(new Date).getTime().toString(),e)}addFile(e,t){const n=this.getEvent("onSelect");!t||n&&!1===n(e,t)?this.oDriver.cancel(e):(this.oDriver.regTaskUid(e),this.oQueue.defer((...e)=>this.oDriver.uploadTask(...e),e,t))}}s.prototype.docTimer={start:function(e){this.clear(),this.timer=setTimeout(e,200)},clear:function(){this.timer&&clearTimeout(this.timer),this.timer=0}},s.prototype.oOptions={},s.prototype.oEvents={},s.prototype.oQueue=null,s.prototype.oDriver=null,window.Jua=s})();