backbone-handlebars 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
|