I'm working on a piece of code from an open source library called gvalidator. The following checkbox validate function only works when I have two or more checkboxes. For some reason the if(elements[i]checked) line is not returning true when elements only has 1 object in the array.
Anyone have a guess as to why this is happening? Thanks!
this.validate = function() {
// Check if the form has a value set for this checkbox
// by cycling through all of the checkboxes
var elements = document.forms[0].elements[this.field.name];
if(undefined == elements.length){
x = elements;
elements = new Array(x);
}
for (i = 0; i < elements.length; i++) {
if (elements[i].checked) {
document.write(elements[i].name);
this.setState(ONEGEEK.forms.FIELD_STATUS_OK);
return true;
} else {
if (this.modified !== true || !this.isRequired) {
this.setState(ONEGEEK.forms.FIELD_STATUS_INFO);
} else {
this.setState(ONEGEEK.forms.FIELD_STATUS_EMPTY);
}
}
}
return false;
};
Jan was right... almost. The following is required in the function validate as the the form.elements function won't always return an array - it returns an element in the case there is only 1 match:
// Check if the form has a value set for this checkbox
// by cycling through all of the checkboxes
var elements = document.forms[0].elements[this.field.name];
if (elements.length === undefined) {
elements = [ elements ];
}
It is also required in the setup function before it adds the validation events in the first place:
this.setup = function() {
...
// Add events to ALL of the items
var elements = document.forms[0].elements[this.field.name];
if (elements.length === undefined) {
elements = [ elements ];
}
for (i = 0; i < elements.length; i++) {
_du.addEvent(elements[i], 'click', this.applyFieldValidation(this));
_du.addEvent(elements[i], 'click', this.applyContextInformation(this));
_du.addEvent(elements[i], 'change', this.applyFieldModification(this));
}
}
I have updated the source code at code http://code.google.com/p/gvalidator/, the latest binary is available for download here: http://code.google.com/p/gvalidator/downloads/list.
There are some serious and some minor flaws in your code. This is how it should look like. Test this code and tell me if it still does not work and provide any error messages in the error console.
this.validate = function () {
// Check if the form has a value set for this checkbox
// by cycling through all of the checkboxes
var elements = document.forms[0].elements[this.field.name];
if (elements.length === undefined) {
elements = [ elements ];
}
for (var i = 0, ii = elements.length; i < ii; ++i) {
if (elements[i].checked) {
document.write(elements[i].name);
this.setState(ONEGEEK.forms.FIELD_STATUS_OK);
return true;
} else {
if (this.modified !== true || !this.isRequired) {
this.setState(ONEGEEK.forms.FIELD_STATUS_INFO);
} else {
this.setState(ONEGEEK.forms.FIELD_STATUS_EMPTY);
}
}
}
return false;
};
Related
I just started learning JavaScript, and I am trying to get two different EventListeners to do the opposite function. Right now, I have it so that you can click on a mark and then a word, letter, or space and the mark appears/disappears there. I want to be able to click a word, letter, or space then click on a mark to add/remove it. Sentence Punctuation Marks I've tried switching the .querySelector and .querySelectorAll, but that doesn't work. Any help would be much appreciated.
var classlist = el.querySelectorAll(".letter, .space");
for (var i = 0; i < classlist.length; i++) {
classlist[i].addEventListener("click", function(event) {
var element = this.parentNode;
console.log(this);
if (
tooltype === "longVowel" ||
tooltype === "shortVowel" ||
this.classList.contains("space") === true
) {
element = this;
console.log(element);
}
var add = true;
var checklist = element.querySelectorAll("." + tooltype);
if (checklist.length > 0) {
add = false;
}
socket0s6.emit("action", {
slide: demo6,
action: "markingWords",
element: element.id,
class: tooltype,
add: add,
});
});
}
var classlist = el.querySelector(".toolbar").querySelectorAll("li");
for (var i = 0; i < classlist.length; i++) {
classlist[i].addEventListener("click", function(event) {
tooltype = this.className;
});
}
document.getElementById("slideContainer").appendChild(el);
/*}
//var oReq = new XMLHttpRequest();
//oReq.addEventListener("load", reqListener);
//oReq.open("GET", "slides/lesson0/slide6.html");
//oReq.send();*/
/*************** Server action ******************/
//socket0s6.on('action', function(details) {
var socket0s6 = {
emit: function(a, details) {
// //console.log(details[1]);
if (details.slide === demo6 && details.action === "markingWords") {
//document.getElementById(details.element).classList.toggle("active");
if (details.add) {
var el = document.createElement("span");
el.className = details.class;
document.getElementById(details.element).appendChild(el);
} else {
//where we will put code to find and remove existing marks
var markList = document
.getElementById(details.element)
.querySelectorAll("." + details.class);
console.log(markList);
for (var i = 0; i < markList.length; i++) {
markList[i].parentNode.removeChild(markList[i]);
}
}
}
},
};
When setting value of object to true it looks and seems it changed it but I still cant use it(as it stayed false).
validateNextMove() {
Card.setArrayNextMoveValid(this.cardRepository.findAll(), false);
let client = this.clientRepository.findByTurn(true);
let provjera = 0;
if (client instanceof UNOClient) {
let cards = client.getCards();
for (let i = 0; i < cards.length; i++) {
if (this.cardCanBePlaced(cards[i])) {
provjera++;
cards[i].setNextMoveValid(true);
console.log(cards[i].getNextMoveValid());
console.log(provjera);
}
}
if (provjera == 0) {
for (let i = 0; i < cards.length; i++) {
cards[i].setNextMoveValid(true);
console.log(cards[i].getNextMoveValid());
console.log(provjera);
}
}
How do I fix this ?
this is my method for checking if card can be place:
cardCanBePlaced(card){
let current = this.discardDeck.slice(-1)[0];
if(typeof current === 'undefined'){
return true;
}
//Check if card is allowed
if(
card.getColor() === current.getColor()
){
return true;
}
return false;
}
if in above mtehod i add global variable to count if there is any available it still doesnt make it work, something like this(counter++ if there is available card of that color)
if(card.getColor()!= current.getColor() && counter==0){
return true;
}
In my HTML page i have table in which each row, there is a check box.
My requirement is if more then one row is selected i.e. if the array length is 2, a toaster message has to be shown.
I got a use case there and it is,
if i select 2 rows(array length is 2), message is showing .
Then select 3rd row(array length is 3) and again deselect 3rd row(array length is 2 again).
Now also it shows the message. Here i don't want that toast.
My approach is :
$scope.toggleOne = function () {
if ($scope.selectedUsers.length === 2) {
showMessage();
}
for (var j = 0; j < $scope.users.length; j++) {
if (!$filter('filter')($scope.selectedUsers, $scope.users[j].id, true).length) {
$scope.selectAllCheckboxOfUsers = false;
return;
}
}
$scope.selectAllCheckboxOfUsers = true;
}
If you want to display the message just when going from 1 selected to 2 selected, you can check for that:
var previousSelectedNum = 0;
$scope.toggleOne = function () {
if ($scope.selectedUsers.length === 2 && previousSelectedNum === 1) {
showMessage();
}
// ...
previousSelectedNum = $scope.selectedUsers.length;
}
You can use a flag such as,
var isMessageShown = false;
Then in your function use as,
$scope.toggleOne = function () {
if($scope.selectedUsers.length === 1){
isMessageShown = false;
}
if ($scope.selectedUsers.length === 2 && !isMessageShown) {
isMessageShown = true;
showMessage();
}
for (var j = 0; j < $scope.users.length; j++) {
if (!$filter('filter')($scope.selectedUsers, $scope.users[j].id, true).length) {
$scope.selectAllCheckboxOfUsers = false;
return;
}
}
$scope.selectAllCheckboxOfUsers = true;
}
I have this for loop, and I would like to execute the else in the for loop only if none of the if conditions are met. The for loop runs until every item in the database has been checked. If none of the items in the database matches the user input then I want to run the else.
Right now, it runs the else right after the first try which means if the item matches is in the last row, it will just throw it in the error page since it stops the evaluation at the first iteration.
for(var i=0; i< rows.length; i++) {
if (rows[i].hashtag == userEnteredHashtag) {
// Display the choose Box page
res.render('chooseBox', {});
}
else {
// Display the invalid hashtag page
res.render('invalidHashtag', {});
}
}
Just move the else portion outside of the loop and execute it based on a flag
var wasFound = false;
for (var i = 0; i < rows.length; i++) {
if (rows[i].hashtag == userEnteredHashtag) {
// ...
wasFound = true; // set the flag here
}
}
if (!wasFound) {
res.render('invalidHashtag', {});
}
So add a check outside.
var hasMatch = false;
for (var i = 0; i < rows.length; i++) {
if (rows[i].hashtag == userEnteredHashtag) {
// Display the choose Box page
res.render('chooseBox', {});
hasMatch = true;
}
}
if (!hasMatch) {
// Display the invalid hashtag page
res.render('invalidHashtag', {});
}
Create a variable to track whether your condition has been met:
var isValid = true;
for(var i=0; i< rows.length; i++) {
if (rows[i].hashtag != userEnteredHashtag) {
isValid = false
}
}
isValid ? res.render('chooseBox') : res.render('invalidHashtag')
Another way to do it is to use filter and forEach.
var rows = [{hashtag: '#a'}, {hashtag: 'b'}, {hashtag: 'c'}];
var userEnteredHashTag = '#a';
var matchingRows = rows.filter(row => row.hashtag === userEnteredHashTag);
if (matchingRows.length) {
matchingRows.forEach(row => console.log(row));
} else {
console.log('invalid');
}
I am currently having some issues with the innerHTML function in a little javascript project. Essentially, I have a few HTML form checkboxes which change a number (that is displayed on the same page) depending on whether they are checked or not. The idea is very much like an IP address. The result is a number between 0 and 255.
What I want to do however is that whenever the user clicks on a checkbox, I need that number to change dynamically. Idea resembles the concept that is used when we write a question on this forum. As you type, the text below changes dynamilly to show exactly what is changed as it changes.
My code isn't working too well. Could you help me please? It keeps giving me the message "undefined" instead of the sum. Thanks for your help.
JavaScript
function displayOctets01(){
var octet01 = new Array(8);
octet01[0] = document.getElementById('octect0101');
octet01[1] = document.getElementById('octect0102');
octet01[2] = document.getElementById('octect0103');
octet01[3] = document.getElementById('octect0104');
octet01[4] = document.getElementById('octect0105');
octet01[5] = document.getElementById('octect0106');
octet01[6] = document.getElementById('octect0107');
octet01[7] = document.getElementById('octect0108');
var firstOctect;
if(octet01[0]==true){
firstOctect+=1;
}
else if(octet01[1]==true){
firstOctect+=2;
}
else if(octet01[2]==true){
firstOctect+=4;
}
else if(octet01[3]==true){
firstOctect+=8;
}
else if(octet01[4]==true){
firstOctect+=16;
}
else if(octet01[5]==true){
firstOctect+=32;
}
else if(octet01[6]==true){
firstOctect+=64;
}
else if(octet01[7]==true){
firstOctect+=128;
}
document.getElementById("octets01").innerHTML = firstOctect;
}
else if(octet01[7]==true){
firstOctect+=128;
}
document.getElementById("octets01").innerHTML = firstOctect;
}
I suspect that something might be wron with how I am handling the variables.
DEMO: http://jsfiddle.net/3TyV3/
The first problem is that the firstOctet variable isn't initialized. That needs to be set to 0 at the beginning of your function. Also, without knowing the purpose of your program, it seems that you don't want to be using else if - you need to check every checkbox. Also, you shouldn't be comparing the element with == true, you should check its checked property Also, your jsFiddle was set to run onLoad, so the function wasn't globally available. Finally, you didn't have an element with the id "octets01" to output to. Try this:
function displayOctets01() {
var octet01 = [],
firstOctect = 0;
octet01[0] = document.getElementById('octect0101');
octet01[1] = document.getElementById('octect0102');
octet01[2] = document.getElementById('octect0103');
octet01[3] = document.getElementById('octect0104');
octet01[4] = document.getElementById('octect0105');
octet01[5] = document.getElementById('octect0106');
octet01[6] = document.getElementById('octect0107');
octet01[7] = document.getElementById('octect0108');
if (octet01[0].checked === true) {
firstOctect += 1;
}
if (octet01[1].checked === true) {
firstOctect += 2;
}
if (octet01[2].checked === true) {
firstOctect += 4;
}
if (octet01[3].checked === true) {
firstOctect += 8;
}
if (octet01[4].checked === true) {
firstOctect += 16;
}
if (octet01[5].checked === true) {
firstOctect += 32;
}
if (octet01[6].checked === true) {
firstOctect += 64;
}
if (octet01[7].checked === true) {
firstOctect += 128;
}
document.getElementById("octets01").innerHTML = firstOctect;
}
DEMO: http://jsfiddle.net/3TyV3/2/
Although I won't lie, I'd reorganize some things. Here's how I would do it:
window.onload = function () {
var checkboxes = document.querySelectorAll('[name="featuresOctet01"]'),
i;
for (i = 0; i < checkboxes.length; i++) {
addEvent(checkboxes[i], "click", clickHandler);
}
};
function addEvent(element, eventName, callback) {
if (element.addEventListener) {
element.addEventListener(eventName, callback, false);
} else if (element.attachEvent) {
element.attachEvent("on" + eventName, callback);
} else {
element["on" + eventName] = callback;
}
}
function clickHandler() {
var firstOctect = 0,
checkboxes = document.querySelectorAll('[name="featuresOctet01"]'),
i, cur;
for (i = 0; i < checkboxes.length; i++) {
cur = checkboxes[i];
if (cur.checked) {
firstOctect += Math.pow(2, i);
}
}
document.getElementById("octets01").innerHTML = firstOctect;
}
DEMO: http://jsfiddle.net/3TyV3/3/
It uses unobtrusive JavaScript by binding the events in JavaScript, not the inline HTML. I did use the click event instead of change because old versions of IE has weird behavior for it with checkboxes/radio buttons. The addEvent function is just a simple function for binding events in new browsers as well as old IE.
It selects all elements with the name "featuresOctet01" and adds the event to each. Then, in the handler, it loops through each checkbox, sees if it's checked, and then adds a value based on 2^i.
References:
addEventListener: https://developer.mozilla.org/en-US/docs/DOM/EventTarget.addEventListener
document.querySelectorAll: https://developer.mozilla.org/en-US/docs/DOM/Document.querySelectorAll
Math.pow: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Math/pow