2016-08-11 22:05:23 +08:00
|
|
|
/*
|
|
|
|
* Form validators. They'll find, render and focus error/s and
|
|
|
|
* prevent form submission.
|
|
|
|
*/
|
2016-07-23 00:02:57 +08:00
|
|
|
|
2016-08-11 22:05:23 +08:00
|
|
|
/*
|
|
|
|
* Calls specified validator along with the arguments on form submition.
|
|
|
|
*/
|
2016-08-09 20:39:24 +08:00
|
|
|
$.fn.onSubmitValidator = function(validatorCb) {
|
|
|
|
var params = Array.prototype.slice.call(arguments, 1);
|
|
|
|
var $form = $(this);
|
|
|
|
if ($form.length) {
|
|
|
|
$form.submit(function (ev) {
|
2016-08-11 22:05:23 +08:00
|
|
|
$form.clearFormErrors();
|
2016-08-09 20:39:24 +08:00
|
|
|
params.unshift(ev);
|
|
|
|
validatorCb.apply(this, params);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2016-09-21 21:54:12 +08:00
|
|
|
/*
|
|
|
|
* @param {boolean} clearErr Set clearErr to true if this is the only
|
|
|
|
* error that can happen/show.
|
|
|
|
*/
|
2017-09-07 20:54:12 +08:00
|
|
|
function textValidator(ev, textInput, textLimitMin, textLimitMax, clearErr, tinyMCEInput) {
|
2016-09-21 21:54:12 +08:00
|
|
|
clearErr = _.isUndefined(clearErr) ? false : clearErr;
|
|
|
|
|
2017-09-07 20:54:12 +08:00
|
|
|
if(tinyMCEInput){
|
|
|
|
var text = tinyMCEInput;
|
2017-01-19 18:37:59 +08:00
|
|
|
} else {
|
|
|
|
var text = $(textInput).val().trim();
|
|
|
|
$(textInput).val(text);
|
|
|
|
var text_from_html = $("<div/>").html(text).text();
|
|
|
|
if (text_from_html.length < text.length) text = text_from_html;
|
|
|
|
}
|
2016-11-11 18:42:16 +08:00
|
|
|
|
2016-10-06 22:39:54 +08:00
|
|
|
var nameTooShort = text.length < textLimitMin;
|
|
|
|
var nameTooLong = text.length > textLimitMax;
|
2016-09-16 17:39:37 +08:00
|
|
|
|
2016-07-22 19:29:01 +08:00
|
|
|
var errMsg;
|
2016-09-16 17:39:37 +08:00
|
|
|
if (nameTooShort) {
|
2016-10-06 22:39:54 +08:00
|
|
|
if (textLimitMin === 1) {
|
2016-09-16 17:39:37 +08:00
|
|
|
errMsg = I18n.t("general.text.not_blank");
|
|
|
|
} else {
|
2016-10-06 22:39:54 +08:00
|
|
|
errMsg = I18n.t("general.text.length_too_short", { min_length: textLimitMin });
|
2016-09-16 17:39:37 +08:00
|
|
|
}
|
|
|
|
} else if (nameTooLong) {
|
2018-10-18 20:22:15 +08:00
|
|
|
if(tinyMCEInput){
|
|
|
|
errMsg = I18n.t("general.text.length_too_long_general");
|
|
|
|
} else {
|
|
|
|
errMsg = I18n.t("general.text.length_too_long", { max_length: textLimitMax });
|
|
|
|
}
|
2016-07-22 19:29:01 +08:00
|
|
|
}
|
|
|
|
|
2016-09-07 05:05:42 +08:00
|
|
|
var noErrors = _.isUndefined(errMsg);
|
|
|
|
if (!noErrors) {
|
2016-09-21 21:54:12 +08:00
|
|
|
renderFormError(ev, textInput, errMsg, clearErr);
|
2016-07-22 19:29:01 +08:00
|
|
|
}
|
2016-09-07 05:05:42 +08:00
|
|
|
return noErrors;
|
2016-07-22 19:29:01 +08:00
|
|
|
}
|
|
|
|
|
2016-07-23 00:02:57 +08:00
|
|
|
function checklistsValidator(ev, checklists, editMode) {
|
2016-07-22 19:29:01 +08:00
|
|
|
var noErrors = true;
|
|
|
|
// For every visible (i.e. not removed) checklist
|
2016-09-07 05:05:42 +08:00
|
|
|
$(checklists).each(function() {
|
|
|
|
var $checklist = $(this);
|
2016-07-22 19:29:01 +08:00
|
|
|
if ($checklist.css('display') != 'none') {
|
|
|
|
|
2016-09-07 05:05:42 +08:00
|
|
|
// For every visible (i.e. not removed) ckecklist item
|
|
|
|
anyChecklistItemFilled = false;
|
2016-07-22 19:29:01 +08:00
|
|
|
$(" .checklist-item-text", $checklist).each(function() {
|
2016-09-07 05:05:42 +08:00
|
|
|
var $itemInput = $(this);
|
|
|
|
var $item = $itemInput.closest("fieldset");
|
|
|
|
if ($item.css('display') != 'none') {
|
|
|
|
|
|
|
|
if ($itemInput.val()) {
|
2016-10-06 22:39:54 +08:00
|
|
|
var itemNameValid = textValidator(ev, $itemInput, 1,
|
2016-10-11 21:13:05 +08:00
|
|
|
<%= Constants::TEXT_MAX_LENGTH %>);
|
2016-09-07 05:05:42 +08:00
|
|
|
if (!itemNameValid) {
|
|
|
|
noErrors = false;
|
|
|
|
}
|
|
|
|
anyChecklistItemFilled = true;
|
|
|
|
} else {
|
|
|
|
// Remove empty checklist item input
|
|
|
|
$item.remove();
|
|
|
|
}
|
2016-07-22 19:29:01 +08:00
|
|
|
}
|
|
|
|
})
|
|
|
|
|
2020-11-03 05:19:33 +08:00
|
|
|
var $checklistInput = $checklist.find(".checklist-name");
|
2016-09-07 05:05:42 +08:00
|
|
|
// In edit mode, checklist's name can't be blank if any items present
|
|
|
|
var allowBlankChklstName = !(anyChecklistItemFilled || editMode);
|
2016-10-06 22:39:54 +08:00
|
|
|
var textLimitMin = allowBlankChklstName ? 0 : 1;
|
2016-09-16 17:39:37 +08:00
|
|
|
var checklistNameValid = textValidator(ev, $checklistInput,
|
2016-10-11 21:13:05 +08:00
|
|
|
textLimitMin, <%= Constants::TEXT_MAX_LENGTH %>);
|
2016-09-07 05:05:42 +08:00
|
|
|
if (!checklistNameValid) {
|
|
|
|
noErrors = false;
|
|
|
|
} else if (allowBlankChklstName) {
|
|
|
|
// Hide empty checklist (remove would break server-side logic)
|
|
|
|
$checklist.hide();
|
2016-07-22 19:29:01 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
return noErrors;
|
|
|
|
}
|
|
|
|
|
2016-10-06 22:39:54 +08:00
|
|
|
var FileTypeEnum = Object.freeze({
|
2019-08-06 21:06:19 +08:00
|
|
|
FILE: GLOBAL_CONSTANTS.FILE_MAX_SIZE_MB * 1024 * 1024,
|
2016-10-11 21:13:05 +08:00
|
|
|
AVATAR: <%= Constants::AVATAR_MAX_SIZE_MB.megabytes %>
|
2016-08-09 20:39:24 +08:00
|
|
|
});
|
2016-07-22 19:29:01 +08:00
|
|
|
|
2016-09-07 05:05:42 +08:00
|
|
|
function filesValidator(ev, fileInputs, fileTypeEnum, canBeEmpty) {
|
|
|
|
canBeEmpty = (typeof canBeEmpty !== 'undefined') ? canBeEmpty : false;
|
2016-08-05 23:00:29 +08:00
|
|
|
var filesValid = true;
|
2016-07-22 19:29:01 +08:00
|
|
|
if (fileInputs.length) {
|
2016-09-07 05:05:42 +08:00
|
|
|
var filesPresentValid = canBeEmpty || filesPresentValidator(ev, fileInputs);
|
2018-07-23 18:16:52 +08:00
|
|
|
var filesSizeValid = false;
|
|
|
|
if (filesPresentValid) {
|
|
|
|
filesSizeValid = filesSizeValidator(ev, fileInputs, fileTypeEnum);
|
|
|
|
}
|
2016-08-26 04:26:53 +08:00
|
|
|
// File spoof check is done on server-side only
|
2016-08-05 23:00:29 +08:00
|
|
|
filesValid = filesPresentValid && filesSizeValid;
|
|
|
|
}
|
|
|
|
return filesValid;
|
|
|
|
}
|
2016-07-22 19:29:01 +08:00
|
|
|
|
2016-08-05 23:00:29 +08:00
|
|
|
function filesPresentValidator(ev, fileInputs) {
|
|
|
|
var filesPresentValid = true;
|
|
|
|
_.each(fileInputs, function(fileInput) {
|
|
|
|
if (!fileInput.files[0]) {
|
|
|
|
assetError = I18n.t("general.file.blank");
|
2016-09-08 18:43:31 +08:00
|
|
|
renderFormError(ev, fileInput, assetError, false, "data-error='file-missing'");
|
2016-08-05 23:00:29 +08:00
|
|
|
filesPresentValid = false;
|
2016-07-22 19:29:01 +08:00
|
|
|
}
|
2016-08-05 23:00:29 +08:00
|
|
|
});
|
|
|
|
return filesPresentValid;
|
2016-07-22 19:29:01 +08:00
|
|
|
}
|
|
|
|
|
2016-08-05 23:00:29 +08:00
|
|
|
function filesSizeValidator(ev, fileInputs, fileTypeEnum) {
|
2016-07-22 19:29:01 +08:00
|
|
|
|
|
|
|
function getFileTooBigError(file) {
|
|
|
|
if (!file) {
|
|
|
|
return ;
|
|
|
|
}
|
2016-09-16 17:39:37 +08:00
|
|
|
if (file.size > fileTypeEnum) {
|
|
|
|
switch (fileTypeEnum) {
|
2016-10-06 22:39:54 +08:00
|
|
|
case FileTypeEnum.FILE:
|
2019-08-06 21:06:19 +08:00
|
|
|
return I18n.t('general.file.size_exceeded', { file_size: GLOBAL_CONSTANTS.FILE_MAX_SIZE_MB }).strToErrorFormat();
|
2016-10-06 22:39:54 +08:00
|
|
|
case FileTypeEnum.AVATAR:
|
2016-10-05 23:45:20 +08:00
|
|
|
return "<%= I18n.t 'general.file.size_exceeded', file_size: Constants::AVATAR_MAX_SIZE_MB %>".strToErrorFormat();
|
2016-09-16 17:39:37 +08:00
|
|
|
}
|
2016-07-22 19:29:01 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2016-12-07 16:02:04 +08:00
|
|
|
function checkFilesTotalSize(fileInputs) {
|
|
|
|
if (!fileInputs || fileInputs < 2) {
|
|
|
|
return ;
|
|
|
|
}
|
|
|
|
|
|
|
|
var size = 0;
|
|
|
|
_.each(fileInputs, function(fileInput) {
|
|
|
|
var file = fileInput.files[0]
|
|
|
|
size += file.size;
|
|
|
|
})
|
|
|
|
|
|
|
|
if (size > fileTypeEnum) {
|
2017-04-25 16:02:00 +08:00
|
|
|
switch (fileTypeEnum) {
|
|
|
|
case FileTypeEnum.FILE:
|
2019-08-06 21:06:19 +08:00
|
|
|
return I18n.t('general.file.total_size', { size: GLOBAL_CONSTANTS.FILE_MAX_SIZE_MB }).strToErrorFormat();
|
2017-04-25 16:02:00 +08:00
|
|
|
case FileTypeEnum.AVATAR:
|
2017-11-15 21:21:04 +08:00
|
|
|
return "<%= I18n.t('users.registrations.edit.avatar_total_size', size: Constants::AVATAR_MAX_SIZE_MB) %>".strToErrorFormat();
|
2017-04-25 16:02:00 +08:00
|
|
|
}
|
2016-12-07 16:02:04 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-22 19:29:01 +08:00
|
|
|
// Check if any file exceeds allowed size limit
|
2016-08-05 23:00:29 +08:00
|
|
|
var filesSizeValid = true;
|
2016-12-12 23:21:38 +08:00
|
|
|
|
|
|
|
// Check total size of uploaded files
|
|
|
|
var totalSizeOK = checkFilesTotalSize(fileInputs);
|
|
|
|
|
2016-07-22 19:29:01 +08:00
|
|
|
_.each(fileInputs, function(fileInput) {
|
|
|
|
var file = fileInput.files[0];
|
|
|
|
var assetError = getFileTooBigError(file);
|
2016-12-12 23:21:38 +08:00
|
|
|
var assetError = totalSizeOK;
|
2016-07-22 19:29:01 +08:00
|
|
|
if (assetError) {
|
2016-09-08 18:43:31 +08:00
|
|
|
renderFormError(ev, fileInput, assetError, false, "data-error='file-size'");
|
2016-08-05 23:00:29 +08:00
|
|
|
filesSizeValid = false;
|
2016-07-22 19:29:01 +08:00
|
|
|
}
|
|
|
|
});
|
2016-08-05 23:00:29 +08:00
|
|
|
if(filesSizeValid) {
|
2016-07-22 19:29:01 +08:00
|
|
|
// Check if there is enough free space for the files
|
2016-08-26 04:26:53 +08:00
|
|
|
filesSizeValid = enoughSpaceValidator(ev, fileInputs);
|
2016-07-22 19:29:01 +08:00
|
|
|
}
|
2016-08-05 23:00:29 +08:00
|
|
|
return filesSizeValid;
|
2016-07-22 19:29:01 +08:00
|
|
|
}
|
|
|
|
|
2020-02-12 19:14:58 +08:00
|
|
|
function numberMinMaxValidator(value, min, max) {
|
|
|
|
if(parseInt(value) < min || isNaN(value))
|
|
|
|
return min;
|
|
|
|
else if(parseInt(value) > max)
|
|
|
|
return max;
|
|
|
|
else return value;
|
|
|
|
}
|
|
|
|
|
2016-08-11 22:05:23 +08:00
|
|
|
/*
|
|
|
|
* Overriden in billing module for checking whether enough
|
2017-01-25 19:12:27 +08:00
|
|
|
* team space is free.
|
2016-08-11 22:05:23 +08:00
|
|
|
*/
|
2016-08-26 04:26:53 +08:00
|
|
|
function enoughSpaceValidator(ev, fileInputs) {
|
2016-07-22 19:29:01 +08:00
|
|
|
return true;
|
2016-08-09 20:39:24 +08:00
|
|
|
}
|