Merge Objects prototype extensions

This commit is contained in:
djmaze 2020-09-04 17:07:35 +02:00
parent 0647b5201f
commit f2d194947d
26 changed files with 108 additions and 127 deletions

View file

@ -86,21 +86,21 @@ Things might work in Edge 18, Firefox 50-62 and Chrome 54-68 due to one polyfill
|js/* |1.14.0 |native |
|----------- |--------: |--------: |
|admin.js |2.130.942 | 939.722 |
|app.js |4.184.455 |2.559.620 |
|admin.js |2.130.942 | 938.738 |
|app.js |4.184.455 |2.556.224 |
|boot.js | 671.522 | 7.265 |
|libs.js | 647.614 | 312.269 |
|libs.js | 647.614 | 312.343 |
|polyfills.js | 325.834 | 0 |
|TOTAL |7.960.367 |3.818.876 |
|TOTAL |7.960.367 |3.814.570 |
|js/min/* |1.14.0 |native |gzip 1.14 |gzip |brotli |
|--------------- |--------: |--------: |--------: |--------: |--------: |
|admin.min.js | 252.147 | 128.874 | 73.657 | 37.574 | 32.236 |
|app.min.js | 511.202 | 349.777 |140.462 | 91.836 | 73.775 |
|admin.min.js | 252.147 | 128.761 | 73.657 | 37.546 | 32.178 |
|app.min.js | 511.202 | 349.280 |140.462 | 91.746 | 73.635 |
|boot.min.js | 66.007 | 4.258 | 22.567 | 1.946 | 1.648 |
|libs.min.js | 572.545 | 295.716 |176.720 | 91.532 | 80.863 |
|libs.min.js | 572.545 | 295.754 |176.720 | 91.521 | 80.871 |
|polyfills.min.js | 32.452 | 0 | 11.312 | 0 | 0 |
|TOTAL |1.434.353 | 778.625 |424.718 |222.888 |188.522 |
|TOTAL |1.434.353 | 778.053 |424.718 |222.759 |188.332 |
655.728 bytes (201.830 gzip) is not much, but it feels faster.

View file

@ -1,6 +1,5 @@
import {
isPosNumeric,
isNonEmptyArray,
pInt,
pString,
delegateRunOnDestroy,
@ -89,9 +88,9 @@ class AppUser extends AbstractApp {
// wakeUp
const interval = 3600000; // 60m
var lastTime = (new Date()).getTime();
var lastTime = Date.now();
setInterval(() => {
const currentTime = (new Date()).getTime();
const currentTime = Date.now();
if (currentTime > (lastTime + interval + 1000)) {
if (rl.hash.check()) {
this.reload();
@ -645,10 +644,10 @@ class AppUser extends AbstractApp {
*/
folderInformationMultiply(boot = false) {
const folders = FolderStore.getNextFolderNames();
if (isNonEmptyArray(folders)) {
if (Array.isNotEmpty(folders)) {
Remote.folderInformationMultiply((sResult, oData) => {
if (StorageResultType.Success === sResult) {
if (oData && oData.Result && oData.Result.List && isNonEmptyArray(oData.Result.List)) {
if (oData && oData.Result && oData.Result.List && Array.isNotEmpty(oData.Result.List)) {
const utc = Date.now() / 1000;
oData.Result.List.forEach(item => {
const hash = getFolderHash(item.Folder),
@ -685,7 +684,7 @@ class AppUser extends AbstractApp {
} else if (unreadCountChange) {
if (folder.fullNameRaw === FolderStore.currentFolderFullNameRaw()) {
const list = MessageStore.messageList();
if (isNonEmptyArray(list)) {
if (Array.isNotEmpty(list)) {
this.folderInformation(folder.fullNameRaw, list);
}
}

View file

@ -265,7 +265,7 @@ export function storeMessageFlagsToCache(message) {
* @param {Array} flags
*/
export function storeMessageFlagsToCacheByFolderAndUid(folder, uid, flags) {
if (Array.isArray(flags) && flags.length) {
if (Array.isNotEmpty(flags)) {
setMessageFlagsToCache(folder, uid, flags);
}
}
@ -279,7 +279,7 @@ export function storeMessageFlagsToCacheBySetAction(folder, uid, setAction) {
let unread = 0;
const flags = getMessageFlagsFromCache(folder, uid);
if (Array.isArray(flags) && flags.length) {
if (Array.isNotEmpty(flags)) {
if (flags[0]) {
unread = 1;
}

View file

@ -41,14 +41,6 @@ export function pString(value) {
return null != value ? '' + value : '';
}
/**
* @param {*} values
* @returns {boolean}
*/
export function isNonEmptyArray(values) {
return isArray(values) && values.length;
}
/**
* @param {string} queryString
* @returns {Object}

2
dev/External/ko.js vendored
View file

@ -485,7 +485,7 @@ ko.extenders.limitedList = (target, limitedList) => {
const currentValue = ko.unwrap(target),
list = ko.unwrap(limitedList);
if (Array.isArray(list) && list.length) {
if (Array.isNotEmpty(list)) {
if (list.includes(newValue)) {
target(newValue);
} else if (list.includes(currentValue, list)) {

View file

@ -1,4 +1,3 @@
import { isNonEmptyArray } from 'Common/Utils';
import { EmailModel } from 'Model/Email';
/**
@ -9,7 +8,7 @@ import { EmailModel } from 'Model/Email';
*/
export function emailArrayToString(emails, friendlyView = false, wrapWithLink = false) {
const result = [];
if (isNonEmptyArray(emails)) {
if (Array.isNotEmpty(emails)) {
emails.forEach(email => result.push(email.toLine(friendlyView, wrapWithLink)));
}
@ -22,7 +21,7 @@ export function emailArrayToString(emails, friendlyView = false, wrapWithLink =
*/
export function emailArrayToStringClear(emails) {
const result = [];
if (isNonEmptyArray(emails)) {
if (Array.isNotEmpty(emails)) {
emails.forEach(email => {
if (email && email.email && email.name) {
result.push(email.email);
@ -39,7 +38,7 @@ export function emailArrayToStringClear(emails) {
*/
export function emailArrayFromJson(json) {
const result = [];
if (isNonEmptyArray(json)) {
if (Array.isNotEmpty(json)) {
json.forEach(email => {
email = EmailModel.newInstanceFromJson(email);
if (email) {

View file

@ -44,7 +44,7 @@ export class AbstractScreen {
fMatcher = null;
const routes = this.routes();
if (Array.isArray(routes) && routes.length) {
if (Array.isNotEmpty(routes)) {
fMatcher = (this.onRoute || (()=>{})).bind(this);
route = new Crossroads();

View file

@ -12,7 +12,7 @@ let currentScreen = null,
const SCREENS = {},
qs = s => document.querySelector(s),
isNonEmptyArray = values => Array.isArray(values) && values.length,
isNonEmptyArray = Array.isNotEmpty,
autofocus = dom => {
// if (!bMobileDevice) {
const af = dom.querySelector('[autofocus]');

View file

@ -2,7 +2,7 @@ import ko from 'ko';
import { FileType } from 'Common/Enums';
import { bMobileDevice } from 'Common/Globals';
import { pInt, isNonEmptyArray, getFileExtension, friendlySize } from 'Common/Utils';
import { pInt, getFileExtension, friendlySize } from 'Common/Utils';
import {
attachmentDownload,
attachmentPreview,
@ -149,7 +149,7 @@ export const staticCombinedIconClass = (data) => {
let result = '',
types = [];
if (isNonEmptyArray(data)) {
if (Array.isNotEmpty(data)) {
result = 'icon-attachment';
types = data.map(item => item ? staticFileType(getFileExtension(item[0]), item[1]) : '')
.filter((value, index, self) => !!value && self.indexOf(value) == index);

View file

@ -1,7 +1,7 @@
import ko from 'ko';
import { ContactPropertyType } from 'Common/Enums';
import { isNonEmptyArray, pInt, pString } from 'Common/Utils';
import { pInt, pString } from 'Common/Utils';
import { emptyContactPic } from 'Common/Links';
import { AbstractModel } from 'Knoin/AbstractModel';
@ -28,7 +28,7 @@ class ContactModel extends AbstractModel {
let name = '',
email = '';
if (isNonEmptyArray(this.properties)) {
if (Array.isNotEmpty(this.properties)) {
this.properties.forEach(property => {
if (property) {
if (ContactPropertyType.FirstName === property[0]) {
@ -56,7 +56,7 @@ class ContactModel extends AbstractModel {
this.display = pString(json.Display);
this.readOnly = !!json.ReadOnly;
if (isNonEmptyArray(json.Properties)) {
if (Array.isNotEmpty(json.Properties)) {
json.Properties.forEach(property => {
if (property && property.Type && null != property.Value && null != property.TypeStr) {
this.properties.push([pInt(property.Type), pString(property.Value), pString(property.TypeStr)]);

View file

@ -1,7 +1,7 @@
import ko from 'ko';
import { FilterRulesType, FiltersAction } from 'Common/Enums';
import { pString, isNonEmptyArray, fakeMd5, delegateRunOnDestroy } from 'Common/Utils';
import { pString, fakeMd5, delegateRunOnDestroy } from 'Common/Utils';
import { i18n } from 'Common/Translator';
import { getFolderFromCacheList } from 'Common/Cache';
@ -225,7 +225,7 @@ class FilterModel extends AbstractModel {
this.conditions([]);
if (isNonEmptyArray(json.Conditions)) {
if (Array.isNotEmpty(json.Conditions)) {
this.conditions(
json.Conditions.map(aData => {
const filterCondition = new FilterConditionModel();

View file

@ -7,8 +7,7 @@ import {
pInt,
deModule,
encodeHtml,
friendlySize,
isNonEmptyArray
friendlySize
} from 'Common/Utils';
import { messageViewLink, messageDownloadLink } from 'Common/Links';
@ -257,7 +256,7 @@ class MessageModel extends AbstractModel {
this.bcc = emailArrayFromJson(json.Bcc);
this.replyTo = emailArrayFromJson(json.ReplyTo);
this.deliveredTo = emailArrayFromJson(json.DeliveredTo);
this.unsubsribeLinks = isNonEmptyArray(json.UnsubsribeLinks) ? json.UnsubsribeLinks : [];
this.unsubsribeLinks = Array.isNotEmpty(json.UnsubsribeLinks) ? json.UnsubsribeLinks : [];
this.subject(json.Subject);
if (isArray(json.SubjectParts)) {
@ -341,7 +340,7 @@ class MessageModel extends AbstractModel {
attachment = null;
const result = [];
if (json && 'Collection/AttachmentCollection' === json['@Object'] && isNonEmptyArray(json['@Collection'])) {
if (json && 'Collection/AttachmentCollection' === json['@Object'] && Array.isNotEmpty(json['@Collection'])) {
for (index = 0, len = json['@Collection'].length; index < len; index++) {
attachment = AttachmentModel.newInstanceFromJson(json['@Collection'][index]);
if (attachment) {
@ -408,7 +407,7 @@ class MessageModel extends AbstractModel {
*/
fromDkimData() {
let result = ['none', ''];
if (isNonEmptyArray(this.from) && 1 === this.from.length && this.from[0] && this.from[0].dkimStatus) {
if (Array.isNotEmpty(this.from) && 1 === this.from.length && this.from[0] && this.from[0].dkimStatus) {
result = [this.from[0].dkimStatus, this.from[0].dkimValue || ''];
}
@ -492,7 +491,7 @@ class MessageModel extends AbstractModel {
let result = null;
const attachments = this.attachments();
if (isNonEmptyArray(attachments)) {
if (Array.isNotEmpty(attachments)) {
cid = cid.replace(/^<+/, '').replace(/>+$/, '');
result = attachments.find(item => cid === item.cidWithOutTags);
}
@ -508,7 +507,7 @@ class MessageModel extends AbstractModel {
let result = null;
const attachments = this.attachments();
if (isNonEmptyArray(attachments)) {
if (Array.isNotEmpty(attachments)) {
result = attachments.find(item => contentLocation === item.contentLocation);
}

View file

@ -1,7 +1,5 @@
import ko from 'ko';
import { isNonEmptyArray } from 'Common/Utils';
import { AbstractModel } from 'Knoin/AbstractModel';
import PgpStore from 'Stores/User/Pgp';
@ -23,7 +21,7 @@ class OpenPgpKeyModel extends AbstractModel {
this.index = index;
this.id = ID;
this.ids = isNonEmptyArray(IDs) ? IDs : [ID];
this.ids = Array.isNotEmpty(IDs) ? IDs : [ID];
this.guid = guID;
this.user = '';
this.users = userIDs;

View file

@ -445,7 +445,7 @@ class RemoteUserAjax extends AbstractAjaxRemote {
let request = true;
const uids = [];
if (Array.isArray(list) && list.length) {
if (Array.isNotEmpty(list)) {
request = false;
list.forEach(messageListItem => {
if (!getMessageFlagsFromCache(messageListItem.folderFullNameRaw, messageListItem.uid)) {

View file

@ -2,7 +2,6 @@ import ko from 'ko';
import { Focused, KeyState } from 'Common/Enums';
import { keyScope, leftPanelDisabled } from 'Common/Globals';
import { isNonEmptyArray } from 'Common/Utils';
import { AbstractAppStore } from 'Stores/AbstractApp';
@ -70,7 +69,7 @@ class AppUserStore extends AbstractAppStore {
this.contactsIsAllowed(!!Settings.get('ContactsIsAllowed'));
const attachmentsActions = Settings.app('attachmentsActions');
this.attachmentsActions(isNonEmptyArray(attachmentsActions) ? attachmentsActions : []);
this.attachmentsActions(Array.isNotEmpty(attachmentsActions) ? attachmentsActions : []);
this.devEmail = Settings.get('DevEmail');
this.devPassword = Settings.get('DevPassword');

View file

@ -68,7 +68,7 @@ class FolderUserStore {
trashFolder = this.trashFolder(),
archiveFolder = this.archiveFolder();
if (Array.isArray(folders) && folders.length) {
if (Array.isNotEmpty(folders)) {
if (sentFolder && UNUSED_OPTION_VALUE !== sentFolder) {
list.push(sentFolder);
}

View file

@ -240,7 +240,7 @@ class MessageUserStore {
initUidNextAndNewMessages(folder, uidNext, newMessages) {
if (getFolderInboxName() === folder && uidNext) {
if (Array.isArray(newMessages) && newMessages.length) {
if (Array.isNotEmpty(newMessages)) {
newMessages.forEach(item => {
addNewMessageCache(folder, item.Uid);
});

View file

@ -1,7 +1,7 @@
import ko from 'ko';
import { i18n } from 'Common/Translator';
import { isNonEmptyArray, pString } from 'Common/Utils';
import { pString } from 'Common/Utils';
import AccountStore from 'Stores/User/Account';
@ -51,7 +51,7 @@ function domControlEncryptedClickHelper(store, dom, armoredMessage, recipients)
decryptedMessage.getText()
);
} else if (validPrivateKey) {
const keyIds = isNonEmptyArray(signingKeyIds) ? signingKeyIds : null,
const keyIds = Array.isNotEmpty(signingKeyIds) ? signingKeyIds : null,
additional = keyIds
? keyIds.map(item => (item && item.toHex ? item.toHex() : null)).filter(value => !!value).join(', ')
: '';
@ -107,7 +107,7 @@ function domControlSignedClickHelper(store, dom, armoredMessage) {
message.getText()
);
} else {
const keyIds = isNonEmptyArray(signingKeyIds) ? signingKeyIds : null,
const keyIds = Array.isNotEmpty(signingKeyIds) ? signingKeyIds : null,
additional = keyIds
? keyIds.map(item => (item && item.toHex ? item.toHex() : null)).filter(value => !!value).join(', ')
: '';
@ -183,7 +183,7 @@ class PgpUserStore {
}).flat().filter(value => !!value)
: [];
if (!result.length && isNonEmptyArray(recipients)) {
if (!result.length && Array.isNotEmpty(recipients)) {
result = recipients.map(sEmail => {
const keys = sEmail ? this.findAllPrivateKeysByEmailNotNative(sEmail) : null;
return keys

View file

@ -12,7 +12,6 @@ import {
} from 'Common/Enums';
import {
isNonEmptyArray,
replySubjectAdd,
encodeHtml,
inFocus,
@ -263,7 +262,7 @@ class ComposePopupView extends AbstractViewNext {
});
this.attachmentsInProcess.subscribe(value => {
if (this.attachmentsInProcessError() && isNonEmptyArray(value)) {
if (this.attachmentsInProcessError() && Array.isNotEmpty(value)) {
this.attachmentsInProcessError(false);
}
});
@ -772,7 +771,7 @@ class ComposePopupView extends AbstractViewNext {
* @param {Array} emails
*/
addEmailsTo(fKoValue, emails) {
if (isNonEmptyArray(emails)) {
if (Array.isNotEmpty(emails)) {
const value = fKoValue().trim(),
values = emails.map(item => item ? item.toLine(false) : null)
.filter((value, index, self) => !!value && self.indexOf(value) == index);
@ -842,15 +841,15 @@ class ComposePopupView extends AbstractViewNext {
excludeEmail[identity.email()] = true;
}
if (isNonEmptyArray(aToEmails)) {
if (Array.isNotEmpty(aToEmails)) {
this.to(this.emailArrayToStringLineHelper(aToEmails));
}
if (isNonEmptyArray(aCcEmails)) {
if (Array.isNotEmpty(aCcEmails)) {
this.cc(this.emailArrayToStringLineHelper(aCcEmails));
}
if (isNonEmptyArray(aBccEmails)) {
if (Array.isNotEmpty(aBccEmails)) {
this.bcc(this.emailArrayToStringLineHelper(aBccEmails));
}
@ -915,7 +914,7 @@ class ComposePopupView extends AbstractViewNext {
this.subject(sSubject);
this.prepearMessageAttachments(message, lineComposeType);
this.aDraftInfo = isNonEmptyArray(aDraftInfo) && 3 === aDraftInfo.length ? aDraftInfo : null;
this.aDraftInfo = Array.isNotEmpty(aDraftInfo) && 3 === aDraftInfo.length ? aDraftInfo : null;
this.sInReplyTo = message.sInReplyTo;
this.sReferences = message.sReferences;
break;
@ -929,7 +928,7 @@ class ComposePopupView extends AbstractViewNext {
this.subject(sSubject);
this.prepearMessageAttachments(message, lineComposeType);
this.aDraftInfo = isNonEmptyArray(aDraftInfo) && 3 === aDraftInfo.length ? aDraftInfo : null;
this.aDraftInfo = Array.isNotEmpty(aDraftInfo) && 3 === aDraftInfo.length ? aDraftInfo : null;
this.sInReplyTo = message.sInReplyTo;
this.sReferences = message.sReferences;
break;
@ -1021,7 +1020,7 @@ class ComposePopupView extends AbstractViewNext {
this.setFocusInPopup();
});
} else if (isNonEmptyArray(oMessageOrArray)) {
} else if (Array.isNotEmpty(oMessageOrArray)) {
oMessageOrArray.forEach(item => {
this.addMessageAsAttachment(item);
});
@ -1047,7 +1046,7 @@ class ComposePopupView extends AbstractViewNext {
}
const downloads = this.getAttachmentsDownloadsForUpload();
if (isNonEmptyArray(downloads)) {
if (Array.isNotEmpty(downloads)) {
Remote.messageUploadAttachments(()=>this.onMessageUploadAttachments(), downloads);
}
@ -1375,7 +1374,7 @@ class ComposePopupView extends AbstractViewNext {
this.addMessageAsAttachment(message);
} else {
const attachments = message.attachments();
(isNonEmptyArray(attachments) ? attachments : []).forEach(item => {
(Array.isNotEmpty(attachments) ? attachments : []).forEach(item => {
let add = false;
switch (type) {
case ComposeType.Reply:

View file

@ -13,7 +13,6 @@ import {
import {
delegateRunOnDestroy,
computedPagenatorHelper,
isNonEmptyArray,
fakeMd5,
pInt
} from 'Common/Utils';
@ -229,7 +228,7 @@ class ContactsPopupView extends AbstractViewNext {
bccEmails = null;
const aC = this.contactsCheckedOrSelected();
if (isNonEmptyArray(aC)) {
if (Array.isNotEmpty(aC)) {
aE = aC.map(oItem => {
if (oItem) {
const data = oItem.getNameAndEmailHelper(),
@ -246,7 +245,7 @@ class ContactsPopupView extends AbstractViewNext {
aE = aE.filter(value => !!value);
}
if (isNonEmptyArray(aE)) {
if (Array.isNotEmpty(aE)) {
this.bBackToCompose = false;
hideScreenPopup(ContactsPopupView);
@ -511,7 +510,7 @@ class ContactsPopupView extends AbstractViewNext {
if (contact) {
id = contact.idContact;
if (isNonEmptyArray(contact.properties)) {
if (Array.isNotEmpty(contact.properties)) {
contact.properties.forEach(property => {
if (property && property[0]) {
if (ContactPropertyType.LastName === property[0]) {
@ -579,7 +578,7 @@ class ContactsPopupView extends AbstractViewNext {
list = [];
if (StorageResultType.Success === result && data && data.Result && data.Result.List) {
if (isNonEmptyArray(data.Result.List)) {
if (Array.isNotEmpty(data.Result.List)) {
list = data.Result.List.map(item => {
const contact = new ContactModel();
return contact.parse(item) ? contact : null;

View file

@ -83,7 +83,7 @@ class PluginPopupView extends AbstractViewNext {
this.readme(oPlugin.Readme);
const config = oPlugin.Config;
if (Array.isArray(config) && config.length) {
if (Array.isNotEmpty(config)) {
this.configures(
config.map(item => ({
'value': ko.observable(item[0]),

View file

@ -16,7 +16,6 @@ import {
import { $htmlCL, leftPanelDisabled, keyScopeReal, useKeyboardShortcuts, moveAction } from 'Common/Globals';
import {
isNonEmptyArray,
inFocus,
removeSelection,
removeInFocus,
@ -213,7 +212,7 @@ class MessageViewMailBoxUserView extends AbstractViewNext {
this.viewFromDkimStatusTitle = ko.computed(() => {
const status = this.viewFromDkimData();
if (isNonEmptyArray(status)) {
if (Array.isNotEmpty(status)) {
if (status[0] && status[1]) {
return status[1];
} else if (status[0]) {

View file

@ -1,13 +0,0 @@
(()=>{
Element.prototype.closestWithin = function(selector, parent) {
const el = this.closest(selector);
return (el && el !== parent && parent.contains(el)) ? el : null;
};
Element.fromHTML = string => {
const template = document.createElement('template');
template.innerHTML = string.trim();
return template.content.firstChild;
};
})();

View file

@ -1,34 +0,0 @@
/**
* Every time the function is executed,
* it will delay the execution with the given amount of milliseconds.
*/
if (!Function.prototype.debounce) {
Function.prototype.debounce = function(ms) {
let func = this, timer;
return function(...args) {
timer && clearTimeout(timer);
timer = setTimeout(()=>{
func.apply(this, args)
timer = 0;
}, ms);
};
};
}
/**
* No matter how many times the event is executed,
* the function will be executed only once, after the given amount of milliseconds.
*/
if (!Function.prototype.throttle) {
Function.prototype.throttle = function(ms) {
let func = this, timer;
return function(...args) {
if (!timer) {
timer = setTimeout(()=>{
func.apply(this, args)
timer = 0;
}, ms);
}
};
};
}

View file

@ -1,5 +1,6 @@
(w=>{
Array.isNotEmpty = array => Array.isArray(array) && array.length;
// Import momentjs locales function
w.moment = {
@ -167,7 +168,7 @@
// Simulate momentjs fromNow function
Date.prototype.fromNow = function() {
let format,
seconds = ((new Date()).getTime() - this.getTime()) / 1000,
seconds = (Date.now() - this.getTime()) / 1000,
str = locale.relativeTime[0 < seconds ? 'past' : 'future'];
seconds = Math.abs(seconds);
if (60 > seconds) {
@ -195,4 +196,50 @@
return str.replace('%s', locale.relativeTime[format].replace('%d', seconds));
}
Element.prototype.closestWithin = function(selector, parent) {
const el = this.closest(selector);
return (el && el !== parent && parent.contains(el)) ? el : null;
};
Element.fromHTML = string => {
const template = document.createElement('template');
template.innerHTML = string.trim();
return template.content.firstChild;
};
/**
* Every time the function is executed,
* it will delay the execution with the given amount of milliseconds.
*/
if (!Function.prototype.debounce) {
Function.prototype.debounce = function(ms) {
let func = this, timer;
return function(...args) {
timer && clearTimeout(timer);
timer = setTimeout(()=>{
func.apply(this, args)
timer = 0;
}, ms);
};
};
}
/**
* No matter how many times the event is executed,
* the function will be executed only once, after the given amount of milliseconds.
*/
if (!Function.prototype.throttle) {
Function.prototype.throttle = function(ms) {
let func = this, timer;
return function(...args) {
if (!timer) {
timer = setTimeout(()=>{
func.apply(this, args)
timer = 0;
}, ms);
}
};
};
}
})(this);

View file

@ -70,6 +70,7 @@ config.paths.js = {
name: 'libs.js',
src: [
'dev/polyfill.js',
'dev/prototype.js',
'node_modules/jquery/dist/jquery.slim.min.js',
'vendors/jquery-ui/js/jquery-ui-1.12.1.custom.min.js', // custom
'vendors/inputosaurus/inputosaurus.js', // custom (modified)
@ -80,9 +81,6 @@ config.paths.js = {
'vendors/keymaster/keymaster.js', // custom (modified)
'vendors/qr.js/qr.min.js', // fixed (license)
'vendors/bootstrap/js/bootstrap.native.min.js', // fixed
'dev/prototype-date.js',
'dev/prototype-element.js',
'dev/prototype-function.js',
'node_modules/knockout/build/output/knockout-latest.js',
'node_modules/knockout-sortable/build/knockout-sortable.min.js ',
'node_modules/simplestatemanager/dist/ssm.min.js',