Dave Collier
Dave Collier

Reputation: 235

Backbone Router & Deep Linking

My single page web application consists of 4-5 views stacked vertically, when a user chooses a menu item, the page will scroll to the appropriate view. When you come into the application for the first time this is not a problem, however if you deep link to a menu item my page throws a fit because it's trying to access properties of an element that does not yet exists.

The problem I am having is understanding why the elements do not exist at the time the router is trying to scroll the page.

If you load / and then select home no problems, but if you directly hit #home via browser that when I get jQuery undefined errors.

Uncaught TypeError: Cannot read property 'top' of undefined

Inside router I am instantiating and rendering all of my views within the initialize function. The idea is the initialize will always happen before any of my routes, clearly not the case.

Again I've read a few threads that show how to have a before and after function for either all routes of individual routes but even using that approach scrollToById fails because it doesn't know what $(id) is at the time of being called.

define(function (require, exports, module) {

        var Backbone = require('backbone');

        return Backbone.Router.extend({
            initialize: function(){
                require(['ui/menu/menu','ui/home/home', 'ui/samples/samples', 'ui/resume/resume', 'ui/contact/contact'], 

                function(Menu, Home, Samples, Resume, Contact){

                    var menu = new Menu();
                        menu.render();

                    var home = new Home();
                        home.render();

                    var samples = new Samples();
                        samples.render();

                    var resume = new Resume();
                        resume.render();

                    var contact = new Contact();
                        contact.render();

                });
            },
            routes: {
                ''          : 'init',
                'home'      : 'home',
                'samples'   : 'samples',
                'resume'    : 'resume',
                'contact'   : 'contact'
            },
            init: function(){

            },
            home: function (){
                this.scrollToById($(".home-container"));
            },
            samples: function(){
                this.scrollToById($(".samples-container"));
            },
            resume: function(){
                this.scrollToById($(".resume-container"));
            },
            contact: function(){
                this.scrollToById($(".contact-container"));
            },
            scrollToById: function(id) {
                var val = $(id).offset().top - 127;

                $('html, body').animate({
                        scrollTop: val
                }, 2000);
            }
        });

    });

Appreciate any tips or advice.

Upvotes: 1

Views: 836

Answers (1)

Kyle R
Kyle R

Reputation: 716

I think the routes event handlers in the router are getting initialized at the same time as the initialize function. Because of this, route events are getting triggered before the DOM elements are rendered.

I would try making a new function outside of Router that contains everything currently inside the initialize function. Then the final thing in that function can be to create an instance of the router. This will ensure that no routes events are called until your scripts and DOM are loaded.

Upvotes: 2

Related Questions