Use preferred helper style in docs,apps,packages

This commit is contained in:
David Greenspan
2014-09-25 14:56:15 -07:00
parent 78bb8399d2
commit 48264ccafd
19 changed files with 622 additions and 535 deletions

View File

@@ -1633,14 +1633,18 @@ Example:
{{lt}}/template>
///// in JS file
Template.postsView.posts = function() {
return Posts.find();
};
Template.postsView.helpers({
posts: function() {
return Posts.find();
}
});
Template.postItem.postClass = function() {
return Session.equals("selectedPost", this._id) ?
"selected" : "";
};
Template.postItem.helpers({
postClass: function() {
return Session.equals("selectedPost", this._id) ?
"selected" : "";
}
});
Template.postItem.events({
'click': function() {
@@ -2220,12 +2224,6 @@ Example:
Now you can invoke this helper with `{{dstache}}foo}}` in the template defined
with `<{{! }}template name="myTemplate">`.
The following syntax is a shorthand for when you only have one helper to define:
Template.myTemplate.foo = function () {
return Session.get("foo");
};
To create a helper that can be used in any template, use
[`Template.registerHelper`](#template_registerhelper).

View File

@@ -457,9 +457,11 @@ functions in JavaScript. Just add the helper functions directly on the
{{lt}}/template>
// in client/myapp.js: reactive helper function
Template.forecast.prediction = function () {
return Session.get("weather");
};
Template.forecast.helpers({
prediction: function () {
return Session.get("weather");
}
});
// in the JavaScript console
> Session.set("weather", "cloudy");
@@ -481,9 +483,11 @@ To iterate over an array or database cursor, use `{{dstache}}#each}}`:
{{lt}}/template>
// in myapp.js
Template.players.topScorers = function () {
return Users.find({score: {$gt: 100}}, {sort: {score: -1}});
};
Template.players.helpers({
topScorers: function () {
return Users.find({score: {$gt: 100}}, {sort: {score: -1}});
}
});
In this case, the data is coming from a database query. When the
database cursor is passed to `{{dstache}}#each}}`, it will wire up all of the
@@ -495,9 +499,11 @@ in `this`. Note that some block helpers change the current context (notably
`{{dstache}}#each}}` and `{{dstache}}#with}}`):
// in a JavaScript file
Template.players.leagueIs = function (league) {
return this.league === league;
};
Template.players.helpers({
leagueIs: function (league) {
return this.league === league;
}
});
<!-- in a HTML file -->
<template name="players">
@@ -514,7 +520,9 @@ in `this`. Note that some block helpers change the current context (notably
Helpers can also be used to pass in constant data.
// Works fine with {{dstache}}#each sections}}
Template.report.sections = ["Situation", "Complication", "Resolution"];
Template.report.helpers({
sections: ["Situation", "Complication", "Resolution"]
});
Finally, you can use an `events` declaration on a template function to set up a
table of event handlers. The format is documented at [Event

View File

@@ -1,6 +1,8 @@
Template.headline.release = function () {
return Meteor.release ? "0.9.2.2" : "(checkout)";
};
Template.headline.helpers({
release: function () {
return Meteor.release ? "0.9.2.2" : "(checkout)";
}
});
Meteor.startup(function () {
// XXX this is broken by the new multi-page layout. Also, it was
@@ -439,44 +441,46 @@ var name_to_id = function (name) {
return x;
};
Template.nav.sections = function () {
var ret = [];
var walk = function (items, depth) {
_.each(items, function (item) {
// Work around (eg) accidental trailing commas leading to spurious holes
// in IE8.
if (!item)
return;
if (item instanceof Array)
walk(item, depth + 1);
else {
if (typeof(item) === "string")
item = {name: item};
ret.push(_.extend({
type: "section",
id: item.name && name_to_id(item.name) || undefined,
depth: depth,
style: ''
}, item));
}
});
};
Template.nav.helpers({
sections: function () {
var ret = [];
var walk = function (items, depth) {
_.each(items, function (item) {
// Work around (eg) accidental trailing commas leading to spurious holes
// in IE8.
if (!item)
return;
if (item instanceof Array)
walk(item, depth + 1);
else {
if (typeof(item) === "string")
item = {name: item};
ret.push(_.extend({
type: "section",
id: item.name && name_to_id(item.name) || undefined,
depth: depth,
style: ''
}, item));
}
});
};
walk(toc, 1);
return ret;
};
walk(toc, 1);
return ret;
},
Template.nav.type = function (what) {
return this.type === what;
};
type: function (what) {
return this.type === what;
},
Template.nav.maybe_current = function () {
return Session.equals("section", this.id) ? "current" : "";
};
maybe_current: function () {
return Session.equals("section", this.id) ? "current" : "";
},
Template.nav_section.depthIs = function (n) {
return this.depth === n;
};
depthIs: function (n) {
return this.depth === n;
}
});
// Show hidden TOC when menu icon is tapped
Template.nav.events({

View File

@@ -4,18 +4,21 @@
Players = new Mongo.Collection("players");
if (Meteor.isClient) {
Template.leaderboard.players = function () {
return Players.find({}, {sort: {score: -1, name: 1}});
};
Template.leaderboard.helpers({
players: function () {
return Players.find({}, {sort: {score: -1, name: 1}});
},
selected_name: function () {
var player = Players.findOne(Session.get("selected_player"));
return player && player.name;
}
});
Template.leaderboard.selected_name = function () {
var player = Players.findOne(Session.get("selected_player"));
return player && player.name;
};
Template.player.selected = function () {
return Session.equals("selected_player", this._id) ? "selected" : '';
};
Template.player.helpers({
selected: function () {
return Session.equals("selected_player", this._id) ? "selected" : '';
}
});
Template.leaderboard.events({
'click button.inc': function () {

View File

@@ -20,32 +20,30 @@ Meteor.startup(function () {
///////////////////////////////////////////////////////////////////////////////
// Party details sidebar
Template.details.party = function () {
return Parties.findOne(Session.get("selected"));
};
Template.details.helpers({
party: function () {
return Parties.findOne(Session.get("selected"));
},
anyParties: function () {
return Parties.find().count() > 0;
},
creatorName: function () {
var owner = Meteor.users.findOne(this.owner);
if (owner._id === Meteor.userId())
return "me";
return displayName(owner);
},
canRemove: function () {
return this.owner === Meteor.userId() && attending(this) === 0;
},
maybeChosen: function (what) {
var myRsvp = _.find(this.rsvps, function (r) {
return r.user === Meteor.userId();
}) || {};
Template.details.anyParties = function () {
return Parties.find().count() > 0;
};
Template.details.creatorName = function () {
var owner = Meteor.users.findOne(this.owner);
if (owner._id === Meteor.userId())
return "me";
return displayName(owner);
};
Template.details.canRemove = function () {
return this.owner === Meteor.userId() && attending(this) === 0;
};
Template.details.maybeChosen = function (what) {
var myRsvp = _.find(this.rsvps, function (r) {
return r.user === Meteor.userId();
}) || {};
return what == myRsvp.rsvp ? "chosen btn-inverse" : "";
};
return what == myRsvp.rsvp ? "chosen btn-inverse" : "";
}
});
Template.details.events({
'click .rsvp_yes': function () {
@@ -73,34 +71,36 @@ Template.details.events({
///////////////////////////////////////////////////////////////////////////////
// Party attendance widget
Template.attendance.rsvpName = function () {
var user = Meteor.users.findOne(this.user);
return displayName(user);
};
Template.attendance.helpers({
rsvpName: function () {
var user = Meteor.users.findOne(this.user);
return displayName(user);
},
Template.attendance.outstandingInvitations = function () {
var party = Parties.findOne(this._id);
return Meteor.users.find({$and: [
{_id: {$in: party.invited}}, // they're invited
{_id: {$nin: _.pluck(party.rsvps, 'user')}} // but haven't RSVP'd
]});
};
outstandingInvitations: function () {
var party = Parties.findOne(this._id);
return Meteor.users.find({$and: [
{_id: {$in: party.invited}}, // they're invited
{_id: {$nin: _.pluck(party.rsvps, 'user')}} // but haven't RSVP'd
]});
},
Template.attendance.invitationName = function () {
return displayName(this);
};
invitationName: function () {
return displayName(this);
},
Template.attendance.rsvpIs = function (what) {
return this.rsvp === what;
};
rsvpIs: function (what) {
return this.rsvp === what;
},
Template.attendance.nobody = function () {
return ! this.public && (this.rsvps.length + this.invited.length === 0);
};
nobody: function () {
return ! this.public && (this.rsvps.length + this.invited.length === 0);
},
Template.attendance.canInvite = function () {
return ! this.public && this.owner === Meteor.userId();
};
canInvite: function () {
return ! this.public && this.owner === Meteor.userId();
}
});
///////////////////////////////////////////////////////////////////////////////
// Map display
@@ -204,9 +204,11 @@ var openCreateDialog = function (x, y) {
Session.set("showCreateDialog", true);
};
Template.page.showCreateDialog = function () {
return Session.get("showCreateDialog");
};
Template.page.helpers({
showCreateDialog: function () {
return Session.get("showCreateDialog");
}
});
Template.createDialog.events({
'click .save': function (event, template) {
@@ -239,9 +241,11 @@ Template.createDialog.events({
}
});
Template.createDialog.error = function () {
return Session.get("createError");
};
Template.createDialog.helpers({
error: function () {
return Session.get("createError");
}
});
///////////////////////////////////////////////////////////////////////////////
// Invite dialog
@@ -250,9 +254,11 @@ var openInviteDialog = function () {
Session.set("showInviteDialog", true);
};
Template.page.showInviteDialog = function () {
return Session.get("showInviteDialog");
};
Template.page.helpers({
showInviteDialog: function () {
return Session.get("showInviteDialog");
}
});
Template.inviteDialog.events({
'click .invite': function (event, template) {
@@ -264,14 +270,16 @@ Template.inviteDialog.events({
}
});
Template.inviteDialog.uninvited = function () {
var party = Parties.findOne(Session.get("selected"));
if (! party)
return []; // party hasn't loaded yet
return Meteor.users.find({$nor: [{_id: {$in: party.invited}},
{_id: party.owner}]});
};
Template.inviteDialog.helpers({
uninvited: function () {
var party = Parties.findOne(Session.get("selected"));
if (! party)
return []; // party hasn't loaded yet
return Meteor.users.find({$nor: [{_id: {$in: party.invited}},
{_id: party.owner}]});
},
Template.inviteDialog.displayName = function () {
return displayName(this);
};
displayName: function () {
return displayName(this);
}
});

View File

@@ -77,13 +77,15 @@ var activateInput = function (input) {
////////// Lists //////////
Template.lists.loading = function () {
return !listsHandle.ready();
};
Template.lists.helpers({
loading: function () {
return !listsHandle.ready();
},
Template.lists.lists = function () {
return Lists.find({}, {sort: {name: 1}});
};
lists: function () {
return Lists.find({}, {sort: {name: 1}});
}
});
Template.lists.events({
'mousedown .list': function (evt) { // select list
@@ -123,27 +125,33 @@ Template.lists.events(okCancelEvents(
}
}));
Template.lists.selected = function () {
return Session.equals('list_id', this._id) ? 'selected' : '';
};
Template.lists.helpers({
selected: function () {
return Session.equals('list_id', this._id) ? 'selected' : '';
},
Template.lists.name_class = function () {
return this.name ? '' : 'empty';
};
name_class: function () {
return this.name ? '' : 'empty';
},
Template.lists.editing = function () {
return Session.equals('editing_listname', this._id);
};
editing: function () {
return Session.equals('editing_listname', this._id);
}
});
////////// Todos //////////
Template.todos.loading = function () {
return todosHandle && !todosHandle.ready();
};
Template.todos.helpers({
loading: function () {
return todosHandle && !todosHandle.ready();
}
});
Template.todos.any_list_selected = function () {
return !Session.equals('list_id', null);
};
Template.todos.helpers({
any_list_selected: function () {
return !Session.equals('list_id', null);
}
});
Template.todos.events(okCancelEvents(
'#new-todo',
@@ -161,40 +169,44 @@ Template.todos.events(okCancelEvents(
}
}));
Template.todos.todos = function () {
// Determine which todos to display in main pane,
// selected based on list_id and tag_filter.
Template.todos.helpers({
todos: function () {
// Determine which todos to display in main pane,
// selected based on list_id and tag_filter.
var list_id = Session.get('list_id');
if (!list_id)
return [];
var list_id = Session.get('list_id');
if (!list_id)
return [];
var sel = {list_id: list_id};
var tag_filter = Session.get('tag_filter');
if (tag_filter)
sel.tags = tag_filter;
var sel = {list_id: list_id};
var tag_filter = Session.get('tag_filter');
if (tag_filter)
sel.tags = tag_filter;
return Todos.find(sel, {sort: {timestamp: 1}});
};
return Todos.find(sel, {sort: {timestamp: 1}});
}
});
Template.todo_item.tag_objs = function () {
var todo_id = this._id;
return _.map(this.tags || [], function (tag) {
return {todo_id: todo_id, tag: tag};
});
};
Template.todo_item.helpers({
tag_objs: function () {
var todo_id = this._id;
return _.map(this.tags || [], function (tag) {
return {todo_id: todo_id, tag: tag};
});
},
Template.todo_item.done_class = function () {
return this.done ? 'done' : '';
};
done_class: function () {
return this.done ? 'done' : '';
},
Template.todo_item.editing = function () {
return Session.equals('editing_itemname', this._id);
};
editing: function () {
return Session.equals('editing_itemname', this._id);
},
Template.todo_item.adding_tag = function () {
return Session.equals('editing_addtag', this._id);
};
adding_tag: function () {
return Session.equals('editing_addtag', this._id);
}
});
Template.todo_item.events({
'click .check': function () {
@@ -256,34 +268,36 @@ Template.todo_item.events(okCancelEvents(
////////// Tag Filter //////////
// Pick out the unique tags from all todos in current list.
Template.tag_filter.tags = function () {
var tag_infos = [];
var total_count = 0;
Template.tag_filter.helpers({
tags: function () {
var tag_infos = [];
var total_count = 0;
Todos.find({list_id: Session.get('list_id')}).forEach(function (todo) {
_.each(todo.tags, function (tag) {
var tag_info = _.find(tag_infos, function (x) { return x.tag === tag; });
if (! tag_info)
tag_infos.push({tag: tag, count: 1});
else
tag_info.count++;
Todos.find({list_id: Session.get('list_id')}).forEach(function (todo) {
_.each(todo.tags, function (tag) {
var tag_info = _.find(tag_infos, function (x) { return x.tag === tag; });
if (! tag_info)
tag_infos.push({tag: tag, count: 1});
else
tag_info.count++;
});
total_count++;
});
total_count++;
});
tag_infos = _.sortBy(tag_infos, function (x) { return x.tag; });
tag_infos.unshift({tag: null, count: total_count});
tag_infos = _.sortBy(tag_infos, function (x) { return x.tag; });
tag_infos.unshift({tag: null, count: total_count});
return tag_infos;
};
return tag_infos;
},
Template.tag_filter.tag_text = function () {
return this.tag || "All items";
};
tag_text: function () {
return this.tag || "All items";
},
Template.tag_filter.selected = function () {
return Session.equals('tag_filter', this.tag) ? 'selected' : '';
};
selected: function () {
return Session.equals('tag_filter', this.tag) ? 'selected' : '';
}
});
Template.tag_filter.events({
'mousedown .tag': function () {

View File

@@ -43,33 +43,35 @@ var clear_selected_positions = function () {
////// offers a button to start a fresh game.
//////
Template.lobby.show = function () {
// only show lobby if we're not in a game
return !game();
};
Template.lobby.helpers({
show: function () {
// only show lobby if we're not in a game
return !game();
},
Template.lobby.waiting = function () {
var players = Players.find({_id: {$ne: Session.get('player_id')},
name: {$ne: ''},
game_id: {$exists: false}});
waiting: function () {
var players = Players.find({_id: {$ne: Session.get('player_id')},
name: {$ne: ''},
game_id: {$exists: false}});
return players;
};
return players;
},
Template.lobby.count = function () {
var players = Players.find({_id: {$ne: Session.get('player_id')},
name: {$ne: ''},
game_id: {$exists: false}});
count: function () {
var players = Players.find({_id: {$ne: Session.get('player_id')},
name: {$ne: ''},
game_id: {$exists: false}});
return players.count();
};
return players.count();
},
Template.lobby.disabled = function () {
var me = player();
if (me && me.name)
return '';
return 'disabled';
};
disabled: function () {
var me = player();
if (me && me.name)
return '';
return 'disabled';
}
});
var trim = function (string) { return string.replace(/^\s+|\s+$/g, ''); };
@@ -92,26 +94,28 @@ var SPLASH = ['','','','',
'P', 'L', 'A', 'Y',
'','','',''];
Template.board.square = function (i) {
var g = game();
return g && g.board && g.board[i] || SPLASH[i];
};
Template.board.helpers({
square: function (i) {
var g = game();
return g && g.board && g.board[i] || SPLASH[i];
},
Template.board.selected = function (i) {
return Session.get('selected_' + i);
};
selected: function (i) {
return Session.get('selected_' + i);
},
Template.board.clock = function () {
var clock = game() && game().clock;
clock: function () {
var clock = game() && game().clock;
if (!clock || clock === 0)
return;
if (!clock || clock === 0)
return;
// format into M:SS
var min = Math.floor(clock / 60);
var sec = clock % 60;
return min + ':' + (sec < 10 ? ('0' + sec) : sec);
};
// format into M:SS
var min = Math.floor(clock / 60);
var sec = clock % 60;
return min + ':' + (sec < 10 ? ('0' + sec) : sec);
}
});
Template.board.events({
'click .square': function (evt) {
@@ -127,9 +131,11 @@ Template.board.events({
////// scratchpad is where we enter new words.
//////
Template.scratchpad.show = function () {
return game() && game().clock > 0;
};
Template.scratchpad.helpers({
show: function () {
return game() && game().clock > 0;
}
});
Template.scratchpad.events({
'click button, keyup input': function (evt) {
@@ -151,9 +157,11 @@ Template.scratchpad.events({
}
});
Template.postgame.show = function () {
return game() && game().clock === 0;
};
Template.postgame.helpers({
show: function () {
return game() && game().clock === 0;
}
});
Template.postgame.events({
'click button': function (evt) {
@@ -165,37 +173,43 @@ Template.postgame.events({
////// scores shows everyone's score and word list.
//////
Template.scores.show = function () {
return !!game();
};
Template.scores.helpers({
show: function () {
return !!game();
},
Template.scores.players = function () {
return game() && game().players;
};
players: function () {
return game() && game().players;
}
});
Template.player.winner = function () {
var g = game();
if (g.winners && _.include(g.winners, this._id))
return 'winner';
return '';
};
Template.player.helpers({
winner: function () {
var g = game();
if (g.winners && _.include(g.winners, this._id))
return 'winner';
return '';
},
Template.player.total_score = function () {
var words = Words.find({game_id: game() && game()._id,
player_id: this._id});
total_score: function () {
var words = Words.find({game_id: game() && game()._id,
player_id: this._id});
var score = 0;
words.forEach(function (word) {
if (word.score)
score += word.score;
});
return score;
};
var score = 0;
words.forEach(function (word) {
if (word.score)
score += word.score;
});
return score;
}
});
Template.words.words = function () {
return Words.find({game_id: game() && game()._id,
player_id: this._id});
};
Template.words.helpers({
words: function () {
return Words.find({game_id: game() && game()._id,
player_id: this._id});
}
});
//////

View File

@@ -107,30 +107,31 @@ validatePassword = function (password) {
// loginButtonLoggedOut template
//
Template._loginButtonsLoggedOut.dropdown = dropdown;
Template._loginButtonsLoggedOut.services = getLoginServices;
Template._loginButtonsLoggedOut.singleService = function () {
var services = getLoginServices();
if (services.length !== 1)
throw new Error(
"Shouldn't be rendering this template with more than one configured service");
return services[0];
};
Template._loginButtonsLoggedOut.configurationLoaded = function () {
return Accounts.loginServicesConfigured();
};
Template._loginButtonsLoggedOut.helpers({
dropdown: dropdown,
services: getLoginServices,
singleService: function () {
var services = getLoginServices();
if (services.length !== 1)
throw new Error(
"Shouldn't be rendering this template with more than one configured service");
return services[0];
},
configurationLoaded: function () {
return Accounts.loginServicesConfigured();
}
});
//
// loginButtonsLoggedIn template
//
// decide whether we should show a dropdown rather than a row of
// buttons
Template._loginButtonsLoggedIn.dropdown = dropdown;
// decide whether we should show a dropdown rather than a row of
// buttons
Template._loginButtonsLoggedIn.helpers({
dropdown: dropdown
});
@@ -138,7 +139,9 @@ Template._loginButtonsLoggedIn.dropdown = dropdown;
// loginButtonsLoggedInSingleLogoutButton template
//
Template._loginButtonsLoggedInSingleLogoutButton.displayName = displayName;
Template._loginButtonsLoggedInSingleLogoutButton.helpers({
displayName: displayName
});
@@ -146,17 +149,23 @@ Template._loginButtonsLoggedInSingleLogoutButton.displayName = displayName;
// loginButtonsMessage template
//
Template._loginButtonsMessages.errorMessage = function () {
return loginButtonsSession.get('errorMessage');
};
Template._loginButtonsMessages.helpers({
errorMessage: function () {
return loginButtonsSession.get('errorMessage');
}
});
Template._loginButtonsMessages.infoMessage = function () {
return loginButtonsSession.get('infoMessage');
};
Template._loginButtonsMessages.helpers({
infoMessage: function () {
return loginButtonsSession.get('infoMessage');
}
});
//
// loginButtonsLoggingInPadding template
//
Template._loginButtonsLoggingInPadding.dropdown = dropdown;
Template._loginButtonsLoggingInPadding.helpers({
dropdown: dropdown
});

View File

@@ -26,29 +26,33 @@ Template._loginButtonsLoggedInDropdown.events({
}
});
Template._loginButtonsLoggedInDropdown.displayName = displayName;
Template._loginButtonsLoggedInDropdown.helpers({
displayName: displayName,
Template._loginButtonsLoggedInDropdown.inChangePasswordFlow = function () {
return loginButtonsSession.get('inChangePasswordFlow');
};
inChangePasswordFlow: function () {
return loginButtonsSession.get('inChangePasswordFlow');
},
Template._loginButtonsLoggedInDropdown.inMessageOnlyFlow = function () {
return loginButtonsSession.get('inMessageOnlyFlow');
};
inMessageOnlyFlow: function () {
return loginButtonsSession.get('inMessageOnlyFlow');
},
Template._loginButtonsLoggedInDropdown.dropdownVisible = function () {
return loginButtonsSession.get('dropdownVisible');
};
dropdownVisible: function () {
return loginButtonsSession.get('dropdownVisible');
}
});
Template._loginButtonsLoggedInDropdownActions.allowChangingPassword = function () {
// it would be more correct to check whether the user has a password set,
// but in order to do that we'd have to send more data down to the client,
// and it'd be preferable not to send down the entire service.password document.
//
// instead we use the heuristic: if the user has a username or email set.
var user = Meteor.user();
return user.username || (user.emails && user.emails[0] && user.emails[0].address);
};
Template._loginButtonsLoggedInDropdownActions.helpers({
allowChangingPassword: function () {
// it would be more correct to check whether the user has a password set,
// but in order to do that we'd have to send more data down to the client,
// and it'd be preferable not to send down the entire service.password document.
//
// instead we use the heuristic: if the user has a username or email set.
var user = Meteor.user();
return user.username || (user.emails && user.emails[0] && user.emails[0].address);
}
});
//
@@ -161,124 +165,131 @@ Template._loginButtonsLoggedOutDropdown.events({
}
});
// additional classes that can be helpful in styling the dropdown
Template._loginButtonsLoggedOutDropdown.additionalClasses = function () {
if (!hasPasswordService()) {
return false;
} else {
if (loginButtonsSession.get('inSignupFlow')) {
return 'login-form-create-account';
} else if (loginButtonsSession.get('inForgotPasswordFlow')) {
return 'login-form-forgot-password';
Template._loginButtonsLoggedOutDropdown.helpers({
// additional classes that can be helpful in styling the dropdown
additionalClasses: function () {
if (!hasPasswordService()) {
return false;
} else {
return 'login-form-sign-in';
if (loginButtonsSession.get('inSignupFlow')) {
return 'login-form-create-account';
} else if (loginButtonsSession.get('inForgotPasswordFlow')) {
return 'login-form-forgot-password';
} else {
return 'login-form-sign-in';
}
}
}
};
},
Template._loginButtonsLoggedOutDropdown.dropdownVisible = function () {
return loginButtonsSession.get('dropdownVisible');
};
dropdownVisible: function () {
return loginButtonsSession.get('dropdownVisible');
},
Template._loginButtonsLoggedOutDropdown.hasPasswordService = hasPasswordService;
hasPasswordService: hasPasswordService
});
// return all login services, with password last
Template._loginButtonsLoggedOutAllServices.services = getLoginServices;
Template._loginButtonsLoggedOutAllServices.helpers({
services: getLoginServices,
Template._loginButtonsLoggedOutAllServices.isPasswordService = function () {
return this.name === 'password';
};
isPasswordService: function () {
return this.name === 'password';
},
Template._loginButtonsLoggedOutAllServices.hasOtherServices = function () {
return getLoginServices().length > 1;
};
hasOtherServices: function () {
return getLoginServices().length > 1;
},
Template._loginButtonsLoggedOutAllServices.hasPasswordService =
hasPasswordService;
hasPasswordService: hasPasswordService
});
Template._loginButtonsLoggedOutPasswordService.fields = function () {
var loginFields = [
{fieldName: 'username-or-email', fieldLabel: 'Username or Email',
visible: function () {
return _.contains(
["USERNAME_AND_EMAIL", "USERNAME_AND_OPTIONAL_EMAIL"],
passwordSignupFields());
}},
{fieldName: 'username', fieldLabel: 'Username',
visible: function () {
return passwordSignupFields() === "USERNAME_ONLY";
}},
{fieldName: 'email', fieldLabel: 'Email', inputType: 'email',
visible: function () {
return passwordSignupFields() === "EMAIL_ONLY";
}},
{fieldName: 'password', fieldLabel: 'Password', inputType: 'password',
visible: function () {
return true;
}}
];
Template._loginButtonsLoggedOutPasswordService.helpers({
fields: function () {
var loginFields = [
{fieldName: 'username-or-email', fieldLabel: 'Username or Email',
visible: function () {
return _.contains(
["USERNAME_AND_EMAIL", "USERNAME_AND_OPTIONAL_EMAIL"],
passwordSignupFields());
}},
{fieldName: 'username', fieldLabel: 'Username',
visible: function () {
return passwordSignupFields() === "USERNAME_ONLY";
}},
{fieldName: 'email', fieldLabel: 'Email', inputType: 'email',
visible: function () {
return passwordSignupFields() === "EMAIL_ONLY";
}},
{fieldName: 'password', fieldLabel: 'Password', inputType: 'password',
visible: function () {
return true;
}}
];
var signupFields = [
{fieldName: 'username', fieldLabel: 'Username',
visible: function () {
return _.contains(
["USERNAME_AND_EMAIL", "USERNAME_AND_OPTIONAL_EMAIL", "USERNAME_ONLY"],
passwordSignupFields());
}},
{fieldName: 'email', fieldLabel: 'Email', inputType: 'email',
visible: function () {
return _.contains(
["USERNAME_AND_EMAIL", "EMAIL_ONLY"],
passwordSignupFields());
}},
{fieldName: 'email', fieldLabel: 'Email (optional)', inputType: 'email',
visible: function () {
return passwordSignupFields() === "USERNAME_AND_OPTIONAL_EMAIL";
}},
{fieldName: 'password', fieldLabel: 'Password', inputType: 'password',
visible: function () {
return true;
}},
{fieldName: 'password-again', fieldLabel: 'Password (again)',
inputType: 'password',
visible: function () {
// No need to make users double-enter their password if
// they'll necessarily have an email set, since they can use
// the "forgot password" flow.
return _.contains(
["USERNAME_AND_OPTIONAL_EMAIL", "USERNAME_ONLY"],
passwordSignupFields());
}}
];
var signupFields = [
{fieldName: 'username', fieldLabel: 'Username',
visible: function () {
return _.contains(
["USERNAME_AND_EMAIL", "USERNAME_AND_OPTIONAL_EMAIL", "USERNAME_ONLY"],
passwordSignupFields());
}},
{fieldName: 'email', fieldLabel: 'Email', inputType: 'email',
visible: function () {
return _.contains(
["USERNAME_AND_EMAIL", "EMAIL_ONLY"],
passwordSignupFields());
}},
{fieldName: 'email', fieldLabel: 'Email (optional)', inputType: 'email',
visible: function () {
return passwordSignupFields() === "USERNAME_AND_OPTIONAL_EMAIL";
}},
{fieldName: 'password', fieldLabel: 'Password', inputType: 'password',
visible: function () {
return true;
}},
{fieldName: 'password-again', fieldLabel: 'Password (again)',
inputType: 'password',
visible: function () {
// No need to make users double-enter their password if
// they'll necessarily have an email set, since they can use
// the "forgot password" flow.
return _.contains(
["USERNAME_AND_OPTIONAL_EMAIL", "USERNAME_ONLY"],
passwordSignupFields());
}}
];
return loginButtonsSession.get('inSignupFlow') ? signupFields : loginFields;
};
return loginButtonsSession.get('inSignupFlow') ? signupFields : loginFields;
},
Template._loginButtonsLoggedOutPasswordService.inForgotPasswordFlow = function () {
return loginButtonsSession.get('inForgotPasswordFlow');
};
inForgotPasswordFlow: function () {
return loginButtonsSession.get('inForgotPasswordFlow');
},
Template._loginButtonsLoggedOutPasswordService.inLoginFlow = function () {
return !loginButtonsSession.get('inSignupFlow') && !loginButtonsSession.get('inForgotPasswordFlow');
};
inLoginFlow: function () {
return !loginButtonsSession.get('inSignupFlow') && !loginButtonsSession.get('inForgotPasswordFlow');
},
Template._loginButtonsLoggedOutPasswordService.inSignupFlow = function () {
return loginButtonsSession.get('inSignupFlow');
};
inSignupFlow: function () {
return loginButtonsSession.get('inSignupFlow');
},
Template._loginButtonsLoggedOutPasswordService.showCreateAccountLink = function () {
return !Accounts._options.forbidClientAccountCreation;
};
showCreateAccountLink: function () {
return !Accounts._options.forbidClientAccountCreation;
},
Template._loginButtonsLoggedOutPasswordService.showForgotPasswordLink = function () {
return _.contains(
["USERNAME_AND_EMAIL", "USERNAME_AND_OPTIONAL_EMAIL", "EMAIL_ONLY"],
passwordSignupFields());
};
showForgotPasswordLink: function () {
return _.contains(
["USERNAME_AND_EMAIL", "USERNAME_AND_OPTIONAL_EMAIL", "EMAIL_ONLY"],
passwordSignupFields());
}
});
Template._loginButtonsFormField.inputType = function () {
return this.inputType || "text";
};
Template._loginButtonsFormField.helpers({
inputType: function () {
return this.inputType || "text";
}
});
//
@@ -295,28 +306,30 @@ Template._loginButtonsChangePassword.events({
}
});
Template._loginButtonsChangePassword.fields = function () {
return [
{fieldName: 'old-password', fieldLabel: 'Current Password', inputType: 'password',
visible: function () {
return true;
}},
{fieldName: 'password', fieldLabel: 'New Password', inputType: 'password',
visible: function () {
return true;
}},
{fieldName: 'password-again', fieldLabel: 'New Password (again)',
inputType: 'password',
visible: function () {
// No need to make users double-enter their password if
// they'll necessarily have an email set, since they can use
// the "forgot password" flow.
return _.contains(
["USERNAME_AND_OPTIONAL_EMAIL", "USERNAME_ONLY"],
passwordSignupFields());
}}
];
};
Template._loginButtonsChangePassword.helpers({
fields: function () {
return [
{fieldName: 'old-password', fieldLabel: 'Current Password', inputType: 'password',
visible: function () {
return true;
}},
{fieldName: 'password', fieldLabel: 'New Password', inputType: 'password',
visible: function () {
return true;
}},
{fieldName: 'password-again', fieldLabel: 'New Password (again)',
inputType: 'password',
visible: function () {
// No need to make users double-enter their password if
// they'll necessarily have an email set, since they can use
// the "forgot password" flow.
return _.contains(
["USERNAME_AND_OPTIONAL_EMAIL", "USERNAME_ONLY"],
passwordSignupFields());
}}
];
}
});
//

View File

@@ -54,19 +54,20 @@ Template._loginButtonsLoggedOutSingleLoginButton.events({
}
});
Template._loginButtonsLoggedOutSingleLoginButton.configured = function () {
return !!ServiceConfiguration.configurations.findOne({service: this.name});
};
Template._loginButtonsLoggedOutSingleLoginButton.capitalizedName = function () {
if (this.name === 'github')
// XXX we should allow service packages to set their capitalized name
return 'GitHub';
else if (this.name === 'meteor-developer')
return 'Meteor';
else
return capitalize(this.name);
};
Template._loginButtonsLoggedOutSingleLoginButton.helpers({
configured: function () {
return !!ServiceConfiguration.configurations.findOne({service: this.name});
},
capitalizedName: function () {
if (this.name === 'github')
// XXX we should allow service packages to set their capitalized name
return 'GitHub';
else if (this.name === 'meteor-developer')
return 'Meteor';
else
return capitalize(this.name);
}
});
// XXX from http://epeli.github.com/underscore.string/lib/underscore.string.js
var capitalize = function(str){

View File

@@ -74,7 +74,7 @@ see the variable without having the client also reload.
Add to leaderboard.js:
Template.leaderboard.available = Autoupdate.newClientAvailable;
Template.leaderboard.helpers({available: Autoupdate.newClientAvailable});
And add `{{available}}` to the leaderboard template in
leaderboard.html.

View File

@@ -1,10 +1,11 @@
Template.configureLoginServiceDialogForFacebook.siteUrl = function () {
return Meteor.absoluteUrl();
};
Template.configureLoginServiceDialogForFacebook.fields = function () {
return [
{property: 'appId', label: 'App ID'},
{property: 'secret', label: 'App Secret'}
];
};
Template.configureLoginServiceDialogForFacebook.helpers({
siteUrl: function () {
return Meteor.absoluteUrl();
},
fields: function () {
return [
{property: 'appId', label: 'App ID'},
{property: 'secret', label: 'App Secret'}
];
}
});

View File

@@ -67,17 +67,19 @@ if (Meteor.isServer) {
} else {
Facts.server = new Mongo.Collection(serverFactsCollection);
Template.serverFacts.factsByPackage = function () {
return Facts.server.find();
};
Template.serverFacts.facts = function () {
var factArray = [];
_.each(this, function (value, name) {
if (name !== '_id')
factArray.push({name: name, value: value});
});
return factArray;
};
Template.serverFacts.helpers({
factsByPackage: function () {
return Facts.server.find();
},
facts: function () {
var factArray = [];
_.each(this, function (value, name) {
if (name !== '_id')
factArray.push({name: name, value: value});
});
return factArray;
}
});
// Subscribe when the template is first made, and unsubscribe when it
// is removed. If for some reason puts two copies of the template on

View File

@@ -1,10 +1,12 @@
Template.configureLoginServiceDialogForGithub.siteUrl = function () {
return Meteor.absoluteUrl();
};
Template.configureLoginServiceDialogForGithub.helpers({
siteUrl: function () {
return Meteor.absoluteUrl();
},
Template.configureLoginServiceDialogForGithub.fields = function () {
return [
{property: 'clientId', label: 'Client ID'},
{property: 'secret', label: 'Client Secret'}
];
};
fields: function () {
return [
{property: 'clientId', label: 'Client ID'},
{property: 'secret', label: 'Client Secret'}
];
}
});

View File

@@ -1,10 +1,12 @@
Template.configureLoginServiceDialogForGoogle.siteUrl = function () {
return Meteor.absoluteUrl();
};
Template.configureLoginServiceDialogForGoogle.helpers({
siteUrl: function () {
return Meteor.absoluteUrl();
},
Template.configureLoginServiceDialogForGoogle.fields = function () {
return [
{property: 'clientId', label: 'Client ID'},
{property: 'secret', label: 'Client secret'}
];
};
fields: function () {
return [
{property: 'clientId', label: 'Client ID'},
{property: 'secret', label: 'Client secret'}
];
}
});

View File

@@ -1,10 +1,12 @@
Template.configureLoginServiceDialogForMeetup.siteUrl = function () {
return Meteor.absoluteUrl();
};
Template.configureLoginServiceDialogForMeetup.helpers({
siteUrl: function () {
return Meteor.absoluteUrl();
},
Template.configureLoginServiceDialogForMeetup.fields = function () {
return [
{property: 'clientId', label: 'Key'},
{property: 'secret', label: 'Secret'}
];
};
fields: function () {
return [
{property: 'clientId', label: 'Key'},
{property: 'secret', label: 'Secret'}
];
}
});

View File

@@ -1,10 +1,12 @@
Template.configureLoginServiceDialogForMeteorDeveloper.siteUrl = function () {
return Meteor.absoluteUrl();
};
Template.configureLoginServiceDialogForMeteorDeveloper.helpers({
siteUrl: function () {
return Meteor.absoluteUrl();
},
Template.configureLoginServiceDialogForMeteorDeveloper.fields = function () {
return [
{property: 'clientId', label: 'App ID'},
{property: 'secret', label: 'App secret'}
];
};
fields: function () {
return [
{property: 'clientId', label: 'App ID'},
{property: 'secret', label: 'App secret'}
];
}
});

View File

@@ -1,11 +1,13 @@
Template.configureLoginServiceDialogForTwitter.siteUrl = function () {
Template.configureLoginServiceDialogForTwitter.helpers({
siteUrl: function () {
// Twitter doesn't recognize localhost as a domain name
return Meteor.absoluteUrl({replaceLocalhost: true});
};
return Meteor.absoluteUrl({replaceLocalhost: true});
},
Template.configureLoginServiceDialogForTwitter.fields = function () {
return [
{property: 'consumerKey', label: 'API key'},
{property: 'secret', label: 'API secret'}
];
};
fields: function () {
return [
{property: 'consumerKey', label: 'API key'},
{property: 'secret', label: 'API secret'}
];
}
});

View File

@@ -1,11 +1,13 @@
Template.configureLoginServiceDialogForWeibo.siteUrl = function () {
// Weibo doesn't recognize localhost as a domain
return Meteor.absoluteUrl({replaceLocalhost: true});
};
Template.configureLoginServiceDialogForWeibo.helpers({
siteUrl: function () {
// Weibo doesn't recognize localhost as a domain
return Meteor.absoluteUrl({replaceLocalhost: true});
},
Template.configureLoginServiceDialogForWeibo.fields = function () {
return [
{property: 'clientId', label: 'App Key'},
{property: 'secret', label: 'App Secret'}
];
};
fields: function () {
return [
{property: 'clientId', label: 'App Key'},
{property: 'secret', label: 'App Secret'}
];
}
});