jnewland-god_web 0.0.2 → 0.1.3
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.textile +82 -0
- data/bin/god_web +46 -25
- data/lib/environment.rb +26 -0
- data/lib/god_web.rb +165 -0
- data/public/iui/backButton.png +0 -0
- data/public/iui/blueButton.png +0 -0
- data/public/iui/cancel.png +0 -0
- data/public/iui/grayButton.png +0 -0
- data/public/iui/iui.css +372 -0
- data/public/iui/iui.js +383 -0
- data/public/iui/iuix.css +1 -0
- data/public/iui/iuix.js +1 -0
- data/public/iui/listArrow.png +0 -0
- data/public/iui/listArrowSel.png +0 -0
- data/public/iui/listGroup.png +0 -0
- data/public/iui/loading.gif +0 -0
- data/public/iui/pinstripes.png +0 -0
- data/public/iui/selection.png +0 -0
- data/public/iui/thumb.png +0 -0
- data/public/iui/toggle.png +0 -0
- data/public/iui/toggleOn.png +0 -0
- data/public/iui/toolButton.png +0 -0
- data/public/iui/toolbar.png +0 -0
- data/public/iui/whiteButton.png +0 -0
- data/views/command.erb +3 -0
- data/views/status.erb +27 -0
- data/views/watch.erb +5 -0
- metadata +32 -7
- data/Readme.txt +0 -55
data/Readme.textile
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
h2. Description
|
2
|
+
|
3
|
+
iPhone friendly web UI "God":http://god.rubyforge.org/
|
4
|
+
|
5
|
+
h2. Screenshots
|
6
|
+
|
7
|
+
"!http://farm3.static.flickr.com/2281/2505507050_2f8fc39795_m.jpg!":http://www.flickr.com/photos/jnewland/2505507050/
|
8
|
+
"!http://farm3.static.flickr.com/2420/2504730261_06ac1ba923_m.jpg!":http://www.flickr.com/photos/jnewland/2504730261/
|
9
|
+
|
10
|
+
h2. Requirements
|
11
|
+
|
12
|
+
* "God":http://god.rubyforge.org/
|
13
|
+
* "Sinatra":http://sinatrarb.com/
|
14
|
+
|
15
|
+
h2. Install
|
16
|
+
|
17
|
+
<pre>
|
18
|
+
<code>
|
19
|
+
git clone git://github.com/jnewland/god_web.git
|
20
|
+
cd god_web
|
21
|
+
gem build god_web.gemspec
|
22
|
+
sudo gem install -l god_web-*.gem
|
23
|
+
</code>
|
24
|
+
</pre>
|
25
|
+
|
26
|
+
h2. Usage
|
27
|
+
|
28
|
+
In your God config:
|
29
|
+
|
30
|
+
<pre>
|
31
|
+
<code>
|
32
|
+
require 'god_web'
|
33
|
+
GodWeb.watch
|
34
|
+
</code>
|
35
|
+
</pre>
|
36
|
+
|
37
|
+
This will create a God watch that runs and monitors GodWeb on port 8888.
|
38
|
+
|
39
|
+
Optionally, you can password protect your @god_web@ instance. To do so, create
|
40
|
+
a YAML config file with username and password keys, like so:
|
41
|
+
|
42
|
+
<pre>
|
43
|
+
<code>
|
44
|
+
username: foo
|
45
|
+
password: sekret
|
46
|
+
</code>
|
47
|
+
</pre>
|
48
|
+
|
49
|
+
Then provide the full path to that yaml file as an option to the @GodWeb.watch@
|
50
|
+
call:
|
51
|
+
|
52
|
+
<pre>
|
53
|
+
<code>
|
54
|
+
require 'god_web'
|
55
|
+
GodWeb.watch(:config => '/full/path/to/god_web.yaml')
|
56
|
+
</code>
|
57
|
+
</pre>
|
58
|
+
|
59
|
+
h2. Contributing
|
60
|
+
|
61
|
+
god_web uses "ditz":http://ditz.rubyforge.org for issue tracking. Fork
|
62
|
+
god_web, clone your copy and then run:
|
63
|
+
|
64
|
+
@ditz todo@
|
65
|
+
|
66
|
+
For more details on a specific issue:
|
67
|
+
|
68
|
+
@ditz show god_web-1@
|
69
|
+
|
70
|
+
Make your changes that fix a bug, then resolve it.
|
71
|
+
|
72
|
+
@ditz close god_web-1@
|
73
|
+
|
74
|
+
Commit, push your changes to GitHub, then send a pull request!
|
75
|
+
|
76
|
+
h3. Author
|
77
|
+
|
78
|
+
"Jesse Newland":http://jnewland.com/
|
79
|
+
|
80
|
+
h3. License
|
81
|
+
|
82
|
+
"WTFPL":http://sam.zoy.org/wtfpl/
|
data/bin/god_web
CHANGED
@@ -1,36 +1,57 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
require '
|
4
|
-
require 'god'
|
5
|
-
require 'sinatra'
|
6
|
-
require 'stringio'
|
7
|
-
require 'yaml'
|
8
|
-
#included until http://sinatra.lighthouseapp.com/projects/9779/tickets/16-patch-http-authentication is in a released version
|
9
|
-
require File.dirname(__FILE__) + '/../lib/sinatra_http_auth'
|
10
|
-
|
11
|
-
config = {
|
12
|
-
'god_port' => 17165,
|
13
|
-
'username' => nil,
|
14
|
-
'password' => nil
|
15
|
-
}
|
16
|
-
begin
|
17
|
-
config.merge!(YAML.load(File.read(ARGV[0])))
|
18
|
-
rescue
|
19
|
-
end
|
3
|
+
require File.dirname(__FILE__) + '/../lib/environment'
|
20
4
|
|
21
5
|
before do
|
22
|
-
unless
|
6
|
+
unless (GODWEB_CONFIG['username'].nil? && GODWEB_CONFIG['password'].nil?) || self.request.path_info == '/heartbeat'
|
23
7
|
authenticate_or_request_with_http_basic "GodWeb" do
|
24
|
-
|user, pass| user ==
|
8
|
+
|user, pass| user == GODWEB_CONFIG['username'] && pass == GODWEB_CONFIG['password']
|
25
9
|
end
|
26
10
|
end
|
11
|
+
GODWEB.ping
|
27
12
|
end
|
28
13
|
|
29
14
|
get '/' do
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
15
|
+
@statuses = GODWEB.status
|
16
|
+
@watches = []
|
17
|
+
@statuses.each do |watch, status|
|
18
|
+
@watches << watch.to_s
|
19
|
+
end
|
20
|
+
@watches.sort!
|
21
|
+
@groups = GODWEB.groups
|
22
|
+
show(:status)
|
23
|
+
end
|
24
|
+
|
25
|
+
get '/w/:watch' do
|
26
|
+
@watch = params["watch"]
|
27
|
+
@status = GODWEB.status[@watch][:state]
|
28
|
+
@commands = GodWeb.possible_statuses(@status)
|
29
|
+
show(:watch, "#{@watch} [#{@status}]")
|
36
30
|
end
|
31
|
+
|
32
|
+
get '/g/:group' do
|
33
|
+
@watch = @group = params["group"]
|
34
|
+
@status = nil
|
35
|
+
@commands = GodWeb.possible_statuses(@status)
|
36
|
+
show(:watch, "#{@group} [group]")
|
37
|
+
end
|
38
|
+
|
39
|
+
get '/w/:watch/:command' do
|
40
|
+
@watch = params["watch"]
|
41
|
+
@command = params["command"]
|
42
|
+
@success = GODWEB.send(@command, @watch)
|
43
|
+
@success = false if @success == []
|
44
|
+
show(:command, "#{@command}ing #{@watch}")
|
45
|
+
end
|
46
|
+
|
47
|
+
get '/heartbeat' do
|
48
|
+
@statuses = GODWEB.status
|
49
|
+
'OK'
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def show(template, title = 'GodWeb')
|
55
|
+
@title = title
|
56
|
+
erb(template)
|
57
|
+
end
|
data/lib/environment.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'god'
|
3
|
+
require 'sinatra'
|
4
|
+
require 'stringio'
|
5
|
+
require 'yaml'
|
6
|
+
require 'erb'
|
7
|
+
#included until http://sinatra.lighthouseapp.com/projects/9779/tickets/16-patch-http-authentication is in a released version
|
8
|
+
require File.dirname(__FILE__) + '/sinatra_http_auth'
|
9
|
+
require File.dirname(__FILE__) + '/god_web'
|
10
|
+
|
11
|
+
config = {
|
12
|
+
'god_port' => 17165,
|
13
|
+
'username' => nil,
|
14
|
+
'password' => nil
|
15
|
+
}
|
16
|
+
begin
|
17
|
+
config.merge!(YAML.load(File.read(ARGV[0])))
|
18
|
+
GODWEB_CONFIG = config
|
19
|
+
rescue
|
20
|
+
GODWEB_CONFIG = config
|
21
|
+
end
|
22
|
+
|
23
|
+
GODWEB = GodWeb.new(config)
|
24
|
+
|
25
|
+
Sinatra.application.options.public = File.dirname(__FILE__) + "/../public"
|
26
|
+
Sinatra.application.options.views = File.dirname(__FILE__) + "/../views"
|
data/lib/god_web.rb
ADDED
@@ -0,0 +1,165 @@
|
|
1
|
+
class GodWeb
|
2
|
+
def initialize(config)
|
3
|
+
@config = config
|
4
|
+
setup
|
5
|
+
ping
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.watch(options = {})
|
9
|
+
options[:port] ||= 8888
|
10
|
+
options[:environment] ||= 'production'
|
11
|
+
start_string = "god_web #{options[:config]} -e #{options[:environment]} -p #{options[:port]}"
|
12
|
+
God.watch do |w|
|
13
|
+
w.name = "god_web"
|
14
|
+
w.interval = 1.minute
|
15
|
+
w.start = "god_web -e production -p 8888"
|
16
|
+
w.start_grace = 10.seconds
|
17
|
+
w.restart_grace = 10.seconds
|
18
|
+
|
19
|
+
w.start_if do |start|
|
20
|
+
start.condition(:process_running) do |c|
|
21
|
+
c.running = false
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
w.restart_if do |restart|
|
26
|
+
restart.condition(:memory_usage) do |c|
|
27
|
+
c.above = 20.megabytes
|
28
|
+
c.times = [3, 5]
|
29
|
+
end
|
30
|
+
|
31
|
+
restart.condition(:cpu_usage) do |c|
|
32
|
+
c.above = 25.percent
|
33
|
+
c.times = 5
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
w.lifecycle do |on|
|
38
|
+
on.condition(:flapping) do |c|
|
39
|
+
c.to_state = [:start, :restart]
|
40
|
+
c.times = 5
|
41
|
+
c.within = 5.minute
|
42
|
+
c.transition = :unmonitored
|
43
|
+
c.retry_in = 10.minutes
|
44
|
+
c.retry_times = 5
|
45
|
+
c.retry_within = 2.hours
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def setup
|
52
|
+
DRb.start_service
|
53
|
+
@server = DRbObject.new(nil, God::Socket.socket(@config['god_port']))
|
54
|
+
end
|
55
|
+
|
56
|
+
# ping server to ensure that it is responsive
|
57
|
+
def ping
|
58
|
+
tries = 3
|
59
|
+
begin
|
60
|
+
@server.ping
|
61
|
+
rescue Exception => e
|
62
|
+
if (tries -= 1) > 0
|
63
|
+
retry
|
64
|
+
end
|
65
|
+
raise e, "The server is not available (or you do not have permissions to access it)"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.possible_statuses(status)
|
70
|
+
case status
|
71
|
+
when :up
|
72
|
+
return %w{stop restart unmonitor}
|
73
|
+
when :unmonitored
|
74
|
+
return %w{start monitor}
|
75
|
+
else
|
76
|
+
return %w{start stop restart}
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
|
82
|
+
def method_missing(meth,*args)
|
83
|
+
if %w{groups status log quit terminate}.include?(meth.to_s)
|
84
|
+
ping
|
85
|
+
send("#{meth}_command")
|
86
|
+
elsif %w{start stop restart unmonitor monitor}.include?(meth.to_s)
|
87
|
+
ping
|
88
|
+
lifecycle_command(args.first, meth.to_s)
|
89
|
+
else
|
90
|
+
raise NoMethodError
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def groups_command
|
95
|
+
groups = []
|
96
|
+
@server.groups.each do |key, value|
|
97
|
+
groups << key
|
98
|
+
end
|
99
|
+
groups.sort
|
100
|
+
end
|
101
|
+
|
102
|
+
def status_command
|
103
|
+
@server.status
|
104
|
+
end
|
105
|
+
|
106
|
+
#TODO
|
107
|
+
# def log_command
|
108
|
+
# begin
|
109
|
+
# Signal.trap('INT') { exit }
|
110
|
+
# name = @args[1]
|
111
|
+
#
|
112
|
+
# unless name
|
113
|
+
# puts "You must specify a Task or Group name"
|
114
|
+
# exit!
|
115
|
+
# end
|
116
|
+
#
|
117
|
+
# t = Time.at(0)
|
118
|
+
# loop do
|
119
|
+
# print @server.running_log(name, t)
|
120
|
+
# t = Time.now
|
121
|
+
# sleep 1
|
122
|
+
# end
|
123
|
+
# rescue God::NoSuchWatchError
|
124
|
+
# puts "No such watch"
|
125
|
+
# rescue DRb::DRbConnError
|
126
|
+
# puts "The server went away"
|
127
|
+
# end
|
128
|
+
# end
|
129
|
+
|
130
|
+
def quit_command
|
131
|
+
begin
|
132
|
+
@server.terminate
|
133
|
+
return false
|
134
|
+
rescue DRb::DRbConnError
|
135
|
+
return true
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def terminate_command
|
140
|
+
stopped_all = false
|
141
|
+
if @server.stop_all
|
142
|
+
stopped_all = true
|
143
|
+
end
|
144
|
+
|
145
|
+
begin
|
146
|
+
@server.terminate
|
147
|
+
return false
|
148
|
+
rescue DRb::DRbConnError
|
149
|
+
return stopped_all
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
|
154
|
+
def lifecycle_command(*args)
|
155
|
+
# get the name of the watch/group
|
156
|
+
name = args.first
|
157
|
+
command = args.last
|
158
|
+
|
159
|
+
# send @command
|
160
|
+
watches = @server.control(name, command)
|
161
|
+
|
162
|
+
watches.empty? ? [] : watches
|
163
|
+
end
|
164
|
+
|
165
|
+
end
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
data/public/iui/iui.css
ADDED
@@ -0,0 +1,372 @@
|
|
1
|
+
/* iui.css (c) 2007 by iUI Project Members, see LICENSE.txt for license */
|
2
|
+
body {
|
3
|
+
margin: 0;
|
4
|
+
font-family: Helvetica;
|
5
|
+
background: #FFFFFF;
|
6
|
+
color: #000000;
|
7
|
+
overflow-x: hidden;
|
8
|
+
-webkit-user-select: none;
|
9
|
+
-webkit-text-size-adjust: none;
|
10
|
+
}
|
11
|
+
|
12
|
+
body > *:not(.toolbar) {
|
13
|
+
display: none;
|
14
|
+
position: absolute;
|
15
|
+
margin: 0;
|
16
|
+
padding: 0;
|
17
|
+
left: 0;
|
18
|
+
top: 45px;
|
19
|
+
width: 100%;
|
20
|
+
min-height: 372px;
|
21
|
+
}
|
22
|
+
|
23
|
+
body[orient="landscape"] > *:not(.toolbar) {
|
24
|
+
min-height: 268px;
|
25
|
+
}
|
26
|
+
|
27
|
+
body > *[selected="true"] {
|
28
|
+
display: block;
|
29
|
+
}
|
30
|
+
|
31
|
+
a[selected], a:active {
|
32
|
+
background-color: #194fdb !important;
|
33
|
+
background-image: url(listArrowSel.png), url(selection.png) !important;
|
34
|
+
background-repeat: no-repeat, repeat-x;
|
35
|
+
background-position: right center, left top;
|
36
|
+
color: #FFFFFF !important;
|
37
|
+
}
|
38
|
+
|
39
|
+
a[selected="progress"] {
|
40
|
+
background-image: url(loading.gif), url(selection.png) !important;
|
41
|
+
}
|
42
|
+
|
43
|
+
/************************************************************************************************/
|
44
|
+
|
45
|
+
body > .toolbar {
|
46
|
+
box-sizing: border-box;
|
47
|
+
-moz-box-sizing: border-box;
|
48
|
+
-webkit-box-sizing: border-box;
|
49
|
+
border-bottom: 1px solid #2d3642;
|
50
|
+
border-top: 1px solid #6d84a2;
|
51
|
+
padding: 10px;
|
52
|
+
height: 45px;
|
53
|
+
background: url(toolbar.png) #6d84a2 repeat-x;
|
54
|
+
}
|
55
|
+
|
56
|
+
.toolbar > h1 {
|
57
|
+
position: absolute;
|
58
|
+
overflow: hidden;
|
59
|
+
left: 50%;
|
60
|
+
margin: 1px 0 0 -75px;
|
61
|
+
height: 45px;
|
62
|
+
font-size: 20px;
|
63
|
+
width: 150px;
|
64
|
+
font-weight: bold;
|
65
|
+
text-shadow: rgba(0, 0, 0, 0.4) 0px -1px 0;
|
66
|
+
text-align: center;
|
67
|
+
text-overflow: ellipsis;
|
68
|
+
white-space: nowrap;
|
69
|
+
color: #FFFFFF;
|
70
|
+
}
|
71
|
+
|
72
|
+
body[orient="landscape"] > .toolbar > h1 {
|
73
|
+
margin-left: -125px;
|
74
|
+
width: 250px;
|
75
|
+
}
|
76
|
+
|
77
|
+
.button {
|
78
|
+
position: absolute;
|
79
|
+
overflow: hidden;
|
80
|
+
top: 8px;
|
81
|
+
right: 6px;
|
82
|
+
margin: 0;
|
83
|
+
border-width: 0 5px;
|
84
|
+
padding: 0 3px;
|
85
|
+
width: auto;
|
86
|
+
height: 30px;
|
87
|
+
line-height: 30px;
|
88
|
+
font-family: inherit;
|
89
|
+
font-size: 12px;
|
90
|
+
font-weight: bold;
|
91
|
+
color: #FFFFFF;
|
92
|
+
text-shadow: rgba(0, 0, 0, 0.6) 0px -1px 0;
|
93
|
+
text-overflow: ellipsis;
|
94
|
+
text-decoration: none;
|
95
|
+
white-space: nowrap;
|
96
|
+
background: none;
|
97
|
+
-webkit-border-image: url(toolButton.png) 0 5 0 5;
|
98
|
+
}
|
99
|
+
|
100
|
+
.blueButton {
|
101
|
+
-webkit-border-image: url(blueButton.png) 0 5 0 5;
|
102
|
+
border-width: 0 5px;
|
103
|
+
}
|
104
|
+
|
105
|
+
.leftButton {
|
106
|
+
left: 6px;
|
107
|
+
right: auto;
|
108
|
+
}
|
109
|
+
|
110
|
+
#backButton {
|
111
|
+
display: none;
|
112
|
+
left: 6px;
|
113
|
+
right: auto;
|
114
|
+
padding: 0;
|
115
|
+
max-width: 55px;
|
116
|
+
border-width: 0 8px 0 14px;
|
117
|
+
-webkit-border-image: url(backButton.png) 0 8 0 14;
|
118
|
+
}
|
119
|
+
|
120
|
+
.whiteButton,
|
121
|
+
.grayButton {
|
122
|
+
display: block;
|
123
|
+
border-width: 0 12px;
|
124
|
+
padding: 10px;
|
125
|
+
text-align: center;
|
126
|
+
font-size: 20px;
|
127
|
+
font-weight: bold;
|
128
|
+
text-decoration: inherit;
|
129
|
+
color: inherit;
|
130
|
+
}
|
131
|
+
|
132
|
+
.whiteButton {
|
133
|
+
-webkit-border-image: url(whiteButton.png) 0 12 0 12;
|
134
|
+
text-shadow: rgba(255, 255, 255, 0.7) 0 1px 0;
|
135
|
+
}
|
136
|
+
|
137
|
+
.grayButton {
|
138
|
+
-webkit-border-image: url(grayButton.png) 0 12 0 12;
|
139
|
+
color: #FFFFFF;
|
140
|
+
}
|
141
|
+
|
142
|
+
/************************************************************************************************/
|
143
|
+
|
144
|
+
body > ul > li {
|
145
|
+
position: relative;
|
146
|
+
margin: 0;
|
147
|
+
border-bottom: 1px solid #E0E0E0;
|
148
|
+
padding: 8px 0 8px 10px;
|
149
|
+
font-size: 20px;
|
150
|
+
font-weight: bold;
|
151
|
+
list-style: none;
|
152
|
+
}
|
153
|
+
|
154
|
+
body > ul > li.group {
|
155
|
+
position: relative;
|
156
|
+
top: -1px;
|
157
|
+
margin-bottom: -2px;
|
158
|
+
border-top: 1px solid #7d7d7d;
|
159
|
+
border-bottom: 1px solid #999999;
|
160
|
+
padding: 1px 10px;
|
161
|
+
background: url(listGroup.png) repeat-x;
|
162
|
+
font-size: 17px;
|
163
|
+
font-weight: bold;
|
164
|
+
text-shadow: rgba(0, 0, 0, 0.4) 0 1px 0;
|
165
|
+
color: #FFFFFF;
|
166
|
+
}
|
167
|
+
|
168
|
+
body > ul > li.group:first-child {
|
169
|
+
top: 0;
|
170
|
+
border-top: none;
|
171
|
+
}
|
172
|
+
|
173
|
+
body > ul > li > a {
|
174
|
+
display: block;
|
175
|
+
margin: -8px 0 -8px -10px;
|
176
|
+
padding: 8px 32px 8px 10px;
|
177
|
+
text-decoration: none;
|
178
|
+
color: inherit;
|
179
|
+
background: url(listArrow.png) no-repeat right center;
|
180
|
+
}
|
181
|
+
|
182
|
+
a[target="_replace"] {
|
183
|
+
box-sizing: border-box;
|
184
|
+
-webkit-box-sizing: border-box;
|
185
|
+
padding-top: 25px;
|
186
|
+
padding-bottom: 25px;
|
187
|
+
font-size: 18px;
|
188
|
+
color: cornflowerblue;
|
189
|
+
background-color: #FFFFFF;
|
190
|
+
background-image: none;
|
191
|
+
}
|
192
|
+
|
193
|
+
/************************************************************************************************/
|
194
|
+
|
195
|
+
body > .dialog {
|
196
|
+
top: 0;
|
197
|
+
width: 100%;
|
198
|
+
min-height: 417px;
|
199
|
+
z-index: 2;
|
200
|
+
background: rgba(0, 0, 0, 0.8);
|
201
|
+
padding: 0;
|
202
|
+
text-align: right;
|
203
|
+
}
|
204
|
+
|
205
|
+
.dialog > fieldset {
|
206
|
+
box-sizing: border-box;
|
207
|
+
-webkit-box-sizing: border-box;
|
208
|
+
width: 100%;
|
209
|
+
margin: 0;
|
210
|
+
border: none;
|
211
|
+
border-top: 1px solid #6d84a2;
|
212
|
+
padding: 10px 6px;
|
213
|
+
background: url(toolbar.png) #7388a5 repeat-x;
|
214
|
+
}
|
215
|
+
|
216
|
+
.dialog > fieldset > h1 {
|
217
|
+
margin: 0 10px 0 10px;
|
218
|
+
padding: 0;
|
219
|
+
font-size: 20px;
|
220
|
+
font-weight: bold;
|
221
|
+
color: #FFFFFF;
|
222
|
+
text-shadow: rgba(0, 0, 0, 0.4) 0px -1px 0;
|
223
|
+
text-align: center;
|
224
|
+
}
|
225
|
+
|
226
|
+
.dialog > fieldset > label {
|
227
|
+
position: absolute;
|
228
|
+
margin: 16px 0 0 6px;
|
229
|
+
font-size: 14px;
|
230
|
+
color: #999999;
|
231
|
+
}
|
232
|
+
|
233
|
+
input {
|
234
|
+
box-sizing: border-box;
|
235
|
+
-webkit-box-sizing: border-box;
|
236
|
+
width: 100%;
|
237
|
+
margin: 8px 0 0 0;
|
238
|
+
padding: 6px 6px 6px 44px;
|
239
|
+
font-size: 16px;
|
240
|
+
font-weight: normal;
|
241
|
+
}
|
242
|
+
|
243
|
+
/************************************************************************************************/
|
244
|
+
|
245
|
+
body > .panel {
|
246
|
+
box-sizing: border-box;
|
247
|
+
-webkit-box-sizing: border-box;
|
248
|
+
padding: 10px;
|
249
|
+
background: #c8c8c8 url(pinstripes.png);
|
250
|
+
}
|
251
|
+
|
252
|
+
.panel > fieldset {
|
253
|
+
position: relative;
|
254
|
+
margin: 0 0 20px 0;
|
255
|
+
padding: 0;
|
256
|
+
background: #FFFFFF;
|
257
|
+
-webkit-border-radius: 10px;
|
258
|
+
border: 1px solid #999999;
|
259
|
+
text-align: right;
|
260
|
+
font-size: 16px;
|
261
|
+
}
|
262
|
+
|
263
|
+
.row {
|
264
|
+
position: relative;
|
265
|
+
min-height: 42px;
|
266
|
+
border-bottom: 1px solid #999999;
|
267
|
+
-webkit-border-radius: 0;
|
268
|
+
text-align: right;
|
269
|
+
}
|
270
|
+
|
271
|
+
fieldset > .row:last-child {
|
272
|
+
border-bottom: none !important;
|
273
|
+
}
|
274
|
+
|
275
|
+
.row > input {
|
276
|
+
box-sizing: border-box;
|
277
|
+
-webkit-box-sizing: border-box;
|
278
|
+
margin: 0;
|
279
|
+
border: none;
|
280
|
+
padding: 12px 10px 0 110px;
|
281
|
+
height: 42px;
|
282
|
+
background: none;
|
283
|
+
}
|
284
|
+
|
285
|
+
.row > label {
|
286
|
+
position: absolute;
|
287
|
+
margin: 0 0 0 14px;
|
288
|
+
line-height: 42px;
|
289
|
+
font-weight: bold;
|
290
|
+
}
|
291
|
+
|
292
|
+
.row > .toggle {
|
293
|
+
position: absolute;
|
294
|
+
top: 6px;
|
295
|
+
right: 6px;
|
296
|
+
width: 100px;
|
297
|
+
height: 28px;
|
298
|
+
}
|
299
|
+
|
300
|
+
.toggle {
|
301
|
+
border: 1px solid #888888;
|
302
|
+
-webkit-border-radius: 6px;
|
303
|
+
background: #FFFFFF url(toggle.png) repeat-x;
|
304
|
+
font-size: 19px;
|
305
|
+
font-weight: bold;
|
306
|
+
line-height: 30px;
|
307
|
+
}
|
308
|
+
|
309
|
+
.toggle[toggled="true"] {
|
310
|
+
border: 1px solid #143fae;
|
311
|
+
background: #194fdb url(toggleOn.png) repeat-x;
|
312
|
+
}
|
313
|
+
|
314
|
+
.toggleOn {
|
315
|
+
display: none;
|
316
|
+
position: absolute;
|
317
|
+
width: 60px;
|
318
|
+
text-align: center;
|
319
|
+
left: 0;
|
320
|
+
top: 0;
|
321
|
+
color: #FFFFFF;
|
322
|
+
text-shadow: rgba(0, 0, 0, 0.4) 0px -1px 0;
|
323
|
+
}
|
324
|
+
|
325
|
+
.toggleOff {
|
326
|
+
position: absolute;
|
327
|
+
width: 60px;
|
328
|
+
text-align: center;
|
329
|
+
right: 0;
|
330
|
+
top: 0;
|
331
|
+
color: #666666;
|
332
|
+
}
|
333
|
+
|
334
|
+
.toggle[toggled="true"] > .toggleOn {
|
335
|
+
display: block;
|
336
|
+
}
|
337
|
+
|
338
|
+
.toggle[toggled="true"] > .toggleOff {
|
339
|
+
display: none;
|
340
|
+
}
|
341
|
+
|
342
|
+
.thumb {
|
343
|
+
position: absolute;
|
344
|
+
top: -1px;
|
345
|
+
left: -1px;
|
346
|
+
width: 40px;
|
347
|
+
height: 28px;
|
348
|
+
border: 1px solid #888888;
|
349
|
+
-webkit-border-radius: 6px;
|
350
|
+
background: #ffffff url(thumb.png) repeat-x;
|
351
|
+
}
|
352
|
+
|
353
|
+
.toggle[toggled="true"] > .thumb {
|
354
|
+
left: auto;
|
355
|
+
right: -1px;
|
356
|
+
}
|
357
|
+
|
358
|
+
.panel > h2 {
|
359
|
+
margin: 0 0 8px 14px;
|
360
|
+
font-size: inherit;
|
361
|
+
font-weight: bold;
|
362
|
+
color: #4d4d70;
|
363
|
+
text-shadow: rgba(255, 255, 255, 0.75) 2px 2px 0;
|
364
|
+
}
|
365
|
+
|
366
|
+
/************************************************************************************************/
|
367
|
+
|
368
|
+
#preloader {
|
369
|
+
display: none;
|
370
|
+
background-image: url(loading.gif), url(selection.png),
|
371
|
+
url(blueButton.png), url(listArrowSel.png), url(listGroup.png);
|
372
|
+
}
|
data/public/iui/iui.js
ADDED
@@ -0,0 +1,383 @@
|
|
1
|
+
/*
|
2
|
+
Copyright (c) 2007, iUI Project Members
|
3
|
+
See LICENSE.txt for licensing terms
|
4
|
+
*/
|
5
|
+
|
6
|
+
|
7
|
+
(function() {
|
8
|
+
|
9
|
+
var slideSpeed = 20;
|
10
|
+
var slideInterval = 0;
|
11
|
+
|
12
|
+
var currentPage = null;
|
13
|
+
var currentDialog = null;
|
14
|
+
var currentWidth = 0;
|
15
|
+
var currentHash = location.hash;
|
16
|
+
var hashPrefix = "#_";
|
17
|
+
var pageHistory = [];
|
18
|
+
var newPageCount = 0;
|
19
|
+
var checkTimer;
|
20
|
+
|
21
|
+
// *************************************************************************************************
|
22
|
+
|
23
|
+
window.iui =
|
24
|
+
{
|
25
|
+
showPage: function(page, backwards)
|
26
|
+
{
|
27
|
+
if (page)
|
28
|
+
{
|
29
|
+
if (currentDialog)
|
30
|
+
{
|
31
|
+
currentDialog.removeAttribute("selected");
|
32
|
+
currentDialog = null;
|
33
|
+
}
|
34
|
+
|
35
|
+
if (hasClass(page, "dialog"))
|
36
|
+
showDialog(page);
|
37
|
+
else
|
38
|
+
{
|
39
|
+
var fromPage = currentPage;
|
40
|
+
currentPage = page;
|
41
|
+
|
42
|
+
if (fromPage)
|
43
|
+
setTimeout(slidePages, 0, fromPage, page, backwards);
|
44
|
+
else
|
45
|
+
updatePage(page, fromPage);
|
46
|
+
}
|
47
|
+
}
|
48
|
+
},
|
49
|
+
|
50
|
+
showPageById: function(pageId)
|
51
|
+
{
|
52
|
+
var page = $(pageId);
|
53
|
+
if (page)
|
54
|
+
{
|
55
|
+
var index = pageHistory.indexOf(pageId);
|
56
|
+
var backwards = index != -1;
|
57
|
+
if (backwards)
|
58
|
+
pageHistory.splice(index, pageHistory.length);
|
59
|
+
|
60
|
+
iui.showPage(page, backwards);
|
61
|
+
}
|
62
|
+
},
|
63
|
+
|
64
|
+
showPageByHref: function(href, args, method, replace, cb)
|
65
|
+
{
|
66
|
+
var req = new XMLHttpRequest();
|
67
|
+
req.onerror = function()
|
68
|
+
{
|
69
|
+
if (cb)
|
70
|
+
cb(false);
|
71
|
+
};
|
72
|
+
|
73
|
+
req.onreadystatechange = function()
|
74
|
+
{
|
75
|
+
if (req.readyState == 4)
|
76
|
+
{
|
77
|
+
if (replace)
|
78
|
+
replaceElementWithSource(replace, req.responseText);
|
79
|
+
else
|
80
|
+
{
|
81
|
+
var frag = document.createElement("div");
|
82
|
+
frag.innerHTML = req.responseText;
|
83
|
+
iui.insertPages(frag.childNodes);
|
84
|
+
}
|
85
|
+
if (cb)
|
86
|
+
setTimeout(cb, 1000, true);
|
87
|
+
}
|
88
|
+
};
|
89
|
+
|
90
|
+
if (args)
|
91
|
+
{
|
92
|
+
req.open(method || "GET", href, true);
|
93
|
+
req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
|
94
|
+
req.setRequestHeader("Content-Length", args.length);
|
95
|
+
req.send(args.join("&"));
|
96
|
+
}
|
97
|
+
else
|
98
|
+
{
|
99
|
+
req.open(method || "GET", href, true);
|
100
|
+
req.send(null);
|
101
|
+
}
|
102
|
+
},
|
103
|
+
|
104
|
+
insertPages: function(nodes)
|
105
|
+
{
|
106
|
+
var targetPage;
|
107
|
+
for (var i = 0; i < nodes.length; ++i)
|
108
|
+
{
|
109
|
+
var child = nodes[i];
|
110
|
+
if (child.nodeType == 1)
|
111
|
+
{
|
112
|
+
if (!child.id)
|
113
|
+
child.id = "__" + (++newPageCount) + "__";
|
114
|
+
|
115
|
+
var clone = $(child.id);
|
116
|
+
if (clone)
|
117
|
+
clone.parentNode.replaceChild(child, clone);
|
118
|
+
else
|
119
|
+
document.body.appendChild(child);
|
120
|
+
|
121
|
+
if (child.getAttribute("selected") == "true" || !targetPage)
|
122
|
+
targetPage = child;
|
123
|
+
|
124
|
+
--i;
|
125
|
+
}
|
126
|
+
}
|
127
|
+
|
128
|
+
if (targetPage)
|
129
|
+
iui.showPage(targetPage);
|
130
|
+
},
|
131
|
+
|
132
|
+
getSelectedPage: function()
|
133
|
+
{
|
134
|
+
for (var child = document.body.firstChild; child; child = child.nextSibling)
|
135
|
+
{
|
136
|
+
if (child.nodeType == 1 && child.getAttribute("selected") == "true")
|
137
|
+
return child;
|
138
|
+
}
|
139
|
+
}
|
140
|
+
};
|
141
|
+
|
142
|
+
// *************************************************************************************************
|
143
|
+
|
144
|
+
addEventListener("load", function(event)
|
145
|
+
{
|
146
|
+
var page = iui.getSelectedPage();
|
147
|
+
if (page)
|
148
|
+
iui.showPage(page);
|
149
|
+
|
150
|
+
setTimeout(preloadImages, 0);
|
151
|
+
setTimeout(checkOrientAndLocation, 0);
|
152
|
+
checkTimer = setInterval(checkOrientAndLocation, 300);
|
153
|
+
}, false);
|
154
|
+
|
155
|
+
addEventListener("click", function(event)
|
156
|
+
{
|
157
|
+
var link = findParent(event.target, "a");
|
158
|
+
if (link)
|
159
|
+
{
|
160
|
+
function unselect() { link.removeAttribute("selected"); }
|
161
|
+
|
162
|
+
if (link.href && link.hash && link.hash != "#")
|
163
|
+
{
|
164
|
+
link.setAttribute("selected", "true");
|
165
|
+
iui.showPage($(link.hash.substr(1)));
|
166
|
+
setTimeout(unselect, 500);
|
167
|
+
}
|
168
|
+
else if (link == $("backButton"))
|
169
|
+
history.back();
|
170
|
+
else if (link.getAttribute("type") == "submit")
|
171
|
+
submitForm(findParent(link, "form"));
|
172
|
+
else if (link.getAttribute("type") == "cancel")
|
173
|
+
cancelDialog(findParent(link, "form"));
|
174
|
+
else if (link.target == "_replace")
|
175
|
+
{
|
176
|
+
link.setAttribute("selected", "progress");
|
177
|
+
iui.showPageByHref(link.href, null, null, link, unselect);
|
178
|
+
}
|
179
|
+
else if (!link.target)
|
180
|
+
{
|
181
|
+
link.setAttribute("selected", "progress");
|
182
|
+
iui.showPageByHref(link.href, null, null, null, unselect);
|
183
|
+
}
|
184
|
+
else
|
185
|
+
return;
|
186
|
+
|
187
|
+
event.preventDefault();
|
188
|
+
}
|
189
|
+
}, true);
|
190
|
+
|
191
|
+
addEventListener("click", function(event)
|
192
|
+
{
|
193
|
+
var div = findParent(event.target, "div");
|
194
|
+
if (div && hasClass(div, "toggle"))
|
195
|
+
{
|
196
|
+
div.setAttribute("toggled", div.getAttribute("toggled") != "true");
|
197
|
+
event.preventDefault();
|
198
|
+
}
|
199
|
+
}, true);
|
200
|
+
|
201
|
+
function checkOrientAndLocation()
|
202
|
+
{
|
203
|
+
if (window.innerWidth != currentWidth)
|
204
|
+
{
|
205
|
+
currentWidth = window.innerWidth;
|
206
|
+
var orient = currentWidth == 320 ? "profile" : "landscape";
|
207
|
+
document.body.setAttribute("orient", orient);
|
208
|
+
setTimeout(scrollTo, 100, 0, 1);
|
209
|
+
}
|
210
|
+
|
211
|
+
if (location.hash != currentHash)
|
212
|
+
{
|
213
|
+
var pageId = location.hash.substr(hashPrefix.length)
|
214
|
+
iui.showPageById(pageId);
|
215
|
+
}
|
216
|
+
}
|
217
|
+
|
218
|
+
function showDialog(page)
|
219
|
+
{
|
220
|
+
currentDialog = page;
|
221
|
+
page.setAttribute("selected", "true");
|
222
|
+
|
223
|
+
if (hasClass(page, "dialog") && !page.target)
|
224
|
+
showForm(page);
|
225
|
+
}
|
226
|
+
|
227
|
+
function showForm(form)
|
228
|
+
{
|
229
|
+
form.onsubmit = function(event)
|
230
|
+
{
|
231
|
+
event.preventDefault();
|
232
|
+
submitForm(form);
|
233
|
+
};
|
234
|
+
|
235
|
+
form.onclick = function(event)
|
236
|
+
{
|
237
|
+
if (event.target == form && hasClass(form, "dialog"))
|
238
|
+
cancelDialog(form);
|
239
|
+
};
|
240
|
+
}
|
241
|
+
|
242
|
+
function cancelDialog(form)
|
243
|
+
{
|
244
|
+
form.removeAttribute("selected");
|
245
|
+
}
|
246
|
+
|
247
|
+
function updatePage(page, fromPage)
|
248
|
+
{
|
249
|
+
if (!page.id)
|
250
|
+
page.id = "__" + (++newPageCount) + "__";
|
251
|
+
|
252
|
+
location.href = currentHash = hashPrefix + page.id;
|
253
|
+
pageHistory.push(page.id);
|
254
|
+
|
255
|
+
var pageTitle = $("pageTitle");
|
256
|
+
if (page.title)
|
257
|
+
pageTitle.innerHTML = page.title;
|
258
|
+
|
259
|
+
if (page.localName.toLowerCase() == "form" && !page.target)
|
260
|
+
showForm(page);
|
261
|
+
|
262
|
+
var backButton = $("backButton");
|
263
|
+
if (backButton)
|
264
|
+
{
|
265
|
+
var prevPage = $(pageHistory[pageHistory.length-2]);
|
266
|
+
if (prevPage && !page.getAttribute("hideBackButton"))
|
267
|
+
{
|
268
|
+
backButton.style.display = "inline";
|
269
|
+
backButton.innerHTML = prevPage.title ? prevPage.title : "Back";
|
270
|
+
}
|
271
|
+
else
|
272
|
+
backButton.style.display = "none";
|
273
|
+
}
|
274
|
+
}
|
275
|
+
|
276
|
+
function slidePages(fromPage, toPage, backwards)
|
277
|
+
{
|
278
|
+
var axis = (backwards ? fromPage : toPage).getAttribute("axis");
|
279
|
+
if (axis == "y")
|
280
|
+
(backwards ? fromPage : toPage).style.top = "100%";
|
281
|
+
else
|
282
|
+
toPage.style.left = "100%";
|
283
|
+
|
284
|
+
toPage.setAttribute("selected", "true");
|
285
|
+
scrollTo(0, 1);
|
286
|
+
clearInterval(checkTimer);
|
287
|
+
|
288
|
+
var percent = 100;
|
289
|
+
slide();
|
290
|
+
var timer = setInterval(slide, slideInterval);
|
291
|
+
|
292
|
+
function slide()
|
293
|
+
{
|
294
|
+
percent -= slideSpeed;
|
295
|
+
if (percent <= 0)
|
296
|
+
{
|
297
|
+
percent = 0;
|
298
|
+
if (!hasClass(toPage, "dialog"))
|
299
|
+
fromPage.removeAttribute("selected");
|
300
|
+
clearInterval(timer);
|
301
|
+
checkTimer = setInterval(checkOrientAndLocation, 300);
|
302
|
+
setTimeout(updatePage, 0, toPage, fromPage);
|
303
|
+
}
|
304
|
+
|
305
|
+
if (axis == "y")
|
306
|
+
{
|
307
|
+
backwards
|
308
|
+
? fromPage.style.top = (100-percent) + "%"
|
309
|
+
: toPage.style.top = percent + "%";
|
310
|
+
}
|
311
|
+
else
|
312
|
+
{
|
313
|
+
fromPage.style.left = (backwards ? (100-percent) : (percent-100)) + "%";
|
314
|
+
toPage.style.left = (backwards ? -percent : percent) + "%";
|
315
|
+
}
|
316
|
+
}
|
317
|
+
}
|
318
|
+
|
319
|
+
function preloadImages()
|
320
|
+
{
|
321
|
+
var preloader = document.createElement("div");
|
322
|
+
preloader.id = "preloader";
|
323
|
+
document.body.appendChild(preloader);
|
324
|
+
}
|
325
|
+
|
326
|
+
function submitForm(form)
|
327
|
+
{
|
328
|
+
iui.showPageByHref(form.action || "POST", encodeForm(form), form.method);
|
329
|
+
}
|
330
|
+
|
331
|
+
function encodeForm(form)
|
332
|
+
{
|
333
|
+
function encode(inputs)
|
334
|
+
{
|
335
|
+
for (var i = 0; i < inputs.length; ++i)
|
336
|
+
{
|
337
|
+
if (inputs[i].name)
|
338
|
+
args.push(inputs[i].name + "=" + escape(inputs[i].value));
|
339
|
+
}
|
340
|
+
}
|
341
|
+
|
342
|
+
var args = [];
|
343
|
+
encode(form.getElementsByTagName("input"));
|
344
|
+
encode(form.getElementsByTagName("select"));
|
345
|
+
return args;
|
346
|
+
}
|
347
|
+
|
348
|
+
function findParent(node, localName)
|
349
|
+
{
|
350
|
+
while (node && (node.nodeType != 1 || node.localName.toLowerCase() != localName))
|
351
|
+
node = node.parentNode;
|
352
|
+
return node;
|
353
|
+
}
|
354
|
+
|
355
|
+
function hasClass(self, name)
|
356
|
+
{
|
357
|
+
var re = new RegExp("(^|\\s)"+name+"($|\\s)");
|
358
|
+
return re.exec(self.getAttribute("class")) != null;
|
359
|
+
}
|
360
|
+
|
361
|
+
function replaceElementWithSource(replace, source)
|
362
|
+
{
|
363
|
+
var page = replace.parentNode;
|
364
|
+
var parent = replace;
|
365
|
+
while (page.parentNode != document.body)
|
366
|
+
{
|
367
|
+
page = page.parentNode;
|
368
|
+
parent = parent.parentNode;
|
369
|
+
}
|
370
|
+
|
371
|
+
var frag = document.createElement(parent.localName);
|
372
|
+
frag.innerHTML = source;
|
373
|
+
|
374
|
+
page.removeChild(parent);
|
375
|
+
|
376
|
+
while (frag.firstChild)
|
377
|
+
page.appendChild(frag.firstChild);
|
378
|
+
}
|
379
|
+
|
380
|
+
function $(id) { return document.getElementById(id); }
|
381
|
+
function ddd() { console.log.apply(console, arguments); }
|
382
|
+
|
383
|
+
})();
|
data/public/iui/iuix.css
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
body{margin:0;font-family:Helvetica;background:#FFF;color:#000;overflow-x:hidden;-webkit-user-select:none;-webkit-text-size-adjust:none;}body>*:not(.toolbar){display:none;position:absolute;margin:0;padding:0;left:0;top:45px;width:100%;min-height:372px;}body[orient="landscape"]>*:not(.toolbar){min-height:268px;}body>*[selected="true"]{display:block;}a[selected],a:active{background-color:#194fdb!important;background-image:url(listArrowSel.png),url(selection.png)!important;background-repeat:no-repeat,repeat-x;background-position:right center,left top;color:#FFF!important;}a[selected="progress"]{background-image:url(loading.gif),url(selection.png)!important;}body>.toolbar{box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;border-bottom:1px solid #2d3642;border-top:1px solid #6d84a2;padding:10px;height:45px;background:url(toolbar.png) #6d84a2 repeat-x;}.toolbar>h1{position:absolute;overflow:hidden;left:50%;margin:1px 0 0 -75px;height:45px;font-size:20px;width:150px;font-weight:bold;text-shadow:rgba(0,0,0,0.4) 0 -1px 0;text-align:center;text-overflow:ellipsis;white-space:nowrap;color:#FFF;}body[orient="landscape"]>.toolbar>h1{margin-left:-125px;width:250px;}.button{position:absolute;overflow:hidden;top:8px;right:6px;margin:0;border-width:0 5px;padding:0 3px;width:auto;height:30px;line-height:30px;font-family:inherit;font-size:12px;font-weight:bold;color:#FFF;text-shadow:rgba(0,0,0,0.6) 0 -1px 0;text-overflow:ellipsis;text-decoration:none;white-space:nowrap;background:none;-webkit-border-image:url(toolButton.png) 0 5 0 5;}.blueButton{-webkit-border-image:url(blueButton.png) 0 5 0 5;border-width:0 5px;}.leftButton{left:6px;right:auto;}#backButton{display:none;left:6px;right:auto;padding:0;max-width:55px;border-width:0 8px 0 14px;-webkit-border-image:url(backButton.png) 0 8 0 14;}.whiteButton,.grayButton{display:block;border-width:0 12px;padding:10px;text-align:center;font-size:20px;font-weight:bold;text-decoration:inherit;color:inherit;}.whiteButton{-webkit-border-image:url(whiteButton.png) 0 12 0 12;text-shadow:rgba(255,255,255,0.7) 0 1px 0;}.grayButton{-webkit-border-image:url(grayButton.png) 0 12 0 12;color:#FFF;}body>ul>li{position:relative;margin:0;border-bottom:1px solid #E0E0E0;padding:8px 0 8px 10px;font-size:20px;font-weight:bold;list-style:none;}body>ul>li.group{position:relative;top:-1px;margin-bottom:-2px;border-top:1px solid #7d7d7d;border-bottom:1px solid #999;padding:1px 10px;background:url(listGroup.png) repeat-x;font-size:17px;font-weight:bold;text-shadow:rgba(0,0,0,0.4) 0 1px 0;color:#FFF;}body>ul>li.group:first-child{top:0;border-top:none;}body>ul>li>a{display:block;margin:-8px 0 -8px -10px;padding:8px 32px 8px 10px;text-decoration:none;color:inherit;background:url(listArrow.png) no-repeat right center;}a[target="_replace"]{box-sizing:border-box;-webkit-box-sizing:border-box;padding-top:25px;padding-bottom:25px;font-size:18px;color:cornflowerblue;background-color:#FFF;background-image:none;}body>.dialog{top:0;width:100%;min-height:417px;z-index:2;background:rgba(0,0,0,0.8);padding:0;text-align:right;}.dialog>fieldset{box-sizing:border-box;-webkit-box-sizing:border-box;width:100%;margin:0;border:none;border-top:1px solid #6d84a2;padding:10px 6px;background:url(toolbar.png) #7388a5 repeat-x;}.dialog>fieldset>h1{margin:0 10px 0 10px;padding:0;font-size:20px;font-weight:bold;color:#FFF;text-shadow:rgba(0,0,0,0.4) 0 -1px 0;text-align:center;}.dialog>fieldset>label{position:absolute;margin:16px 0 0 6px;font-size:14px;color:#999;}input{box-sizing:border-box;-webkit-box-sizing:border-box;width:100%;margin:8px 0 0 0;padding:6px 6px 6px 44px;font-size:16px;font-weight:normal;}body>.panel{box-sizing:border-box;-webkit-box-sizing:border-box;padding:10px;background:#c8c8c8 url(pinstripes.png);}.panel>fieldset{position:relative;margin:0 0 20px 0;padding:0;background:#FFF;-webkit-border-radius:10px;border:1px solid #999;text-align:right;font-size:16px;}.row{position:relative;min-height:42px;border-bottom:1px solid #999;-webkit-border-radius:0;text-align:right;}fieldset>.row:last-child{border-bottom:none!important;}.row>input{box-sizing:border-box;-webkit-box-sizing:border-box;margin:0;border:none;padding:12px 10px 0 110px;height:42px;background:none;}.row>label{position:absolute;margin:0 0 0 14px;line-height:42px;font-weight:bold;}.row>.toggle{position:absolute;top:6px;right:6px;width:100px;height:28px;}.toggle{border:1px solid #888;-webkit-border-radius:6px;background:#FFF url(toggle.png) repeat-x;font-size:19px;font-weight:bold;line-height:30px;}.toggle[toggled="true"]{border:1px solid #143fae;background:#194fdb url(toggleOn.png) repeat-x;}.toggleOn{display:none;position:absolute;width:60px;text-align:center;left:0;top:0;color:#FFF;text-shadow:rgba(0,0,0,0.4) 0 -1px 0;}.toggleOff{position:absolute;width:60px;text-align:center;right:0;top:0;color:#666;}.toggle[toggled="true"]>.toggleOn{display:block;}.toggle[toggled="true"]>.toggleOff{display:none;}.thumb{position:absolute;top:-1px;left:-1px;width:40px;height:28px;border:1px solid #888;-webkit-border-radius:6px;background:#fff url(thumb.png) repeat-x;}.toggle[toggled="true"]>.thumb{left:auto;right:-1px;}.panel>h2{margin:0 0 8px 14px;font-size:inherit;font-weight:bold;color:#4d4d70;text-shadow:rgba(255,255,255,0.75) 2px 2px 0;}#preloader{display:none;background-image:url(loading.gif),url(selection.png),url(blueButton.png),url(listArrowSel.png),url(listGroup.png);}
|
data/public/iui/iuix.js
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
(function(){var _1=20;var _2=0;var _3=null;var _4=null;var _5=0;var _6=location.hash;var _7="#_";var _8=[];var _9=0;var _a;window.iui={showPage:function(_b,_c){if(_b){if(_4){_4.removeAttribute("selected");_4=null;}if(hasClass(_b,"dialog")){showDialog(_b);}else{var _d=_3;_3=_b;if(_d){setTimeout(slidePages,0,_d,_b,_c);}else{updatePage(_b,_d);}}}},showPageById:function(_e){var _f=$(_e);if(_f){var _10=_8.indexOf(_e);var _11=_10!=-1;if(_11){_8.splice(_10,_8.length);}iui.showPage(_f,_11);}},showPageByHref:function(_12,_13,_14,_15,cb){var req=new XMLHttpRequest();req.onerror=function(){if(cb){cb(false);}};req.onreadystatechange=function(){if(req.readyState==4){if(_15){replaceElementWithSource(_15,req.responseText);}else{var _18=document.createElement("div");_18.innerHTML=req.responseText;iui.insertPages(_18.childNodes);}if(cb){setTimeout(cb,1000,true);}}};if(_13){req.open(_14||"GET",_12,true);req.setRequestHeader("Content-Type","application/x-www-form-urlencoded");req.setRequestHeader("Content-Length",_13.length);req.send(_13.join("&"));}else{req.open(_14||"GET",_12,true);req.send(null);}},insertPages:function(_19){var _1a;for(var i=0;i<_19.length;++i){var _1c=_19[i];if(_1c.nodeType==1){if(!_1c.id){_1c.id="__"+(++_9)+"__";}var _1d=$(_1c.id);if(_1d){_1d.parentNode.replaceChild(_1c,_1d);}else{document.body.appendChild(_1c);}if(_1c.getAttribute("selected")=="true"||!_1a){_1a=_1c;}--i;}}if(_1a){iui.showPage(_1a);}},getSelectedPage:function(){for(var _1e=document.body.firstChild;_1e;_1e=_1e.nextSibling){if(_1e.nodeType==1&&_1e.getAttribute("selected")=="true"){return _1e;}}}};addEventListener("load",function(_1f){var _20=iui.getSelectedPage();if(_20){iui.showPage(_20);}setTimeout(preloadImages,0);setTimeout(checkOrientAndLocation,0);_a=setInterval(checkOrientAndLocation,300);},false);addEventListener("click",function(_21){var _22=findParent(_21.target,"a");if(_22){function unselect(){_22.removeAttribute("selected");}if(_22.href&&_22.hash&&_22.hash!="#"){_22.setAttribute("selected","true");iui.showPage($(_22.hash.substr(1)));setTimeout(unselect,500);}else{if(_22==$("backButton")){history.back();}else{if(_22.getAttribute("type")=="submit"){submitForm(findParent(_22,"form"));}else{if(_22.getAttribute("type")=="cancel"){cancelDialog(findParent(_22,"form"));}else{if(_22.target=="_replace"){_22.setAttribute("selected","progress");iui.showPageByHref(_22.href,null,null,_22,unselect);}else{if(!_22.target){_22.setAttribute("selected","progress");iui.showPageByHref(_22.href,null,null,null,unselect);}else{return;}}}}}}_21.preventDefault();}},true);addEventListener("click",function(_23){var div=findParent(_23.target,"div");if(div&&hasClass(div,"toggle")){div.setAttribute("toggled",div.getAttribute("toggled")!="true");_23.preventDefault();}},true);function checkOrientAndLocation(){if(window.innerWidth!=_5){_5=window.innerWidth;var _25=_5==320?"profile":"landscape";document.body.setAttribute("orient",_25);setTimeout(scrollTo,100,0,1);}if(location.hash!=_6){var _26=location.hash.substr(_7.length);iui.showPageById(_26);}}function showDialog(_27){_4=_27;_27.setAttribute("selected","true");if(hasClass(_27,"dialog")&&!_27.target){showForm(_27);}}function showForm(_28){_28.onsubmit=function(_29){_29.preventDefault();submitForm(_28);};_28.onclick=function(_2a){if(_2a.target==_28&&hasClass(_28,"dialog")){cancelDialog(_28);}};}function cancelDialog(_2b){_2b.removeAttribute("selected");}function updatePage(_2c,_2d){if(!_2c.id){_2c.id="__"+(++_9)+"__";}location.href=_6=_7+_2c.id;_8.push(_2c.id);var _2e=$("pageTitle");if(_2c.title){_2e.innerHTML=_2c.title;}if(_2c.localName.toLowerCase()=="form"&&!_2c.target){showForm(_2c);}var _2f=$("backButton");if(_2f){var _30=$(_8[_8.length-2]);if(_30&&!_2c.getAttribute("hideBackButton")){_2f.style.display="inline";_2f.innerHTML=_30.title?_30.title:"Back";}else{_2f.style.display="none";}}}function slidePages(_31,_32,_33){var _34=(_33?_31:_32).getAttribute("axis");if(_34=="y"){(_33?_31:_32).style.top="100%";}else{_32.style.left="100%";}_32.setAttribute("selected","true");scrollTo(0,1);clearInterval(_a);var _35=100;slide();var _36=setInterval(slide,_2);function slide(){_35-=_1;if(_35<=0){_35=0;if(!hasClass(_32,"dialog")){_31.removeAttribute("selected");}clearInterval(_36);_a=setInterval(checkOrientAndLocation,300);setTimeout(updatePage,0,_32,_31);}if(_34=="y"){_33?_31.style.top=(100-_35)+"%":_32.style.top=_35+"%";}else{_31.style.left=(_33?(100-_35):(_35-100))+"%";_32.style.left=(_33?-_35:_35)+"%";}}}function preloadImages(){var _37=document.createElement("div");_37.id="preloader";document.body.appendChild(_37);}function submitForm(_38){iui.showPageByHref(_38.action||"POST",encodeForm(_38),_38.method);}function encodeForm(_39){function encode(_3a){for(var i=0;i<_3a.length;++i){if(_3a[i].name){args.push(_3a[i].name+"="+escape(_3a[i].value));}}}var _3c=[];encode(_39.getElementsByTagName("input"));encode(_39.getElementsByTagName("select"));return _3c;}function findParent(_3d,_3e){while(_3d&&(_3d.nodeType!=1||_3d.localName.toLowerCase()!=_3e)){_3d=_3d.parentNode;}return _3d;}function hasClass(_3f,_40){var re=new RegExp("(^|\\s)"+_40+"($|\\s)");return re.exec(_3f.getAttribute("class"))!=null;}function replaceElementWithSource(_42,_43){var _44=_42.parentNode;var _45=_42;while(_44.parentNode!=document.body){_44=_44.parentNode;_45=_45.parentNode;}var _46=document.createElement(_45.localName);_46.innerHTML=_43;_44.removeChild(_45);while(_46.firstChild){_44.appendChild(_46.firstChild);}}function $(id){return document.getElementById(id);}function ddd(){console.log.apply(console,arguments);}})();
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
data/views/command.erb
ADDED
data/views/status.erb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
<html>
|
2
|
+
<head>
|
3
|
+
<title><%= @title %></title>
|
4
|
+
<meta name="viewport" content="width=320; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;"/>
|
5
|
+
<style type="text/css" media="screen">@import "/iui/iui.css";</style>
|
6
|
+
<script type="application/x-javascript" src="/iui/iui.js"></script>
|
7
|
+
</head>
|
8
|
+
<body>
|
9
|
+
<div class="toolbar">
|
10
|
+
<h1 id="pageTitle"><%= @title %></h1>
|
11
|
+
<a id="backButton" class="button" href="#"></a>
|
12
|
+
<a class="button" href="/" target="_self">Refresh</a>
|
13
|
+
</div>
|
14
|
+
<ul id="home" selected="true" title="GodWeb">
|
15
|
+
<% unless @groups.empty? %>
|
16
|
+
<li class="group">Groups</li>
|
17
|
+
<% @groups.each do |watch| %>
|
18
|
+
<li id="<%= watch %>"><a href="/g/<%= watch %>"><%= watch %></a></li>
|
19
|
+
<% end %>
|
20
|
+
<% end %>
|
21
|
+
<li class="group">Watches</li>
|
22
|
+
<% @watches.each do |watch| %>
|
23
|
+
<li id="<%= watch %>" class="<%= @statuses[watch][:state] %>"><a href="/w/<%= watch %>"><%= watch %>[<%= @statuses[watch][:state] %>]</a></li>
|
24
|
+
<% end %>
|
25
|
+
</ul>
|
26
|
+
</body>
|
27
|
+
</html>
|
data/views/watch.erb
ADDED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jnewland-god_web
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jesse Newland
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-05-
|
12
|
+
date: 2008-05-19 00:00:00 -07:00
|
13
13
|
default_executable: god_web
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -30,18 +30,43 @@ dependencies:
|
|
30
30
|
- !ruby/object:Gem::Version
|
31
31
|
version: 0.2.2
|
32
32
|
version:
|
33
|
-
description:
|
33
|
+
description: iPhone friendly web UI for God
|
34
34
|
email: jnewland@gmail.com
|
35
35
|
executables:
|
36
36
|
- god_web
|
37
37
|
extensions: []
|
38
38
|
|
39
39
|
extra_rdoc_files:
|
40
|
-
- Readme.
|
40
|
+
- Readme.textile
|
41
41
|
files:
|
42
42
|
- bin/god_web
|
43
|
+
- lib/environment.rb
|
44
|
+
- lib/god_web.rb
|
43
45
|
- lib/sinatra_http_auth.rb
|
44
|
-
-
|
46
|
+
- views/command.erb
|
47
|
+
- views/status.erb
|
48
|
+
- views/watch.erb
|
49
|
+
- public/iui/backButton.png
|
50
|
+
- public/iui/blueButton.png
|
51
|
+
- public/iui/cancel.png
|
52
|
+
- public/iui/grayButton.png
|
53
|
+
- public/iui/iui.css
|
54
|
+
- public/iui/iui.js
|
55
|
+
- public/iui/iuix.css
|
56
|
+
- public/iui/iuix.js
|
57
|
+
- public/iui/listArrow.png
|
58
|
+
- public/iui/listArrowSel.png
|
59
|
+
- public/iui/listGroup.png
|
60
|
+
- public/iui/loading.gif
|
61
|
+
- public/iui/pinstripes.png
|
62
|
+
- public/iui/selection.png
|
63
|
+
- public/iui/thumb.png
|
64
|
+
- public/iui/toggle.png
|
65
|
+
- public/iui/toggleOn.png
|
66
|
+
- public/iui/toolButton.png
|
67
|
+
- public/iui/toolbar.png
|
68
|
+
- public/iui/whiteButton.png
|
69
|
+
- Readme.textile
|
45
70
|
has_rdoc: false
|
46
71
|
homepage: http://github.com/jnewland/god_web
|
47
72
|
post_install_message:
|
@@ -64,9 +89,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
64
89
|
requirements: []
|
65
90
|
|
66
91
|
rubyforge_project: god_web
|
67
|
-
rubygems_version: 1.0
|
92
|
+
rubygems_version: 1.2.0
|
68
93
|
signing_key:
|
69
94
|
specification_version: 2
|
70
|
-
summary:
|
95
|
+
summary: iPhone friendly web UI for God
|
71
96
|
test_files: []
|
72
97
|
|
data/Readme.txt
DELETED
@@ -1,55 +0,0 @@
|
|
1
|
-
= god_web
|
2
|
-
|
3
|
-
* http://github.com/jnewland/god_web
|
4
|
-
|
5
|
-
== DESCRIPTION:
|
6
|
-
|
7
|
-
Sinatra web frontend for God
|
8
|
-
|
9
|
-
== REQUIREMENTS:
|
10
|
-
|
11
|
-
* God
|
12
|
-
* Sinatra
|
13
|
-
|
14
|
-
== INSTALL:
|
15
|
-
|
16
|
-
* sudo gem install jnewland-god_web -s http://gems.github.com
|
17
|
-
|
18
|
-
== USAGE:
|
19
|
-
|
20
|
-
* sudo god_web -p PORT_TO_RUN_ON -e production
|
21
|
-
|
22
|
-
Optionally, you can password protect your god_web instance. To do so, create
|
23
|
-
a YAML config file with username and password keys, like so:
|
24
|
-
|
25
|
-
username: foo
|
26
|
-
password: sekret
|
27
|
-
|
28
|
-
Then provide that yaml file as the first argument to god_web:
|
29
|
-
|
30
|
-
* sudo god_web /path/to/god_web.yml -p PORT_TO_RUN_ON -e production
|
31
|
-
|
32
|
-
== LICENSE:
|
33
|
-
|
34
|
-
(The MIT License)
|
35
|
-
|
36
|
-
Copyright (c) 2008 Jesse Newland
|
37
|
-
|
38
|
-
Permission is hereby granted, free of charge, to any person obtaining
|
39
|
-
a copy of this software and associated documentation files (the
|
40
|
-
'Software'), to deal in the Software without restriction, including
|
41
|
-
without limitation the rights to use, copy, modify, merge, publish,
|
42
|
-
distribute, sublicense, and/or sell copies of the Software, and to
|
43
|
-
permit persons to whom the Software is furnished to do so, subject to
|
44
|
-
the following conditions:
|
45
|
-
|
46
|
-
The above copyright notice and this permission notice shall be
|
47
|
-
included in all copies or substantial portions of the Software.
|
48
|
-
|
49
|
-
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
50
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
51
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
52
|
-
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
53
|
-
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
54
|
-
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
55
|
-
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|