skip to Main Content

I want to create a typing game for my portfolio project . I am new to programming .
I want to render every random word in a div and every character wrapped in a span tag inside that div.
i achieved rendering the divs but wrapping the characters inside span tags seems impossible . i tried many ways but couldn’t get it to work.

closest i got is this function which takes the word and parent as a param and creates spans in that parent element

    function spanifyWords(word, parent){
     for (i=0 ; i< word.length; i++){
         let newSpan = document.createElement("span");
         newSpan = parent.appendChild(newSpan);
         newSpan.innerHTML += word[i];
            }
        }

if i call this function with for example

spanifyWords("hello", wordsContainer) ;

then it creates 5 span tags which each char inside the main div .
this one works fine as long as i dont call it in other function which renders divs inside the main div(wordsContainer).

function renderDivs(n){
            for (i=0; i<n; i++){
                let randomIndex = Math.floor(Math.random()*wordsCount)
                let randomWord = newArray[randomIndex];
                let newDiv = document.createElement("div")   
                 newDiv = wordsContainer.appendChild(newDiv)
                newDiv.innerHTML += spanifyWords(randomWord, newDiv);   //  this needs attention
            
        }

    }

my guess is that I’m doing something wrong at the last line of second function . either function is not able to configure the parent or Javascript innerHTML doesn’t take a function as a value.

can someone please tell me what is wrong with the second function?

2

Answers


  1. The spanifyWords function already adds the span elements to the container, so there is no need to set the innerHTML at all (in fact, you were setting it to undefined as spanifyWords does not return anything). Directly use spanifyWords(randomWord, newDiv); instead.

    Furthermore, declare each loop counter with let i = 0; so that it is scoped to the block instead of global.

    Login or Signup to reply.
    • The for loop’s i = 0 should be let i = 0; otherwise it’s set to the global scope
    • No need to reset newSpan = parent.append(newSpan); just use parent.append(newSpan);
    • Use just wordsContainer.append(newDiv); without the innerHTML = – that task is already done in the spanifyWords function
    • Use const where due
    const wordsContainer = document.querySelector("#wordsContainer");
    const newArray = ["hello", "world", "lorem", "ipsum"];
    const wordsCount = newArray.length;
    
    function spanifyWords(word, parent){
      for (let i=0 ; i < word.length; i++){
        const newSpan = document.createElement("span");
        parent.append(newSpan);
        newSpan.textContent = word[i];
      }
    }
    
    function renderDivs(n){
      for (let i=0; i<n; i++){
        const randomIndex = Math.floor(Math.random() * wordsCount);
        const randomWord = newArray[randomIndex];
        const newDiv = document.createElement("div"); 
        wordsContainer.append(newDiv);
        spanifyWords(randomWord, newDiv);
      }
    }
    
    renderDivs(6);
    #wordsContainer * {
      outline: 1px solid #000;
      padding: 1rem;
      font: 1rem/1 sans-serif;
    }
      <div id="wordsContainer"></div>

    Here’s also a slight variation on the above code:

    // Utility functions
    const el = (sel, par) => (par || document).querySelector(sel);
    const els = (sel, par) => (par || document).querySelectorAll(sel);
    const elNew = (tag, prop) => Object.assign(document.createElement(tag), prop);
    const repeat = (n, cb) => [...Array(n)].forEach((_, i) => cb(i));
    
    // Wordify
    const elWords = el("#wordsContainer");
    const words = ["hello", "world", "lorem", "ipsum"];
    
    const spanify = (word) => [...word].reduce((a, x) => a + `<span>${x}</span>`, "");
    
    function renderDivs(n){
      repeat(n, () => {
        const randomIndex = Math.floor(Math.random() * words.length);
        const randomWord = words[randomIndex];
        const elDiv = elNew("div", { innerHTML: spanify(randomWord) });
        elWords.append(elDiv);
      });
    }
    
    renderDivs(6);
    #wordsContainer * {
      outline: 1px solid #000;
      padding: 1rem;
      font: 1rem/1 sans-serif;
    }
    <div id="wordsContainer"></div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search