backbone-handlebars 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/Gemfile +16 -0
- data/Guardfile +18 -0
- data/LICENSE.txt +20 -0
- data/README.markdown +58 -0
- data/Rakefile +67 -0
- data/VERSION +1 -0
- data/generators/backbone_view/backbone_view_generator.rb +9 -0
- data/generators/backbone_view/templates/view.coffee.erb +2 -0
- data/generators/backbone_view/templates/view_template.html.handlebars +2 -0
- data/lib/assets/javascripts/handlebars_helpers.coffee +46 -0
- data/lib/assets/javascripts/handlebars_view.coffee +26 -0
- data/lib/backbone-handlebars.rb +5 -0
- data/lib/backbone-handlebars/engine.rb +9 -0
- data/lib/backbone-handlebars/helper.rb +13 -0
- data/lib/generators/backbone/USAGE +8 -0
- data/lib/generators/backbone/backbone_generator.rb +6 -0
- data/rakelib/coffeescript.rake +30 -0
- data/spec/javascripts/fixtures/child_view.handlebars.html +4 -0
- data/spec/javascripts/fixtures/multiple_child_parent_view.handlebars.html +7 -0
- data/spec/javascripts/fixtures/parent_view.handlebars.html +6 -0
- data/spec/javascripts/fixtures/simple_view.handlebars.html +4 -0
- data/spec/javascripts/handlebars_view_spec.coffee +55 -0
- data/spec/javascripts/helpers/SpecHelper.js +9 -0
- data/spec/javascripts/helpers/loadTemplateHelper.js +17 -0
- data/spec/javascripts/jasmine-jquery-1.1.3.js +205 -0
- data/spec/javascripts/jquery.js +167 -0
- data/spec/javascripts/support/jasmine.yml +78 -0
- data/spec/javascripts/support/jasmine_config.rb +23 -0
- data/spec/javascripts/support/jasmine_runner.rb +32 -0
- data/test/helper.rb +18 -0
- data/test/test_backbone-handlebars.rb +7 -0
- data/vendor/assets/javascripts/backbone.js +1066 -0
- data/vendor/assets/javascripts/handlebars.js +1417 -0
- data/vendor/assets/javascripts/underscore.js +748 -0
- metadata +164 -0
data/.document
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
# Add dependencies required to use your gem here.
|
3
|
+
# Example:
|
4
|
+
# gem "activesupport", ">= 2.3.5"
|
5
|
+
|
6
|
+
# Add dependencies to develop your gem here.
|
7
|
+
# Include everything needed to run rake, tests, features, etc.
|
8
|
+
group :development do
|
9
|
+
gem "shoulda", ">= 0"
|
10
|
+
gem "bundler", "~> 1.0.0"
|
11
|
+
gem "jeweler", "~> 1.6.0"
|
12
|
+
gem "rcov", ">= 0"
|
13
|
+
gem "jasmine"
|
14
|
+
gem "coffee-script"
|
15
|
+
gem "guard-coffeescript"
|
16
|
+
end
|
data/Guardfile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# A sample Guardfile
|
2
|
+
# More info at http://github.com/guard/guard#readme
|
3
|
+
#
|
4
|
+
# Guard is a tool to respond to local filesystem events and take action. As such, it works better using native filesystem event libraries
|
5
|
+
#
|
6
|
+
# 1. Setup an RVM 1.9.2 environment to run guard
|
7
|
+
# 2. gem install guard-coffeescript growl rb-fsevent
|
8
|
+
# 3. run the 'guard' command; this fires up a server to monitor the coffescript as shown below
|
9
|
+
# 4. C-\ will force guard to recompile everything it knows about
|
10
|
+
# 5. Install the Gowl "Extras" growlnotify
|
11
|
+
|
12
|
+
guard 'coffeescript', :output => 'javascripts/compiled' do
|
13
|
+
watch(%r{lib/assets/javascripts/.+\.coffee})
|
14
|
+
end
|
15
|
+
|
16
|
+
guard 'coffeescript', :output => 'spec/javascripts/compiled', :bare => true do
|
17
|
+
watch(%r{spec/javascripts/.*_spec\.coffee})
|
18
|
+
end
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011 Chris Nelson
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.markdown
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
handlebone
|
2
|
+
===================
|
3
|
+
|
4
|
+
This gem is extracted out of a backbone project where we are using handlebars
|
5
|
+
templates. It contains:
|
6
|
+
|
7
|
+
* handlebars.js
|
8
|
+
* A HandlebarsView superclass
|
9
|
+
* a rails helper module for rendering all your handlebars templates into your rails view
|
10
|
+
* Some handlebars helpers to make things easier
|
11
|
+
|
12
|
+
Usage
|
13
|
+
=====
|
14
|
+
|
15
|
+
This gem is designed to integrate with the asset pipeline of rails 3.1+. Somewhere in your
|
16
|
+
coffeescript or javascript code you'll need to require it:
|
17
|
+
|
18
|
+
#= require handlebars_view
|
19
|
+
|
20
|
+
This will bring in handlebars and the view superclass. To use it, write a view like so:
|
21
|
+
|
22
|
+
class FooView extends HandlebarsView
|
23
|
+
|
24
|
+
name: "foo_view"
|
25
|
+
|
26
|
+
This will cause the view to look for a template in an element with id "foo_view_template" and use
|
27
|
+
handlebars to render this view, passing in the view's model as the template
|
28
|
+
context. You can change this by overriding the templateContext function in your view.
|
29
|
+
|
30
|
+
HandlebarsHelpers
|
31
|
+
=================
|
32
|
+
|
33
|
+
Some helper methods to make writing those templates easier.
|
34
|
+
|
35
|
+
{{get "property"}}
|
36
|
+
|
37
|
+
This will grab a property from the model that is the current context
|
38
|
+
|
39
|
+
{{#eachProperty "children"}}hi!{{/eachProperty}}
|
40
|
+
|
41
|
+
A block helper that iterates over a property that contains an array.
|
42
|
+
|
43
|
+
Somewhere in your DOM ready, you'll need to call registerHelpers. Like so:
|
44
|
+
|
45
|
+
$ -> Backbone.HandlebarsHelpers.registerHelpers()
|
46
|
+
|
47
|
+
Also, you can register your own helpers by passing an object where each propery is a method that will
|
48
|
+
become a helper
|
49
|
+
|
50
|
+
Backbone.HandlebarsHelpers.registerHelpers(new MyHelpers())
|
51
|
+
|
52
|
+
RenderTemplatesHelper
|
53
|
+
======================
|
54
|
+
|
55
|
+
We've found it best practice to keep our handlebars templates in separate files so our rails
|
56
|
+
views don't get all noisy. This all let's use the same HandleBars view on more than one rails
|
57
|
+
view and in our jasmine specs. This gem also includes a rails helper module RenderTemplatesHelper.
|
58
|
+
Best to just look at the code to see what it does for now, it's super simple.
|
data/Rakefile
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler'
|
5
|
+
begin
|
6
|
+
Bundler.setup(:default, :development)
|
7
|
+
rescue Bundler::BundlerError => e
|
8
|
+
$stderr.puts e.message
|
9
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
10
|
+
exit e.status_code
|
11
|
+
end
|
12
|
+
require 'rake'
|
13
|
+
|
14
|
+
require 'jeweler'
|
15
|
+
Jeweler::Tasks.new do |gem|
|
16
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
17
|
+
gem.name = "backbone-handlebars"
|
18
|
+
gem.homepage = "http://github.com/superchris/backbone-handlebars"
|
19
|
+
gem.license = "MIT"
|
20
|
+
gem.summary = %Q{Backbone views with handlebars templates}
|
21
|
+
gem.description = %Q{That's all folks}
|
22
|
+
gem.email = "superchrisnelson@gmail.com"
|
23
|
+
gem.authors = ["Chris Nelson"]
|
24
|
+
gem.files.include "vendor/assets/**/*"
|
25
|
+
gem.files.include "lib/**/*"
|
26
|
+
# dependencies defined in Gemfile
|
27
|
+
end
|
28
|
+
Jeweler::RubygemsDotOrgTasks.new
|
29
|
+
|
30
|
+
require 'rake/testtask'
|
31
|
+
Rake::TestTask.new(:test) do |test|
|
32
|
+
test.libs << 'lib' << 'test'
|
33
|
+
test.pattern = 'test/**/test_*.rb'
|
34
|
+
test.verbose = true
|
35
|
+
end
|
36
|
+
|
37
|
+
require 'rcov/rcovtask'
|
38
|
+
Rcov::RcovTask.new do |test|
|
39
|
+
test.libs << 'test'
|
40
|
+
test.pattern = 'test/**/test_*.rb'
|
41
|
+
test.verbose = true
|
42
|
+
test.rcov_opts << '--exclude "gems/*"'
|
43
|
+
end
|
44
|
+
|
45
|
+
task :default => :test
|
46
|
+
|
47
|
+
require 'rake/rdoctask'
|
48
|
+
Rake::RDocTask.new do |rdoc|
|
49
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
50
|
+
|
51
|
+
rdoc.rdoc_dir = 'rdoc'
|
52
|
+
rdoc.title = "backbone-handlebars #{version}"
|
53
|
+
rdoc.rdoc_files.include('README*')
|
54
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
55
|
+
end
|
56
|
+
|
57
|
+
begin
|
58
|
+
require 'jasmine'
|
59
|
+
load 'jasmine/tasks/jasmine.rake'
|
60
|
+
rescue LoadError
|
61
|
+
task :jasmine do
|
62
|
+
abort "Jasmine is not available. In order to run jasmine, you must: (sudo) gem install jasmine"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.1
|
@@ -0,0 +1,9 @@
|
|
1
|
+
class BackboneViewGenerator < Rails::Generator::NamedBase
|
2
|
+
|
3
|
+
def manifest
|
4
|
+
record do |m|
|
5
|
+
m.template "view.coffee.erb", "backbone/views/#{name}.coffee", :assigns => {:name => name}
|
6
|
+
m.template "view_template.html.handlebars", "backbone/templates/#{name}.html.handlebars", :assigns => {:name => name}
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
class Backbone.HandlebarsHelpers
|
2
|
+
|
3
|
+
is: (block) ->
|
4
|
+
hash = block.hash
|
5
|
+
block() if this[hash.property] == hash.value
|
6
|
+
|
7
|
+
stripe: (collection, block) ->
|
8
|
+
item_contents = for index in [0...collection.length]
|
9
|
+
collection[index].stripeClass = if ((index % 2) == 0) then "even" else "odd"
|
10
|
+
block collection[index]
|
11
|
+
item_contents.join("\n")
|
12
|
+
|
13
|
+
formatNumber: (number) ->
|
14
|
+
$.formatNumber number, {format: "#,###"}
|
15
|
+
|
16
|
+
formatCurrency: (number) ->
|
17
|
+
$.formatNumber number, {format: "$#,###.00"}
|
18
|
+
|
19
|
+
formatPercentage: (number) ->
|
20
|
+
formatted = $.formatNumber number, {format: "#,###.0000"}
|
21
|
+
"#{formatted}%"
|
22
|
+
|
23
|
+
get: (property)->
|
24
|
+
@get(property)
|
25
|
+
|
26
|
+
helperMissing: -> ""
|
27
|
+
|
28
|
+
eachProperty: (property, block)->
|
29
|
+
block(object) for object in @get(property)
|
30
|
+
|
31
|
+
view: (block) ->
|
32
|
+
params = block.hash
|
33
|
+
view = block.data.view
|
34
|
+
viewClass = eval(params.viewClass)
|
35
|
+
if params.modelClass
|
36
|
+
modelClass = eval(params.modelClass)
|
37
|
+
model = new modelClass(this)
|
38
|
+
else
|
39
|
+
model = this
|
40
|
+
childView = new viewClass(model: model, parent: view)
|
41
|
+
view.subViews.push childView
|
42
|
+
block(model)
|
43
|
+
|
44
|
+
@registerHelpers: (helpers)->
|
45
|
+
helpers or= new HandlebarsHelpers()
|
46
|
+
Handlebars.registerHelper name, helper for name, helper of helpers
|
@@ -0,0 +1,26 @@
|
|
1
|
+
#= require handlebars
|
2
|
+
class Backbone.HandlebarsView extends Backbone.View
|
3
|
+
constructor: (options = {})->
|
4
|
+
@el = $("##{@name}") unless options.el
|
5
|
+
@subViews = []
|
6
|
+
@parent = options.parent
|
7
|
+
super
|
8
|
+
templateEl = $("##{@name}_template")
|
9
|
+
console.log "Did you include the template for #{@name}, putz?" if console? && templateEl.size() == 0
|
10
|
+
@template = if templateEl.size() > 0 then Handlebars.compile(templateEl.html(), true) else -> ""
|
11
|
+
|
12
|
+
templateContext: ->
|
13
|
+
@model
|
14
|
+
|
15
|
+
render: ->
|
16
|
+
@subViews = []
|
17
|
+
@el.html @template @templateContext(), Handlebars.helpers, Handlebars.partials, {view: this}
|
18
|
+
@renderSubView(subView) for subView in @subViews
|
19
|
+
|
20
|
+
findEl: ->
|
21
|
+
@el = $("[data-id='#{@model.id}']")
|
22
|
+
|
23
|
+
renderSubView: (subView) ->
|
24
|
+
subView.findEl()
|
25
|
+
subView.delegateEvents()
|
26
|
+
subView.render()
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module BackboneHandlebars
|
2
|
+
module RenderTemplatesHelper
|
3
|
+
def render_backbone_template(template)
|
4
|
+
raw File.read(::Rails.root.join "app", "assets", "templates", "#{template}.handlebars.html")
|
5
|
+
end
|
6
|
+
|
7
|
+
def render_backbone_templates
|
8
|
+
template_directory = ::Rails.root.join "app", "assets", "templates", "*.handlebars.html"
|
9
|
+
templates = Dir.glob(template_directory).collect { |t| File.read t }
|
10
|
+
raw templates.join("\n")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
namespace :coffeescript do
|
2
|
+
|
3
|
+
def compile_files(files, output_dir)
|
4
|
+
require 'coffee-script'
|
5
|
+
files.each do |f|
|
6
|
+
new_f = File.join(output_dir, f.pathmap("%n").match(/^([^.]+)/).to_s + ".js")
|
7
|
+
File.open(new_f, "w") do |out|
|
8
|
+
puts "compiling #{f} to #{new_f}"
|
9
|
+
out.puts CoffeeScript.compile File.read(f)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
namespace :compile do
|
15
|
+
desc "re-compile the coffeescript into javascript"
|
16
|
+
task :assets do
|
17
|
+
coffee_files = FileList["lib/assets/javascripts/*.coffee" ]
|
18
|
+
mkdir_p "javascripts/compiled"
|
19
|
+
compile_files(coffee_files, "javascripts/compiled")
|
20
|
+
end
|
21
|
+
|
22
|
+
desc "re-compile the spec coffeescript into javascript"
|
23
|
+
task :specs do
|
24
|
+
mkdir_p "spec/javascripts/compiled"
|
25
|
+
compile_files(FileList["spec/javascripts/*.coffee"], "spec/javascripts/compiled")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
task :compile => ["compile:assets", "compile:specs"]
|
30
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
|
2
|
+
class SimpleView extends Backbone.HandlebarsView
|
3
|
+
name: "simple_view"
|
4
|
+
|
5
|
+
class window.ParentView extends Backbone.HandlebarsView
|
6
|
+
name: "parent_view"
|
7
|
+
|
8
|
+
class window.ChildView extends Backbone.HandlebarsView
|
9
|
+
name: "child_view"
|
10
|
+
findEl: -> @el = $("#child")
|
11
|
+
|
12
|
+
class window.MultipleChildParentView extends Backbone.HandlebarsView
|
13
|
+
name: "multiple_child_parent_view"
|
14
|
+
|
15
|
+
class window.SimpleModel extends Backbone.Model
|
16
|
+
|
17
|
+
describe "HandlebarsView", ->
|
18
|
+
beforeEach ->
|
19
|
+
Backbone.HandlebarsHelpers.registerHelpers()
|
20
|
+
describe "SimpleView", ->
|
21
|
+
beforeEach ->
|
22
|
+
setFixtures "<div id='simple_view'></div>"
|
23
|
+
loadTemplate "simple_view.handlebars.html"
|
24
|
+
@simpleView = new SimpleView(model: new SimpleModel(foo: "bar"))
|
25
|
+
@simpleView.render()
|
26
|
+
it "finds it's el", ->
|
27
|
+
expect(@simpleView.el).toExist()
|
28
|
+
it "can render model data", ->
|
29
|
+
expect(@simpleView.el.html()).toMatch /bar/
|
30
|
+
|
31
|
+
describe "subviews", ->
|
32
|
+
beforeEach ->
|
33
|
+
setFixtures "<div id='parent_view'></div>"
|
34
|
+
loadTemplate "parent_view.handlebars.html"
|
35
|
+
loadTemplate "child_view.handlebars.html"
|
36
|
+
@parentView = new ParentView(model: new SimpleModel(id: 1))
|
37
|
+
@parentView.render()
|
38
|
+
it "renders the child template too", ->
|
39
|
+
expect(@parentView.el.html()).toMatch /Foo/
|
40
|
+
it "has a child view as a subviews", ->
|
41
|
+
expect(@parentView.subViews.length).toEqual(1)
|
42
|
+
|
43
|
+
describe "multiple child views", ->
|
44
|
+
beforeEach ->
|
45
|
+
setFixtures "<div id='multiple_child_parent_view'></div>"
|
46
|
+
loadTemplate "multiple_child_parent_view.handlebars.html"
|
47
|
+
loadTemplate "simple_view.handlebars.html"
|
48
|
+
children = [new SimpleModel(id: 1, foo: "baz"), new SimpleModel(id: 2, foo: "bing")]
|
49
|
+
@multipleChildParentView = new MultipleChildParentView(model: new SimpleModel(children: children))
|
50
|
+
@multipleChildParentView.render()
|
51
|
+
it "renders children views", ->
|
52
|
+
expect(@multipleChildParentView.el.html()).toMatch /baz/
|
53
|
+
expect(@multipleChildParentView.el.html()).toMatch /bing/
|
54
|
+
|
55
|
+
|