hedyorg / hedy

Hedy is a gradual programming language to teach children programming. Gradual languages use different language levels, where each level adds new concepts and syntactic complexity. At the end of the Hedy level sequence, kids master a subset of syntactically valid Python.
https://www.hedy.org
European Union Public License 1.2
1.26k stars 282 forks source link

🧹 Add HedySelect custom element #5540

Open jpelay opened 1 month ago

jpelay commented 1 month ago

One of the advantages of frameworks is that they allow you to define custom HTML elements and couple them with JavaScript behavior. Since a few years ago, vanilla JavaScript now supports the notion of custom elements as part of the wider technologies used to support web components. The basic notion here is that we can define a template that will hold the HTML code for our element, and then clone that template and attach it to our DOM, at the same time executing a function that will be called once the component is connected.

There's another way to show the component, by using the shadow DOM. This will further encapsulate the element, by hiding it's inner components from the general application, however this has the disadvantage of not being able to use tailwind in this component, since it can't access the CSS stylesheets from the application. Due to this limitation I decided to just attach the element to the old fashioned DOM.

The basic structure of the components is the following:

After doing this we can just use the component within our HTML like we'd do with any other component. With the example of the selects, we used to have a prepareDropdowns function that was called on page load. Now, that function is called for every select once they're connected using the connectedCallback property. The usage of the select in the HTML is like this:

<hedy-select id="select_id">
    <select multiple>
        <option value="1">1</option>
        <option value="2">2</option>
        <option value="3">3</option>
    </select>
</hedy-select>

That inner select will be used to generate the appropriate divs that will make the options, and will eventually be hidden from the document.

To get the selected items, we just need to query our desired hedy-select and use the selected property; this will return a string array with the selected options. Notice that if the select is single, you can just select the first element of the array.

(document.querySelector('#levels_dropdown') as HedySelect).selected

Going forward we can use this idea to replace other parts of our code base that can be made into single, reusable components. Do you guys have any ideas about this?

How to test

Everything should work normally