Example of loading a template from a script tag within the same document.
+
+
+
+
+
+
+
diff --git a/Examples/index.html b/Examples/index.html
index e13f315..f14d59a 100644
--- a/Examples/index.html
+++ b/Examples/index.html
@@ -9,7 +9,7 @@
-
+
$($div).load($(this).attr("href"), function () {
$(".contentContainer > div").hide();
$(".codeContainer > div").hide();
- $(".contentContainer div.content").html($div.html());
+ $(".contentContainer div.content").html("").append($div);
$(".codeContainer pre code").text($div.html());
if(highlightSupported()) {
$(".codeContainer pre code").each(function () {
diff --git a/bower.json b/bower.json
new file mode 100644
index 0000000..5b6e0c6
--- /dev/null
+++ b/bower.json
@@ -0,0 +1,32 @@
+{
+ "name": "jquery-load-template",
+ "homepage": "http://codepb.github.io/jquery-template/",
+ "authors": [
+ "Paul Burgess "
+ ],
+ "description": "jQuery plugin for loading and using templates. The plugin supports loading templates from within the page, or using AJAX to load html files.",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/codepb/jquery-template.git"
+ },
+ "main": "dist/jquery.loadTemplate.js",
+ "keywords": [
+ "templates",
+ "templating",
+ "jquery-plugin"
+ ],
+ "ignore": [
+ "Examples",
+ "tests",
+ ".gitattributes",
+ ".gitignore",
+ ".travis.yml",
+ "loadTemplate.jquery.json",
+ "MIT-LICENSE.txt",
+ "package.json",
+ "readme.md"
+ ],
+ "dependencies": {
+ "jquery": ">=1.8"
+ }
+}
diff --git a/jquery-loadTemplate/jquery.loadTemplate-1.3.2.js b/dist/jquery.loadTemplate.js
similarity index 62%
rename from jquery-loadTemplate/jquery.loadTemplate-1.3.2.js
rename to dist/jquery.loadTemplate.js
index 60da5ee..aa9ba52 100644
--- a/jquery-loadTemplate/jquery.loadTemplate-1.3.2.js
+++ b/dist/jquery.loadTemplate.js
@@ -2,18 +2,20 @@
"use strict";
var templates = {},
queue = {},
- formatters = {};
+ formatters = {},
+ isArray;
function loadTemplate(template, data, options) {
var $that = this,
$template,
- settings,
- isFile;
+ isFile,
+ settings;
data = data || {};
- settings = $.extend({
+ settings = $.extend(true, {
// These are the defaults.
+ async: true,
overwriteCache: false,
complete: null,
success: null,
@@ -29,10 +31,16 @@
append: false,
prepend: false,
beforeInsert: null,
- afterInsert: null
+ afterInsert: null,
+ bindingOptions: {
+ ignoreUndefined: false,
+ ignoreNull: false,
+ ignoreEmptyString: false
+ }
}, options);
if ($.type(data) === "array") {
+ isArray = true;
return processArray.call(this, template, data, settings);
}
@@ -77,6 +85,7 @@
done = 0,
success = 0,
errored = false,
+ errorObjects = [],
newOptions;
if (settings.paged) {
@@ -85,20 +94,20 @@
todo = data.length;
}
+ if (!settings.append && !settings.prepend) {
+ $that.html("");
+ }
+
newOptions = $.extend(
{},
settings,
{
- complete: function () {
- if (doPrepend) {
- $that.prepend(this.html());
- } else {
- $that.append(this.html());
- }
+ append: !settings.prepend && true,
+ complete: function (data) {
done++;
- if (done === todo) {
+ if (done === todo || errored) {
if (errored && settings && typeof settings.error === "function") {
- settings.error.call($that);
+ settings.error.call($that, errorObjects);
}
if (settings && typeof settings.complete === "function") {
settings.complete();
@@ -113,20 +122,22 @@
}
}
},
- error: function () {
+ error: function (e) {
errored = true;
+ errorObjects.push(e);
}
}
);
- if (!settings.append && !settings.prepend) {
- $that.html("");
- }
+
if (doPrepend) data.reverse();
$(data).each(function () {
- var $div = $("");
- loadTemplate.call($div, template, this, newOptions);
+
+ loadTemplate.call($that, template, this, newOptions);
+ if (errored) {
+ return false;
+ }
});
return this;
@@ -155,38 +166,38 @@
function urlAvoidCache(url) {
if (url.indexOf('?') !== -1) {
- return url += "&_=" + uniqueId();
+ return url + "&_=" + uniqueId();
}
else {
- return url += "?_=" + uniqueId();
+ return url + "?_=" + uniqueId();
}
}
function loadAndPrepareTemplate(template, selection, data, settings) {
- var $templateContainer = $("");
templates[template] = null;
+ var templateUrl = template;
if (settings.overwriteCache) {
- template = urlAvoidCache(template);
+ templateUrl = urlAvoidCache(templateUrl);
}
- $templateContainer.load(template, function (responseText, textStatus) {
- if (textStatus === "error") {
- handleTemplateLoadingError(template, selection, data, settings);
- } else {
- handleTemplateLoadingSuccess($templateContainer, template, selection, data, settings);
+ $.ajax({
+ url: templateUrl,
+ async: settings.async,
+ success: function (templateContent) {
+ handleTemplateLoadingSuccess($(templateContent), template, selection, data, settings);
+ },
+ error: function (e) {
+ handleTemplateLoadingError(template, selection, data, settings, e);
}
});
}
function loadTemplateFromDocument($template, selection, data, settings) {
- var $templateContainer = $("");
-
- if ($template.is("script")) {
+ if ($template.is("script") || $template.is("template")) {
$template = $.parseHTML($.trim($template.html()));
}
- $templateContainer.html($template);
- prepareTemplate.call(selection, $templateContainer, data, settings);
+ prepareTemplate.call(selection, $template, data, settings);
if (typeof settings.success === "function") {
settings.success();
@@ -194,12 +205,16 @@
}
function prepareTemplate(template, data, settings) {
- bindData(template, data);
+ var template = $("").append(template);
+ bindData(template, data, settings);
$(this).each(function () {
- var $templateHtml = $(template.html());
+ var $templateHtml = template.children().clone(true);
+ $("select", $templateHtml).each(function (key, value) {
+ $(this).val($("select", template).eq(key).val())
+ });
if (settings.beforeInsert) {
- settings.beforeInsert($templateHtml);
+ settings.beforeInsert($templateHtml, data);
}
if (settings.append) {
@@ -207,28 +222,28 @@
} else if (settings.prepend) {
$(this).prepend($templateHtml);
} else {
- $(this).html($templateHtml);
+ $(this).html("").append($templateHtml);
}
if (settings.afterInsert) {
- settings.afterInsert($templateHtml);
+ settings.afterInsert($templateHtml, data);
}
});
if (typeof settings.complete === "function") {
- settings.complete.call($(this));
+ settings.complete.call($(this), data);
}
}
- function handleTemplateLoadingError(template, selection, data, settings) {
+ function handleTemplateLoadingError(template, selection, data, settings, error) {
var value;
if (typeof settings.error === "function") {
- settings.error.call(selection);
+ settings.error.call(selection, error);
}
$(queue[template]).each(function (key, value) {
if (typeof value.settings.error === "function") {
- value.settings.error.call(value.selection);
+ value.settings.error.call(value.selection, error);
}
});
@@ -265,68 +280,101 @@
}
}
- function bindData(template, data) {
+ function bindData(template, data, settings) {
data = data || {};
- processElements("data-content", template, data, function ($elem, value) {
- $elem.html(applyFormatters($elem, value, "content"));
+ processElements("data-content", template, data, settings, function ($elem, value) {
+ $elem.html(applyFormatters($elem, value, "content", settings));
+ });
+
+ processElements("data-content-append", template, data, settings, function ($elem, value) {
+ $elem.append(applyFormatters($elem, value, "content", settings));
});
- processElements("data-content-append", template, data, function ($elem, value) {
- $elem.append(applyFormatters($elem, value, "content"));
+ processElements("data-content-prepend", template, data, settings, function ($elem, value) {
+ $elem.prepend(applyFormatters($elem, value, "content", settings));
});
- processElements("data-content-prepend", template, data, function ($elem, value) {
- $elem.prepend(applyFormatters($elem, value, "content"));
+ processElements("data-content-text", template, data, settings, function ($elem, value) {
+ $elem.text(applyFormatters($elem, value, "content", settings));
});
- processElements("data-content-text", template, data, function ($elem, value) {
- $elem.text(applyFormatters($elem, value, "content"));
+ processElements("data-innerHTML", template, data, settings, function ($elem, value) {
+ $elem.html(applyFormatters($elem, value, "content", settings));
});
- processElements("data-src", template, data, function ($elem, value) {
- $elem.attr("src", applyFormatters($elem, value, "src"));
+ processElements("data-src", template, data, settings, function ($elem, value) {
+ $elem.attr("src", applyFormatters($elem, value, "src", settings));
}, function ($elem) {
$elem.remove();
});
- processElements("data-alt", template, data, function ($elem, value) {
- $elem.attr("alt", applyFormatters($elem, value, "alt"));
+ processElements("data-href", template, data, settings, function ($elem, value) {
+ $elem.attr("href", applyFormatters($elem, value, "href", settings));
+ }, function ($elem) {
+ $elem.remove();
});
- processElements("data-value", template, data, function ($elem, value) {
- $elem.attr("value", applyFormatters($elem, value, "value"));
+ processElements("data-alt", template, data, settings, function ($elem, value) {
+ $elem.attr("alt", applyFormatters($elem, value, "alt", settings));
+ });
+
+ processElements("data-title", template, data, settings, function ($elem, value) {
+ $elem.attr("title", applyFormatters($elem, value, "title", settings));
+ });
+
+ processElements("data-id", template, data, settings, function ($elem, value) {
+ $elem.attr("id", applyFormatters($elem, value, "id", settings));
+ });
+
+ processElements("data-css", template, data, settings, function ($elem, value) {
+ $elem.css(applyFormatters($elem, value, "css", settings))
+ });
+
+ processElements("data-class", template, data, settings, function ($elem, value) {
+ $elem.addClass(applyFormatters($elem, value, "class", settings));
});
- processElements("data-link", template, data, function ($elem, value) {
+ processElements("data-link", template, data, settings, function ($elem, value) {
var $linkElem = $("");
- $linkElem.attr("href", applyFormatters($elem, value, "link"));
+ $linkElem.attr("href", applyFormatters($elem, value, "link", settings));
$linkElem.html($elem.html());
$elem.html($linkElem);
});
- processElements("data-link-wrap", template, data, function ($elem, value) {
+ processElements("data-link-wrap", template, data, settings, function ($elem, value) {
var $linkElem = $("");
- $linkElem.attr("href", applyFormatters($elem, value, "link-wrap"));
+ $linkElem.attr("href", applyFormatters($elem, value, "link-wrap", settings));
$elem.wrap($linkElem);
});
- processElements("data-options", template, data, function ($elem, value) {
+ processElements("data-options", template, data, settings, function ($elem, value) {
$(value).each(function () {
var $option = $("");
$option.attr('value', this).text(this).appendTo($elem);
});
});
- processAllElements(template, data);
+ processAllElements(template, data, settings);
+
+ processElements("data-value", template, data, settings, function ($elem, value) {
+ $elem.val(applyFormatters($elem, value, "value", settings));
+ });
+
+
}
- function processElements(attribute, template, data, dataBindFunction, noDataFunction) {
+ function processElements(attribute, template, data, settings, dataBindFunction, noDataFunction) {
$("[" + attribute + "]", template).each(function () {
var $this = $(this),
param = $this.attr(attribute),
value = getValue(data, param);
+ if (!valueIsAllowedByBindingOptions($this, value, settings)) {
+ $this.remove();
+ return;
+ }
+
$this.removeAttr(attribute);
if (typeof value !== 'undefined' && dataBindFunction) {
@@ -338,7 +386,44 @@
return;
}
- function processAllElements(template, data) {
+ function valueIsAllowedByBindingOptions(bindingOptionsContainer, value, settings) {
+
+ var bindingOptions = getBindingOptions(bindingOptionsContainer, settings);
+
+ if (bindingOptions.ignoreUndefined && typeof value === "undefined") {
+ return false;
+
+ } else if (bindingOptions.ignoreNull && value === null) {
+ return false;
+
+ } else if (bindingOptions.ignoreEmptyString && value === "") {
+ return false;
+
+ } else {
+ return true;
+ }
+ }
+
+ function getBindingOptions(bindingOptionsContainer, settings) {
+
+ var bindingOptions = {};
+
+ // binding options passed as template attribute, i.e. 'data-binding-options'
+ if (bindingOptionsContainer instanceof jQuery && bindingOptionsContainer.attr("data-binding-options")) {
+
+ bindingOptions = $.parseJSON(bindingOptionsContainer.attr("data-binding-options"));
+ bindingOptionsContainer.removeAttr("data-binding-options");
+
+ // binding options defined in a "data-template-bind" attribute
+ } else if (typeof bindingOptionsContainer === "object" && bindingOptionsContainer.hasOwnProperty('bindingOptions')) {
+ bindingOptions = bindingOptionsContainer.bindingOptions;
+ }
+
+ // extend general bindingOptions with specific settings
+ return $.extend({}, settings.bindingOptions, bindingOptions);
+ }
+
+ function processAllElements(template, data, settings) {
$("[data-template-bind]", template).each(function () {
var $this = $(this),
param = $.parseJSON($this.attr("data-template-bind"));
@@ -353,9 +438,16 @@
} else {
value = getValue(data, this.value);
}
- if (typeof value !== "undefined" && this.attribute) {
+ if (this.attribute) {
+
+ if (!valueIsAllowedByBindingOptions(this, value, settings)) {
+ $this.remove();
+ return;
+ }
+
switch (this.attribute) {
case "content":
+ case "innerHTML":
$this.html(applyDataBindFormatters($this, value, this));
break;
case "contentAppend":
@@ -386,9 +478,11 @@
});
}
- function applyDataBindFormatters($elem, value, data) {
+ function applyDataBindFormatters($elem, value, data, settings) {
if (data.formatter && formatters[data.formatter]) {
- return formatters[data.formatter].call($elem, value, data.formatOptions);
+ return (function (formatterSettings) {
+ return formatters[data.formatter].call($elem, value, data.formatOptions, formatterSettings);
+ })(settings);
}
return value;
}
@@ -401,14 +495,14 @@
part,
value = data;
- while ((part = paramParts.shift()) && typeof value !== "undefined") {
+ while ((part = paramParts.shift()) && typeof value !== "undefined" && value != null) {
value = value[part];
}
return value;
}
- function applyFormatters($elem, value, attr) {
+ function applyFormatters($elem, value, attr, settings) {
var formatterTarget = $elem.attr("data-format-target"),
formatter;
@@ -416,24 +510,31 @@
formatter = $elem.attr("data-format");
if (formatter && typeof formatters[formatter] === "function") {
var formatOptions = $elem.attr("data-format-options");
- return formatters[formatter].call($elem[0], value, formatOptions);
+ return (function (formatterSettings) {
+ return formatters[formatter].call($elem[0], value, formatOptions, $.extend({}, formatterSettings));
+ })(settings);
}
}
return value;
}
- addTemplateFormatter("nestedTemplateFormatter", function (value, options) {
+ addTemplateFormatter("nestedTemplateFormatter", function (value, options, internalSettings) {
if (!options) {
return;
}
-
+
if (typeof options === "string" && options[0] === "{") {
options = $.parseJSON(options);
}
var parentElement = options.parentElement || "div";
var template = options.template || options;
- return $("<" + parentElement + "/>").loadTemplate(template, value);
+
+ //If a parent is specified, return it; otherwise only return the generated children.
+ if (options.parentElement)
+ return $("<" + parentElement + "/>").loadTemplate(template, value, internalSettings);
+ else
+ return $("<" + parentElement + "/>").loadTemplate(template, value, internalSettings).children();
});
$.fn.loadTemplate = loadTemplate;
$.addTemplateFormatter = addTemplateFormatter;
diff --git a/dist/jquery.loadTemplate.min.js b/dist/jquery.loadTemplate.min.js
new file mode 100644
index 0000000..bf88099
--- /dev/null
+++ b/dist/jquery.loadTemplate.min.js
@@ -0,0 +1 @@
+!function(t){"use strict";function e(e,n,c){var s,f,p,d=this;return n=n||{},p=t.extend(!0,{async:!0,overwriteCache:!1,complete:null,success:null,error:function(){t(this).each(function(){t(this).html(p.errorMessage)})},errorMessage:"There was an error loading the template.",paged:!1,pageNo:1,elemPerPage:10,append:!1,prepend:!1,beforeInsert:null,afterInsert:null,bindingOptions:{ignoreUndefined:!1,ignoreNull:!1,ignoreEmptyString:!1}},c),"array"===t.type(n)?(T=!0,i.call(this,e,n,p)):(a(e)||(s=t(e),"string"==typeof e&&0===e.indexOf("#")&&(p.isFile=!1)),f=p.isFile||void 0===p.isFile&&(void 0===s||0===s.length),f&&!p.overwriteCache&&w[e]?o(e,d,n,p):f&&!p.overwriteCache&&w.hasOwnProperty(e)?r(e,d,n,p):f?l(e,d,n,p):u(s,d,n,p),this)}function n(e,n){n?P[e]=n:P=t.extend(P,e)}function a(t){return"string"==typeof t&&t.indexOf("/")>-1}function i(n,a,i){i=i||{};var r,o=this,c=a.length,s=i.prepend&&!i.append,l=0,u=0,f=!1,p=[];if(i.paged){var d=(i.pageNo-1)*i.elemPerPage;a=a.slice(d,d+i.elemPerPage),c=a.length}return i.append||i.prepend||o.html(""),r=t.extend({},i,{append:!i.prepend&&!0,complete:function(t){(++l===c||f)&&(f&&i&&"function"==typeof i.error&&i.error.call(o,p),i&&"function"==typeof i.complete&&i.complete())},success:function(){++u===c&&i&&"function"==typeof i.success&&i.success()},error:function(t){f=!0,p.push(t)}}),s&&a.reverse(),t(a).each(function(){if(e.call(o,n,this,r),f)return!1}),this}function r(t,e,n,a){k[t]?k[t].push({data:n,selection:e,settings:a}):k[t]=[{data:n,selection:e,settings:a}]}function o(t,e,n,a){var i=w[t].clone();f.call(e,i,n,a),"function"==typeof a.success&&a.success()}function c(){return(new Date).getTime()}function s(t){return-1!==t.indexOf("?")?t+"&_="+c():t+"?_="+c()}function l(e,n,a,i){w[e]=null;var r=e;i.overwriteCache&&(r=s(r)),t.ajax({url:r,async:i.async,success:function(r){d(t(r),e,n,a,i)},error:function(t){p(e,n,a,i,t)}})}function u(e,n,a,i){(e.is("script")||e.is("template"))&&(e=t.parseHTML(t.trim(e.html()))),f.call(n,e,a,i),"function"==typeof i.success&&i.success()}function f(e,n,a){h(e=t("").append(e),n,a),t(this).each(function(){var i=e.children().clone(!0);t("select",i).each(function(n,a){t(this).val(t("select",e).eq(n).val())}),a.beforeInsert&&a.beforeInsert(i,n),a.append?t(this).append(i):a.prepend?t(this).prepend(i):t(this).html("").append(i),a.afterInsert&&a.afterInsert(i,n)}),"function"==typeof a.complete&&a.complete.call(t(this),n)}function p(e,n,a,i,r){var o;for("function"==typeof i.error&&i.error.call(n,r),t(k[e]).each(function(t,e){"function"==typeof e.settings.error&&e.settings.error.call(e.selection,r)}),"function"==typeof i.complete&&i.complete.call(n);k[e]&&(o=k[e].shift());)"function"==typeof o.settings.complete&&o.settings.complete.call(o.selection);void 0!==k[e]&&k[e].length>0&&(k[e]=[])}function d(t,e,n,a,i){var r;for(w[e]=t.clone(),f.call(n,t,a,i),"function"==typeof i.success&&i.success.call(n);k[e]&&(r=k[e].shift());)f.call(r.selection,w[e].clone(),r.data,r.settings),"function"==typeof r.settings.success&&r.settings.success.call(r.selection)}function h(e,n,a){v("data-content",e,n=n||{},a,function(t,e){t.html(O(t,e,"content",a))}),v("data-content-append",e,n,a,function(t,e){t.append(O(t,e,"content",a))}),v("data-content-prepend",e,n,a,function(t,e){t.prepend(O(t,e,"content",a))}),v("data-content-text",e,n,a,function(t,e){t.text(O(t,e,"content",a))}),v("data-innerHTML",e,n,a,function(t,e){t.html(O(t,e,"content",a))}),v("data-src",e,n,a,function(t,e){t.attr("src",O(t,e,"src",a))},function(t){t.remove()}),v("data-href",e,n,a,function(t,e){t.attr("href",O(t,e,"href",a))},function(t){t.remove()}),v("data-alt",e,n,a,function(t,e){t.attr("alt",O(t,e,"alt",a))}),v("data-title",e,n,a,function(t,e){t.attr("title",O(t,e,"title",a))}),v("data-id",e,n,a,function(t,e){t.attr("id",O(t,e,"id",a))}),v("data-css",e,n,a,function(t,e){t.css(O(t,e,"css",a))}),v("data-class",e,n,a,function(t,e){t.addClass(O(t,e,"class",a))}),v("data-link",e,n,a,function(e,n){var i=t("");i.attr("href",O(e,n,"link",a)),i.html(e.html()),e.html(i)}),v("data-link-wrap",e,n,a,function(e,n){var i=t("");i.attr("href",O(e,n,"link-wrap",a)),e.wrap(i)}),v("data-options",e,n,a,function(e,n){t(n).each(function(){t("").attr("value",this).text(this).appendTo(e)})}),y(e,n,a),v("data-value",e,n,a,function(t,e){t.val(O(t,e,"value",a))})}function v(e,n,a,i,r,o){t("["+e+"]",n).each(function(){var n=t(this),c=n.attr(e),s=x(a,c);m(n,s,i)?(n.removeAttr(e),void 0!==s&&r?r(n,s):o&&o(n)):n.remove()})}function m(t,e,n){var a=g(t,n);return(!a.ignoreUndefined||void 0!==e)&&((!a.ignoreNull||null!==e)&&(!a.ignoreEmptyString||""!==e))}function g(e,n){var a={};return e instanceof jQuery&&e.attr("data-binding-options")?(a=t.parseJSON(e.attr("data-binding-options")),e.removeAttr("data-binding-options")):"object"==typeof e&&e.hasOwnProperty("bindingOptions")&&(a=e.bindingOptions),t.extend({},n.bindingOptions,a)}function y(e,n,a){t("[data-template-bind]",e).each(function(){var e=t(this),i=t.parseJSON(e.attr("data-template-bind"));e.removeAttr("data-template-bind"),t(i).each(function(){var i;if(i="object"==typeof this.value?x(n,this.value.data):x(n,this.value),this.attribute){if(!m(this,i,a))return void e.remove();switch(this.attribute){case"content":case"innerHTML":e.html(b(e,i,this));break;case"contentAppend":e.append(b(e,i,this));break;case"contentPrepend":e.prepend(b(e,i,this));break;case"contentText":e.text(b(e,i,this));break;case"options":var r=this;t(i).each(function(){t("").attr("value",this[r.value.value]).text(b(e,this[r.value.content],r)).attr("selected",void 0!=typeof this[r.value.selected]&&this[r.value.selected]).appendTo(e)});break;default:e.attr(this.attribute,b(e,i,this))}}})})}function b(t,e,n,a){return n.formatter&&P[n.formatter]?function(a){return P[n.formatter].call(t,e,n.formatOptions,a)}(a):e}function x(t,e){if("this"===e)return t;for(var n,a=e.split("."),i=t;(n=a.shift())&&void 0!==i&&null!=i;)i=i[n];return i}function O(e,n,a,i){var r,o=e.attr("data-format-target");if((o===a||!o&&"content"===a)&&(r=e.attr("data-format"))&&"function"==typeof P[r]){var c=e.attr("data-format-options");return function(a){return P[r].call(e[0],n,c,t.extend({},a))}(i)}return n}var T,w={},k={},P={};n("nestedTemplateFormatter",function(e,n,a){if(n){"string"==typeof n&&"{"===n[0]&&(n=t.parseJSON(n));var i=n.parentElement||"div",r=n.template||n;return n.parentElement?t("<"+i+"/>").loadTemplate(r,e,a):t("<"+i+"/>").loadTemplate(r,e,a).children()}}),t.fn.loadTemplate=e,t.addTemplateFormatter=n}(jQuery);
\ No newline at end of file
diff --git a/jquery-loadTemplate/jquery.loadTemplate-1.3.2.min.js b/jquery-loadTemplate/jquery.loadTemplate-1.3.2.min.js
deleted file mode 100644
index f3299a8..0000000
--- a/jquery-loadTemplate/jquery.loadTemplate-1.3.2.min.js
+++ /dev/null
@@ -1 +0,0 @@
-(function(a){var u={},t={},h={};function m(D,z,B){var y=this,x,C,A;z=z||{};C=a.extend({overwriteCache:false,complete:null,success:null,error:function(){a(this).each(function(){a(this).html(C.errorMessage)})},errorMessage:"There was an error loading the template.",paged:false,pageNo:1,elemPerPage:10,append:false,prepend:false,beforeInsert:null,afterInsert:null},B);if(a.type(z)==="array"){return r.call(this,D,z,C)}if(!g(D)){x=a(D);if(typeof D==="string"&&D.indexOf("#")===0){C.isFile=false}}A=C.isFile||(typeof C.isFile==="undefined"&&(typeof x==="undefined"||x.length===0));if(A&&!C.overwriteCache&&u[D]){p(D,y,z,C)}else{if(A&&!C.overwriteCache&&u.hasOwnProperty(D)){c(D,y,z,C)}else{if(A){l(D,y,z,C)}else{n(x,y,z,C)}}}return this}function b(y,x){if(x){h[y]=x}else{h=a.extend(h,y)}}function g(x){return typeof x==="string"&&x.indexOf("/")>-1}function r(G,y,D){D=D||{};var x=this,H=y.length,A=D.prepend&&!D.append,z=0,F=0,B=false,C;if(D.paged){var E=(D.pageNo-1)*D.elemPerPage;y=y.slice(E,E+D.elemPerPage);H=y.length}C=a.extend({},D,{complete:function(){if(A){x.prepend(this.html())}else{x.append(this.html())}z++;if(z===H){if(B&&D&&typeof D.error==="function"){D.error.call(x)}if(D&&typeof D.complete==="function"){D.complete()}}},success:function(){F++;if(F===H){if(D&&typeof D.success==="function"){D.success()}}},error:function(){B=true}});if(!D.append&&!D.prepend){x.html("")}if(A){y.reverse()}a(y).each(function(){var I=a("");m.call(I,G,this,C)});return this}function c(A,y,x,z){if(t[A]){t[A].push({data:x,selection:y,settings:z})}else{t[A]=[{data:x,selection:y,settings:z}]}}function p(B,z,y,A){var x=u[B].clone();o.call(z,x,y,A);if(typeof A.success==="function"){A.success()}}function v(){return new Date().getTime()}function w(x){if(x.indexOf("?")!==-1){return x+="&_="+v()}else{return x+="?_="+v()}}function l(B,z,y,A){var x=a("");u[B]=null;if(A.overwriteCache){B=w(B)}x.load(B,function(C,D){if(D==="error"){j(B,z,y,A)}else{k(x,B,z,y,A)}})}function n(x,A,z,B){var y=a("");if(x.is("script")){x=a.parseHTML(a.trim(x.html()))}y.html(x);o.call(A,y,z,B);if(typeof B.success==="function"){B.success()}}function o(z,x,y){f(z,x);a(this).each(function(){var A=a(z.html());if(y.beforeInsert){y.beforeInsert(A)}if(y.append){a(this).append(A)}else{if(y.prepend){a(this).prepend(A)}else{a(this).html(A)}}if(y.afterInsert){y.afterInsert(A)}});if(typeof y.complete==="function"){y.complete.call(a(this))}}function j(A,y,x,z){var B;if(typeof z.error==="function"){z.error.call(y)}a(t[A]).each(function(C,D){if(typeof D.settings.error==="function"){D.settings.error.call(D.selection)}});if(typeof z.complete==="function"){z.complete.call(y)}while(t[A]&&(B=t[A].shift())){if(typeof B.settings.complete==="function"){B.settings.complete.call(B.selection)}}if(typeof t[A]!=="undefined"&&t[A].length>0){t[A]=[]}}function k(x,B,z,y,A){var C;u[B]=x.clone();o.call(z,x,y,A);if(typeof A.success==="function"){A.success.call(z)}while(t[B]&&(C=t[B].shift())){o.call(C.selection,u[B].clone(),C.data,C.settings);if(typeof C.settings.success==="function"){C.settings.success.call(C.selection)}}}function f(y,x){x=x||{};s("data-content",y,x,function(z,A){z.html(e(z,A,"content"))});s("data-content-append",y,x,function(z,A){z.append(e(z,A,"content"))});s("data-content-prepend",y,x,function(z,A){z.prepend(e(z,A,"content"))});s("data-content-text",y,x,function(z,A){z.text(e(z,A,"content"))});s("data-src",y,x,function(z,A){z.attr("src",e(z,A,"src"))},function(z){z.remove()});s("data-alt",y,x,function(z,A){z.attr("alt",e(z,A,"alt"))});s("data-value",y,x,function(z,A){z.attr("value",e(z,A,"value"))});s("data-link",y,x,function(z,B){var A=a("");A.attr("href",e(z,B,"link"));A.html(z.html());z.html(A)});s("data-link-wrap",y,x,function(z,B){var A=a("");A.attr("href",e(z,B,"link-wrap"));z.wrap(A)});s("data-options",y,x,function(z,A){a(A).each(function(){var B=a("");B.attr("value",this).text(this).appendTo(z)})});q(y,x)}function s(x,B,y,z,A){a("["+x+"]",B).each(function(){var C=a(this),D=C.attr(x),E=i(y,D);C.removeAttr(x);if(typeof E!=="undefined"&&z){z(C,E)}else{if(A){A(C)}}});return}function q(y,x){a("[data-template-bind]",y).each(function(){var z=a(this),A=a.parseJSON(z.attr("data-template-bind"));z.removeAttr("data-template-bind");a(A).each(function(){var C;if(typeof(this.value)==="object"){C=i(x,this.value.data)}else{C=i(x,this.value)}if(typeof C!=="undefined"&&this.attribute){switch(this.attribute){case"content":z.html(d(z,C,this));break;case"contentAppend":z.append(d(z,C,this));break;case"contentPrepend":z.prepend(d(z,C,this));break;case"contentText":z.text(d(z,C,this));break;case"options":var B=this;a(C).each(function(){var D=a("");D.attr("value",this[B.value.value]).text(d(z,this[B.value.content],B)).attr("selected",typeof this[B.value.selected]==undefined?false:this[B.value.selected]).appendTo(z)});break;default:z.attr(this.attribute,d(z,C,this))}}})})}function d(x,z,y){if(y.formatter&&h[y.formatter]){return h[y.formatter].call(x,z,y.formatOptions)}return z}function i(x,y){if(y==="this"){return x}var z=y.split("."),A,B=x;while((A=z.shift())&&typeof B!=="undefined"){B=B[A]}return B}function e(x,C,y){var B=x.attr("data-format-target"),A;if(B===y||(!B&&y==="content")){A=x.attr("data-format");if(A&&typeof h[A]==="function"){var z=x.attr("data-format-options");return h[A].call(x[0],C,z)}}return C}b("nestedTemplateFormatter",function(A,x){if(!x){return}if(typeof x==="string"&&x[0]==="{"){x=a.parseJSON(x)}var y=x.parentElement||"div";var z=x.template||x;return a("<"+y+"/>").loadTemplate(z,A)});a.fn.loadTemplate=m;a.addTemplateFormatter=b})(jQuery);
\ No newline at end of file
diff --git a/loadTemplate.jquery.json b/loadTemplate.jquery.json
index c66835d..52192ad 100644
--- a/loadTemplate.jquery.json
+++ b/loadTemplate.jquery.json
@@ -6,7 +6,7 @@
"templates",
"templating"
],
- "version": "1.3.2",
+ "version": "1.5.10",
"author": {
"name": "Paul Burgess and other contributors",
"url": "https://github.com/codepb/jquery-template"
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..f8eee4f
--- /dev/null
+++ b/package.json
@@ -0,0 +1,22 @@
+{
+ "name": "jquery.loadtemplate",
+ "version": "1.5.10",
+ "main": "dist/jquery.loadTemplate.js",
+ "author": "Paul Burgess",
+ "description": "jQuery plugin for loading and using templates. The plugin is designed to be simple yet powerful, and supports loading templates from within the page, or using AJAX to load html files.",
+ "homepage": "http://codepb.github.io/jquery-template/",
+ "keywords": [
+ "templates",
+ "templating",
+ "jquery-plugin"
+ ],
+ "bugs": "https://github.com/codepb/jquery-template/issues",
+ "license": "MIT",
+ "repository" : {
+ "type" : "git",
+ "url" : "https://github.com/codepb/jquery-template"
+ },
+ "dependencies" : {
+ "jquery": ">=1.8"
+ }
+}
diff --git a/readme.md b/readme.md
index 7e86885..3b0970f 100644
--- a/readme.md
+++ b/readme.md
@@ -1,4 +1,5 @@
# jQuery.loadTemplate
+[](https://cdnjs.com/libraries/jquery.loadtemplate)
jQuery Template is a jQuery plugin that makes using templates easy and quick. The plugin supports loading HTML files as templates, or taking a jQuery object as the template (usually using script tags to hold the template).
@@ -58,9 +59,13 @@ Similarly the content of the template could be held in a separate html file with
The plugin has a number of data-... attributes that can be used to populate various attributes with the data. There is also the powerful data-template-bind attribute that accepts a JSON object, enabling binding to any attribute, or the content of the element.
+#### Arrays
+
+You can pass an array of objects instead of a single object and the template will be populated and added to the container for each item in the array. There are options built in that allow you to page the results from an array as well. See the options section below and the included examples.
+
### Data Formatters
-It is also possible to define data formatters. These are assigned through the `$.addTemplateFormatter` method. This function either accepts a map of functions and the keys that they will be referenced by, or a single function with a single key as two separate parameters. Each formatter takes two values, the value being assigned, and a template to use to define how this data is displayed. The data-format-template may be empty. Example usage of this is below:
+It is also possible to define data formatters. These are assigned through the `$.addTemplateFormatter` method. This function either accepts a map of functions and the keys that they will be referenced by, or a single function with a single key as two separate parameters. Each formatter takes two values, the value being assigned, and a template to use to define how this data is displayed. The data-format-options may be empty. Example usage of this is below:
$.addTemplateFormatter("UpperCaseFormatter",
function(value, template) {
@@ -95,11 +100,17 @@ Formatters must be added before they are used else a template will not be able t
### Bindings
There are a number of different bindings and ways to bind the data. The following attributes are available:
-- "data-content" - binds the value supplied to the content of the element (uses $(elem).html(value))
+- "data-innerHTML" (>= 1.4.5) - binds the value supplied to the content (innerHTML) of the element (uses $(elem).html(value))
+- "data-content" - alias for the newer "data-innerHTML"
+- "data-content-text" - binds the value supplied to the content of the element as text (uses $(elem).text(value))
- "data-content-append" - appends the value to the end of the element (uses $(elem).append(value))
- "data-content-prepend" - prepends the value to the beginning of the element (uses $(elem).prepend(value))
+- "data-id" - sets the id of the element to the value provided (uses $(elem).attr("id", value));
+- "data-href" - sets the href value of the element to the value provided (uses $(elem).attr("href", value));
- "data-alt" - sets the alt value of the element to the value provided (uses $(elem).attr("alt", value));
- "data-value" - sets the value attribute of the element to the value provided (uses $(elem).val(value))
+- "data-class" - sets the class attribute of the element to the value provided (uses $(elem).class(value))
+- "data-css" - sets the CSS attribute of the element to the value provided (uses $(elem).css(value))
- "data-link" - sets the innerHtml of the element to be a link to the value provided (wraps the content in an <a> tag).
- "data-link-wrap" - wraps the element in a link to the value provided. Same as "data-link", but the <a> tag wraps the element as well as the content.
- "data-options" - adds options to a select box. The value for this should reference an array of strings, each option will be output as a separate option. The value will be the same as the displayed text for each option. For a more powerful version of this look at the data-template-bind option.
@@ -122,9 +133,14 @@ An example of using the "data-template-bind" attribute would be the following:
### Options
-There are a number of options the plugin accepts. These are:
+There are a number of options the plugin accepts. These can be set by passing an object containing the settings you would like to set as the third parameter to .loadTemplate:
+
+ $(container).loadTemplate(template, data, { append: true, elemPerPage: 20 });
+
+The full list of options are:
- "overwriteCache" (default false) - Whether to ignore the cache and reload the template (if you've previously loaded the template, but it might have changed, you'll want to set this to true.
+- "async" (default true) - Whether to load templates asynchronously (if templates require an Ajax call)
- "complete" (default null) - Callback function to call on complete. Will always be called regardless of success or failure.
- "success" (default null) - Callback function to call on successful completion.
- "error" (default, outputting error message to template container) - Callback function to call on error.
@@ -137,7 +153,8 @@ There are a number of options the plugin accepts. These are:
- "prepend" (default false) - If set to true, the template will be prepended to the element rather than replacing the contents of the element. The append option takes priority over prepend, so if both options are set to true, the element is appended and not prepended.
- "beforeInsert" (default null) - Callback function to be called before inserting the template into the document. The format of the function is function($elem) where $elem is the jQuery object of the populated template about to be inserted into the document.
- "afterInsert" (default null) - As above, a callback function to be called after inserting the template into the document. The format is the same as above.
+- "bindingOptions" (default all flags false): add flags to ignore certain types of values. {"ignoreUndefined": false, "ignoreNull": false, "ignoreEmptyString": false}. The flags you set here, are overwritten on an element level by those specified in a template with a "data-binding-options" or a "data-template-bind" attribute. Examples can be found in the Examples/OptionalBinding folder.
## Future Plans
-I would like to develop the plugin further so it would be possible to watch the objects holding the data, so any changes to the data would be reflected in the UI. This would have to be simple, lightweight, and ideally would work just with natural JavaScript objects. I also welcome any ideas as to how the plugin could be improved.
\ No newline at end of file
+I would like to develop the plugin further so it would be possible to watch the objects holding the data, so any changes to the data would be reflected in the UI. This would have to be simple, lightweight, and ideally would work just with natural JavaScript objects. I also welcome any ideas as to how the plugin could be improved.
diff --git a/tests/files/bindingOptions.js b/tests/files/bindingOptions.js
new file mode 100644
index 0000000..5497175
--- /dev/null
+++ b/tests/files/bindingOptions.js
@@ -0,0 +1,79 @@
+(function () {
+
+ var data = [{
+ "title": "Super Mario World 2",
+ "subtitle": "Yoshi's Island"
+ },{
+ "title": "The Little Prince",
+ "subtitle": null
+ },{
+ "title": "The Da Vinci Code"
+ },{
+ "title": "Lord of the Flies",
+ "subtitle": ""
+ }];
+
+ function testLoadWithFunctionParameters() {
+ $("#bindingOptionsContainer").loadTemplate($("#templateWithoutBindingOptions"), data, {bindingOptions: {"ignoreUndefined": true, "ignoreNull": true, "ignoreEmptyString": true}});
+ }
+
+ function testLoadWithTemplateAttributes() {
+ $("#bindingOptionsContainer").loadTemplate($("#templateWithBindingOptions"), data);
+ }
+
+ function testLoadTemplateWithBindingOptionsInDataTemplateBindAttribute() {
+ $("#bindingOptionsContainer").loadTemplate($("#templateWithBindingOptionsAsDataBindTemplateAttribute"), data);
+ }
+
+ function test(assert, async) {
+ return [
+ {
+ name: "jQuery Loaded",
+ test: function () {
+ assert(jQuery);
+ }
+ },
+ {
+ name: "loadTemplate Loaded",
+ test: function () {
+ assert(typeof $.fn.loadTemplate === 'function');
+ }
+ },
+ {
+ name: "Load template with binding options as function parameters",
+ test: function () {
+ testLoadWithFunctionParameters();
+
+ var childs = $('#bindingOptionsContainer h4').length;
+ assert(childs === 1);
+ }
+ },
+ {
+ name: "Load template with binding options as template attributes",
+ setup: function () {
+ $('#bindingOptionsContainer').empty();
+ },
+ test: function () {
+ testLoadWithTemplateAttributes();
+
+ var childs = $('#bindingOptionsContainer h4').length;
+ assert(childs === 1);
+ }
+ },
+ {
+ name: "Load template with binding options in 'data-template-bind' attribute",
+ setup: function () {
+ $('#bindingOptionsContainer').empty();
+ },
+ test: function () {
+ testLoadTemplateWithBindingOptionsInDataTemplateBindAttribute();
+
+ var childs = $('#bindingOptionsContainer h4').length;
+ assert(childs === 1);
+ }
+ }];
+ }
+
+ addTests(test);
+
+})();
diff --git a/tests/files/callback.js b/tests/files/callback.js
index b9899d4..40abd43 100644
--- a/tests/files/callback.js
+++ b/tests/files/callback.js
@@ -49,12 +49,12 @@
afterInsert : function(elem){
sequence.push('after');
+ ++afterInsertCounter;
+
if ($('#render').children().length === afterInsertCounter) {
elemSequence.push(true);
}
-
- ++afterInsertCounter;
-
+
},
complete : function(){
sequence.push('complete');
diff --git a/tests/files/error.js b/tests/files/error.js
index 518c3aa..e33fcf4 100644
--- a/tests/files/error.js
+++ b/tests/files/error.js
@@ -1,97 +1,95 @@
-(function(){
+(function () {
var data = [
{
- "name" : "test1",
- "id" : 1
+ "name": "test1",
+ "id": 1
},
{
- "name" : "test2",
- "id" : 2
+ "name": "test2",
+ "id": 2
},
{
- "name" : "test3",
- "id" : 3
+ "name": "test3",
+ "id": 3
},
{
- "name" : "test4",
- "id" : 4
+ "name": "test4",
+ "id": 4
},
{
- "name" : "test5",
- "id" : 5
+ "name": "test5",
+ "id": 5
}
];
-
- function errorsHandle(assert,async){
+
+ function errorsHandle(assert, async) {
var successCounter = 0,
errorCounter = 0,
completeCounter = 0,
sequence = [];
-
+
return {
name: "Custom Error Callback",
- setup: function(){
+ setup: function () {
+
+ },
+ test: function () {
$("#render").loadTemplate('test.html', data, {
- complete : function(){
+ complete: function () {
sequence.push('complete');
++completeCounter;
+ //success callback will not be fired
+ assert("Success Counter 0 = " + successCounter, 0 === successCounter);
+
+ //error should be fired
+ assert("Error Counter 1 = " + errorCounter, 1 === errorCounter);
+
+ //complete should be called even with errors
+ assert("Complete Counter 1 = " + completeCounter, 1 === completeCounter);
+
+ //sequence by now should be
+ var expected = 'error,complete';
+ var got = sequence.toString();
+ assert("Sequence " + expected + " = " + got, expected == got);
},
- success : function(){
+ success: function () {
sequence.push('success');
++successCounter;
},
- error : function(){
+ error: function () {
sequence.push('error');
++errorCounter;
}
});
- },
- test: function () {
-
- //give it some time to check URL
- setTimeout(async(function () { // async testing
-
- //success callback will not be fired
- assert("Success Counter 0 = " + successCounter, 0 === successCounter);
-
- //error should be fired
- assert("Error Counter 1 = " + errorCounter, 1 === errorCounter);
-
- //complete should be called even with errors
- assert("Complete Counter 1 = " + completeCounter, 1 === completeCounter);
-
- //sequence by now should be
- var expected = 'error,complete';
- var got = sequence.toString();
- assert("Sequence " + expected + " = " + got, expected == got );
-
- }), 1000);
+
+
}
};
}
-
- function deafultError(assert,async){
+
+ function deafultError(assert, async) {
var successCounter = 0,
errorCounter = 0,
completeCounter = 0,
sequence = [];
-
+
return {
name: "Default Error Callback",
- setup: function(){
- $("#render").loadTemplate('doesnotexists/test.html', data);
+ setup: function () {
+
},
test: function () {
- //give it some time to check URL
- setTimeout(async(function () { //asnc testing
- var got = $('#render').text();
- var expected = "There was an error loading the template.";
- assert("Error Message " + expected + " = " + got, got == expected);
- }), 1000);
+ $("#render").loadTemplate('doesnotexists/test.html', data, {
+ complete: function () {
+ var got = $('#render').text();
+ var expected = "There was an error loading the template.";
+ assert("Error Message " + expected + " = " + got, got == expected);
+ }
+ });
}
};
}
-
- addTests(errorsHandle,deafultError);
-
+
+ addTests(errorsHandle, deafultError);
+
})();
diff --git a/tests/index.html b/tests/index.html
index 44f5d45..f0786d9 100644
--- a/tests/index.html
+++ b/tests/index.html
@@ -3,7 +3,7 @@
loadTemplate Test Suite
-
+
@@ -12,7 +12,8 @@
'files/general.js',
'files/formatters.js',
'files/callback.js',
- 'files/error.js'
+ 'files/error.js',
+ 'files/bindingOptions.js'
]);
@@ -112,6 +113,23 @@
+
+
+
+
+
+
+
+