3

I am using backbone.js to create a single page app. I am new to backbone, so please forgive any wrong semantics.

My Problem is when rendering the views.

Initially, I have a javascript in my index.html that executes the some dom manipulation(image slider).

The JS is wrapped in $(window).load() so all is fine on initiation. The code obviously doesn't execute unless the page is loaded from url. the code will not run from backbone views or router. So the page loads without the dom manipulation.

I have tried to insert my code into the render and initialize function in the view, but to no avail. Should I add this code to the router? that seems to be a bit of a hack.

Where should I include the "dom ready" code? and / or is there a better way to manage views and their dom elements on load in backbone?

the code:

home.js

window.HomeView = Backbone.View.extend({
initialize:function () {
    this.render();
},

render:function () {
    $(this.el).html(this.template());

    this.startOrbits();
    return this;
},



startOrbits:function(){
    $(window).load(function() {
        $('#orbit-main').orbit({ fluid: '16x6', swipe:true });
        $('#orbit-news').orbit({ fluid: '8x6', bullets: true, directionalNav:false, captions:true, advanceSpeed: 9000});
    });
},




});
fhkurdi
  • 43
  • 6
  • Shouldn't you be able to `this.$('#orbit-main').orbit(...)` inside the appropriate `render` method? Just put that after `#orbit-main` is inside `this.$el`. – mu is too short Oct 27 '12 at 02:55
  • @mu is too short: i added this.startOrbits inside the render function, I also tried adding inside initialize after render(); . The code runs before the new view is rendered still. – fhkurdi Oct 27 '12 at 15:38
  • Read my comment carefully: `$(x)` and [`this.$(x)`](http://backbonejs.org/#View-dollar) are different things. `$(x)` will only work if `x` is in the DOM, `this.$(x)` will work if `x` is inside `this.el` even if `this.el` hasn't been added to the DOM yet. – mu is too short Oct 27 '12 at 18:29
  • I was not aware that I can do that. Thanks for pointing that out. Unfortunately, That didn't work, I got an error saying that orbit is not a function. I did find a solution below though. Thanks for your input. – fhkurdi Oct 27 '12 at 19:26

2 Answers2

1

But when I go to another view, then back, the code obviously doesn't excite

I'm not quite sure what that means. Leaving the "excite" part aside, you don't "go to" views; views are just ways of adding elements to the page, or adding logic to existing elements.

If I had to guess though, I'd imagine that you're using the Backbone router to move between virtual "pages" (and you use views to make those pages). If that's the case, you need to look at the Backbone router events:

http://documentcloud.github.com/backbone/#Router

http://documentcloud.github.com/backbone/#FAQ-events

Specifically, I think you want to bind an event handler (on your router) to "route:nameOfYourRoute", or just :route" (if you want to trigger your logic on every virtual page load).

Hope that helps, and if my guesses are wrong please edit your question to clarify.

machineghost
  • 33,529
  • 30
  • 159
  • 234
  • Sorry about the type-o. I meant execute. and Yes, You understood me correctly. Im using the backbone router to run pages based on url tags. The problem is that Im trying to find a way to run code after a view has rendered. Adding the code in router will trigger the logic, but a bit too early, the page has not render yet. – fhkurdi Oct 27 '12 at 15:43
  • I'm confused: did you actually try my suggestion? Route events fire *after* the route callback is applied; the code is literally `callback && callback.apply(this, args); this.trigger.apply(this, ['route:' + name].concat(args));` so any logic you add in an event handler *will* fire after your view has rendered (assuming of course that you invoke the render inside the route's callback). – machineghost Oct 27 '12 at 17:19
  • I was able to identify a solution. I had an if statement in my router that I commented out. That way, a new view is generated EVERY time the router function is triggered, instead of using the "cached" view. The solution is Below. Is this optimal? im trying to apply and understand your proposed solution also. where do i add the code? thanks for your patience. – fhkurdi Oct 27 '12 at 19:19
  • Glad you figured things out :-) There's nothing wrong with creating a new view every time (unless you do it A LOT and don't clean up your references), but it does seem unnecessary. By commenting out that `if` you are saying "make a new view every time", which is fine if it's what you want ... but I think what you really want is to just re-*render* every time: you're currently doing that by creating a new view, invoking its initialize, and thus triggering its render. Your code might be cleaner if you kept your if, but added an else block that did `this.homeView.render();` inside of it. – machineghost Oct 28 '12 at 00:33
  • P.S. You may want to consider editing your question to make things clearer and include (only) the relevant code, just for future readers that may come here. Also, you should accept your own answer so that this question doesn't linger in the unanswered questions queue. However, if you found my answer to be useful you are welcome to upvote it :-) – machineghost Oct 28 '12 at 00:37
1

I was able to find a solution. After commenting out the if statement in my router function, things went smoothly.

 home: function () {
            // if (!this.homeView) {
                this.homeView = new HomeView();
            // }
            $('#main-content').html(this.homeView.el);
            this.homeView.startOrbits();
            this.headerView.selectMenuItem('home');
        },

I do realize that this means I create a new view on every rout trigger. Please feel free to offer more optimal solutions.

fhkurdi
  • 43
  • 6