From fe3f95e569b61ddbd18bad5a2930115988eefcdc Mon Sep 17 00:00:00 2001
From: Zac Spitzer
Date: Mon, 12 Oct 2015 12:08:01 +1100
Subject: [PATCH 01/13] Update internal.js
there is no need to clone() here, it creates a memory leak as it's not attached the to DOM and therefore isn't removed by remove()
---
src/internal.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/internal.js b/src/internal.js
index 9b9bba4..1d7984e 100644
--- a/src/internal.js
+++ b/src/internal.js
@@ -873,7 +873,7 @@ function replacePlaceHolder(placeholder, element)
placeholder.each(function (index, item)
{
// todo: check how append is implemented. Perhaps cloning here is superfluous.
- $(item).before(element.clone(true)).remove();
+ $(item).before(element).remove();
});
}
@@ -945,4 +945,4 @@ function sortRows()
this.rows.sort(sort);
}
}
-}
\ No newline at end of file
+}
From 1225b4a0475bcf57fc88dc9f98d284299f466ff2 Mon Sep 17 00:00:00 2001
From: Zac Spitzer
Date: Fri, 30 Oct 2015 14:29:05 +1100
Subject: [PATCH 02/13] Add an event columnToggle
Trigger an event when columns are toggled on or off
---
src/internal.js | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/internal.js b/src/internal.js
index 1d7984e..5ed0af8 100644
--- a/src/internal.js
+++ b/src/internal.js
@@ -393,6 +393,7 @@ function renderColumnSelection(actions)
that.element.find("tbody").empty(); // Fixes an column visualization bug
renderTableHeader.call(that);
loadData.call(that);
+ that.element.trigger("columnToggle" + namespace, column);
}
});
dropDown.find(getCssSelector(css.dropDownMenuItems)).append(item);
From 2d26feab84017344a679b45f5bbfdb54149941ae Mon Sep 17 00:00:00 2001
From: Zac Spitzer
Date: Thu, 15 Sep 2016 11:48:17 +0200
Subject: [PATCH 03/13] 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
+}
From d33185db250f7e109d80ba0cb49b69d1bffc0f1a Mon Sep 17 00:00:00 2001
From: Zac Spitzer
Date: Thu, 15 Sep 2016 11:55:46 +0200
Subject: [PATCH 04/13] Update extensions.js
---
src/extensions.js | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/extensions.js b/src/extensions.js
index 4956360..968da4d 100644
--- a/src/extensions.js
+++ b/src/extensions.js
@@ -101,9 +101,10 @@ if (!String.prototype.resolve)
for (var i = 0; i < str.length; i++){
if (typeof str[i] === "object"){
var key = str[i].key;
+ var v = "";
// now we have a variable to be substitued
if (substitutes.hasOwnProperty(key[0]))
- var v = substitutes[key[0]];
+ v = substitutes[key[0]];
else
continue;
From 8d11d27a72c6b5d73d9a4d0c686296c457456802 Mon Sep 17 00:00:00 2001
From: Zac Spitzer
Date: Thu, 15 Sep 2016 12:00:50 +0200
Subject: [PATCH 05/13] lint clean up
---
src/extensions.js | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/src/extensions.js b/src/extensions.js
index 968da4d..cab961c 100644
--- a/src/extensions.js
+++ b/src/extensions.js
@@ -76,11 +76,16 @@ if (!String.prototype.resolve)
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){
+ if (hasStart || hasEnd)
+ {
str[i] = s; //plain old html
} else {
str[i] = {
@@ -104,9 +109,13 @@ if (!String.prototype.resolve)
var v = "";
// now we have a variable to be substitued
if (substitutes.hasOwnProperty(key[0]))
+ {
v = substitutes[key[0]];
+ }
else
+ {
continue;
+ }
for (var k = 1; k < key.length; k++){
if (v.hasOwnProperty(key[k])){
From f7cfe39c2c7ede5e8cc285a7d159c34ddb396b8c Mon Sep 17 00:00:00 2001
From: Zac Spitzer
Date: Fri, 9 Dec 2016 11:45:21 +1100
Subject: [PATCH 06/13] move label infos templated string into templates
rather than needing to recursively process every string, move the templated string for infos into the template definitions
---
src/public.js | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/src/public.js b/src/public.js
index 16c5c44..16c001f 100644
--- a/src/public.js
+++ b/src/public.js
@@ -334,7 +334,10 @@ Grid.defaults = {
**/
labels: {
all: "All",
- infos: "Showing {{ctx.start}} to {{ctx.end}} of {{ctx.total}} entries",
+ showing: "Showing",
+ to: "to",
+ of: "of",
+ entries: "entries",
loading: "Loading...",
noResults: "No results found!",
refresh: "Refresh",
@@ -406,7 +409,7 @@ Grid.defaults = {
header: "