Skip to content

Commit 7ba97ba

Browse files
committedJul 13, 2016
Commit 79 (v0.9.79 - Beta)
Improvements: - Several improvments to event binding using {^{on ...}} or data-link'"{on ...}" Unit tests - Several additional unit tests Documentation: - New documentation topics: - Event binding (www.jsviews.com/#link-events) - The {^{on}} tag (www.jsviews.com/#jsvontag)
1 parent 9da79b9 commit 7ba97ba

27 files changed

+954
-423
lines changed
 

‎jquery.observable.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/*! JsObservable v0.9.78 (Beta): http://jsviews.com/#jsobservable */
1+
/*! JsObservable v0.9.79 (Beta): http://jsviews.com/#jsobservable */
22
/*
33
* Subcomponent of JsViews
44
* Data change events for data-linking

‎jquery.observable.min.js

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎jquery.observable.min.js.map

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎jquery.views.js

+48-32
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/*! jquery.views.js v0.9.78 (Beta): http://jsviews.com/ */
1+
/*! jquery.views.js v0.9.79 (Beta): http://jsviews.com/ */
22
/*
33
* Interactive data-driven views using JsRender templates.
44
* Subcomponent of JsViews
@@ -44,7 +44,7 @@ var setGlobals = $ === false; // Only set globals if script block in browser (no
4444
jsr = jsr || setGlobals && global.jsrender;
4545
$ = $ || global.jQuery;
4646

47-
var versionNumber = "v0.9.78",
47+
var versionNumber = "v0.9.79",
4848
requiresStr = "JsViews requires ";
4949

5050
if (!$ || !$.fn) {
@@ -1591,6 +1591,7 @@ function addDataBinding(linkMarkup, node, currentView, boundTagId, isLink, data,
15911591
tag = tag.linkCtx ? tag.linkCtx.tag : tag;
15921592

15931593
linkCtx = tag.linkCtx || {
1594+
type: "inline",
15941595
data: currentView.data, // source
15951596
elem: tag._elCnt ? tag.parentElem : node, // target
15961597
view: currentView,
@@ -1643,6 +1644,7 @@ function addDataBinding(linkMarkup, node, currentView, boundTagId, isLink, data,
16431644
params = tokens[9];
16441645

16451646
linkCtx = {
1647+
type: isLink ? "top" : "link",
16461648
data: data, // source
16471649
elem: node, // target
16481650
view: currentView,
@@ -1798,12 +1800,7 @@ function callAfterLink(tag, eventArgs) {
17981800
tagCtx = tag.tagCtx,
17991801
view = tagCtx.view,
18001802
props = tagCtx.props,
1801-
linkCtx = tag.linkCtx = tag.linkCtx || {
1802-
tag: tag,
1803-
data: view.data,
1804-
view: view,
1805-
ctx: view.ctx
1806-
};
1803+
linkCtx = tag.linkCtx;
18071804

18081805
if (tag.onAfterLink) {
18091806
tag.onAfterLink(tagCtx, linkCtx, eventArgs);
@@ -2580,7 +2577,7 @@ $converters.merge = function(val) {
25802577
$tags("on", {
25812578
attr: NONE,
25822579
init: function(tagCtx) {
2583-
var props, elemProp, classProp, content,
2580+
var content,
25842581
tag = this,
25852582
i = 0,
25862583
args = tagCtx.args, // [events,] [selector,] handler
@@ -2589,22 +2586,21 @@ $tags("on", {
25892586
for (; i<l && !$isFunction(args[i]); i++); // Handler is first arg of type function
25902587
tag._hi = l>i && i+1; // handler index
25912588
if (tag._.inline) {
2589+
if (!$sub.rTmpl.exec(content = tagCtx.tmpl.markup)) {
2590+
// Inline {^{on}} tag with no content (or external template content) or with content containing
2591+
// no HTML or JsRender tags: We will wrap the (text) content, or the operation name in a <button> element
2592+
// (Otherwise we will attach the handler to the element content after data-linking)
2593+
tag.template = "<button>" + ($.trim(content) || tagCtx.params.args[i] || "noop") + "</button>";
2594+
}
25922595
tag.attr = HTML;
2593-
content = tagCtx.content;
2594-
content = content && content.markup;
2595-
props = tagCtx.props;
2596-
elemProp = props.elem || "button";
2597-
classProp = props["class"];
2598-
tag.template = rFirstElem.exec(content) && content || "<" + elemProp + (classProp ? ' class="' + classProp + '">' : ">")
2599-
+ ($.trim(content) || props.label || tagCtx.params.args[i] || "noop") + "</" + elemProp + ">";
26002596
}
26012597
},
26022598
render: function() {
26032599
var tagCtx = this.tagCtx;
26042600
return tagCtx.render(tagCtx.view, true); // no arg, so renders against parentView.data
26052601
},
26062602
onAfterLink: function(tagCtx, linkCtx) {
2607-
var handler, params,
2603+
var handler, params, find, activeElem,
26082604
tag = this,
26092605
i = tag._hi,
26102606
args = tagCtx.args, // [events,] [selector,] handler
@@ -2618,10 +2614,13 @@ $tags("on", {
26182614
handler = args[i-1];
26192615
params = args.slice(i); // Subsequent args are params
26202616
args = args.slice(0, i-1); // Preceding args (if any) are events and selector
2621-
tag._sel = args[1];
2622-
tag.activeElem = tag.activeElem || (tag._.inline
2623-
? (tag._elCnt && error('Use data-link="{on...}"'), tag._sel = undefined, tag.contents(true, args[1] || "*"))
2624-
: $(linkCtx.elem));
2617+
tag._sel = args[1]; // Selector for descendant elements - for delegated events on those elements, delegating to the activeElem
2618+
2619+
activeElem = tag.activeElem = tag.activeElem || $(tag._.inline
2620+
? (tag._sel = args[1] || "*", tag.parentElem)
2621+
// If inline, attach to child elements of tag parent element (filtered by selector argument if provided.
2622+
// (In handler we'll filter out events from sibling elements preceding or following tag.)
2623+
: linkCtx.elem);
26252624

26262625
if (!contextOb) {
26272626
// Get the path for the preceding object (context object) of handler (which is the last arg), compile function
@@ -2634,19 +2633,33 @@ $tags("on", {
26342633
tag.onDispose();
26352634
}
26362635

2637-
tag.activeElem.on(
2636+
activeElem.on(
26382637
tag._evs = args[0] || "click", // events defaults to "click"
26392638
tag._sel,
26402639
data == undefined ? null : data,
2641-
tag._hlr = function(ev) {
2642-
return handler.apply(contextOb || linkCtx.data, [].concat(
2643-
params, // e.g. par1, par2
2644-
ev,
2645-
{change: ev.type, view: view, linkCtx: linkCtx},
2646-
params.slice.call(arguments, 1) // If triggering event (e.g. jsv-domchange) has additional arguments after ev, pass them too
2647-
));
2648-
// for {on 'click' handler par1 par2} use handler(par1, par2, ev, domchangeEventArgs)
2649-
// for {on 'jsv-domchange' handler par1 par2} use handler(par1, par2, ev, domchangeEventArgs, tagCtx, linkCtx, observableEventArgs)
2640+
tag._hlr = function hndlr(ev) {
2641+
var nodes, length,
2642+
found = !tag._.inline;
2643+
2644+
if (!found) { // If inline, filter out events from sibling elements preceding or following tag.
2645+
nodes = tag.contents("*");
2646+
l = nodes.length;
2647+
while (!found && l--) {
2648+
if (nodes[l].contains(ev.target)) {
2649+
found = true;
2650+
}
2651+
}
2652+
}
2653+
if (found) { // target elem is indeed within the tag, so call the {on} handler
2654+
return handler.apply(contextOb || linkCtx.data, [].concat(
2655+
params, // e.g. par1, par2
2656+
ev,
2657+
{change: ev.type, view: view, linkCtx: linkCtx},
2658+
params.slice.call(arguments, 1) // If triggering event (e.g. jsv-domchange) has additional arguments after ev, pass them too
2659+
));
2660+
// for {on 'click' handler par1 par2} use handler(par1, par2, ev, domchangeEventArgs)
2661+
// for {on 'jsv-domchange' handler par1 par2} use handler(par1, par2, ev, domchangeEventArgs, tagCtx, linkCtx, observableEventArgs)
2662+
}
26502663
}
26512664
);
26522665
}
@@ -2655,7 +2668,10 @@ $tags("on", {
26552668
return false;
26562669
},
26572670
onDispose: function() {
2658-
this.activeElem.off(this._evs, this._sel, this._hlr);
2671+
var self = this;
2672+
if (self.activeElem) {
2673+
self.activeElem.off(self._evs, self._sel, self._hlr);
2674+
}
26592675
},
26602676
flow: true,
26612677
dataBoundOnly: true

‎jquery.views.min.js

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎jquery.views.min.js.map

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎jsrender.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/*! JsRender v0.9.78 (Beta): http://jsviews.com/#jsrender */
1+
/*! JsRender v0.9.79 (Beta): http://jsviews.com/#jsrender */
22
/*! **VERSION FOR WEB** (For NODE.JS see http://jsviews.com/download/jsrender-node.js) */
33
/*
44
* Best-of-breed templating in browser or on Node.js.
@@ -44,7 +44,7 @@ var setGlobals = $ === false; // Only set globals if script block in browser (no
4444

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

47-
var versionNumber = "v0.9.78",
47+
var versionNumber = "v0.9.79",
4848
jsvStoreName, rTag, rTmplString, topView, $views, $expando,
4949

5050
//TODO tmplFnsCache = {},
@@ -258,7 +258,7 @@ function $viewsDelimiters(openChars, closeChars, link) {
258258
// Default: bind tagName cvt cln html code params slash bind2 closeBlk comment
259259
// /(?:{(\^)?{(?:(\w+(?=[\/\s}]))|(\w+)?(:)|(>)|(\*))\s*((?:[^}]|}(?!}))*?)(\/)?|{(\^)?{(?:(?:\/(\w+))\s*|!--[\s\S]*?--))}}
260260

261-
rTmplString = new RegExp("<.*>|([^\\\\]|^)[{}]|" + openChars + ".*" + closeChars);
261+
$sub.rTmpl = rTmplString = new RegExp("<.*>|([^\\\\]|^)[{}]|" + openChars + ".*" + closeChars);
262262
// rTmplString looks for html tags or { or } char not preceded by \\, or JsRender tags {{xxx}}. Each of these strings are considered
263263
// NOT to be jQuery selectors
264264
return $viewsSettings;

‎jsrender.min.js

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎jsrender.min.js.map

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)