diff --git a/README.md b/README.md index 590b21e06..35f44c5d8 100644 --- a/README.md +++ b/README.md @@ -75,23 +75,23 @@ Things might work in Edge 15-18, Firefox 47-62 and Chrome 54-68 due to one polyf |js/* |1.14.0 |native |gzip 1.14 |gzip | |----------- |--------: |--------: |--------: |--------: | -|admin.js |2.130.942 |1.133.275 | 485.481 | 274.632 | -|app.js |4.184.455 |2.844.189 | 932.725 | 664.075 | +|admin.js |2.130.942 |1.130.247 | 485.481 | 273.277 | +|app.js |4.184.455 |2.840.968 | 932.725 | 662.061 | |boot.js | 671.522 | 44.029 | 169.502 | 15.460 | -|libs.js | 647.614 | 431.049 | 194.728 | 132.315 | +|libs.js | 647.614 | 426.949 | 194.728 | 131.409 | |polyfills.js | 325.834 | 0 | 71.825 | 0 | -|TOTAL js |7.960.367 |4.452.542 |1.854.261 |1.086.482 | +|TOTAL js |7.960.367 |4.442.193 |1.854.261 |1.082.207 | |js/min/* |1.14.0 |native |gzip 1.14 |gzip | |--------------- |--------: |--------: |--------: |--------: | -|admin.min.js | 252.147 | 153.095 | 73.657 | 43.734 | -|app.min.js | 511.202 | 378.695 |140.462 | 99.511 | +|admin.min.js | 252.147 | 152.759 | 73.657 | 43.564 | +|app.min.js | 511.202 | 378.335 |140.462 | 99.341 | |boot.min.js | 66.007 | 5.589 | 22.567 | 2.333 | -|libs.min.js | 572.545 | 387.636 |176.720 |122.519 | +|libs.min.js | 572.545 | 385.139 |176.720 |121.907 | |polyfills.min.js | 32.452 | 0 | 11.312 | 0 | -|TOTAL js/min |1.434.353 | 925.015 |424.718 |268.097 | +|TOTAL js/min |1.434.353 | 921.822 |424.718 |267.145 | -509.338 bytes (156.621 gzip) is not much, but it feels faster. +512.531 bytes (157.573 gzip) is not much, but it feels faster. |css/* |1.14.0 |native | diff --git a/dev/Common/Utils.js b/dev/Common/Utils.js index 6eb91ccf5..f0f188cd9 100644 --- a/dev/Common/Utils.js +++ b/dev/Common/Utils.js @@ -7,19 +7,15 @@ import { Mime } from 'Common/Mime'; const $ = jQuery, $div = $('
'), - isArray = Array.isArray; - -var htmlspecialchars = ((de,se,gt,lt,sq,dq,bt) => { - return (str, quote_style = 3, double_encode = true) => { - str = (''+str) - .replace(double_encode?de:se,'&') - .replace(gt,'<') - .replace(lt,'>') - .replace(bt,'`'); - if (quote_style & 1) { str = str.replace(sq,'''); } - return (quote_style & 2) ? str.replace(dq,'"') : str; - }; -})(/&/g,/&(?![\w#]+;)/gi,//g,/'/g,/"/g,/`/g); + isArray = Array.isArray, + htmlmap = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''' + }, + htmlspecialchars = str => (''+str).replace(/[&<>"']/g, m => htmlmap[m]); /** * @param {*} value @@ -89,15 +85,13 @@ export function simpleQueryParser(queryString) { * @returns {string} */ export function fakeMd5(len = 32) { - const line = '0123456789abcdefghijklmnopqrstuvwxyz', - lineLen = line.length; + const line = '0123456789abcdefghijklmnopqrstuvwxyz'; len = pInt(len); let result = ''; - while (result.length < len) { - result += line.substr(Math.round(Math.random() * lineLen), 1); - } + while (len--) + result += line.substr(Math.round(Math.random() * 36), 1); return result; } diff --git a/dev/External/ko.js b/dev/External/ko.js index 1b4c90b94..b4609240d 100644 --- a/dev/External/ko.js +++ b/dev/External/ko.js @@ -747,35 +747,33 @@ ko.bindingHandlers.emailsTags = { $el = $(element), fValue = fValueAccessor(), fAllBindings = fAllBindingsAccessor(), - fAutoCompleteSource = fAllBindings.autoCompleteSource || null, - inputDelimiters = [',', ';', '\n'], - fFocusCallback = (value) => { - if (fValue && fValue.focused) { - fValue.focused(!!value); - } - }; + inputDelimiters = [',', ';', '\n']; $el.inputosaurus({ parseOnBlur: true, allowDragAndDrop: true, - focusCallback: fFocusCallback, + focusCallback: value => { + if (fValue && fValue.focused) { + fValue.focused(!!value); + } + }, inputDelimiters: inputDelimiters, - autoCompleteSource: fAutoCompleteSource, - splitHook: (value) => { + autoCompleteSource: fAllBindings.autoCompleteSource || null, + splitHook: value => { const v = value.trim(); if (v && inputDelimiters.includes(v.substr(-1))) { return EmailModel.splitEmailLine(value); } return null; }, - parseHook: (input) => + parseHook: input => input.map(inputValue => { const values = EmailModel.parseEmailLine(inputValue); return values.length ? values : inputValue; }).flat(Infinity).map( item => (item.toLine ? [item.toLine(false), item] : [item, null]) ), - change: (event) => { + change: event => { $el.data('EmailsTagsValue', event.target.value); fValue(event.target.value); } diff --git a/dev/Model/Email.js b/dev/Model/Email.js index 147b29cc1..ac1adb1b8 100644 --- a/dev/Model/Email.js +++ b/dev/Model/Email.js @@ -1,4 +1,4 @@ -import { encodeHtml, isNonEmptyArray } from 'Common/Utils'; +import { encodeHtml } from 'Common/Utils'; 'use strict'; @@ -64,12 +64,10 @@ function _handleAddress(tokens) { comment: [], group: [], text: [] - - // Filter out , (comments) and regular text }; - for (var i = 0, len = tokens.length; i < len; i++) { - var token = tokens[i]; + // Filter out , (comments) and regular text + tokens.forEach(token => { if (token.type === 'operator') { switch (token.value) { case '<': @@ -85,12 +83,10 @@ function _handleAddress(tokens) { default: state = 'text'; } - } else { - if (token.value) { - data[state].push(token.value); - } + } else if (token.value) { + data[state].push(token.value); } - } + }); // If there is no text but a comment, replace the two if (!data.text.length && data.comment.length) { @@ -108,25 +104,25 @@ function _handleAddress(tokens) { } else { // If no address was found, try to detect one from regular text if (!data.address.length && data.text.length) { - for (var _i = data.text.length - 1; _i >= 0; _i--) { - if (data.text[_i].match(/^[^@\s]+@[^@\s]+$/)) { - data.address = data.text.splice(_i, 1); + var i = data.text.length; + while (i--) { + if (data.text[i].match(/^[^@\s]+@[^@\s]+$/)) { + data.address = data.text.splice(i, 1); break; } } - var _regexHandler = function _regexHandler(address) { - if (!data.address.length) { - data.address = [address.trim()]; - return ' '; - } - return address; - }; - // still no address if (!data.address.length) { - for (var _i2 = data.text.length - 1; _i2 >= 0; _i2--) { - data.text[_i2] = data.text[_i2].replace(/\s*\b[^@\s]+@[^@\s]+\b\s*/, _regexHandler).trim(); + i = data.text.length; + while (i--) { + data.text[i] = data.text[i].replace(/\s*\b[^@\s]+@[^@\s]+\b\s*/, address => { + if (!data.address.length) { + data.address = [address.trim()]; + return ''; + } + return address.trim(); + }); if (data.address.length) { break; } @@ -202,8 +198,8 @@ class Tokenizer } tokenize() { - var list = [], i = this.str.length; - while (i--) this.checkChar(this.str[i]); + var list = []; + [...this.str].forEach(c => this.checkChar(c)); this.list.forEach(node => { node.value = (node.value || '').toString().trim(); @@ -420,7 +416,7 @@ class EmailModel { static splitEmailLine(line) { const parsedResult = addressparser(line); - if (isNonEmptyArray(parsedResult)) { + if (parsedResult.length) { const result = []; let exists = false; parsedResult.forEach((item) => { @@ -443,7 +439,7 @@ class EmailModel { static parseEmailLine(line) { const parsedResult = addressparser(line); - if (isNonEmptyArray(parsedResult)) { + if (parsedResult.length) { return parsedResult.map(item => item.address ? new EmailModel(item.address.replace(/^[<]+(.*)[>]+$/g, '$1'), item.name || '') : null ).filter(value => !!value); @@ -463,7 +459,7 @@ class EmailModel { } const result = addressparser(emailAddress); - if (isNonEmptyArray(result) && result[0]) { + if (result.length) { this.name = result[0].name || ''; this.email = result[0].address || ''; this.clearDuplicateName(); diff --git a/dev/View/Popup/Compose.js b/dev/View/Popup/Compose.js index 8942314ab..160dcbbc1 100644 --- a/dev/View/Popup/Compose.js +++ b/dev/View/Popup/Compose.js @@ -1401,7 +1401,7 @@ class ComposePopupView extends AbstractViewNext { } }); - this.addAttachmentEnabled(true).dragAndDropEnabled(oJua.isDragAndDropSupported()); + this.addAttachmentEnabled(true).dragAndDropEnabled(true); } else { this.addAttachmentEnabled(false).dragAndDropEnabled(false); } diff --git a/vendors/inputosaurus/inputosaurus.js b/vendors/inputosaurus/inputosaurus.js index 6686daa8b..ab5ba5ec2 100644 --- a/vendors/inputosaurus/inputosaurus.js +++ b/vendors/inputosaurus/inputosaurus.js @@ -18,7 +18,7 @@ */ -(function($) { +($ => { var inputosaurustext = { @@ -39,22 +39,12 @@ // the value tags are created on the fly when an inputDelimiter is detected inputDelimiters : [',', ';'], - // this separator is used to rejoin all input items back to the value of the original - outputDelimiter : ',', - - allowDuplicates : false, - allowDragAndDrop : true, focusCallback : null, parseOnBlur : false, - // optional wrapper for widget - wrapperElement : null, - - width : null, - // simply passing an autoComplete source (array, string or function) will instantiate autocomplete functionality autoCompleteSource : '', @@ -65,17 +55,14 @@ // the array of tag names is passed and expected to be returned as an array after manipulation parseHook : null, - elementHook : null, - - // define a placeholder to display when the input is empty - placeholder: null + splitHook : null }, _create: function() { var widget = this, els = {}, o = widget.options, - placeholder = o.placeholder || this.element.attr('placeholder') || null; + placeholder = this.element.attr('placeholder') || null; this._chosenValues = []; @@ -85,7 +72,7 @@ if (this.options.allowDragAndDrop) { els.ul.droppable({ - 'drop': function(event, ui) { + 'drop': (event, ui) => { ui.draggable.addClass('inputosaurus-dropped'); els.input.val(ui.draggable.data('inputosaurus-value')); @@ -106,9 +93,9 @@ els.origInputCont = $('
  • '); els.lastEdit = ''; - els.input.on('focus', function () { + els.input.on('focus', () => { widget._focusTrigger(true); - }).on('blur', function () { + }).on('blur', () => { widget._focusTrigger(false); }); @@ -116,21 +103,15 @@ if (placeholder) { o.placeholder = placeholder; els.input.attr('placeholder', o.placeholder); - if (o.width) { - els.input.css('min-width', o.width - 50); - } } - o.wrapperElement && o.wrapperElement.append(els.ul); - this.element.replaceWith(o.wrapperElement || els.ul); + this.element.replaceWith(els.ul); els.origInputCont.append(this.element).hide(); els.inputCont.append(els.input); els.ul.append(els.inputCont); els.ul.append(els.origInputCont); - o.width && els.ul.css('width', o.width); - this.elements = els; widget._attachEvents(); @@ -148,13 +129,10 @@ _focusTrigger : function (bValue) { var widget = this; - window.clearTimeout(this._focusTriggerTimer); - this._focusTriggerTimer = window.setTimeout(function () { + clearTimeout(this._focusTriggerTimer); + this._focusTriggerTimer = setTimeout(() => { widget.elements.ul[!bValue ? 'removeClass' : 'addClass']('inputosaurus-focused'); - if (widget.options.focusCallback) - { - widget.options.focusCallback(bValue); - } + widget.options.focusCallback(bValue); }, 10); }, @@ -169,7 +147,7 @@ source : this.options.autoCompleteSource, minLength : 1, autoFocus : true, - select : function(ev, ui){ + select : (ev, ui) => { ev.preventDefault(); widget.elements.input.val(ui.item.value); widget.parseInput(); @@ -190,9 +168,7 @@ } } }, - focus: function () { - return false; - } + focus: () => false }); } }, @@ -210,12 +186,6 @@ } }, - /*_closeAutoCompleteMenu : function() { - if(this.options.autoCompleteSource){ - this.elements.input.autocomplete('close'); - } - },*/ - parseInput : function(ev) { var widget = (ev && ev.data.widget) || this, val, @@ -226,11 +196,7 @@ val = widget.elements.input.val(); if (val) { - if ($.isFunction(widget.options.splitHook)) { - hook = widget.options.splitHook(val); - } else { - delimiterFound = widget._containsDelimiter(val); - } + hook = widget.options.splitHook(val); } if (hook) { @@ -246,15 +212,13 @@ values.push(val); } - $.isFunction(widget.options.parseHook) && (values = widget.options.parseHook(values)); + values = widget.options.parseHook(values); if(values.length){ widget._setChosen(values); widget.elements.input.val(''); widget._resizeInput(); } - - widget._resetPlaceholder(); }, _inputFocus : function(ev) { @@ -284,7 +248,7 @@ // reposition autoComplete menu as