filtered rows in navigable table - javascript

UPDATE:
I finally found a solution (with a while loop, in code below) but there is a problem: when I navigate search results (so elements which are not hidden), after navigating a bit in filtered results, the navigation stops working and I get a "TypeError: rows[selectedRow] is undefined"
if(selectedRow >= rows.length){
selectedRow = 0;
} else if(selectedRow < 0){
selectedRow = rows.length-1;
}
This part works for the full list but not in the filtered list. I think the while loop is causing this. How can I fix this please ?
Navigation:
var rows = document.getElementById("pokemons-list").children[1].children;
var selectedRow = 0;
document.body.onkeydown = function(e){
//Clear out old row's color
rows[selectedRow].style.backgroundColor = "#FFFFFF";
//Calculate new row
if(e.keyCode == 38){
if(rows[selectedRow].style.display == "none"){
while(rows[selectedRow].style.display == "none"){
selectedRow--;
}
}else {
selectedRow--;
}
} else if(e.keyCode == 40){
if(rows[selectedRow].style.display == "none"){
while(rows[selectedRow].style.display == "none"){
selectedRow++;
}
}else {
selectedRow++;
}
} else if(e.keyCode == 13){
Pokemon_ID = selectedRow + 1;
document.getElementById("id-input").value = Pokemon_ID;
document.getElementById("id-input").click();
}
if(selectedRow >= rows.length){
selectedRow = 0;
} else if(selectedRow < 0){
selectedRow = rows.length-1;
}
//Set new row's color
rows[selectedRow].style.backgroundColor = "dodgerblue";
};

It looks like your filter function hides rows that don't match the string that you've entered. The hiding is implemented by setting the display property to "none".
When you navigate, can't you ignore table rows that have their display property set to "none"?
Update: You can check the value of rows[selectedRow].style.display before performing rows[selectedRow].style.backgroundColor = "dodgerblue". If the value is "none", repeat the change that you made to selectedRow within the function (whether it was an increment or a decrement).
Update 2: Consider the block of code below:
while(rows[selectedRow].style.display == "none"){
selectedRow++;
}
If the value of selectedRow on entering the while loop is 0 and rows[0].style.display has the value "none" then the body of the loop changes the value of selectedRow to -1. The control will immediately go back to the loop guard and it'll try to check the value of
rows[-1].style.display. This is something you want to avoid, so why don't you try checking selectedRow after every line where you change it? A quick solution would involve changing the loop-bodies of your while loops:
while(rows[selectedRow].style.display == "none"){
selectedRow++;
if(selectedRow >= rows.length){
selectedRow = 0;
}
}
and
while(rows[selectedRow].style.display == "none"){
selectedRow--;
if(selectedRow < 0){
selectedRow = rows.length-1;
}
}

Related

Set minimum required length of a text input field using javascript?

I want to be able to perform validation based on how many characters were entered by the user - I want there to be a minimum of 7 characters. (The maximum value is set using an HTML attribute) - I have tried the following:
v3 = document.getElementById("npo-registration-number");
flag3 = true;
if (val >= 3 || val == 0) {
if (v3.value == "") {
v3.style.borderColor = "red";
flag3 = false;
}
else if (v3.value.length === 7){
v3.style.borderColor = "green";
flag3 = true;
}
}
The above works to an extent. The input fields border colour will only show green if 7 characters are inputted. However, if i delete characters from that point onwards, the border remains green. Any help on the matter is appreciated.
I'm not entirely sure about what you want; is this close to what you are looking for?
You probably did this and didn't include it in your snippet, but we need this to run each time the form is edited. We add an event listener to the input.
const input = document.getElementById('npo-registration-number');
input.addEventListener('input', () => {
// set the border to red if the value is < 7 characters
if (input.value.length < 7) {
input.style.borderColor = 'red';
return;
}
// otherwise, set it to green
input.style.borderColor = 'green';
});
This fixes an issue: you do not set the color of the border to red unless the value of the form is an empty string. Rather, we want the border to be red whenever the input length goes below seven.
It's because of your condition
if (v3.value == "") {
v3.style.borderColor = "red";
flag3 = false;
}
When you start deleting characters in input, your input is not becoming red again because It's red only when there are no characters and it change to green after 7 characters inputed.
You need to capture the input event so js can evaluate and update.
https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/input_event
const ev3 = document.getElementById("npo-registration-number");
let flag3 = true;
ev3.addEventListener('input', (e) => {
const val = e.target.value;
if (val.length === 7){
ev3.style.borderColor = "green";
flag3 = true;
}
else {
ev3.style.borderColor = "red";
flag3 = true;
}
});
input {
outline: 0;
border: 1px solid;
}
<input id="npo-registration-number" type='text'>
You can just use button that will run this function for it, like send or post buttons(many sites use this method).
function click(){
v3 = document.getElementById("npo-registration-number");
flag3 = true;
if (val >= 3 || val == 0) {
if (v3.value == "") {
v3.style.borderColor = "red";
flag3 = false;
}
else if (v3.value.length === 7){
v3.style.borderColor = "green";
flag3 = true;
}
}
}
Try this please
v3 = document.getElementById("npo-registration-number");
flag3 = true;
if (v3.value == "") {
v3.style.borderColor = "red";
flag3 = false;
} else {
if (v3.value.length < 7){
v3.style.borderColor = "red";
flag3 = false;
}
else {
v3.style.borderColor = "green";
flag3 = true;
}
}

Hiding and unhiding a particular element

I'm trying to hide a particular element on my browser game.
When it reaches the point of being visible it has to stay visible.
At the moment I've tried a few approaches but none of them seem to do the last part which is keeping it visible when the number of clicks goes back under the amount needed to make it visible.
CSS:
upgrade3 {
display: none;
}
js1(which completely doesn't work):
function showPerk() {
if (clicks >= price3reached || totalupgradeperk3 > 0) {
do{
document.getElementById("upgrade3").style.display =="block";
}
while(document.getElementById("upgrade3".style.display === 'none'));
}
update();
}
js2 (works but hides the element when going under the amount needed):
if (blnhideperk = true) {
if (clicks >= price3reached || totalupgradeperk3 > 0) {
document.getElementById("upgrade3").style.display = "block";
blnhideperk === false;
} // use === its something wierd about js = / == / === all do different comparisons
else {
document.getElementById("upgrade3").style.display = "none";
}
}
upgrade
Try
document.getElementById("upgrade3").style.display = "none";
Note the 1 equal sign, not 2 or 3, as those have other uses.
if (blnhideperk = true){
if (clicks >= price3reached || totalupgradeperk3 > 0){
document.getElementById("upgrade3").style.display = "block";
blnhideperk === false;}}
and moving
document.getElementById("upgrade3").style.display = "block";
out of the loop istead of in the else statement
seemed to do the trick

Toggle Menus using buttons in JS - But it shows both menus

i want to toggle two menus offered by two buttons.the issue is when i click on button one, it shows the menu bound with button one but when i click the other, it shows both instead of hiding the first one and vice versa, on my login page. The menus are identified by the ids of; 'reqpwd' and 'signup' in html / JS. What is worng? also suggest improvement in code if possible. My JS code:
<script>
window.onload = function() {
document.getElementById('reqpwd').style.display = 'none';
document.getElementById('signup').style.display = 'none';
};
function chk(elm) {
var signup_ = signup.id;
var reqpwd_ = reqpwd.id;
elm_ = elm.id;
if (elm_ == reqpwd_){
hide(signup_);
show(reqpwd_);
}
if (elm_== signup_){
hide(reqpwd_);
show(signup_);
}
};
function show(abc) {
var menuBox = document.getElementById(abc);
if(menuBox.style.display == "none") { // if is menuBox displayed, hide it
menuBox.style.display = "block";
} };
function hide(abc){ // if is menuBox hidden, display it
var menuBox = document.getElementById(abc);
if(menuBox.style.display == "block"){
menuBox.style.display == "none";
}
};
</script>
Instead of menuBox.style.display == "none"; try using menuBox.style.visibility== "hidden";
Edit:
I have changed a few things in your code. Didn't make a whole lot of sense to me the way you're setting the styles on load (missing HTML), so I had to use IDs that made sense to me.
Edit:
Ok, my bad. I updated the code. I think the problem is on hide you're using double equals instead of single equals on menuBox.style.display == "none";. Thus the menu is never hiding.
https://codepen.io/juanferrer/pen/qmOmWa
Finally i have landed into something like this using the flag variable as a state indicator.. now the only requirement is to check toggle as well as disappear the relevant menu by the same button..i.e. if signup menu is already open, the signup or reset button should close it and vice versa.
window.onload = function() {
document.getElementById('regd').style.visibility = 'hidden'; //regisration msg
document.getElementById('rset').style.visibility = 'hidden'; //reset msg
document.getElementById('reqpwd').style.display = 'none';
document.getElementById('signup').style.display = 'none';
};
var flag = 0;
function chk(elm) {
var signup_ = signup.id;
var reqpwd_ = reqpwd.id;
elm_ = elm.id;
if (elm_ == reqpwd_ && flag === 0 || elm_ == reqpwd_ && flag == 2) {
flag = 1;
hide(signup_);
show(reqpwd_);
}
if (elm_ == signup_ && flag === 0 || elm_ == signup_ && flag == 1) {
flag = 2;
show(signup_);
hide(reqpwd_);
}
if (elm_ == reqpwd_ && flag == 1 || elm_ == signup_ && flag == 2) {
hide(elm_);
flag = 0;
}
};
function show(abc) {
var menuBox = document.getElementById(abc);
if (menuBox.style.display === "none") { // if is menuBox hidden, display it
menuBox.style.display = "block";
}
};
function hide(abc) { // if is menuBox
var menuBox = document.getElementById(abc);
if (menuBox.style.display === "block") { //if displayed, hide it
menuBox.style.display = "none";
}
};

jQuery method not finding selector

I am writing a simple jQuery function to pick up a selector from the html page and on keypress(up or down) should add a CSS class to it.
Problem is that it is not detecting the selector to add the class.
The HTML selector is nested deep into the code.
html
body
div.fixed-header
div#main-nav.primary-nav.navbar
div.navbar-inner
div.primary-nav-right-content
ul.nav
li#global-search
div.search-results
ul.search-dropdown
ul.search-entry
I am trying to detect the selector ul.search-entry in my jquery.
What I have right now in my javascript is this.
var selector = $('ul.search-entry');
var selected;
$(window).keydown(function(e){
if(e.which === 40){
if(selected){
selected.removeClass('selected');
next = selected.next();
if(next.length > 0){
selected = next.addClass('selected');
}else{
selected = selector.eq(0).addClass('selected');
}
}else{
selected = selector.eq(0).addClass('selected');
}
}else if(e.which === 38){
if(selected){
selected.removeClass('selected');
next = selected.prev();
if(next.length > 0){
selected = next.addClass('selected');
}else{
selected = selector.last().addClass('selected');
}
}else{
selected = selector.last().addClass('selected');
}
}
else{
}
});
I have been racking my head for too long and I know am missing something really small. Any thoughts?
Set selector to just the selector string, not the collection that results, and call jQuery to search for it when needed.
var selector = 'ul.search-entry';
var selected;
$(window).keydown(function(e){
if(e.which === 40){
if(selected){
selected.removeClass('selected');
next = selected.next();
if(next.length > 0){
selected = next.addClass('selected');
}else{
selected = $(selector).eq(0).addClass('selected');
}
}else{
selected = $(selector).eq(0).addClass('selected');
}
}else if(e.which === 38){
if(selected){
selected.removeClass('selected');
next = selected.prev();
if(next.length > 0){
selected = next.addClass('selected');
}else{
selected = $(selector).last().addClass('selected');
}
}else{
selected = $(selector).last().addClass('selected');
}
}
else{
}
});

Next/Previous button throws error

I keep getting the following error when I try to insert values by clicking the Next button on values that are already entered in.
Unable to get the value of the property '0': object is null or undefined.
I believe the error is happening at the last value in the array. I indicated the line below with a comment in the code. I want it to get the next value in the array but there isn't one created yet (it gets the next value just fine if the next value is not the last one in the array).
I think that is the reason it's throwing an object null. However, I can't seem to check for the null/undefined and set it using statements such as result[count+1][0] == undefined because it doesn't work! It always throws an error no matter what I do.
Some help would be much appreciated.
Test case:
Insert a value in text box 1 and text box 2
Click Next
Click Previous (in order to edit the values inserted above)
Change the values in the text boxes to something else
Click Next -- error happens
Code:
<html>
<head>
<script type="text/javascript"></script>
</head>
<body>
<script type="text/javascript">
var result = new Array();
var count = 0;
var input1 = new Array();
var input2 = new Array();
function move(direction) {
if(direction == 'next')
{
var rate1 = [document.getElementById("txt1").value];
var rate2 = [document.getElementById("txt2").value];
if (result.length == count){
if (rate1 == '' || rate2 == '') {
alert('you need to put in a value');
}
else {
result.push([[rate1], [rate2]]);
document.getElementById("txt1").value = '';
document.getElementById("txt2").value = '';
count++;
}
}
else {
try{
(result[count][0]) = document.getElementById("txt1").value;
(result[count][1]) = document.getElementById("txt2").value;
document.getElementById("txt1").value = result[count++][0]; //error happening here. trying to show next value but there isn't one created yet.
document.getElementById("txt2").value = result[count++][1];
document.getElementById("txt1").value = '';
document.getElementById("txt2").value = '';
}
catch(err) {
alert(err.description);
}
count++;
}
}
if (direction == 'prev')
{
if(count <= 0)
{
alert("no more elements");
}
else
{
var prev_val1 = (result[count - 1][0]);
document.getElementById("txt1").value = prev_val1;
var prev_val2 = (result[count - 1][1]);
document.getElementById("txt2").value = prev_val2;
count--;
}
}
document.getElementById("txtresult").value = result;
}
</script>
<li>text 1</li>
<input type="text" id="txt1"/>
<br>
<li>text 2</li>
<input type="text" id="txt2"/>
<br>
<input type="button" id="btn" value="next" onclick="move('next')" />
<input type="button" id="btnprevious" value="previous" onclick="move('prev')" />
<br>
<input type="text" id="txtresult"/>
</body>
</html>
You can add a check like this:
if (typeof result[count++] === "undefined") { /* do or do not */ };
Right before:
document.getElementById("txt1").value = result[count++][0];
function move(direction) {
if(direction == 'next')
{
var rate1 = [document.getElementById("txt1").value];
var rate2 = [document.getElementById("txt2").value];
if (result.length == count){
if (rate1 == '' || rate2 == '') {
alert('you need to put in a value');
}
else {
result.push([[rate1], [rate2]]);
document.getElementById("txt1").value = '';
document.getElementById("txt2").value = '';
count++;
}
}
else {
try{
(result[count][0]) = document.getElementById("txt1").value;
(result[count][1]) = document.getElementById("txt2").value;
if( result[ ++count ] ) // this checks for undefined
{
document.getElementById("txt1").value = result[count][0]; //error happening here. trying to show next value but there isn't one created yet.
document.getElementById("txt2").value = result[count][1];
}
else
{
document.getElementById("txt1").value = '';
document.getElementById("txt2").value = '';
count--; // decrement counter
}
}catch(err) {
alert(err.description);
}
count++;
}
}
if (direction == 'prev')
{
if(count <= 0)
{
alert("no more elements");
}
else
{
var prev_val1 = (result[count - 1][0]);
document.getElementById("txt1").value = prev_val1;
var prev_val2 = (result[count - 1][1]);
document.getElementById("txt2").value = prev_val2;
count--;
}
}
document.getElementById("txtresult").value = result;
}
why do you do count++ in these 2 lines?
document.getElementById("txt1").value = result[count++][0]; //error happening here. trying to show next value but there isn't one created yet.
document.getElementById("txt2").value = result[count++][1];
seems like interpreter first increment the count and then try to get item of result which is undefined...
as i undestand pressing previous must "set cursor" to previous vaues so you can change previously entered values... in this case you shouldn't increment counter in these lines.. just remove ++
I don't get why you embedded the arrays three deep. I cleaned up some of the code and made the names more understandable (at least to me).
Regardless, when you were on the last value in the array, count++ didn't exist. Also, don't use count++ as this will increment your count var. Don't use ++ to simplify unless you truly know what you're doing and want to increment. Also, tricky shortcuts will confuse people trying to read your code, so try to be as explicit as possible. (There are exceptions to this statement, as in, you don't need to write for a person who has never coded before)
Here is working javascript:
var result = new Array();
var count = 0;
function move(direction) {
if(direction == 'next') {
var box1 = document.getElementById("txt1").value; //why did you wrap these as arrays?
var box2 = document.getElementById("txt2").value; //
if (result.length == count){
if (box1 == '' || box2 == '') {
alert('you need to put in a value');
} else {
result.push([box1, box2]); //why did you wrap individual numbers in arrays?
document.getElementById("txt1").value = '';
document.getElementById("txt2").value = '';
}
} else {
try{
result[count][0] = document.getElementById("txt1").value;
result[count][1] = document.getElementById("txt2").value;
if(result[count+1]) { // need this because if on last value in the array, count+1 will not exist yet
document.getElementById("txt1").value = result[count+1][0]; //do not do ++. this will increment count here. don't be tricky with ++
document.getElementById("txt2").value = result[count+1][1]; //because it will confuse others and lead to off by 1 errors
} else {
document.getElementById("txt1").value = '';
document.getElementById("txt2").value = '';
}
}
catch(err) {
alert(err.description);
}
}
count++;
}
if (direction == 'prev') {
if(count <= 0){
alert("no more elements");
} else {
var prev_val1 = result[count - 1][0];
var prev_val2 = result[count - 1][1];
document.getElementById("txt1").value = prev_val1;
document.getElementById("txt2").value = prev_val2;
count--;
}
}
document.getElementById("txtresult").value = result;
}

Categories