How to convert this jQuery code to plain JavaScript?

37
January 22, 2020, at 10:10 PM

I'm trying to get the focus method (touch, mouse or keyboard) on links setting a data-attribute.

$(function() {
    var i,
        r = document.getElementsByTagName("a")[0];
    if ("ontouchstart" in window) {
        document.addEventListener("touchstart", function(event) {
            i = "touch";
        }, true);
    }
    else {
        document.addEventListener("mousedown", function(event) {
            i = "mouse";
        }, true);
    }
    document.addEventListener("keydown", function(event) {
        i = "keyboard";
    }, true);
})

The problem is that I only get results writing the last part in jQuery:

    $("a").focus(function() {
        $(this).attr("data-focus-method", i)
    })
    $("a").blur(function() {
        $(this).removeAttr("data-focus-method")
    })

And I want to write the whole code in plain JavaScript. I've tried the way below:

    r.addEventListener("focus", function() {
        r.setAttribute("data-focus-method", i);
    });
    r.addEventListener("blur", function() {
        r.removeAttribute("data-focus-method");
    });

But it doesn't work. Can somebody help me please?

Answer 1

I suggest to use querySelectorAll method and use forEach to iterate the nodelist

document.querySelectorAll("a").forEach((link) => {
  link.addEventListener("focus", function() {
    this.setAttribute("data-focus-method", i);
  });
  link.addEventListener("blur", function() {
    this.removeAttribute("data-focus-method");
  });
});
Answer 2

I'm not sure why you're trying to override the i on method whenever a key is pressed on the keyboard. However, I'm assuming that's the desired effect since you don't mention it in your question.

That said, here's something to get you closer to your goal of a vanilla JS version of the code.

The answer uses the spread operator to convert the nodeList you get from getElementsByTagName to an array and then forEach() to loop through the array items. For each item, we add two event listeners. one for focus, and one for blur.

When focused, we add the attribute. When blurred we remove the attribute. I opted for set attribute and remove attribute, but you can also use dataset if you want.

To determine what i (the method) is, I used let and a ternary operator.

I'm still not sure why you want to override the method when a key is pressed on the keyboard so I left that. I can improve that if you let me know what the desired effect is.

let i = ("ontouchstart" in window) ? "touch" : "mouse"; 
 
document.addEventListener("keydown", () => { 
  i = "keyboard" 
}) 
 
const links = [...document.getElementsByTagName("a")]; 
 
links.forEach(link => { 
  link.addEventListener("focus", () => { 
    link.setAttribute('data-focus-method', i); 
  }); 
  link.addEventListener("blur", () => { 
    link.removeAttribute('data-focus-method'); 
  }) 
})
<a href="#">My link 1</a> 
<a href="#">My link 2</a> 
<a href="#">My link 3</a>

Answer 3

I got the solution adding:

    var w;
    for (w = 0; w < r.length; w++) {
        r[w].addEventListener("focus", function() {
            this.setAttribute("data-focus-method", i);
        });
        r[w].addEventListener("blur", function() {
            this.removeAttribute("data-focus-method");
        });
    }

By the way, thanks for everyone who helped me!

READ ALSO
How to scroll div continuously on mousedown event?

How to scroll div continuously on mousedown event?

I have two divs and two buttons:

91
Google Invisible ReCaptcha on multiple forms in a same page - PHP

Google Invisible ReCaptcha on multiple forms in a same page - PHP

I am following this Invisible ReCaptcha doc on my php website: http://wwwpinnacleinternet

80
Select2 not responsive in UI

Select2 not responsive in UI

This is "select2": Image

80
Loading bar and number of mails sended [closed]

Loading bar and number of mails sended [closed]

Want to improve this question? Update the question so it's on-topic for Stack Overflow

86