6

I have a website that I'm trying to make functional on mobile as well. However, when I combine click and touchstart events for PC and tablets respectively, neither works(Clicking on the element the events are attached to aren't firing). Can anyone explain how I should go about fixing this? Here's an example of one element not working, the pen has the entire project.

HTML

<div id="menu">
    <h1>MENU</h1>
</div>
<div class="dropdown hidden">
    <ul>
        <li id="home_navlink">Home</li>
        <li id="about_navlink">About Me</li>
        <li id="work_navlink">My Work</li>
        <li id="contact_navlink">Contact Me</li>
    </ul>
</div>

JS

let menu = document.getElementById("menu");
let dropdown = document.getElementsByClassName("dropdown")[0];
menu.addEventListener("click touchstart", function(){
    if(dropdown.classList.contains("showing")){
        dropdown.classList.remove("showing");
        dropdown.classList.add("hidden");
    }
    else{
        dropdown.classList.remove("hidden");
        dropdown.classList.add("showing");
    }
})

Pen

Robert
  • 624
  • 2
  • 8
  • 19
  • click is equivalent to a touchstart and a touchend event. isn't it? try combining these two and logically trigger a event. If you don't want this headache then , you can try tap event of jquery mobile. – Koushik Chatterjee Jul 08 '17 at 18:55
  • I was always under the assumption that click was the equivalent, but just having the click event makes it not work on mobile. How would you recommend using touchstart and touchend together? Nest touchend inside the touchstart event? I may use jQuery Mobile, it's supposed to be used for mobile sites anyway, correct? – Robert Jul 08 '17 at 18:57
  • another point, by using addEventListener, you cannot pass multiple event name, its a native javascript method, you are probably get confused with the jQuery `on` style of attaching multiple events – Koushik Chatterjee Jul 08 '17 at 19:00
  • Ah, I wasn't aware of that, I was getting it confused with the on method from jQuery. So I guess the best thing to do would add a check for mobile and pc within my script to handle both events separately? Or simply use jQuery or jQuery Mobile? – Robert Jul 08 '17 at 19:02
  • well, using jQuery mobile is not mandatory, you can handle everything from javascript, but I would recomend atleast to use jQuery to manipulate DOM easily. If you want I can give you a sample code to handle this with jQuery as well as with only plain javascript – Koushik Chatterjee Jul 08 '17 at 19:05
  • Providing an example with plain javascript would be great. Using jQuery, I'd just need to replace the addEventListener with jQuery's on method and it would work. Which is probably what I should be doing anyway since I've included the library. – Robert Jul 08 '17 at 19:07
  • addEventListener only accepts one event argument and you're passing 2 – JJJ Jul 08 '17 at 19:25

3 Answers3

8

Fetch the menu using javascript:

let menu = document.getElementById("menu");
let dropdown = document.getElementsByClassName("dropdown")[0];

Declare a handler function as a function reference:

let clickHandler = function() {
    if (dropdown.classList.contains("showing")) {
        dropdown.classList.remove("showing");
        dropdown.classList.add("hidden");
    } else {
        dropdown.classList.remove("hidden");
        dropdown.classList.add("showing");
    }
}

Assign it to the click event:

menu.addEventListener("click", clickHandler);

And then check for touch event handler and assign a function for touchstart:

if ('ontouchstart' in window) {
    menu.addEventListener("touchstart", function() {
        var touchHndl = function() {
            //call the clickHandler actually
            clickHandler();
            //remove the touchend haldler after perform
            this.removeEventListener(touchHndl)
        }
        //attach a handler for touch end when you are in touchstart event
        this.addEventListener(touchHndl);
    });
}

So you were asking about a code segment in plain javascript, hope it helps. :)

jox
  • 2,218
  • 22
  • 32
Koushik Chatterjee
  • 4,106
  • 3
  • 18
  • 32
2

The event is firing if you just remove "touchstart" from the event listener, create a function containing the actual body of the event and create two event listener, one for click and one for touchstart. I don't think you can bind multiple events to one listener natively.

You set a lot of listener so you can use a function to bind one function for multiple events like this one : Binding multiple events to a listener.

Also, there is a typo when you start declaring the event listener :

inlineWorkLink.addEventListener("click touchstart", function(){});
Glagan
  • 21
  • 1
  • 5
2
const mytap = ( window.ontouchstart === null ) ? 'touchstart' : 'click';
xxx.addEventListener( mytap, (e) => {
// code
});
b0li
  • 21
  • 2
  • Please don't post only code as answer, but also provide an explanation what your code does and how it solves the problem of the question. Answers with an explanation are usually more helpful and of better quality, and are more likely to attract upvotes. – Tyler2P Aug 04 '21 at 13:52