jelly 0.6.5 → 0.8.10
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/README.markdown +7 -7
- data/VERSION.yml +2 -3
- data/generators/jelly/jelly_generator.rb +0 -1
- data/generators/jelly/templates/javascripts/ajax_with_jelly.js +4 -6
- data/generators/jelly/templates/javascripts/jelly.js +134 -69
- data/jelly.gemspec +7 -8
- data/lib/jelly.rb +2 -3
- data/lib/jelly/common.rb +8 -0
- data/lib/jelly/jelly_controller.rb +30 -13
- data/lib/jelly/jelly_helper.rb +24 -16
- data/spec/jelly/common_spec.rb +46 -0
- data/spec/jelly/jelly_controller_spec.rb +327 -0
- data/spec/{helpers → jelly}/jelly_helper_spec.rb +35 -16
- data/spec/spec_helper.rb +4 -0
- metadata +5 -5
- data/generators/jelly/templates/javascripts/jquery/jquery.protify-0.3.js +0 -345
- data/spec/controllers/jelly_controller_spec.rb +0 -118
data/README.markdown
CHANGED
@@ -71,7 +71,7 @@ page-specifc function when the page has loaded. Let's look at some code:
|
|
71
71
|
|
72
72
|
In public/javascripts/pages/stories.js, we create a simple Jelly file:
|
73
73
|
|
74
|
-
Jelly.add("Stories", {
|
74
|
+
Jelly.Pages.add("Stories", {
|
75
75
|
|
76
76
|
index: function() {
|
77
77
|
$('a.clickme').click(function() {
|
@@ -85,7 +85,7 @@ Jelly will automatically execute the `index` function when the Rails app runs th
|
|
85
85
|
continue the example by adding more Javascript functions that map to the `new` and `show` Rails actions. We can also
|
86
86
|
specify an `all` function, which will be executed on all actions in the `StoriesController`.
|
87
87
|
|
88
|
-
Jelly.add("Stories", {
|
88
|
+
Jelly.Pages.add("Stories", {
|
89
89
|
|
90
90
|
index: function() {
|
91
91
|
$('a.clickme').click(function() {
|
@@ -134,15 +134,15 @@ method in our view. This can be done either in your layout (for components to at
|
|
134
134
|
|
135
135
|
in the `<head>` tag of the layout:
|
136
136
|
|
137
|
-
|
137
|
+
<% attach_javascript_component('SearchBox') %>
|
138
138
|
|
139
139
|
or in a view:
|
140
140
|
|
141
141
|
<% content_for :javascript do -%>
|
142
|
-
|
142
|
+
<% attach_javascript_component('SearchBox') %>
|
143
143
|
<% end -%>
|
144
144
|
|
145
|
-
Components
|
145
|
+
Components are initialized **before** the page-specific Javascript functions by default.
|
146
146
|
|
147
147
|
AJAX With Jelly
|
148
148
|
---------------
|
@@ -179,7 +179,7 @@ The controller, stories_controller.rb
|
|
179
179
|
|
180
180
|
The javascript, pages/stories.js:
|
181
181
|
|
182
|
-
Jelly.add("Stories", {
|
182
|
+
Jelly.Pages.add("Stories", {
|
183
183
|
|
184
184
|
new: function() {
|
185
185
|
$("#create_story_link").click(function() {
|
@@ -234,7 +234,7 @@ The controller, stories_controller.rb
|
|
234
234
|
|
235
235
|
The javascript, pages/stories.js:
|
236
236
|
|
237
|
-
Jelly.add("Stories", {
|
237
|
+
Jelly.Pages.add("Stories", {
|
238
238
|
|
239
239
|
new: function() {
|
240
240
|
$("#create_story_link").click(function() {
|
data/VERSION.yml
CHANGED
@@ -5,7 +5,6 @@ class JellyGenerator < Rails::Generator::Base
|
|
5
5
|
m.file 'javascripts/ajax_with_jelly.js', "public/javascripts/ajax_with_jelly.js"
|
6
6
|
m.directory('public/javascripts/jquery')
|
7
7
|
m.file 'javascripts/jquery/jquery-1.3.2.js', "public/javascripts/jquery/jquery-1.3.2.js"
|
8
|
-
m.file 'javascripts/jquery/jquery.protify-0.3.js', "public/javascripts/jquery/jquery.protify-0.3.js"
|
9
8
|
m.directory('public/javascripts/pages')
|
10
9
|
end
|
11
10
|
end
|
@@ -19,15 +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 :
|
26
|
+
success : function(callbacks) {
|
27
|
+
Jelly.Observers.notify.call(observers, callbacks);
|
28
|
+
}
|
26
29
|
}, otherParams);
|
27
30
|
};
|
28
|
-
|
29
|
-
$.ajaxWithJelly.onSuccess = function(json) {
|
30
|
-
Jelly.notifyObservers(json);
|
31
|
-
return true;
|
32
|
-
};
|
33
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.
|
5
|
+
* version 0.8.10
|
6
6
|
*
|
7
7
|
* Copyright (c) 2009 Pivotal Labs
|
8
8
|
* Licensed under the MIT license.
|
@@ -12,83 +12,148 @@
|
|
12
12
|
*/
|
13
13
|
|
14
14
|
if (!window.Jelly) Jelly = new Object();
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
});
|
21
|
-
};
|
22
|
-
|
23
|
-
Jelly.attach = function(component, args) {
|
24
|
-
this.components.push([component, args]);
|
25
|
-
};
|
26
|
-
|
27
|
-
Jelly.notifyObservers = function(params) {
|
28
|
-
var context = params.on ? eval(params.on) : page;
|
29
|
-
if (context[params.method]) {
|
30
|
-
context[params.method].apply(context, params.arguments);
|
31
|
-
}
|
32
|
-
$.protify(Jelly.components).each(function(componentAndArgs) {
|
33
|
-
var component = componentAndArgs[0];
|
34
|
-
if (component[params.method] && component != context) {
|
35
|
-
component[params.method].apply(component, params.arguments);
|
15
|
+
if (!Function.prototype.bind) {
|
16
|
+
Function.prototype.bind = function(object) {
|
17
|
+
var self = this;
|
18
|
+
return function() {
|
19
|
+
return self.apply(object, arguments);
|
36
20
|
}
|
37
|
-
});
|
38
|
-
};
|
39
|
-
|
40
|
-
Jelly.Components = {
|
41
|
-
init: function() {
|
42
|
-
$.protify(Jelly.components).each(function(componentAndArgs) {
|
43
|
-
var component = componentAndArgs[0];
|
44
|
-
var args = componentAndArgs[1] || [];
|
45
|
-
if (component.init) component.init.apply(component, args);
|
46
|
-
});
|
47
21
|
}
|
48
|
-
}
|
49
|
-
|
50
|
-
Jelly.Pages = {
|
22
|
+
}
|
23
|
+
$.extend(Jelly, {
|
51
24
|
init: function() {
|
52
|
-
this.
|
53
|
-
|
25
|
+
this.observers = [];
|
26
|
+
this.attach = this.Observers.attach;
|
27
|
+
this.notifyObservers = this.Observers.notify;
|
28
|
+
this.Pages.init();
|
54
29
|
},
|
55
30
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
31
|
+
Observers: {
|
32
|
+
attach: function() {
|
33
|
+
if (this == Jelly) {
|
34
|
+
return Jelly.Observers.attach.apply(this.observers, arguments);
|
35
|
+
}
|
36
|
+
for (var i = 0; i < arguments.length; i++) {
|
37
|
+
var definitionOrComponent = arguments[i];
|
38
|
+
if (definitionOrComponent.component) {
|
39
|
+
var component = Jelly.Observers.evaluateComponent(definitionOrComponent.component);
|
40
|
+
if (component.init) {
|
41
|
+
var initReturnValue = component.init.apply(component, definitionOrComponent.arguments);
|
42
|
+
if (initReturnValue === false || initReturnValue === null) {
|
43
|
+
} else {
|
44
|
+
Jelly.Observers.pushIfObserver.call(this, initReturnValue || component);
|
45
|
+
}
|
46
|
+
} else {
|
47
|
+
Jelly.Observers.pushIfObserver.call(this, component);
|
48
|
+
}
|
49
|
+
} else {
|
50
|
+
Jelly.Observers.pushIfObserver.call(this, Jelly.Observers.evaluateComponent(definitionOrComponent));
|
51
|
+
}
|
52
|
+
}
|
53
|
+
},
|
54
|
+
|
55
|
+
evaluateComponent: function(component) {
|
56
|
+
return (typeof component == "string") ? eval(component) : component;
|
57
|
+
},
|
58
|
+
|
59
|
+
pushIfObserver: function(observer) {
|
60
|
+
if (observer) {
|
61
|
+
this.push(observer);
|
62
|
+
}
|
63
|
+
},
|
64
|
+
|
65
|
+
notify: function(callbacks) {
|
66
|
+
if (this == Jelly) {
|
67
|
+
return Jelly.Observers.notify.apply(this.observers, arguments);
|
68
|
+
}
|
69
|
+
if (!$.isArray(callbacks)) {
|
70
|
+
callbacks = [callbacks];
|
71
|
+
}
|
72
|
+
|
73
|
+
var observers = this.slice(0);
|
74
|
+
for (var i = 0; i < callbacks.length; i++) {
|
75
|
+
var callback = callbacks[i];
|
76
|
+
|
77
|
+
// Deprecate 'on' in favor of making each page action a Component.
|
78
|
+
if (callback.on) {
|
79
|
+
var additionalObserver = eval(callback.on);
|
80
|
+
if (observers.indexOf(additionalObserver) == -1) {
|
81
|
+
observers.push(additionalObserver);
|
82
|
+
}
|
83
|
+
}
|
84
|
+
|
85
|
+
if (callback.method) {
|
86
|
+
for (var j = 0; j < observers.length; j++) {
|
87
|
+
var observer = observers[j];
|
88
|
+
if (observer[callback.method]) {
|
89
|
+
if (observer.detach && observer.detach()) {
|
90
|
+
Jelly.Observers.garbageCollectObserver.call(this, observer);
|
91
|
+
} else {
|
92
|
+
observer[callback.method].apply(observer, callback.arguments);
|
93
|
+
}
|
94
|
+
}
|
95
|
+
}
|
96
|
+
}
|
97
|
+
|
98
|
+
if (callback.attach) {
|
99
|
+
Jelly.Observers.attach.apply(this, callback.attach);
|
100
|
+
}
|
101
|
+
}
|
102
|
+
},
|
103
|
+
|
104
|
+
garbageCollectObserver: function(observer) {
|
105
|
+
var index = this.indexOf(observer);
|
106
|
+
if (index > -1) {
|
107
|
+
Jelly.Observers.remove.call(this, index, index + 1);
|
108
|
+
}
|
109
|
+
},
|
110
|
+
|
111
|
+
remove: function(from, to) {
|
112
|
+
var rest = this.slice((to || from) + 1 || this.length);
|
113
|
+
this.length = from < 0 ? this.length + from : from;
|
114
|
+
return this.push.apply(this, rest);
|
60
115
|
}
|
61
|
-
|
62
|
-
}
|
63
|
-
};
|
64
|
-
Jelly.add = Jelly.Pages.add; // Deprecated
|
116
|
+
},
|
65
117
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
Jelly.Page.
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
window.page = page;
|
80
|
-
if (page.all) page.all();
|
81
|
-
if (page[actionName]) page[actionName].call(page);
|
82
|
-
page.loaded = true;
|
83
|
-
};
|
84
|
-
|
85
|
-
Jelly.Location = {
|
86
|
-
init: function() {
|
118
|
+
Pages: {
|
119
|
+
init: function() {
|
120
|
+
this.all = {};
|
121
|
+
Jelly.all = this.all; // Deprecated
|
122
|
+
},
|
123
|
+
|
124
|
+
add: function(name) {
|
125
|
+
var page = new Jelly.Page.Constructor(name);
|
126
|
+
for (var i = 1; i < arguments.length; i++) {
|
127
|
+
$.extend(page, arguments[i]);
|
128
|
+
}
|
129
|
+
return page;
|
130
|
+
}
|
87
131
|
},
|
88
132
|
|
89
|
-
|
90
|
-
|
133
|
+
Page: {
|
134
|
+
init: function(controllerName, actionName) {
|
135
|
+
var page = Jelly.Pages.all[controllerName] || new Jelly.Page.Constructor(controllerName);
|
136
|
+
window.page = page;
|
137
|
+
if (page.all) page.all();
|
138
|
+
if (page[actionName]) page[actionName].call(page);
|
139
|
+
page.loaded = true;
|
140
|
+
return page;
|
141
|
+
},
|
142
|
+
Constructor: function(name) {
|
143
|
+
this.loaded = false;
|
144
|
+
this.documentHref = Jelly.Location.documentHref;
|
145
|
+
|
146
|
+
this.name = name;
|
147
|
+
Jelly.Pages.all[name] = this;
|
148
|
+
}
|
149
|
+
},
|
150
|
+
|
151
|
+
Location: {
|
152
|
+
on_redirect: function(location) {
|
153
|
+
top.location.href = location;
|
154
|
+
}
|
91
155
|
}
|
92
|
-
};
|
156
|
+
});
|
157
|
+
Jelly.add = Jelly.Pages.add; // Deprecated
|
93
158
|
|
94
159
|
Jelly.init();
|
data/jelly.gemspec
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
# Generated by jeweler
|
2
|
-
# DO NOT EDIT THIS FILE
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run
|
2
|
+
# DO NOT EDIT THIS FILE
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{jelly}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.8.10"
|
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{
|
12
|
+
s.date = %q{2010-01-20}
|
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 = [
|
@@ -26,7 +26,6 @@ Gem::Specification.new do |s|
|
|
26
26
|
"generators/jelly/templates/javascripts/ajax_with_jelly.js",
|
27
27
|
"generators/jelly/templates/javascripts/jelly.js",
|
28
28
|
"generators/jelly/templates/javascripts/jquery/jquery-1.3.2.js",
|
29
|
-
"generators/jelly/templates/javascripts/jquery/jquery.protify-0.3.js",
|
30
29
|
"install.rb",
|
31
30
|
"jelly.gemspec",
|
32
31
|
"lib/jelly.rb",
|
@@ -42,8 +41,9 @@ Gem::Specification.new do |s|
|
|
42
41
|
s.rubygems_version = %q{1.3.5}
|
43
42
|
s.summary = %q{a sweet unobtrusive javascript framework for jQuery and Rails}
|
44
43
|
s.test_files = [
|
45
|
-
"spec/
|
46
|
-
"spec/
|
44
|
+
"spec/jelly/common_spec.rb",
|
45
|
+
"spec/jelly/jelly_controller_spec.rb",
|
46
|
+
"spec/jelly/jelly_helper_spec.rb",
|
47
47
|
"spec/rails_root/app/controllers/application_controller.rb",
|
48
48
|
"spec/rails_root/app/helpers/application_helper.rb",
|
49
49
|
"spec/rails_root/config/boot.rb",
|
@@ -76,4 +76,3 @@ Gem::Specification.new do |s|
|
|
76
76
|
s.add_dependency(%q<rails>, [">= 2.3.0"])
|
77
77
|
end
|
78
78
|
end
|
79
|
-
|
data/lib/jelly.rb
CHANGED
@@ -12,6 +12,5 @@ ActionView::Base.class_eval do
|
|
12
12
|
include JellyHelper
|
13
13
|
end
|
14
14
|
|
15
|
-
ActionView::Helpers::AssetTagHelper.register_javascript_expansion :jelly => ["jquery/jquery-1.3.2", "
|
16
|
-
|
17
|
-
ActionView::Helpers::AssetTagHelper.register_javascript_expansion :only_jelly => ["jquery/jquery.protify-0.3", "jelly", "ajax_with_jelly"]
|
15
|
+
ActionView::Helpers::AssetTagHelper.register_javascript_expansion :jelly => ["jquery/jquery-1.3.2", "ajax_with_jelly", "jelly"]
|
16
|
+
ActionView::Helpers::AssetTagHelper.register_javascript_expansion :only_jelly => ["jelly", "ajax_with_jelly"]
|
data/lib/jelly/common.rb
CHANGED
@@ -3,5 +3,13 @@ module Jelly
|
|
3
3
|
def jelly_callback_hash(method, *arguments)
|
4
4
|
{"method" => method, "arguments" => arguments}
|
5
5
|
end
|
6
|
+
|
7
|
+
def jelly_callback_attach_hash(components=jelly_attachments)
|
8
|
+
{"attach" => components}
|
9
|
+
end
|
10
|
+
|
11
|
+
def jelly_attachment_hash(component_name, *args)
|
12
|
+
{'component' => component_name, 'arguments' => args}
|
13
|
+
end
|
6
14
|
end
|
7
15
|
end
|
@@ -3,22 +3,39 @@ module JellyController
|
|
3
3
|
include Jelly::Common
|
4
4
|
|
5
5
|
def jelly_callback(callback_base_name = @action_name, options = {}, &block)
|
6
|
-
|
6
|
+
raw_jelly_callback(options) do
|
7
|
+
arguments = block ? instance_eval(&block) : []
|
8
|
+
arguments = [arguments] unless arguments.is_a?(Array)
|
9
|
+
jelly_callback_hash("on_#{callback_base_name}", *arguments).merge(options)
|
10
|
+
end
|
7
11
|
end
|
8
12
|
|
9
|
-
def
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
ERB
|
20
|
-
request.xhr? ? erb : "<textarea>#{erb}</textarea>"
|
13
|
+
def raw_jelly_callback(options={}, &block)
|
14
|
+
options.symbolize_keys!
|
15
|
+
options[:format] ||= if params[:callback]
|
16
|
+
:jsonp
|
17
|
+
elsif request.xhr?
|
18
|
+
:json
|
19
|
+
else
|
20
|
+
:iframe
|
21
|
+
end
|
22
|
+
render :inline => jelly_callback_erb(options, &block)
|
21
23
|
end
|
22
24
|
|
25
|
+
def jelly_callback_erb(options={}, &block)
|
26
|
+
options[:format] ||= :json
|
27
|
+
@jelly_block = block
|
28
|
+
case options[:format].to_sym
|
29
|
+
when :iframe
|
30
|
+
"<textarea>#{jelly_callback_erb_template}</textarea>"
|
31
|
+
when :jsonp
|
32
|
+
"#{params[:callback]}(#{jelly_callback_erb_template});"
|
33
|
+
else
|
34
|
+
jelly_callback_erb_template
|
35
|
+
end
|
36
|
+
end
|
23
37
|
|
38
|
+
def jelly_callback_erb_template
|
39
|
+
"<%= instance_eval(&@jelly_block).to_json %>"
|
40
|
+
end
|
24
41
|
end
|
data/lib/jelly/jelly_helper.rb
CHANGED
@@ -14,35 +14,43 @@ module JellyHelper
|
|
14
14
|
def spread_jelly
|
15
15
|
attach_javascript_component("Jelly.Location")
|
16
16
|
attach_javascript_component("Jelly.Page", controller.controller_path.camelcase, controller.action_name)
|
17
|
+
<<-HTML
|
18
|
+
#{window_token_javascript_tag}
|
19
|
+
#{attach_javascript_component_javascript_tag(jelly_attachments)}
|
20
|
+
HTML
|
21
|
+
end
|
22
|
+
|
23
|
+
def window_token_javascript_tag
|
24
|
+
javascript_tag("window._token = '#{form_authenticity_token}';")
|
25
|
+
end
|
26
|
+
|
27
|
+
def attach_javascript_component_javascript_tag(*components)
|
28
|
+
components = [components].flatten
|
17
29
|
javascript_tag <<-JS
|
18
|
-
window._token = '#{form_authenticity_token}'
|
19
|
-
#{@content_for_javascript}
|
20
30
|
$(document).ready(function() {
|
21
|
-
#{
|
31
|
+
Jelly.attach.apply(Jelly, #{components.to_json});
|
22
32
|
});
|
23
33
|
JS
|
24
34
|
end
|
25
35
|
|
26
|
-
def clear_jelly_attached
|
27
|
-
|
36
|
+
def clear_jelly_attached
|
37
|
+
jelly_attachments.clear
|
28
38
|
end
|
29
39
|
|
30
40
|
def attach_javascript_component(component_name, *args)
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
@jelly_attached_components << key
|
35
|
-
content_for(:javascript, key)
|
41
|
+
key = jelly_attachment_hash(component_name, *args)
|
42
|
+
unless jelly_attachments.include? key
|
43
|
+
jelly_attachments << key
|
36
44
|
end
|
37
45
|
end
|
38
46
|
|
39
47
|
def attach_javascript_component_on_ready(component_name, *args)
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
48
|
+
warn "attach_javascript_component_on_ready is deprecated since attach_javascript_component adds components to be attached in a $(document).ready block\n#{puts caller.join("\n\t")}"
|
49
|
+
attach_javascript_component(component_name, *args)
|
50
|
+
end
|
51
|
+
|
52
|
+
def jelly_attachments
|
53
|
+
@jelly_attachments ||= []
|
46
54
|
end
|
47
55
|
|
48
56
|
end
|