(function($) { Alpaca.AbstractTemplateEngine = Base.extend( { constructor: function(id) { this.base(); this.id = id; this.cleanup = function(html) { if (html) { // if if starts with a script tag, then we strip that out if ($(html).length === 1) { if ($(html)[0].nodeName.toLowerCase() === "script") { return $(html).html(); } } } return html; }; }, /** * Compiles the given template (or URI or dom selector) * * The callback is fired once the compile completes and has signature callback(err). * * @param cacheKey * @param template * @param callback */ compile: function(cacheKey, template, callback) { var self = this; // the value being compiled can be // HTML // URL (http, ./ or /) // dom selector (#abc, .classname) // dom element // here we try to determine what type of value it is var type = "html"; if (Alpaca.isString(template)) { var lc = template.toLowerCase(); if (Alpaca.isUri(lc)) { type = "uri"; } else if (template.indexOf("#") === 0 || template.indexOf(".") === 0 || template.indexOf("[") === 0) { type = "selector"; } } else { // it's a dom element, we flow through } // now extract html and compile if (type === "selector") { self._compile(cacheKey, template, function(err) { callback(err); }); } else if (type === "uri") { var fileExtension = self.fileExtension(); var url = template; if (url.indexOf("." + fileExtension) === -1) { url += "." + fileExtension; } // load the template via ajax $.ajax({ "url": url, "dataType": "html", "success": function(html, code, xhr) { // cleanup html html = self.cleanup(html); self._compile(cacheKey, html, function(err) { callback(err); }); }, "error": function(xhr, code) { callback({ "message": xhr.responseText, "xhr": xhr, "code": code }, null); } }); } else if (type === "html") { var html = template; if (html instanceof jQuery) { html = $(html).outerHTML(); } self._compile(cacheKey, html, function(err) { callback(err); }); } else { callback(new Error("Template engine cannot determine how to handle type: " + type)); } }, _compile: function(cacheKey, html, callback) { // for null templates, set to empty string if (Alpaca.isEmpty(html)) { html = ""; } // trim the html html = Alpaca.trim(html); if (html.toLowerCase().indexOf("<script") === 0) { // already has script tag } else { // apply script tag html = "<script type='" + this.supportedMimetypes()[0] + "'>" + html + "</script>"; } Alpaca.logDebug("Compiling template: " + this.id + ", cacheKey: " + cacheKey + ", template: " + html); this.doCompile(cacheKey, html, callback); }, /** * @extension_point * * @param cacheKey * @param html * @param callback */ doCompile: function(cacheKey, html, callback) { }, /** * @extension_point * * @param cacheKey * @param model * @param errorCallback */ execute: function(cacheKey, model, errorCallback) { Alpaca.logDebug("Executing template for cache key: " + cacheKey); var html = this.doExecute(cacheKey, model, errorCallback); // removes wrapping <script/> tag html = this.cleanup(html); return html; }, /** * Execute a template and hand back a text string. * * @extension_point * * @param cacheKey * @param model * @param errorCallback */ doExecute: function(cacheKey, model, errorCallback) { return null; }, /** * Hands back the expected file extension for templates loaded via URI. * * @return {String} */ fileExtension: function() { return "html"; }, /** * Hands back the list of associated script tag types for templates loaded from the DOM. * * @return {Array} */ supportedMimetypes: function() { return []; }, /** * Determines whether an existing template is already in cache. * * @param cacheKey */ isCached: function(cacheKey) { return false; }, /** * Acquires an array of cache keys matching the view. * * @param viewId */ findCacheKeys: function(viewId) { return []; } }); })(jQuery);