owned this note
owned this note
Published
Linked with GitHub
---
tags: mstu5003, tinker, js
---
# TINKER - Javascript Part 0
Many of the prompts can be demonstrated with: **[Bootstrap Meowmix](https://codepen.io/jmk2142/pen/EwKXbo)** but you're also free to tinker around with a website of your own liking. I recommend starting with Meowmix because it's a simple page with less confusing distractions.
## Why Javascript and how JS + HTML?
As we get into Javascript our ultimate goal is to combine the logic of Javascript (i.e. programming) to manipulate the structure and content of HTML. Examples:
- Change the content on the page:
```htmlmixed=
<!-- FROM -->
<div>
<p>Hello!</p>
</div>
<!-- Some Javascript to manipulate the content of the <p> tag -->
<!-- TO -->
<div>
<p>Good bye.</p>
</div>
```
For example when you edit a Google Document the screen is constantly manipulating the text content of the HTML behind the surface of the editor.
- Manipulate element properties on our page:
```htmlmixed=
<!-- FROM: hidden -->
<div class="warning hide">Please format your code.</div>
<!-- Some Javascript to manipulate the class of the div -->
<!-- TO: shown! -->
<div class="warning show">Please format your code.</div>
```
For example when you forget to enter your email address a warning panel shows up on the form next to the item. We changed the class which is associated with CSS rules `display:none` to `display:block`. It was always there, but only showed up after we manipulated the class!
- Alter the structure of our page (i.e. create/remove HTML):
```htmlmixed=
<!-- Start with THIS -->
<div class="feed">Nothing to see here...</div>
<button>Push to tweet!</button>
<!-- Some Javascript to make the button DO something... -->
<!-- E.g. Pushing the button creates new tweet HTML and adds it -->
<!-- Might produce/add THIS html -->
<div class="feed">
<div class="tweet">
<p>What's up with anti-vaxers?</p>
</div>
</div>
```
For example your new tweet feed has no published tweets. As soon as we push the publish button, we GENERATE a new HTML template for a tweet and add that HTML to our feed div (where tweet html components are supposed to go.)
HTML/CSS is good for creating the starting point of our pages and apps. By itself, it is a static (unchanging) structure. Once we want to make dynamic experiences that means our pages change.
- Elements are added or removed.
- Properties of elements (like `textContent` and `className`) are changed.
- Events like clicking have to be listened for and told what to do in response.
To get into this stuff, we need to tinker with a few things:
- Learn how to use the Developer Tools (Devtools) in Chrome
- Familiarity with element representation in HTML vs. JS Objects / DOM
- Start directly manipulating elements with simple Javascript
---
## Developer Tools
We need special tools in order to tinker around with our HTML and JS. Google Chrome (and all other modern browsers) usually come with these tools included. Using these tools, you can look at the code of any page you visit AND manipulate it on your end to tinker around.
Note that changes you make through these tools are local only - meaning they happen in your browser and not the server. As soon as you refresh your page those changes will be gone and no one else will see those changes so you can't break pages or do real damage. (Yet.)
### 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`.
- 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.
- 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?
<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
Objects represent ideas with multiple property/value pairs.
Example:
```javascript=
// Representing a student - an object model
let student = {
name: "Harry Potter",
alive: true,
birthYear: 1980
}
```
:::warning
**MEMORIZE THIS SYNTAX!**
The entire thing is a JS Object and the syntax needed to work with one.
- Curly braces `{ }` indicate the start and end of the object.
- Each property has a value and comes in pairs.
- Properties always have values even if the value is: `undefined`, `null`, `" "`, etc.
- Property naming convention is `camelCase`.
- Property and its value are separated by a `:` semi-colon.
- It's convention to have a space directly after the `:` for readability
- Property/value pairs are indented inside the open/close of the object.
- Each property/value pair is separated by a `,` and new-line for readability.
:::
If I want to **read** a value from the student object we can use dot-notation to reference the property we want to read or **GET** (the value) of.
- Pattern: `object.property` or object-dot-property.
- E.g. `student.name` returns `Harry Potter`
- E.g. `student.alive` returns `true`
- E.g. `student.birthYear` returns `1980`
If we want to **write** a value (i.e. change) on the student object we can use dot-notation and assignment to **SET** the value.
- Pattern: `object.property = value` or object-dot-property assigned new value.
- E.g. `student.name = "Ron Weasley"` changes the name.
- E.g. `student.alive = !student.alive` toggles true to false.
- E.g. `student.birthYear = student.birthYear - 10` subtracts years resulting in 1970.
### 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"
}
```
Note that the element object is the `{ ... }` stuff. It exists regardless of whether it's assigned to a variable or not. But we need a way to reference it in order to do things with it. As such, let's assign it to a variable we can reference. A common *convention* used is to name elements `el` which is short for element.
:::spoiler
> Jin's 3:39 am thoughts: Think of variables and data like babies. A baby (our data object) is born, it exists. But there is no way to talk about the baby if the baby doesn't have a reference (i.e. variable name.) What is its weight? (What thing are you referring to?) `let it = { weight: 10 }` What is `it.weight` ? Oh, it's `10` pounds.
> Interestingly there is actually one way we can refer to the baby without variables. I physically pass you the baby and ask weight? (Looking at the _data_ that was passed into arms.) It is `10`. If someone can explain this analogy in reference to code later in this Tinker, you're in excellent shape.
:::
<br>
:::info
What JS code do you need to write and execute in order to:
- GET the class name of the element?
- READ the text content of the element?
- CHANGE the ID of the element to "ABC123"?
- WRITE/REPLACE the text "Teachers College, Columbia U." to this element?
- ADD (not replace) a class "special" to the element?
<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
If the document object model is a giant object, with nested objects - each object representing an element, then we can make an analogy to something like this.
Here we have Harry Potter (the giant root object) and he has friends which are children objects nested in a list under the property `friends`. This structure repersents a relationship between them in a hierarchical way.
> Harry Potter HAS friends.
```javascript=
// Representing relationships - like a document object model
{
name: "Harry Potter",
alive: true,
birthYear: 1980,
friends: [
{
name: "Voldemort",
alive: false,
birthYear: 1926
},
{
name: "Hermione",
alive: true,
birthYear: 1979
}
]
}
```
One special note here:
- The value of `friends` is NOT two things (i.e. !2 friend objects)
- The value of `friends` is a SINGLE array-like list (i.e. datatype)
- If I ask what is the value of `friends` it is an Array-like data thing with a length of two (i.e. 2 friend objects.)
- So there is a difference between GETTING the value of `friends` and getting a specific friend object in that list. Since we're working with an array-like list, you can use numerical indexes to reference a specific object in that list. E.g. `object.friends[0]` vs. `object.friends[1]`
### 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?
- READ the content of the anchor element?
- Change the source of the image element to "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?
- What if also, we only wanted to add the class "important" if the element is an anchor and NOT an image?<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?
- Check whether this element has an ID?
- Change the text content of this element from "Code yuck" to "Code YES!" ?
- To add the class "X" to this element? (It already has a class called "Z".)?
- Check whether there are any other nested elements inside this one?
<br>
Try copy/pasting the prior code or constructing your own "demo" object into your console and testing out your hypotheses to these prompts.
:::
### Elements have many many properties...
So far we've been presenting you with little sketches of what element objects in the DOM look like. Example:
```javscript=
{
tagName: "DIV",
id: "petStore",
className: "container",
textContent: "Welcome!"
}
```
But this is just a few of the hundreds of properties that elements have. Most developers don't have all of these memorized. We know a few common ones we often use (like the ones I mention) and if we want to do something to an element that our short-list doesn't solve - we look it up.
Programmers think:
> There must be a relevant element property to do the thing I want to do.
> I need to research what that property is and what kind of values it needs.
---
## Querying Elements from the DOM
So now that we have a general idea of how to manipulate objects, and we established that working with elements, the DOM, is all about reading and manipulating the property/values of objects...
> How do we actually GRAB elements from the DOM?
What we need to do is *query* the DOM and have the comptuter fetch for us element(s) object(s) that we need.
:::warning
MEMORIZE THIS PATTERN!
- `document.querySelector("selector")`
<br>
Where *selector* is a **CSS selector String**.
- Select by tag: `"someTag"`
- Select by ids: `"#someID"`
- Select by classes: `".someClass"`
- Any CSS valid selector: `"div article.x > span"` *Select span elements, that are direct children to article elements with the class x, anywhere inside a div.*
- Don't forget the double quotes around your selectors to make them interpretted as Strings (or it might protest.)
:::
What `document.querySelector()` does is it is a function that when called accepts a pattern and looks for an element in our DOM, returning to us the element object if it finds it. Example:
```htmlembedded=
<!-- HTML -->
<div id="x" class="apple">
<div id="y">
<p class="story">My Paragraph</p>
</div>
</div>
```
```javascript=
// Computer conceptualizes the DOM like this:
{
tagName: "DIV",
id: "x",
className: "apple",
children: [
{
tagName: "DIV",
id: "y",
children: [
{
tagName: "P",
className: "story",
textContent: "My Paragraph"
}
]
}
]
}
```
```javascript=
document.querySelector("#x"); // returns object representing element div#x
document.querySelector("#x").className; // returns class "apple" of div#x
document.querySelector("#x").className = "apricot"; // sets|changes class of div#x
// Using variables helps make our code readable and references reusable
let el = document.querySelector("#y"); // returns the div#y object
console.log(el.className); // prints "" to the console
el.className = "pineapple"; // sets the class to "pineapple"
let paragraph = el.children[0]; // el was div#y, children at index 0 is p.story
alert(paragraph.textContent); // alert popup with textContent value
```
So now we can use Javascript to query the DOM, get elements, and then change them using what we understand about object manipulation.
:::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.
:::
### CSS Properties
If you want to dynamically apply styles the easiest way to do it is to create regular CSS rules and then use classes to toggle the styles on or off. Example:
```htmlmixed=
<div id="item-1" class="answer">My Correct Answer</div>
<div id="item-2" class="answer">My Incorrect Answer</div>
```
```css=
.correct {
color: green;
}
.incorrect {
color: red;
}
```
```javascript=
// SETS class to answer and correct
// APPLIES the .correct CSS style rules
document.querySelector("#item-1").className = "answer correct";
// ASSIGNS variable el as reference to element object (readability)
// CONCATENATES the second class to the first with space
// APPLIES the .incorrect CSS style rules
let el = document.querySelector("#item-2");
el.className += " incorrect";
```
However you can directly manipulate an element object's style rules using the elements `style` property.
The `style` property is an object `{ }` with many property value pairs. Every CSS rule you can make is represented in this object. Much like we have manipulated element properties, we can manipulate this CSS style object's properties as well.
```htmlembedded=
<div class="pet">CAT</div>
```
```css=
.pet {
width: 100px;
font-family: Helvetica;
background-color: gold;
}
```
```javascript=
{
tagName: "DIV",
className: "pet",
style: {
width: "100px",
fontFamily: "Helvetica",
backgroundColor: "gold"
}
}
```
:::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?
- If you wanted to change the background color to "salmon" what would you write in the console (JS code?)
<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?
- If an element is not using a style rule, how is that represented in the object as a property/value pair?
:::
---
## 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.
- Browse/Scroll through the object to get a superficial awareness of the different properties available. Thoughts?
- Dig deeper by clicking into the following properties.
- `children`
- `parentElement`
- `nextElementSibling`
- `previousElementSibling`
- What do the values of these properties represent?
- What is the relationship between an element and the values of these above properties?
- How far does the rabbit hole go?
:::
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".
:::
---
## 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.
- **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
Technically, these are within or very close to the concepts we've gotten through but applied in a new (DOM and elements) contextual way so of course, it's going to be challenging as hell. :see_no_evil: :hear_no_evil: :speak_no_evil:
If you can solve all these you're ahead of the game. If you have trouble, don't worry - there are things you can start to learn and be aware of as we keep going down this path and revist these concepts again and again.
The concept of functions are going to be an important one though as we march into the next unit - where understanding the details and nuances of functions as well as what data goes in and what data comes out... is going to be the foundation for being able to make things like button clicking interactive.
:::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
:::
:::success
**Challenge 2:** Create a function that can will change multiple element texts.
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
:::
:::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
<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
<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
<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
:::
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>