---
tags: mstu5003, tinker, js
---
# TINKER - Javascript Part 0
### Group #3: Ada Zhou, Aixue Zhang, Regina Wright, Ze Lu
---
### Tinker Activity Stuff:
:::info
Open up **[Bootstrap Meowmix](https://codepen.io/jmk2142/pen/EwKXbo)** as the sandbox for learning the developer tools.

- In codepen go to `Change View > Debug Mode` to open up the page on a new tab with only the Meowmix code. (I.e. no Codepen menus etc.)
- Right-click on the Meowmix heading 1 and do `INSPECT` in order to open up the developer tools.
- OPEN the `Elements` tool which should be one of the tabbed menus in the dev tools. It should already be open, and since you *inspected* the heading 1, the `<h1>` tag should already be highlighted!
- Double-click on different elements, attributes, content and change the values, open them up and explore.
- Drag and drop elements into different parts of the "HTML" structure.
- Click on an element, and look at the `Styles` sub-tool to see what classes and styles are being applied on the element.
- Manipulate some of the existing class style rules. (Double click on stuff and change the values with your keyboard.)
- Add new rules directly to the individual element by adding rules to `element.style { yourRules:here }`
- OPEN the `Console` tool which should be one of the tabbed menus in the dev tools.
- Do not use Codepen's console on the pen editing page. This is a very rudimentary console that does not support many important features we need.
- In console type and run this code:
```javascript=
let mySpan = document.querySelector("#catBadge"); // then press ENTER
console.log(mySpan); // then press ENTER
console.dir(mySpan); // then press ENTER
```
- What seems to be the difference between what gets printed in the console when you do `console.log` vs `console.dir` ? Hint: click on the caret that appears before the output with the `console.dir`.
:::success
Answer: `console.log` displays object as a string, and it bascially shows the code in HTML which is something we are able to understand. `console.dir` is more machine based, it has all the information of an object; it displays the entire hierarchy of an object which can be expanded, including its children, lists of specific properties, etc.
:::
- In the `Elements` tool right-click on the `#catBadge` and do `Copy > Copy Selector`. Paste it somewhere - what do you get? Try this with another element.
:::success
Answer: We got "#catBadge" for `#catBadge`, and "body > div:nth-child(1) > div > div > div > p" for `<p class="small">`. We guess for the element that has an id, when we copy selector and paste, the id name will be copied. But if it's an element without id, a basic hierarchy about where the element is located will be pasted; for example, the p element is in the third nested div of the first div of the body.
:::
- Like before, this time try `Copy > Copy JS Path`. Then, in your console type `console.dir()` and inside the parentheses paste what you copied. We are passing *an argument* into the `console.dir()` function call. Press `ENTER` to execute the code.
- Try this again but for the "Extremely Deadly" badge that is inside our Table.
- Based on your tinkering around with this tool, can you make any inferences about the code and how it works?
:::success
Answer:
- When we click `Copy JS Path`, the "document.querySelector" will be copied together with the selector, while `Copy Selector` can only copy the selector itself. Before we do `console.dir()`, we need to add `let el = the thing we grabbed`. So if we copy JS path, we can directly paste what we copied after `let el = `, but if we copy the selector, we need to type out the "document.querySelector ()" first after the `let el = ` and paste the selector into the parentheses.
- After we paste the code into `console.dir()`, like what we mentioned in the first question about how `console.dir()` works, all the information of the pasted element will be displayed.
:::
<br>
Try some other things in the console. Any JS will work here. NOTES:
- `ENTER` key will exectute the JS statement/expression in the console.
- For multi-line code in the console, use `SHIFT+ENTER` to go to the next line.
- In console (and codepen) if you highlight multiple lines and push `TAB` it will indent all those lines at once.
- `SHIFT+TAB` will detent lines.
```javascript=
clear(); // if you want to clear your console clutter
// and any other JS you want to try out here
let num = 100 + 7;
alert("Hello!");
function boo() {
document.body.innerHTML = "BOO!";
}
boo(); // Note: This will erase Meowmix and you'll have to refresh
```
:::
---
## Elements as HTML vs JS Objects
- **Representation ONE**: *Human visual ideas* - When we think of creating pages, we're thinking of content and how it's visually represented.
- **Representation TWO**: *Human-computer readable structure* - When we talk to the computer, we provide a representaion of our ideas in HTML.
- **Representation THREE**: *Computer internal thinking structure* - When the computer processes our HTML, it turns it into another structural form where every element in our HTML and its properties are represented as an object. Each of these objects are nested to preserve the hierarchical relationship as a GIANT object called the **DOM or document object model**.
We imagine this:
```
-----------------------
| ---- |
| | | My Name |
| ---- |
-----------------------
```
If we think of representing elements in HTML like this:
```htmlmixed=
<div id="myID" class="business-card">
<img src="http://myphoto.com">
<a href="http://mywebsite.com">My Name</a>
</div>
```
We can say the computer thinks about it more like a JS Object which looks like the following. Note how each child element is represented by its own object with properties. The entire object of nested objects is the **DOM (Document Object Model)**.
```javscript=
// Conceptual illustration of the DOM as an object
{
tagName: "DIV",
id: "myID",
className: "business-card",
children: [
{
tagName: "IMG",
src: "http://myphoto.com"
},
{
tagName: "A",
href: "http://mywebsite.com",
textContent: "My Name"
}
]
}
```
As such, we need to be comfortable with JS Objects. The syntax, the structure, the jargon. We need to know how to GET these objects from our page, how to READ the values of the object properties, and how to WRITE new values to change our pages.
### JS Objects - Analogy to Object representation of an element
### Tinker Activity Stuff:
Given that, let's look at a single representation of an element as an object, how we'd find it in the DOM.
```javascript=
let el = {
tagName: "DIV",
id: "myID",
className: "business-card",
textContent: "TC"
}
```
:::info
What JS code do you need to write and execute in order to:
- GET the class name of the element?
:::success
```javascript=
el.className
```
:::
- READ the text content of the element?
:::success
```javascript=
el.textContent
```
:::
- CHANGE the ID of the element to "ABC123"?
:::success
```javascript=
el.id = "ABC123"
```
:::
- WRITE/REPLACE the text "Teachers College, Columbia U." to this element?
:::success
```javascript=
el.textContent = "Teachers College, Columbia U."
```
:::
- ADD (not replace) a class "special" to the element?
:::success
```javascript=
el.["special"] = ""
```
:::
<br>
You can copy/paste the previous code into your console and press `ENTER` to execute it. Now if you type the variable reference `el` and push `ENTER` it will return to you the object. So any time you make a change, type `el` + `ENTER` to take a new look at your updated object and see how it has changed (or not.)
You can use this to test your ideas to the prompts above. Refreshing your browser will clear all variables so keep that in mind.
:::
---
### Objects in Objects - Analogy to Document Object Model
### Tinker Activity Stuff:
Now lets revisit and imagine the DOM, represented as a giant nested JS Object with each object representing an element and its property/values.
```javascript=
let el = {
tagName: "DIV",
id: "myID",
className: "business-card",
children: [
{
tagName: "IMG",
src: "http://myphoto.com"
},
{
tagName: "A",
href: "http://mywebsite.com",
textContent: "My Name"
}
]
}
```
:::info
In reference to the above code, what JS code do you need to write and execute in order to:
- GET the anchor element object?
```javascript=
let anchorElement = el["children"][1];
```
- READ the content of the anchor element?
```javascript=
console.log(anchorElement)
```
- Change the source of the image element to "images/unicorn.gif" ?
```javascript=
el["children"][0]["src"] = "images/unicorn.gif"
```
- ADD the class "important" to all elements in the `children` list?
- What if there were 1000 children element objects in this list?
```javascript=
for (let i = 0; i < el["children"].length; i++){
el["children"][i]["important"] = "Something You Wanna Add";
}
```
- What if also, we only wanted to add the class "important" if the element is an anchor and NOT an image?
```javascript=
for (let i = 0; i < el["children"].length; i++){
if (el["children"][i]["tagName"] === "A"){
el["children"][i]["important"] = "Something You Wanna Add";
}
}
```
<br><br>
If I run some magical code that queries the page, finds, and returns to you an object that represents an element, and I give it the variable name `specialEl`... What code would you need to run in order to:
- GET the type of element this is?
```javascript=
let elementType = specialEl.tagName;
```
- Check whether this element has an ID?
```javascript=
console.log(specialEl.hasOwnProperty('id'));
```
- Change the text content of this element from "Code yuck" to "Code YES!" ?
```javascript=
specialEl.textContent = "Code YES!";
```
- To add the class "X" to this element? (It already has a class called "Z".)?
```javascript=
specialEl["X"] = "Something you wanna add";
```
- Check whether there are any other nested elements inside this one?
```javascript=
for (const element in specialEl) {
if (typeof(specialEl[element]) === "object"){
console.log("There is a nested element inside!");
}
}
```
<br>
Try copy/pasting the prior code or constructing your own "demo" object into your console and testing out your hypotheses to these prompts.
:::
## Querying Elements from the DOM:
:::info
Above demo code:
- Create a new PEN in codepen and copy the HTML into the HTML panel.
- Go into debug mode and try the above JS code line by line in the console.
- Get comfortable TYPING out this level of code by memory.
<br>
Using **[Bootstrap Meowmix](https://codepen.io/jmk2142/pen/EwKXbo)**:
- Apply the patterns and techniques above to:
- Select and query elements of your choosing.
- Read the values of different element properties.
- Set or change the values of different element properties.
- HINT: Since this is a bootstrap page - there are certain classes like the ones that end in `danger, warning, info, primary` that if you switch out... will give you an interesting effect.
- Report your findings and thoughts.
:::
:::success
### Findings about querying elements:
- In the console of debug mode, when we use query selector to select id "x" (""#x"), it returns the whole html with the id of x.
- When we use **document.querySelector("#x").className**, it returns the class name **apple** in string.
- When we add value after selecting the id and classname, it will replace the original vaue and return the value added. For instance, using **document.querySelector("#x").className = "apricot"**, "apricot" will be returned as the new class name for #x instead of the original "apple".
- Using **Bootstrap Meowmix**, we changed the class name from **badge badge-success mr-1** to **badge badge-danger mr-1**. Therefore, the badge color changed to red, corresponding the color of danger in bootstrap.
:::
### CSS Properties:
:::info
Above Demo Code:
Compare and contrast the syntax of the CSS (rules) and how the computer represents the style object as part of the DOM.
- What are some of the key differences between the two?
:::success
Answer: CSS is fixed, but Javascript is dynamic. Using CSS in the first one, we could define properties of .incorrect and .correct. Then with Javascript, we use DOM to target where we want to change. We do not change anything in HTML, but simply target the id and class in Javascript, then add class name of what we have defined in CSS to HTML. However, for the second one, we define everything in CSS. Javascript reads those values of CSS as style. Additionally, if we want to change something in the second one, we could target class in CSS, then change CSS styles in Javascript using DOM.
:::
- If you wanted to change the background color to "salmon" what would you write in the console (JS code?)
:::success
There are couple ways:
- We could target tag name **div**.
```javascript=
document.querySelector('div').style.backgroundColor = 'salmon';
```
- We could target class **.pet**.
```javascript=
document.querySelector('.pet').style.backgroundColor = 'salmon';
```
- We could use let, to toggle the style on and off
```javascript=
let el =document.querySelector('div').style;
el.backgroundColor = "salmon";
```
:::
<br>
Using **[Bootstrap Meowmix](https://codepen.io/jmk2142/pen/EwKXbo)**:
- Using `document.querySelector()` and `console.dir()` lookup the `style` property of an element and browse through the list of properties available.
- What are some style properties you've used in CSS before and can you manipulate them through JS?
:::success
Answer: When we lookup the style properties, we saw many things that we have used in CSS before, such as border, background, color, font, margin, padding, width, and etc. We can manipulate them using DOM through JS.
:::
- If an element is not using a style rule, how is that represented in the object as a property/value pair?
:::success
Answer: If an element is not using a style rule, it would be represented as an empty string. For instance, when changed the background color from gold to salmon, as we look up the style for .pet, the background color property would write "salmon". But for the border property, it shows "" because we did not define the border style.
:::
:::
---
## Traversing the DOM...:
If the DOM represents all elements as objects and they're all nested in one giant object, what does this mean for us?
### Tinker Activity Stuff:
Let's explore a few more *interesting* properties that elements have.
:::info
Using **[Bootstrap Meowmix](https://codepen.io/jmk2142/pen/EwKXbo)**:
- Using the `Element` inspector with Meowmix, use the `Copy > Copy JS Path` to grab an element and set it to a variable `el`.
- Use `console.dir(el)` to print an element object to the console.
- Explore the object, "opening it up" by clicking on the small triangle/caret next to it.
:::
:::success
Answers:
### Findings about traversing the DOM:
- ***Browse/Scroll through the object to get a superficial awareness of the different properties available. Thoughts?***
- *There are A LOT of properties available. We can also see the hierarchical relationship between the different elements in the DOM. They all afford different ways to manipulate the HTML using JS. It is interesting to make the connection that on any given "finished product" there are all these given properties that are set to "null" just waiting for a developer to to give it a different value (or set a different rule? define?) It is also cool that they are all in alphabetical order so that it is easy for a developer to find the property they need. The properties that are not set to "null" are the ones we can see the effect of or know are active in the webpage.*
:::
:::success
Answers:
- ***Dig deeper by clicking into the following properties.***
- `children`
- `parentElement`
- `nextElementSibling`
- `previousElementSibling`
- ***What do the values of these properties represent?***
- *The values of these properties represent the current state of the element they belong to. So for example under the `parentElement` there are several properties with the value of `null`.
- This means that these properties essentially aren't visible or existent in the page vs properties that have values like `false` or even `StylePropertyMap {size: 0}` which have a different meaning and are existent/represented in the webpage actions and interactions.
- ***What is the relationship between an element and the values of these above properties?***
- The values of the properties tell the computer how (or what?) to represent and or alter the state of an element based on certain actions or interactions.
- ***How far does the rabbit hole go?***
- Pretty far! For the properties of the one element that I used to tinker with here, there were several expansion arrows I could click to see more property values. It does look like each has a stopping point though, after I click the expanding arrow for a "parent property" it seems that the sub-properties that pop up underneath it do not all have expansion arrows. SO, you theoretically could get the point where you've reached the end of a list of properties. However, a wondering is if the code is dynamic based on action and interaction, how that stopping point changes.
:::
Extend your thoughts to the following context:
```htmlembedded=
<article id="item-xyz">
<h3>Code is fun!</h3>
<p class="lead">It's a challenge but...</p>
<p>I practice every day at <a href="http://codepen.io">Codepen</a></p>
<div>
<span class="author">Professor JK</span>
<span class="published">05/16/2021</span>
</div>
</article>
```
```javascript=
// Code to articulate
let el = document.querySelector("div > span");
let name = el.textContent;
console.log(name);
let articleEl = el.parentElement.parentElement;
alert(articleEl.id);
let pargraphEl = articleEl.querySelector(".lead");
let linkEl = paragraphEl.nextElementSibling.querySelector("a");
linkEl.href = "http://codepen.io/jmk2142";
let dataEl = document.querySelector("div");
dataEl.children[0].textContent = "05/16/2022";
```
:::info
- Take turns verbally articulating the above code line by line, expression by expression to describe the state changes, sequence of statements/routines, and causality of executing said routines.
- Try using terms like:
- object, function, call, return, property, value, data, string, first/second/next/then, variable, assign, get, set, execute, console, print, index.
- There are a few new twists here. You can make observations about the code behavior by creating a pen with the HTML and going through the JS in the console line by line.
- What is the implication of this with respect to starting at some location within the structure of the DOM and getting to another location? In other words, "traversing the DOM".
:::success
Answer: The implication of this is that when you understand the language and hierarchy of the code, you can "traverse the DOM" to analyze and make observations about how different parts of the code works and how it is impacting the visual output and alteration of HTML as well as locating different bugs or errors that may be occurring. When you understand the relationship between different elements it makes it possible to move through the hierarchy to find what you are looking for.
:::
---
## Manipulating the Web for Practice:
Use **[Bootstrap Meowmix](https://codepen.io/jmk2142/pen/EwKXbo)** for the following. Or feel free to use any website (E.g. Twitter, Pinterest, Facebook, TC's website) to hack around. Meowmix is simpler so it'll be more clear in terms of what is what. But "hacking" a website and fabricating fake-news is a lot more fun. :camera_with_flash:
:::info
- Using the `Elements` inspector and `Console`, tinker around the Meowmix page and get comfortable with the Javascript we've been talking about above:
- Querying elements
- Reading element properties
- Manipulating the value of said properties
- Report back what you set out to do as a Tinker group, how you went about it, what the results were, and what you noticed / learned as it relates to the materials covered above.
```javascript=
// Example:
// Todo: Change the text of the paragraph element with class "small"
let paraEl = document.querySelector("p.small");
paraEl.innerHTML = "I'm the new text";
```
- **EXTRA:** Explore one of your own HTML/Bootstrap project in debug mode, using the following tools. Try making manipulations through the `Elements` and `Console` tools. Using your a small project like your own will also be helpful in making connections since the classes, rules, structure are all your own - easier to understand what you're doing.
:::
---
## Super Challenges: Next week Todo
:::success
**Challenge 1:** Create a function that changes the text color to `#e91e63` any time the function is called.
- Function name: something appropriate
- Parameters: 1 String argument - a CSS Selector
- Body: function should query the element using the argument, then change the appropriate property.
- Returns: none
- Other: proper indentation
:::danger
Answer:
```javascript=
function challengeOne(cssSelector) {
var element = document.querySelector(cssSelector);
element.style.color = "#e91e63";
}
```
:::
:::success
**Challenge 2:** Create a function that can will change
Instead of `document.querySelector()` you will need to use `document.querySelectorAll()`
See [MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll)
- Function name: something appropriate
- Parameters: 2 String arguments - a CSS Selector, a text message
- Body: function should query ALL elements matching the selector you passed in as an argument. It should loop through the list of elements returned by `querySelectorAll()` and for each element object, add or change the text content to the text message passed in as the second argument.
- Returns: none
- Hints: arrays, loops
- Other: proper indentation, formatting
:::danger
Answer:
```javascript=
function challengeTwo(cssSelector, textMessage) {
var allEl = document.querySelectorAll(cssSelector);
for(let i = 0; i < allEl.length; i++ ){
allEl[i].textContent = textMessage;
}
}
```
:::
:::success
**Challenge 3**: Refactoring above function to augment its behavior. Function will alternate between adding color and changing text, as well as set an id for all elements.
Additional Function 1:
- Function name: `colorizedEl`
- Parameters: 1 element Object argument
- Body: this function should change the color property of the passed in element object to `#e91e63`.
- Returns: the element object that you just changed the color of
```javascript=
function colorizedEl(elObj){
elObj.color = "#e91e63";
return elObj;
}
```
<br>
Additional Function 2:
- Function name: `editedEl`
- Parameters: 2 arguments - 1 element Object argument, 1 text message
- Body: this function should add or change the text content to the text message passed in as the second argument.
- Returns: the element object that you just changed the text of
```javascript=
function editedEl(elObj, textMessage){
elObj.textContent = textMessage;
return elObj;
}
```
<br>
Additional Function 3:
- Function name: `setID`
- Parameters: 1 element Object argument
- Body: this function should set an id on the element passed into the function as your argument to the following pattern: `id-` + `randomNum`. E.g. `id-101`, `id-224`, `id-694`.
- Returns: none
```javascript=
function setID(elObj) {
let randomNum = Math.floor(Math.random() * 1000);
elObj.id = "id-" + randomNum;
}
```
<br>
Refactored Function: Function from Challenge 2 but integrating the additional Function 1, 2, and 3
- Function name: something appropriate
- Parameters: 2 String arguments - a CSS Selector, a text message
- Body: Using your existing function from Challenge 2 you will modify/refactor it to do the following new thing. While looping through elements you will alternate between changing the color and changing the text. If the index is even you should use `colorizedEl` to change the color of the element. If the index is odd you should use `editedEl`. All elements should be given an id using the `setID` function.
- Returns: none
- HINT: arrays, loops, conditionals, using the function returns in a smart way (see Additional Function 1 and 2), calling functions in functions.
- Other: proper indentation, formatting
```javascript=
function challengeThree(cssSelector, textMessage) {
var allEl = document.querySelectorAll(cssSelector);
for(let i = 0; i < allEl.length; i++){
let elTemp = ((i%2)==0) ? colorizedEl(allEl[i]) : editedEl(allEl[i], textMessage);
allEl[i] = setID(elTemp);
}
```
:::
Thing is you don't really need me to prove your solution to these challenges do or don't work. If you want answers, create a codepen with some demo code in the HTML and JS. Run your proposed solutions (call your functions) and see if the visual results work. :grin:
---
<style>
.alert > ul,
.alert pre,
.alert img {
margin-top: 1em;
}
</style>