what is the difference, in using class vs addClassName jscript?
in a for loop, whenever I was adding a class to the existing class, then after each loop cycle it was adding new class to it. So condition to enter the loop was changing after each time.
when I used class instead of addClassName then everything started to work as it should be. Which is after each reverse session the loop was matching the condition.
How it can be explained?
WORKING VERSION:
for (var i = 0; i < fields.length; i++) //instead of .each
{
alert(0.5);
alert(fields[i].className);
if (fields[i].className == 'text' || fields[i].className == 'date' || fields[i].className == 'number' || fields[i].className == 'text error' || fields[i].className == 'date error' || fields[i].className == 'number error' || fields[i].className == 'text valid' || fields[i].className == 'date valid' || fields[i].className == 'number valid' || fields[i].className == 'text valid error' || fields[i].className == 'date valid error' || fields[i].className == 'number valid error' )
{
alert(0.3);
var val = fields[i];
var classname = "";
if(val.value.length <= 4) {
classname = fields[i].className + " error";
fields[i].class = classname;
Effect.Shake(fields[i], { times:3 }, 50);
errorString = 'Please complete all required fields.';
alert(0.6);
alert(val.value);
alert(0.66);
alert(fields[i].name);
alert(val.value.class);
//error++;
}
else {
classname = fields[i].className + " valid";
fields[i].class = classname;
alert(8.5);
alert(val.value.class);
}
}
alert(8.8);
alert(fields[i].class);
}
VERSION WHICH IS NOT WORKING:
for (var i = 0; i < fields.length; i++) //instead of .each
{
if (fields[i].className == 'text' || fields[i].className == 'date' || fields[i].className == 'number' || fields[i].className == 'text error' || fields[i].className == 'date error' || fields[i].className == 'number error' )
{
var val = fields[i];
if(val.value.length <= 4) {
fields[i].addClassName('error');
Effect.Shake(fields[i], { times:3 }, 50);
errorString = 'Please complete all required fields.';
error++;
} else {
fields[i].addClassName('valid');
}
}
}
Explanation
class is a reserved keyword (for possible future use), therefore it should not be used as object attribute (like someobject.reservedKeyword) and therefore className instead of class is used as nnnnnn points out in the comment to your question.
In your code, this won't work:
fields[i].class = classname
...but this one will
fields[i].className = classname
This is the source code of prototypejs addClassName
function addClassName(element, className) {
if (!(element = $(element))) return;
if (!hasClassName(element, className))
element.className += (element.className ? ' ' : '') + className;
return element;
}
see the prototypejs link
Solution
Therefore use addClassName, removeClassName and hasClassName. In your code:
for (var i = 0; i < fields.length; i++) {
if(fields[i].hasClassName("text") || fields[i].hasClassName("number") || fields[i].hasClassName("date")) {
if(fields[i].value.length<=4) {
fields[i].addClassName("error");
fields[i].removeClassName("valid");
Effect.Shake(fields[i], { times:3 }, 50);
errorString = 'Please complete all required fields.';
}
else {
fields[i].addClassName("valid");
fields[i].removeClassName("error");
}
}
}
Note: in modern browsers we use classList attribute instead:
prototype.js | modern browsers
---------------------------------------------------------------------
element.hasClassName("someclass") | element.classList.contains("someclass")
element.addClassName("someclass") | element.classList.add("someclass")
element.removeClassName("someclass") | element.classList.remove("someclass")
addClassName is the prototypejs way of adding a class to an HTML element.
If you have been assigning to $('something').class what you did is add a property to that object in particular, each time you set it to that object it would be replaced, if you create a new object that refers to the same element it will not have that property and - of course - it will not be tied to the class of the HTML element.
Related
I have a drop down menu, and when I select the 'All' option, it gives me this error on the console:
TypeError: Cannot read property '0' of undefined
at n.$scope.onSearchByChanged (http://localhost:8080/js/jenkinsVersion/directives/assignment-filter.js:70:81)
So, I went to my script, function, line 70,character 81 :
$scope.onSearchByChanged = function () {
if ($scope.filter.list.searchBy == 'DEPARTMENT_CODE' && !$scope.filterScope.departments) {
$scope.loadDepartments();
} else if ($scope.filter.list.searchBy != 'DEPARTMENT_CODE') {
$scope.filter.list.departmentId = 0;
}
if ($scope.filter.list.searchBy == 'GROUP' && !$scope.filterScope.editorGroups) {
$scope.loadEditorGroups();
} else if ($scope.filter.list.searchBy != 'GROUP') {
$scope.filter.list.groupId = $scope.filterScope.editorGroups[0].id; //line 70
}
$scope.clearFilter('text');
};
if ($scope.filter.list.searchBy == 'GROUP' && !$scope.filterScope.editorGroups) {
$scope.loadEditorGroups();
}
if ($scope.filter.list.searchBy == 'DEPARTMENT_CODE' && !$scope.filterScope.departments) {
$scope.loadDepartments();
}
$scope.isStatusSelected = function (status) {
return _.indexOf($scope.filter.list.talentAssignmentStatuses, status) > -1;
};
$scope.selectTalentAssignmentStatus = function (status) {
$scope.clearFilter('text');
if ($scope.isStatusSelected(status)) {
_.remove($scope.filter.list.talentAssignmentStatuses, function (el) {
return status == el;
});
} else {
$scope.filter.list.talentAssignmentStatuses.push(status);
}
};
here is the loadEditorGroups function :
$scope.loadEditorGroups = function () {
Reference.getEditorGroups($scope, function (response) {
$scope.filterScope.editorGroups = response.list;
if ($scope.filterScope.editorGroups.length > 0) {
$scope.filter.list.groupId = $scope.filterScope.editorGroups[0].id
}
});
};
I'm still learning JS. Why is this error being thrown? When I change the value of the item I want to retrieve from that editorGroups list it just gives me the same error but with the corresponding number. Your help would be appreciated, please let me know if I can supply further information. Thank you!
Your logic for this if-else block is probably wrong:
if ($scope.filter.list.searchBy == 'GROUP' && !$scope.filterScope.editorGroups) {
$scope.loadEditorGroups();
} else if ($scope.filter.list.searchBy != 'GROUP') {
$scope.filter.list.groupId = $scope.filterScope.editorGroups[0].id; //line 70
}
The program will enter the else if block when both:
the if condition is false, that is: ($scope.filter.list.searchBy == 'GROUP' && !$scope.filterScope.editorGroups) == false
the else if condition is true, that is: ($scope.filter.list.searchBy != 'GROUP') == true
We can take these two statements and simplify them:
!($scope.filter.list.searchBy == 'GROUP' && !$scope.filterScope.editorGroups) && ($scope.filter.list.searchBy != 'GROUP')
($scope.filter.list.searchBy != 'GROUP' || $scope.filterScope.editorGroups) && ($scope.filter.list.searchBy != 'GROUP')
($scope.filter.list.searchBy != 'GROUP')
In step 2, I applied De Morgan's law to simplify !(A && B) to (!A || !B).
In step 3, I simplified the &&, since (A || B) && A is the same as just A.
So really, all we know when we enter the else if block is that searchBy != 'GROUP'. We do not know anything about editorGroups, and indeed, it may be undefined!
What you're probably looking for is:
if ($scope.filter.list.searchBy == 'GROUP' || !$scope.filterScope.editorGroups) {
$scope.loadEditorGroups();
} else if ($scope.filter.list.searchBy != 'GROUP') {
$scope.filter.list.groupId = $scope.filterScope.editorGroups[0].id;
}
Notice the || in the if condition. This ensures that the else if is executed only when ($scope.filter.list.searchBy != 'GROUP' && $scope.filterScope.editorGroups), so that editorGroups[0] will not give an error. I don't know enough if this is what you intended this code to do, so correct me when I'm wrong. :-)
70:81 means line 70, character 81.
The problem is at editorGroups[0]: If editorGroups is undefined, it cannot read editorGroups[0] because undefined has no property called 0.
Make sure that editorGroups isn't undefined and you'll be fine!
I have an If statement that using || with an && operator e.g if((a || b) && c) however it is only works with the first condition i.e a but not with second i.e b even though running the debugger I can see that the condition is met and it goes to the correct line of code. Is there a better way to get this to work on both conditions?
code I have now:
function _getCatFormGUID(catName) {
debugger;
var dept = Browser.getValue(getElement("126D81CA203C21CF014C8A3550227892FE4B4A6A"));
if((catName == '1' && dept == "Entwicklung") || (catName == '7' && dept == "Entwicklung")){
return "A270AE7F957A74EF0842403EEA0032017567F3E8";
}
if((catName == '1' && dept != "Entwicklung") || (catName == '7' && dept != "Entwicklung")) {
return "8EDD0768A7CDF8FD8AE90DB473F41EF0B33FA14F";
}
return "";}
I have tried the following also:
if((catName == '1' || catName == '7') && dept == "Entwicklung"){
return "A270AE7F957A74EF0842403EEA0032017567F3E8";
}
and
if(catName == '1' && dept == "Entwicklung"){
return "A270AE7F957A74EF0842403EEA0032017567F3E8";
}
if(catName == '7' && dept == "Entwicklung"){
return "A270AE7F957A74EF0842403EEA0032017567F3E8";
}
It only returns for catName =='1'.
If I understood your problem correctly, I will write your first bit of code as bellow
function _getCatFormGUID(catName) {
var dept = Browser.getValue(getElement("126D81CA203C21CF014C8A3550227892FE4B4A6A"));
if (catName == '1' || catName == '7') {
if(dept == 'Entwicklung'){
return "A270AE7F957A74EF0842403EEA0032017567F3E8";
}
else{
return "8EDD0768A7CDF8FD8AE90DB473F41EF0B33FA14F";
}
}
else{
return "";
}
}
The problem is that you have to understand how those 2 logical operators do the comparison: because your first condition catName == '1' is true, it will never go to second conditions from the first parenthesis nor in the second paranthesis.Given your example, you might rewrite your logical condition from:
if((catName == '1' && dept == "Entwicklung") || (catName == '7' && dept == "Entwicklung")){
return "A270AE7F957A74EF0842403EEA0032017567F3E8";
}
to
if(dept == "Entwicklung" && catName == '1' || catName == '7'){ return something; }
}
I have a form that submits using jquery, everythinh works fine. If the there is an error the browser displays the error. But the problem is if the form is resubmitted the error wont change. Either to nothing or a different message.
<script>
$(document).ready(function(e) {
$('#addNew').submit(function(e) {
event.preventDefault();
var err_count = 0;
var name_err = '';
var name_err_count = 0;
if($('#f_name').val() === ''){
err_count++;
name_err_count++;
name_err = "You need a first name";
}else{
name_err = '';
}
if($('#l_name').val() === ''){
err_count++;
name_err_count++;
if(name_err_count > 0){
name_err += " and a last name.";
}else{
name_err += "You need a last name";
}
}else{
name_err = '';
}
$('#name_err').replaceWith(name_err);
});
});
</script>
<select id="prefix"><option>Mr</option><option>Mrs</option><option>Miss</option><option>Ms</option></select> <input type="text" id="f_name" name="f_name" placeholder="First Name" /> <input type="text" id="l_name" name="l_name" placeholder="Family Name" /><br />
<div class="form_err" id="name_err"></div>
There are 4 problems with your code, let's tackle them in order of appearance:
You passed the event as variable e to your submit-function, so variable event is undefined:
$('#addNew').submit(function(e) {
event.preventDefault();
undefined.preventDefault(); is obviously going to crash your function upon execution (so that's why it 'does not work': everything after that statement is not executed).
Fix:
$('#addNew').submit(function(event) { // or just `e` instead of `event`
event.preventDefault(); // or just `e` instead of `event`
Then you have:
err_count++;
name_err_count++;
if(name_err_count > 0){
name_err_count will be always be > 0 since you have just (post-)incremented it..
Solution: increment your error-counter(s) after your check:
if (name_err_count > 0) { //you could omit the `> 0` check and inverse if/else
// logic here
} else {
// logic here
}
err_count++;
name_err_count++;
Next, you end with an else on your Last Name if-check:
}else{
name_err = '';
}
Thus, if the value of element#l_name is set (so not '') your name_err string will be cleared to '', even if it held an error-message generated by your previous first name check..
Fix: delete it (since your name_err was already an empty string upon initialization and not filled by other error-messages if none of them apply).
Also have a look at If vs. else if vs. else statements?
Finally, by using $('#name_err').replaceWith(name_err); you replace the element #name_err with an un-identified textnode (containing your error-message). When the function runs the next time, there is no #name_err element to replace.
To fix this you should use elm.html() (or less preferably elm.text())
Also have a look at this answer: What's the difference between jQuery's replaceWith() and html()?
So (applying above fixes) here is your corrected code (jsfiddle here):
$(document).ready(function (e) {
$('#addNew').submit(function (event) {
event.preventDefault();
var err_count = 0;
var name_err = '';
var name_err_count = 0;
if ($('#f_name').val() === '') {
name_err = 'You need a first name';
err_count++;
name_err_count++;
}
if ($('#l_name').val() === '') {
if (name_err_count > 0) {
name_err += ' and a last name.';
} else {
name_err += 'You need a last name';
}
err_count++;
name_err_count++;
}
$('#name_err').html(name_err);
});
});
PS, you could delete the name_error_count and just check if your name_err evaluates to TRUE or FALSE (empty strings evaluate to FALSE in javascript) in conjunction with a ternary (and some more optimizations) for simpler/easier to read code.
$(document).ready(function(e) {
$('#addNew').submit(function(event) {
var err_count = 0,
name_err = '';
event.preventDefault();
if ($('#f_name').val() === '') {
name_err = 'a first name';
err_count++;
}
if ($('#l_name').val() === '') {
name_err += (name_err ? ' and ' : '')
+ 'a last name';
err_count++;
}
// example of simply adding a check (for a hobby)
// if ($('#hobby').val() === '') {
// name_err += (name_err ? ' and ' : '')
// + 'a hobby';
// err_count++;
// }
$('#name_err').html( name_err ? 'You need ' + name_err : '' );
});
});
Example jsfiddle here.
Another approach would be to use an array to hold your partial error-messages (that were added to it using arr.push()). That way you can keep track/count of the error's (per section if you'd wanted, like name) by using arr.length and convert them to a string using arr.join(' and ') even whilst outputting your string: (arr.length ? 'You need ' + arr.join(' and ') : '')
Note: this way you could also simply obtain you total number of errors by doing err_count+=arr_section_err.length; after each check-block. In other words, err_count++; in every check could then also be deleted.
That would look like this:
$(document).ready(function(e) {
$('#addNew').submit(function(event) {
var err_count = 0,
name_err = [];
event.preventDefault();
if($('#f_name').val() === '') name_err.push('a first name');
if($('#l_name').val() === '') name_err.push('a last name');
// if($('#hobby').val() === '') name_err.push('a hobby'); // TRIVIAL
err_count+=name_err.length;
$('#name_err').html( name_err.length
? 'You need ' + name_err.join(' and ')
: ''
);
});
});
Example jsfiddle here.
As I have just explained that an empty string is falsy in javascript, then
if($('#f_name').val() === '') name_err.push('a first name');
equals
if(!($('#f_name').val())) name_err.push('a first name');
which equals
$('#f_name').val() || name_err.push('a first name');
$('#l_name').val() || name_err.push('a last name'); // showcasing the beauty
$('#hobby').val() || name_err.push('a hobby'); // note alignment on ||
Example jsfiddle here. Pretty elegant and simple if you ask me.
As you see, you could continue to build your error-message dynamically as you originally intended (contrary to using if/else structures that (repeatedly) check (combinations of) element-values and having complete static strings for every combination (as someone else suggested) resulting in an exponential increase in 'work' (check's and DOM-access) and a rather unmaintainable 'spaghetti'-code when checking for example just 5 elements..).
Hope this helps!
Actually, this should be an else if.
$(document).ready(function (e) {
$('#addNew').submit(function (e) {
e.preventDefault();
if($('#f_name').val() === '' && $('#l_name').val() === ''){
name_err = " You need a first and a last name.";
}else if($('#l_name').val() === '' && $('#f_name').val() !== ''){
name_err = "You need a last name";
}else if($('#l_name').val() !== '' && $('#f_name').val() === ''){
name_err = "You need a first name";
}else{
name_err = 'Looks Good';
}
$('#name_err').html(name_err);
});
});
…now with rock solid else if.
http://jsfiddle.net/VS3Ya/2/
Try this,
<script>
var err_count ;
var name_err;
var name_err_count;
$(document).ready(function(e) {
$('#addNew').submit(function(e) {
event.preventDefault();
initializeVariables();
if($('#f_name').val() === ''){
err_count++;
name_err_count++;
name_err = "You need a first name";
}
else{
name_err = '';
}
if($('#l_name').val() === ''){
err_count++;
name_err_count++;
if(name_err_count > 0){
name_err += " and a last name.";
}
else{
name_err += "You need a last name";
}
}
else{
name_err = '';
}
$('#name_err').replaceWith(name_err);
});
});
function initializeVariables(){
err_count = 0;
name_err = '';
name_err_count = 0;
}
</script>
I think the problem is that the variables are still holding onto the values. I am not sure about the .html() or .replaceWith(), but going by the discussion, .html() seems to be the way.
See the bottom of this post;
function isVowel(aCharacter)
{
return ((aCharacter == 'a') || (aCharacter == 'A')||
(aCharacter == 'e') || (aCharacter == 'E')||
(aCharacter == 'i') || (aCharacter == 'I')||
(aCharacter == 'o') || (aCharacter == 'O')||
(aCharacter == 'u') || (aCharacter == 'U')||
(aCharacter == 'y') || (aCharacter == 'Y'));
}
function myF(aString)
{
// variable to hold resultString
var resultString = '';
// variable to hold the current and previous characters
var currentCharacter = '';
var precedingCharacter = '';
// in the case of the first character in the string there is no
// previous character, so we assign an empty string '' to the variable at first
//precedingCharacter = '';
// TODO part (ii)
// add code as directed in the question
var i = 0;
for( i; i < sString.length; ++i)
{
currentCharacter = sString.charAt(i);
if (isVowel(currentCharacter) && (!isVowel(precedingCharacter)))
{
resultString = resultString + 'ub';
}
resultString = resultString + currentCharacter;
precedingCharacter = currentCharacter;
}
return resultString;
}
var string1 = "the cat sat on the mat";
var result1 = myF(string1);
document.write(string1);//THIS ISN'T GOING TO BE DISPLAYED, BUT WHY?
document.write('<BR>');
document.write(result1);
You iterate on sString wich doesn't exist and not on your parameter aString.
Where is sString being declared in your function? Try with aString (or declare var sString = aString) and try again.
Please change function myF(aString) to function myF(sString)
There is a naming mistake. Here is a working copy of your code .
http://jsfiddle.net/hXarY/
You can try using "firebug" to catch such errors if you do not already do.
function isVowel(aCharacter)
{
return ((aCharacter == 'a') || (aCharacter == 'A')||
(aCharacter == 'e') || (aCharacter == 'E')||
(aCharacter == 'i') || (aCharacter == 'I')||
(aCharacter == 'o') || (aCharacter == 'O')||
(aCharacter == 'u') || (aCharacter == 'U')||
(aCharacter == 'y') || (aCharacter == 'Y'));
}
function myF(sString) // this should be sString , not aString
{
// variable to hold resultString
var resultString = '';
// variable to hold the current and previous characters
var currentCharacter = '';
var precedingCharacter = '';
// in the case of the first character in the string there is no
// previous character, so we assign an empty string '' to the variable at first
//precedingCharacter = '';
// TODO part (ii)
// add code as directed in the question
var i = 0;
for( i; i < sString.length; ++i)
{
currentCharacter = sString.charAt(i);
if (isVowel(currentCharacter) && (!isVowel(precedingCharacter)))
{
resultString = resultString + 'ub';
}
resultString = resultString + currentCharacter;
precedingCharacter = currentCharacter;
}
return resultString;
}
var string1 = "the cat sat on the mat";
var result1 = myF(string1);
document.write(string1);//THIS ISN'T GOING TO BE DISPLAYED, BUT WHY?
document.write('<BR>');
document.write(result1);
I understand that we can use (javascript)
if (typeof textbox === "object") { }
but are there methods which will allow me to ensure that the object is a textbox?
var isInputText = obj instanceof HTMLInputElement && obj.type == 'text';
As of 2016, use this:
function isTextBox(element) {
var tagName = element.tagName.toLowerCase();
if (tagName === 'textarea') return true;
if (tagName !== 'input') return false;
var type = element.getAttribute('type').toLowerCase(),
// if any of these input types is not supported by a browser, it will behave as input type text.
inputTypes = ['text', 'password', 'number', 'email', 'tel', 'url', 'search', 'date', 'datetime', 'datetime-local', 'time', 'month', 'week']
return inputTypes.indexOf(type) >= 0;
}
Are you looking for something like this?
if(textbox.tagName && textbox.tagName.toLowerCase() == "textarea") {
alert('this is a textarea');
}
If you need to know if it's a text input, you can do this:
if(textbox.tagName && textbox.tagName.toLowerCase() == "input" && textbox.type.toLowerCase() == "text") {
alert('this is a text input');
}
If it's a text input you're looking for:
if (textbox.tagName == "input" && textbox.getAttribute("type") == "text") {
// it's a text input
}
If you're looking for a textarea
if (textbox.tagName == "textarea") {
// it's a textarea
}
if(textbox instanceof HTMLInputElement && textbox.getAttribute("type") == "text") {
alert("I'm an input text element");
}
I think perhaps you would want to get a reference to an element, and then check for the return value of .type i.e.
var element = document.getElementById('element_in_question');
if(element.type == "textarea"){
console.log('I must be textarea');
}