Skip to content

Instantly share code, notes, and snippets.

@danfinlay
Created January 28, 2015 04:31
Show Gist options
  • Save danfinlay/cbfe5a7693cd811d1199 to your computer and use it in GitHub Desktop.
Save danfinlay/cbfe5a7693cd811d1199 to your computer and use it in GitHub Desktop.
Editing DOM with Javascript

Editing DOM With Javascript

A friend recently asked me for some help with jQuery. He wanted to know how to store data on html elements from the JSON payload he was receiving. His initial approaches were much like some of my own early approaches, storing data on elements using data attributes, and then updating those accordingly.

I've since come to learn that these are considered bad practices, and for good enough reasons. Sure, it can work, but it will be slow, and difficult to implement, and if your UI gets very complicated, you'll find yourself juggling multiple sources of truth in your application.

There are several approaches available to the modern web app developer, and I'm sorry I don't believe I'm a grand enough authority to choose a specific one for a project that isn't mine, but I am aware of enough different approaches I think I can get you oriented with what to look for in a good solution.

A Single Source of Truth

A term you'll hear a lot in programming and philosophy is the pursuit of a single source of truth. The idea is that it's a lot easier to manage your application if you know where the truth is at any point, and can easily refer to it, and then I can let all other instances of the truth derive from that source.

For example, if the user is logged in, I will want to store their name somewhere. If I store their name on the div element in the corner of the screen, and I also use their name in the profile page, and they edit their name, now I need to go back and remember every place I've rendered their name, and change them to match the new one. This could get pretty tedious to program manually.

Usually what you want to do instead, is have one place where you keep your local truth, or Model, and use it to update the page, or View.

Templating

One of the most common approaches to sending a Model to the View is a templating engine. A templating engine will generally take some raw data, and insert it into a markup-type document.

The most basic templating engine I use (when it's sufficient) is mustache. Mustache has implementations in just about every language, and it's easy as heck. You give it some data, and a template file, and it combines it to make the output result. You can use it to render HTML, or really anything you want. On the downside, mustache has no logic, and it renders a big block of dom at a time, so if you make a lot of small changes, it's probably too slow for your needs.

If you need more power or logic than mustache, you might consider the handlebars.js templating engine, which uses a syntax almost identical to mustache, but it includes some logic, making it a bit more powerful.

One framework that's been getting a lot of attention lately is React.js, which uses a virtual dom to very efficiently only replace the required pieces of the page, which could be great with a very busy page, but it has its own pretty weird non-html syntax, and so it has a steeper learning curve.

Templating engines are one fairly simple option when dealing with this topic. If you'd like to explore more options, you can use this template-chooser.

Frameworks

If you aren't a fan of managing your own models and network interactions, and calling to the template engine yourself, that's when you consider using a Framework. Frameworks tend to dictate the entire structure of your application, so it's a pretty big decision to make, but if you aren't interested in making organizational decisions, or are indecisive about organization and would prefer to be guided, they can be a great benefit.

Generally a Framework will have some Model layer that allows you to synchronize your data with the server. They will have a View layer that allows you to keep the page up to date with the Model, and then lastly usually a Controller layer for implementing logic inbetween, like responding to user behavior, sorting and filtering model data for presentation, or other details like this.

MVC

This pattern of Model-View-Controller is quite a buzz-term, and really it varies a ton from framework to framework. It's one of the most popular framework acronyms, but these days it's hip for every Framework to claim its own weird acronym to describe how they organize the workflow they'll enforce.

Framework Options

There are a ton of framework options, and this is a scary thing to try to answer, so I'm going to keep it brief and give you my general impression of a few of the frameworks out there:

  • Backbone.js: The original front-end Javascript framework. The people I know who learned this are trying to learn something else.
  • Meteor.js: A paired front and backend solution. It's all-or-nothing, and that's too much commitment for me, so I haven't.
  • jQuery: Often called a framework, but it's really just a convenience library for editing the DOM.
  • Browserify: Not really a framework, but a method of organizing a Javascript project with dependencies from npm, this is my go-to lightweight project organization solution for hobby projects, but if you're not great at organization, it can be difficult to manage with larger projects.
  • Knockout.js A nicely lightweight MVC framework. I just had a great talk with a talented developer who uses it for browser plugins. One of the nicest parts is it doesn't use a templating language at all, it uses html attributes to manage what should be updated by what models.
  • Ember.js A big, full-featured framework. It has a hell of a learning curve, but it has pretty much everything a large project could want. My one big ol' word of warning is if you use Ember-Data, make all your relationships async.
  • Angular.js Another big full-featured framework. I wouldn't pick it over Ember right now, since they just announced Angular 2.0, which will have a lot of breaking changes, and so you'll learn a lot just to throw it away at the moment.

Roll Your Own

All that said, these are all just convenience methods of organizing the flow from data, to interface, to user input, back to data again.

The important thing to keep in mind is that you want to keep these processes as simple for yourself as possible. Storing the model data in one place makes it easy to pass it to a template, and re-render the template whenever anything changes.

Clever organization could also allow you to update your view without templates. For example, if you were only tracking one kind of record, let's call them Geopoints, you might just keep track of them in a data store like this:

var geoPointStore = {
  1: {lat:34, lon:488} // By relating an ID to a GeoPoint, we can easily refer to it.
}
// Let's say we want to update the position of a <div> with this Geopoint!
function updateView () {
  for( var id in geoPointStore ){
    var geoPoint = geoPointStore[ id ]
    $('div #geopoint1').css({ left: geoPoint.lat, top: geoPoint:lon })
  }
}
// You'll need to call that method whenever you want to update your geoPoints:
updateView()

That's not even a very clever method, but it's a simple example of how you could keep your view up to date with a model without any framework, and without having to destroy and re-create elements, either. This method would be more efficient than a lot of the frameworks out there, funny enough.

Conclusion

Well, that's my general take. Having had to learn Ember over the last year, I'd definitely use it for the right type of application (fairly complex, with a RESTful API), but for smaller, or more unusual projects, I find it fun to experiment with the way my projects are organized and implemented, and experimenting with these things is how we get better anyway.

I hope this has been helpful! Feel free to add your comments below, or fork this document and make changes, and even submit pull requests! I'm not really promoting this right now, but it wouldn't be the first time a Gist I'd written found attention without my attempts, so it's worth keeping up to date.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment