Skip to content

Instantly share code, notes, and snippets.

@koemeet
Created April 28, 2014 11:06
Show Gist options
  • Save koemeet/11368569 to your computer and use it in GitHub Desktop.
Save koemeet/11368569 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Ember block helper</title>
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" />
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script src="http://builds.handlebarsjs.com.s3.amazonaws.com/handlebars-v1.3.0.js"></script>
<script src="http://builds.emberjs.com/release/ember.js"></script>
</head>
<body>
<script type="text/x-handlebars" data-template-name="application">
<div class="navbar navbar-inverse navbar-static-top" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Block Helper</a>
</div>
<div class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li>{{#link-to "index"}}Home{{/link-to}}</li>
<li>{{#link-to "about"}}Try me{{/link-to}}</li>
</ul>
{{block "actions"}}
</div>
</div>
</div>
<div class="container">
{{outlet}}
</div>
</script>
<script type="text/x-handlebars" data-template-name="index">
<p>Hi</p>
<p>As you can see, nothing special is going on here. Navigate to "Try me" and see the block helper in action!</p>
</script>
<script type="text/x-handlebars" data-template-name="about">
{{#block "actions"}}
<form class="navbar-form navbar-left" role="search">
<div class="form-group">
<input type="text" class="form-control" placeholder="Search">
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
{{/block}}
<p>As you can see, the navigation bar has gained a search box! Only by replacing the "actions" block inside this template file. Try to navigate to another route, it will return to it's correct state automatically.</p>
</script>
</body>
</html>
var storage = Ember.Object.create({
blocks: {},
blockCount: function(name) {
if (this.blocks[name]) {
return this.blocks[name].length;
}
return 0;
},
addBlock: function(name, view) {
this.blocks[name] = this.blocks[name] || [];
this.blocks[name].push(view);
this.render(name);
},
removeBlock: function(name, view) {
var index = this.blocks[name].indexOf(view);
this.blocks[name].splice(index, 1);
this.render(name);
},
render: function(block) {
var blocks = this.blocks[block],
template;
block = blocks['0'];
if (blocks.length > 0) {
var lastBlock = blocks[blocks.length - 1];
block.set("template", lastBlock.get("origin.template"));
Ember.run.scheduleOnce("render", function () {
block.set("context", lastBlock.get("origin.context"));
});
}
}
});
Ember.Handlebars.registerHelper('block', function(blockName, options) {
var data = options.data,
context = (options.contexts && options.contexts[0]) || this,
template = options.fn,
currentView = data.view;
// View holding template and context states.
var blockView = Ember.View.create({
origin: {
template: template,
context: context
}
});
// When the parent view is destroyed, remove it's block references from the stack.
currentView.on("willDestroyElement", function() {
storage.removeBlock(blockName, blockView);
});
storage.addBlock(blockName, blockView);
// Only render this block for the first iteration.
if (storage.blockCount(blockName) == 1) {
Ember.Handlebars.helpers.view.call(this, blockView, options);
}
});
App = Ember.Application.create({
LOG_TRANSITIONS: true,
LOG_VIEW_LOOKUPS: true
});
App.Router.map(function() {
this.route('about');
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment