mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2025-10-08 04:47:22 +08:00
Additional changes, refactoring and improvements.
This commit is contained in:
parent
01aad1764c
commit
86880f0299
12 changed files with 235 additions and 237 deletions
|
@ -158,24 +158,6 @@ $(document.body).ready(function () {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
/*
|
|
||||||
* Truncate long strings where is necessary
|
|
||||||
*/
|
|
||||||
|
|
||||||
function truncateLongString( el, chars ) {
|
|
||||||
var input = $.trim(el.text());
|
|
||||||
|
|
||||||
if( input.length >= chars){
|
|
||||||
var newText = el.text().slice(0, chars);
|
|
||||||
for( var i = newText.length; i > 0; i--){
|
|
||||||
if(newText[i] === ' '){
|
|
||||||
newText = newText.slice(0, i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
el.text(newText + '...');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$(document).ready(function(){
|
$(document).ready(function(){
|
||||||
$('.tree-link a').each( function(){
|
$('.tree-link a').each( function(){
|
||||||
truncateLongString( $(this), 30);
|
truncateLongString( $(this), 30);
|
||||||
|
|
|
@ -102,10 +102,10 @@
|
||||||
|
|
||||||
|
|
||||||
exports.directUpload = function (form, origId, signUrl, cb, cbErr, errKey) {
|
exports.directUpload = function (form, origId, signUrl, cb, cbErr, errKey) {
|
||||||
var fileInputs = $(form).find("input[type=file]");
|
var $fileInputs = $(form).find("input[type=file]");
|
||||||
var file = fileInputs.get(0).files[0];
|
var file = $fileInputs.get(0).files[0];
|
||||||
|
|
||||||
var isValid = checkFilesValidity(fileInputs);
|
var isValid = filesValidator($fileInputs);
|
||||||
|
|
||||||
if (!isValid) {
|
if (!isValid) {
|
||||||
cbErr();
|
cbErr();
|
||||||
|
|
|
@ -185,9 +185,6 @@ function formEditAjax($form) {
|
||||||
reorderCheckboxData(this);
|
reorderCheckboxData(this);
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.on("ajax:send", function(e, data) {
|
|
||||||
selectedTabIndex = $form.find("li.active").index() + 1;
|
|
||||||
})
|
|
||||||
.on("ajax:success", function(e, data) {
|
.on("ajax:success", function(e, data) {
|
||||||
$(this).after(data.html);
|
$(this).after(data.html);
|
||||||
var $new_step = $(this).next();
|
var $new_step = $(this).next();
|
||||||
|
@ -212,23 +209,19 @@ function formEditAjax($form) {
|
||||||
var $form = $(this).next();
|
var $form = $(this).next();
|
||||||
$(this).remove();
|
$(this).remove();
|
||||||
|
|
||||||
|
$errInput = $form.find(".form-group.has-error").first().find("input");
|
||||||
|
renderFormError($errInput);
|
||||||
|
|
||||||
formCallback($form);
|
formCallback($form);
|
||||||
initEditableHandsOnTable($form);
|
initEditableHandsOnTable($form);
|
||||||
applyCancelCallBack();
|
applyCancelCallBack();
|
||||||
formEditAjax($form);
|
formEditAjax($form);
|
||||||
tabsPropagateErrorClass($form);
|
|
||||||
|
|
||||||
//Rerender tables
|
//Rerender tables
|
||||||
$form.find("[data-role='step-hot-table']").each(function() {
|
$form.find("[data-role='step-hot-table']").each(function() {
|
||||||
renderTable($(this));
|
renderTable($(this));
|
||||||
});
|
});
|
||||||
|
|
||||||
// Select the same tab pane as before
|
|
||||||
$form.find("ul.nav-tabs li.active").removeClass("active");
|
|
||||||
$form.find(".tab-content div.active").removeClass("active");
|
|
||||||
$form.find("ul.nav-tabs li:nth-child(" + selectedTabIndex + ")").addClass("active");
|
|
||||||
$form.find(".tab-content div:nth-child(" + selectedTabIndex + ")").addClass("active");
|
|
||||||
|
|
||||||
animateSpinner(null, false);
|
animateSpinner(null, false);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -262,10 +255,12 @@ function formNewAjax($form) {
|
||||||
var $form = $(this).next();
|
var $form = $(this).next();
|
||||||
$(this).remove();
|
$(this).remove();
|
||||||
|
|
||||||
|
$errInput = $form.find(".form-group.has-error").first().find("input");
|
||||||
|
renderFormError($errInput);
|
||||||
|
|
||||||
formCallback($form);
|
formCallback($form);
|
||||||
formNewAjax($form);
|
formNewAjax($form);
|
||||||
applyCancelOnNew();
|
applyCancelOnNew();
|
||||||
tabsPropagateErrorClass($form);
|
|
||||||
|
|
||||||
animateSpinner(null, false);
|
animateSpinner(null, false);
|
||||||
});
|
});
|
||||||
|
@ -583,89 +578,37 @@ $("[data-action='new-step']").on("ajax:success", function(e, data) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
function nameValidator(event) {
|
|
||||||
var $form = $(event.target.form);
|
|
||||||
var nameTooShort = $( "#step_name" ).val().length === 0;
|
|
||||||
var nameTooLong = $( "#step_name" ).val().length > 50;
|
|
||||||
var errMsg;
|
|
||||||
if (nameTooShort) {
|
|
||||||
errMsg = I18n.t("devise.names.not_blank");
|
|
||||||
} else if (nameTooLong) {
|
|
||||||
errMsg = I18n.t("devise.names.length_too_long", { max_length: 50 });
|
|
||||||
animateSpinner(null,false);
|
|
||||||
}
|
|
||||||
|
|
||||||
var hasErrors = !_.isUndefined(errMsg);
|
|
||||||
if (hasErrors) {
|
|
||||||
renderError($("#step_name"), errMsg);
|
|
||||||
}
|
|
||||||
return !hasErrors;
|
|
||||||
}
|
|
||||||
|
|
||||||
function checklistsValidator(event, editMode) {
|
|
||||||
var $form = $(event.target.form);
|
|
||||||
var noErrors = true;
|
|
||||||
|
|
||||||
// For every visible (i.e. not removed) checklist
|
|
||||||
$form.find(".nested_step_checklists[style!='display: none']").each(function() {
|
|
||||||
var $checklistNameInput = $(this).find(".checklist_name");
|
|
||||||
var checklistNameEmpty = !$checklistNameInput.val();
|
|
||||||
anyChecklistItemFilled = false;
|
|
||||||
|
|
||||||
// For every ckecklist item input
|
|
||||||
$(" .checklist-item-text", $(this)).each(function() {
|
|
||||||
if($(this).val()) {
|
|
||||||
anyChecklistItemFilled = true;
|
|
||||||
} else {
|
|
||||||
// Remove empty checklist item
|
|
||||||
$(this).closest("fieldset").remove();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
if(checklistNameEmpty) {
|
|
||||||
if(anyChecklistItemFilled || editMode) {
|
|
||||||
// In edit mode, name can't be blank
|
|
||||||
var errMsg = I18n.t("devise.names.not_blank");
|
|
||||||
renderError($checklistNameInput, errMsg);
|
|
||||||
noErrors = false;
|
|
||||||
} else {
|
|
||||||
// Hide empty checklist
|
|
||||||
$(this).hide();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$(event.target).blur();
|
|
||||||
return noErrors;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Needed because server-side validation failure clears locations of
|
// Needed because server-side validation failure clears locations of
|
||||||
// files to be uploaded and checklist's items etc. Also user
|
// files to be uploaded and checklist's items etc. Also user
|
||||||
// experience is improved
|
// experience is improved
|
||||||
function stepValidator(event, editMode, forS3) {
|
function stepValidator(ev, editMode, forS3) {
|
||||||
var $form = $(event.target.form);
|
var $form = $(ev.target.form);
|
||||||
$form.clear_form_errors();
|
|
||||||
if(!editMode) {
|
|
||||||
// Most td's disappear when editing step and not pressing on
|
|
||||||
// tables tab, so we can't use this function
|
|
||||||
clearBlankTables($form)
|
|
||||||
}
|
|
||||||
clearBlankFileForms($form);
|
|
||||||
// TODO File type check
|
|
||||||
var fileSizeValid = uploadFileSizeCheck(event);
|
|
||||||
var checklistsValid = checklistsValidator(event, editMode);
|
|
||||||
var nameValid = nameValidator(event);
|
|
||||||
|
|
||||||
if(fileSizeValid && checklistsValid && nameValid) {
|
$form.clear_form_errors();
|
||||||
|
$tables = $form.find(".nested_step_tables");
|
||||||
|
removeBlankExcelTables($tables, editMode);
|
||||||
|
removeBlankFileForms($form);
|
||||||
|
|
||||||
|
var $fileInputs = $form.find("input[type=file]");
|
||||||
|
var filesValid = filesValidator($fileInputs);
|
||||||
|
var $checklists = $form.find(".nested_step_checklists");
|
||||||
|
var checklistsValid = checklistsValidator($checklists, editMode);
|
||||||
|
var $nameInput = $form.find("#step_name");
|
||||||
|
var nameValid = nameValidator($nameInput);
|
||||||
|
|
||||||
|
if(filesValid && checklistsValid && nameValid) {
|
||||||
if(forS3) {
|
if(forS3) {
|
||||||
// Needed to redirect uploaded files to S3
|
// Needed to redirect uploaded files to S3
|
||||||
startFileUpload(event, event.target);
|
startFileUpload(ev, ev.target);
|
||||||
} else {
|
} else {
|
||||||
// Files are saved locally
|
// Files are saved locally
|
||||||
// Validations passed, so animate spinner for possible file uploading
|
// Validations passed, so animate spinner for possible file uploading
|
||||||
// (startFileUpload already calls it)
|
// (startFileUpload already calls it)
|
||||||
animateSpinner();
|
animateSpinner();
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// Don't submit form
|
||||||
|
ev.preventDefault();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -727,8 +670,6 @@ function startFileUpload(ev, btn) {
|
||||||
var inputPos = 0;
|
var inputPos = 0;
|
||||||
var inputPointer = 0;
|
var inputPointer = 0;
|
||||||
|
|
||||||
$form.clear_form_errors();
|
|
||||||
clearBlankFileForms(form);
|
|
||||||
animateSpinner();
|
animateSpinner();
|
||||||
|
|
||||||
function processFile () {
|
function processFile () {
|
||||||
|
@ -763,7 +704,7 @@ function startFileUpload(ev, btn) {
|
||||||
var $el = $(el);
|
var $el = $(el);
|
||||||
|
|
||||||
$form.clear_form_errors();
|
$form.clear_form_errors();
|
||||||
renderError($el, assetError);
|
renderFormError($el, assetError);
|
||||||
} else {
|
} else {
|
||||||
tabsPropagateErrorClass($form);
|
tabsPropagateErrorClass($form);
|
||||||
}
|
}
|
||||||
|
@ -777,30 +718,3 @@ function startFileUpload(ev, btn) {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
return noErrors;
|
return noErrors;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove empty file forms in step
|
|
||||||
function clearBlankFileForms(form) {
|
|
||||||
$(form).find("input[type='file']").each(function () {
|
|
||||||
if (!this.files[0]) {
|
|
||||||
$(this).closest("fieldset").remove();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove empty tables in step
|
|
||||||
function clearBlankTables(form) {
|
|
||||||
$(form).find(".nested_step_tables").each(function () {
|
|
||||||
if (!$(this).find("td:not(:empty)").length) {
|
|
||||||
$(this).closest("fieldset").remove();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// This checks if the ctarget param exist in the
|
|
||||||
// rendered url and opens the comment tab
|
|
||||||
$(document).ready(function(){
|
|
||||||
if( getParam('ctarget') ){
|
|
||||||
var target = "#"+ getParam('ctarget');
|
|
||||||
$(target).find('a.comment-tab-link').click();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ $("#new-result-asset").on("ajax:success", function(e, data) {
|
||||||
var $form = $(data.html);
|
var $form = $(data.html);
|
||||||
$("#results").prepend($form);
|
$("#results").prepend($form);
|
||||||
|
|
||||||
$form.add_upload_file_size_check();
|
$form.files_validator();
|
||||||
formAjaxResultAsset($form);
|
formAjaxResultAsset($form);
|
||||||
|
|
||||||
// Cancel button
|
// Cancel button
|
||||||
|
@ -30,7 +30,7 @@ function applyEditResultAssetCallback() {
|
||||||
$result.after($form);
|
$result.after($form);
|
||||||
$result.remove();
|
$result.remove();
|
||||||
|
|
||||||
$form.add_upload_file_size_check();
|
$form.files_validator();
|
||||||
formAjaxResultAsset($form);
|
formAjaxResultAsset($form);
|
||||||
|
|
||||||
// Cancel button
|
// Cancel button
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
function checkFilesValidity(fileInputs) {
|
|
||||||
|
|
||||||
function getFileError(file) {
|
|
||||||
if (!file) {
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
var size = parseInt(file.size);
|
|
||||||
<% sizeLimit = FILE_SIZE_LIMIT %>;
|
|
||||||
if (size > <%= sizeLimit.megabytes %>) {
|
|
||||||
return "<%= I18n.t 'general.file_size_exceeded', file_size: sizeLimit %>";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var isValid = true;
|
|
||||||
_.each(fileInputs, function(fileInput) {
|
|
||||||
var file = fileInput.files[0];
|
|
||||||
var assetError = getFileError(file);
|
|
||||||
var input = $(fileInput);
|
|
||||||
input.closest('.form-group').removeClass('has-error');
|
|
||||||
input.parent().find("[data-error='file-size']").remove();
|
|
||||||
if (assetError) {
|
|
||||||
renderError(input, assetError, "data-error='file-size'");
|
|
||||||
isValid = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return isValid;
|
|
||||||
}
|
|
35
app/assets/javascripts/sitewide/form_cleanups.js
Normal file
35
app/assets/javascripts/sitewide/form_cleanups.js
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
$.fn.clear_form_errors = function() {
|
||||||
|
$(this).find('.nav.nav-tabs li').removeClass('has-error');
|
||||||
|
$(this).find('.form-group').removeClass('has-error');
|
||||||
|
$(this).find('span.help-block').remove();
|
||||||
|
};
|
||||||
|
|
||||||
|
$.fn.clear_form_fields = function() {
|
||||||
|
$(this).find("input")
|
||||||
|
.not("button")
|
||||||
|
.not('input[type="submit"], input[type="reset"], input[type="hidden"]')
|
||||||
|
.not('input[type="radio"]') // Leave out radios as this messes up Bootstrap btn-groups
|
||||||
|
.val('')
|
||||||
|
.removeAttr('checked')
|
||||||
|
.removeAttr('selected');
|
||||||
|
};
|
||||||
|
|
||||||
|
function removeBlankFileForms(form) {
|
||||||
|
$(form).find("input[type='file']").each(function () {
|
||||||
|
if (!this.files[0]) {
|
||||||
|
$(this).closest("fieldset").remove();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not the actual Excel tables, but are similar
|
||||||
|
function removeBlankExcelTables(tables, editMode) {
|
||||||
|
if(!editMode) {
|
||||||
|
// In edit mode, tables can't be blank
|
||||||
|
tables.each(function () {
|
||||||
|
if (!$(this).find("td:not(:empty)").length) {
|
||||||
|
$(this).closest("fieldset").remove();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -36,73 +36,26 @@ $.fn.render_form_errors_no_clear = function(model_name, errors, input_group) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
$.fn.clear_form_errors = function() {
|
// Show error message and mark error input (if errMsg is defined)
|
||||||
$(this).find('.nav.nav-tabs li').removeClass('has-error');
|
// and, if present, mark and show the tab where the error occured,
|
||||||
$(this).find('.form-group').removeClass('has-error');
|
// and go to the input, if it is the most upper one or if errMsg is
|
||||||
$(this).find('span.help-block').remove();
|
// undefined
|
||||||
};
|
|
||||||
|
|
||||||
$.fn.clear_form_fields = function() {
|
|
||||||
$(this).find("input")
|
|
||||||
.not("button")
|
|
||||||
.not('input[type="submit"], input[type="reset"], input[type="hidden"]')
|
|
||||||
.not('input[type="radio"]') // Leave out radios as this messes up Bootstrap btn-groups
|
|
||||||
.val('')
|
|
||||||
.removeAttr('checked')
|
|
||||||
.removeAttr('selected');
|
|
||||||
};
|
|
||||||
|
|
||||||
// Add JavaScript client-side upload file size checking
|
|
||||||
// Callback function can be provided to be called
|
|
||||||
// any time at least one file size is too large
|
|
||||||
$.fn.add_upload_file_size_check = function(callback) {
|
|
||||||
var $form = $(this);
|
|
||||||
|
|
||||||
if ($form.length && $form.length > 0) {
|
|
||||||
$form.submit(function (ev) {
|
|
||||||
uploadFileSizeCheck(ev, callback);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function uploadFileSizeCheck(ev, callback) {
|
|
||||||
var $fileInputs = $(ev.target.form).find("input[type='file']");
|
|
||||||
if ($fileInputs.length && $fileInputs.length > 0) {
|
|
||||||
var isValid = checkFilesValidity($fileInputs);
|
|
||||||
|
|
||||||
if (!isValid) {
|
|
||||||
// Don't submit form
|
|
||||||
ev.preventDefault();
|
|
||||||
ev.stopPropagation();
|
|
||||||
|
|
||||||
if (callback) {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Show error message and mark error element and, if present, mark
|
|
||||||
// and show the tab where the error occured.
|
|
||||||
// NOTE: Similar to $.fn.render_form_errors, except here we process
|
// NOTE: Similar to $.fn.render_form_errors, except here we process
|
||||||
// one error at a time, which is not read from the form but is
|
// one error at a time, which is not read from the form but is
|
||||||
// specified manually.
|
// specified manually.
|
||||||
function renderError(nameInput, errMsg, errAttributes) {
|
function renderFormError(nameInput, errMsg, errAttributes) {
|
||||||
var $errMsgSpan = $(nameInput).next(".help-block");
|
if(!_.isUndefined(errMsg)) {
|
||||||
if(!$errMsgSpan.length) {
|
var $errMsgSpan = $(nameInput).next(".help-block");
|
||||||
errAttributes = (_.isUndefined(errAttributes)) ? "" : " " + errAttributes;
|
errAttributes = _.isUndefined(errAttributes) ? "" : " " + errAttributes;
|
||||||
|
if (!$errMsgSpan.length) {
|
||||||
|
$(nameInput).closest(".form-group").addClass("has-error");
|
||||||
|
}
|
||||||
$(nameInput).after("<span class='help-block'" + errAttributes + ">" + errMsg + "</span>");
|
$(nameInput).after("<span class='help-block'" + errAttributes + ">" + errMsg + "</span>");
|
||||||
$(nameInput).closest(".form-group").addClass("has-error");
|
|
||||||
} else {
|
|
||||||
$errMsgSpan.html(errMsg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$form = $(nameInput).closest("form");
|
$form = $(nameInput).closest("form");
|
||||||
$tab = $(nameInput).closest(".tab-pane");
|
$tab = $(nameInput).closest(".tab-pane");
|
||||||
if($tab.length) {
|
if ($tab.length) {
|
||||||
tabsPropagateErrorClass($form);
|
tabsPropagateErrorClass($form);
|
||||||
$parent = $tab;
|
$parent = $tab;
|
||||||
} else {
|
} else {
|
||||||
|
@ -110,27 +63,27 @@ function renderError(nameInput, errMsg, errAttributes) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Focus and scroll to the error if it is the first (most upper) one
|
// Focus and scroll to the error if it is the first (most upper) one
|
||||||
if($parent.find(".form-group.has-error").length === 1) {
|
if ($parent.find(".form-group.has-error").length === 1 || _.isUndefined(errMsg)) {
|
||||||
goToFormElement(nameInput);
|
goToFormElement(nameInput);
|
||||||
}
|
}
|
||||||
|
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
// If any of tabs (if exist) has errors, add has-error class to
|
// If any of tabs (if exist) has errors, mark parent tab
|
||||||
// parent tab navigation link and show the tab (if not already)
|
// navigation link and show the tab (if not already)
|
||||||
function tabsPropagateErrorClass(parent) {
|
function tabsPropagateErrorClass($form) {
|
||||||
var $contents = parent.find("div.tab-pane");
|
var $contents = $form.find("div.tab-pane");
|
||||||
_.each($contents, function(tab) {
|
_.each($contents, function(tab) {
|
||||||
var $tab = $(tab);
|
var $tab = $(tab);
|
||||||
var $errorFields = $tab.find(".has-error");
|
var $errorFields = $tab.find(".has-error");
|
||||||
if ($errorFields.length > 0) {
|
if ($errorFields.length) {
|
||||||
var id = $tab.attr("id");
|
var id = $tab.attr("id");
|
||||||
var navLink = parent.find("a[href='#" + id + "'][data-toggle='tab']");
|
var navLink = $form.find("a[href='#" + id + "'][data-toggle='tab']");
|
||||||
if (navLink.parent().length > 0) {
|
if (navLink.parent().length) {
|
||||||
navLink.parent().addClass("has-error");
|
navLink.parent().addClass("has-error");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
$(".nav-tabs .has-error:first:not(.active) > a", parent).tab("show");
|
$(".nav-tabs .has-error:first:not(.active) > a", $form).tab("show");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
// Scroll to and focus on element
|
// Scroll to and focus on element
|
||||||
function goToFormElement(el) {
|
function goToFormElement(input) {
|
||||||
$("html, body").animate(
|
$("html, body").animate(
|
||||||
{
|
{
|
||||||
scrollTop: $(el).closest(".form-group").offset().top
|
scrollTop: $(input).closest(".form-group").offset().top
|
||||||
- ($(".navbar-fixed-top").outerHeight(true)
|
- ($(".navbar-fixed-top").outerHeight(true)
|
||||||
+ $(".navbar-secondary").outerHeight(true)
|
+ $(".navbar-secondary").outerHeight(true)
|
||||||
+ $(".alert-dismissable").outerHeight(true))
|
+ $(".alert-dismissable").outerHeight(true))
|
||||||
},
|
},
|
||||||
"slow",
|
"slow",
|
||||||
function() { $(el).focus(); }
|
function() { $(input).focus(); }
|
||||||
);
|
);
|
||||||
}
|
}
|
25
app/assets/javascripts/sitewide/string_utils.js
Normal file
25
app/assets/javascripts/sitewide/string_utils.js
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
// Truncate long strings where is necessary
|
||||||
|
function truncateLongString( el, chars ) {
|
||||||
|
var input = $.trim(el.text());
|
||||||
|
|
||||||
|
if( input.length >= chars){
|
||||||
|
var newText = el.text().slice(0, chars);
|
||||||
|
for( var i = newText.length; i > 0; i--){
|
||||||
|
if(newText[i] === ' '){
|
||||||
|
newText = newText.slice(0, i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
el.text(newText + '...');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Usefull for converting locals messages to form
|
||||||
|
// format (i.e. lower cased capital and no dot)
|
||||||
|
String.prototype.strToFormFormat = function() {
|
||||||
|
var length = this.length;
|
||||||
|
if (this[length - 1] === ".") {
|
||||||
|
length -= 1;
|
||||||
|
}
|
||||||
|
return this.charAt(0).toLowerCase() + this.slice(1, length);
|
||||||
|
}
|
116
app/assets/javascripts/sitewide/validators.js.erb
Normal file
116
app/assets/javascripts/sitewide/validators.js.erb
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
function nameValidator($nameInput) {
|
||||||
|
var nameTooShort = $nameInput.val().length === 0;
|
||||||
|
var nameTooLong = $nameInput.val().length > 50;
|
||||||
|
var errMsg;
|
||||||
|
if (nameTooShort) {
|
||||||
|
errMsg = I18n.t("devise.names.not_blank");
|
||||||
|
} else if (nameTooLong) {
|
||||||
|
errMsg = I18n.t("devise.names.length_too_long", { max_length: 50 });
|
||||||
|
}
|
||||||
|
|
||||||
|
var hasErrors = !_.isUndefined(errMsg);
|
||||||
|
if (hasErrors) {
|
||||||
|
renderFormError($nameInput, errMsg);
|
||||||
|
}
|
||||||
|
return !hasErrors;
|
||||||
|
}
|
||||||
|
|
||||||
|
function checklistsValidator(checklists, editMode) {
|
||||||
|
var noErrors = true;
|
||||||
|
// For every visible (i.e. not removed) checklist
|
||||||
|
checklists.each(function() {
|
||||||
|
$checklist = $(this);
|
||||||
|
if ($checklist.css('display') != 'none') {
|
||||||
|
var $checklistNameInput = $checklist.find(".checklist_name");
|
||||||
|
anyChecklistItemFilled = false;
|
||||||
|
|
||||||
|
// For every ckecklist item input
|
||||||
|
$(" .checklist-item-text", $checklist).each(function() {
|
||||||
|
$checklistItemInput = $(this);
|
||||||
|
if ($checklistItemInput.val()) {
|
||||||
|
anyChecklistItemFilled = true;
|
||||||
|
} else {
|
||||||
|
// Remove empty checklist item input
|
||||||
|
$checklistItemInput.closest("fieldset").remove();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!$checklistNameInput.val()) {
|
||||||
|
if (anyChecklistItemFilled || editMode) {
|
||||||
|
// In edit mode, checklist's name can't be blank
|
||||||
|
var errMsg = I18n.t("devise.names.not_blank");
|
||||||
|
renderFormError($checklistNameInput, errMsg);
|
||||||
|
noErrors = false;
|
||||||
|
} else {
|
||||||
|
// Hide empty checklist (remove would break logic)
|
||||||
|
$checklist.hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return noErrors;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add JavaScript client-side upload file checking
|
||||||
|
// Callback function can be provided to be called
|
||||||
|
// any time at least one file size is not valid
|
||||||
|
$.fn.files_validator = function(callback) {
|
||||||
|
var $form = $(this);
|
||||||
|
if ($form.length) {
|
||||||
|
$form.submit(function (ev) {
|
||||||
|
var $fileInputs = $form.find("input[type=file]");
|
||||||
|
filesValidator($fileInputs, callback);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function filesValidator(fileInputs, callback) {
|
||||||
|
var filesSizeValid = true;
|
||||||
|
if (fileInputs.length) {
|
||||||
|
var filesSizeValid = filesSizeValidator(fileInputs);
|
||||||
|
// TODO File content check
|
||||||
|
|
||||||
|
if (!filesSizeValid && callback) {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return filesSizeValid;
|
||||||
|
}
|
||||||
|
|
||||||
|
function filesSizeValidator(fileInputs) {
|
||||||
|
|
||||||
|
function getFileTooBigError(file) {
|
||||||
|
if (!file) {
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
var size = parseInt(file.size);
|
||||||
|
<% sizeLimit = FILE_SIZE_LIMIT %>;
|
||||||
|
if (size > <%= sizeLimit.megabytes %>) {
|
||||||
|
return "<%= I18n.t 'general.file_size_exceeded', file_size: sizeLimit %>".strToFormFormat();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Check if any file exceeds allowed size limit
|
||||||
|
var fileSizeValid = true;
|
||||||
|
_.each(fileInputs, function(fileInput) {
|
||||||
|
var file = fileInput.files[0];
|
||||||
|
var assetError = getFileTooBigError(file);
|
||||||
|
var input = $(fileInput);
|
||||||
|
if (assetError) {
|
||||||
|
renderFormError(input, assetError, "data-error='file-size'");
|
||||||
|
fileSizeValid = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if(fileSizeValid) {
|
||||||
|
// Check if there is enough free space for the files
|
||||||
|
fileSizeValid = enaughSpaceValidator(fileInputs);
|
||||||
|
}
|
||||||
|
return fileSizeValid;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Overriden in billing module for checking
|
||||||
|
// whether enough organization space is free
|
||||||
|
function enaughSpaceValidator(fileInputs) {
|
||||||
|
return true;
|
||||||
|
}
|
|
@ -63,7 +63,7 @@ forms
|
||||||
});
|
});
|
||||||
|
|
||||||
// Add upload file size checking
|
// Add upload file size checking
|
||||||
$("form[data-for='avatar']").add_upload_file_size_check();
|
$("form[data-for='avatar']").files_validator();
|
||||||
|
|
||||||
// S3 direct uploading
|
// S3 direct uploading
|
||||||
function startFileUpload(ev, btn) {
|
function startFileUpload(ev, btn) {
|
||||||
|
@ -103,7 +103,7 @@ function startFileUpload(ev, btn) {
|
||||||
var $el = $form.find("input[type=file]");
|
var $el = $form.find("input[type=file]");
|
||||||
|
|
||||||
$form.clear_form_errors();
|
$form.clear_form_errors();
|
||||||
renderError($el, avatarError);
|
renderFormError($el, avatarError);
|
||||||
}
|
}
|
||||||
}, "avatar");
|
}, "avatar");
|
||||||
|
|
||||||
|
|
|
@ -19,8 +19,8 @@ en:
|
||||||
title: "Forgot your password?"
|
title: "Forgot your password?"
|
||||||
submit: "Send me reset password instructions"
|
submit: "Send me reset password instructions"
|
||||||
names:
|
names:
|
||||||
not_blank: "Name can't be blank"
|
not_blank: "name can't be blank"
|
||||||
length_too_long: "Name is too long (maximum is %{max_length} characters)"
|
length_too_long: "name is too long (maximum is %{max_length} characters)"
|
||||||
registrations:
|
registrations:
|
||||||
password_changed: "Password successfully updated."
|
password_changed: "Password successfully updated."
|
||||||
sessions:
|
sessions:
|
||||||
|
|
Loading…
Add table
Reference in a new issue