Skip to content

Commit

Permalink
v1.0.11 release
Browse files Browse the repository at this point in the history
Feature improvement when using JsRender in a browser, without jQuery:
It is now possible to pass an ID selector for a script block
to $.templates("#myTmpl"), even when using JsRender without jQuery

See #363
  Provide support for passing an ID selector to $.templates() even
  when using JsRender without jQuery

Sync with other changes in v1.0.11 for JsViews
  • Loading branch information
BorisMoore committed Jan 28, 2021
1 parent 645902a commit 3c4b7b1
Show file tree
Hide file tree
Showing 18 changed files with 158 additions and 61 deletions.
7 changes: 4 additions & 3 deletions README.md
Expand Up @@ -40,7 +40,7 @@ When jQuery is present, JsRender loads as a jQuery plugin and adds `$.views`, `$

#### Using JsRender without jQuery

When jQuery is not present, JsRender provides its own `jsrender` namespace object, exposed as `window.jsrender`
When jQuery is not present, JsRender provides its own global namespace object: `jsrender` (or `window.jsrender`)

The `jsrender` namespace provides the same methods/APIs as with jQuery, so if jQuery is not present you can still use all the API examples, by simply writing:

Expand All @@ -49,6 +49,7 @@ var $ = window.jsrender;

// Now use code as in samples/examples, with $.views... $.templates... $.render...
```
(*Note:* If jQuery is not loaded, then [passing a jQuery selector](http://www.jsviews.com/#compiletmpl@fromscriptblock) to `$.templates()` will only work for the *ID selector*)

*Example HTML page:* [JsRender without jQuery](http://www.jsviews.com/#download/pages-jsr)

Expand Down Expand Up @@ -83,10 +84,10 @@ Name: {{:name}}
then, somewhere in your script:

```js
var tmpl = $.templates("#myTemplate");
var tmpl = $.templates("#myTemplate"); // Pass in a jQuery selector for the script block
```

On Node.js, from an .html file containing the template markup:
On Node.js, [from an .html file](https://www.jsviews.com/#jsr-node-quickstart@htmlfiles) containing the template markup:

```js
var $ = require('jsrender'); // returns the jsrender namespace object
Expand Down
6 changes: 3 additions & 3 deletions jsrender-node.js
@@ -1,4 +1,4 @@
/*! JsRender v1.0.10: http://jsviews.com/#jsrender */
/*! JsRender v1.0.11: http://jsviews.com/#jsrender */
/*! **VERSION FOR NODE.JS** (For WEB see http://jsviews.com/download/jsrender.js) */
/*
* Best-of-breed templating in browser or on Node.js.
Expand All @@ -20,7 +20,7 @@ if (typeof exports !== 'object' ) {
//========================== Top-level vars ==========================

// global var is the this object, which is window when running in the usual browser environment
var versionNumber = "v1.0.10",
var versionNumber = "v1.0.11",
$, jsvStoreName, rTag, rTmplString, topView, $views,
_ocp = "_ocp", // Observable contextual parameter

Expand Down Expand Up @@ -726,7 +726,7 @@ function renderTag(tagName, parentView, tmpl, tagCtxs, isUpdate, onError) {
tag.linkCtx = linkCtx;
if (tag._.bnd = boundTag || linkCtx.fn) {
// Bound if {^{tag...}} or data-link="{tag...}"
tag._.ths = tagCtx.params.props.this; // Tag has a this=expr binding, to get javascript reference to tag instance
tag._.ths = tagCtx.params.props["this"]; // Tag has a this=expr binding, to get javascript reference to tag instance
tag._.lt = tagCtxs.lt; // If a late path @some.path has not returned @some object, mark tag as late
tag._.arrVws = {};
} else if (tag.dataBoundOnly) {
Expand Down
8 changes: 5 additions & 3 deletions jsrender.js
@@ -1,4 +1,4 @@
/*! JsRender v1.0.10: http://jsviews.com/#jsrender */
/*! JsRender v1.0.11: http://jsviews.com/#jsrender */
/*! **VERSION FOR WEB** (For NODE.JS see http://jsviews.com/download/jsrender-node.js) */
/*
* Best-of-breed templating in browser or on Node.js.
Expand Down Expand Up @@ -44,7 +44,7 @@ var setGlobals = $ === false; // Only set globals if script block in browser (no

$ = $ && $.fn ? $ : global.jQuery; // $ is jQuery passed in by CommonJS loader (Browserify), or global jQuery.

var versionNumber = "v1.0.10",
var versionNumber = "v1.0.11",
jsvStoreName, rTag, rTmplString, topView, $views, $expando,
_ocp = "_ocp", // Observable contextual parameter

Expand Down Expand Up @@ -753,7 +753,7 @@ function renderTag(tagName, parentView, tmpl, tagCtxs, isUpdate, onError) {
tag.linkCtx = linkCtx;
if (tag._.bnd = boundTag || linkCtx.fn) {
// Bound if {^{tag...}} or data-link="{tag...}"
tag._.ths = tagCtx.params.props.this; // Tag has a this=expr binding, to get javascript reference to tag instance
tag._.ths = tagCtx.params.props["this"]; // Tag has a this=expr binding, to get javascript reference to tag instance
tag._.lt = tagCtxs.lt; // If a late path @some.path has not returned @some object, mark tag as late
tag._.arrVws = {};
} else if (tag.dataBoundOnly) {
Expand Down Expand Up @@ -1115,6 +1115,8 @@ function compileTmpl(name, tmpl, parentTmpl, options) {
// Look for server-generated script block with id "./some/file.html"
elem = document.getElementById(value);
}
} else if (value.charAt(0) === "#") {
elem = document.getElementById(value.slice(1));
} else if ($.fn && !$sub.rTmpl.test(value)) {
try {
elem = $(value, document)[0]; // if jQuery is loaded, test for selector returning elements, and get first element
Expand Down
4 changes: 2 additions & 2 deletions jsrender.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion jsrender.min.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
@@ -1,6 +1,6 @@
{
"name": "jsrender",
"version": "v1.0.10",
"version": "v1.0.11",
"description": "Best-of-breed templating in browser or on Node.js (with Express 4, Hapi and Browserify integration)",
"main": "./jsrender-node.js",
"browser": "./jsrender.js",
Expand Down
12 changes: 7 additions & 5 deletions test/browserify/bundles/1-bundle.js

Large diffs are not rendered by default.

12 changes: 7 additions & 5 deletions test/browserify/bundles/12-nested-bundle.js

Large diffs are not rendered by default.

12 changes: 7 additions & 5 deletions test/browserify/bundles/2-bundle.js

Large diffs are not rendered by default.

12 changes: 7 additions & 5 deletions test/browserify/bundles/3-bundle.js

Large diffs are not rendered by default.

10 changes: 6 additions & 4 deletions test/browserify/bundles/htm-jsrender-tmpl-bundle.js
@@ -1,12 +1,12 @@
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
/*! JsRender v1.0.10: http://jsviews.com/#jsrender */
/*! JsRender v1.0.11: http://jsviews.com/#jsrender */
/*! **VERSION FOR WEB** (For NODE.JS see http://jsviews.com/download/jsrender-node.js) */
/*
* Best-of-breed templating in browser or on Node.js.
* Does not require jQuery, or HTML DOM
* Integrates with JsViews (http://jsviews.com/#jsviews)
*
* Copyright 2020, Boris Moore
* Copyright 2021, Boris Moore
* Released under the MIT License.
*/

Expand Down Expand Up @@ -45,7 +45,7 @@ var setGlobals = $ === false; // Only set globals if script block in browser (no

$ = $ && $.fn ? $ : global.jQuery; // $ is jQuery passed in by CommonJS loader (Browserify), or global jQuery.

var versionNumber = "v1.0.10",
var versionNumber = "v1.0.11",
jsvStoreName, rTag, rTmplString, topView, $views, $expando,
_ocp = "_ocp", // Observable contextual parameter

Expand Down Expand Up @@ -754,7 +754,7 @@ function renderTag(tagName, parentView, tmpl, tagCtxs, isUpdate, onError) {
tag.linkCtx = linkCtx;
if (tag._.bnd = boundTag || linkCtx.fn) {
// Bound if {^{tag...}} or data-link="{tag...}"
tag._.ths = tagCtx.params.props.this; // Tag has a this=expr binding, to get javascript reference to tag instance
tag._.ths = tagCtx.params.props["this"]; // Tag has a this=expr binding, to get javascript reference to tag instance
tag._.lt = tagCtxs.lt; // If a late path @some.path has not returned @some object, mark tag as late
tag._.arrVws = {};
} else if (tag.dataBoundOnly) {
Expand Down Expand Up @@ -1116,6 +1116,8 @@ function compileTmpl(name, tmpl, parentTmpl, options) {
// Look for server-generated script block with id "./some/file.html"
elem = document.getElementById(value);
}
} else if (value.charAt(0) === "#") {
elem = document.getElementById(value.slice(1));
} else if ($.fn && !$sub.rTmpl.test(value)) {
try {
elem = $(value, document)[0]; // if jQuery is loaded, test for selector returning elements, and get first element
Expand Down
10 changes: 6 additions & 4 deletions test/browserify/bundles/html-jsr-tmpl-bundle.js
@@ -1,12 +1,12 @@
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
/*! JsRender v1.0.10: http://jsviews.com/#jsrender */
/*! JsRender v1.0.11: http://jsviews.com/#jsrender */
/*! **VERSION FOR WEB** (For NODE.JS see http://jsviews.com/download/jsrender-node.js) */
/*
* Best-of-breed templating in browser or on Node.js.
* Does not require jQuery, or HTML DOM
* Integrates with JsViews (http://jsviews.com/#jsviews)
*
* Copyright 2020, Boris Moore
* Copyright 2021, Boris Moore
* Released under the MIT License.
*/

Expand Down Expand Up @@ -45,7 +45,7 @@ var setGlobals = $ === false; // Only set globals if script block in browser (no

$ = $ && $.fn ? $ : global.jQuery; // $ is jQuery passed in by CommonJS loader (Browserify), or global jQuery.

var versionNumber = "v1.0.10",
var versionNumber = "v1.0.11",
jsvStoreName, rTag, rTmplString, topView, $views, $expando,
_ocp = "_ocp", // Observable contextual parameter

Expand Down Expand Up @@ -754,7 +754,7 @@ function renderTag(tagName, parentView, tmpl, tagCtxs, isUpdate, onError) {
tag.linkCtx = linkCtx;
if (tag._.bnd = boundTag || linkCtx.fn) {
// Bound if {^{tag...}} or data-link="{tag...}"
tag._.ths = tagCtx.params.props.this; // Tag has a this=expr binding, to get javascript reference to tag instance
tag._.ths = tagCtx.params.props["this"]; // Tag has a this=expr binding, to get javascript reference to tag instance
tag._.lt = tagCtxs.lt; // If a late path @some.path has not returned @some object, mark tag as late
tag._.arrVws = {};
} else if (tag.dataBoundOnly) {
Expand Down Expand Up @@ -1116,6 +1116,8 @@ function compileTmpl(name, tmpl, parentTmpl, options) {
// Look for server-generated script block with id "./some/file.html"
elem = document.getElementById(value);
}
} else if (value.charAt(0) === "#") {
elem = document.getElementById(value.slice(1));
} else if ($.fn && !$sub.rTmpl.test(value)) {
try {
elem = $(value, document)[0]; // if jQuery is loaded, test for selector returning elements, and get first element
Expand Down
2 changes: 1 addition & 1 deletion test/unit-tests-jsrender-no-jquery.html
Expand Up @@ -10,7 +10,7 @@

<script src="unit-tests/tests-jsrender-no-jquery.js"></script>

<script id="myTmpl" type="text/x-jsrender">A_{{:name}}_B</script>
<script id="myTmpl" class="myTmpl" type="text/x-jsrender">A_{{:name}}_B</script>
<script id="./test/templates/file/path.html" type="text/x-jsrender">ServerRenderedTemplate_{{:name}}_B</script>
</head>
<body>
Expand Down
2 changes: 1 addition & 1 deletion test/unit-tests-jsrender-with-jquery.html
Expand Up @@ -10,7 +10,7 @@

<script src="unit-tests/tests-jsrender-with-jquery.js"></script>

<script id="myTmpl" type="text/x-jsrender">A_{{:name}}_B</script>
<script id="myTmpl" class="myTmpl" type="text/x-jsrender">A_{{:name}}_B</script>
<script id="my_tmpl" type="text/x-jsrender">A_{{:name}}_B</script>
<script id="my_tmpl2" type="text/x-jsrender">' " \ \' \"</script>
<script id="./test/templates/file/path.html" type="text/x-jsrender">ServerRenderedTemplate_{{:name}}_B</script>
Expand Down
21 changes: 12 additions & 9 deletions test/unit-tests/tests-jsrender-amd-scriptloader.js
Expand Up @@ -13,8 +13,9 @@ if (!window.attachEvent || window.addEventListener) { // Running RequireJS in qu
QUnit.module("AMD Script Loader");

QUnit.test("Loading JsRender, without jQuery, using RequireJS", function(assert) {
var done = assert.async(),
jq = window.jQuery;
var done;
if (assert.async) { done = assert.async() } else { stop() }
var jq = window.jQuery;
undefine();

require(["//www.jsviews.com/download/jsrender.js"], function($) { // Or point to correct local path for jsrender.js on your system
Expand All @@ -24,13 +25,14 @@ QUnit.test("Loading JsRender, without jQuery, using RequireJS", function(assert)

var result = $.templates("Name: {{:name}}").render({name: "Jo"}) + " " + (!!$.jsrender);
assert.equal(result, "Name: Jo true", "JsRender Loaded");
done();
if (assert.async) { done() } else { start() }
});
});

QUnit.test("Loading JsRender and jQuery, without forcing load order, using RequireJS", function(assert) {
var done = assert.async(),
jq = window.jQuery;
var done;
if (assert.async) { done = assert.async() } else { stop() }
var jq = window.jQuery;
undefine();

// Note JsRender does not require jQuery - so its AMD definition does not specify jQuery dependency.
Expand All @@ -42,14 +44,15 @@ QUnit.test("Loading JsRender and jQuery, without forcing load order, using Requi

var result = $.templates("Name: {{:name}}").render({name: "Jo"}) + " " + ($ === $jq || !!$.jsrender);
assert.equal(result, "Name: Jo true", "JsRender Loaded");
done();
if (assert.async) { done() } else { start() }
});
});
});

QUnit.test("Loading JsRender with jQuery, and force jQuery to load before JsRender, using RequireJS", function(assert) {
var done = assert.async(),
jq = window.jQuery;
var done;
if (assert.async) { done = assert.async() } else { stop() }
var jq = window.jQuery;
undefine();

// Note JsRender does not require jQuery - so its AMD definition does not specify jQuery dependency.
Expand All @@ -63,7 +66,7 @@ QUnit.test("Loading JsRender with jQuery, and force jQuery to load before JsRend

var result = $.templates("Name: {{:name}}").render({name: "Jo"}) + " " + (jq !== $ && $ === window.jQuery && $ === $jq);
assert.equal(result, "Name: Jo true", "JsRender LoadedX");
done();
if (assert.async) { done() } else { start() }
});
});
});
Expand Down
57 changes: 56 additions & 1 deletion test/unit-tests/tests-jsrender-no-jquery.js
Expand Up @@ -1261,6 +1261,7 @@ var teams = [

QUnit.module("api no jQuery");
QUnit.test("templates", function(assert) {

// ................................ Arrange ..................................
$.templates("./test/templates/file/path.html", null); // In case template has been stored in a previous test

Expand Down Expand Up @@ -1302,7 +1303,61 @@ QUnit.test("templates", function(assert) {
document.getElementById("./test/templates/file/path.html").removeAttribute("data-jsv-tmpl");
}

// =============================== Arrange ===============================
if (isBrowser) {
var tmplElem = document.getElementById("myTmpl");

// ................................ Act ..................................
tmpl0 = $.templates({markup: "#myTmpl"}); // Compile template declared in script block, but do not cache

// ............................... Assert .................................
assert.equal(tmpl0.render({name: "Jo0"}), "A_Jo0_B",
"Compile template declared in script block, without caching");

// ................................ Act ..................................
tmpl1 = $.templates("#myTmpl"); // Compile and cache, using "#myTmpl" as key);

// ............................... Assert .................................
assert.equal(tmpl1 !== tmpl0 && tmpl1.render({name: "Jo1"}), "A_Jo1_B",
"Compile template declared in script block, and cache on file path");

// ................................ Act ..................................
tmpl2 = $.templates("#myTmpl"); // Use cached template, accessed by $.templates["#myTmpl"]

// ............................... Assert .................................
assert.equal(tmpl2 === tmpl1 && tmpl1.render({name: "Jo2"}), "A_Jo2_B",
"Re-use cached template declared in script block");

// ................................ Act ..................................
var tmpl2b = $.templates(".myTmpl"); // Try to access script element by class selector - but fail because jQuery not loaded, so only "#xxx" selector is supported

// ............................... Assert .................................
if ($.fn || window._$ || tmpl2b === tmpl2) {
assert.equal(tmpl2b === tmpl2 && tmpl2b.render({name: "Jo2"}), "A_Jo2_B",
"Try to access script block using class selector - but not supported, by design, when jQuery not loaded");
} else {
assert.equal(tmpl2b !== tmpl2 && tmpl2b.render({name: "Jo2"}), ".myTmpl",
"Can access script block using class selector - when jQuery loaded");
}

// ................................ Act ..................................
tmpl2 = $.templates("#myAbsentTmpl");

// ............................... Assert .................................
assert.equal(tmpl2.render({name: "Jo2"}), "#myAbsentTmpl",
"Access missing script block template - renders as string");

// ................................ Act ..................................
tmpl3 = $.templates({markup: "#myTmpl"}); // Re-compile template but do not cache. Leave cached template.

// ............................... Assert .................................
assert.equal(tmpl3 !== tmpl0 && tmpl3 !== tmpl1 && tmpl3.render({name: "Jo3"}), "A_Jo3_B",
"Recompile template declared in script block, without caching");

// ................................ Reset ................................
tmplElem.removeAttribute("data-jsv-tmpl");
}

// =============================== Arrange ===============================
tmplString = "A_{{:name}}_B";

var tmpl = $.templates(tmplString);
Expand Down

0 comments on commit 3c4b7b1

Please sign in to comment.