<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://ragnagoats.net:443/wiki/index.php?action=history&amp;feed=atom&amp;title=MediaWiki%3AGadget-test.js</id>
	<title>MediaWiki:Gadget-test.js - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://ragnagoats.net:443/wiki/index.php?action=history&amp;feed=atom&amp;title=MediaWiki%3AGadget-test.js"/>
	<link rel="alternate" type="text/html" href="https://ragnagoats.net:443/wiki/index.php?title=MediaWiki:Gadget-test.js&amp;action=history"/>
	<updated>2026-04-10T10:13:37Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.41.0</generator>
	<entry>
		<id>https://ragnagoats.net:443/wiki/index.php?title=MediaWiki:Gadget-test.js&amp;diff=1364&amp;oldid=prev</id>
		<title>Administrator: Created page with &quot;// Global variables let skillLevels = {}; let skillsByClass = {}; let maxJobLevels = {}; let slot = 1;  document.addEventListener(&#039;DOMContentLoaded&#039;, () =&gt; {     loadStateFromLocalStorage(); });   // Function to read a local JSON file function loadLocalJSONFile(file, callback) {     const xhr = new XMLHttpRequest();     xhr.overrideMimeType(&#039;application/json&#039;);     xhr.open(&#039;GET&#039;, file, true);     xhr.onreadystatechange = function () {         if (xhr.readyState === 4 &amp;&amp;...&quot;</title>
		<link rel="alternate" type="text/html" href="https://ragnagoats.net:443/wiki/index.php?title=MediaWiki:Gadget-test.js&amp;diff=1364&amp;oldid=prev"/>
		<updated>2024-01-18T12:47:48Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;// Global variables let skillLevels = {}; let skillsByClass = {}; let maxJobLevels = {}; let slot = 1;  document.addEventListener(&amp;#039;DOMContentLoaded&amp;#039;, () =&amp;gt; {     loadStateFromLocalStorage(); });   // Function to read a local JSON file function loadLocalJSONFile(file, callback) {     const xhr = new XMLHttpRequest();     xhr.overrideMimeType(&amp;#039;application/json&amp;#039;);     xhr.open(&amp;#039;GET&amp;#039;, file, true);     xhr.onreadystatechange = function () {         if (xhr.readyState === 4 &amp;amp;&amp;amp;...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;// Global variables&lt;br /&gt;
let skillLevels = {};&lt;br /&gt;
let skillsByClass = {};&lt;br /&gt;
let maxJobLevels = {};&lt;br /&gt;
let slot = 1;&lt;br /&gt;
&lt;br /&gt;
document.addEventListener(&amp;#039;DOMContentLoaded&amp;#039;, () =&amp;gt; {&lt;br /&gt;
    loadStateFromLocalStorage();&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Function to read a local JSON file&lt;br /&gt;
function loadLocalJSONFile(file, callback) {&lt;br /&gt;
    const xhr = new XMLHttpRequest();&lt;br /&gt;
    xhr.overrideMimeType(&amp;#039;application/json&amp;#039;);&lt;br /&gt;
    xhr.open(&amp;#039;GET&amp;#039;, file, true);&lt;br /&gt;
    xhr.onreadystatechange = function () {&lt;br /&gt;
        if (xhr.readyState === 4 &amp;amp;&amp;amp; xhr.status === 200) {&lt;br /&gt;
            callback(xhr.responseText);&lt;br /&gt;
        }&lt;br /&gt;
    };&lt;br /&gt;
    xhr.send(null);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function updateClassHeader(className) {&lt;br /&gt;
    const classHeading = document.querySelector(`h2[data-class-name=&amp;quot;${className}&amp;quot;]`);&lt;br /&gt;
    if (classHeading) {&lt;br /&gt;
        // Calculate the total skill points for this class&lt;br /&gt;
        const totalSkillPoints = Object.values(skillLevels[className] || {}).reduce((sum, level) =&amp;gt; sum + level, 0);&lt;br /&gt;
        const maxLevel = maxJobLevels[className];&lt;br /&gt;
        classHeading.textContent = `${className} (${totalSkillPoints} / ${maxLevel})`;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Function to display JSON data with dynamic max job levels and tooltips&lt;br /&gt;
function displayJSONData(data) {&lt;br /&gt;
    const parsedData = JSON.parse(data);&lt;br /&gt;
    const dataDisplay = document.getElementById(&amp;#039;data-display&amp;#039;);&lt;br /&gt;
&lt;br /&gt;
    // Group skills by class name and initialize skill levels&lt;br /&gt;
    skillsByClass = {};&lt;br /&gt;
    parsedData.skills.forEach(skillItem =&amp;gt; {&lt;br /&gt;
        const className = skillItem.className;&lt;br /&gt;
        if (!skillsByClass[className]) {&lt;br /&gt;
            skillsByClass[className] = [];&lt;br /&gt;
            // No need to initialize skillLevels here as it will be done in the next step&lt;br /&gt;
        }&lt;br /&gt;
        skillsByClass[className].push(skillItem);&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // Initialize skillLevels with each skill starting at 0&lt;br /&gt;
    Object.keys(skillsByClass).forEach(className =&amp;gt; {&lt;br /&gt;
        skillLevels[className] = {};&lt;br /&gt;
        skillsByClass[className].forEach(skill =&amp;gt; {&lt;br /&gt;
            skillLevels[className][skill.name] = 0;&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // Get maximum job levels&lt;br /&gt;
    maxJobLevels = parsedData.maxJob.reduce((levels, job) =&amp;gt; {&lt;br /&gt;
        levels[job.name] = job.maxLevel;&lt;br /&gt;
        return levels;&lt;br /&gt;
    }, {});&lt;br /&gt;
    // Sort the classes in the order they appear in the JSON file&lt;br /&gt;
    const sortedClasses = parsedData.skills.reduce((classes, skill) =&amp;gt; {&lt;br /&gt;
        if (!classes.includes(skill.className)) {&lt;br /&gt;
            classes.push(skill.className);&lt;br /&gt;
        }&lt;br /&gt;
        return classes;&lt;br /&gt;
    }, []);&lt;br /&gt;
&lt;br /&gt;
    function createTooltip(skillDescription) {&lt;br /&gt;
        const tooltip = document.createElement(&amp;#039;div&amp;#039;);&lt;br /&gt;
        tooltip.classList.add(&amp;#039;tooltip&amp;#039;);&lt;br /&gt;
        tooltip.innerHTML = skillDescription;&lt;br /&gt;
        document.body.appendChild(tooltip);&lt;br /&gt;
&lt;br /&gt;
        return tooltip;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Loop through the sorted classes&lt;br /&gt;
    sortedClasses.forEach(className =&amp;gt; {&lt;br /&gt;
        // Create a heading for the class with dynamic max level (starting from 0)&lt;br /&gt;
        const classHeading = document.createElement(&amp;#039;h2&amp;#039;);&lt;br /&gt;
        classHeading.setAttribute(&amp;#039;data-class-name&amp;#039;, className);&lt;br /&gt;
        classHeading.textContent = className;&lt;br /&gt;
        updateClassHeader(className); // Update class header initially&lt;br /&gt;
        dataDisplay.appendChild(classHeading);&lt;br /&gt;
&lt;br /&gt;
	dataDisplay.addEventListener(&amp;#039;contextmenu&amp;#039;, event =&amp;gt; event.preventDefault());&lt;br /&gt;
&lt;br /&gt;
        // Create a div to hold the skills horizontally&lt;br /&gt;
        const skillsContainer = document.createElement(&amp;#039;div&amp;#039;);&lt;br /&gt;
        skillsContainer.classList.add(&amp;#039;skills-container&amp;#039;);&lt;br /&gt;
&lt;br /&gt;
        // Loop through the skills for this class&lt;br /&gt;
        skillsByClass[className].forEach(skillItem =&amp;gt; {&lt;br /&gt;
            // Create a skill container to display each skill&lt;br /&gt;
            const skillContainer = document.createElement(&amp;#039;div&amp;#039;);&lt;br /&gt;
            skillContainer.classList.add(&amp;#039;skill-container&amp;#039;);&lt;br /&gt;
&lt;br /&gt;
            // Create an image element for the skill picture (with tooltip)&lt;br /&gt;
            const skillPicture = document.createElement(&amp;#039;img&amp;#039;);&lt;br /&gt;
            skillPicture.src = skillItem.skillPicture;&lt;br /&gt;
            skillPicture.alt = &amp;#039;Skill Picture&amp;#039;;&lt;br /&gt;
            skillPicture.classList.add(&amp;#039;skill-picture&amp;#039;);&lt;br /&gt;
	skillPicture.addEventListener(&amp;#039;contextmenu&amp;#039;, event =&amp;gt; event.preventDefault());&lt;br /&gt;
&lt;br /&gt;
            // Set data attributes for skill picture and skill container&lt;br /&gt;
            skillPicture.setAttribute(&amp;#039;data-skill-picture&amp;#039;, skillItem.skillPicture);&lt;br /&gt;
            skillContainer.setAttribute(&amp;#039;data-skill-name&amp;#039;, skillItem.name);&lt;br /&gt;
            skillContainer.setAttribute(&amp;#039;data-class-name&amp;#039;, className);&lt;br /&gt;
&lt;br /&gt;
            // Check if the skill is a quest skill and add a class for quest skills&lt;br /&gt;
            if (skillItem.isQuestSkill) {&lt;br /&gt;
                skillContainer.classList.add(&amp;#039;quest-skill&amp;#039;); // Add a class for quest skills&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            // Append the skill picture to the skill container&lt;br /&gt;
            skillContainer.appendChild(skillPicture);&lt;br /&gt;
&lt;br /&gt;
            // Create a div to hold the skill name&lt;br /&gt;
            const skillNameDiv = document.createElement(&amp;#039;div&amp;#039;);&lt;br /&gt;
            skillNameDiv.classList.add(&amp;#039;skill-name&amp;#039;);&lt;br /&gt;
            skillNameDiv.textContent = skillItem.name; // Set the skill name text&lt;br /&gt;
&lt;br /&gt;
            // Append the skill name div to the skill container&lt;br /&gt;
            skillContainer.appendChild(skillNameDiv);&lt;br /&gt;
&lt;br /&gt;
            // Create bubbles for skill level&lt;br /&gt;
            const skillLevel = document.createElement(&amp;#039;div&amp;#039;);&lt;br /&gt;
            skillLevel.classList.add(&amp;#039;skill-level&amp;#039;);&lt;br /&gt;
&lt;br /&gt;
            // Create gray bubbles based on maxLevel&lt;br /&gt;
            for (let i = 0; i &amp;lt; skillItem.maxLevel; i++) {&lt;br /&gt;
                const bubble = document.createElement(&amp;#039;div&amp;#039;);&lt;br /&gt;
                bubble.classList.add(&amp;#039;bubble&amp;#039;, &amp;#039;gray&amp;#039;);&lt;br /&gt;
                skillLevel.appendChild(bubble);&lt;br /&gt;
            }&lt;br /&gt;
	loadStateFromLocalStorage();&lt;br /&gt;
            // Function to handle skill level changes&lt;br /&gt;
function changeSkillLevel(e) {&lt;br /&gt;
    e.stopPropagation();&lt;br /&gt;
    const skillContainer = e.currentTarget;&lt;br /&gt;
    const className = skillContainer.getAttribute(&amp;#039;data-class-name&amp;#039;);&lt;br /&gt;
    const skillName = skillContainer.getAttribute(&amp;#039;data-skill-name&amp;#039;);&lt;br /&gt;
    const skillItem = skillsByClass[className].find(skill =&amp;gt; skill.name === skillName);&lt;br /&gt;
&lt;br /&gt;
    // Determine new level based on click&lt;br /&gt;
    if (e.button === 0) { // Left click&lt;br /&gt;
        // Increase skill level&lt;br /&gt;
        if (skillLevels[className][skillName] &amp;lt; skillItem.maxLevel) {&lt;br /&gt;
            skillLevels[className][skillName]++;&lt;br /&gt;
        }&lt;br /&gt;
    } else if (e.button === 2) { // Right click&lt;br /&gt;
        // Decrease skill level&lt;br /&gt;
        if (skillLevels[className][skillName] &amp;gt; 0) {&lt;br /&gt;
            skillLevels[className][skillName]--;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    updateClassHeader(className);&lt;br /&gt;
    saveStateToLocalStorage();&lt;br /&gt;
    refreshUI();&lt;br /&gt;
}            // Add event listeners to change skill level on clicks&lt;br /&gt;
            skillContainer.addEventListener(&amp;#039;click&amp;#039;, changeSkillLevel);&lt;br /&gt;
            skillContainer.addEventListener(&amp;#039;contextmenu&amp;#039;, changeSkillLevel);&lt;br /&gt;
&lt;br /&gt;
            // Append the skill level to the skill container&lt;br /&gt;
            skillContainer.appendChild(skillLevel);&lt;br /&gt;
&lt;br /&gt;
            // Append the skill container to the skills container&lt;br /&gt;
            skillsContainer.appendChild(skillContainer);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        // Append the skills container to the dataDisplay element&lt;br /&gt;
        dataDisplay.appendChild(skillsContainer);&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // Function to handle skill container hover event&lt;br /&gt;
    function handleSkillHover(event) {&lt;br /&gt;
        const skillContainer = event.currentTarget;&lt;br /&gt;
        const skillName = skillContainer.getAttribute(&amp;#039;data-skill-name&amp;#039;);&lt;br /&gt;
&lt;br /&gt;
        // Find the skill that corresponds to the hovered skill container&lt;br /&gt;
        const hoveredSkill = parsedData.skills.find(skill =&amp;gt; skill.name === skillName);&lt;br /&gt;
		&lt;br /&gt;
		    const tooltip = createTooltip(hoveredSkill.description);&lt;br /&gt;
&lt;br /&gt;
            // Position the tooltip relative to the skill image&lt;br /&gt;
            const skillPicture = skillContainer.querySelector(&amp;#039;.skill-picture&amp;#039;);&lt;br /&gt;
            const skillPictureRect = skillPicture.getBoundingClientRect();&lt;br /&gt;
            const offsetX = 10; // Adjust the X offset as needed&lt;br /&gt;
            const offsetY = 10; // Adjust the Y offset as needed&lt;br /&gt;
&lt;br /&gt;
            tooltip.style.left = `${skillPictureRect.right + offsetX}px`;&lt;br /&gt;
            tooltip.style.top = `${skillPictureRect.top - offsetY}px`;&lt;br /&gt;
&lt;br /&gt;
            // Handle mouseleave to remove the tooltip&lt;br /&gt;
            skillContainer.addEventListener(&amp;#039;mouseleave&amp;#039;, () =&amp;gt; {&lt;br /&gt;
                document.body.removeChild(tooltip);&lt;br /&gt;
            });&lt;br /&gt;
		//skillContainer.addEventListener(&amp;#039;contextmenu&amp;#039;, event =&amp;gt; event.preventDefault());&lt;br /&gt;
&lt;br /&gt;
        if (hoveredSkill) {&lt;br /&gt;
            // Iterate through the required skills and highlight their containers and change bubble colors&lt;br /&gt;
            hoveredSkill.requires.forEach(req =&amp;gt; {&lt;br /&gt;
                const requiredSkillName = req.skillName;&lt;br /&gt;
                const requiredSkillContainer = document.querySelector(`[data-skill-name=&amp;quot;${requiredSkillName}&amp;quot;]`);&lt;br /&gt;
		requiredSkillContainer.classList.add(&amp;#039;highlight2&amp;#039;);&lt;br /&gt;
                if (requiredSkillContainer) {&lt;br /&gt;
                    const requiredLevel = req.requiredLevel;&lt;br /&gt;
		    meep = 0;&lt;br /&gt;
                    // Change bubble colors based on required level and only if not met&lt;br /&gt;
                    const requiredSkillLevel = requiredSkillContainer.querySelector(&amp;#039;.skill-level&amp;#039;);&lt;br /&gt;
                    const blueBubbles = requiredSkillLevel.querySelectorAll(&amp;#039;.bubble.blue&amp;#039;);&lt;br /&gt;
                    const grayBubbles = requiredSkillLevel.querySelectorAll(&amp;#039;.bubble.gray&amp;#039;);&lt;br /&gt;
                    blueBubbles.forEach((blueBubble, index) =&amp;gt; {&lt;br /&gt;
			meep++;&lt;br /&gt;
                    });&lt;br /&gt;
                    grayBubbles.forEach((grayBubble, index) =&amp;gt; {&lt;br /&gt;
                        if (index+meep &amp;gt;= requiredLevel) {&lt;br /&gt;
                            grayBubble.style.backgroundColor = &amp;#039;&amp;#039;; //&lt;br /&gt;
			    skillContainer.classList.remove(&amp;#039;highlight&amp;#039;);&lt;br /&gt;
                        } else {&lt;br /&gt;
                            grayBubble.style.backgroundColor = &amp;#039;purple&amp;#039;; // Change bubble to purple&lt;br /&gt;
				requiredSkillContainer.classList.add(&amp;#039;highlight&amp;#039;);&lt;br /&gt;
				requiredSkillContainer.classList.remove(&amp;#039;highlight2&amp;#039;);&lt;br /&gt;
                        }&lt;br /&gt;
			if(meep &amp;gt;= requiredLevel){&lt;br /&gt;
				skillContainer.classList.remove(&amp;#039;highlight&amp;#039;);&lt;br /&gt;
				&lt;br /&gt;
				console.log(meep);&lt;br /&gt;
			}&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Function to handle skill container exit event&lt;br /&gt;
    function handleSkillExit() {&lt;br /&gt;
        // Remove highlighting and required level information from all skill containers&lt;br /&gt;
        skillContainers.forEach(skillContainer =&amp;gt; {&lt;br /&gt;
            skillContainer.classList.remove(&amp;#039;highlight&amp;#039;);&lt;br /&gt;
	    skillContainer.classList.remove(&amp;#039;highlight2&amp;#039;);&lt;br /&gt;
            skillContainer.style.backgroundColor = &amp;#039;&amp;#039;; // Remove background color&lt;br /&gt;
            const skillLevel = skillContainer.querySelector(&amp;#039;.skill-level&amp;#039;);&lt;br /&gt;
            if (skillLevel) {&lt;br /&gt;
                const bubbles = skillLevel.querySelectorAll(&amp;#039;.bubble&amp;#039;);&lt;br /&gt;
                bubbles.forEach(bubble =&amp;gt; {&lt;br /&gt;
                    bubble.style.backgroundColor = &amp;#039;&amp;#039;; // Remove bubble background color&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Attach event listeners to each skill-container for hover events&lt;br /&gt;
    const skillContainers = document.querySelectorAll(&amp;#039;.skill-container&amp;#039;);&lt;br /&gt;
    skillContainers.forEach(skillContainer =&amp;gt; {&lt;br /&gt;
        skillContainer.addEventListener(&amp;#039;mouseenter&amp;#039;, handleSkillHover);&lt;br /&gt;
        skillContainer.addEventListener(&amp;#039;mouseleave&amp;#039;, handleSkillExit);&lt;br /&gt;
    });&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
loadLocalJSONFile(&amp;#039;your-json-file.json&amp;#039;, displayJSONData);&lt;br /&gt;
&lt;br /&gt;
// Function to save the current state to localStorage&lt;br /&gt;
function saveStateToLocalStorage() {&lt;br /&gt;
    const state = {&lt;br /&gt;
        skillLevels: skillLevels&lt;br /&gt;
    };&lt;br /&gt;
    const jsonState = JSON.stringify(state);&lt;br /&gt;
    const jsonState2 = JSON.stringify(slot);&lt;br /&gt;
    localStorage.setItem(&amp;#039;gameState2&amp;#039;+slot, jsonState);&lt;br /&gt;
    localStorage.setItem(&amp;#039;lastslot&amp;#039;, jsonState2);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function loadStateFromLocalStorage() {&lt;br /&gt;
    skillLevels = {};&lt;br /&gt;
    const jsonState2 = localStorage.getItem(&amp;#039;lastslot&amp;#039;);&lt;br /&gt;
	console.log(jsonState2);&lt;br /&gt;
    if (jsonState2) {&lt;br /&gt;
        slot = JSON.parse(jsonState2);&lt;br /&gt;
    }&lt;br /&gt;
    const jsonState = localStorage.getItem(&amp;#039;gameState2&amp;#039;+slot);&lt;br /&gt;
    if (jsonState) {&lt;br /&gt;
        const state = JSON.parse(jsonState);&lt;br /&gt;
        skillLevels = state.skillLevels;&lt;br /&gt;
        refreshUI();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function loadSlot(newSlot) {&lt;br /&gt;
    saveStateToLocalStorage();&lt;br /&gt;
    slot = newSlot;&lt;br /&gt;
    const jsonState = localStorage.getItem(&amp;#039;gameState2&amp;#039;+slot);&lt;br /&gt;
    if (jsonState) {&lt;br /&gt;
        const state = JSON.parse(jsonState);&lt;br /&gt;
        skillLevels = state.skillLevels;&lt;br /&gt;
    }&lt;br /&gt;
    refreshUI();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function refreshUI() {&lt;br /&gt;
    Object.keys(skillsByClass).forEach(className =&amp;gt; {&lt;br /&gt;
        updateClassHeader(className);&lt;br /&gt;
        skillsByClass[className].forEach(skillItem =&amp;gt; {&lt;br /&gt;
            const skillContainer = document.querySelector(`.skill-container[data-skill-name=&amp;quot;${skillItem.name}&amp;quot;][data-class-name=&amp;quot;${className}&amp;quot;]`);&lt;br /&gt;
            if (skillContainer) {&lt;br /&gt;
                updateSkillLevelBubbles(skillContainer, skillItem, className);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function clearData() {&lt;br /&gt;
    localStorage.removeItem(&amp;#039;gameState2&amp;#039;+slot);&lt;br /&gt;
    localStorage.removeItem(&amp;#039;lastslot&amp;#039;);&lt;br /&gt;
    refreshUI();&lt;br /&gt;
    // Additional code to reset the game state in your application&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function updateSkillLevelBubbles(skillContainer, skillItem, className) {&lt;br /&gt;
    const skillLevelContainer = skillContainer.querySelector(&amp;#039;.skill-level&amp;#039;);&lt;br /&gt;
    if (skillLevelContainer) {&lt;br /&gt;
        // Get the current level for this specific skill&lt;br /&gt;
        const skillName = skillContainer.getAttribute(&amp;#039;data-skill-name&amp;#039;);&lt;br /&gt;
        const currentLevel = skillLevels[className][skillName] || 0;&lt;br /&gt;
        &lt;br /&gt;
        const bubbles = skillLevelContainer.querySelectorAll(&amp;#039;.bubble&amp;#039;);&lt;br /&gt;
        bubbles.forEach((bubble, index) =&amp;gt; {&lt;br /&gt;
            if (index &amp;lt; currentLevel) {&lt;br /&gt;
                bubble.classList.add(&amp;#039;blue&amp;#039;);&lt;br /&gt;
                bubble.classList.remove(&amp;#039;gray&amp;#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                bubble.classList.add(&amp;#039;gray&amp;#039;);&lt;br /&gt;
                bubble.classList.remove(&amp;#039;blue&amp;#039;);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Administrator</name></author>
	</entry>
</feed>