0
votes

I've created a Backbone, Marionette and Require.js application and am now trying to add smooth transitioning between regions.

To do this easily* ive decided to extend the marionette code so it works across all my pages (theres a lot of pages so doing it manually would be too much)

Im extending the marionette.region open and close function. Problem is that it now doesnt call the onClose function inside each of my views.

If I add the code directly to the marionette file it works fine. So I'm probably merging the functions incorrectly, right?

Here is my code:

extendMarrionette: function () {
  _.extend(Marionette.Region.prototype, {

    open : function (view) {
      var that = this;

      // if this is the main content and should transition
      if (this.$el.attr("id") === "wrapper" && document.wrapperIsHidden === true) {
        this.$el.empty().append(view.el);
        $(document).trigger("WrapperContentChanged")

      } else if (this.$el.attr("id") === "wrapper" && document.wrapperIsHidden === false) {
        $(document).on("WrapperIsHidden:open", function () {

          //swap content
          that.$el.empty().append(view.el);

          //tell router to transition in
          $(document).trigger("WrapperContentChanged");

          //remove this event listener
          $(document).off("WrapperIsHidden:open", that);
        });

      } else {
        this.$el.empty().append(view.el);
      }

    },

    //A new function Ive added - was originally inside the close function below. Now the close function calls this function.
    kill : function (that) {
      var view = this.currentView;
      $(document).off("WrapperIsHidden:close", that)
      if (!view || view.isClosed) {
        return;
      }

      // call 'close' or 'remove', depending on which is found
      if (view.close) {
        view.close();
      }
      else if (view.remove) {
        view.remove();
      }

      Marionette.triggerMethod.call(that, "close", view);

      delete this.currentView;
    },

    // Close the current view, if there is one. If there is no
    // current view, it does nothing and returns immediately.
    close : function () {
      var view = this.currentView;
      var that = this;

      if (!view || view.isClosed) {
        return;
      }

      if (this.$el.attr("id") === "wrapper" && document.wrapperIsHidden === true) {
        this.kill(this);

      } else if (this.$el.attr("id") === "wrapper" && document.wrapperIsHidden === false) {

        //Browser bug fix - needs set time out
        setTimeout(function () {
          $(document).on("WrapperIsHidden:close", that.kill(that));
        }, 10)


      } else {
        this.kill(this);
      }

    }

  });
}
2
What version of Marionette are you using?Andrew Hubbs
Im using V 1.8.3 - should probably do the upgrade to v2Dustin Silk
Thanks. The Region code has changed a lot between the different versions ;-].Andrew Hubbs

2 Answers

1
votes

Why don't you extend the Marionette.Region? That way you can choose between using your custom Region class, or the original one if you don't need the smooth transition in all cases. (And you can always extend it again if you need some specific behavior for some specific case).

https://github.com/marionettejs/backbone.marionette/blob/master/docs/marionette.region.md#region-class

var MyRegion = Marionette.Region.extend({
    open: function() {
        //Your open function
    }

    kill: function() {
        //Your kill function
    }

    close: function() {
        //Your close function
    }
});

App.addRegions({
    navigationRegion: MyRegion
});
0
votes

Perhaps your issue is that you are not passing a function to your event listener, but instead calling the code directly in the code below.

setTimeout(function(){
  $(document).on("WrapperIsHidden:close", that.kill(that));
}, 10)

It is likely that you want something like this:

setTimeout(function(){
  $(document).on("WrapperIsHidden:close", function (){ that.kill(that); });
}, 10)

Another possible problem is that you are mixing up your references to this/that in your kill function. It seems like you probably want var view to either be assigned to that.view or to use this rather than that throughout the method.

Answer to your additional problems:

You should try passing the view variable from the close function directly into your kill function because the reference to currentView is already changed to the new view object when you actually want to old view object. The reason this is happening is that you are setting a timeout before executing the kill function. You can see this if you look at the show source code. It expects close, open and then currentView assignment to happen synchronously in order.