honkster-jelly 0.7.7 → 0.8.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/VERSION.yml CHANGED
@@ -1,4 +1,4 @@
1
1
  ---
2
- :minor: 7
3
- :patch: 7
2
+ :minor: 8
3
+ :patch: 1
4
4
  :major: 0
@@ -19,12 +19,13 @@ if(!window.Jelly) Jelly = new Object();
19
19
  authenticity_token: window._token
20
20
  });
21
21
  }
22
+ var observers = otherParams.observers || Jelly.observers;
22
23
  return $.extend({
23
24
  dataType: 'json',
24
25
  cache: false,
25
- success : $.ajaxWithJelly.onSuccess
26
+ success : function(callbacks) {
27
+ Jelly.notifyObservers.call(observers, callbacks);
28
+ }
26
29
  }, otherParams);
27
30
  };
28
-
29
- $.ajaxWithJelly.onSuccess = Jelly.notifyObservers.bind(Jelly);
30
31
  })(jQuery);
@@ -2,7 +2,7 @@
2
2
  * Jelly. a sweet unobtrusive javascript framework
3
3
  * for jQuery and Rails
4
4
  *
5
- * version 0.7.7
5
+ * version 0.8.1
6
6
  *
7
7
  * Copyright (c) 2009 Pivotal Labs
8
8
  * Licensed under the MIT license.
@@ -21,8 +21,9 @@ if (!Function.prototype.bind) {
21
21
  }
22
22
  }
23
23
  Jelly.init = function() {
24
- this.components = [];
25
24
  this.observers = [];
25
+ this.observers.pending = [];
26
+ this.attach = this.Observers.attach;
26
27
  this.notifyObservers = this.Observers.notify;
27
28
  this.Components.initCalled = false;
28
29
  this.Pages.init();
@@ -32,65 +33,79 @@ Jelly.init = function() {
32
33
  });
33
34
  };
34
35
 
35
- Jelly.attach = function() {
36
- for (var i = 0; i < arguments.length; i++) {
37
- var definition = arguments[i];
38
- var component = (typeof definition.component == "string") ?
39
- eval(definition.component) :
40
- definition.component;
41
- var evaluatedDefinition = {
42
- component: component,
43
- arguments: definition.arguments
44
- };
45
- this.components.push(evaluatedDefinition);
46
- if (Jelly.Components.initCalled) {
47
- Jelly.Components.initComponentFromDefinition(evaluatedDefinition);
36
+ Jelly.Components = {
37
+ init: function() {
38
+ for (var i = 0; i < Jelly.observers.pending.length; i++) {
39
+ Jelly.Observers.initPending.call(Jelly.observers, Jelly.observers.pending[i]);
48
40
  }
41
+ this.initCalled = true;
49
42
  }
50
43
  };
51
44
 
52
- Jelly.Components = {
53
- init: function() {
54
- for (var i = 0; i < Jelly.components.length; i++) {
55
- this.initComponentFromDefinition(Jelly.components[i]);
45
+ Jelly.Observers = {
46
+ attach: function() {
47
+ if (this == Jelly) {
48
+ return Jelly.Observers.attach.apply(this.observers, arguments);
49
+ }
50
+ this.pending = this.pending || [];
51
+ for (var i = 0; i < arguments.length; i++) {
52
+ var definition = arguments[i];
53
+ var component = (typeof definition.component == "string") ?
54
+ eval(definition.component) :
55
+ definition.component;
56
+ var evaluatedDefinition = {
57
+ component: component,
58
+ arguments: definition.arguments
59
+ };
60
+ this.pending.push(evaluatedDefinition);
61
+ if (Jelly.Components.initCalled) {
62
+ Jelly.Observers.initPending.call(this, evaluatedDefinition);
63
+ }
56
64
  }
57
- this.initCalled = true;
58
65
  },
59
- initComponentFromDefinition: function(definition) {
66
+
67
+ initPending: function(definition) {
60
68
  var observer;
61
69
  if (definition.component.init) {
62
70
  observer = definition.component.init.apply(definition.component, definition.arguments);
63
71
  }
64
- Jelly.observers.push(observer ? observer : definition.component);
65
- }
66
- };
72
+ this.push(observer ? observer : definition.component);
73
+ },
67
74
 
68
- Jelly.Observers = {
69
- notify: function(params) {
70
- if (this == Jelly) return Jelly.Observers.notify.call(this.observers, params);
71
- var observers = this.slice(0);
75
+ notify: function(callbacks) {
76
+ if (this == Jelly) {
77
+ return Jelly.Observers.notify.apply(this.observers, arguments);
78
+ }
79
+ if (!$.isArray(callbacks)) {
80
+ callbacks = [callbacks];
81
+ }
72
82
 
73
- // Deprecate 'on' in favor of making each page action a Component.
74
- if (params.on) {
75
- var additionalObserver = eval(params.on);
76
- if (observers.indexOf(additionalObserver) == -1) {
77
- observers.push(additionalObserver);
83
+ var observers = this.slice(0);
84
+ for (var i = 0; i < callbacks.length; i++) {
85
+ var callback = callbacks[i];
86
+
87
+ // Deprecate 'on' in favor of making each page action a Component.
88
+ if (callback.on) {
89
+ var additionalObserver = eval(callback.on);
90
+ if (observers.indexOf(additionalObserver) == -1) {
91
+ observers.push(additionalObserver);
92
+ }
78
93
  }
79
- }
80
94
 
81
- for (var i = 0; i < observers.length; i++) {
82
- var observer = observers[i];
83
- if (observer[params.method]) {
84
- if (observer.detach && observer.detach()) {
85
- Jelly.Observers.garbageCollectObserver.call(this, observer);
86
- } else {
87
- observer[params.method].apply(observer, params.arguments);
95
+ for (var j = 0; j < observers.length; j++) {
96
+ var observer = observers[j];
97
+ if (observer[callback.method]) {
98
+ if (observer.detach && observer.detach()) {
99
+ Jelly.Observers.garbageCollectObserver.call(this, observer);
100
+ } else {
101
+ observer[callback.method].apply(observer, callback.arguments);
102
+ }
88
103
  }
89
104
  }
90
- }
91
105
 
92
- if (params.attach) {
93
- Jelly.attach.apply(Jelly, params.attach);
106
+ if (callback.attach) {
107
+ Jelly.Observers.attach.apply(this, callback.attach);
108
+ }
94
109
  }
95
110
  },
96
111
 
data/jelly.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{jelly}
8
- s.version = "0.7.7"
8
+ s.version = "0.8.1"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Pivotal Labs, Inc"]
12
- s.date = %q{2009-12-28}
12
+ s.date = %q{2009-12-29}
13
13
  s.description = %q{Jelly provides a set of tools and conventions for creating rich ajax/javascript web applications with jQuery and Ruby on Rails.}
14
14
  s.email = %q{opensource@pivotallabs.com}
15
15
  s.extra_rdoc_files = [
@@ -3,6 +3,14 @@ module JellyController
3
3
  include Jelly::Common
4
4
 
5
5
  def jelly_callback(callback_base_name = @action_name, options = {}, &block)
6
+ raw_jelly_callback(options) do
7
+ arguments = block.try(:call) || []
8
+ jelly_callback_hash("on_#{callback_base_name}", *arguments).merge(options)
9
+ end
10
+ end
11
+
12
+ def raw_jelly_callback(options={}, &block)
13
+ options.symbolize_keys!
6
14
  options[:format] ||= if request.xhr?
7
15
  :json
8
16
  elsif params[:callback]
@@ -10,14 +18,12 @@ module JellyController
10
18
  else
11
19
  :iframe
12
20
  end
13
- render :inline => jelly_callback_erb("on_#{callback_base_name}", options, block)
21
+ render :inline => jelly_callback_erb(options, &block)
14
22
  end
15
23
 
16
- def jelly_callback_erb(callback_name, options, block)
24
+ def jelly_callback_erb(options={}, &block)
17
25
  options[:format] ||= :json
18
- @callback_name = callback_name
19
- @options = options
20
- @block = block
26
+ @jelly_block = block
21
27
  case options[:format].to_sym
22
28
  when :iframe
23
29
  "<textarea>#{jelly_callback_erb_template}</textarea>"
@@ -32,9 +38,7 @@ module JellyController
32
38
  def jelly_callback_erb_template
33
39
  <<-ERB
34
40
  <%= begin
35
- args = @block ? instance_eval(&@block) : []
36
- args = [args] unless args.is_a?(Array)
37
- json = {"method" => @callback_name, "arguments" => args}.reverse_merge(@options).to_json
41
+ json = instance_eval(&@jelly_block).to_json
38
42
  @jsonp_callback ? "\#{@jsonp_callback}(\#{json});" : json
39
43
  end %>
40
44
  ERB
@@ -15,6 +15,54 @@ describe ApplicationController do
15
15
  @controller.respond_to?(:jelly_callback).should be_true
16
16
  end
17
17
 
18
+ context "when given a format" do
19
+ describe "json" do
20
+ it "responds with a json hash, even if the request is not xhr" do
21
+ stub(request).xhr? {false}
22
+
23
+ @controller.send(:jelly_callback, 'foo', {'format' => :json, 'bar' => 'baz'}) do
24
+ "grape"
25
+ end
26
+ callback = JSON.parse(response.body)
27
+ callback["method"].should == "on_foo"
28
+ callback["arguments"].should == ["grape"]
29
+ callback["bar"].should == "baz"
30
+ end
31
+ end
32
+
33
+ describe "jsonp" do
34
+ it "responds with a jsonp callback based on the callback param" do
35
+ @controller.params[:callback] = "Jelly.notifyObservers"
36
+
37
+ @controller.send(:jelly_callback, 'foo', {'format' => :jsonp, 'bar' => 'baz'}) do
38
+ "grape"
39
+ end
40
+ json = Regexp.new('Jelly\.notifyObservers\((.*)\);').match(response.body)[1]
41
+ callback = JSON.parse(json)
42
+ callback["method"].should == "on_foo"
43
+ callback["arguments"].should == ["grape"]
44
+ callback["bar"].should == "baz"
45
+ end
46
+ end
47
+
48
+ describe "iframe" do
49
+ it "responds with a the json in a textarea tag" do
50
+ @controller.send(:jelly_callback, 'foo', {'format' => :iframe, 'bar' => 'baz'}) do
51
+ "grape"
52
+ end
53
+ body = response.body
54
+ body.should =~ /^<textarea>/
55
+ body.should =~ /<\/textarea>$/
56
+ doc = Nokogiri::HTML(body)
57
+
58
+ callback = JSON.parse(doc.at("textarea").inner_html)
59
+ callback["method"].should == "on_foo"
60
+ callback["arguments"].should == ["grape"]
61
+ callback["bar"].should == "baz"
62
+ end
63
+ end
64
+ end
65
+
18
66
  context "when the request is XHR" do
19
67
  before do
20
68
  stub(request).xhr? {true}
@@ -71,81 +119,123 @@ describe ApplicationController do
71
119
  end
72
120
  end
73
121
  end
122
+ end
74
123
 
75
- describe "#jelly_callback_erb" do
76
- before do
77
- stub(request).xhr? {true}
124
+ describe "#raw_jelly_callback" do
125
+ attr_reader :response
126
+ before do
127
+ @response = Struct.new(:body).new
128
+ stub(@controller).render do |params|
129
+ response.body = ERB.new(params[:inline]).result(@controller.send(:binding))
78
130
  end
131
+ end
132
+
133
+ it "have the method included" do
134
+ @controller.respond_to?(:raw_jelly_callback).should be_true
135
+ end
136
+
137
+ context "when given a format" do
138
+ describe "json" do
139
+ it "responds with a json hash, even if the request is not xhr" do
140
+ stub(request).xhr? {false}
79
141
 
80
- context "with options" do
81
- it "should work with a block" do
82
- erb = @controller.send(:jelly_callback_erb, 'foo', {'bar' => 'baz'}, lambda{'grape'})
83
- JSON.parse(ERB.new(erb).result(@controller.send(:binding))).should == {
84
- 'method' => 'foo',
85
- 'arguments' => ['grape'],
86
- 'bar' => 'baz',
87
- 'format' => 'json'
88
- }
142
+ @controller.send(:raw_jelly_callback, :format => :json) do
143
+ jelly_callback_hash("foo", "grape").merge('bar' => 'baz')
144
+ end
145
+ callback = JSON.parse(response.body)
146
+ callback["method"].should == "foo"
147
+ callback["arguments"].should == ["grape"]
148
+ callback["bar"].should == "baz"
89
149
  end
150
+ end
151
+
152
+ describe "jsonp" do
153
+ it "responds with a jsonp callback based on the callback param" do
154
+ @controller.params[:callback] = "Jelly.notifyObservers"
90
155
 
91
- it "should work without a block" do
92
- erb = @controller.send(:jelly_callback_erb, 'foo', {'bar' => 'baz'}, nil)
93
- JSON.parse(ERB.new(erb).result(@controller.send(:binding))).should == {
94
- 'method' => 'foo',
95
- 'arguments' => [],
96
- 'bar' => 'baz',
97
- 'format' => 'json'
98
- }
156
+ @controller.send(:raw_jelly_callback, :format => :jsonp) do
157
+ jelly_callback_hash("foo", "grape").merge('bar' => 'baz')
158
+ end
159
+ json = Regexp.new('Jelly\.notifyObservers\((.*)\);').match(response.body)[1]
160
+ callback = JSON.parse(json)
161
+ callback["method"].should == "foo"
162
+ callback["arguments"].should == ["grape"]
163
+ callback["bar"].should == "baz"
99
164
  end
165
+ end
166
+
167
+ describe "iframe" do
168
+ it "responds with a the json in a textarea tag" do
169
+ @controller.send(:raw_jelly_callback, :format => :iframe) do
170
+ jelly_callback_hash("foo", "grape").merge('bar' => 'baz')
171
+ end
172
+ body = response.body
173
+ body.should =~ /^<textarea>/
174
+ body.should =~ /<\/textarea>$/
175
+ doc = Nokogiri::HTML(body)
100
176
 
101
- it "should work if options are passed with symbol keys" do
102
- erb = @controller.send(:jelly_callback_erb, 'foo', {:bar => 'baz'}, nil)
103
- JSON.parse(ERB.new(erb).result(@controller.send(:binding))).should == {
104
- 'method' => 'foo',
105
- 'arguments' => [],
106
- 'bar' => 'baz',
107
- 'format' => 'json'
108
- }
177
+ callback = JSON.parse(doc.at("textarea").inner_html)
178
+ callback["method"].should == "foo"
179
+ callback["arguments"].should == ["grape"]
180
+ callback["bar"].should == "baz"
109
181
  end
110
182
  end
183
+ end
184
+
185
+ context "when the request is XHR" do
186
+ before do
187
+ stub(request).xhr? {true}
188
+ end
111
189
 
112
- context "without options" do
113
- it "should work with a block" do
114
- erb = @controller.send(:jelly_callback_erb, 'foo', {}, lambda{'grape'})
115
- JSON.parse(ERB.new(erb).result(@controller.send(:binding))).should == {
116
- 'method' => 'foo',
117
- 'arguments' => ['grape'],
118
- 'format' => 'json'
119
- }
190
+ it "responds with a json hash" do
191
+ @controller.send(:raw_jelly_callback) do
192
+ jelly_callback_hash("foo", "grape").merge('bar' => 'baz')
120
193
  end
194
+ callback = JSON.parse(response.body)
195
+ callback["method"].should == "foo"
196
+ callback["arguments"].should == ["grape"]
197
+ callback["bar"].should == "baz"
198
+ end
199
+
200
+ end
121
201
 
122
- it "should work with a block of more than one thing" do
123
- erb = @controller.send(:jelly_callback_erb, 'foo', {}, lambda{['grape','tangerine']})
124
- JSON.parse(ERB.new(erb).result(@controller.send(:binding))).should == {
125
- 'method' => 'foo',
126
- 'arguments' => ['grape','tangerine'],
127
- 'format' => 'json'
128
- }
202
+ context "when the request is not XHR" do
203
+ before do
204
+ stub(request).xhr? {false}
205
+ end
206
+
207
+ context "when there is a callback param" do
208
+ before do
209
+ @controller.params[:callback] = "Jelly.notifyObservers"
129
210
  end
130
211
 
131
- it "should work without a block" do
132
- erb = @controller.send(:jelly_callback_erb, 'foo', {}, nil)
133
- JSON.parse(ERB.new(erb).result(@controller.send(:binding))).should == {
134
- 'method' => 'foo',
135
- 'arguments' => [],
136
- 'format' => 'json'
137
- }
212
+ it "responds with a call to the given callback method with the json as an argument" do
213
+ @controller.send(:raw_jelly_callback) do
214
+ jelly_callback_hash("foo", "grape").merge('bar' => 'baz')
215
+ end
216
+ json = Regexp.new('Jelly\.notifyObservers\((.*)\);').match(response.body)[1]
217
+ callback = JSON.parse(json)
218
+ callback["method"].should == "foo"
219
+ callback["arguments"].should == ["grape"]
220
+ callback["bar"].should == "baz"
138
221
  end
139
222
  end
140
223
 
141
- it "should escape html in the arguments" do
142
- block = lambda{'<div class="foo"></div>'}
143
- erb = @controller.send(:jelly_callback_erb, 'foo', {}, block)
144
- JSON.parse(ERB.new(erb).result(@controller.send(:binding))).should == {
145
- 'method' => 'foo',
146
- 'arguments' => ['<div class="foo"></div>'],
147
- 'format' => 'json'
148
- }
224
+ context "when there is not a callback param" do
225
+ it "wraps the json response in a textarea tag to support File Uploads in an iframe target (see: http://malsup.com/jquery/form/#code-samples)" do
226
+ @controller.send(:raw_jelly_callback) do
227
+ jelly_callback_hash("foo", "grape").merge('bar' => 'baz')
228
+ end
229
+ body = response.body
230
+ body.should =~ /^<textarea>/
231
+ body.should =~ /<\/textarea>$/
232
+ doc = Nokogiri::HTML(body)
233
+
234
+ callback = JSON.parse(doc.at("textarea").inner_html)
235
+ callback["method"].should == "foo"
236
+ callback["arguments"].should == ["grape"]
237
+ callback["bar"].should == "baz"
238
+ end
149
239
  end
150
240
  end
151
241
  end
data/spec/spec_helper.rb CHANGED
@@ -2,6 +2,7 @@
2
2
  # from the project root directory.
3
3
  ENV["RAILS_ENV"] ||= 'test'
4
4
  ENV['RAILS_ROOT'] ||= File.dirname(__FILE__) + '/rails_root'
5
+ ARGV.push("-b")
5
6
  require File.expand_path(File.join(ENV['RAILS_ROOT'], 'config/environment.rb'))
6
7
  require 'rubygems'
7
8
  gem "test-unit"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: honkster-jelly
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.7
4
+ version: 0.8.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pivotal Labs, Inc
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-12-28 00:00:00 -08:00
12
+ date: 2009-12-29 00:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency