spakit 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +2 -0
- data/Manifest.txt +7 -0
- data/README.txt +142 -0
- data/Rakefile +11 -0
- data/init.rb +2 -0
- data/lib/spakit.rb +27 -0
- data/lib/spakit_helper.rb +70 -0
- metadata +71 -0
data/History.txt
ADDED
data/Manifest.txt
ADDED
data/README.txt
ADDED
@@ -0,0 +1,142 @@
|
|
1
|
+
Author:: Wen-Tien Chang(mailto:ihower@handlino.com), hlb(mailto:hlb@handlino.com)
|
2
|
+
Copyright:: Copyright (c) 2007 Handlino Inc.
|
3
|
+
License:: Distributed under the New BSD License
|
4
|
+
|
5
|
+
== Description ==
|
6
|
+
Spakit is a plugin that makes it very easy to turn your Rails App
|
7
|
+
Into a "single page application" (SPA).
|
8
|
+
|
9
|
+
To enable SPA, simply install the plug-in, create a spakit layout and use Spakit helper.
|
10
|
+
Don't need modify any model/controller code... ;)
|
11
|
+
|
12
|
+
Spakit will send xhr request(i.e. prototype's Ajax.Updater ) with ?layout=spakit,
|
13
|
+
and controller return HTML with spakit layout. Note that spakit_form_for not support file upload submit.
|
14
|
+
|
15
|
+
By the way, Message plugin is another SPA plugin,using different approach.
|
16
|
+
|
17
|
+
== Requirements
|
18
|
+
* Rails 2.0.2
|
19
|
+
|
20
|
+
== Install ==
|
21
|
+
* gem install spakit
|
22
|
+
* cd /your_app/vendor/plugin/
|
23
|
+
* gem unpack spakit
|
24
|
+
|
25
|
+
== Usage ==
|
26
|
+
|
27
|
+
For now, Spakit provide three helper:
|
28
|
+
|
29
|
+
* spakit_link_to, just like remote_link_to
|
30
|
+
* spakit_form_for, just like form_for, but you must specify :url
|
31
|
+
* spakit_form_tag, just like form_tag
|
32
|
+
|
33
|
+
by default spakit will replace HTML element called #content.
|
34
|
+
|
35
|
+
== Layout code example ==
|
36
|
+
You should write flash message here because we often place that in application layout.
|
37
|
+
|
38
|
+
# /view/layouts/spakit.rhtml
|
39
|
+
|
40
|
+
<p><%= flash[:notice] %></p>
|
41
|
+
<%= yield %>
|
42
|
+
|
43
|
+
== History Bookmarks ==
|
44
|
+
|
45
|
+
We recommend Really Simple History(RSH) library to handle browser forward/back.
|
46
|
+
|
47
|
+
Example code:
|
48
|
+
|
49
|
+
# environment.rb
|
50
|
+
|
51
|
+
module SpakitHelper
|
52
|
+
@@spa_options = {
|
53
|
+
:update => 'content-region',
|
54
|
+
:loading => 'SPA.loading',
|
55
|
+
:complete => 'SPA.complete'
|
56
|
+
}
|
57
|
+
end
|
58
|
+
|
59
|
+
# application.js
|
60
|
+
# We use jquery syntax, you can use prototype to define your function.
|
61
|
+
|
62
|
+
var $j = jQuery.noConflict();
|
63
|
+
|
64
|
+
(function($) {
|
65
|
+
SPA = {
|
66
|
+
currentHash: null,
|
67
|
+
currentLocation: null,
|
68
|
+
init: function() {
|
69
|
+
if ( $('#waiting-message').length == 0 ) {
|
70
|
+
$('<div id="waiting-message"><img src="/images/ajax-loader.gif"></div>').appendTo('#bd');
|
71
|
+
$('#waiting-message').hide();
|
72
|
+
}
|
73
|
+
},
|
74
|
+
loading: function() {
|
75
|
+
this.init();
|
76
|
+
$('#waiting-message').show();
|
77
|
+
},
|
78
|
+
hide: function() {
|
79
|
+
$('#waiting-message').hide();
|
80
|
+
},
|
81
|
+
historyChange: function(newLocation, historyData, isFresh) {
|
82
|
+
if (isFresh == null) {
|
83
|
+
if (historyStorage.hasKey(newLocation)) {
|
84
|
+
if (newLocation == "start") {
|
85
|
+
newLocation = location.pathname;
|
86
|
+
}
|
87
|
+
|
88
|
+
$.ajax({
|
89
|
+
type: "GET",
|
90
|
+
url: newLocation,
|
91
|
+
data: { layout: "spakit" },
|
92
|
+
beforeSend: function(){ SPA.loading(); },
|
93
|
+
complete: function(res, status){
|
94
|
+
if ( status == "success" || status == "notmodified" ) {
|
95
|
+
$('#content-region').html(res.responseText);
|
96
|
+
}
|
97
|
+
SPA.hide();
|
98
|
+
}
|
99
|
+
});
|
100
|
+
}
|
101
|
+
} else {
|
102
|
+
/* new data */
|
103
|
+
dhtmlHistory.add(newLocation, historyData);
|
104
|
+
}
|
105
|
+
},
|
106
|
+
complete: function(newLocation) {
|
107
|
+
this.historyChange(newLocation, "", true);
|
108
|
+
this.hide();
|
109
|
+
}
|
110
|
+
};
|
111
|
+
|
112
|
+
SPA.currentHash = window.location.hash;
|
113
|
+
if (SPA.currentHash.length) {
|
114
|
+
if (SPA.currentHash.charAt(0) == '#' && SPA.currentHash.charAt(1) == '/') {
|
115
|
+
SPA.currentLocation = SPA.currentHash.slice(1);
|
116
|
+
}
|
117
|
+
}
|
118
|
+
|
119
|
+
$(document).ready(function(){
|
120
|
+
dhtmlHistory.initialize();
|
121
|
+
if (SPA.currentLocation) {
|
122
|
+
if (SPA.currentLocation != '#start') {
|
123
|
+
window.location.href = SPA.currentLocation;
|
124
|
+
}
|
125
|
+
} else {
|
126
|
+
dhtmlHistory.addListener(SPA.historyChange);
|
127
|
+
if (dhtmlHistory.isFirstLoad()) {
|
128
|
+
dhtmlHistory.add("start", "");
|
129
|
+
}
|
130
|
+
}
|
131
|
+
});
|
132
|
+
|
133
|
+
})(jQuery);
|
134
|
+
|
135
|
+
window.dhtmlHistory.create({
|
136
|
+
toJSON: function(o) {
|
137
|
+
return JSON.stringify(o);
|
138
|
+
},
|
139
|
+
fromJSON: function(s) {
|
140
|
+
return JSON.parse(s);
|
141
|
+
}
|
142
|
+
});
|
data/Rakefile
ADDED
data/init.rb
ADDED
data/lib/spakit.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
module ActionController
|
2
|
+
|
3
|
+
class Base
|
4
|
+
alias :rails_redirect_to :redirect_to
|
5
|
+
alias :rails_render :render
|
6
|
+
|
7
|
+
def redirect_to(options = {}, response_status = {})
|
8
|
+
if options.class == Hash
|
9
|
+
options.merge!( :layout => 'spakit' ) if ( self.params[:layout].to_s == 'spakit' && !options.include?(:layout) )
|
10
|
+
elsif options.class == String
|
11
|
+
options = options + '?layout=spakit' if ( self.params[:layout].to_s == 'spakit' && !options.include?('layout=') )
|
12
|
+
end
|
13
|
+
|
14
|
+
rails_redirect_to(options, response_status)
|
15
|
+
end
|
16
|
+
|
17
|
+
# deprecated_status is for rspec compatible
|
18
|
+
# http://rubyforge.org/pipermail/rspec-users/2007-November/004780.html
|
19
|
+
def render(options = nil,deprecated_status=nil, &block) #:doc:
|
20
|
+
options.merge!( :layout => 'spakit' ) if ( options.class == Hash && !options.include?(:layout) && self.params[:layout].to_s == 'spakit' )
|
21
|
+
options = { :layout => 'spakit' } if ( !options && self.params[:layout].to_s == 'spakit' ) #rails default
|
22
|
+
|
23
|
+
rails_render(options, &block)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module SpakitHelper
|
2
|
+
|
3
|
+
@@spa_options = {
|
4
|
+
:update => 'content',
|
5
|
+
:loading => nil,
|
6
|
+
:complete => nil
|
7
|
+
}
|
8
|
+
|
9
|
+
# api is the same as remote_link_to
|
10
|
+
# TODO: omit CSRF auth token if method is get
|
11
|
+
def spakit_link_to(name, options = {}, html_options = nil)
|
12
|
+
#abs path will use non-SPA
|
13
|
+
return link_to(name,options[:url]) if options[:url].class == String && options[:url].include?('http://')
|
14
|
+
|
15
|
+
html_options = { :href => url_for(options[:url]) } unless html_options
|
16
|
+
html_options[:href] = url_for(options[:url]) unless (html_options && html_options[:href] )
|
17
|
+
|
18
|
+
options.merge!( :method => :get ) unless options[:method]
|
19
|
+
options.merge!( :update => @@spa_options[:update] ) if (@@spa_options[:update] && !options[:update])
|
20
|
+
options.merge!( :loading => "#{@@spa_options[:loading]}()" ) if (@@spa_options[:loading] && !options[:loading])
|
21
|
+
options.merge!( :complete => "#{@@spa_options[:complete]}('#{html_options[:href]}');" ) if (@@spa_options[:complete] && !options[:complete])
|
22
|
+
options.merge! ( :with => "'layout=spakit'" ) unless options[:with]
|
23
|
+
|
24
|
+
link_to_remote(name, options, html_options)
|
25
|
+
end
|
26
|
+
|
27
|
+
# api is the same as remote_remote_for, but you must provide :url
|
28
|
+
# spakit_remote_for @event, :url => hash_for_events_path, :html => {...} do |f|
|
29
|
+
# is just equal
|
30
|
+
# form_remote_for @event, :url => hash_for_events_path.merge(:layout => 'spakit'), :update => 'content', :loading => "SPA.show()",:complete => "SPA.hide()" do |f|
|
31
|
+
# TODO: can omit :url
|
32
|
+
def spakit_form_for(record_or_name_or_array, *args, &proc)
|
33
|
+
options = args.extract_options!
|
34
|
+
|
35
|
+
target = url_for( options[:url] )
|
36
|
+
options.merge!( :update => @@spa_options[:update] ) if (@@spa_options[:update] && !options[:update])
|
37
|
+
options.merge!( :loading => "#{@@spa_options[:loading]}()" ) if (@@spa_options[:loading] && !options[:loading])
|
38
|
+
options.merge!( :complete => "#{@@spa_options[:complete]}('#{target}');" ) if (@@spa_options[:complete] && !options[:complete])
|
39
|
+
|
40
|
+
#can't use options[:with] here because it will force to use Form.serialize
|
41
|
+
if options[:url].is_a?(Hash)
|
42
|
+
options[:url].merge!( :layout => 'spakit' )
|
43
|
+
elsif options[:url].is_a?(String)
|
44
|
+
options[:url] = options[:url] + '?layout=spakit' #String
|
45
|
+
end
|
46
|
+
|
47
|
+
options[:html] = { :action => target } unless options[:html]
|
48
|
+
options[:html].merge!( :action => target ) if ( options[:html] and !options[:html][:action] )
|
49
|
+
|
50
|
+
form_remote_for(record_or_name_or_array, *(args << options), &proc)
|
51
|
+
end
|
52
|
+
|
53
|
+
def spakit_form_tag( options = {}, &block)
|
54
|
+
target = ( options[:url].is_a?(Hash) ) ? url_for( options[:url] ) : options[:url]
|
55
|
+
options.merge!( :update => @@spa_options[:update] ) if (@@spa_options[:update] && !options[:update])
|
56
|
+
options.merge!( :loading => "#{@@spa_options[:loading]}()" ) if (@@spa_options[:loading] && !options[:loading])
|
57
|
+
options.merge!( :complete => "#{@@spa_options[:complete]}('#{target}');" ) if (@@spa_options[:complete] && !options[:complete])
|
58
|
+
|
59
|
+
if options[:url].is_a?(Hash)
|
60
|
+
options[:url].merge!( :layout => 'spakit' )
|
61
|
+
elsif options[:url].is_a?(String)
|
62
|
+
options[:url] = options[:url] + '?layout=spakit' #String
|
63
|
+
end
|
64
|
+
|
65
|
+
options[:html] = { :action => target } unless options[:html]
|
66
|
+
options[:html].merge!( :action => target ) if ( options[:html] and !options[:html][:action] )
|
67
|
+
|
68
|
+
form_remote_tag(options, &block)
|
69
|
+
end
|
70
|
+
end
|
metadata
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: spakit
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.9.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Wen-Tien Chang
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2008-04-08 00:00:00 +08:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: hoe
|
17
|
+
version_requirement:
|
18
|
+
version_requirements: !ruby/object:Gem::Requirement
|
19
|
+
requirements:
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 1.5.1
|
23
|
+
version:
|
24
|
+
description: ""
|
25
|
+
email:
|
26
|
+
- ihower@handlino.com
|
27
|
+
executables: []
|
28
|
+
|
29
|
+
extensions: []
|
30
|
+
|
31
|
+
extra_rdoc_files:
|
32
|
+
- History.txt
|
33
|
+
- Manifest.txt
|
34
|
+
- README.txt
|
35
|
+
files:
|
36
|
+
- History.txt
|
37
|
+
- init.rb
|
38
|
+
- Manifest.txt
|
39
|
+
- Rakefile
|
40
|
+
- lib/spakit.rb
|
41
|
+
- lib/spakit_helper.rb
|
42
|
+
- README.txt
|
43
|
+
has_rdoc: true
|
44
|
+
homepage: Spakit is a plugin that makes it very easy to turn your Rails App
|
45
|
+
post_install_message:
|
46
|
+
rdoc_options:
|
47
|
+
- --main
|
48
|
+
- README.txt
|
49
|
+
require_paths:
|
50
|
+
- lib
|
51
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: "0"
|
56
|
+
version:
|
57
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: "0"
|
62
|
+
version:
|
63
|
+
requirements: []
|
64
|
+
|
65
|
+
rubyforge_project: spakit
|
66
|
+
rubygems_version: 1.1.0
|
67
|
+
signing_key:
|
68
|
+
specification_version: 2
|
69
|
+
summary: ""
|
70
|
+
test_files: []
|
71
|
+
|