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 +5 -0
- data/.gitignore +23 -0
- data/CHANGES +4 -0
- data/LICENSE +20 -0
- data/README.rdoc +265 -0
- data/Rakefile +91 -0
- data/VERSION +1 -0
- data/lib/sinatra/js.rb +564 -0
- data/sinatra-js.gemspec +70 -0
- data/spec/fixtures/app/views/js/app.rjs +1 -0
- data/spec/fixtures/public/insert.js +1 -0
- data/spec/fixtures/public/inserted-from-path.js +1 -0
- data/spec/sinatra/js_spec.rb +315 -0
- data/spec/spec_helper.rb +59 -0
- metadata +156 -0
data/.document
ADDED
data/.gitignore
ADDED
data/CHANGES
ADDED
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
|