mirror of
https://github.com/meteor/meteor.git
synced 2026-05-02 03:01:46 -04:00
First pass of template-level API extensions
Untested, but a demo is in the works
This commit is contained in:
1
examples/landmark-demo/.meteor/.gitignore
vendored
Normal file
1
examples/landmark-demo/.meteor/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
local
|
||||
6
examples/landmark-demo/.meteor/packages
Normal file
6
examples/landmark-demo/.meteor/packages
Normal file
@@ -0,0 +1,6 @@
|
||||
# Meteor packages used by this project, one per line.
|
||||
#
|
||||
# 'meteor add' and 'meteor remove' will edit this file for you,
|
||||
# but you can also edit it by hand.
|
||||
|
||||
autopublish
|
||||
53
examples/landmark-demo/client/landmark-demo.js
Normal file
53
examples/landmark-demo/client/landmark-demo.js
Normal file
@@ -0,0 +1,53 @@
|
||||
Timers = new Meteor.Collection(null);
|
||||
|
||||
if (! Session.get("x")) {
|
||||
Session.set("x", 1);
|
||||
}
|
||||
|
||||
if (! Session.get("y")) {
|
||||
Session.set("y", 1);
|
||||
}
|
||||
|
||||
if (! Session.get("z")) {
|
||||
Session.set("z", 1);
|
||||
}
|
||||
|
||||
Template.redrawButtons.events = {
|
||||
'click input.x': function () {
|
||||
Session.set("x", Session.get("x") + 1);
|
||||
},
|
||||
|
||||
'click input.y': function () {
|
||||
Session.set("y", Session.get("y") + 1);
|
||||
},
|
||||
|
||||
'click input.z': function () {
|
||||
Session.set("z", Session.get("z") + 1);
|
||||
}
|
||||
};
|
||||
|
||||
Template.preserveDemo.preserve = [ '.input' ];
|
||||
|
||||
Template.preserveDemo.x =
|
||||
Template.constantDemo.x =
|
||||
Template.stateDemo.x =
|
||||
function () {
|
||||
return Session.get("x");
|
||||
};
|
||||
|
||||
|
||||
Template.stateDemo.events = {
|
||||
'click .create': function () {
|
||||
Timers.insert({});
|
||||
}
|
||||
};
|
||||
|
||||
Template.stateDemo.timers = function () {
|
||||
return Timers.find();
|
||||
};
|
||||
|
||||
Template.timer.events = {
|
||||
'click .delete': function () {
|
||||
Timers.remove(this._id);
|
||||
}
|
||||
};
|
||||
1
examples/landmark-demo/landmark-demo.css
Normal file
1
examples/landmark-demo/landmark-demo.css
Normal file
@@ -0,0 +1 @@
|
||||
/* CSS declarations go here */
|
||||
60
examples/landmark-demo/landmark-demo.html
Normal file
60
examples/landmark-demo/landmark-demo.html
Normal file
@@ -0,0 +1,60 @@
|
||||
<head>
|
||||
<title>landmark-demo</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Landmark demo</h1>
|
||||
{{> redrawButtons }}
|
||||
{{> preserveDemo }}
|
||||
<!--{{> constantDemo }} -->
|
||||
{{> stateDemo }}
|
||||
</body>
|
||||
|
||||
<template name="redrawButtons">
|
||||
<input type="button" value="X++" class="x">
|
||||
<input type="button" value="Y++" class="y">
|
||||
<input type="button" value="Z++" class="z">
|
||||
<br>
|
||||
</template>
|
||||
|
||||
<template name="preserveDemo">
|
||||
<h2>Simple element preservation</h2>
|
||||
X={{x}}<br>
|
||||
<input type="text"><br>
|
||||
X={{x}}
|
||||
</template>
|
||||
|
||||
<template name="constantDemo">
|
||||
<h2>Constant regions</h2>
|
||||
X={{x}}<br>
|
||||
{{#constant}}
|
||||
<div style="float: left; padding-right: 20px;">
|
||||
<iframe width="200" height="200" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" src="https://maps.google.com/maps?f=q&source=s_q&hl=en&geocode=&q=140+10th+Street,+San+Francisco,+CA&aq=0&oq=140+10th+s&sll=37.7577,-122.4376&sspn=0.166931,0.329247&ie=UTF8&hq=&hnear=140+10th+St,+San+Francisco,+California+94103&t=m&ll=37.774921,-122.415419&spn=0.013569,0.017252&z=14&iwloc=A&output=embed"></iframe><br /><small><a href="https://maps.google.com/maps?f=q&source=embed&hl=en&geocode=&q=140+10th+Street,+San+Francisco,+CA&aq=0&oq=140+10th+s&sll=37.7577,-122.4376&sspn=0.166931,0.329247&ie=UTF8&hq=&hnear=140+10th+St,+San+Francisco,+California+94103&t=m&ll=37.774921,-122.415419&spn=0.013569,0.017252&z=14&iwloc=A" style="color:#0000FF;text-align:left">View Larger Map</a></small>
|
||||
</div>
|
||||
{{/constant}}
|
||||
{{#constant}}
|
||||
<div>
|
||||
<iframe width="200" height="200" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" src="https://maps.google.com/maps?f=q&source=s_q&hl=en&geocode=&q=880+Harrison+Street,+San+Francisco,+CA&aq=0&oq=880+harrison&sll=37.7577,-122.4376&sspn=0.166931,0.329247&ie=UTF8&hq=&hnear=880+Harrison+St,+San+Francisco,+California+94107&t=m&ll=37.779534,-122.411213&spn=0.013568,0.01708&z=14&iwloc=A&output=embed"></iframe><br /><small><a href="https://maps.google.com/maps?f=q&source=embed&hl=en&geocode=&q=880+Harrison+Street,+San+Francisco,+CA&aq=0&oq=880+harrison&sll=37.7577,-122.4376&sspn=0.166931,0.329247&ie=UTF8&hq=&hnear=880+Harrison+St,+San+Francisco,+California+94107&t=m&ll=37.779534,-122.411213&spn=0.013568,0.01708&z=14&iwloc=A" style="color:#0000FF;text-align:left">View Larger Map</a></small>
|
||||
</div>
|
||||
{{/constant}}
|
||||
X={{x}}
|
||||
</template>
|
||||
|
||||
<template name="stateDemo">
|
||||
<h2>Template callbacks</h2>
|
||||
X={{x}}<br>
|
||||
<input type="button" value="Create a timer" class="create"><br>
|
||||
{{#each timers}}
|
||||
<div>
|
||||
{{> timer}}
|
||||
Y={{y}}
|
||||
</div>
|
||||
{{/each}}
|
||||
X={{x}}
|
||||
</template>
|
||||
|
||||
<template name="timer">
|
||||
<span class="elapsed"></span>
|
||||
<input type="button" value="Delete" class="delete">
|
||||
Z={{z}}
|
||||
</template>
|
||||
@@ -21,10 +21,11 @@ Handlebars.json_ast_to_func = function (ast) {
|
||||
//
|
||||
// partials take one argument, data
|
||||
|
||||
// XXX handlebars' format for arguments is stupid. eg, options ===
|
||||
// options.fn. plow this stuff under. treat block arguments (fn,
|
||||
// inverse) as just another kind of argument, same as what is passed
|
||||
// in via named arguments.
|
||||
// XXX handlebars' format for arguments is not the clearest, likely
|
||||
// for backwards compatibility to mustache. eg, options ===
|
||||
// options.fn. take the opportunity to clean this up. treat block
|
||||
// arguments (fn, inverse) as just another kind of argument, same as
|
||||
// what is passed in via named arguments.
|
||||
Handlebars._default_helpers = {
|
||||
'with': function (data, options) {
|
||||
return options.fn(data);
|
||||
|
||||
@@ -27,11 +27,23 @@
|
||||
);
|
||||
};
|
||||
|
||||
Handlebars._default_helpers.constant = function(options) {
|
||||
// XXX
|
||||
};
|
||||
_.extend(Handlebars._default_helpers, {
|
||||
isolate: function (options) {
|
||||
return Spark.isolate(function () {
|
||||
return options.fn(this);
|
||||
});
|
||||
},
|
||||
constant: function (options) {
|
||||
return Spark.createLandmark({ constant: true }, function () {
|
||||
return options.fn(this);
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// map from landmark id, to the 'this' object for
|
||||
// create/render/destroy callbacks on templates
|
||||
var templateInstanceData = {};
|
||||
|
||||
Meteor._def_template = function (name, raw_func) {
|
||||
Meteor._hook_handlebars();
|
||||
@@ -44,23 +56,42 @@
|
||||
// on which invocation of the partial this is.
|
||||
var partial = function (data, branch) {
|
||||
return Spark.labelBranch(branch, function () {
|
||||
var html = Spark.isolate(function() {
|
||||
return raw_func(data, {
|
||||
helpers: partial,
|
||||
partials: Meteor._partials,
|
||||
name: name
|
||||
});
|
||||
});
|
||||
var tmpl = name && Template[name] || {};
|
||||
|
||||
var t = name && Template[name];
|
||||
if (t) {
|
||||
html = Spark.attachEvents(t.events || {}, html);
|
||||
html = Spark.createLandmark(
|
||||
{ preserve: t.preserve || {} },
|
||||
// XXX actually, we need to make this landmark available
|
||||
// to Forms and execute the template here.
|
||||
function(landmark) { return html; });
|
||||
}
|
||||
var html = Spark.createLandmark({
|
||||
preserve: tmpl.preserve || {},
|
||||
create: function () {
|
||||
templateInstanceData[this.id] = {};
|
||||
tmpl.create &&
|
||||
tmpl.create.call(templateInstanceData[this.id]);
|
||||
},
|
||||
render: function () {
|
||||
tmpl.render &&
|
||||
tmpl.render.call(templateInstanceData[this.id], this);
|
||||
},
|
||||
destroy: function () {
|
||||
tmpl.destroy &&
|
||||
tmpl.destroy.call(templateInstanceData[this.id]);
|
||||
delete templateInstanceData[this.id];
|
||||
}
|
||||
}, function (landmark) {
|
||||
var html = Spark.isolate(function () {
|
||||
// XXX Forms needs to run a hook before and after raw_func
|
||||
// (and receive 'landmark')
|
||||
return raw_func(data, {
|
||||
helpers: partial,
|
||||
partials: Meteor._partials,
|
||||
name: name
|
||||
});
|
||||
});
|
||||
|
||||
// events need to be inside the landmark, not outside, so
|
||||
// that when an event fires, you can retrieve the enclosing
|
||||
// landmark to get the template data
|
||||
if (tmpl.events)
|
||||
html = Spark.attachEvents(tmpl.events, html);
|
||||
return html;
|
||||
});
|
||||
|
||||
html = Spark.setDataContext(data, html);
|
||||
return html;
|
||||
|
||||
Reference in New Issue
Block a user