To miał być poradnik z JavaScript, ale..

Cześć cukiereczki,

Dzisiaj tak, krócej niż by mi wypadało, ale za to będzie pouczająco 😅

W poprzednim miesiącu zrobiłem głosowando na PL Tutorsowym discordzie nt. tego co by zamieścić na blogu. Wygrał poradnik z JavaScript dot. zamieniania testu na emoji. Z mojej strony chciałem do tego podejść za bardzo ambitnie i zrobić mechanizm klikowo-pisowy (nie ma takiego określenia) i żeby to jeszcze było kompatybilne z Discordem. Jak się okazało coś mi wyszło, ale wstyd jednak nazywać to osiągnięciem

Co poszło źle?

Zdecydowanie chęci wyższe niż talent. Tak dawno nie pisałem tego typu kodu, że aż czułem się juniorem w tej dziedzinie. Ja się znam na oprogramowaniu pisanym po stronie serwera, a nie na czymś co ma dobrze wyglądać i jeszcze ma służyć do pisania tekstu.

Brak odpowiedniego przygotowania: bo dużo czasu mi poszło na samo domyślanie się, a denerwowałem się na to, że po prostu nie wiedziałem czego używać. Ostatecznie jak zobaczyłem jak działa taki mechanizm na Discordzie to uznałem, że nie mam na tyle czasu, aby coś podobnego zrobić.

Na dodatek specjalnie robiłem sobie pod górkę, bo uparłem się, że nie użyję ani jednego frameworka, co w przypadku Vue lub React łatwiej idzie napisać taki konwerter. Ja jednak chciałem być ten fajny co pokaże wszystkim gdzie raki zimują, a sam się dałem zrobić w konia 🦄

No i co teraz?

Osobiście dostałem nauczkę i lepiej będzie jak będę pisać o tym na czym się znam czyli backend i język PHP. Poniżej udostępniam wam kochani tą koślawą wersję konwertera tak bardziej w ramach ciekawostki niż materiału edukacyjnego.

<!DOCTYPE html>
<html lang="pl">
<head>
    <meta charset="UTF-8">
    <!-- <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0"> -->
    <title>Konwerter textu na emoji</title>
    <script src="src/Text2EmojiConventer/Emoji.js"></script>
    <script src="src/Text2EmojiConventer/EmojiListMock.js"></script>
    <script src="src/Text2EmojiConventer/Text2EmojiConventer.js"></script>
    <link rel="stylesheet" href="styles/main.css">
</head>
<body>
    <div class="container">
        <p>Wpisz tekst:</p>
        <div contenteditable id="textarea"></div>
        <p>Poniżej lista emoji które możesz użyć:</p>
        <div id="emojiList"></div>
    </div>
    <script src="src/main.js"></script>
</body>
</html>
#textarea {
    border-bottom: 1px solid;
    min-height: 20px;
    outline: none;
    padding: 8px;
}

#textarea:focus-visible {
    border: 1px outset;
}

.emoji_container {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: center;
    align-content: flex-start;
    align-items: center;
    column-gap: 8px;
    row-gap: 4px;
}

img.emoji_img {
    width: 16px;
    height: 16px;
}

#emojiList {
    display: flex;
    flex-direction: column;
    flex-wrap: wrap;
    justify-content: center;
    align-content: flex-start;
    align-items: flex-start;
    column-gap: 2px;
    row-gap: 2px;
}
const textAreaElement = document.querySelector("#textarea");
const emojiListElement = document.querySelector("#emojiList");

const text2Emoji = new Text2EmojiConventer(textAreaElement, emojiListElement);
text2Emoji.initialize(EmojiListMock);

class Emoji
{
    /** @var {String} */
    #imgUrl;

    get imgUrl() { return this.#imgUrl; }

    /** @var {String} */
    #targetText;

    get targetText() { return this.#targetText; }

    /**
     * @param {String} imgUrl 
     * @param {String} targetText 
     */
    constructor(imgUrl, targetText) {
        this.#imgUrl = imgUrl;
        this.#targetText = targetText;
    }
}

const EmojiListMock = new Array(
    new Emoji('emojis/coin.png', ':coin:'),
    new Emoji('emojis/horse.png', ':horse:'),
    new Emoji('emojis/kekw.png', ':kekw:')
);
class Text2EmojiConventer
{
    /** @var {HTMLElement} */
    #textAreaElement;
    
    /** @var {HTMLElement} */
    #emojiListElement;

    #textAreaRange;

    /** @var {Emoji[]} */
    #emojiList;

    /**
     * @param {HTMLElement} textAreaElement 
     * @param {HTMLElement} emojiListElement 
     */
    constructor(textAreaElement, emojiListElement) {
        this.#emojiListElement = emojiListElement;
        this.#textAreaElement = textAreaElement;
    }

    /**
     * @param {Emoji[]} emojiList
     */
    initialize(emojiList) {
        this.#emojiList = emojiList;
        this._generateEmojiList(emojiList);
        this._calcTextAreaRange();
    }

    /**
     * @param {Emoji[]} emojiList
     */
    _generateEmojiList(emojiList) {
        /** @var {Emoji} emoji */
        emojiList.forEach(emoji => {
            const emojiElement = document.createElement('img');
            emojiElement.className = `emoji_img`;
            emojiElement.src = emoji.imgUrl;

            const emojiElementDescription = document.createElement('span');
            emojiElementDescription.className = "emoji_desc";
            emojiElementDescription.textContent = emoji.targetText;

            const emojiContainer = document.createElement('div');
            emojiContainer.className = "emoji_container";

            emojiContainer.appendChild(emojiElement);
            emojiContainer.appendChild(emojiElementDescription);

            this.#emojiListElement.appendChild(emojiContainer);
        });
    }

    /**
     * @param {Emoji[]} emojiList
     */
    _calcTextAreaRange() {
        this.#textAreaElement.oninput = () => {
            this._emojiOnInput()
        }
    }

    _emojiOnInput() {
        /** @var {Emoji} emoji */
        const that = this;
        this.#emojiList.forEach(function(emoji) {
            if(that.#textAreaElement.innerHTML.includes(emoji.targetText)) {
                const emojiElement = document.createElement('img');
                emojiElement.className = `emoji_img`;
                emojiElement.src = emoji.imgUrl;
                that.#textAreaElement.innerHTML = that.#textAreaElement.innerHTML.replaceAll(emoji.targetText, emojiElement.outerHTML);
            }
        });
    }

}

Oraz w katalogu ./emojis/ umieściłem 3 pliki:

  • coin.png
  • horse.png (a żeby było ciekawiej to animowane png)
  • kekw.png

Obrazki trzeba znaleźć jednak na własną rękę.

Podsumowanie

Także, może banalnie, ale jednak z sensem, cokolwiek robicie róbcie to na swoje siły i o ile się da i jest to możliwe to analizujcie i planujcie swoje większe pomysły i cele. Ja się dałem ponieść i czuję, że zawiodłem 😣

Żeby jednak nie kończyć smutno to sam się na tym błędzie nauczyłem i też nie ma tego złego co by na dobre nie wyszło! 😀

Subscribe
Powiadom o
guest
3 komentarzy
najstarszy
najnowszy oceniany
Inline Feedbacks
View all comments
Kamil
Kamil
1 rok temu

Mysie pysie, słodziaki, cukiereczki? Jak tak dalej będziesz nas nazywać to w końcu nas zjesz Enter 😀

Angry
Angry
10 miesięcy temu

Bywa i tak

Włączyć powiadomienia? Bardzo pragnę Dam sobie radę