jQuery method not finding selector - javascript

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{
}
});

Related

Script does not jump to the next field when the maxlength is reached

This is my script
<script>
var InputContainer = document.getElementsByClassName("InputContainer")[0];
container.onkeyup = function(e) {
var target = e.srcElement || e.target;
var maxLength = parseInt(target.attributes["maxlength"].value, 10);
var myLength = target.value.length;
if (myLength >= maxLength) {
var next = target;
while (next = next.nextElementSibling) {
if (next == null)
break;
if (next.tagName.toLowerCase() === "input") {
next.focus();
break;
}
}
}
// Move to previous field if empty (user pressed backspace)
else if (myLength === 0) {
var previous = target;
while (previous = previous.previousElementSibling) {
if (previous == null)
break;
if (previous.tagName.toLowerCase() === "input") {
previous.focus();
break;
}
}
}
}
</script>
I have also put a around the entire form.
You can find the original webpage at: https://im-here.biz/ContactForm/contact-inc.php
Obviously, I am doing something wrong here.
Ideas?
I can see an error in the console on the above-mentioned URL. By seeing your code there is no container defined. I guess you should be using InputContainer instead of the container variable or change the declaration like this:
<script defer>
// Put your code here
var container = document.getElementsByClassName("InputContainer")[0];
</script>

How to exclude down arrow key from event-listener

I am developing a dictionary which has autocomplete when I start typing it shows words as list starting with that letter. (Like vocabulary.com)
searchInput.addEventListener('keyup',function(){
let search = $('#search').val()
$.ajax({
type: 'GET',
url: '/home/autocomplete/' + search
dataType: "json",
success: function (response) {
let word = response.words
suggestionsPanel.innerHTML = '';
$.each(word, function (idx, w) {
$('.suggestions').append(`<li name = ${w}>${w}</li>`)
// $('.suggestions li:first').addClass('selected')
})};
Now i want to add down arrow key to go move through list. I added another key down event listener buy it keeps executing first event listener function. How to make it both work?
var li = $('.suggestions > li');
var liSelected;
$(window).keydown(function(e) {
if(e.which === 40) {
if(liSelected) {
liSelected.removeClass('selected');
next = liSelected.next();
if(next.length > 0) {
liSelected = next.addClass('selected');
} else {
liSelected = li.eq(0).addClass('selected');
}
} else {
liSelected = li.eq(0).addClass('selected');
}
} else if(e.which === 38) {
if(liSelected) {
liSelected.removeClass('selected');
next = liSelected.prev();
if(next.length > 0) {
liSelected = next.addClass('selected');
} else {
liSelected = li.last().addClass('selected');
}
} else {
liSelected = li.last().addClass('selected');
}
}
});
The keyup event emits a keyCode property, which you can use to identify the down arrow key.
If found, you can then exit the callback on that basis.
The down arrow key has a key code of 40.
searchInput.addEventListener('keyup', function(evt) {
if (evt.keyCode == 40) return;
//otherwise continue...

Using jQuery Mask Plugin on dynamic value

I'm trying to use jQuery-Mask-Plugin on an input which value can be dynamic. This input can be any number with, at least, 2 digits to a maximum of 8 digits and the mask is a '-'. For example I can have '2-2', '45-8' or '9999999-8', etc.
The issue is that the mask isn't working at all. I managed to make it work using $("#input-area input").mask("00-0"); but that way, my mask isn't dynamic.
Here's what I was trying to do:
var options = {
onKeyPress: function (conta, ev, el, op) {
var masks = ['0-0', '00-0', '000-0', '0000-0', '00000-0', '000000-0', '0000000-0', '0000000-0'];
if(conta.length == 2){
var mask = masks[0];
} else if(conta.length == 3){
var mask = masks[1];
} else if(conta.length == 4){
var mask = masks[2];
} else if(conta.length == 5){
var mask = masks[3];
} else if(conta.length == 6){
var mask = masks[4];
} else if(conta.length == 7){
var mask = masks[5];
} else if(conta.length == 8){
var mask = masks[7];
}
$('#input-area input').mask(mask, options);
}
}
if($('#input-area > div > input').length == 2){
$('#input-area > div > input').mask('0-0', options);
} else if($('#input-area > div > input').length == 3){
$('#input-area > div > input').mask('00-0', options);
} else if($('#input-area > div > input').length == 4){
$('#input-area > div > input').mask('000-0', options);
} else if($('#input-area > div > input').length == 5){
$('#input-area > div > input').mask('0000-0', options);
} else if($('#input-area > div > input').length == 6){
$('#input-area > div > input').mask('00000-0', options);
} else if($('#input-area > div > input').length == 7){
$('#input-area > div > input').mask('000000-0', options);
} else if($('#input-area > div > input').length == 8){
$('#input-area > div > input').mask('0000000-0', options);
}
A few things wrong here
First of all and the most obvious is that you are initiating the
mask before the input is loaded in DOM. Load the input first then
the mask
You are missing code: Where is the event that loads the dynamic input?
You are loading your onKeyPress in the options?
You might want to structure your jquery as such
HTML
However your keypress is made (click event), make it so it passes the value of the length. Basically, load your data-id dynamically beforehand in the button. In my example, it is 2
<button class="loadinput" data-id="2">Click</button>
<div id="input-area"><div></div></div>
JQUERY
Then in jquery load the input first, then load the mask
$(document).on('click', '.loadinput', function() {
var this_length = $(this).attr('data-id');
$('#input-area > div').html('<input id="thisinput" type="text">');
if (this_length == 2) {
$('#thisinput').mask('0-0');
} else if (this_length == 3) {
$('#thisinput').mask('00-0')
}...and so on
})
Searching a bit further in the docs of Jquery Mask Plugin I found Recursive digits. It will be something like: $('#input-area > div > input').mask('##0-0', {reverse: true});

filtered rows in navigable table

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;
}
}

How can I get the next/prev link with jquery regardless of where it is in DOM?

How can I find the next or previous <a> regardless of where it is placed in DOM?
When I press key down, I want to highlight the next <a>, when I press up I want to highlight the previous one regardless of where it is nested in DOM.
<div id="info">
<span>How can I get this when pressing up?</span>
<a class="focus" href="#home">I'm here - and will either press up or down</a>
<div>
<ul>
<li>How can I get this when pressing down?</li>
<li>Another link</li>
</ul>
</div>
</div>
I have tried next(), nextAll(), prev() and prevAll() with out luck.
This is what I have so far
$(document).keypress(e){
var keyCode = e.keyCode;
switch (keyCode) {
case 38:
e.preventDefault();
$("body").trigger('nav', 'up');
break;
case 40:
e.preventDefault();
$("body").trigger('nav', 'down');
break;
}
$("body").bind('nav', function(direction){
var currentLink = $(".focus").first();
if(direction === 'up'){
var prevLink = ???
} else if (direction === 'down'){
var nextLink = ???
}
});
});
This is a basic code i write on jsfiddle, you can start with.
http://jsfiddle.net/sabri/skXZT/10/
Javascript
var allLink = jQuery('a');
var currentHighLight = allLink.filter('.highlight');
$('body').keyup(function(event) {
index = allLink.index(currentHighLight);
currentHighLight.removeClass('highlight');
if (event.which == 38) {
allLink.eq(index-1).addClass('highlight')
} else if (event.which == 40) {
allLink.eq(index+1).addClass('highlight')
}
currentHighLight = allLink.filter('.highlight');
});
on down key, do:
if($('a[cur="1"]').length==0) {
$('a:first').attr('cur', "1");
$('a:first').addClass('highlight');
return false;
}
var previous = null, next = null;
$('a').each(function() {
if(previous!=null && $(previous).attr('cur')=='1') {
$(previous).removeAttr('cur');
$(previous).removeClass('highlight');
$(this).attr('cur', "1");
$(this).addClass('highlight');
return false;
}
previous = this;
}
on up key, do:
if($('a[cur="1"]').length==0) {
$('a:first').attr('cur', "1");
$('a:first').addClass('highlight');
return false;
}
var previous = null;
$('a').each(function() {
if($(this).attr('cur')=='1') {
$(this).removeAttr('cur');
$(this).removeClass('highlight');
if(previous!=null) {
$(this).attr('cur', "1");
$(this).addClass('highlight');
}
else {
$('a:last').attr('cur', "1");
$('a:last').addClass('highlight');
}
return false;
}
previous = this;
}

Categories