JS refactoring in progress on this one. Don't  merge this yet!

Raising a pull request so I can view the diffs and think of ways to refactor better.