Display All ().html in Javascript - javascript

Sorry for the lack of description in title, it's difficult to explain.
So I have a simple signup page and I made a bunch of functions in my code that check things such as the username length, make sure the passwords match, etc..
The problem is, if there is more than one error in the users input, it only displays one error at the bottom.
HEre is the JSfiddle: http://jsfiddle.net/LCBradley3k/xqcJS/19/
Javascript:
$('#join').on('click', function () {
var correct = true;
$('input[type="text"], input[type="password"]').each(function (indx) {
var $currentField = $(this);
if ($currentField.val() === '') {
$currentField.addClass('empty');
correct = false;
$currentField.one('keydown', function () {
$currentField.removeClass('empty');
});
} else {
$currentField.removeClass('empty');
}
});
function userLength() {
var x = $('input[name="user"]').val();
if (x.length < 6) {
$('#answer').html('Less than six characters.');
$('input[name="user"]').addClass('empty');
return false;
} else {
return true;
}
}
function passwordCheck() {
var x = $('input[name="password"]').val();
var y = $('input[name="passwordcheck"]').val();
if (x === y) {
return true;
} else {
$('#answer').html('Two different passwords');
$('input[name="password"], input[name="passwordcheck"]').addClass('empty');
return false;
}
}
function validateForm() {
var x = $('input[name="email"]').val();
if (x.indexOf('#') !== -1 && x.lastIndexOf(".") !== -1) {
return true;
} else {
$('#answer').html('Not a valid email');
$('input[name="email"]').addClass('empty');
return false;
}
}
if (correct) {
if (userLength()) {
if (passwordCheck()) {
if (validateForm()) {
$('#answer').html('Thank You!');
setTimeout(function () {
$('.inputs').hide("slide", {
direction: "up"
}, 1000);
}, 2000);
}
}
}
} else {
$('#answer').html('Please fill highlighted fields.');
}
});
You can see that all of them edit the #('#answer') div with .html(). But only one is displayed when there is more than one error. Once that error is fixed and the button is pressed, it will then display the next error. I want them all to be displayed in a list.

I created a fiddle that may be of some help. The idea is to create an array with the errors in it like so:
var errors = [];
errors.push("Error 1");
errors.push("Error 2");
As you step through the validation, every time an error is encountered you simply push the error string onto the array. When you get to the end of the validation you need to compile these errors into html like that can be appended to your $('#answer') element. In this case the items are compiled into an unordered list. You can change this to fit your needs.
var content = "<ul>";
for(var a = 0, len = errors.length; a < len; a++) {
content += "<li>" + errors[a] + "</li>";
}
content += "</ul>";
$('#answer').html(content);
The html is built dynamically and stored in the variable content. content is then appended to your html element that displays the errors (in your case answer).

You have 2 issues with doing what you want.
First, you are only continuing your checks if the first one passes, due to your nested if statements.
Second, you are replacing the #answer html with the message, which means even if you do each check, you will only see the results of the last one.
A simple fix would be to un-nest your if statements, and keep a variable that tracks the overall pass state. Secondly, instead of using .html(), use .append(), but make sure to clear out #answer before starting your checks.
correct &= checkFilled();
correct &= userLength();
correct &= passwordCheck();
correct &= validateForm();
if (correct) {
// ...
}
Fiddle: http://jsfiddle.net/jtbowden/9cFKW/
Note: I made your form filled check it's own function to work better with this method.
You can do some more fancy things, like pushing error messages on an array, and then checking the array for errors at the end and appending all of the messages, but this should get you started.

Related

Add class to clicked button if statement

I'm trying to make hangaman game so if the user click the correct letter 'dont-draw' class will be added if he enter the wrong letter another class will added, but is seems this if condition never became false
else if(theClickedLetter !== wordGeuss){
e.target.classList.add('draw');
}
here is the code:
document.addEventListener('click', function(e) {
let theClickedLetter = e.target.textContent;
arrayGuess.forEach((wordGeuss, index) => {
if (theClickedLetter === wordGeuss) {
e.target.classList.add('dont-draw');
let n = Array.from(lettersGess.children);
n[index].textContent = theClickedLetter;
}
else if (theClickedLetter !== wordGeuss) {
e.target.classList.add('draw');
}
})
})
So first think you can do to test what's going on is that you add an else in the end and see where the logic is ending up at. Since you didn't provide a complete HTML, I couldn't do much on the testing end so I can only suggest you how to test and possible fixes. Here's your code with an else:
document.addEventListener('click', function(e) {
let theClickedLetter = e.target.textContent;
arrayGuess.forEach((wordGeuss, index) => {
if (theClickedLetter === wordGeuss) {
e.target.classList.add('dont-draw');
let n = Array.from(lettersGess.children);
n[index].textContent = theClickedLetter;
}
else if (theClickedLetter !== wordGeuss) {
e.target.classList.add('draw');
}
else {
console.log('ending up in else')
}
})
})
Then you can see what's going wrong. Possible issues and fixes are
The way you get the text from the event (try using other methods like e.target.innerText)
Try printing both of the variables before the if else block and see what's gone wrong (see if the values actually match and debug accordingly)
Just use an else at the end to put the code e.target.classList.add('draw');, that might be a possible solution

Cross Site Scripting cannot be cleared

In order to prevent malicious html/scripts from being entered in input fields and saved in our application, we are inspecting the user input for html and if found, we don't submit.
We do this using the following function
/**
* Parse for HTML elements to avoid cross-site scripting
* #param str
*/
function isHTML() {
var str = $("#AttributeInstance").val();
var htmltempElement = document.createElement('div');
htmltempElement.innerHTML = str;
for (var c = htmltempElement.childNodes, i = c.length; i--;) {
if (c[i].nodeType == 1) {
htmltempElement = null;
str = null;
return true;
}
}
return false;
}
The function is working great. For instance, if on our form, the user enters the following
<img src=a onerror=alert(1)>
The function returns true and we don't save the value.
Here is how we call this function
if (isHTML()) {
alert("Found HTML! Stop!");
instance = "";
$("#AttributeInstance").val(""); //clear the input field
}
else {
alert("No HTML! Continue");
alert(instance);
addKpi(group, name, instance, instanceSelection);
}
alert("Finished");
Now here is the issue. This code results in an alert of "Found HTML! Stop!" and then "Finished" being displayed.
But then we also get an alert of "1" which is from the original input value that contains the script. By this point, that field has been cleared and we are not storing the malicious script value anywhere, however, it pops it up as a message even though it was clearly detected and we stop processing.
Any ideas? Or any suggestion how to better detect cross site scripting values in an input field?
If we remove the following from the function
htmltempElement.innerHTML = str;
for (var c = htmltempElement.childNodes, i = c.length; i--;) {
if (c[i].nodeType == 1) {
htmltempElement = null;
str = null;
return true;
}
}
Then the script does not pop up the "1" There's something about checking for a script this way that ends up processing the script it seems.

Cannot figure out why form error messages are cleared on resubmission

On first submit the error messages come up. In order to clear out error messages for correct values, I created a loop to clear out any spans on those labels, with the thinking that ALL messages would be cleared out, then run through the error checking again and re-apply the error messages.
Even if I return false on the loop to clear out the error messages it just refreshes the page. And the code does not appear to make it past that point and go through the standard error checking.
var label = document.getElementsByTagName("label");
var span = document.getElementsByTagName("span");
var spanMatch = false;
//attempting to remove any span tags once it's resubmitted
for (var k=0; k<label.length; k++) {
if (label.childNodes = span[1]) {
label.removeChild.span[1];
spanMatch = true;
}
}
if (spanMatch) {return false;}
var match = false;
//created a single loop so it would check all without return false until all were checked
for (var i=0; i<1; i++) {
if (!loanVal.match(regexOne)) {
wholeError(obj.loanAmt.name);
match = true;
}
if (!interestVal.match(regexTwo)){
floatError(obj.interest.name);
match = true;
}
if (!periodVal.match(regexOne)) {
wholeError(obj.period.name);
match = true;
}
}
if (match) {return false;}
else {alert("Something is right");}
}
I hope that is enough code to tell where the problem is. Here's a link to this problem online: http://russet.wccnet.edu/~sfloyd/inp271/php-js-project/loan-calc/index.php
Thanks

Javascript Array Losing an Element At Random

I have a very strange issue that I am running into. I am using jsTree from JQueryUI on one of my sites, and I have different implementations of it used in different .js files. One of them seems to work, which is very confusing as it uses almost identical code (only the variable names are different) to the implementation that is broken. The problem comes from the contextmenu function. The code I am using is as follows:
$(document).ready(function () {
if(typeof dryerList == 'undefined' || dryerList.length == 0) {
var dryerList = [];
$.ajax({
url:'../TrackingApp/getGrainBins.php?t=234.23423452353',
async: false,
success: function(text) {
try {
dryerList = $.parseJSON(text);
} catch (e) {
alert('ERROR: ' + e);
}
if(dryerList.length == 0) {
alert('ERROR: No fleet data received.')
}
}
});
}
$("#dryerListTree").jstree({
plugins : ['json_data', 'ui', 'themes', 'contextmenu'],
contextmenu: {items: customBinMenu},
json_data : { data: binNodes }
});
$('#dryerListTree').bind("dblclick.jstree", function (event) {
var node = $(event.target).closest("li");
var id = node[0].id;
for(i=0; i < dryerList.length; i++) {
if(id == dryerList[i].id) {
centerMap(dryerList[i].y, dryerList[i].x);
break;
}
}
});
});
function customBinMenu(node) {
if ($(node).hasClass("folder")) {
return;
}
var items = {
centerItem: {
label: "Locate",
action: function () {
// Centers map on selected bin
var id = node[0].id;
for(i=0; i < dryerList.length; i++) {
if(id == dryerList[i].id) {
centerMap(dryerList[i].y, dryerList[i].x);
break;
}
}
}
},
dashboardItem: {
label: "Dashboard",
action: function () {
// Opens dryer info window over map
var id = node[0].id;
var dryerIndex = -1;
for(i=0; i < dryerList.length; i++) {
if(id == dryerList[i].id) {
dryerIndex = i;
break;
}
}
}
}
};
return items;
}
The strange bit is, the double-click handler works just fine. When I get to the customBinMenu() function, the dryerList array is there, and dryerList[0] contains 4 of the 5 values that it should- but somehow the 'id' element has been dropped from that object. I have been looking at this for quite some time, and I can't figure out how it can drop a single element from the object without losing any other data, especially when identical code is working for a similar list. Any suggestions?
Ok, I read in your question: 'and dryerList[0] contains 4 of the 5 values that it should- but somehow the 'id' element has been dropped from that object'
So by 'element' and 'value' I assume you mean 'attribute': the node's 'id'-attribute to be precise ??
I see in your code: var id = node[0].id;
That should be: var id = node[0].getAttribute("id");
Good luck!
UPDATE 1:
Ok, if (as per your comment) var id = node[0].id; (getting id from node[0]) is ok, then if(id == dryerList[i].id) looks wrong, since you just (re-)defined id to be the value of node[0]'s id.
Actually I would not use 'id' as a var-name (in this case).
So what if you did: var idc = node[0].getAttribute("id");
and then: if(idc === dryerList[i].getAttribute("id"))
UPDATE 5: You still have some errors by the way:
You forgot a semi-colon to close the alert in:
if(dryerList.length == 0) {
alert('ERROR: No fleet data received.')
}
You should use '===' to compare with '0' on line 2 and 14
naturally in real life you would define function customBinMenu(node) before it was used in your document.ready function.
Fixed by swapping code order.
The same goes for this document.ready function where you used var dryerList before it was defined.
Fixed by: var dryerList = dryerList || []; if(dryerList.length === 0){//ajax & json code}
Could you please confirm if this fiddle, which is now valid javascript, represents your intended baseline-code that still results in your problem of the 'id'-attribute being 'undefined' in dryerList's node-collection (since the code you posted contained some simple errors that are fixed in this jsfiddle, excluding the things mentioned in update 1, since you commented that this is not the problem) ?
May I ask (since you start at document.ready), why do you (still) check if dryerList already exists?
May I ask if you could update that corrected fiddle with some demo-data for us to toy around with?

Calling function from function WEIRD RESULTS

I was trying to show a text gradually on the screen (like marquee). e.g. H.. He.. Hell.. Hello. when I'm tracing it in debug in VS2010 it's working! but when it's actually running it shows the whole sentence at once.
I made a certain "delay" for about 3 seconds between each letter so it would suppose to take a while, but in reality it's shows everything immediately.
Who's the genius to solve this mystery? (please don't give me advices how to create the marquee effect, it's not the issue anymore. now it's just a WAR between me and javascript!) I'm assuming that it has to do with synchronization when calling function from function?
Thanks to whomever will help me get my sanity back.
you can download the code from here (VS project):
http://pcgroup.co.il/downloads/misc/function_from_function.zip
or view it here:
<body>
<script type="text/javascript">
//trying to display this source sentence letter by letter:
var source = "hi javascript why are you being such a pain";
var target = "";
var pos = 0;
var mayGoOn = false;
//this function calls another function which suppose to "build" the sentence increasing index using the global var pos (it's even working when following it in debug)
function textticker() {
if (pos < source.length) {
flash();
if (mayGoOn == true) {
pos++;
mayGoOn = false;
document.write(target);
textticker();
}
}
}
function flash() {
//I tried to put returns everywhere assuming that this may solve it probably one of them in not necessary but it doesn't solve it
if (mayGoOn == true) { return; }
while (true) {
var d = new Date();
if (d.getSeconds() % 3 == 0) {
//alert('this suppose to happen only in about every 3 seconds');
target = source.substring(0, pos);
mayGoOn = true;
return;
}
}
}
textticker();
</script>
You're obviously doing it wrong. Take a look at this.
var message = "Hello World!";
function print(msg, idx) {
if(!idx) {
idx = 0;
}
$('#hello').html(msg.substring(0, idx));
if(idx < msg.length) {
setTimeout(function() { print(msg, idx + 1) }, 200);
}
}
print(message);
Demo: http://jsbin.com/evehus

Categories