sinatra-js 0.1.5

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 ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,23 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+ doc
21
+
22
+ ## PROJECT::SPECIFIC
23
+ spec/fixtures/public/system
data/CHANGES ADDED
@@ -0,0 +1,4 @@
1
+
2
+ rel 0.1.0 (2010-03-03)
3
+
4
+ * initial release
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 kematzy
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.rdoc ADDED
@@ -0,0 +1,265 @@
1
+ = Sinatra::JS
2
+
3
+ A Sinatra Extension that makes working with JS easy.
4
+
5
+
6
+
7
+ == Installation
8
+
9
+ # Add RubyGems.org (former Gemcutter) to your RubyGems sources
10
+ $ gem sources -a http://rubygems.org
11
+
12
+ $ (sudo)? gem install sinatra-js
13
+
14
+ == Dependencies
15
+
16
+ This Gem depends upon the following:
17
+
18
+ === Runtime:
19
+
20
+ * sinatra ( >= 1.0.a )
21
+ * sinatra-tags[http://github.com/kematzy/sinatra-tags] ( >= 0.1.0 )
22
+ * sinatra-outputbuffer[http://github.com/kematzy/sinatra-outputbuffer] ( >= 0.1.0 )
23
+ * sinatra-basics[http://github.com/kematzy/sinatra-basics] ( >= 0.5.0 )
24
+
25
+ Optionals:
26
+
27
+ * sinatra-settings[http://github.com/kematzy/sinatra-settings] (>= 0.1.1) # to view default settings in a browser display.
28
+ * sinatra-logger[http://github.com/kematzy/sinatra-logger] (>= 0.1.0) # to capture error messages in the log file.
29
+
30
+
31
+ === Development & Tests:
32
+
33
+ * sinatra-tests (>= 0.1.6)
34
+ * rspec (>= 1.3.0 )
35
+ * rack-test (>= 0.5.3)
36
+ * rspec_hpricot_matchers (>= 0.1.0)
37
+
38
+
39
+ == Getting Started
40
+
41
+ To start using Sinatra::JS, just require and register the extension in your App...
42
+
43
+ require 'sinatra/js'
44
+
45
+ class YourApp < Sinatra::Base
46
+ register(Sinatra::JS)
47
+
48
+ <snip...>
49
+
50
+ end
51
+
52
+
53
+ You then get access to 6 useful helper methods:
54
+
55
+
56
+ === <tt>js() / javascript()</tt>
57
+
58
+ This method serves two purposes:
59
+
60
+ a) Return a stylesheet <tt><script src=""></script></tt> tag with the <tt>path</tt> given.
61
+
62
+ js('jquery') # =>
63
+
64
+ <script src="/jquery.js" type="text/javascript" charset="utf-8"></script>
65
+
66
+ js('/js/jquery-tools.js') # =>
67
+
68
+ <script src="/js/jquery-tools.js" type="text/javascript" charset="utf-8"></script>
69
+
70
+
71
+ You can even pass an array of files to the method, which then outputs the <tt><script></tt>
72
+ tags for each file.
73
+
74
+ js( ['/js/jquery.js', '/js/jquery.ui'] ) # =>
75
+
76
+ <script src="/js/jquery.js" type="text/javascript" charset="utf-8"></script>
77
+ <script src="/js/jquery.ui.js" type="text/javascript" charset="utf-8"></script>
78
+
79
+
80
+
81
+ b) When passed a *block*, a <tt><script></tt> tag will be created with the yielded block
82
+ as its contents.
83
+
84
+ js do
85
+ "document.write('hi');"
86
+ end
87
+ # =>
88
+
89
+ <script type="text/javascript" charset="utf-8">
90
+ document.write('hi');
91
+ </script>
92
+
93
+
94
+ === <tt>js_custom() & js_custom_add()</tt>
95
+
96
+ These two methods works together, like this:
97
+
98
+ First you add the <tt>js_custom()</tt> method to your layout(s) (../views/layout.erb):
99
+
100
+ <html>
101
+ <head>
102
+ <snip...>
103
+
104
+ <%= js_custom %>
105
+
106
+ </head>
107
+
108
+
109
+
110
+ Then in your views, you can use the <tt>js_custom_add()</tt> method to add custom JS
111
+ to the page, like this:
112
+
113
+ # in ../views/template.erb
114
+ <%= js_custom_add( "window.alert('this works');" )
115
+
116
+ # in ../views/shared/sidebar.erb
117
+ <%= js_custom_add( "document.write('this also works');" )
118
+
119
+
120
+ Which outputs the following in the <tt><head></tt> element of your page.
121
+
122
+ <html>
123
+ <head>
124
+ <snip...>
125
+
126
+ <script type="text/javascript" charset="utf-8">
127
+ window.alert('this works');
128
+ document.write('this also works');
129
+ </script>
130
+
131
+
132
+ This functionality makes it very easy to add special JS functionality to any page,
133
+ even from within multiple views.
134
+
135
+
136
+ === <tt>js_custom_files() & js_custom_add_file()</tt>
137
+
138
+ These two methods also works together in a similar fashion, like this:
139
+
140
+ First of, add the <tt>js_custom_files()</tt> method to your layout(s) (../views/layout.erb):
141
+
142
+ <html>
143
+ <head>
144
+ <snip...>
145
+
146
+ <%= js_custom_files %>
147
+
148
+ </head>
149
+
150
+
151
+ Then in your views, you can use the <tt>js_custom_add_file()</tt> method to add a custom JS
152
+ file to the page, like this:
153
+
154
+ <%= js_custom_add_file('home') #=>
155
+
156
+ <script src="/home.js" type="text/javascript" charset="utf-8"></script>
157
+
158
+
159
+ You can also use the method to embed the content of a .js file into the <tt><head></tt>
160
+ part of any page, like this:
161
+
162
+ # NB! path is starting from APP_ROOT/public/
163
+
164
+ js_custom_add_file('home.js',:insert_into_html) #=>
165
+
166
+ <html>
167
+ <head>
168
+ <snip...>
169
+
170
+ <script type="text/javascript" charset="utf-8">
171
+ // the contents of ../public/home.js
172
+ </script>
173
+
174
+
175
+ You can even give a file system path to embed the content of a globaly shared .js file
176
+ outside of your applications path. Providing an easy way to resuse common snippets of code.
177
+
178
+
179
+ # NB! make sure the path and .js file works together as a real path.
180
+
181
+ # the :path value should always be a directory without the trailing slash.
182
+
183
+ js_custom_add_file('win.open.js',:insert_into_html, '/path/2/some/directory')
184
+
185
+
186
+ <html>
187
+ <head>
188
+ <snip...>
189
+
190
+ <script type="text/javascript" charset="utf-8">
191
+ // the contents of /path/2/some/directory/win.open.js
192
+ </script>
193
+
194
+
195
+
196
+ === <tt>js_insert_file()</tt>
197
+
198
+ This is a simple convenicence method that takes a path to a JS file
199
+ and inserts its content straight into the current view, without any enclosing HTML tags.
200
+
201
+ The method depends upon the settings of the <tt>:js_shared_source_files_dir</tt>
202
+ configuration variable defined inside your application.
203
+ By default this is set to <tt>'ENV['HOME']/.alt/js'</tt>.
204
+
205
+ An example of how to use this functionality:
206
+
207
+ # in your app's routes configurations
208
+
209
+ get('/js/app.js') do
210
+ content_type 'text/javascript'
211
+ erb('js/app'.to_sym, :layout => false)
212
+ end
213
+
214
+
215
+ # in views/js/app.erb
216
+
217
+ <%= js_insert_file('jquery') %>
218
+
219
+ # => insert the contents of ENV['HOME']/.alt/js/jquery.js
220
+
221
+
222
+ You can also load and insert local files, ie files in your app's <tt>public/js/</tt> directory
223
+ by adding the <tt>:local</tt> flag to the call.
224
+
225
+ <%= js_insert_file('tweets', :local) %>
226
+
227
+ # => insert the contents of /path/2/your/app/public/js/tweets.js
228
+
229
+
230
+
231
+ == RTFM
232
+
233
+ If the above is not clear enough, please check the Specs for a better understanding.
234
+
235
+
236
+ == Errors / Bugs
237
+
238
+ If something is not behaving intuitively, it is a bug, and should be reported.
239
+ Report it here: http://github.com/kematzy/sinatra-js/issues
240
+
241
+
242
+ == TODOs
243
+
244
+ * Keep it up to date with any changes in Sinatra.
245
+
246
+ * Add bundle functionality from Sinatra::Bundles gem.
247
+
248
+ * Improve the specs a bit and add missing tests.
249
+
250
+ * Any other improvements I or You can think of.
251
+
252
+
253
+ == Note on Patches/Pull Requests
254
+
255
+ * Fork the project.
256
+ * Make your feature addition or bug fix.
257
+ * Add tests for it. This is important so I don't break it in a future version unintentionally.
258
+ * Commit, do not mess with rakefile, version, or history.
259
+ * (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
260
+ * Send me a pull request. Bonus points for topic branches.
261
+
262
+ == Copyright
263
+
264
+ Copyright (c) 2010 kematzy. See LICENSE for details.
265
+
data/Rakefile ADDED
@@ -0,0 +1,91 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "sinatra-js"
8
+ gem.summary = %Q{A Sinatra Extension that makes working with JS easy.}
9
+ gem.description = %Q{A Sinatra Extension that makes working with JS easy.}
10
+ gem.email = "kematzy@gmail.com"
11
+ gem.homepage = "http://github.com/kematzy/sinatra-js"
12
+ gem.authors = ["kematzy"]
13
+ gem.add_dependency "sinatra", ">= 1.0"
14
+ gem.add_dependency "sinatra-tags"
15
+ gem.add_dependency "sinatra-assets"
16
+ gem.add_development_dependency "sinatra-tests", ">= 0.1.6"
17
+ gem.add_development_dependency "rspec", ">= 1.3.0"
18
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
19
+ end
20
+ Jeweler::GemcutterTasks.new
21
+ rescue LoadError
22
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
23
+ end
24
+
25
+ require 'spec/rake/spectask'
26
+ Spec::Rake::SpecTask.new(:spec) do |spec|
27
+ spec.libs << 'lib' << 'spec'
28
+ spec.spec_opts = ["--color", "--format", "specdoc", "--require", "spec/spec_helper.rb"]
29
+ spec.spec_files = FileList['spec/**/*_spec.rb']
30
+ end
31
+
32
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
33
+ spec.libs << 'lib' << 'spec'
34
+ spec.spec_opts = ["--color", "--format", "specdoc", "--require", "spec/spec_helper.rb"]
35
+ spec.pattern = 'spec/**/*_spec.rb'
36
+ spec.rcov = true
37
+ end
38
+
39
+ namespace :spec do
40
+
41
+ desc "Run all specifications quietly"
42
+ Spec::Rake::SpecTask.new(:quiet) do |t|
43
+ t.libs << "lib"
44
+ t.spec_opts = ["--color", "--require", "spec/spec_helper.rb"]
45
+ end
46
+
47
+ desc "Run specific spec verbosely (SPEC=/path/2/file)"
48
+ Spec::Rake::SpecTask.new(:select) do |t|
49
+ t.libs << "lib"
50
+ t.spec_files = [ENV["SPEC"]]
51
+ t.spec_opts = ["--color", "--format", "specdoc", "--require", "spec/spec_helper.rb"]
52
+ end
53
+
54
+ end
55
+
56
+ task :spec => :check_dependencies
57
+
58
+ task :default => :spec
59
+
60
+ require 'rake/rdoctask'
61
+ Rake::RDocTask.new do |rdoc|
62
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
63
+
64
+ rdoc.rdoc_dir = 'rdoc'
65
+ rdoc.title = "Sinatra::JS #{version}"
66
+ rdoc.rdoc_files.include('README*')
67
+ rdoc.rdoc_files.include('lib/**/*.rb')
68
+ end
69
+
70
+ desc 'Build the rdoc HTML Files'
71
+ task :docs do
72
+ version = File.exist?('VERSION') ? IO.read('VERSION').chomp : "[Unknown]"
73
+
74
+ sh "sdoc -N --title 'Sinatra::JS v#{version}' lib/ README.rdoc"
75
+ end
76
+
77
+ namespace :docs do
78
+
79
+ desc 'Remove rdoc products'
80
+ task :remove => [:clobber_rdoc]
81
+
82
+ desc 'Force a rebuild of the RDOC files'
83
+ task :rebuild => [:rerdoc]
84
+
85
+ desc 'Build docs, and open in browser for viewing (specify BROWSER)'
86
+ task :open => [:docs] do
87
+ browser = ENV["BROWSER"] || "safari"
88
+ sh "open -a #{browser} doc/index.html"
89
+ end
90
+
91
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.5
data/lib/sinatra/js.rb ADDED
@@ -0,0 +1,564 @@
1
+
2
+ require 'sinatra/base'
3
+ require 'sinatra/tags'
4
+ require 'sinatra/assets'
5
+
6
+ module Tilt
7
+
8
+ ## RJS (RubyJS) support, piggy-backing onto the ERBTemplate
9
+ # so that we can use <% %> tags with Ruby code inside the .rjs file
10
+ register 'rjs', ERBTemplate
11
+
12
+ end #/module Tilt
13
+
14
+ module Sinatra
15
+
16
+ module Templates
17
+
18
+ ## add support for .rjs
19
+ def rjs(template, options={}, locals={})
20
+ options[:outvar] = '@_out_buf'
21
+ options[:layout] = false
22
+ render :rjs, template, options, locals
23
+ end
24
+
25
+ end #/module Templates
26
+
27
+ # = Sinatra::JS
28
+ #
29
+ # A Sinatra Extension that makes working with JS easy.
30
+ #
31
+ #
32
+ #
33
+ # == Installation
34
+ #
35
+ # # Add RubyGems.org (former Gemcutter) to your RubyGems sources
36
+ # $ gem sources -a http://rubygems.org
37
+ #
38
+ # $ (sudo)? gem install sinatra-js
39
+ #
40
+ # == Dependencies
41
+ #
42
+ # This Gem depends upon the following:
43
+ #
44
+ # === Runtime:
45
+ #
46
+ # * sinatra ( >= 1.0.a )
47
+ # * sinatra-tags[http://github.com/kematzy/sinatra-tags] ( >= 0.1.0 )
48
+ # * sinatra-outputbuffer[http://github.com/kematzy/sinatra-outputbuffer] ( >= 0.1.0 )
49
+ # * sinatra-basics[http://github.com/kematzy/sinatra-basics] ( >= 0.5.0 )
50
+ #
51
+ # Optionals:
52
+ #
53
+ # * sinatra-settings[http://github.com/kematzy/sinatra-settings] (>= 0.1.1) # to view default settings in a browser display.
54
+ # * sinatra-logger[http://github.com/kematzy/sinatra-logger] (>= 0.1.0) # to capture error messages in the log file.
55
+ #
56
+ #
57
+ # === Development & Tests:
58
+ #
59
+ # * sinatra-tests (>= 0.1.6)
60
+ # * rspec (>= 1.3.0 )
61
+ # * rack-test (>= 0.5.3)
62
+ # * rspec_hpricot_matchers (>= 0.1.0)
63
+ #
64
+ #
65
+ # == Getting Started
66
+ #
67
+ # To start using Sinatra::JS, just require and register the extension in your App...
68
+ #
69
+ # require 'sinatra/js'
70
+ #
71
+ # class YourApp < Sinatra::Base
72
+ # register(Sinatra::JS)
73
+ #
74
+ # <snip...>
75
+ #
76
+ # end
77
+ #
78
+ #
79
+ # You then get access to 6 useful helper methods:
80
+ #
81
+ #
82
+ # === <tt>js() / javascript()</tt>
83
+ #
84
+ # This method serves two purposes:
85
+ #
86
+ # a) Return a stylesheet <tt><script src=""></script></tt> tag with the <tt>path</tt> given.
87
+ #
88
+ # js('jquery') # =>
89
+ #
90
+ # <script src="/jquery.js" type="text/javascript" charset="utf-8"></script>
91
+ #
92
+ # js('/js/jquery-tools.js') # =>
93
+ #
94
+ # <script src="/js/jquery-tools.js" type="text/javascript" charset="utf-8"></script>
95
+ #
96
+ #
97
+ # You can even pass an array of files to the method, which then outputs the <tt><script></tt>
98
+ # tags for each file.
99
+ #
100
+ # js( ['/js/jquery.js', '/js/jquery.ui'] ) # =>
101
+ #
102
+ # <script src="/js/jquery.js" type="text/javascript" charset="utf-8"></script>
103
+ # <script src="/js/jquery.ui.js" type="text/javascript" charset="utf-8"></script>
104
+ #
105
+ #
106
+ #
107
+ # b) When passed a *block*, a <tt><script></tt> tag will be created with the yielded block
108
+ # as its contents.
109
+ #
110
+ # js do
111
+ # "document.write('hi');"
112
+ # end
113
+ # # =>
114
+ #
115
+ # <script type="text/javascript" charset="utf-8">
116
+ # document.write('hi');
117
+ # </script>
118
+ #
119
+ #
120
+ # === <tt>js_custom() & js_custom_add()</tt>
121
+ #
122
+ # These two methods works together, like this:
123
+ #
124
+ # First you add the <tt>js_custom()</tt> method to your layout(s) (../views/layout.erb):
125
+ #
126
+ # <html>
127
+ # <head>
128
+ # <snip...>
129
+ #
130
+ # <%= js_custom %>
131
+ #
132
+ # </head>
133
+ #
134
+ #
135
+ #
136
+ # Then in your views, you can use the <tt>js_custom_add()</tt> method to add custom JS
137
+ # to the page, like this:
138
+ #
139
+ # # in ../views/template.erb
140
+ # <%= js_custom_add( "window.alert('this works');" )
141
+ #
142
+ # # in ../views/shared/sidebar.erb
143
+ # <%= js_custom_add( "document.write('this also works');" )
144
+ #
145
+ #
146
+ # Which outputs the following in the <tt><head></tt> element of your page.
147
+ #
148
+ # <html>
149
+ # <head>
150
+ # <snip...>
151
+ #
152
+ # <script type="text/javascript" charset="utf-8">
153
+ # window.alert('this works');
154
+ # document.write('this also works');
155
+ # </script>
156
+ #
157
+ #
158
+ # This functionality makes it very easy to add special JS functionality to any page,
159
+ # even from within multiple views.
160
+ #
161
+ #
162
+ # === <tt>js_custom_files() & js_custom_add_file()</tt>
163
+ #
164
+ # These two methods also works together in a similar fashion, like this:
165
+ #
166
+ # First of, add the <tt>js_custom_files()</tt> method to your layout(s) (../views/layout.erb):
167
+ #
168
+ # <html>
169
+ # <head>
170
+ # <snip...>
171
+ #
172
+ # <%= js_custom_files %>
173
+ #
174
+ # </head>
175
+ #
176
+ #
177
+ # Then in your views, you can use the <tt>js_custom_add_file()</tt> method to add a custom JS
178
+ # file to the page, like this:
179
+ #
180
+ # <%= js_custom_add_file('home') #=>
181
+ #
182
+ # <script src="/home.js" type="text/javascript" charset="utf-8"></script>
183
+ #
184
+ #
185
+ # You can also use the method to embed the content of a .js file into the <tt><head></tt>
186
+ # part of any page, like this:
187
+ #
188
+ # # NB! path is starting from APP_ROOT/public/
189
+ #
190
+ # js_custom_add_file('home.js',:insert_into_html) #=>
191
+ #
192
+ # <html>
193
+ # <head>
194
+ # <snip...>
195
+ #
196
+ # <script type="text/javascript" charset="utf-8">
197
+ # // the contents of ../public/home.js
198
+ # </script>
199
+ #
200
+ #
201
+ # You can even give a file system path to embed the content of a globaly shared .js file
202
+ # outside of your applications path. Providing an easy way to resuse common snippets of code.
203
+ #
204
+ #
205
+ # # NB! make sure the path and .js file works together as a real path.
206
+ #
207
+ # # the :path value should always be a directory without the trailing slash.
208
+ #
209
+ # js_custom_add_file('win.open.js',:insert_into_html, '/path/2/some/directory')
210
+ #
211
+ #
212
+ # <html>
213
+ # <head>
214
+ # <snip...>
215
+ #
216
+ # <script type="text/javascript" charset="utf-8">
217
+ # // the contents of /path/2/some/directory/win.open.js
218
+ # </script>
219
+ #
220
+ #
221
+ #
222
+ # === <tt>js_insert_file()</tt>
223
+ #
224
+ # This is a simple convenicence method that takes a path to a JS file
225
+ # and inserts its content straight into the current view, without any enclosing HTML tags.
226
+ #
227
+ # The method depends upon the settings of the <tt>:js_shared_source_files_dir</tt>
228
+ # configuration variable defined inside your application.
229
+ # By default this is set to <tt>'ENV['HOME']/.alt/js'</tt>.
230
+ #
231
+ # An example of how to use this functionality:
232
+ #
233
+ # # in your app's routes configurations
234
+ #
235
+ # get('/js/app.js') do
236
+ # content_type 'text/javascript'
237
+ # erb('js/app'.to_sym, :layout => false)
238
+ # end
239
+ #
240
+ #
241
+ # # in views/js/app.erb
242
+ #
243
+ # <%= js_insert_file('jquery') %>
244
+ #
245
+ # # => insert the contents of ENV['HOME']/.alt/js/jquery.js
246
+ #
247
+ #
248
+ # You can also load and insert local files, ie files in your app's <tt>public/js/</tt> directory
249
+ # by adding the <tt>:local</tt> flag to the call.
250
+ #
251
+ # <%= js_insert_file('tweets', :local) %>
252
+ #
253
+ # # => insert the contents of /path/2/your/app/public/js/tweets.js
254
+ #
255
+ #
256
+ # == TODOs
257
+ #
258
+ # * Keep it up to date with any changes in Sinatra.
259
+ #
260
+ # * Add bundle functionality from Sinatra::Bundles gem.
261
+ #
262
+ # * Improve the specs a bit and add missing tests.
263
+ #
264
+ # * Any other improvements I or You can think of.
265
+ #
266
+ # == Copyright
267
+ #
268
+ # Copyright (c) 2010 kematzy. See LICENSE for details.
269
+ #
270
+ module JS
271
+
272
+ VERSION = '0.1.5' unless const_defined?(:VERSION)
273
+ def self.version; "Sinatra::JS v#{VERSION}"; end
274
+
275
+
276
+ module Helpers
277
+
278
+
279
+ attr_accessor :sinatra_js_custom_code, :sinatra_js_custom_files
280
+
281
+ ##
282
+ # Return script tag to _path_. When a _block_ is passed,
283
+ # a script tag will be created with the yielded value as
284
+ # its contents.
285
+ #
286
+ # ==== Examples
287
+ #
288
+ # js do
289
+ # "document.write('hi');"
290
+ # end
291
+ # # =>
292
+ #
293
+ # js('jquery') # =>
294
+ #
295
+ # <script src="/jquery.js" type="text/javascript" charset="utf-8"></script>
296
+ #
297
+ # js('/js/jquery-tools.js') # =>
298
+ #
299
+ # <script src="/js/jquery-tools.js" type="text/javascript" charset="utf-8"></script>
300
+ #
301
+ #
302
+ # You can even pass an array of files to the method, which then outputs the <tt><script></tt>
303
+ # tags for each file.
304
+ #
305
+ # js( ['/js/jquery.js', '/js/jquery.ui'] ) # =>
306
+ #
307
+ # <script src="/js/jquery.js" type="text/javascript" charset="utf-8"></script>
308
+ # <script src="/js/jquery.ui.js" type="text/javascript" charset="utf-8"></script>
309
+ #
310
+ # @api public
311
+ def js(path = nil, attrs = {}, &block)
312
+ attrs = { :type => 'text/javascript', :charset => "utf-8" }.merge(attrs)
313
+ return tag(:script, yield, attrs) if block_given?
314
+ unless path.nil?
315
+ if path.is_a?(Array)
316
+ out = ''
317
+ path.each do |f|
318
+ fpath = url_for("#{f.sub(/\.js$/,'')}.js") unless remote_asset?(f)
319
+ attrs[:src] = fpath
320
+ out << tag(:script, { :newline => false }.merge(attrs) )
321
+ end
322
+ out
323
+ else
324
+ path = url_for("#{path.sub(/\.js$/,'')}.js") unless remote_asset?(path)
325
+ attrs[:src] = path
326
+ tag(:script, { :newline => false }.merge(attrs) )
327
+ end
328
+ end
329
+ end
330
+ alias_method :javascript, :js
331
+
332
+ ##
333
+ # Adds custom JS to the page load from within a view, helper method and so on
334
+ #
335
+ # ==== Examples
336
+ #
337
+ # js_custom_add("window.alert('this works');") => void (output is handled through the :js_custom method)
338
+ #
339
+ # @api public
340
+ def js_custom_add(js)
341
+ @sinatra_js_custom_code ||= []
342
+ @sinatra_js_custom_code << js
343
+ end
344
+
345
+ ##
346
+ # Add a custom JS file to the page load from within a view, helper method and so on
347
+ #
348
+ # ==== Examples
349
+ #
350
+ # js_custom_add_file(:filename || path to remote file) => void (output handled through the :js_custom_files method)
351
+ #
352
+ # # You can also embed the code from a .js file into the head element of a page.
353
+ # NB! path is starting from APP_ROOT/public/
354
+ #
355
+ # js_custom_add_file('home.js',:insert_into_html)
356
+ # => <script type="text/javascript"..> JS content </script>
357
+ #
358
+ # You can even give a file system path to embed the styles of a .js file.
359
+ #
360
+ # js_custom_add_file('home.js',:insert_into_html, '/path/2/some/directory')
361
+ # => <script type="text/javascript"..> Some JS content </script>
362
+ #
363
+ # @api public
364
+ def js_custom_add_file(file, insert_into_html = nil, path = nil)
365
+ if insert_into_html.nil?
366
+ @sinatra_js_custom_files ||= []
367
+ if file.is_a?(Array)
368
+ file.each {|f| @sinatra_js_custom_files << f }
369
+ else
370
+ @sinatra_js_custom_files << file
371
+ end
372
+ else
373
+ # read the file into js_custom_add
374
+ path_js = path.nil? ? self.class.public : path
375
+ file_js = "#{path_js}/#{file.sub('.js','')}.js"
376
+ if test(?f, file_js)
377
+ js_custom_add(IO.read(file_js))
378
+ else
379
+ err_msg = "ERROR: js_custom_add_file(:insert_into_html) method could NOT find and embed this JS file=[ #{file_js} ]"
380
+ if self.respond_to?(:logger)
381
+ logger.warn(err_msg)
382
+ else
383
+ warn(err_msg)
384
+ end
385
+ end
386
+ end
387
+ end
388
+
389
+ ##
390
+ # Simple convenicence method that takes a path to a JS file
391
+ # and inserts its content into the current <tt>.js.erb</tt> file
392
+ #
393
+ # Depends upon the settings of the <tt>:js_source_files_dir</tt> configuration variable
394
+ # defined inside your application. By default it is set to <tt>'/$HOME/.alt/css'</tt>
395
+ #
396
+ # ==== Examples
397
+ #
398
+ # # in your app's routes configurations
399
+ # get('/js/app.js') do
400
+ # content_type 'application/javascript'
401
+ # erb('js/app.js'.to_sym, :layout => false)
402
+ # end
403
+ #
404
+ #
405
+ #
406
+ # # in views/js/app.js.erb
407
+ # js_insert_file('min/jquery') => path/2/js/files/min/jquery.js
408
+ #
409
+ # which inserts the JS code from that file into the output.
410
+ #
411
+ #
412
+ #
413
+ #
414
+ # @api public
415
+ def js_insert_file(path = '', local = nil )
416
+ file_path = local.nil? ? "#{self.class.js_shared_source_files_dir}/#{path}" : path
417
+ file_path = file_path.sub(/\.js$/,'') << ".js"
418
+ if test(?f, file_path)
419
+ content = IO.read(file_path)
420
+ else
421
+ content = "// ERROR: the JS file [#{file_path}] could NOT be found"
422
+ end
423
+ content
424
+ end
425
+
426
+ ##
427
+ # Outputs given custom JS if provided from within a view, helper method and so on
428
+ #
429
+ # ==== Examples
430
+ #
431
+ # js_custom => <script...> var custom = 'it works'; </script>
432
+ #
433
+ #
434
+ # You can also add the JQuery document.ready code to the output, by simply
435
+ # adding <tt>:jquery_block</tt> to the method.
436
+ #
437
+ # <%= js_custom(:jquery_block) %>
438
+ #
439
+ # <script type="text/javascript" charset="utf-8">
440
+ # $(document).ready( function () {
441
+ # // some custom JS code here
442
+ # });
443
+ # </script>
444
+ #
445
+ #
446
+ # @api public
447
+ def js_custom(js=nil, add_jquery_block = nil)
448
+ if js.is_a?(Symbol)
449
+ js = nil
450
+ add_jquery_block = :jquery
451
+ end
452
+ out = ''
453
+ out << js unless js.nil?
454
+ unless @sinatra_js_custom_code.nil?
455
+ @sinatra_js_custom_code.each { |i| out << " #{i}\n" }
456
+ end
457
+ if add_jquery_block.nil?
458
+ code_js = out.strip
459
+ else
460
+ code_js = "$(document).ready( function () {\n #{out.strip}\n } );"
461
+ end
462
+ out = out.empty? ?
463
+ '' : %Q[<script type="text/javascript" charset="utf-8">\n#{code_js}\n</script>\n]
464
+ end
465
+
466
+ ##
467
+ # Outputs given custom JS files that have been included
468
+ #
469
+ # ==== Examples
470
+ #
471
+ # <%= js_custom_files %> =>
472
+ # <script src="/js/custom1.js" ...>
473
+ # <script src="/js/custom2.js" ...>
474
+ #
475
+ # @api public
476
+ def js_custom_files
477
+ unless @sinatra_js_custom_files.nil?
478
+ out = "<!-- custom js files -->\n"
479
+ @sinatra_js_custom_files.each do |file|
480
+ # file = url_for("#{file.to_s.sub(/\.js$/,'')}.js") unless remote_asset?(file)
481
+ file = "#{file.to_s.sub(/\.js$/,'')}.js" unless remote_asset?(file)
482
+ out << js(file)
483
+ # out << %Q[ <script src="#{file}" type="text/javascript" charset="utf-8"></script>\n]
484
+ end
485
+ out << " <!-- /custom js files -->\n"
486
+ else
487
+ '' # return empty string, it's better than nil in this case
488
+ end
489
+ end
490
+
491
+ end #/ Helpers
492
+
493
+
494
+ ##
495
+ # Handles all JS requests, and returns the RJS (RubyJS) file version of it,
496
+ # or else passes the request on to the file system.
497
+ #
498
+ # NB! the path value given is NOT used as the name of the source directory in app/views,
499
+ # so ensure that there is always an app/views/js directory in place.
500
+ #
501
+ # ie:
502
+ # get_all_js_requests() => expects a app/views/js dir with the .rjs files
503
+
504
+ # get_all_js_requests('/javascripts') => expects a app/views/js dir with the .rjs files
505
+ #
506
+ # ==== Examples
507
+ #
508
+ # get_all_js_requests() => catches 'site.com/js/app.js
509
+ # get_all_js_requests('/javascripts') => catches 'site.com/javascripts/app.js
510
+ #
511
+ # @api public
512
+ def get_all_js_requests(path='/js', options = {})
513
+ path, options = '/js', path if path.is_a?(Hash)
514
+
515
+ get("#{path}/*.js", {} ) do
516
+ begin
517
+ options = { :cache => false, :layout => false }.merge(options)
518
+ content_type 'text/javascript', :charset => 'utf-8'
519
+ rjs("js/#{params[:splat].first}".to_sym, options ).gsub(/\n\r?$/,"")
520
+ rescue Errno::ENOENT
521
+ content_type 'text/html' # reset the content_type
522
+ pass
523
+ end
524
+ end
525
+ end
526
+
527
+
528
+ ##
529
+ # Registers these Extensions:
530
+ #
531
+ # * Sinatra::Tags
532
+ # * Sinatra::Basics::Assets
533
+ #
534
+ # Default Settings:
535
+ #
536
+ # * +:js_shared_source_files_dir+ => set the path to the Shared directory with compliled JS templates.
537
+ # Default is: <tt>'ENV['HOME']/.alt/js'</tt>
538
+ #
539
+ # @api public
540
+ def self.registered(app)
541
+ app.register(Sinatra::Tags)
542
+ app.register(Sinatra::Assets)
543
+
544
+ app.helpers Sinatra::JS::Helpers
545
+
546
+ # set the path to the Shared directory with compliled JS templates
547
+ app.set :js_shared_source_files_dir, File.join(File.expand_path(ENV['HOME']) ,'.alt', 'js')
548
+
549
+
550
+ ## add the extension specific options to those inspectable by :settings_inspect method
551
+ # provided by the Sinatra::Settings extension
552
+ if app.respond_to?(:sinatra_settings_for_inspection)
553
+ %w( js_shared_source_files_dir ).each do |m|
554
+ app.sinatra_settings_for_inspection << m
555
+ end
556
+ end
557
+
558
+ end #/ self.registered
559
+
560
+ end #/ JS
561
+
562
+ register(Sinatra::JS)
563
+
564
+ end #/ Sinatra