Skip to content

Commit 30ccd6d

Browse files
committed
Rewrote codebase in ES2015, divided into smaller files, use latest Meteor templating API
1 parent be80cb9 commit 30ccd6d

23 files changed

+506
-487
lines changed

.jshintrc

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"curly": false,
3+
"esnext": true,
4+
"globals": {
5+
"Hooks": true
6+
},
7+
"predef": [
8+
"Blaze",
9+
"EJSON",
10+
"Meteor",
11+
"Package",
12+
"Template",
13+
"Tinytest",
14+
"Tracker",
15+
"_",
16+
"$"
17+
]
18+
}

.versions

+51-35
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,51 @@
1-
2-
3-
4-
5-
6-
7-
8-
9-
10-
11-
12-
13-
14-
15-
16-
17-
18-
19-
local-test:aldeed:[email protected]
20-
21-
22-
23-
24-
25-
26-
27-
28-
29-
30-
31-
32-
33-
34-
35-
1+
2+
3+
4+
5+
6+
7+
8+
9+
10+
11+
12+
13+
14+
15+
16+
17+
18+
19+
20+
21+
22+
23+
24+
25+
26+
27+
local-test:aldeed:[email protected]
28+
29+
30+
31+
32+
33+
34+
35+
36+
37+
38+
39+
40+
41+
42+
43+
44+
45+
46+
47+
48+
49+
50+
51+

LICENSE

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
The MIT License (MIT)
22

3-
Copyright (c) 2014 Eric Dobbertin
3+
Copyright (c) 2014-2015 Eric Dobbertin
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy of
66
this software and associated documentation files (the "Software"), to deal in

README.md

+43-9
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,46 @@ A smart package for Meteor that allows you to:
1616
* use `template.get(fieldName)` to access the first field named `fieldName` in the current or ancestor template instances.
1717
* pass a function to `Template.parentData(fun)` to get the first data context which passes the test.
1818

19-
## Prerequisites
20-
21-
Requires Meteor 1.0+
19+
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
20+
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
21+
**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
22+
23+
- [Installation](#installation)
24+
- [Compatibility](#compatibility)
25+
- [Template.forEach(callback)](#templateforeachcallback)
26+
- [Template.forEachCurrentlyRenderedInstance(callback)](#templateforeachcurrentlyrenderedinstancecallback)
27+
- [Template.onCreated / Template.onRendered / Template.onDestroyed](#templateoncreated--templateonrendered--templateondestroyed)
28+
- [hooks(options)](#hooksoptions)
29+
- [replaces(templateName)](#replacestemplatename)
30+
- [inheritsHelpersFrom(templateName), inheritsEventsFrom(templateName), and inheritsHooksFrom(templateName)](#inheritshelpersfromtemplatename-inheritseventsfromtemplatename-and-inheritshooksfromtemplatename)
31+
- [clearEventMaps()](#cleareventmaps)
32+
- [copyAs(newTemplateName)](#copyasnewtemplatename)
33+
- [template.parent(numLevels, includeBlockHelpers)](#templateparentnumlevels-includeblockhelpers)
34+
- [template.get(fieldName)](#templategetfieldname)
35+
- [Template.parentData(fun)](#templateparentdatafun)
36+
- [Contributors](#contributors)
37+
38+
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
2239

2340
## Installation
2441

2542
```bash
2643
$ meteor add aldeed:template-extension
2744
```
2845

46+
## Compatibility
47+
48+
- Use a 3.x.x release with Meteor 1.0.x or Meteor 1.1.x
49+
- Use a 4.x.x release with Meteor 1.2+
50+
2951
## Template.forEach(callback)
3052

3153
Call `callback` once for each defined template. Generally, you'll want to call this in a `Meteor.startup` function or sometime after all templates have been loaded.
3254

55+
## Template.forEachCurrentlyRenderedInstance(callback)
56+
57+
Call `callback` once for each template instance that is currently rendered.
58+
3359
## Template.onCreated / Template.onRendered / Template.onDestroyed
3460

3561
Run a function whenever *any* template is created/rendered/destroyed.
@@ -43,7 +69,7 @@ Template.onRendered(function () {
4369

4470
## hooks(options)
4571

46-
Use this instead of setting created/rendered/destroyed property directly. You can call it multiple times to attach multiple hooks to the same template.
72+
An alternative syntax to `onCreated`, `onRendered`, and `onDestroyed`.
4773

4874
```js
4975
Template.foo.hooks({
@@ -82,9 +108,11 @@ Template.foo.hooks({
82108
*client.js*
83109

84110
```js
85-
Template.foo.bar = function () {
86-
return "TEST";
87-
};
111+
Template.foo.helpers({
112+
bar: function () {
113+
return "TEST";
114+
}
115+
});
88116

89117
Template.foo.events({
90118
'click button': function (event, template) {
@@ -99,6 +127,8 @@ Whenever `{{> foo}}` is used, the contents of the `foo2` template will be shown
99127

100128
This is useful when a package you are using defines a template for something and you'd like to adjust some things in that template for your app.
101129

130+
NOTE: This simply swaps the render function. Helpers, callbacks, and events assigned to `foo2` will not fire when `{{> foo}}` is used. Only the `foo` helpers, callbacks, and events are used.
131+
102132
## inheritsHelpersFrom(templateName), inheritsEventsFrom(templateName), and inheritsHooksFrom(templateName)
103133

104134
*html*
@@ -147,6 +177,10 @@ In this example, both templates are rendered. Both use the `bar` helper defined
147177

148178
Additionally, these methods can be called with an array of template names: `Template.foo2.inheritsHooksFrom(['foo', 'bar', 'baz']);`
149179

180+
## clearEventMaps()
181+
182+
After `Template.foo.events({...})` has been called one or more times, you can remove all the added event handlers by calling `Template.foo.clearEventMaps()`
183+
150184
## copyAs(newTemplateName)
151185

152186
*html*
@@ -204,7 +238,7 @@ they are not.
204238
## template.get(fieldName)
205239

206240
To not have to hard-code the number of levels when accessing parent template instances you can use
207-
`get(fieldName)` method which returns the value of the first field named `fieldName` in the current
241+
`get(fieldName)` method which returns the value of the first property named `fieldName` on the current
208242
or ancestor template instances, traversed in the hierarchical order. It traverses block helper template
209243
instances as well. This pattern makes it easier to refactor templates without having to worry about
210244
changes to number of levels.
@@ -223,7 +257,7 @@ var data = Template.parentData(function (data) {return data instanceof MyDocumen
223257

224258
## Contributors
225259

226-
* @aldeed ([Support via Gratipay](https://gratipay.com/aldeed/))
260+
* @aldeed
227261
* @grabbou
228262
* @mitar
229263
* @jgladch

lib/hooks.js

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
Hooks = {
2+
global: {
3+
created: [],
4+
rendered: [],
5+
destroyed: []
6+
},
7+
master: {
8+
created: function () {
9+
Hooks.runGlobal('created', this, arguments);
10+
},
11+
rendered: function () {
12+
Hooks.runGlobal('rendered', this, arguments);
13+
},
14+
destroyed: function () {
15+
Hooks.runGlobal('destroyed', this, arguments);
16+
}
17+
}
18+
};
19+
20+
Hooks.addGlobal = (template) => {
21+
// For each hookType, define the hooks for this template.
22+
// Since we might call this multiple times from startup code
23+
// and other functions, make sure we do it only once.
24+
// Doing it twice would create an infinite loop of self-calling
25+
// hooks.
26+
if (!template._hasTemplateExtensionMasterHooks) {
27+
template.onCreated(Hooks.master.created);
28+
template.onRendered(Hooks.master.rendered);
29+
template.onDestroyed(Hooks.master.destroyed);
30+
31+
template._hasTemplateExtensionMasterHooks = true;
32+
}
33+
};
34+
35+
Hooks.runGlobal = (type, template, args) => {
36+
for (let hook of Hooks.global[type]) {
37+
hook.apply(template, args);
38+
}
39+
};

lib/template-clear-event-maps.js

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Template.prototype.clearEventMaps = function clearEventMaps() {
2+
this.__eventMaps = [];
3+
};

lib/template-copy-as.js

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
Template.prototype.copyAs = function copyAs(newTemplateName) {
2+
var self = this;
3+
4+
function createNewTemplate(templateName) {
5+
var newTemplate =
6+
Template[templateName] = new Template(`Template.${templateName}`, self.renderFunction);
7+
8+
newTemplate.inheritsHelpersFrom(self);
9+
newTemplate.inheritsEventsFrom(self);
10+
newTemplate.inheritsHooksFrom(self);
11+
12+
return newTemplate;
13+
}
14+
15+
// Check if newTemplateName is an array
16+
if (_.isArray(newTemplateName)) {
17+
let result = [];
18+
for (let name of newTemplateName) {
19+
result.push(createNewTemplate(name));
20+
}
21+
return result;
22+
} else { //newTemplateName is a string
23+
return createNewTemplate(newTemplateName);
24+
}
25+
};

lib/template-for-each-instance.js

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
Template._renderedInstances = [];
2+
3+
Template.onRendered(function () {
4+
Template._renderedInstances.push(this);
5+
});
6+
7+
Template.onDestroyed(function () {
8+
var i = Template._renderedInstances.indexOf(this);
9+
if (i > -1) Template._renderedInstances.splice(i, 1);
10+
});
11+
12+
Template.forEachCurrentlyRenderedInstance = (func) => {
13+
Template._renderedInstances.forEach(func);
14+
};

lib/template-for-each.js

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
Template.forEach = (callback) => {
2+
// for some reason we get the "body" template twice when looping, so
3+
// we track that and only call the callback once.
4+
var alreadyDidBody = false;
5+
for (var t in Template) {
6+
if (Template.hasOwnProperty(t)) {
7+
var tmpl = Template[t];
8+
if (Blaze.isTemplate(tmpl)) {
9+
let name = tmpl.viewName;
10+
if (name === "body") {
11+
if (!alreadyDidBody) {
12+
alreadyDidBody = true;
13+
callback(tmpl);
14+
}
15+
} else if (name !== 'Template.__dynamic' && name !== 'Template.__dynamicWithDataContext') {
16+
callback(tmpl);
17+
}
18+
}
19+
}
20+
}
21+
};

lib/template-global-hooks.js

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Setup for multiple hooks support
2+
// We assume that no other code will be directly defining
3+
// a hook once the client has started.
4+
Meteor.startup(() => {
5+
Template.forEach((template) => {
6+
Hooks.addGlobal(template);
7+
});
8+
});
9+
10+
Template.onCreated = (hook) => {
11+
Hooks.global.created.push(hook);
12+
};
13+
14+
Template.onRendered = (hook) => {
15+
Hooks.global.rendered.push(hook);
16+
};
17+
18+
Template.onDestroyed = (hook) => {
19+
Hooks.global.destroyed.push(hook);
20+
};

lib/template-hooks.js

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
Template.prototype.hooks = function (hooks) {
2+
if (!hooks || typeof hooks !== "object") {
3+
throw new Error("hooks argument must be an object with created, rendered, and/or destroyed properties, each set to a function");
4+
}
5+
6+
if (typeof hooks.created === 'function') this.onCreated(hooks.created);
7+
if (typeof hooks.rendered === 'function') this.onRendered(hooks.rendered);
8+
if (typeof hooks.destroyed === 'function') this.onDestroyed(hooks.destroyed);
9+
};

lib/template-inherits-events-from.js

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
Template.prototype.inheritsEventsFrom = function inheritsEventsFrom(otherTemplate) {
2+
var self = this;
3+
4+
self.__eventMaps = self.__eventMaps || [];
5+
6+
function inheritEvents(template) {
7+
// String template names can be provided and template object is looked up
8+
if (typeof template === 'string') template = Template[template];
9+
if (!template) return;
10+
11+
self.__eventMaps = self.__eventMaps.concat(template.__eventMaps);
12+
}
13+
14+
// Accept an array as otherTemplate argument
15+
if (_.isArray(otherTemplate)) {
16+
_.each(otherTemplate, inheritEvents);
17+
} else { //otherTemplate is a string
18+
inheritEvents(otherTemplate);
19+
}
20+
};

0 commit comments

Comments
 (0)