Search code examples
javascriptjqueryajaxgoogle-font-api

Problem with getting clicked element after click


I'm coding a site that displays all fonts from google-fonts by using they api. I'm getting those fonts using ajax and they are displaying good, but when then i try to give click event to all p tags (each contains one font) and display them in console by using console.log($(this)) it shows something that looks like ajax object.

$(() => {
    $(".press").click(() => {
        $.ajax({
            url: 'https://www.googleapis.com/webfonts/v1/webfonts?key=MyApiKey'
        }).done(function (response) {
            let items = response.items;
            for (var i = 0; i < items.length; i++) {
                const font = items[i];
                let fontFamily = font.family;
                $("div.fonts").append('<p class="font" id="'+i+'">'+fontFamily+'</p>');
                $("p#"+i).click(() => {
                    console.log($(this));
                });
                if (i === 723) {
                    const font = items[i];
                    let fontFamily = font.family;
                    let fontUrl = font.files.regular;
                    $("body").append("<style>@font-face {font-family: "+fontFamily+";src: url("+fontUrl+");}</style>")
                    let div = document.querySelector("#div5");
                    $("#div5").css("font-family", fontFamily);
                    break;
                }
            }
        }).fail(function (error) {
            console.log("Error: " + error);
        });
    });

});

Solution

  • There are two problems:

    1. You're using an arrow function, so it closes over this rather than having it set by how it's called. Use a traditional function instead for the click handler. Or, if you prefer, keep using an arrow function but accept the event parameter and use its currentTarget property, which is the same thing this normally is (the element on which you hooked the event).

    2. You're using an invalid selector for the paragraphs. A CSS ID selector cannot start with a digit. jQuery lets you get away with it if you use a pure ID selector like #1 because it optimizes that to a getElementById call, but when you do a compound selector like p#1, it fails. Add a prefix, like x, to the IDs and to the ID selectors — or better yet, just look up the event handler on the p directly rather than looking it up again.

    Something like this (see *** comments):

    $(() => {
    
        $(".press").click(() => {
            $.ajax({
                url: 'https://www.googleapis.com/webfonts/v1/webfonts?key=MyApiKey'
            }).done(function (response) {
                let items = response.items;
                for (var i = 0; i < items.length; i++) {
                    const font = items[i];
                    let fontFamily = font.family;
                    // *** Directly hook up the event handler, no need for the `id` attribute
                    $('<p class="font">'+fontFamily+'</p>')
                        .click(function() { // *** Use a traditional function
                            console.log($(this));
                        })
                        .appendTo("div.fonts");
                    if (i === 723) {
                        const font = items[i];
                        let fontFamily = font.family;
                        let fontUrl = font.files.regular;
                        $("body").append("<style>@font-face {font-family: "+fontFamily+";src: url("+fontUrl+");}</style>")
                        let div = document.querySelector("#div5");
                        $("#div5").css("font-family", fontFamily);
                        break;
                    }
                }
            }).fail(function (error) {
                console.log("Error: " + error);
            });
        });
    
    });