Closures Exercise

Link to assignment demo

I think I have the hang of closures (sort of... maybe...), but the exercises were an exercise in debugging as well. Let's see how this went.

Exercise 1

Use a closure to create 100 DOM elements with setTimeout()

The text given was wrong, and I was able to get through it after a couple of iterations on the code. I first had some mistakes with creating the loop and setTimeout correctly and had the instantaneous computation, but the key seemed to weirdly be in creating a separate count variable that could iterate outside of the loop rather than passing in an argument (which is where the second exercise is giving me trouble).

Here's the code excerpt

makeElements(100);

function makeElements(input) 
{

    var count = 0;

    for (var i = 0; i < 100; i++) 
    {
        setTimeout(makeElt, i * 100);
    }

    

    setTimeout(exerciseTwoSetup,2000);

    function makeElt() 
    {
        var divElement = document.createElement('div');
        console.log(divElement.innerHTML);
        var divText = document.createTextNode('Number: ' + (count+1));
        divElement.appendChild(divText);
        console.log(divElement.innerHTML);
        document.body.appendChild(divElement);

        count++;
    }
    
}

Exercise 2

Use a closure to animate a DOM element in some way with the style() function. (Fill in the blanks).

I am SO CLOSE to figuring this one out! I first started out with making the Exercise 2 h3 header clickable so that it would change color and then realized I missed the point of the prompt, which was scale. So I created multiple divs with a class to mark that they were clickable, but weirdly my event handler was triggering so that every other element was already flashing colors when they were first created. Here's my code snippet: 

//Animation exercise
function exerciseTwoSetup()
{
    //create the Exercise 2 header
    document.body.appendChild(document.createElement('p'));

    var headerTitle = document.createTextNode('Exercise 2');
    var headerElement = document.createElement('h3');
    headerElement.appendChild(headerTitle);
    headerElement.id = "exercisetwo";
    document.body.appendChild(headerElement);

    //create the clickable divs to flash colors when clicked on
    for(var k = 0; k <= 20; k++)
    {
        console.log('creating element');
        var divElement = document.createElement('div');
        var divText = document.createTextNode('Click on Me!');

        divElement.appendChild(divText);
        divElement.className = "clickable";
        divElement.id = "click" + k;
        divElement.style.padding = "15px";
        document.body.appendChild(divElement);
    }
    
    //add event handler
    var elements = document.getElementsByClassName("clickable");

    for(var j = 0; j < elements.length; j++)
    {
        elements[j].addEventListener("click",animate);
    }
    
}

function animate() 
{
    // console.log("called for: " + document.getElementById(this.id));
    
    //check to see if element has been clicked on previously to turn color flashing on or off
    if(document.getElementById(this.id).className === "clicked")
    {
        clearInterval(interval); 
        document.getElementById(this.id).style.color = "black";
        document.getElementById(this.id).className = "clickable";   
    }   
    else
    {
        console.log("turning color on.");
        document.getElementById(this.id).className = "clicked";
        interval = setInterval(changeColor, 250);
    }

    function changeColor() 
    {
        //BUG! unable to change color since this keyword returns null
        this.style.color = getRandomColor();
        
    }

    function getRandomColor() //taken from http://stackoverflow.com/questions/1484506/random-color-generator-in-javascript
    {
        var letters = '0123456789ABCDEF'.split('');
        var color = '#';
        for (var i = 0; i < 6; i++ ) 
        {
            color += letters[Math.floor(Math.random() * 16)];
        }
        return color;
    }

Where I've got it now is successfully triggering the closure but actually not being able to create the random color; I'm using the this keyword but that's not actually getting passed into the color generation function. 

Exercise 3

Use a closure to make an API call to openweathermap.org. Send openweathermap a zip code and when the weather is returned, create a DOM element with that zip code and the weather data.

I ran out of time to work on the second part of this because I spent time wrestling with p5. I cannot for whatever reason make any p5 calls, which is why all my exercises are done without it. It's such a shame because the code is much simpler than what I implemented. I'm not sure why that is, I forked off the example code so the folder paths are preserved.

In any case, I resorted to jQuery in desperation and was able to parse through the data structure returned by the Open Weather Maps. Note to self: when using an API, there's 100% chance you have to register to get a key. 

Code is here: 

function assignQuery() 
{
    var headerTitle = document.createTextNode('Exercise 3');
    var headerElement = document.createElement('h3');
    headerElement.appendChild(headerTitle);
    headerElement.id = "exercisethree";
    document.body.appendChild(headerElement);

    var url = 'http://api.openweathermap.org/data/2.5/weather?zip='+ zip + ',us&appid=2de143494c0b295cca9337e1e96b00e0';
  
    $.getJSON(url, gotData);

  function gotData(data) 
  {
    console.log(data);

    var weatherDiv = document.createElement('div');
    var weatherText = document.createTextNode(data.weather[0].description + " for zip code " + zip);

    weatherDiv.appendChild(weatherText);
    document.body.appendChild(weatherDiv);
  }

}

To use multiple zip codes, I imagine you'd probably store an array of the zip codes that the user would want to see and then call the function on each element in the array, but I guess that's maybe sidestepping the closure functionality? Is this better performance wise?

In conclusion, I thought I knew what I was doing. Perhaps not so much.

If it weren't for the typo, this would be the summary of my relationship with closures

If it weren't for the typo, this would be the summary of my relationship with closures