Handlebars + jQuery

Goal: add HTML components using jQuery without writing a whole bunch of HTML as a string. Instead, we’ll store HTML components in their own files, to be recycled as needed.

Old solution: 

$("#element").append("
<div><span class='myClass' id='" + relevantId + "'>" + relevantID + "</span>Some text about " + jsVariable + " element</div>
”)

Better solution: 

React.js has been been on my “to learn” list for far too long, and I swear I’m going to tackle in next – I think (hope) that it’ll solve my components issue.

Meanwhile, however, I’ve had to get around with jQuery, and have been running into a more and more persistent problem. Appending HTML with jQuery is easy for small bits of code, but ridiculous for larger snippets or components. Fortunately, I just found a solution: Handlebars.js, a front-end templating engine. We’re going to store our HTML snippets/components in their own files, and inject variables as needed. So, if we’re coding a Twitter clone, each post would be built from a post.html file, with relevant data inserted from JS using {{variable}}. Our files will look like this (sorry about the screenshot – WordPress formatting sucks)

Screen Shot 2017-09-28 at 4.31.37 PM

Handlebars will compile these HTML files with the variables we’ll provide it with. By the way, if this is looking familiar, it’s because it’s how things work in Angular and React, too (as far as I’ve seen), but we’re implementing it without the massive learning curve or intensity of using a whole front-end framework.

So, let’s get down to business. Here’s the step by step:

1. Add a Handlebars CDN link to your HTML file. Grab the latest version here. I recommend the handlebars.min.js file, since it’s a little smaller. Add the file in a ​script tag, before jQuery and your own JS script.

2. Create a .html component file following the convention above, inserting variables with this format: {{var}}. You can also use a bunch of other pre-built Handlebars conventions outlined in the documentation. I’ll call this file component.html.

3. Now, we’re gonna need to fetch the contents of the HTML file in your JS script. You can do this using jQuery’s $.get() method. The code will look like this:

$.get("component.html", function(data) {
  // do something with the data here...
}, 'html')

4. Next, a bit of Handlebars magic – this should go inside the function(data).

Note: function(data) is a callback function – it’s only run once $.get() fetches the contents of the external file. Because JS is asynchronous in nature, it will continue to run code written the $.get() section as the app waits for the $.get() to return the data from an external resource (in our case, a file).  So, in order to operate on the data after we fetch it, we pass in a callback function with the data as a parameter.

 var myTemplate = Handlebars.compile(data);

// this is where we store our variables
var context= {
 "name": "Biz Stone",
 "post": "I am a very important person at Twitter"
 };

// Handlebars magic injects our variables into our template
var compiledPost = myTemplate(context);

// this should look familiar
$("#postSection").append(compiledPost);

5. Voila! We’ve now appended a whole HTML snipped with our own variables. No more messy strings in our JS/jQuery code.

PS: With a little patience and regex string manipulation, it’s possible to get rid of Handlebars altogether and search the $.get() html response for variables encased in {{ }}, replacing them with your own values. However, for the sake of speed, I leave that exercise to the reader.

Advertisements

Building a Starfield with Canvas

I’ve played around with HTML canvas before, and have even made a field of twinkling stars. However, this time, I wanted to recreate an old Windows screensaver where you fly through a star field. In short, something like this.

This proved to be harder than I expected. My first real attempt had stars increasing in size and velocity as they got further from the center.

starfield1.gif

First attempt

The problem with that is that no stars don’t seem to move towards us, just off the side of the screen – so, I’ve essentially created a particle emitter. You’re watching stars be created far in the distance, and the sense of depth comes from the changing star size as they get closer to the edge of the screen.

This wasn’t good enough. I wanted each star to actually occupy a position in 3D space, and then have this position be reflected in the view, creating a more realistic simulation. I wanted to create a sense of a star coming right at you. The issue is that stars have to come off the screen eventually no matter what – so, as a star gets closer to you, it needs to (1) increase in size and (2) move toward the edge of the screen

This really tripped me up for a few days. I couldn’t wrap my head around how I can represent 3D space in 2D. I was using the pythagorean theorem in 2D, using each star’s X and Y coordinates. I knew I needed to integrate depth, Z, but I wasn’t sure how. Then, after a few days, it hit me. I watched several working starfields closely to isolate what was happening, and I realized that a star’s distance from the origin point – the center, in my case – impacted two things:

  1. the size of the star (stars closer to the us appear larger)
  2. the speed with which the star travels (stars closer to us appear to move faster)

Then came the epiphany. Stars can only move along X & Y axes, but the speed with which they move implies their distance from us. 

Using this, I could now create a sense of depth. Two stars can occupy very close X & Y coordinates – sit next to each other – but if one is bigger and moves towards us faster, we perceive it as being much closer. It took me a bit of time to finagle the relationship between the Z coordinate and the star size/speed, but once I did – voila! The starfield looked much more realistic:

giphy

Second attempt (with depth)

So, how does it work? I created a star object with X, Y, and Z coordinates. At each screen refresh, I needed to change each star’s…. (1) x & y coordinates and (2) size, as determined by its Z coordinate.

(1) Each frame, I would get the distance between the star and the center, and would move 2000th of this – times the star’s Z coordinate (which is between 1 and 100+). Thus, stars with higher Z coordinates – which means the star is closer to us – would move off the screen faster.

(2) A star’s size would similarly grow as the star’s Z coordinate increased, and the star got closer.

// each frame...

star.size = 0.2 + 0.038*star.z; 
// a star is always at least 0.2 px in radius + some fraction of 3.8, based on distance - 0.2-4px radius total

star.x += (star.x - center.x)/2000 * star.z; 
star.y += (star.y - center.y)/2000 * star.z;

star.z++;

It took me 4-5 days to come up with that relatively simple bit of code – to wrap my head around the relationship between a 2D screen and a 3D space. Once I did, I decided to gamify my new project. More on that soon!

Project: Book vs. Movie

James and I have been looking to build something together and learn to collaborate better as programmers. James came up with a great idea: people often wonder which is better the book or the movie? So, we built a small app to find out.

Book vs. Movie queries the Goodreads API and the IMDB API to fetch movie metadata and rating, and displays them to the user, highlighting the winner.

We built the app with Node and Express, with some jQuery on the front end, sitting side by side at Think Coffee near NUY. This wasn’t our first collaboration, but it was the first time I’ve ever really pair programmed with anyone – we took turns writing code, both of us focused on the code in front of us. We both learned to work with a few different APIs and parse XML to JSON, but more importantly, I picked up a whole bunch of small techniques and tips on how we set up and build projects. James likes to use as few libraries/packages/external tools as possible, so we were both a bit out of our comfort zone – he was trying to thoroughly understand how the NPM packages and libraries that I picked up on the fly, and I was trying to use as few tools as possible, and really get what’s happening under the hood.

It was great to watch James work on the front end as well – something I’m not great at or feel as comfortable with. I learned about CSS animations, and picked up a few neat tricks

The main issue we ran into – that we chose to bypass for the sake of building faster – is that movie/book pairs often have different titles. A great next step would be giving the users an opportunity to tell us what movie pairings are correct – and then displaying these pairings first in future searches.

The end result is a finished – albeit simple – website, and a desire to build more. In the end, we hooked up the app to a Mongo DB to track incoming searches, and let it out into the big wide world. It feels good to build for people.

Recurse Center, not.

So, after an excited two weeks applying, I got rejected from the Recurse Center after my initial Skype interview (on stage 2/3). This is a bummer – I had gotten really excited about the idea, and thought it would have been a great fit. Getting rejected sucks, and I’m not going to try and turn this into some sort of a “this is meant to be” or “everything is just great” post – but I do want to reflect on the experience honestly.

One of my big worries is that this would have the perfect time for me to attend Recurse – it would have been a great environment in which to grow as a developer and soak up the skills I want to and need to learn. My path now is harder – I’ll continue learning and building on my own , and if I’m still free in three-four months (and can afford to be free for *another* 3-4 months), I’ll apply again. I’m worried that once I get a job, it’ll be a lot harder to find 3 months to attend.

Anyway, all in all, the application experience was smooth and a few good things that came out of it:

  1. Having a hard deadline pushed me to finish my personal website (which I had already been working on) and I wrote out a whole new small project for the application.
  2. I approached all the questions genuinely, and the application gave me a good structure in which to evaluate my programming abilities and my plans. For example, I got to plan out what I’d focus on learning in the next 3 months, and I thought about the kind of engineer I’d want to be in a few years.
  3. The overall process – the application, the website, the interviewer, the speed with which they responded – was fantastic.
  4. I made it through the first round, which is the first time someone objective (not a friend or co-worker or mentor) looked at my code, and gave it a pass.
  5. think I have an idea why I didn’t pass onto the final round. Of course, RC doesn’t offer feedback, so this is a guess – but I think it came down to my communication ability, particularly around the things I learn (I tried, poorly, to explain the JS event loop). This is frustrating, because I was involved in interviewing lots of people at Codecademy, and watched candidates flounder and ramble, and I knew this was a weakness of mine – and I still fell into the trap of doing it. I also didn’t have the most defined plan for what I wanted to learn, but I’m not sure if this held me back (I was given the advice of not proposing a project that’s too specific). So, while it’s frustrating to think about how I could have done better, at least I have an idea where I underperformed – and can focus on fixing it next time.
  6. If I do choose to reapply, there are a few people that have gotten in on their second try, and had a great experience.

Finally, and I think most importantly, I loved every hour I coded. While getting rejected stings, I jumped right back into my next project  the next day (more on that soon!). If I let this deter me, it was never the right move to begin with. So – onto my next project!

 

 

This is trouble

I’ve run into a bit of JS this trouble. Take a look a this dog object:

var dogs = [];

function Dog(name){
  this.name = name;

  this.bark = function(){
    console.log("Woof! My name is" + this.name);
  }
  this.friends = function(){
    dogs.forEach(function(dog){
      console.log("My name is " + this.name + " and I'm friends with " + dog.name);
    });
  }
}

ruffy = new Dog("ruffy");
rex = new Dog("rex");
spot = new Dog("spot");

dogs.push(ruffy, rex, spot);

ruffy.bark();
ruffy.friends();

When I run ruffy.bark(), I get Woof! My name is ruffy So, then, what would you expect the the result of ruffy.friends() to be? Here’s what I’m getting:

My name is undefined and I'm friends with ruffy
My name is undefined and I'm friends with rex
My name is undefined and I'm friends with spot

This was strange, because I figured this would refer to the object – after all, the same technique works for getting the dog’s name!

After a bit of console.log-ging, I’ve found that in bark() this refers to the Dog object, but within the forEach loop, this refers to the global variable. I’ve found a few fixes:

  1. use a for loop instead of a forEach loop
  2. use the ES6 for of loop
  3. create a variable to store this outside of the forEach  loop.
this.friends = function(){
  var self = this;                 // self == this, the object instance calling the method
  dogs.forEach(function(dog){
    console.log("My name is " + self.name + " and I'm friends with " + dog.name);
  });
}

 

Recurse Center Application

After working on it for close to two weeks, I just submitted my application to the Recurse Center. We hired a few people from RC at Codecademy, so it has been on my radar for some time. However, Esther recently pointed me there again, and after reviewing the website, I was absolutely hooked. It looks like the ideal experience at this specific point in my life – when I have the time and a strong desire to learn as much as I can about programming. I’ve also had some great experiences in self-driven environments like this, both at Explorchestra and back in Interlochen.

Either way, though, I’m going to focus on learning and improving as a programmer – I’m having a blast working on this stuff full-time.

In other news, I’ve finished and deployed my new two projects alongside the application. I’m happy to present my redesigned website, maximpekarsky.com, as well as a small battle simulator I built as a part of QRL, a game I’m working on.

Cloning an array of objects in JS

I just spent a few frustrating hours trying to debug some code I had written to simulate a battle between groups of units. My script works as following:

  1. Create an array of unit objects based on user inputs, where each unit has a player id, HP, strength, speed, and other typical game parameters. This is our template array for the simulation
  2. By iterating trough this template array of units, create three more arrays:
    • an array with all units added based on their speed count (so that faster units are more frequent and likely to be selected)
    • a filtered array for just Player 1 units
    • a filtered array for just Player 2 units
  3. Run a number of battle simulations with arrays from Step 2. After each simulation, where units attack and change each other’s stats (namely HP), clear my three arrays, and create new ones with fresh unit stats from the template Array defined in Step 1.

The issue I ran into was that my units seemed to carry over their stats from previous simulation runs, even though I wiped the 3 arrays used in my simulation clean, and referenced my master array to clone units. If the error here seems abundantly clear, then you’ve already learned the lesson I just did. I cloned my units as following:

var masterArray = [
  {
    name: "joe",
    hp: 10
  },
  {
    name: "lena",
    hp: 12
  }
]

var tempArray = [];

for (var i = 0; i masterArray.length; i++) {
    tempArray.push(masterArray[i]);                  // !!!
}

The issue, I found, is that I wasn’t copying the object – only an object reference. Therefore, when I made changes to my tempArray[0].hp, for example, it would also affect masterArray[0]. Both objects referred to the same location in memory, so I wasn’t cloning the actual object – I was referring to the same object in both arrays.

The answer, I learned, is “deep cloning“. Though this feels a little like cheating, the following solution (one of many!) worked:

newObject = JSON.parse(JSON.stringify(oldObject)); 
//similarly: 
tempArray.push(JSON.parse(JSON.stringify(masterArray[i])));

We’re converting the object to text, and then parsing it into a new object – no longer referencing the same memory location as the initial object.

I’ve heard about reference vs. primitive variables, but now I’m getting a taste for them.

Step Away

It’s amazing how many technical problems resolve themselves when I step away from the code after working on it for a while. Challenges that suck me in and that seem needlessly complex suddenly become simple when the brain has time to work on them for a little while.

The Right Problem

You’re working on the wrong problem.

I’ve noticed that it’s easier for me to dig into experimenting with code until I get it right than to force myself to think through the best solution for a hard problem. For my current project, a text-based multiplayer game, I’ve created a Trello board to project-manage myself, and prioritized all the tasks – all the problems to solve and components to build.

I’ve noticed that when I butt up against a hard problem, I procrastinate by solving easier, much less important features. For example, a hard problem for my game is how two groups of units enter and resolve combat. Before can tackle the code, I need to think through and decide on the best solution. This is hard and uncomfortable – but it’s also the crux of the whole project, and the reason people would play this game.

Instead of sitting there and patiently thinking through the best solutions, I think for three minutes, and then turn for a distraction. However, I’m too motivated to slack off on Facebook, so I start building something totally non-essential, like a setInterval countdown system – a small UX improvement – which gives me that kick of satisfaction. In the grand scheme of things, it’s a poor decision.

So, I have to consciously stop myself and say: “Max, you’re working on the wrong thing. You should be working on the crucial feature, not the easy, fun one.”

“Also, now you’re avoiding work altogether by writing a blog post. Come on!”

The “Almost-There” Step

One of my favorite stages in learning to code is when you know what the right answer is, know exactly what to type, but don’t understand why. Your mind is close to making sense of a concept, but hasn’t gotten there yet. I call this the “almost-there” step. It’s unsettling and frustrating.

Inevitably, if you persist, the topic clicks into place, and then you fully understand it.

I’m in exactly such a place now with Node routes. A route accepts a function(request, response) as a parameter. I understand that the request is whatever the user is asking for, and the response is what we’re returning – and the response parameter seems to be able to return statuses, redirect, etc. But, on the whole, I still don’t fully get what’s happening here.