User:Zuhui/SI26/Storybook/Code to work 2: Difference between revisions

From XPUB & Lens-Based wiki
No edit summary
Line 145: Line 145:
<br>
<br>
<br>
<br>
===<s>synchronizing spans and divs</s>===
===synchronizing spans and divs===
'''Goal:'''
added basic variables and queryselectorall for the divs
connect each <code>span</code> and <code>div</code> as some sort of a single unit, so they'd move together
<syntaxhighlight lang="javascript">
:: ↳ when <code>span</code> is moved, added, or pulled out, its matching <code>div</code> should sync with it
let sentence = document.getElementById("sentence");
:: ↳ this mechanism should work in a way that CSS selectors and combinators can pick up
let space = document.getElementById("space");
<br>
 
<br>
let words = Array.from(document.querySelectorAll("#sentence span"));
<div style="float:right; text-align:right;">
let figures = Array.from(document.querySelectorAll("#space div"));
[https://stackoverflow.com/questions/25544516/how-to-keep-html-dom-elements-synchronized-with-the-associated-javascript-object How to keep html DOM elements synchronized with the associated javascript object? reddit]<br>
 
[https://www.w3schools.com/js/js_objects.asp#gsc.tab=0 js Objects w3c]<br>
let removedWords = [];
[https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_objects Working with Objects mdn]
let removedDivs = [];
<br>
</syntaxhighlight>
<br>
<br><br>
[https://www.reddit.com/r/learnprogramming/comments/11azbne/how_to_associate_a_dom_element_with_an_instance/ how to associate a DOM element with an instance variable? reddit]<br>
 
[https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map Map objects mdn]<br>
'''now adding under function removeRandom ()'''<br>
[https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_classes#instance_methods Using classes, Instance methods mdn]<br>
with Joseph's help,
''"You can use the Map class to store your class instances, stored and retrieved by some key."''<br><br>
<syntaxhighlight lang="javascript">
''"Objects vs. Maps:<br>Object is similar to Map—both let you set keys to values, retrieve those values, delete keys, and detect whether something is stored at a key.<br> For this reason (and because there were no built-in alternatives), Object has been used as Map historically."''
function removeRandom () {
<br>
    if (words.length > 1) {
<br>
        let pickRandom = Math.floor(Math.random() * words.length );
[https://www.altcademy.com/blog/what-is-an-instance-in-javascript/ What is an instance in javascript]<br>
        let removing = words.splice(pickRandom,1)[0];
[https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/new new mdn]<br>
        removedWords.push(removing);
</div>
        removing.remove(); //.remove() method removes the element from the DOM.
<br>
 
<br>
        var spaceRemoving = removing.classList[0].replace("word_","");
<br>
        let matchingDiv = document.querySelector("#space div." + spaceRemoving);
<br>
       
<br>
        removedDivs.push(matchingDiv);
<br>
        matchingDiv.remove();
<br>
    }
<br>
}
<br>
</syntaxhighlight>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
* I could to use either <code>Object</code> or <code>Map</code> (i'll see the the difference later) to save my spans and divs as a paired units.
: ↳ but this doesn't mean that the <code>div</code> will actually move in a same way the <code>span</code> moves, it's mostly for convenience to find the matching <code>div</code> for the <code>span</code>.
:: ↳ just like using an array doesn't automatically change DOM nodes, saving <code>span</code> and <code>div</code> in an <code>Object</code> doens't mean they will update in the DOM by themselves. I need methods.
<br>
<br>
<div style="float:right; text-align:right;">
<div style="float:right; text-align:right;">
[https://plainenglish.io/blog/how-to-watch-for-dom-changes-with-javascript How to watch for DOM changes with Javascript]<br>
[https://developer.mozilla.org/en-US/docs/Web/API/Element/classList classList mdn]<br>
[https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver MutationObserver mdn]<br>
[https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList DOMTokenList mdn]<br>
<br>
[https://dev.to/lensco825/how-the-domtokenlist-api-works-3lef How the DOMTokenList API works dev]<br>
<br>
[https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList replace() mdn]<br>  
<br>
</div>
</div>
<br>
<br>
Line 202: Line 187:
<br>
<br>
<br>
<br>
<br>
'''code explained:'''
<br>
* ok, now I want to punch myself in the face, this is an unnecessarily difficult and messy way to do this. I assumed it should be a complex process syncing divs to the moving spans but I just realized that I can basically work the divs the same way I worked the spans. they have the same class names...I just need to figure out for it to get the same named divs.
<br>
<br>


===synchronizing spans and divs 2===
<br>
<br>
<br>
=CSS=
=CSS=
<br>
<br>

Revision as of 18:10, 5 March 2025

Html structure


previous version

<body>
    <p id="sentence">
        <span class="word_do">do</span>
        <span class="word_tigers">tigers</span>
        <span class="word_melt">melt</span>
        <span class="word_like">like</span>
        <span class="word_butter">butter</span>
        <span class="word_in">in</span>
        <span class="word_the">the</span>
        <span class="word_forest">forest</span>
        <span class="word_questionmark">?</span>
    </p> 

    <div id="stage">
        <div class="do"></div>
        <div class="tigers object"></div>
        <div class="melt object"></div>
        <div class="like"></div>
        <div class="butter object"></div>
        <div class="in"></div>
        <div class="the"></div>
        <div class="forest object"></div>
        <div class="questionmark"></div>
    </div>
   
    <script src="java1.js"></script>
</body>

now all the divs are also siblings, so they will listen to same command that controls the spans(words)


Javascript


previous version

basic variables

let sentence = document.getElementById("sentence")//this is added from the first version, in the first version, I didn’t define "sentence", so there was no way to know where to put the words back from removedWords in "bringBack"function.
let words = Array.from(document.querySelectorAll("#sentence span"));
let removedWords = [];



randomly removing, bringing words back function

function removeRandomWord () {
    if (words.length > 1) {
        let pickRandom = Math.floor(Math.random() * words.length);
        let remove = words.splice(pickRandom,1)[0]; //had to add "[0]" to pull the word out of the array and turn it into node. switching between nodelists and arrays requires extra steps
        removedWords.push(remove);
        remove.remove(); //.remove() method removes the element from the DOM.
    }
}

function bringbackRandomWord () {
    if (removedWords.length > 0) {
        let pickRandom = Math.floor(Math.random() * removedWords.length);
        let bringBack = removedWords.splice(pickRandom,1)[0];
        words.push(bringBack);
        sentence.innerHTML = sentence.innerHTML + " "; //try to add space between the spans but this doesn't work at the moment.
        sentence.appendChild(bringBack); //opposite of remove() is appendChild()
    }
}
↳ how do I add a space (" ") after each word that is brought back?
sentence.innerHTML += " ";
↳ this works only the first time shrinking the browser, but when i try again, it stops working. then at some point, it starts adding more words. as if the words are duplicating itself





  • I think appendChild() should be a way to go. Just like how I brought the spans back with that method. But using it with properties like innerHTML, innerText, textContent, doesn’t work.
↳ throwing spaghetties on the wall approach using those 3 properties around the line did work at some point in terms of adding spaces in between my spans, but the browser rendered all my spans as [object HTMLSpanElement]. technically doesn’t work, but it’s something.
↳ so [object HTMLSpanElement] means it broke the structure of my spans and turned them into raw text within sentence.innerHTML
↳ this means the original span elements are no longer treated as elements, but instead they got converted into plain text.
↳ my spans are DOM node/elements, they should not be rendered as raw text. I need to use DOM methods again for appendchild() instead of DOM properties to control the elements directly with js.







sentence.appendChild(document.createTextNode(" "));

it works.



two innerWidth variables and "resize" eventlistener

let prevWidth = window.innerWidth;

first define prevWidth as innerWidth outside of the eventlistener

window.addEventListener("resize", () => {
    let currWidth = window.innerWidth;
    let widthChange = Math.abs(prevWidth - currWidth);
    console.log(widthChange)

    if (currWidth < prevWidth && widthChange > 100) {
        removeRandomWord();
        prevWidth = currWidth;
    }
    else if (prevWidth < currWidth && widthChange > 100) {
        bringbackRandomWord();
        prevWidth = currWidth;
    }
     //instead of updating prevWidth at the very end of the function, update it inside each if statement
     //previous version was updating currWidth to prevWidth, i thought i was saving the currWidth to prevWidth but it works other way around.
});




break

Undefined butter.png



synchronizing spans and divs

added basic variables and queryselectorall for the divs

let sentence = document.getElementById("sentence");
let space = document.getElementById("space");

let words = Array.from(document.querySelectorAll("#sentence span"));
let figures = Array.from(document.querySelectorAll("#space div"));

let removedWords = [];
let removedDivs = [];



now adding under function removeRandom ()
with Joseph's help,

function removeRandom () {
    if (words.length > 1) {
        let pickRandom = Math.floor(Math.random() * words.length );
        let removing = words.splice(pickRandom,1)[0];
        removedWords.push(removing);
        removing.remove(); //.remove() method removes the element from the DOM.

        var spaceRemoving = removing.classList[0].replace("word_","");
        let matchingDiv = document.querySelector("#space div." + spaceRemoving);
        
        removedDivs.push(matchingDiv);
        matchingDiv.remove();
    }
}





code explained:

CSS