GUI and buttons
We call widget a graphical element which can interact with the user. Buttons, checkbox, text entry, etc. are common widgets.
HTML describes a set of basic widgets using the <input> tag that can be used "as it is" with default behavior set for contact forms. However, the behavior of these widget may be finely adapted to your needs using JavaScript.
Consider the following code
HTML<input id="button" type="button" value="click me"> <br> Type some text: <input id="textEntry" type="text">
"use strict"; // Button const button = document.querySelector("#button"); button.addEventListener('click',buttonClicked); function buttonClicked(event) { console.log('clicked'); } // Text entry const textEntry = document.querySelector("#textEntry"); textEntry.addEventListener('change',textModified); function textModified(event) { console.log('text modified into ',textEntry.value); }
- - Check the console when you click on the button, or write some text in the corresponding widget.
- - Adapt the code such that the message `You typed the following text: ${TEXT}` appears when the user click on the button, where `${TEXT}` corresponds to the content of the text widget.
Color box
The widget <input type="color"> allows to select a color interactively. Use the following code to adapt the color of an element in the webpage. HTML<span id="textInColor">You can choose the color of this text.</span> <input id="colorInput" type="color">
const textElement = document.querySelector('#textInColor'); const colorElement = document.querySelector('#colorInput'); colorElement.addEventListener('input', changeColorAction); function changeColorAction(event) { textElement.style.color = colorElement.value; }
- Note that the event type input is called every time the value of the widget is modified.
Exercise: Color Gradient
Create the code allowing to parameterize the extreme color of a rectangular box, as well as its length, as seen in the following example
Hints:
- - Widget allowing color selection and slider can be set using the color and range type.
-
- Example: <input type="color">, and <input id="length" type="range" min="30" max="80">
- Example: <input type="color">, and <input id="length" type="range" min="30" max="80">
- - You can listen to the event input to get a dynamic bahavior during the color selection.
- - The current value of a widget (ex. color, slider value, etc) can be accessed in JavaScript using the syntax elementName.value
- - Background color and width of a DOM element can be changed in JavaScript using the syntax elementName.style.background = ..., and elementName.style.width = ...
-
- Note that the "width" must be set as a string and contains its unit (px, em, %, etc.)
- - A color gradient can be set as the following background color value: linear-gradient(to right, color1, color2); where color1 and color2 correspond to the left and right colors.
When setting the visual appearance of an element, you can use either:
- 1- A separated CSS file associated to your HTML file using the command <link rel="stylesheet" type="text/css" href="style.css"> (the prefered method for real website).
<div class="myClass"> Some content </div>
.myClass { color: red; }
- 2- A single HTML file where the CSS part is described in the >head< tag.
<head> <!-- ... all metadata --> <style> .myClass { color: red; } </style> </head> <body> <div class="myClass"> Some content </div> </body>
- 3- Use an inline "style" on each HTML tag we want to apply it
<div style="color:red;"> Some content </div>
- - Note that this inline definition is to be avoided when writing the HTML code of a website manually (the style must be set for each individual element, and can lead to a lot of repetitions). But it is fine to use it in JavaScript as the automatization is performed by the code.
- - Note also that if you have both inline-style and external CSS acting on the same element, the inline-style will take priority over the CSS.
textContent vs innerHTML
Text content
Consider the following code
HTMLType some text: <input id="textEntry" type="text"> <p>You typed the following text: <span id="textRender"></span> </p>
const textEntry = document.querySelector("#textEntry"); textEntry.addEventListener('change',textModified); function textModified(event) { const textRender = document.querySelector("#textRender"); textRender.textContent = textEntry.value; }
This code basically copies the content of the input into the textContent entry of the HTML.
Note that writing HTML tag (ex. <p>Hello</p>) in the textEntry input is only copied and pasted as string, and not interpreted as HTML.
innerHTML
Now consider this new JavaScript linetextRender.innerHTML = textEntry.value;
TextRender.textContent = textEntry.value;
innerHTML creates a new HTML content from the string parameter. It means that, at the opposite of textContent that was only describing a pure text input, innerHTML is able to interpret HTML tags.
Type <p>Hello</p> in the textEntry, and observe that, this time, the <p> tag is interpreted and Hello appears on a new line.
This may lead to more possibilities of user inputs (ex. insert <p style="font-size:300%;color:red">Text</p>).
For instance: Type the following in the text Entry <img src=x onerror=alert("Hello")>.
This open a popup through the execution of the JavaScript alert function, which is probably not the expected behavior of the program.
Note that this JavaScript only runs on the client side, thus such unexpected code execution is not a real _security risk_ as it cannot impact other distant users or database. However, the principle of code injection to a servers that would run text inputs could be similar, and could leads to more dramatic security issues.
Good practice
As a general good practice rule:- - Avoid the use of innerHTML if an external user (beyond the programmer) can type its content.
- - Prefer the use of more focused modifiers such as textContent, or class modification from a limited set described in the CSS file if you use forms.
As a global security good practice:
- Take care not to let the user having a possible action on something unexpected when using user inputs.
- Always prefer specific functions that cannot execute/evaluate such inputs.