maccman-bowline 0.1.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/History.txt +4 -0
- data/MIT-LICENSE +20 -0
- data/Manifest.txt +58 -0
- data/README.txt +113 -0
- data/Rakefile +24 -0
- data/assets/jquery.bowline.js +96 -0
- data/assets/jquery.chain.js +2348 -0
- data/assets/jquery.js +3549 -0
- data/bin/bowline-gen +6 -0
- data/bowline.gemspec +42 -0
- data/examples/account_binder.rb +29 -0
- data/examples/example.js +24 -0
- data/examples/twitter.html +43 -0
- data/examples/twitter_binder.rb +40 -0
- data/examples/twitter_login.html +29 -0
- data/examples/users_binder.rb +39 -0
- data/lib/bowline.rb +42 -0
- data/lib/bowline/binders.rb +177 -0
- data/lib/bowline/binders/collection.rb +27 -0
- data/lib/bowline/binders/singleton.rb +25 -0
- data/lib/bowline/commands/console.rb +27 -0
- data/lib/bowline/commands/generate.rb +1 -0
- data/lib/bowline/commands/run.rb +13 -0
- data/lib/bowline/ext/array.rb +5 -0
- data/lib/bowline/ext/class.rb +51 -0
- data/lib/bowline/ext/object.rb +12 -0
- data/lib/bowline/ext/string.rb +9 -0
- data/lib/bowline/gem_dependency.rb +42 -0
- data/lib/bowline/generators.rb +59 -0
- data/lib/bowline/generators/application.rb +49 -0
- data/lib/bowline/generators/binder.rb +25 -0
- data/lib/bowline/generators/migration.rb +51 -0
- data/lib/bowline/generators/model.rb +20 -0
- data/lib/bowline/initializer.rb +596 -0
- data/lib/bowline/jquery.rb +31 -0
- data/lib/bowline/observer.rb +43 -0
- data/lib/bowline/tasks/app.rake +70 -0
- data/lib/bowline/tasks/bowline.rb +8 -0
- data/lib/bowline/tasks/database.rake +167 -0
- data/lib/bowline/tasks/log.rake +9 -0
- data/lib/bowline/tasks/misk.rake +3 -0
- data/templates/Rakefile +7 -0
- data/templates/binder.rb +9 -0
- data/templates/config/application.yml +1 -0
- data/templates/config/boot.rb +21 -0
- data/templates/config/database.yml +4 -0
- data/templates/config/environment.rb +12 -0
- data/templates/config/manifest +18 -0
- data/templates/config/tiapp.xml +24 -0
- data/templates/gitignore +15 -0
- data/templates/migration.rb +7 -0
- data/templates/model.rb +4 -0
- data/templates/public/index.html.erb +23 -0
- data/templates/public/javascripts/application.js +0 -0
- data/templates/public/stylesheets/application.css +0 -0
- data/templates/script/console +3 -0
- data/templates/script/init +11 -0
- data/templates/script/run +3 -0
- metadata +143 -0
data/bin/bowline-gen
ADDED
data/bowline.gemspec
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{bowline}
|
5
|
+
s.version = "0.1.1"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Alex MacCaw"]
|
9
|
+
s.date = %q{2009-04-23}
|
10
|
+
s.default_executable = %q{bowline-gen}
|
11
|
+
s.description = %q{My take on Ruby desktop GUIs}
|
12
|
+
s.email = ["info@eribium.org"]
|
13
|
+
s.executables = ["bowline-gen"]
|
14
|
+
s.extra_rdoc_files = ["History.txt", "Manifest.txt", "README.txt"]
|
15
|
+
s.files = ["History.txt", "MIT-LICENSE", "Manifest.txt", "README.txt", "Rakefile", "assets/jquery.bowline.js", "assets/jquery.chain.js", "assets/jquery.js", "bin/bowline-gen", "bowline.gemspec", "examples/account_binder.rb", "examples/example.js", "examples/twitter.html", "examples/twitter_binder.rb", "examples/twitter_login.html", "examples/users_binder.rb", "lib/bowline.rb", "lib/bowline/binders.rb", "lib/bowline/binders/collection.rb", "lib/bowline/binders/singleton.rb", "lib/bowline/commands/console.rb", "lib/bowline/commands/generate.rb", "lib/bowline/commands/run.rb", "lib/bowline/ext/array.rb", "lib/bowline/ext/class.rb", "lib/bowline/ext/object.rb", "lib/bowline/ext/string.rb", "lib/bowline/gem_dependency.rb", "lib/bowline/generators.rb", "lib/bowline/generators/application.rb", "lib/bowline/generators/binder.rb", "lib/bowline/generators/migration.rb", "lib/bowline/generators/model.rb", "lib/bowline/initializer.rb", "lib/bowline/jquery.rb", "lib/bowline/observer.rb", "lib/bowline/tasks/app.rake", "lib/bowline/tasks/bowline.rb", "lib/bowline/tasks/database.rake", "lib/bowline/tasks/log.rake", "lib/bowline/tasks/misk.rake", "templates/Rakefile", "templates/binder.rb", "templates/config/application.yml", "templates/config/boot.rb", "templates/config/database.yml", "templates/config/environment.rb", "templates/config/manifest", "templates/config/tiapp.xml", "templates/gitignore", "templates/migration.rb", "templates/model.rb", "templates/public/index.html.erb", "templates/public/javascripts/application.js", "templates/public/stylesheets/application.css", "templates/script/console", "templates/script/init", "templates/script/run"]
|
16
|
+
s.has_rdoc = true
|
17
|
+
s.homepage = %q{http://github.com/maccman/bowline}
|
18
|
+
s.rdoc_options = ["--main", "README.txt"]
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
s.rubyforge_project = %q{maccman}
|
21
|
+
s.rubygems_version = %q{1.3.2}
|
22
|
+
s.summary = %q{My take on Ruby desktop GUIs}
|
23
|
+
|
24
|
+
if s.respond_to? :specification_version then
|
25
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
26
|
+
s.specification_version = 3
|
27
|
+
|
28
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
29
|
+
s.add_runtime_dependency(%q<templater>, [">= 0.3.2"])
|
30
|
+
s.add_development_dependency(%q<newgem>, [">= 1.3.0"])
|
31
|
+
s.add_development_dependency(%q<hoe>, [">= 1.8.0"])
|
32
|
+
else
|
33
|
+
s.add_dependency(%q<templater>, [">= 0.3.2"])
|
34
|
+
s.add_dependency(%q<newgem>, [">= 1.3.0"])
|
35
|
+
s.add_dependency(%q<hoe>, [">= 1.8.0"])
|
36
|
+
end
|
37
|
+
else
|
38
|
+
s.add_dependency(%q<templater>, [">= 0.3.2"])
|
39
|
+
s.add_dependency(%q<newgem>, [">= 1.3.0"])
|
40
|
+
s.add_dependency(%q<hoe>, [">= 1.8.0"])
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class AccountBinder < Bowline::Singleton
|
2
|
+
class << self
|
3
|
+
# self.collection is a special method
|
4
|
+
# Basically it'll update users on the client side
|
5
|
+
def index
|
6
|
+
self.item = current_account
|
7
|
+
end
|
8
|
+
|
9
|
+
def destroy
|
10
|
+
current_account.destroy
|
11
|
+
self.item = nil
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# Everything has a js_id which is basically the lowercase classname + _ + self.id
|
16
|
+
def highlight
|
17
|
+
# Calls $(element).highlight()
|
18
|
+
self.element.highlight
|
19
|
+
end
|
20
|
+
|
21
|
+
# Overrides charge on user
|
22
|
+
def charge!
|
23
|
+
# calls charge on model (i.e. do sql commit )
|
24
|
+
self.item.charge!
|
25
|
+
# Now gui stuff
|
26
|
+
flash[:notice] = "Successfully charged"
|
27
|
+
highlight
|
28
|
+
end
|
29
|
+
end
|
data/examples/example.js
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
$('#users').bowline('users_binder');
|
2
|
+
|
3
|
+
var user = $('#users').items(10);
|
4
|
+
user.update({name: 'Alex'}); // will automatiinvokey
|
5
|
+
user.item().errors //=> []
|
6
|
+
|
7
|
+
// Deletes item from DOM too
|
8
|
+
item.destroy()
|
9
|
+
|
10
|
+
// invoke collection method
|
11
|
+
// This will invoke UserBinder.admins and fill #users with admins
|
12
|
+
$('#users').invoke('admins');
|
13
|
+
|
14
|
+
// invoke singleton method
|
15
|
+
$('#users').items(10).invoke('charge!');
|
16
|
+
|
17
|
+
// invoke charge! on every user
|
18
|
+
$('#users').items().invoke('charge!')
|
19
|
+
|
20
|
+
// // For binding over a http connection - an async invoke
|
21
|
+
// // last argument is a function
|
22
|
+
// $('#users').items(10).invoke('charge!', function(){
|
23
|
+
//
|
24
|
+
// })
|
@@ -0,0 +1,43 @@
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
|
2
|
+
"http://www.w3.org/TR/html4/strict.dtd">
|
3
|
+
|
4
|
+
<html lang="en">
|
5
|
+
<head>
|
6
|
+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
7
|
+
<title>twitter</title>
|
8
|
+
<meta name="generator" content="TextMate http://macromates.com/">
|
9
|
+
<meta name="author" content="Alex MacCaw">
|
10
|
+
<!-- Date: 2009-01-10 -->
|
11
|
+
<script src="jquery.js" type="text/javascript" charset="utf-8"></script>
|
12
|
+
<script src="chain.js" type="text/javascript" charset="utf-8"></script>
|
13
|
+
<script src="bowline.js" type="text/javascript" charset="utf-8"></script>
|
14
|
+
<script type="text/javascript" charset="utf-8">
|
15
|
+
jQuery(function($){
|
16
|
+
var tweets = $('#tweets').bowline.init('twitter_binder');
|
17
|
+
|
18
|
+
// Update status
|
19
|
+
var update = function(){
|
20
|
+
tweets.invoke('update', $('#update').val());
|
21
|
+
}
|
22
|
+
|
23
|
+
// Add event handlers
|
24
|
+
$('#updateForm').submit(update);
|
25
|
+
|
26
|
+
tweets.invoke('index');
|
27
|
+
});
|
28
|
+
</script>
|
29
|
+
</head>
|
30
|
+
<body>
|
31
|
+
<div id="tweets">
|
32
|
+
<div class="item">
|
33
|
+
<img class="profile_image_url" />
|
34
|
+
<span class="text">Loading...</span>
|
35
|
+
</div>
|
36
|
+
</div>
|
37
|
+
|
38
|
+
<form action="updateForm" method="get" accept-charset="utf-8">
|
39
|
+
<input type="text" name="update" id="update">
|
40
|
+
<input type="submit" value="Update →">
|
41
|
+
</form>
|
42
|
+
</body>
|
43
|
+
</html>
|
@@ -0,0 +1,40 @@
|
|
1
|
+
class TwitterBinder < Bowline::Collection
|
2
|
+
class << self
|
3
|
+
# What about filters - should they be implemented?
|
4
|
+
cattr_accessor :user, :pass
|
5
|
+
|
6
|
+
def index
|
7
|
+
self.items = twit.timeline(:user)
|
8
|
+
end
|
9
|
+
|
10
|
+
def update(text)
|
11
|
+
twit.update(text)
|
12
|
+
index # update timeline
|
13
|
+
end
|
14
|
+
|
15
|
+
def login
|
16
|
+
self.user, self.pass = params[:user], params[:pass]
|
17
|
+
if logged_in?
|
18
|
+
show_view :twitter
|
19
|
+
index
|
20
|
+
else
|
21
|
+
js.alert('Credentials invalid')
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def logged_in?
|
26
|
+
return false unless self.user && self.pass
|
27
|
+
begin
|
28
|
+
twit.timeline && true
|
29
|
+
rescue Twitter::CantConnect
|
30
|
+
false
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
protected
|
35
|
+
|
36
|
+
def twit
|
37
|
+
Twitter::Base.new(self.user, self.pass)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
|
2
|
+
"http://www.w3.org/TR/html4/strict.dtd">
|
3
|
+
|
4
|
+
<html lang="en">
|
5
|
+
<head>
|
6
|
+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
7
|
+
<title>twitter_login</title>
|
8
|
+
<meta name="generator" content="TextMate http://macromates.com/">
|
9
|
+
<meta name="author" content="Alex MacCaw">
|
10
|
+
<!-- Date: 2009-01-10 -->
|
11
|
+
<script src="jquery.js" type="text/javascript" charset="utf-8"></script>
|
12
|
+
<script src="chain.js" type="text/javascript" charset="utf-8"></script>
|
13
|
+
<script src="bowline.js" type="text/javascript" charset="utf-8"></script>
|
14
|
+
</head>
|
15
|
+
<body>
|
16
|
+
<script type="text/javascript" charset="utf-8">
|
17
|
+
jQuery(function($){
|
18
|
+
$.setupForms();
|
19
|
+
});
|
20
|
+
</script>
|
21
|
+
|
22
|
+
<form action="twitter_binder.login" method="get">
|
23
|
+
<input type="text" name="user" id="user">
|
24
|
+
<input type="password" name="pass" id="pass">
|
25
|
+
|
26
|
+
<p><input type="submit" value="Login →"></p>
|
27
|
+
</form>
|
28
|
+
</body>
|
29
|
+
</html>
|
@@ -0,0 +1,39 @@
|
|
1
|
+
class UsersBinder < Bowline::Collection
|
2
|
+
class << self
|
3
|
+
# self.items is a special method
|
4
|
+
# Basically it'll update users on the client side
|
5
|
+
def index
|
6
|
+
self.items = User.all
|
7
|
+
end
|
8
|
+
|
9
|
+
# def index(offset)
|
10
|
+
# self.items = User.all(:conditions => ['id > ?', offset])
|
11
|
+
# end
|
12
|
+
|
13
|
+
def admins
|
14
|
+
self.items = User.admins.all
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def update(attrs)
|
19
|
+
if @item.update_attributes(attrs)
|
20
|
+
flash[:notice] = "Successfully updated"
|
21
|
+
else
|
22
|
+
flash[:notice] = "Errors updating users"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def highlight
|
27
|
+
# Calls $('user_1').highlight()
|
28
|
+
self.element.highlight
|
29
|
+
end
|
30
|
+
|
31
|
+
# Overrides charge on user
|
32
|
+
def charge!
|
33
|
+
# calls charge! on model (i.e. do sql commit )
|
34
|
+
self.item.charge!
|
35
|
+
# Now gui stuff
|
36
|
+
flash[:notice] = "Successfully charged"
|
37
|
+
highlight
|
38
|
+
end
|
39
|
+
end
|
data/lib/bowline.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
module Bowline
|
2
|
+
VERSION = '0.1.1'
|
3
|
+
|
4
|
+
# The raw JavaScript window object
|
5
|
+
def self.js
|
6
|
+
if defined?($app_window)
|
7
|
+
$app_window
|
8
|
+
else
|
9
|
+
Class.new {
|
10
|
+
def self.method_missing(*a)
|
11
|
+
Bowline.logger.info "Sending to Window: #{a.inspect}"
|
12
|
+
self
|
13
|
+
end
|
14
|
+
}
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Change which page we're on
|
19
|
+
def self.show_view(name)
|
20
|
+
js.window.location = "app://public/#{name}.html"
|
21
|
+
end
|
22
|
+
|
23
|
+
class Base
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
$LOAD_PATH << File.dirname(__FILE__)
|
28
|
+
|
29
|
+
require 'bowline/ext/object'
|
30
|
+
require 'bowline/ext/array'
|
31
|
+
require 'bowline/ext/class'
|
32
|
+
require 'bowline/ext/string'
|
33
|
+
|
34
|
+
require 'bowline/gem_dependency'
|
35
|
+
require 'bowline/initializer'
|
36
|
+
|
37
|
+
require 'bowline/jquery'
|
38
|
+
require 'bowline/observer'
|
39
|
+
|
40
|
+
require 'bowline/binders'
|
41
|
+
require 'bowline/binders/collection'
|
42
|
+
require 'bowline/binders/singleton'
|
@@ -0,0 +1,177 @@
|
|
1
|
+
module Bowline
|
2
|
+
module Binders
|
3
|
+
class Base
|
4
|
+
cattr_accessor :params
|
5
|
+
|
6
|
+
class << self
|
7
|
+
# See Bowline::js
|
8
|
+
def js
|
9
|
+
Bowline::js
|
10
|
+
end
|
11
|
+
|
12
|
+
# Equivalent of the 'jQuery' function
|
13
|
+
def jquery
|
14
|
+
@@jquery ||= JQuery.new
|
15
|
+
end
|
16
|
+
|
17
|
+
# See the Observer class
|
18
|
+
def observer
|
19
|
+
@@observer ||= Observer.new
|
20
|
+
end
|
21
|
+
|
22
|
+
# See Bowline::logger
|
23
|
+
def logger
|
24
|
+
Bowline::logger
|
25
|
+
end
|
26
|
+
|
27
|
+
# See Bowline::show_view
|
28
|
+
def show_view(*args)
|
29
|
+
Bowline::show_view(*args)
|
30
|
+
end
|
31
|
+
|
32
|
+
def params=(p)
|
33
|
+
case p
|
34
|
+
when String
|
35
|
+
# Params comes in a string (since it's a
|
36
|
+
# serialized form) - we need to make it into
|
37
|
+
# a nestled hash.
|
38
|
+
# Stolen from Ramaze
|
39
|
+
m = proc {|_,o,n|o.merge(n,&m)}
|
40
|
+
@@params = params.inject({}) do |hash, (key, value)|
|
41
|
+
parts = key.split(/[\]\[]+/)
|
42
|
+
hash.merge(parts.reverse.inject(value) { |x, i| {i => x} }, &m)
|
43
|
+
end
|
44
|
+
else
|
45
|
+
@@params = p
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def setup(d)
|
50
|
+
@@elements ||= []
|
51
|
+
@@elements << d
|
52
|
+
self.item_sync!
|
53
|
+
end
|
54
|
+
|
55
|
+
def instance(el)
|
56
|
+
self.new(el).method(:send)
|
57
|
+
end
|
58
|
+
|
59
|
+
# todo - flash?
|
60
|
+
|
61
|
+
def inherited(child)
|
62
|
+
return if self == Bowline::Binders::Base
|
63
|
+
return if child == Bowline::Binders::Singleton
|
64
|
+
return if child == Bowline::Binders::Collection
|
65
|
+
name = child.name.underscore
|
66
|
+
name = name.split('/').last
|
67
|
+
js.send("bowline_#{name}_setup=", child.method(:setup))
|
68
|
+
js.send("bowline_#{name}_instance=", child.method(:instance))
|
69
|
+
js.send("bowline_#{name}=", child.method(:send))
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
attr_reader :element
|
74
|
+
attr_reader :item
|
75
|
+
|
76
|
+
# Todo
|
77
|
+
# We want initialize method to take
|
78
|
+
# no argument, and for every item in items
|
79
|
+
# to have initialize called on startup,
|
80
|
+
# so they can set up event handlers etc
|
81
|
+
def self.new(element, *args) #:nodoc:
|
82
|
+
allocate.instance_eval do
|
83
|
+
# jQuery element
|
84
|
+
@element = element
|
85
|
+
# Calling chain.js 'item' function
|
86
|
+
@item = element.item()
|
87
|
+
if @item
|
88
|
+
@item.with_indifferent_access
|
89
|
+
# If possible, find Ruby object
|
90
|
+
if @item[:id] && respond_to?(:find)
|
91
|
+
@item = find(@item[:id])
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
initialize(*args)
|
96
|
+
self
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# Trigger jQuery events on this element
|
101
|
+
def trigger(event, data = nil)
|
102
|
+
self.element.trigger(event, data)
|
103
|
+
end
|
104
|
+
|
105
|
+
# Bind event to element:
|
106
|
+
# bind(:click) { puts "element clicked" }
|
107
|
+
# todo - two events with the same item/event overwrite each other
|
108
|
+
# todo - need initalize method on class - so we can set events there
|
109
|
+
def bind(event, method_name, &block)
|
110
|
+
event_name = [event, item_id].join(":")
|
111
|
+
callback = block
|
112
|
+
callback ||= begin
|
113
|
+
method_name.is_a?(Method) ?
|
114
|
+
method_name : method(method_name)
|
115
|
+
end
|
116
|
+
self.observer.append(event_name, callback)
|
117
|
+
self.element.bind(
|
118
|
+
event.to_s,
|
119
|
+
event_name,
|
120
|
+
self.observer.method(:call)
|
121
|
+
)
|
122
|
+
end
|
123
|
+
|
124
|
+
def click(method_name = nil, &block)
|
125
|
+
bind(:click, method, &block)
|
126
|
+
end
|
127
|
+
|
128
|
+
# Raw DOM element
|
129
|
+
def dom
|
130
|
+
self.element[0]
|
131
|
+
end
|
132
|
+
|
133
|
+
# Shortcut methods
|
134
|
+
|
135
|
+
# See self.class.show_view
|
136
|
+
def show_view(*args)
|
137
|
+
self.class.show_view(*args)
|
138
|
+
end
|
139
|
+
|
140
|
+
# See self.class.js
|
141
|
+
def js
|
142
|
+
self.class.js
|
143
|
+
end
|
144
|
+
alias :page :js
|
145
|
+
|
146
|
+
# See self.class.jquery
|
147
|
+
def jquery
|
148
|
+
self.class.jquery
|
149
|
+
end
|
150
|
+
|
151
|
+
# See self.class.observer
|
152
|
+
def observer
|
153
|
+
self.class.observer
|
154
|
+
end
|
155
|
+
|
156
|
+
# See self.class.logger
|
157
|
+
def logger
|
158
|
+
self.class.logger
|
159
|
+
end
|
160
|
+
|
161
|
+
private
|
162
|
+
# This is just a unique identifier
|
163
|
+
# for the item - and isn't
|
164
|
+
# used in the dom
|
165
|
+
def item_id
|
166
|
+
if item.respond_to?(:dom_id)
|
167
|
+
item.dom_id
|
168
|
+
else
|
169
|
+
[
|
170
|
+
item.id,
|
171
|
+
self.class.name.underscore
|
172
|
+
].join("_")
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|