I have the next code (code does not run like copied here) that I would like to use for addressing errors on an input field of a form. The field is checked when the focus of the field is lost. An ajax request checks if the entry is allowed for that field (based on a lookup table). The two user functions set and remove error class around the input field.
When an error occurs, I want the field in error to have the only focus of the whole form (user has to correct this field before a different field is selected).
That last requirement does not work in the code. The focus is handed intermitted to the fields. It seems like if I have to click more then needed as well.
Question: What am I doing wrong?
$(document).ready(function() {
var errors = [];
//check value in lookup table with ajax
$("body").on("blur", "input[data-table]", function() {
var name = $(this).attr("id");
var table = $("input[name=" + name + "]").data().table;
var value = $(this).val();
var len = value.length;
//Only if an entry has been made in the field
if (len > 0) {
var jqxhr = $.post("/controller/lookup.php", {
table: table,
value: value
}, function() {});
//Done with the request
jqxhr.done(function(data) {
var e = JSON.parse(data).error;
if (e == "true") {
//set error
setError(name);
//prevent focus on other
$("body").on("click", "input", function(e) {
if (!(e.target.id == name))
$("input#" + name).focus();
});
} else {
removeError(name);
$("body").off("click", "input");
}
});
//A failure has occured
jqxhr.fails(function(xhr, msg) {
//TODO: exception handling
});
}
//if the field has been cleared remove error
removeError(name);
});
function setError(name) {
//Check if error already exists
if (!getErrors(name)) {
var e = getErrorIndex(name);
if (e > -1) errors[e].error = true;
else errors.push({
name: name,
error: true
});
var span = "<span class=\"glyphicon glyphicon-exclamation-sign\" style=\"color: red; float: left\"></span>";
//Decorate errors
$("input#" + name).parent().addClass("has-error");
$("input#" + name).after(span);
};
}
function removeError(name) {
var e = getErrorIndex(name);
if (e > -1) {
errors[e].error = false;
$("input#" + name).parent().removeClass("has-error");
$("input#" + name).next().remove();
}
}
function getErrors(needle) {
for (var i = 0; i < errors.length; i++) {
if (errors[i].name === needle) return errors[i].error;
}
return false;
}
function getErrorIndex(needle) {
for (var i = 0; i < errors.length; i++) {
if (errors[i].name === needle) return i;
}
return -1;
}
});
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
Related
For my Project I need to have a site, which can generate a custom amount of Inputs, which will become buttons in another page.
And I need the values for the Input in order to Label the Buttons correctly.
HTML
<h2>settings:</h2>
<p>Add Amount of Checks:</p>
<input id="NumOfButtons"
name="NumOfButtons"
pattern=""
size="30"
spellcheck="false"
title="Amount of Checks"
value="">
<script>
let input = document.getElementById("NumOfButtons");
let listTA = new Array;
input.addEventListener("keyup", function (event) {
if (event.keyCode === 13) {
event.preventDefault();
var x = parseInt(document.getElementById("NumOfButtons").value);
listTA = new Array(x);
for (let i = 0; i < x; ++i) {
var textarea = document.createElement("input");
textarea.name = "input";
textarea.maxLength = "100";
textarea.id = "TextAreaID"
listTA[i] = textarea;
document.getElementById("Buttons").appendChild(textarea);
}
}
});
</script>
<div id="Buttons">
<br />
<button onclick="sendDataAndGoToKontrolle()">save & continue</button>
<p>Reset F5</p>
</div>
<script>
function sendDataAndGoToKontrolle() {
var filtered;
if (listTA != null) {
let x = new Array;
for (let i = 0; i < listTA.length; ++i) x[i] = listTA[i].document.getElementById("TextAreaID").value;
if (!(x.length === 0)) {
for (let i = 0; i < x.length; ++i) {
if (x[i] === null) {
var filtered = x.filter(function (el) { return el != null; });
console.log("TextAreas filtered!")
} else console.log("Nothing to filter!")
}
} else console.log("Nothin written in TextAreas!");
} else console.log("No TextArea created!");
if (!(filtered === null)) {
//Send Prüfungen to Controller
$.ajax({
url: "#Url.Action("NewIDSettingsPage")",
type: "GET",
data: { Prüfungen: filtered },
success: function () {
console.log("Successfully sent!");
//window.location.href = '/home/NewIDSettingsPage';
},
error: function (xhr, status, error) {
var errorMessage = xhr.status + ': ' + xhr.statusText;
console.log("ERROR: " + errorMessage);}});
} else console.log("ERROR");
}
</script>
The result should be a list/Array of string(values of the Inputs).
If you need any further information, please write a Comment and I will look to reply quickly.
Do not give all the input elements the same id. textarea.id = "TextAreaID" is wrong.
If you want to group the inputs together you should set the class:
textarea.className = "TextAreaClass"
Or if you want to give each one an id, append i to the id to make it unique:
textarea.id = "TextAreaID"+i;
When trying to get the values of your inputs you have the following:
x[i] = listTA[i].document.getElementById("TextAreaID").value;
Which doesn't make a lot of sense. What you should probably be doing is:
x[i] = listTA[i].value;
Because you have stored the element in the array, you don't need to get the element from the document.
I have two problems one I can't get the Regex (for email) I created to fire properly when I add it to my logic. It seems to make the field which was fine (by entering correct input) invalidate when I tab away...
The second problem is the select dropdown. I am not sure what is the best practice but I essentially would like the select dropdown to remain with the error messages until either the user has selected a proper state.
This is my code:
var ValidationChecker = (function validationHndlr() {
'use strict';
var doc = document;
var form;
var emailRegExp;
var formElements;
emailRegExp = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+#[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/;
form = doc.getElementsByTagName('form')[0];
formElements = form.elements;
function addMultipleListeners(element, events, handler, useCapture, args) {
if (!(events instanceof Array)) {
throw 'addMultipleListeners: ' +
'please supply an array of eventstrings ' +
'(like ["click","mouseover"])';
}
//create a wrapper to be able to use additional arguments
var handlerFn = function(e) {
handler.apply(this, args && args instanceof Array ? args : []);
}
for (var i = 0; i < events.length - 1; i += 1) {
element.addEventListener(events[i], handlerFn, useCapture);
}
}
for (let i = 0, l = formElements.length; i < l; i++) {
var elId = doc.getElementById(formElements[i].id);
addMultipleListeners(elId, ['focus', 'blur', 'keyup'], function(e) {
if ((formElements[i].value == '') || (formElements[i].value == null) || ((formElements[i].type == 'email') != emailRegExp) ) {
formElements[i].classList.add('invalid-input');
formElements[i].nextElementSibling.style.display = 'block';
formElements[i].nextElementSibling.innerHTML = 'Not valid!';
}
}, false);
elId.addEventListener('keyup', function(e) {
console.log('keyup working?');
if ((formElements[i].value != '') && (formElements[i].value.length > 2)) {
formElements[i].classList.remove('invalid-input');
if (formElements[i].nextElementSibling.type !== 'submit') {
formElements[i].nextElementSibling.style.display = 'none'
}
}
}, false);
}
})();
How can I simplify current JavaScript code? It looks too complicated.
// Data from AJAX response
var errorsJSON = {
"name-pl": ["The name-pl field is required."],
"name-en": ["The name-en field is required."]
}
var errorString = $(this).data('validate-multiple');
var errorNamesArray = errorString.split(", ");
var ul = $('<ul class="list-unstyled">');
$.each(errorNamesArray, function(key, value) {
if (errorsJSON.hasOwnProperty(value)) {
ul.append(`<li><span class="help-block">${errorsJSON[value]}</span></li>`);
}
});
if (! $(this).is(':visible') && ul.children('li').length > 0) {
$(this).find('div.controls').empty().append(ul);
$(this).slideDown(500);
} else if ($(this).is(':visible') && ul.children('li').length === 0) {
$(this).slideUp(500);
} else if ($(this).is(':visible') && ul.children('li').length > 0) {
$(this).slideUp(500, function() {
$(this).find('div.controls').empty().append(ul);
$(this).slideDown(500);
});
}
Here I pasted both html and js code http://jsfiddle.net/ecLjnnhm/
I would like to point out that errorsJSON can change and depends what user put in the input fields.
Readability: Use variables to store the conditions of your if statements instead of lengthy declarations each time.
Efficiency: Cache $(this) as a variable so jQuery only has to do the work once.
Personal preference: I'd suggest prefacing any jQuery object variables (like ul in your case) with a $ to indicate that they're a jQuery object.
// Data from AJAX response
var errorsJSON = {
"name-pl": ["The name-pl field is required."],
"name-en": ["The name-en field is required."]
}
var errorString = $(this).data('validate-multiple');
var errorNamesArray = errorString.split(", ");
var $ul = $('<ul class="list-unstyled">');
var $t = $(this);
var isVisible = $t.is(':visible');
var hasErrors = false;
$.each(errorNamesArray, function(key, value) {
if (errorsJSON.hasOwnProperty(value)) {
$ul.append(`<li><span class="help-block">${errorsJSON[value]}</span></li>`);
hasErrors = true;
}
});
if (!isVisible && hasErrors) {
$t.find('div.controls').empty().append(ul);
$t.slideDown(500);
} else if (isVisible && !hasErrors) {
$t.slideUp(500);
} else if (isVisible && hasErrors) {
$t.slideUp(500, function() {
$t.find('div.controls').empty().append(ul);
$t.slideDown(500);
});
}
When i click the search button it always alert me "TypeError: this.Rows is undefined
for (var i = 0, row; row = this.Rows[i], rowText = this.RowsText[i]; i++) { "
Here is my code:
<script language="javascript" type="text/javascript">
//define the table search as an object, which can implement both functions and properties
window.tableSearch = {};
//initialize the search, setup the current object
tableSearch.init = function() {
//define the properties I want on the tableSearch object
this.Rows = document.getElementById('data').getElementsByTagName('TR');
this.RowsLength = tableSearch.Rows.length;
this.RowsText = [];
//loop through the table and add the data to
for (var i = 0; i < tableSearch.RowsLength; i++) {
this.RowsText[i] = (tableSearch.Rows[i].innerText) ? tableSearch.Rows[i].innerText.toUpperCase() : tableSearch.Rows[i].textContent.toUpperCase();
}
}
//onlys shows the relevant rows as determined by the search string
tableSearch.runSearch = function() {
//get the search term
this.Term = document.getElementById('textBoxSearch').value.toUpperCase();
//loop through the rows and hide rows that do not match the search query
for (var i = 0, row; row = this.Rows[i], rowText = this.RowsText[i]; i++) {
row.style.display = ((rowText.indexOf(this.Term) != -1) || this.Term === '') ? '' : 'none';
}
}
//runs the search
tableSearch.search = function(e) {
//checks if the user pressed the enter key, and if they did then run the search
var keycode;
if (window.event) { keycode = window.event.keyCode; }
else if (e) { keycode = e.which; }
else { return false; }
if (keycode == 13) {
tableSearch.runSearch();
}
else { return false; }
}
</script>
The two most probable causes to that problem are:
You never called your init function. Make sure to call it after your HTML has loaded and before using Rows the first time.
There is a Firefox bug where getElementsByTagName('TR'); returns undefined. make sure that that is not your problem.
I have CustomNewForm for inserting items in the sharepoint list.
The fields are "Reason" and "Reason OverView"; both Multiple Line Rich Text fields. I need to copy some text from "Reason" to "Reason Overview".(A substring)
I tried to get this done with workflow but couldn't find a solution to get a substring of a form field.
I am trying to get the value from "Reason" field in javascript; but unable to do so.
MY CODE :: (not working)
<script type="text/javascript">
function PreSaveAction()
{
var Reason = getTagFromIdentifierAndTitle("textarea","TextField","Reason");
var Original = getTagFromIdentifierAndTitle("textarea","TextField","Reason Overview");
alert('Hi');
Original.innerHTML=Reason.innerHTML;
return true;
}
function getTagFromIdentifierAndTitle(tagName, identifier, title)
{
var len = identifier.length;
var tags = document.getElementsByTagName(tagName);
for (var i=0; i < tags.length; i++)
{
var tempString = tags[i].id;
if (tags[i].title == title && (identifier == "" || tempString.indexOf(identifier) == tempString.length - len))
{
return tags[i];
}
}
return null;
}
</script>
Any way to get this done??
I solved it using this
<script type="text/javascript">
function PreSaveAction()
{
var Reason = getTagFromIdentifierAndTitle("textarea","TextField","Reason");
var Original = getTagFromIdentifierAndTitle("textarea","TextField","Reason Overview");
var reasonText = RTE_GetEditorDocument(Reason.id);
var reasonOverviewText = reasonText.body.innerText;
if(reasonOverviewText.length>=20)
{
reasonOverviewText = reasonOverviewText.substring(0,20)+'......';
Original.innerText = reasonOverviewText;
}
else
{
Original.innerText = reasonOverviewText;
}
return true;
}
function getTagFromIdentifierAndTitle(tagName, identifier, title)
{
var len = identifier.length;
var tags = document.getElementsByTagName(tagName);
for (var i=0; i < tags.length; i++)
{
var tempString = tags[i].id;
if (tags[i].title == title && (identifier == "" || tempString.indexOf(identifier) == tempString.length - len))
{
return tags[i];
}
}
return null;
}
</script>