documentcloud / jammit

Industrial Strength Asset Packaging for Rails
http://documentcloud.github.com/jammit/
MIT License
1.16k stars 197 forks source link

Maintain position of JST templates #80

Closed shayne closed 8 years ago

shayne commented 13 years ago

Ran into an issue where I needed some vendored libraries (like underscore and jQuery) loaded before my templates, but my application specific js (e.g. common.js, core.js) loaded after the templates.

Updates to packager and compressor.

jashkenas commented 13 years ago

I kind of think that it's a feature to have all of the templates included at the bottom of the asset package. Shouldn't your JavaScript that needs the templates to be loaded be waiting for DOMReady, and not executing the templates immediately?

shayne commented 13 years ago

I understand your point and maybe you can weigh in on my reasoning.

I'm building a simple example app using Rails, Backbone and Jammit. My backbone collections, models and views are loaded into memory before the DOM is ready, this seems logical to me.

The order specified is my assets.yml looks something like:

The common.js files contains the Backbone models, views and collections.

Here's one of those views:

var TaskView = Backbone.View.extend({
  tagName: "li",

  events: {
    "click .destroy" : "destroyTask"
  },

  template: JST["task"],    // needs to have template in memory

  initialize : function() {
    this.render();

    this.model.bind("change", _.bind(this.render, this));
  },

  render : function() {
    $(this.el).html(this.template(this.model.toJSON()));
    this.handleEvents();
    return this;
  },

  destroyTask : function() {
    this.model.destroy();
    $(this.el).slideUp(300, function() {
      $(this).remove();
    });
    return false;
  }
});

With the Jammit always putting JSTs at the bottom I'd need to create three expansions in my assets.yml:

  1. vendor - all 3rd party libs
  2. templates - JSTs
  3. common - application specific JS including Backbone models, views, collections, etc...

This is a workaround really that adds two additional requests for JS just to accomodate an order of operations.

Interested at your take...

jashkenas commented 13 years ago

That's an excellent use case for doing ordered JavaScript template includes. I'll take a pass at merging your patch. For the time being, you can just look up the template from the JST object inside of the render function...

mikz commented 13 years ago

I would use @Array.split@ or @Array.chunk@ to split array and preserve ordering even if there would be multiple template blocks. But sadly first is dependent on active_support/core_extensions and second on Ruby 1.9.2.

agibralter commented 13 years ago

You could also not refer to global objects before they are defined and access them at "run time" (i.e. when the function is called):

var TaskView = Backbone.View.extend({
  tagName: "li",

  events: {
    "click .destroy" : "destroyTask"
  },

  template: "task",

  initialize : function() {
    this.render();

    this.model.bind("change", _.bind(this.render, this));
  },

  render : function() {
    $(this.el).html(JST[this.template](this.model.toJSON()));
    this.handleEvents();
    return this;
  },

  destroyTask : function() {
    this.model.destroy();
    $(this.el).slideUp(300, function() {
      $(this).remove();
    });
    return false;
  }
});
zerowidth commented 13 years ago

+1 to this. In the meantime, lazy-evaluation of templates in the render function bypasses the issue.

trungpham commented 13 years ago

I need this too...

jsmestad commented 13 years ago

+1 to this as well.

atavistock commented 13 years ago

We're facing the same problem. It would also be the path of least confusion to make reasonable attempts to preserve the order.

trungpham commented 13 years ago

any update on this pull request? it has only been opened for 10 months. :)

jashkenas commented 13 years ago

Nope -- just been busy, sorry about that.

unicornrainbow commented 12 years ago

+1 This would be nice to have.

I was surprised to learn that JST are included at the end... I'm curious about the rationale behind doing it that way verus just honoring the order specified in the assets.yml file.

jarosan commented 12 years ago

Just came across this issue. +1 on keeping the include order.

euge commented 12 years ago

+1

euge commented 12 years ago

This patch is still valid, but PATH_TO_URL needs to be replaced with path_to_url. Thanks

splurgy-michi commented 11 years ago

+1. Hit a scenario where the document ready state is ALREADY true when the JS is being loaded in. This causes the application to start running as soon as it is loaded in before it has a chance to load in the templates (this is an IE8-only issue and is highly annoying). Using document on ready does not help in this scenario.

sobrinho commented 10 years ago

I'm surprised by this behaviour too, I workarounded it using the lazy-evaluation but still do not make sense.

+1 for merging, respecting the assets.yml order is a must :+1: