Grab a notecard and answer the following questions:
Name | Description |
---|---|
document.createElement("tag") | creates and returns a new empty DOM node representing an element of that type |
parent.appendChild(child) | Appends the given DOM element (child) into the parent DOM element (parent). |
// create a new <h2> node
let newHeading = document.createElement("h2");
// Add text to the node
newHeading.textContent = "This is a heading!"
// append the h2 to element with id #intro
id("intro").appendChild(newHeading);
The slides below describe some of the different HTML elements found in the section exercises, as well as some extra ones, which you may find helpful for following the JS requirements (and learn a bit more about common types of UI elements)!
It is often useful to group form-elements together on the page to show that they are related.
fieldset
: A container to group UI elementslegend
: A legend for a fieldset
which appears by
default as the text within the top-left border
Note that we also see form
elements used to group UI elements,
but since we're not submitting to any server in this exercise, we choose to use a fieldset
.
textarea
textarea
elements can be used for multiline text input, such as paragraphs or messages.
These are used in the extra Encrypt-It exercise.
select
elements
represent dropdown menus. They contain option
elements, which represent each option in the dropdown.
The value of the select
element is equal to the value of the chosen option
element.
These are used to select tiers in the tier list maker, and you will be programatically populating the options of the select to match the tiers.
The input
element serves many roles, depending on its type
attribute.
type="text"
:
Accepts single-line text input.
type="radio"
:
Accepts one of multiple options. Give multiple radio inputs the same name
attribute
to link them together.
type="checkbox"
:
Like radio, but accepts any number of the given options.
There are many more that you can look up on MDN. The tier list maker uses text input elements.
Oftentimes you want to label form elements with text, and have the form element get
selected if the user clicks on the text. By surrounding the text with a
label
element, and giving it a for
attribute equal to the id of another form element,
it will select that form element remotely when clicked.
This is a pretty complex page! Here is a running solution (don't read the code). We will take it step by step. Be sure to test your code as you go. Go down to get started.
These exercises are designed to get you acquainted with creating and appending elements on the page, interacting with form elements, and manipulating the page in other ways through event-driven programming. When you are done, you will have a functional tier-list maker, which is a tool designed to show the relative value of various related things (and quite popular on the internet lately.)
We have provided tier-list.zip
with starting HTML
for you to use and build upon, as well as starter
CSS which you are free to edit. There is also a mostly-empty JS file to follow along in.
We will be implementing the following features, in this order:
There are many further changes you can make beyond this if you want to make a robust, powerful tier-list tool, but this is a good starting point.
The provided JS code has many empty functions to help guide your programming. In practice, you will have to determine for yourself what functions need to be built to make a product, which takes practice.
Hook up event listeners for four UI elements to these functions to get started. You can use alerts to confirm they are set up properly. Read the function documentation to determine which function matches the intended goal.
#make-list
: On click, should switch to the maker view and generate the empty tier list in place of whatever was there before.#row-count
: On change, update the number of text input elements to match the number of tiers.#add-item
: On click, should add an item to the tier list based on user input.#go-back
: On click, switch to the setup view.
Add code to the relevant functions you linked in part 1 so that clicking the
#make-list
element goes to the #maker
view, and clicking the
#go-back
element goes to the #setup
view.
You may find classList.toggle(class)
to be a useful DOM object function.
It will flip the class on/off to the opposite state of what it was previously in
You can remove DOM elements from the page in a few different ways.
element.parentNode.removeChild(element);
.
This gets the elements parent, and tells the parent to remove itself as a child.container.innerHTML = ""
. This will clear out all of the HTML inside.NOTE: For code quality, do not use innerHTML outside of clearing parent containers in this class. This is due to security vulnerabilities with innerHTML as well as other code quality concerns.
When the #row-count
element is changed by the user,
clear out the text input elements previously in the #row-names
element, and repopulate it with the number of elements specified in the #row-count
element (do not worry about negatives.)
When making an input element with createElement
, you need to remember to
set the type
attribute on the element to the correct kind.
Each tier-row has the following structure:
<div class="tier-row">
<p class="tier-name"><!-- Tier Name Here --></p>
<div class="tier-items" id="tier-0">
<!-- img elements here later -->
</div>
</div>
Start by writing generateTierRow
to generate and return this HTML object.
The tier name and .tier-items
id are passed in as parameters.
Next, using generateTierRow
, write some of makeList
that will
append a .tier-row
to the #tier-list
for each row specified
in the #setup
text inputs. Use "tier-n", where n is the row from the top, as
an id to reference later when we add items to the list. Be sure to clear out whatever tier
list was there previously before you start adding rows, and add the relevant classes so that
the CSS works.
Also in makeList
, we will be creating option
elements for
the #tier-select
element, one for each tier. Each option should have
text content equal to the tier name, and a value equal to the id you set in step 4 on
the .tier-items
element. This way, a selected tier name can link to a row
in the list. To factor out some code, you might want to also write and use the generateTierOption
function.
Finally we can add some items to the list. Complete the relevant functions so that when
the #add-item
button is pressed, an item is added to the list in the
specified tier, with the specified src, and with an alt equal to the item name.
If the user wants to view the name or image source of a tier item, they should be able to do so by clicking the item. When a tier-item is created, add a click event listener to it which triggers a function that displays the item's properties in the fieldset. Then complete that function.
Finally, we want to be able to delete items. Add another event listener to each item, this time for double-clicks, which deletes the item from the DOM tree.
With steps 7 and 8 implemented, you can now edit items by double-clicking to remove them, changing some of the values in the fieldset, and then re-adding them!
These are non-testable things you could look into if you are curious how they might be done.
In this series of exercises, you will be practicing using different UI elements in HTML with a JavaScript program to perform some operations on user input. Specifically, you will finish a cryptogram generator, which takes any message as input and outputs a cipher message in a few different possible outputs.
We have provided encrypt-it.zip
with starting HTML
for you to use and build upon. We have also included
some CSS, although you're free to add styling on your own!
encrypt-it.js
Now you'll write a bit of JavaScript testing code that logs a message to the console. This is just a test to make sure that your browser is running your JavaScript file, before we move on to the main execises.
console.log("Window loaded!");
such that the message is logged to the console when the page is loaded
HTML
page to your JavaScript file using a script
tagconsole
message? If so, move on.
Otherwise, double-check your script
tag syntax or ask a TA for help.
Now let's set up a very basic JS event handler. Modify your JS code and
so that the "Button clicked!" console
message won't
output until the user clicks the "Encrypt-It!" button.
Strategy:
window
's
load
event is needed (remeber we don't have access to the DOM
until the page is loaded).
console
statement inside a new function
handleClick
.
handleClick
function is called.
console.log
message? If so, move on. Otherwise, double-check the syntax and
for both of your event listeners (window load and button click), or ask a TA for helpModify your JS code so that when the user clicks "Encrypt-It!", the text in
the input text area will be encrypted using a basic shift-cipher, and output
into the page's paragraph element with the id of output
.
Details:
document.getElementById
or
document.querySelector
to access a DOM element in JS.
handleClick
function so that when called, it now retrieves the textarea's text value and
generates a shift cipher (algorithm discussed on the slide below; a
solution for this cipher function is provided at the very bottom if
you'd like to skip the algorithm part). This generated cipher will be
output as text in the #result
paragraph.
The rules of a shift cipher are fairly straightforward. Let the English alphabet we all know and love(?) be called A. Let the shift-encrypted alphabet be called C. For simplicity, we will shift letters in our encryption function by 1 letter. Then C is defined as mapping each letters in A to the letter alphabetically next. For example, 'a' is mapped to 'b', 'b' is mapped to 'c', ... and 'z' is mapped to 'a' (creating a cycle of 26 letters). In this exercise, we will consider uppercase letters and lowercase letters equivalent to one another (ie, 'a' is considered equal to 'A').
Visually, the cipher can be represented as the following:
input letter a b c d e f g h i j k l m n o p q r s t u v w x y z | | | | | | | | | | | | | | | | | | | | | | | | | | v v v v v v v v v v v v v v v v v v v v v v v v v v output letter b c d e f g h i j k l m n o p q r s t u v w x y z a
Your task in this part is to convert the text in the input text area from alphabet A to alphabet C. This is all you need to know to implement the cipher in this lab, but if you would like additional hints, there are some provided in the slide below.
Note that the value you get from the textarea is just a long string. So your goal is to build up a new string that is the result of applying the cipher to each letter in the input text, in order, and adding it to your result string.
There are a few ways to go about this, but note that one of the most
intuitive approaches would be to use a for
loop through the input
string and add 1 to each letter (letters are actually represented by numerical values,
so this is a natural operation). To handle the z -> a shift, you can add a special case
for each letter, or use mod arithmetic to avoid this extra case.
You may find charCodeAt(index)
and fromCharCode(asciiNum)
helpful for this problem.
If you get stuck on this function, you may refer to a sample solution on the slide below. But it's strongly recommended you implement it on your own!
One function solution is given below (you can also solve this with arrays):
/**
* Returns an encrypted version of the given text, where
* each letter is shifted alphabetically ahead by 1 letter,
* and 'z' is shifted to 'a' (creating an alphabetical cycle).
*/
function shiftCipher(text) {
text = text.toLowerCase();
let result = "";
for (let i = 0; i < text.length; i++) {
if (text[i] < 'a' || text[i] > 'z') {
result += text[i];
} else if (text[i] === 'z') {
result += 'a';
} else { // letter is between 'a' and 'y'
let letter = text.charCodeAt(i);
let resultLetter = String.fromCharCode(letter + 1);
result += resultLetter;
}
}
return result;
}
Now that you have a cool encryption feature implemented, let's add some features for the user to decorate their encrypted message.
We have broken this part into are a few smaller exercises - move down the slides to work through them!
First, we want to restrict the shift cipher functionality to only work when "Shift Cipher" is selected in the drop down menu. Only when this is the currently-selected option and then the "Encrypt-It" button is clicked should the input text be encrypted.
For dropdown menus, you can get the value of the current option
using el.value
, where el
is the DOM element for
the select
dropdown.
When the Reset button is clicked, the textarea and the output paragraph should
both be cleared (using textContent
).
Next, implement a feature such that when the all-caps checkbox is checked, all of the text in the output paragraph appear only in uppercase.
To do so, add a CSS file with a class ".uppercase" that
uses text-transform: "uppercase";
to make an element all-uppercase. When
the "All Caps" option is checked, the output paragraph should have this
class. When unchecked, it should not have this class so that it uses
whatever casing was used in the original input text.
Hint 1: The event corresponding to changing the state of a checkbox input as
checked/unchecked is change
.
Hint 2: To update the class list of a DOM element, you can use
el.classList.add("classname")
and
el.classList.remove("classname")
. We'll see this more in lecture!
Implement a feature to such that the text in the output paragraph should have the font size of whatever is currently selected in the radio button group.
To minimize changing styles in JavaScript, you can add CSS classes to accomplish font size changes (similar to the previous step).
Note: This part is a more challenging feature we have provided if you'd like to explore a more advanced cipher algorithm and and add a few more UI features. We have also suggested other features to try on the next slide!
In this part, you will implement the "Randomized" cipher option. This is similar to the Shift Cipher, only "result alphabet" C is randomly-generated. In other words, each letter in the English alphabet is mapped to one of the 25 other letters, but no two letters may have the same mapping (e.g., "a" and "c" can not both map to "d").
First, you should modify your button event handler to determine whether the "Shift Cipher" or "Randomized Cipher" option is selected in the dropdown menu. If the "Randomized Cipher" option is selected, it should call a new function which outputs a randomized encrypted version of the input text area to the output div.
If you would like some hints for writing this algorithm, there are some in the slides below.
Because we aren't simply adding 1 to each letter (or mapping 'a' to 'z'), you might find an array helpful when creating a random cipher alphabet. One way to randomly-generate the cipher is to keep track of unchosen letters in the English alphabet using a string or array. Then, randomly choose one of the unchosen letters (you may find Math.floor()
and Math.random()
useful here).
Next, push this randomly-chosen letter to the end of the cipher array. Continue this process until you have removed all letters from your English alphabet and have 26 letters in your cipher array (where the first index is the letter randomly-chosen first, and the last index is the letter that was chosen last).
If you get stuck on this function, you may refer to a sample solution on the slide below. But it's strongly recommended you implement it on your own.
One possible solution is given below:
function generateCipher(text) {
let alphabet = "abcdefghijklmnopqrstuvwxyz".split("");
let cipher = [];
// it's poor style to hardcode a magic number like 26
let alphabetLength = alphabet.length;
for (let i = 0; i < alphabetLength; i++) {
let randomIndex = Math.floor(Math.random() * alphabet.length);
cipher.push(alphabet.splice(
[Math.floor(Math.random() * alphabet.length)], 1));
}
document.getElementById("output").textContent = cipher;
let result = "";
for (let i = 0; i < outputText.length; i++) {
if (text[i] >= 'a' && text[i] <= 'z') {
let letterCode = text.charCodeAt(i) - 'a'.charCodeAt(0);
result += cipher[letterCode];
} else {
result += text[i];
}
}
document.getElementById("output").textContent = result.replace(",", "");
}
Did you enjoy making your own encrypted messages? Here are a few other ideas to add to your file:
.txt
file of dictionary words,
you can try to write a tool that takes input (probably from a Shift or Randomized cipher) and tries to decode it,
matching sequences of characters to words in the dictionary.