Selecting a list item on a touch screen - javascript

I've found multiple threads based on or around this question however the answers so far haven't helped what so ever. I'm trying to get this to work through pure JavaScript (JQuery accepted).
So far I have it working so that I can select an item via web browser on a computer but the click event doesn't seem to work with touch screens. I've tried multiple "solutions" from other threads such as adding touch for example:
$('.List').on('click touch', function () {
// code
});
My current JavaScript (Works on pc):
document.querySelector('.List').addEventListener('click', function (e) {
var selected;
if (e.target.tagName === 'LI') {
selected = document.querySelector('li.selected');
if (selected)
selected.classList = '';
e.target.classList = 'selected'
}
document.getElementById('ItemValue').value = e.target.innerText;
});
In the above JavaScript I'm simply adding a colour to the background of the list item and getting the inner text and storing it.
My list (Items are added at runtime)
<div id="SelectedItems" class="ListBox">
<ul id="Selected" class="List ItemList" runat="server" >
<%--List items here--%>
</ul>
</div>

If you sure, you are including the Jquery library, try using this solution.
Since all your list items are loading at run time, you can also use like this,
$(document).ready(function () {
$(document).on('click', '#Selected li' function () {
// code
});
});

Related

An AJAX Search Plugin is removing my Event Listeners from an 'Accordion' style list

I'm using Search & Filter pro WP plugin for the ease of a client using it.
I've created a results page and filter on a demo site (for testing) that works fine but I know the categories will get large on the real site. So I turned the plugins' filters into an Accordion style list.
It works fine until certain searches reload all those filter results with AJAX and they remove my event listeners (which are sitting on elements for the moment, I know it's not ideal but for now I just want to see if it could work).
I imagine because my script has already been parsed when the DOM loaded, the AJAX from the plugin is just redefining those elements and they are then missing the Event Listeners or something.
Any help would be appreciated.
Here's my script:
<?php
add_action( 'wp_footer', function () { ?>
<script>
const clicker = document.querySelectorAll('#search-filter-form-4346 > ul > li > h4');
// looping through the <h4> elements and adding an event listener onto each, the class toggle just adds an animation to a pseudo-element spinner
for (let i = 0; i < clicker.length; i++) {
clicker[i].addEventListener("click", function() {
this.classList.toggle("open-filter-dropdown");
console.log('EL was created');
// declaring the <ul> as a variable
const openFilterPanel = this.nextElementSibling;
// animating the <ul> elements max-height
if (openFilterPanel.style.maxHeight) {
openFilterPanel.style.maxHeight = null;
} else {
openFilterPanel.style.maxHeight = openFilterPanel.scrollHeight + "px";
}
console.log('openFilterPanel style is changed');
});
}
</script>
<?php } );
I'm pretty new to javascript, I get the basic concepts but this kind of an interference is above my head. I tried refactoring my code, forcing the page to refresh and other such measures. None of these work very well. I also thought I could use a 'loadend' event on the document to re-add my ELs but that didn't work either.
Hoping there is a workaround here, otherwise I might have to find another solution or plugin.
Thanks in advance!

How does event bubbling/ capturing affect e.preventDefault()?

edit: For new viewers of the question, my title is misleading. The solution to this problem had nothing to do with event bubbling/capturing as was my assumption at the time of posting.
I have a mobile navigation menu that contains 3 <li> elements which, when clicked, toggleSlide() a dropdown menu. The jQuery code for each of them is largely the same:
const coreSlider = function() {
const aContainer = document.querySelector('#dropdown-A');
const aLinks = document.querySelector('#A-links');
const dontOpen = document.querySelector('.mob-prev-def');
$(aContainer).on('click', function() {
$(aLinks).slideToggle(200);
});
$(dontOpen).on('click', function(e) {
e.preventDefault();
});
}
...
Above is an example of the jQuery code on 1 of these dropdown containers, and behaves exactly as I want it to (toggles the drop-down menu on click, but does not redirect to the href value inside the <li> inside the container. However, I still want the links that appear on click to direct them to the relevant part of my website.
There are 2 more containers with jQuery code exactly like this, but for whatever reason the e.preventDefault() part of the code on them doesn't work as intended, and redirects on click. I figure that event bubbling/ capturing has something to do with it, but I'm not sure how exactly it is functioning in this example. To that end, what's going on here and how can I fix it to ensure all containers behave as I want? Here's my HTML:
<ul id="nav-links">
<li id="dropdown-A">
...
<div id="A-links">
...
...
...
</div>
</li>
<li id="dropdown-D">
...
<div id="D-links">
...
...
...
...
</div>
</li>
<li id="dropdown-E">
...
<div id="E-links">
...
...
</div>
</li>
<li id="gallery">Gallery</li>
</ul>
Edit: thanks to user Stone3m, I managed to add in a solution:
const prevDef = function() {
const dontOpen = $('.mob-pref-dev');
$(dontOpen).on('click', function(e) {
e.preventDefault();
});
}
prevDef();
The issue here is that you are using querySelector, which only selects one occurrence.
You should be using querySelectorAll with a forEach loop for every occurrence.
A quick and simple method would be to:
document.querySelectorAll('.mob-prev-def').forEach(item => {
item.addEventListener('click', function(e) {
e.preventDefault()
})
})
Sorry, I prefer vanilla JavaScript, but you could figure it out in jQuery now (I hope!)

jquery not resetting menu navigation trigger

Currently I have this script that allows a button to open and close a menu whilst also changing it's class to do a little animation state change depending on open/close,... simple but effective.....
$(document).ready(function () {
var $navToggle = $('.nav-toggle');
$(".navbtn").click(function () {
if($navToggle.hasClass('active')){
$('#menu').multilevelpushmenu('collapse');
$navToggle.removeClass('active');
$(this).addClass('active');
}
else{
$('#menu').multilevelpushmenu('expand');
$navToggle.addClass('active');
$(this).removeClass('active');
}
});
within the menu is a list with some options (standard) and when one is clicked it performs the following script based on its tag in the list... here's the html and js for that....
html
<li>
<i class="fa fa-briefcase"></i>Who are Musability?
</li>
JS
$('.fa-briefcase').parent().on('click', function () {
$("#colorscreen").remove();
$( '#menu' ).multilevelpushmenu( 'collapse' );
$("body").append('<div id="colorscreen" class="animated"></div>');
$("#colorscreen").addClass("fadeInUpBig");
$('.fadeInUpBig').css('background-color', 'rgba(13,135,22,0.1)');
$(".tile-area-main").css({width: "720px"}).load("content.html");
$('.nav-toggle').removeClass('active');
$(this).addClass('active');
});
all functions work great separately but when i introduce the functions for the button click fa-briefcase it wont allow me to open the menu again why is this ?
... on another note (therefore probably a new question at another time) this code is repetitive for all buttons and wonder if there is a way of standardizing the stuff that is repeated into one big function ? not sure about how i would go about it but it isn't the focus of this question , although any advice greatly recieved.
What does your content.html file contain?
Because if it contains other JavaScript it could be messing with it.
i.e.
Instead of $(".tile-area-main").load("content.html");
Try $(".tile-area-main").load("content.html#div");
Where #div is the div with the contents you want to load() in
EDIT: Just noticed your comments, seems like you've fixed it yourself, but glad my method worked :)

for loop vs forEach in JavaScript -- example from book

I am currently learning JavaScript using O'Reilly's "Learning Web Application Development". In the example, we are constructing a website using HTML and CSS, which includes 3 tabs which should be able to be selected and become the "active" tab. The books claims that the following two ways of writing the tab code are equivalent:
1)
var main = function() {
"use strict";
var tabNumber;
for (tabNumber=1;tabNumber<=3;tabNumber++) {
var tabSelector = ".tabs a:nth-child("+tabNumber+") span";
$(tabSelector).on("click",function() {
$(".tabs span").removeClass("active");
$(tabSelector).addClass("active");
$("main .content").empty();
return false;
});
}
}
$(document).ready(main);
2)
var main = function() {
"use strict";
$(".tabs a span").toArray().forEach(function(element) {
$(element).on("click", function() {
console.print("this element: " + element);
$(".tabs span").removeClass("active");
$(element).addClass("active");
$("main .content").empty();
return false;
});
});
}
$(document).ready(main);
However, they do not output the same result. The version using forEach works correctly, so that when I click one of the tabs the attention moves to that tab and it becomes highlighted. However, in the version using a for loop, whenever I click any tab, the attention always moves to the last tab. To confirm what is happening, I printed out the name of the element inside the event listener with both methods, using 3 tabs total. And using the for loop, no matter which tab I click I am getting a response of
"this element: .tabs a:nth-child(3) span"
Could someone please help me explain why this is happening? Why is the output different using for or forEach? And why, using for, is it always passing the last element of tabs to the event listener?
Looks like there's a problem here:
var tabSelector = ".tabs a:nth-child("+tabNumber+") span";
$tabSelector.on("click",function(){
You've created a variable that doesn't have the $ at the beginning, then attached the event to a variable (not sure what it would refer to) with a $ at the beginning.
It should be changed to this, I believe:
$(tabSelector).on("click",function(){
In the for loop solution, you are setting tabSelector multiple times like so:
var tabSelector = ".tabs a:nth-child("+tabNumber+") span";
This selector is, in the end, going to be set to the last tabNumber, which is always going to be called when you make a reference to it:
$(tabSelector).addClass("active");
To avoid that, replace it by this, which will be different for each of them:
$(this).addClass("active");
JS Fiddle Demo

How do I prevent .slideToggle() from 'over stacking'?

My code:
$(document).ready(function() {
var up = false;
$('#that_list').slideUp();
$('#updates').click(function() {
$('#that_list').slideToggle(200);
});
});
It works, but if I click the anchor called updates too many times the list of items called that_list slides up and down multiple times after I stop clicking. I'm pretty new to jquery and javascript and have not found a solution to this on the website (maybe I'm not searching for the right question.)

Categories