Great question. I don’t have a perfect option, but I’ll offer a variant of your solution #3 that I like. Same idea as solution #3 but move the jade template for the _full file into your code, since it is boilerplate and javascript can generate it when needed for a full page. disclaimer: untested, but I humbly suggest:
app.use(function (req, res, next) {
var template = "extends layout.jade\n\nblock content\n include ";
res.renderView = function (viewName, opts) {
if (req.xhr) {
var renderResult = jade.compile(template + viewName + ".jade\n", opts);
res.send(renderResult);
} else {
res.render(viewName, opts);
}
next();
};
});
And you can get more clever with this idea as your scenarios become more complicated, for example saving this template to a file with placeholders for file names.
Of course this is still not a perfect solution. You’re implementing features that should really be handled by your template engine, same as your original objection to solution #3. If you end up writing more than a couple dozen of lines of code for this then try to find a way to fit the feature into Jade and send them a pull request. For example if the jade “extends” keyword took an argument that could disable extending the layout for xhr requests…
For your second problem, I’m not sure any template engine can help you. If you’re using ajax navigation, you can’t very well “unload” page_a.js when the navigation happens via some back end template magic. I think you have to use traditional javascript isolation techniques for this (client-side). To your specific concerns: Implement the page specific logic (and variables) in closures, for starter, and have sensible cooperation between them where necessary. Secondly, you don’t need to worry too much about hooking up double event handlers. Assuming the main content gets cleared on ajax navigation and also those are the elements that had the event handlers get attached that will call get reset (of course) when the new ajax content is loaded into the DOM.