Domanda

Intro

I'm trying to create an aggregate file with all of my UnderscoreJS templates in it. I'll explain how I've achieved this with a JSP app with a Java backend.

How I got it working in my JSP app:

When using jsp pages, you're able to do:

<html>
<head> ... </head>
<body>
  ...
  <jsp:include page="./path/to/aggregate_templates.jsp"/>
</body>
</html>

And in this file, you can have all of your UnderscoreJS templates listed like so:

<jsp:include page="./path/to/js/view/home/file.template"/>
<jsp:include page="./path/to/js/view/home/file2.template"/>
...

Question

Rather than a Java backend, I'm using a NodeJS server. Is there a way I can have an aggregate template file on the fly that does the same thing as jsp:include? Or is my only option something like this: Templating using RequireJS (text.js plugin) and Underscore?

È stato utile?

Soluzione

The solution:

  1. Append all *.template files together with fileUtil.aggregateTemplates() into aggregate.template
  2. When index.html is loaded in the browser, main.js runs
  3. Before doing anything else, main.js calls TemplateCache.setup()
  4. TemplateCache.setup() adds the contents of aggregate.template to $("#templates")
  5. All templates are now in the html and at the Backbone views' disposal

The code:

In app.js

...
var fileUtil = require('./utils/file-util');
var aggregateTemplateFile = 'path/to/aggregate.template';
var targetDir = 'path/to/directory/containing/template/files';
fileUtil.aggregateTemplates(targetDir, aggregateTemplateFile);
...

In file-util.js

var fs = require('fs');
var path = require('path');

/**
 * Traverse the directory
 * @param dir - directory to traverse
 * @param cond - callback for determining whether or not to keep file
 * @param done - callback for what to do with results
 */
var walk = function(dir, cond, done){
    var results = [];
    fs.readdir(dir, function(err, list){
        if(err){
            return done(err);
        }
        var i = 0;
        (function next(){
            var file = list[i++];
            if(!file){
                return done(null, results);
            }
            file = path.resolve(dir, file);
            fs.stat(file, function(err, stat){
                if(stat && stat.isDirectory()){
                    walk(file, cond, function(err, res){
                        results = results.concat(res);
                        next();
                    });
                }else{
                    if(cond(file)){
                        results.push(file);
                    }
                    next();
                }
            });
        })();
    });
};

/**
 * Create aggregate file
 * @param fileArr - array of files (full path)
 * @param targetFile - file to print to (full path)
 * @param strictOrder - (optional) boolean whether or not to enforce order
 */
var createAggregate = function(fileArr, targetFile, strictOrder){
    if(!fileArr || fileArr.length<1){
        return;
    }
    fs.writeFileSync(targetFile, ""); // clear file
    if(strictOrder){
        var i = 0;
        (function next(){
            var file = fileArr[i++];
            if(!file){
                return;
            }
            fs.readFile(file, function(err, data){
                if(err) throw err;
                fs.appendFileSync(targetFile, data);
                next();
            });
        })();
        return;
    }
    for(var i=0; i<fileArr.length; i++){
        var file = fileArr[i];
        fs.readFile(file, function(err, data){
            if(err) throw err;
            fs.appendFileSync(targetFile, data);
        });
    }
};

/**
 * Create an aggregate template file
 * @param targetDir - directory to look in (full path)
 * @param targetFile - file to print to (full path)
 */
exports.aggregateTemplates = function(targetDir, targetFile){
    // Determine what kind of files we care about
    var isTemplate = function(file){
        return file.match(/.+\.template$/);
    };
    // Determine what we do with the results
    var done = function(err, result){
        if(err) throw err;
        createAggregate(result, targetFile);
    };
    // Traverse the target directory
    walk(targetDir, isTemplate, done);
};

In index.html

<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <title>MyApp</title>
    <link rel="stylesheet" href="/lib/bootstrap/css/bootstrap.css">
    <link rel="stylesheet" href="/lib/bootstrap/css/bootstrap-custom.css">
    <link rel="stylesheet" href="/lib/font-awesome/css/font-awesome.css">
    <link rel="stylesheet" href="/stylesheets/style.css">
    <link rel="stylesheet" href="/stylesheets/style-responsive.css">
</head>
<body class="center-on-page">
    <div id="header" class="affix"></div>
    <div id="content"></div>

    <div id="javascript">
        <!-- JavaScript Library Imports -->
        <!-- JavaScript Local Imports -->

        <!-- Code Entry Point -->
        <script type="text/javascript" src="/js/main.js"></script>
    </div>

    <!-- Underscore Templates -->
    <div id="templates"></div>
</body>
</html>

In main.js

(function(){

$.when(app.util.TemplateCache.setup())
    .done(function(){
        // Start the router
        new app.Router();
        Backbone.history.start();
    });

})();

app.util.TemplateCache.setup

app.util.TemplateCache.setup = function(){
    var opts = { url: "aggregate.template" };
    return $.ajax(opts)
        .done(function(data, textStatus, jqxhr){
            console.log("Loaded aggregate template file");
            $("#templates").html(data);
        })
        .fail(function(data, textStatus, jqxhr){
            console.log("Failed to load aggregate template file");
        });
};
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top