Source: feedback.js

"use strict";
// SPDX-License-Identifier: GPL-3.0-or-later
// myMPD (c) 2018-2024 Juergen Mang <mail@jcgames.de>
// https://github.com/jcorporation/mympd

/** @module feedback_js */

/**
 * Handler for click on feedback (like or rating)
 * @param {EventTarget} target The target
 * @returns {void}
 */
//eslint-disable-next-line no-unused-vars
function clickFeedback(target) {
    const parent = target.closest('.btn-group');
    const feedbackType = parent.getAttribute('data-feedback');
    if (feedbackType === 'like') {
        voteLike(target);
    }
    else {
        voteRating(target);
    }
}

/**
 * Sets the feedback mode buttons
 * @param {string} id Element id
 * @param {string} stickerType MPD sticker type
 * @returns {void}
 */
function setFeedbacktypeId(id, stickerType) {
    const el = document.getElementById(id);
    setFeedbacktype(el, stickerType);
}

/**
 * Sets the feedback mode buttons
 * @param {Element} el Element
 * @param {string} stickerType MPD sticker type
 * @returns {void}
 */
function setFeedbacktype(el, stickerType) {
    if (features.featLike === true &&
        el.getAttribute('data-feedback') !== 'like')
    {
        elClear(el);
        el.appendChild(createLike(1, stickerType));
    }
    else if (features.featRating === true  &&
             el.getAttribute('data-feedback') !== 'rating')
    {
        elClear(el);
        el.appendChild(createStarRating(0, stickerType));
    }
    else {
        elClear(el);
    }
}

/**
 * Sets the current feedback
 * @param {Element} el Feedback element group
 * @param {number} like Like feedback value
 * @param {number} rating Star rating feedback value
 * @returns {void}
 */
function setFeedback(el, like, rating) {
    if (el.getAttribute('data-feedback') === 'like') {
        setLike(el, like);
    }
    else {
        setRating(el, rating);
    }
}

/**
 * Love/hate event handler
 * @param {EventTarget} el triggering element
 * @returns {void}
 */
//eslint-disable-next-line no-unused-vars
function voteLike(el) {
    if (el.nodeName === 'DIV') {
        return;
    }
    let vote = Number(el.getAttribute('data-vote'));
    if (vote === 0 &&
        el.classList.contains('active'))
    {
        vote = 1;
        el.classList.remove('active');
    }
    else if (vote === 2 &&
             el.classList.contains('active'))
    {
        vote = 1;
        el.classList.remove('active');
    }
    const aEl = el.parentNode.querySelector('.active');
    if (aEl !== null) {
        aEl.classList.remove('active');
    }
    if (vote === 0 ||
        vote === 2)
    {
        el.classList.add('active');
    }
    const uri = getData(el.parentNode, 'uri');
    const stickerType = el.parentNode.getAttribute('data-type');
    sendAPI("MYMPD_API_LIKE", {
        "uri": uri,
        "like": vote,
        "type": stickerType
    }, null, false);
}

/**
 * Creates the hate/love elements
 * @param {number} like like value 0 - 2
 * @param {string} stickerType MPD sticker type
 * @returns {HTMLElement} div element
 */
function createLike(like, stickerType) {
    const thDown = elCreateText('button', {"data-vote": "0", "data-title-phrase": "Hate", "class": ["btn", "btn-secondary", "mi"]}, 'thumb_down');
    if (like === 0) {
        thDown.classList.add('active');
    }
    const thUp = elCreateText('button', {"data-vote": "2", "data-title-phrase": "Love", "class": ["btn", "btn-secondary", "mi"]}, 'thumb_up');
    if (like === 2) {
        thUp.classList.add('active');
    }
    return elCreateNodes('div', {"class": ["btn-group"], "data-feedback": "like", "data-type": stickerType}, [
        thDown,
        thUp
    ]);
}

/**
 * Sets the vote button group
 * @param {HTMLElement | Element} el container for the thumbs
 * @param {number} vote The vote
 * @returns {void}
 */
function setLike(el, vote) {
    const btnHate = el.firstElementChild;
    const btnLove = el.lastElementChild;
    switch(vote) {
        case 0:
            btnLove.classList.remove('active');
            btnHate.classList.add('active');
            break;
        case 2:
            btnLove.classList.add('active');
            btnHate.classList.remove('active');
            break;
        default:
            btnLove.classList.remove('active');
            btnHate.classList.remove('active');
            break;
    }
}

/**
 * Rating event handler
 * @param {EventTarget} el triggering element
 * @returns {void}
 */
//eslint-disable-next-line no-unused-vars
function voteRating(el) {
    const rating = Number(el.getAttribute('data-vote'));
    const stickerType = el.parentNode.getAttribute('data-type');
    const uri = getData(el.parentNode, 'uri');
    setRating(el.parentNode, rating);

    sendAPI("MYMPD_API_RATING", {
        "uri": uri,
        "rating": rating,
        "type": stickerType
    }, null, false);
}

/**
 * Sets the star rating element
 * @param {HTMLElement | Element} el container for the stars
 * @param {number} rating the rating (0-10)
 * @returns {void}
 */
function setRating(el, rating) {
    const starEls = el.querySelectorAll('button');
    for (let i = 1; i < 6; i++) {
        starEls[i].textContent = rating >= i * 2
            ? ligatures.stared
            : ligatures.star;
    }
    if (rating === 0) {
        elDisable(starEls[0]);
    }
    else {
        elEnable(starEls[0]);
    }
}

/**
 * Creates a button group for star rating
 * @param {number} rating the rating (0-10)
 * @param {string} stickerType MPD sticker type
 * @returns {HTMLElement} div element
 */
function createStarRating(rating, stickerType) {
    const div = elCreateEmpty('div', {"class": ["btn-group"], "data-feedback": "rating", "data-type": stickerType});
    const clearEl = elCreateText('button', {"class": ["btn", "btn-secondary", "mi", "px-1"], "data-title-phrase": "Clear", "title": "Clear", "data-vote": "0" }, 'clear');
    if (rating === 0) {
        clearEl.setAttribute('disabled', 'disabled');
    }
    div.appendChild(clearEl);
    for (let i = 1; i < 6; i++) {
        const vote = i * 2;
        const lig = rating >= vote
            ? ligatures.stared
            : ligatures.star;
        const padding = i === 5
                ? ['ps-0', 'pe-1']
                : ['px-0'];
        div.appendChild(
            elCreateText('button', {"class": ["btn", "btn-secondary", "mi", ... padding], "title": vote.toString(), "data-vote": vote.toString() }, lig)
        );
    }
    return div;
}

/**
 * Shows the stars rating
 * @param {number} rating the rating (0-10)
 * @returns {HTMLElement} div element
 */
function showStarRating(rating) {
    const div = elCreateEmpty('div', {});
    for (let i = 1; i < 6; i++) {
        const vote = i * 2;
        const lig = rating >= vote
            ? ligatures.stared
            : ligatures.star;
        div.appendChild(
            elCreateText('span', {"class": ["mi"], "title": vote.toString()}, lig)
        );
    }
    return div;
}