From 2d26feab84017344a679b45f5bbfdb54149941ae Mon Sep 17 00:00:00 2001 From: Zac Spitzer Date: Thu, 15 Sep 2016 11:48:17 +0200 Subject: [PATCH] Drastically faster templating approach The current templating approach is really inefficient, as it recursively loops thru every passed available variable for substituion and applies a regex for each one. It's much faster to initially parse the template and then only process those strings which are actually present in the template. This revised implementation both caches the parsed templates and then only processes the string which are present. The performance improvement is quite drastic, especially with large tables. A large table was previously taking 15s to render in Chrome, now takes less than 1s with this approach --- src/extensions.js | 74 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 54 insertions(+), 20 deletions(-) diff --git a/src/extensions.js b/src/extensions.js index cb37139..4956360 100644 --- a/src/extensions.js +++ b/src/extensions.js @@ -65,32 +65,66 @@ if (!String.prototype.resolve) return value; } }; + + var _templateCache = {}; + var getTemplate = function(template){ + if (!_templateCache.hasOwnProperty(template)){ + var str = template.split(/{([^{}]+)}/g); + + for (var i = 0; i < str.length; i++){ + var s = str[i]; + var hasStart = (s.charAt(0) === "}"); + var hasEnd = (s.charAt(s.length - 1) === "{"); + if (hasStart) + s = s.substr(1); + if (hasEnd) + s = s.substr(0, s.length - 1); + + if (hasStart || hasEnd){ + str[i] = s; //plain old html + } else { + str[i] = { + token: str[i], + key: s.split(".") + }; + } + } + _templateCache[template] = str; + } + return _templateCache[template]; + }; String.prototype.resolve = function (substitutes, prefixes) { - var result = this; - $.each(substitutes, function (key, value) - { - if (value != null && typeof value !== "function") - { - if (typeof value === "object") - { - var keys = (prefixes) ? $.extend([], prefixes) : []; - keys.push(key); - result = result.resolve(value, keys) + ""; - } + var str = getTemplate(this); + var result = ""; + for (var i = 0; i < str.length; i++){ + if (typeof str[i] === "object"){ + var key = str[i].key; + // now we have a variable to be substitued + if (substitutes.hasOwnProperty(key[0])) + var v = substitutes[key[0]]; else - { - if (formatter && formatter[key] && typeof formatter[key] === "function") - { - value = formatter[key](value); + continue; + + for (var k = 1; k < key.length; k++){ + if (v.hasOwnProperty(key[k])){ + v = v[key[k]]; + } else { + v = null; + break; } - key = (prefixes) ? prefixes.join(".") + "." + key : key; - var pattern = new RegExp("\\{\\{" + key + "\\}\\}", "gm"); - result = result.replace(pattern, (value.replace) ? value.replace(/\$/gi, "$") : value); } + var formatter_key = key[key.length-1]; + if (formatter && formatter[formatter_key] && typeof formatter[formatter_key] === "function"){ + result += formatter[formatter_key](v); + } else { + result += v; + } + } else { + result += str[i]; // plain old html } - }); + } return result; }; } @@ -167,4 +201,4 @@ if (!Array.prototype.propValues) } return result; }; -} \ No newline at end of file +}