isotope 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. data.tar.gz.sig +1 -0
  2. data/CHANGELOG.rdoc +3 -0
  3. data/Gemfile +5 -0
  4. data/Gemfile.lock +11 -0
  5. data/LICENSE +18 -0
  6. data/Manifest +65 -0
  7. data/README.md +289 -0
  8. data/Rakefile +13 -0
  9. data/examples/rails3-example/Gemfile +34 -0
  10. data/examples/rails3-example/Gemfile.lock +77 -0
  11. data/examples/rails3-example/README +256 -0
  12. data/examples/rails3-example/Rakefile +7 -0
  13. data/examples/rails3-example/app/controllers/application_controller.rb +3 -0
  14. data/examples/rails3-example/app/controllers/articles_controller.rb +63 -0
  15. data/examples/rails3-example/app/helpers/application_helper.rb +2 -0
  16. data/examples/rails3-example/app/helpers/articles_helper.rb +2 -0
  17. data/examples/rails3-example/app/views/articles/article.html.ejs +11 -0
  18. data/examples/rails3-example/app/views/articles/show_client.html.erb +35 -0
  19. data/examples/rails3-example/app/views/articles/show_server_template_in_view.html.erb +4 -0
  20. data/examples/rails3-example/app/views/layouts/application.html.erb +13 -0
  21. data/examples/rails3-example/config.ru +4 -0
  22. data/examples/rails3-example/config/application.rb +42 -0
  23. data/examples/rails3-example/config/boot.rb +13 -0
  24. data/examples/rails3-example/config/database.yml +22 -0
  25. data/examples/rails3-example/config/environment.rb +5 -0
  26. data/examples/rails3-example/config/environments/development.rb +26 -0
  27. data/examples/rails3-example/config/environments/production.rb +49 -0
  28. data/examples/rails3-example/config/environments/test.rb +35 -0
  29. data/examples/rails3-example/config/initializers/backtrace_silencers.rb +7 -0
  30. data/examples/rails3-example/config/initializers/inflections.rb +10 -0
  31. data/examples/rails3-example/config/initializers/mime_types.rb +5 -0
  32. data/examples/rails3-example/config/initializers/secret_token.rb +7 -0
  33. data/examples/rails3-example/config/initializers/session_store.rb +8 -0
  34. data/examples/rails3-example/config/locales/en.yml +5 -0
  35. data/examples/rails3-example/config/routes.rb +65 -0
  36. data/examples/rails3-example/db/development.sqlite3 +0 -0
  37. data/examples/rails3-example/db/seeds.rb +7 -0
  38. data/examples/rails3-example/doc/README_FOR_APP +2 -0
  39. data/examples/rails3-example/public/404.html +26 -0
  40. data/examples/rails3-example/public/422.html +26 -0
  41. data/examples/rails3-example/public/500.html +26 -0
  42. data/examples/rails3-example/public/favicon.ico +0 -0
  43. data/examples/rails3-example/public/images/rails.png +0 -0
  44. data/examples/rails3-example/public/index.html +239 -0
  45. data/examples/rails3-example/public/javascripts/application.js +2 -0
  46. data/examples/rails3-example/public/javascripts/controls.js +965 -0
  47. data/examples/rails3-example/public/javascripts/dragdrop.js +974 -0
  48. data/examples/rails3-example/public/javascripts/effects.js +1123 -0
  49. data/examples/rails3-example/public/javascripts/isotope.js +56 -0
  50. data/examples/rails3-example/public/javascripts/prototype.js +6001 -0
  51. data/examples/rails3-example/public/javascripts/rails.js +175 -0
  52. data/examples/rails3-example/public/robots.txt +5 -0
  53. data/examples/rails3-example/script/rails +6 -0
  54. data/examples/rails3-example/test/functional/articles_controller_test.rb +9 -0
  55. data/examples/rails3-example/test/performance/browsing_test.rb +9 -0
  56. data/examples/rails3-example/test/test_helper.rb +13 -0
  57. data/examples/rails3-example/test/unit/helpers/article_helper_test.rb +4 -0
  58. data/examples/rails3-example/test/unit/helpers/articles_helper_test.rb +4 -0
  59. data/examples/rails3-example/tmp/pids/server.pid +1 -0
  60. data/examples/sinatra-example/server.rb +4 -0
  61. data/isotope.gemspec +32 -0
  62. data/lib/isotope.js +53 -0
  63. data/lib/isotope.rb +75 -0
  64. data/lib/version.rb +9 -0
  65. data/test/article.ejs +11 -0
  66. data/test/isotope_spec.rb +103 -0
  67. metadata +163 -0
  68. metadata.gz.sig +0 -0
@@ -0,0 +1 @@
1
+ j�v�
@@ -0,0 +1,3 @@
1
+ == 1.0.0 Initial release, 2010-10-28
2
+
3
+ * Initial release
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source :rubygemss
2
+ source :gemcutter
3
+ source "http://gems.github.com"
4
+
5
+ gem "johnson"
@@ -0,0 +1,11 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ remote: http://gems.github.com/
4
+ specs:
5
+ johnson (1.2.0)
6
+
7
+ PLATFORMS
8
+ ruby
9
+
10
+ DEPENDENCIES
11
+ johnson
data/LICENSE ADDED
@@ -0,0 +1,18 @@
1
+ Copyright (c) 2010 Elad Ossadon
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the "Software"), to deal in
5
+ the Software without restriction, including without limitation the rights to
6
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
7
+ the Software, and to permit persons to whom the Software is furnished to do so,
8
+ subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
15
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
16
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,65 @@
1
+ CHANGELOG.rdoc
2
+ Gemfile
3
+ Gemfile.lock
4
+ LICENSE
5
+ Manifest
6
+ README.md
7
+ Rakefile
8
+ examples/rails3-example/Gemfile
9
+ examples/rails3-example/Gemfile.lock
10
+ examples/rails3-example/README
11
+ examples/rails3-example/Rakefile
12
+ examples/rails3-example/app/controllers/application_controller.rb
13
+ examples/rails3-example/app/controllers/articles_controller.rb
14
+ examples/rails3-example/app/helpers/application_helper.rb
15
+ examples/rails3-example/app/helpers/articles_helper.rb
16
+ examples/rails3-example/app/views/articles/article.html.ejs
17
+ examples/rails3-example/app/views/articles/show_client.html.erb
18
+ examples/rails3-example/app/views/articles/show_server_template_in_view.html.erb
19
+ examples/rails3-example/app/views/layouts/application.html.erb
20
+ examples/rails3-example/config.ru
21
+ examples/rails3-example/config/application.rb
22
+ examples/rails3-example/config/boot.rb
23
+ examples/rails3-example/config/database.yml
24
+ examples/rails3-example/config/environment.rb
25
+ examples/rails3-example/config/environments/development.rb
26
+ examples/rails3-example/config/environments/production.rb
27
+ examples/rails3-example/config/environments/test.rb
28
+ examples/rails3-example/config/initializers/backtrace_silencers.rb
29
+ examples/rails3-example/config/initializers/inflections.rb
30
+ examples/rails3-example/config/initializers/mime_types.rb
31
+ examples/rails3-example/config/initializers/secret_token.rb
32
+ examples/rails3-example/config/initializers/session_store.rb
33
+ examples/rails3-example/config/locales/en.yml
34
+ examples/rails3-example/config/routes.rb
35
+ examples/rails3-example/db/development.sqlite3
36
+ examples/rails3-example/db/seeds.rb
37
+ examples/rails3-example/doc/README_FOR_APP
38
+ examples/rails3-example/public/404.html
39
+ examples/rails3-example/public/422.html
40
+ examples/rails3-example/public/500.html
41
+ examples/rails3-example/public/favicon.ico
42
+ examples/rails3-example/public/images/rails.png
43
+ examples/rails3-example/public/index.html
44
+ examples/rails3-example/public/javascripts/application.js
45
+ examples/rails3-example/public/javascripts/controls.js
46
+ examples/rails3-example/public/javascripts/dragdrop.js
47
+ examples/rails3-example/public/javascripts/effects.js
48
+ examples/rails3-example/public/javascripts/isotope.js
49
+ examples/rails3-example/public/javascripts/prototype.js
50
+ examples/rails3-example/public/javascripts/rails.js
51
+ examples/rails3-example/public/robots.txt
52
+ examples/rails3-example/script/rails
53
+ examples/rails3-example/test/functional/articles_controller_test.rb
54
+ examples/rails3-example/test/performance/browsing_test.rb
55
+ examples/rails3-example/test/test_helper.rb
56
+ examples/rails3-example/test/unit/helpers/article_helper_test.rb
57
+ examples/rails3-example/test/unit/helpers/articles_helper_test.rb
58
+ examples/rails3-example/tmp/pids/server.pid
59
+ examples/sinatra-example/server.rb
60
+ isotope.gemspec
61
+ lib/isotope.js
62
+ lib/isotope.rb
63
+ lib/version.rb
64
+ test/article.ejs
65
+ test/isotope_spec.rb
@@ -0,0 +1,289 @@
1
+ # Isotope - Ruby Hybrid Template Engine for Client Side and Server Side
2
+
3
+ ## The problem:
4
+
5
+ In Ajax-based sites, there's a constant dilemma: How to get objects rendered in templates? In server side (and output full HTML)? Client side (and mess with JSON objects)?
6
+ What should be the role division between server and client?
7
+
8
+ ## Common Approaches, Pros & Cons:
9
+
10
+ A few approaches to output a rendered template evaluated with an object are:
11
+
12
+ ### Approach #1: Regular ERB Partial
13
+
14
+ Evaluate a simple ERB partial with a local object, and server it as a **string** to the client, simply by
15
+
16
+ <%= render :partial => "article", :object => @article %>
17
+
18
+ in a view, or from a controller and request it by Ajax.
19
+
20
+ This partial can look like:
21
+
22
+ <h2><%=article.title%></h2>
23
+ <div class="content">
24
+ <%=article.content%>
25
+ </div>
26
+ <ul class="tags">
27
+ <%article.tags.each { |tag|%>
28
+ <li><%=tag.name%></li>
29
+ <%}%>
30
+ </ul>
31
+
32
+ #### Pros
33
+
34
+ * Simple, readable and well known ERB for Rails/Sinatra
35
+ * SEO and accessibility - HTML code is downloaded into the source
36
+
37
+ #### Cons
38
+
39
+ * Server side only
40
+ * Requires download of the whole HTML code, can cause performance issues
41
+ * Cannot bind easily to a different object on client side. Must re-rendered in the server-side and be downloaded
42
+
43
+
44
+ ### Approach #2: Client Side EJS Template with JSON Objects
45
+
46
+ Having an EJS template in the HTML code, with techniques such as John Resig's [JavaScript Micro-Templating](http://ejohn.org/blog/javascript-micro-templating/)
47
+
48
+ <script type="text/html" id="article-template">
49
+ <h2><%=item.title%></h2>
50
+
51
+ <div class="content">
52
+ <%=item.content%>
53
+ </div>
54
+
55
+ <ul class="tags">
56
+ <%item.tags.forEach(function (tag) {%>
57
+ <li><%=tag.name%></li>
58
+ <%});%>
59
+ </ul>
60
+ </script>
61
+
62
+ Ask the server for a JSON article and evaluate the template with this object into a string, and place it inside a container, using a techniques as mentioned:
63
+
64
+ var results = document.getElementById("results"); // some container on the page
65
+ results.innerHTML = tmpl("article-template", article); // article is an object, probably a result of an AJAX JSON request
66
+
67
+ #### Pros
68
+
69
+ * Fast - requires the server to send only the JSON object and the HTML is downloaded only once as a template
70
+
71
+ #### Cons
72
+
73
+ * SEO and accessibility - HTML code isn't in the source of the page but being rendered after load
74
+
75
+
76
+ ### Approach #3: Regular ERB Partial With Marked Spots for Data Place Holders
77
+
78
+ This approach tries to combine server side and client side but requires a lot of work. It contains a regular ERB template and place holder markers like class names on elements.
79
+ The template can be first evaluated on the server with a Ruby object and on the client side it can be evaluated with a different JS object (probably from a JSON request).
80
+
81
+ Template file should look like:
82
+
83
+ <h2 class="data-title"><%=article.title%></h2>
84
+ <div class="content data-content">
85
+ <%=article.content%>
86
+ </div>
87
+ <ul class="tags data-tags">
88
+ <%article.tags.each { |tag|%>
89
+ <li><%=tag.name%></li>
90
+ <%}%>
91
+ </ul>
92
+
93
+ And then, from a JS function, doing something like:
94
+
95
+ // article is an object probably from a JSON request
96
+ container.querySelector('.data-title').textContent=article.title;
97
+ container.querySelector('.data-content').textContent=article.content;
98
+ var tags=container.querySelector('.data-tags');
99
+ tags.innerHTML="";
100
+ article.tags.forEach(function (tag) {
101
+ tags.appendChild(document.createElement("li")).textContent=tag.name;
102
+ });
103
+
104
+ #### Pros
105
+
106
+ * One template for both client and server (not really, see Cons)
107
+ * SEO and accessibility - HTML code is downloaded into the source
108
+
109
+ #### Cons
110
+
111
+ * On the client side - Must mimic the Ruby functionality with JS when it comes to loops, conditions etc. However, text values are pretty easy to embed. This code should probably written manually for everything that is not a simple textual content.
112
+ * Must maintain data place holder markers
113
+
114
+
115
+ ### So...
116
+
117
+ In these three approaches, the developer needs to choose according to the task and the project requirements, or worse, maintain two templates, ERB and EJS.
118
+
119
+ Each approach is written in a totally different way, and switching between the approaches means a lot of work.
120
+
121
+
122
+ ## Introducing: Isotope - Ruby Hybrid Template Engine for Client Side and Server Side
123
+
124
+ So why not combining all the **pros** of the approaches together?
125
+
126
+ The biggest constraints to be considered are:
127
+
128
+ * Client side doesn't understand Ruby
129
+ * Ruby can't be translated fully into JavaScript
130
+ * And the most important one: **Template should be maintained in one single file for both client and server uses**
131
+
132
+ Isotope is from greek - "Equal Place". An equal place of editing a template for both client and server (Thanks @yuvalraz for the name!).
133
+
134
+ Using [**jbarnette**](http://github.com/jbarnette/)'s AWESOME [**Johnson**](http://github.com/jbarnette/johnson/) gem, Ruby and JavaScript can interact together!
135
+
136
+ That means, that ruby code can handle EJS templates and JSON objects. A **great and very inspiring article** is [Write your Rails view in… JavaScript?](http://tenderlovemaking.com/2008/05/06/write-your-rails-view-in-javascript/) by [Aaron Patterson](http://tenderlovemaking.com/).
137
+
138
+ In this approach, only **one template is written and maintained in an EJS format**, for both client side and server side.
139
+
140
+ ## Usage
141
+
142
+ Isotope gives the ability to have a single template file, and easily switch between the approaches:
143
+
144
+ # article.ejs
145
+
146
+ <h2><%=item.title%></h2>
147
+
148
+ <div class="content">
149
+ <%=item.content%>
150
+ </div>
151
+
152
+ <ul class="tags">
153
+ <%item.tags.forEach(function (tag) {%>
154
+ <li><%=tag.name%></li>
155
+ <%});%>
156
+ </ul>
157
+
158
+ ### On the Client Side
159
+
160
+ Outputting from the server side (controller or view)
161
+
162
+ <%= Isotope.render_template("full/path/to/article.ejs", :id => "article-template") %>
163
+
164
+ *Notice: a full path should be sent as the first variable, so either use `File.join(File.dirname(__FILE__), '../relative/path/to/article.ejs')` or with `Rails.root.join('app/views/articles/article.ejs')`*
165
+
166
+ The above code will output:
167
+
168
+ <script type="text/x-isotope" id="article-template">
169
+ <h2><%=item.title%></h2>
170
+
171
+ <div class="content">
172
+ <%=item.content%>
173
+ </div>
174
+
175
+ <ul class="tags">
176
+ <%item.tags.forEach(function (tag) {%>
177
+ <li><%=tag.name%></li>
178
+ <%});%>
179
+ </ul>
180
+ </script>
181
+
182
+ which is easy to evaluate with any JS object using the [mentioned technique](http://ejohn.org/blog/javascript-micro-templating/).
183
+
184
+ ### On the Server Side (The Holy Grail)
185
+
186
+ Using [Johnson](http://github.com/jbarnette/johnson/), the famous [micro-templating technique](http://ejohn.org/blog/javascript-micro-templating/) and JSONed Ruby objects, this library provides the following functionality:
187
+
188
+ <%= Isotope.render_partial("full/path/to/article.js", :locals => { :item => @article }) %>
189
+
190
+ *Notice: a full path should be sent as the first variable, so either use `File.join(File.dirname(__FILE__), '../relative/path/to/article.ejs')` or with `Rails.root.join('app/views/articles/article.ejs')`*
191
+
192
+ This code reads the source of the EJS file, uses Johnson and John Resig's technique and serves a **string** as an output.
193
+
194
+
195
+ ### Installation:
196
+
197
+ gem install isotope
198
+
199
+ Or
200
+ # Rails 3.x
201
+ ruby script/rails plugin install git@github.com:elado/isotope.git
202
+
203
+ # Rails 2.3.x
204
+ ruby script/plugin install git@github.com:elado/isotope.git
205
+
206
+
207
+ #### Rails
208
+
209
+ ##### Rails 3.x
210
+
211
+ Add to your Gemfile
212
+
213
+ gem 'json'
214
+ gem 'johnson'
215
+ gem 'isotope'
216
+
217
+ and run `bundle install`
218
+
219
+ ##### Rails 2.3.x
220
+
221
+ Add to config/environment.rb
222
+
223
+ config.gem 'json'
224
+ config.gem 'johnson'
225
+ config.gem 'isotope'
226
+
227
+ and run `rake gems:install`
228
+
229
+ ##### Server Side Example:
230
+
231
+ # ArticlesController
232
+
233
+ def show
234
+ @article = {
235
+ :title => "Hello!",
236
+ :content => "World!",
237
+ :tags => [
238
+ {:name => "tag 1"},
239
+ {:name => "tag 2"},
240
+ {:name => "tag 3"},
241
+ {:name => "tag 4"}
242
+ ]
243
+ } # Or an ActiveRecord fetch
244
+
245
+ render :text => Isotope.render_partial(Rails.root.join('app/views/articles/article.ejs'), :locals => { :item => @article })
246
+ end
247
+
248
+ Or, with a view:
249
+
250
+ # ArticlesController
251
+
252
+ def show
253
+ @article = {
254
+ :title => "Hello!",
255
+ :content => "World!",
256
+ :tags => [
257
+ {:name => "tag 1"},
258
+ {:name => "tag 2"},
259
+ {:name => "tag 3"},
260
+ {:name => "tag 4"}
261
+ ]
262
+ } # Or an ActiveRecord fetch
263
+ end
264
+
265
+ # views/articles/show.html.erb
266
+
267
+ <%= Isotope.render_partial(Rails.root.join('app/views/articles/article.ejs'), :locals => { :item => @article }) %>
268
+
269
+ ##### Client Side Example:
270
+
271
+ # views/articles/show.html.erb
272
+
273
+ <%= Isotope.render_template(Rails.root.join('app/views/articles/article.ejs'), :id => "article") %>
274
+
275
+
276
+ #### Sinatra
277
+
278
+ Actually the same usage, more or less.
279
+
280
+
281
+ ---
282
+
283
+ Would love to hear your comments!
284
+
285
+ Elad Ossadon
286
+
287
+ * [http://devign.me](http://devign.me)
288
+ * [http://elad.ossadon.com](http://elad.ossadon.com)
289
+ * [elad@ossadon.com](mailto:elad@ossadon.com)
@@ -0,0 +1,13 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'echoe'
4
+
5
+ Echoe.new('isotope', '1.0.1') do |p|
6
+ p.summary = "Ruby Hybrid (Server and Client sides) templates"
7
+ p.description = "Isotope provides an easy way to use a signle EJS template on both server and client side"
8
+ p.url = "http://github.com/elado/isotope"
9
+ p.author = "Elad Ossadon"
10
+ p.email = "elad@ossadon.com"
11
+ p.ignore_pattern = ["tmp/*", "script/*"]
12
+ p.development_dependencies = []
13
+ end
@@ -0,0 +1,34 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gem 'rails', '>=3.0.0'
4
+
5
+ # gem 'isotope'
6
+ gem 'json'
7
+ gem 'johnson'
8
+
9
+ # Bundle edge Rails instead:
10
+ # gem 'rails', :git => 'git://github.com/rails/rails.git'
11
+
12
+ gem 'sqlite3-ruby', :require => 'sqlite3'
13
+
14
+ # Use unicorn as the web server
15
+ # gem 'unicorn'
16
+
17
+ # Deploy with Capistrano
18
+ # gem 'capistrano'
19
+
20
+ # To use debugger
21
+ # gem 'ruby-debug'
22
+
23
+ # Bundle the extra gems:
24
+ # gem 'bj'
25
+ # gem 'nokogiri'
26
+ # gem 'sqlite3-ruby', :require => 'sqlite3'
27
+ # gem 'aws-s3', :require => 'aws/s3'
28
+
29
+ # Bundle gems for the local environment. Make sure to
30
+ # put test-only gems in this group so their generators
31
+ # and rake tasks are available in development mode:
32
+ # group :development, :test do
33
+ # gem 'webrat'
34
+ # end