dcell 0.9.0 → 0.10.0
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/.travis.yml +4 -1
- data/CHANGES.md +11 -0
- data/Gemfile +6 -3
- data/LICENSE.txt +1 -1
- data/README.md +27 -243
- data/benchmarks/receiver.rb +2 -2
- data/dcell.gemspec +7 -7
- data/explorer/css/bootstrap-responsive.css +686 -0
- data/explorer/css/bootstrap-responsive.min.css +12 -0
- data/explorer/css/bootstrap.css +3990 -0
- data/explorer/css/bootstrap.min.css +689 -0
- data/explorer/css/explorer.css +28 -0
- data/explorer/ico/favicon.ico +0 -0
- data/explorer/img/glyphicons-halflings-white.png +0 -0
- data/explorer/img/glyphicons-halflings.png +0 -0
- data/explorer/img/logo.png +0 -0
- data/explorer/index.html.erb +94 -0
- data/explorer/js/bootstrap.js +1726 -0
- data/explorer/js/bootstrap.min.js +6 -0
- data/lib/dcell.rb +27 -2
- data/lib/dcell/celluloid_ext.rb +14 -3
- data/lib/dcell/directory.rb +15 -3
- data/lib/dcell/explorer.rb +76 -0
- data/lib/dcell/future_proxy.rb +32 -0
- data/lib/dcell/info_service.rb +117 -0
- data/lib/dcell/mailbox_proxy.rb +6 -7
- data/lib/dcell/messages.rb +5 -6
- data/lib/dcell/node.rb +25 -55
- data/lib/dcell/node_manager.rb +81 -0
- data/lib/dcell/registries/cassandra_adapter.rb +86 -0
- data/lib/dcell/registries/gossip/core.rb +235 -0
- data/lib/dcell/registries/gossip_adapter.rb +26 -0
- data/lib/dcell/registries/moneta_adapter.rb +0 -7
- data/lib/dcell/registries/redis_adapter.rb +0 -31
- data/lib/dcell/registries/zk_adapter.rb +1 -39
- data/lib/dcell/router.rb +37 -30
- data/lib/dcell/rpc.rb +23 -23
- data/lib/dcell/server.rb +5 -2
- data/lib/dcell/version.rb +1 -1
- data/logo.png +0 -0
- data/spec/dcell/actor_proxy_spec.rb +4 -0
- data/spec/dcell/celluloid_ext_spec.rb +11 -0
- data/spec/dcell/directory_spec.rb +1 -1
- data/spec/dcell/explorer_spec.rb +17 -0
- data/spec/dcell/global_spec.rb +4 -0
- data/spec/dcell/registries/gossip_adapter_spec.rb +6 -0
- data/spec/spec_helper.rb +14 -7
- data/spec/support/registry_examples.rb +0 -18
- data/tasks/cassandra.task +84 -0
- metadata +55 -35
- data/celluloid-zmq/.gitignore +0 -17
- data/celluloid-zmq/.rspec +0 -4
- data/celluloid-zmq/CHANGES.md +0 -31
- data/celluloid-zmq/Gemfile +0 -7
- data/celluloid-zmq/README.md +0 -56
- data/celluloid-zmq/Rakefile +0 -7
- data/celluloid-zmq/celluloid-zmq.gemspec +0 -28
- data/celluloid-zmq/lib/celluloid/zmq.rb +0 -36
- data/celluloid-zmq/lib/celluloid/zmq/reactor.rb +0 -90
- data/celluloid-zmq/lib/celluloid/zmq/sockets.rb +0 -130
- data/celluloid-zmq/lib/celluloid/zmq/version.rb +0 -5
- data/celluloid-zmq/lib/celluloid/zmq/waker.rb +0 -55
- data/celluloid-zmq/spec/celluloid/zmq/actor_spec.rb +0 -6
- data/celluloid-zmq/spec/spec_helper.rb +0 -2
data/.travis.yml
CHANGED
data/CHANGES.md
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
0.10.0
|
2
|
+
------
|
3
|
+
* DCell::Explorer provides a web UI with Reel
|
4
|
+
* Info service at DCell::Node#[:info]
|
5
|
+
* Distributed gossip protocol, now default adapter
|
6
|
+
* Support for marshaling Celluloid::Futures
|
7
|
+
* Cassandra registry
|
8
|
+
* Initial DCell::NodeManager
|
9
|
+
* celluloid-zmq split out into a separate gem
|
10
|
+
* Use Celluloid.uuid for mailbox and call IDs
|
11
|
+
|
1
12
|
0.9.0
|
2
13
|
-----
|
3
14
|
* Use new Celluloid::ZMQ APIs
|
data/Gemfile
CHANGED
@@ -1,8 +1,11 @@
|
|
1
1
|
source "http://rubygems.org"
|
2
2
|
|
3
|
-
gem 'celluloid', :git
|
4
|
-
gem 'celluloid-io', :git
|
5
|
-
gem 'celluloid-zmq', :
|
3
|
+
gem 'celluloid', :git => 'git://github.com/celluloid/celluloid'
|
4
|
+
gem 'celluloid-io', :git => 'git://github.com/celluloid/celluloid-io'
|
5
|
+
gem 'celluloid-zmq', :git => 'git://github.com/celluloid/celluloid-zmq'
|
6
|
+
#gem 'reel', :git => 'git://github.com/celluloid/reel'
|
7
|
+
|
8
|
+
gem 'jruby-openssl', :platform => :jruby
|
6
9
|
|
7
10
|
# Specify your gem's dependencies in dcell.gemspec
|
8
11
|
gemspec
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,7 @@
|
|
1
|
-

|
2
2
|
=====
|
3
|
-
[](http://travis-ci.org/celluloid/dcell)
|
4
|
+
[](https://gemnasium.com/celluloid/dcell)
|
4
5
|
|
5
6
|
> "Objects can message objects transparently that live on other machines
|
6
7
|
> over the network, and you don't have to worry about the networking gunk,
|
@@ -17,15 +18,28 @@ and register several available services on a given node, obtain handles to
|
|
17
18
|
them, and easily pass these handles around the network just like any other
|
18
19
|
objects.
|
19
20
|
|
20
|
-
DCell is a distributed extension to Celluloid, which provides
|
21
|
-
objects for Ruby with many of the features of Erlang, such as the
|
22
|
-
to supervise objects and restart them when they crash, and also link to
|
21
|
+
DCell is a distributed extension to [Celluloid][celluloid], which provides
|
22
|
+
concurrent objects for Ruby with many of the features of Erlang, such as the
|
23
|
+
ability to supervise objects and restart them when they crash, and also link to
|
23
24
|
other objects and receive event notifications of when they crash. This makes
|
24
25
|
it easier to build robust, fault-tolerant distributed systems.
|
25
26
|
|
26
|
-
|
27
|
+
DCell uses the [0MQ][zeromq] messaging protocol which provides a robust,
|
28
|
+
fault-tolerant brokerless transport for asynchronous messages sent between
|
29
|
+
nodes. DCell is built on top of the [Celluloid::ZMQ][celluloid-zmq] library,
|
30
|
+
which provides a Celluloid-oriented wrapper around the underlying
|
31
|
+
[ffi-rzmq][ffi-rzmq] library.
|
27
32
|
|
28
|
-
|
33
|
+
[Please see the DCell Wiki](https://github.com/celluloid/dcell/wiki)
|
34
|
+
for more detailed documentation and usage notes.
|
35
|
+
|
36
|
+
Like DCell? [Join the Celluloid Google Group][googlegroup]
|
37
|
+
|
38
|
+
[celluloid]: http://celluloid.io/
|
39
|
+
[zeromq]: http://www.zeromq.org/
|
40
|
+
[celluloid-zmq]: https://github.com/celluloid/celluloid-zmq
|
41
|
+
[ffi-rzmq]: https://github.com/chuckremes/ffi-rzmq
|
42
|
+
[googlegroup]: http://groups.google.com/group/celluloid-ruby
|
29
43
|
|
30
44
|
### Is It Good?
|
31
45
|
|
@@ -38,245 +52,15 @@ Not entirely, but eager early adopters are welcome!
|
|
38
52
|
Supported Platforms
|
39
53
|
-------------------
|
40
54
|
|
41
|
-
DCell works on Ruby 1.9.
|
42
|
-
|
43
|
-
To use JRuby 1.6 in 1.9 mode, you'll need to pass the "--1.9" command line
|
44
|
-
option to the JRuby executable, or set the "JRUBY_OPTS=--1.9" environment
|
45
|
-
variable:
|
46
|
-
|
47
|
-
export JRUBY_OPTS=--1.9
|
48
|
-
|
49
|
-
(Note: I'd recommend putting the above in your .bashrc/.zshrc/etc in
|
50
|
-
general. 1.9 is the future, time to embrace it)
|
51
|
-
|
52
|
-
To use JRuby 1.7 in 1.9 mode...just use it :)
|
53
|
-
|
54
|
-
Celluloid works on Rubinius in either 1.8 or 1.9 mode.
|
55
|
-
|
56
|
-
All components, including the 0MQ bindings, Redis, and Zookeeper adapters
|
57
|
-
are all certified to work on the above platforms. The 0MQ binding is FFI.
|
58
|
-
The Redis adapter is pure Ruby. The Zookeeper adapter uses an MRI-style
|
59
|
-
native extension but also supplies a pure-Java backend for JRuby.
|
60
|
-
|
61
|
-
Prerequisites
|
62
|
-
-------------
|
63
|
-
|
64
|
-
DCell requires 0MQ. On OS X, this is available through Homebrew by running:
|
65
|
-
|
66
|
-
brew install zeromq
|
67
|
-
|
68
|
-
DCell keeps the state of all connected nodes and global configuration data
|
69
|
-
in a service it calls the "registry". There are presently two supported
|
70
|
-
registry services:
|
71
|
-
|
72
|
-
* Redis (Fast and Loose): Redis is a persistent data structures server.
|
73
|
-
It's simple and easy to use for development and prototyping, but lacks a
|
74
|
-
good distribution story.
|
75
|
-
|
76
|
-
* Zookeeper (Serious Business): Zookeeper is a high-performance coordination
|
77
|
-
service for distributed applications. It exposes common services such as
|
78
|
-
naming, configuration management, synchronization, and group management.
|
79
|
-
Unfortunately, it has slightly more annoying client-side dependencies and is
|
80
|
-
more difficult to deploy than Redis.
|
81
|
-
|
82
|
-
You may pick either one of these services to use as DCell's registry. The
|
83
|
-
default is Redis.
|
84
|
-
|
85
|
-
To install a local copy of Redis on OS X with Homebrew, run:
|
86
|
-
|
87
|
-
brew install redis
|
88
|
-
|
89
|
-
To install a local copy Zookeeper for testing purposes, run:
|
90
|
-
|
91
|
-
rake zookeeper:install
|
92
|
-
|
93
|
-
and to start it run:
|
94
|
-
|
95
|
-
rake zookeeper:start
|
96
|
-
|
97
|
-
Configuration
|
98
|
-
-------------
|
99
|
-
|
100
|
-
The simplest way to configure and start DCell is with the following:
|
101
|
-
|
102
|
-
```ruby
|
103
|
-
require 'dcell'
|
104
|
-
|
105
|
-
DCell.start
|
106
|
-
```
|
107
|
-
|
108
|
-
This configures DCell with all the default options, however there are many
|
109
|
-
options you can override, e.g.:
|
110
|
-
|
111
|
-
```ruby
|
112
|
-
DCell.start :id => "node42", :addr => "tcp://127.0.0.1:2042"
|
113
|
-
```
|
114
|
-
|
115
|
-
DCell identifies each node with a unique node ID, that defaults to your
|
116
|
-
hostname. Each node needs to be reachable over 0MQ, and the addr option
|
117
|
-
specifies the 0MQ address where the host can be reached. When giving a tcp://
|
118
|
-
URL, you *must* specify an IP address and not a hostname.
|
119
|
-
|
120
|
-
To join a cluster you'll need to provide the location of the registry server.
|
121
|
-
This can be done through the "registry" configuration key:
|
122
|
-
|
123
|
-
```ruby
|
124
|
-
DCell.start :id => "node24", :addr => "tcp://127.0.0.1:2042",
|
125
|
-
:registry => {
|
126
|
-
:adapter => 'redis',
|
127
|
-
:host => 'mycluster.example.org',
|
128
|
-
:port => 6379
|
129
|
-
}
|
130
|
-
```
|
131
|
-
|
132
|
-
When configuring DCell to use Redis, use the following options:
|
133
|
-
|
134
|
-
- **adapter**: "redis" (*optional, alternatively "zk"*)
|
135
|
-
- **host**: hostname or IP address of the Redis server (*optional, default localhost*)
|
136
|
-
- **port**: port of the Redis server (*optional, default 6379*)
|
137
|
-
- **password**: password to the Redis server (*optional*)
|
138
|
-
|
139
|
-
Usage
|
140
|
-
-----
|
141
|
-
|
142
|
-
You've now configured a single node in a DCell cluster. You can obtain the
|
143
|
-
DCell::Node object representing the local node by calling DCell.me:
|
144
|
-
|
145
|
-
```ruby
|
146
|
-
>> DCell.start
|
147
|
-
=> #<Celluloid::Supervisor(DCell::Application):0xed6>
|
148
|
-
>> DCell.me
|
149
|
-
=> #<DCell::Node[cryptosphere.local] @addr="tcp://127.0.0.1:7777">
|
150
|
-
```
|
151
|
-
|
152
|
-
DCell::Node objects are the entry point for locating actors on the system.
|
153
|
-
DCell.me returns the local node. Other nodes can be obtained by their
|
154
|
-
node IDs:
|
155
|
-
|
156
|
-
```ruby
|
157
|
-
>> node = DCell::Node["cryptosphere.local"]
|
158
|
-
=> #<DCell::Node[cryptosphere.local] @addr="tcp://127.0.0.1:7777">
|
159
|
-
```
|
160
|
-
|
161
|
-
DCell::Node.all returns all connected nodes in the cluster:
|
162
|
-
|
163
|
-
```ruby
|
164
|
-
>> DCell::Node.all
|
165
|
-
=> [#<DCell::Node[test_node] @addr="tcp://127.0.0.1:21264">, #<DCell::Node[cryptosphere.local] @addr="tcp://127.0.0.1:7777">]
|
166
|
-
```
|
167
|
-
|
168
|
-
DCell::Node is a Ruby Enumerable. You can iterate across all nodes with
|
169
|
-
DCell::Node.each.
|
170
|
-
|
171
|
-
Once you've obtained a node, you can look up services it exports and call them
|
172
|
-
just like you'd invoke methods on any other Ruby object:
|
173
|
-
|
174
|
-
```ruby
|
175
|
-
>> node = DCell::Node["cryptosphere.local"]
|
176
|
-
=> #<DCell::Node[cryptosphere.local] @addr="tcp://127.0.0.1:7777">
|
177
|
-
>> time_server = node[:time_server]
|
178
|
-
=> #<Celluloid::Actor(TimeServer:0xee8)>
|
179
|
-
>> time_server.time
|
180
|
-
=> "The time is: 2011-11-10 20:23:47 -0800"
|
181
|
-
```
|
182
|
-
|
183
|
-
You can also find all available services on a node with DCell::Node#all:
|
184
|
-
|
185
|
-
```ruby
|
186
|
-
>> node = DCell::Node["cryptosphere.local"]
|
187
|
-
=> #<DCell::Node[cryptosphere.local] @addr="tcp://127.0.0.1:7777">
|
188
|
-
>> node.all
|
189
|
-
=> [:time_server]
|
190
|
-
```
|
191
|
-
|
192
|
-
Registering Actors
|
193
|
-
------------------
|
194
|
-
|
195
|
-
All services exposed by DCell must take the form of registered Celluloid actors.
|
196
|
-
What follows is an extremely brief introduction to creating and registering
|
197
|
-
actors, but for more information, you should definitely [read the Celluloid
|
198
|
-
documentation](http://celluloid.github.com).
|
199
|
-
|
200
|
-
DCell exposes all Celluloid actors you've registered directly onto the network.
|
201
|
-
The best way to register an actor is by supervising it. Below is an example of
|
202
|
-
how to create an actor and register it on the network:
|
203
|
-
|
204
|
-
```ruby
|
205
|
-
class TimeServer
|
206
|
-
include Celluloid
|
207
|
-
|
208
|
-
def time
|
209
|
-
"The time is: #{Time.now}"
|
210
|
-
end
|
211
|
-
end
|
212
|
-
```
|
213
|
-
|
214
|
-
Now that we've defined the TimeServer, we're going to supervise it and register
|
215
|
-
it in the local registry:
|
216
|
-
|
217
|
-
```ruby
|
218
|
-
>> TimeServer.supervise_as :time_server
|
219
|
-
=> #<Celluloid::Supervisor(TimeServer):0xee4>
|
220
|
-
```
|
221
|
-
|
222
|
-
Supervising actors means that if they crash, they're automatically restarted
|
223
|
-
and registered under the same name. We can access registered actors by using
|
224
|
-
Celluloid::Actor#[]:
|
225
|
-
|
226
|
-
```ruby
|
227
|
-
>> Celluloid::Actor[:time_server]
|
228
|
-
=> #<Celluloid::Actor(TimeServer:0xee8)>
|
229
|
-
>> Celluloid::Actor[:time_server].time
|
230
|
-
=> "The time is: 2011-11-10 20:17:48 -0800"
|
231
|
-
```
|
232
|
-
|
233
|
-
This same actor is now available using the DCell::Node#[] syntax:
|
234
|
-
|
235
|
-
```ruby
|
236
|
-
>> node = DCell.me
|
237
|
-
=> #<DCell::Node[cryptosphere.local] @addr="tcp://127.0.0.1:1870">
|
238
|
-
>> node[:time_server].time
|
239
|
-
=> "The time is: 2011-11-10 20:28:27 -0800"
|
240
|
-
```
|
241
|
-
|
242
|
-
Globals
|
243
|
-
-------
|
244
|
-
|
245
|
-
DCell provides a registry global for storing configuration data and actors you
|
246
|
-
wish to publish globally to the entire cluster:
|
247
|
-
|
248
|
-
```ruby
|
249
|
-
>> actor = Celluloid::Actor[:dcell_server]
|
250
|
-
=> #<Celluloid::Actor(DCell::Server:0xf2e) @addr="tcp://127.0.0.1:7777">
|
251
|
-
>> DCell::Global[:sweet_server] = actor
|
252
|
-
=> #<Celluloid::Actor(DCell::Server:0xf2e) @addr="tcp://127.0.0.1:7777">
|
253
|
-
>> DCell::Global[:sweet_server]
|
254
|
-
=> #<Celluloid::Actor(DCell::Server:0xf2e) @addr="tcp://127.0.0.1:7777">
|
255
|
-
```
|
256
|
-
|
257
|
-
What about DRb?
|
258
|
-
---------------
|
259
|
-
|
260
|
-
Ruby already has a distributed object system as part of its standard library:
|
261
|
-
DRb, which stands for Distributed Ruby. What's wrong with DRb? Why do we need
|
262
|
-
a new system? DRb has one major drawback: it's inherently synchronous. The
|
263
|
-
only thing you can do to an object is to make a method call, which sends a
|
264
|
-
remote object a message, executes the method, and returns a response.
|
55
|
+
DCell works on Ruby 1.9.3, JRuby 1.6, and Rubinius 2.0.
|
265
56
|
|
266
|
-
|
267
|
-
|
268
|
-
the standard reqeust/response pattern afforded by DRb. DCell also supports the
|
269
|
-
Erlang-style approach to fault-tolerance, advocating that actors shouldn't handle
|
270
|
-
errors but should crash and restart in a clean state. Linking to actors on remote
|
271
|
-
nodes can be used to detect these sorts of errors and have dependent actors
|
272
|
-
restart in a clean state.
|
57
|
+
DCell requires Ruby 1.9 mode on all interpreters. This works out of the
|
58
|
+
box on MRI/YARV, and requires the following flags elsewhere:
|
273
59
|
|
274
|
-
|
275
|
-
|
276
|
-
concurrent in-process messaging system in its own right without the distributed
|
277
|
-
components.
|
60
|
+
* JRuby: --1.9 command line option, or JRUBY_OPTS=--1.9 environment variable
|
61
|
+
* rbx: -X19 command line option
|
278
62
|
|
279
63
|
Copyright
|
280
64
|
---------
|
281
65
|
|
282
|
-
Copyright (c)
|
66
|
+
Copyright (c) 2012 Tony Arcieri. See LICENSE.txt for further details.
|
data/benchmarks/receiver.rb
CHANGED
data/dcell.gemspec
CHANGED
@@ -7,7 +7,7 @@ Gem::Specification.new do |gem|
|
|
7
7
|
gem.version = DCell::VERSION
|
8
8
|
gem.authors = ["Tony Arcieri"]
|
9
9
|
gem.email = ["tony.arcieri@gmail.com"]
|
10
|
-
gem.homepage = "http://github.com/
|
10
|
+
gem.homepage = "http://github.com/celluloid/dcell"
|
11
11
|
gem.summary = "An asynchronous distributed object framework based on Celluloid"
|
12
12
|
gem.description = "DCell is an distributed object framework based on Celluloid built on 0MQ and Zookeeper"
|
13
13
|
|
@@ -16,13 +16,13 @@ Gem::Specification.new do |gem|
|
|
16
16
|
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
17
17
|
gem.require_paths = ["lib"]
|
18
18
|
|
19
|
-
gem.
|
20
|
-
gem.
|
21
|
-
gem.
|
22
|
-
gem.
|
23
|
-
gem.
|
19
|
+
gem.add_runtime_dependency "celluloid", "~> 0.10.0"
|
20
|
+
gem.add_runtime_dependency "celluloid-zmq", "~> 0.10.0"
|
21
|
+
gem.add_runtime_dependency "reel", "~> 0.0.1"
|
22
|
+
gem.add_runtime_dependency "redis"
|
23
|
+
gem.add_runtime_dependency "redis-namespace"
|
24
|
+
gem.add_runtime_dependency "moneta"
|
24
25
|
|
25
26
|
gem.add_development_dependency "rake"
|
26
27
|
gem.add_development_dependency "rspec"
|
27
|
-
#gem.add_development_dependency "zk"
|
28
28
|
end
|
@@ -0,0 +1,686 @@
|
|
1
|
+
/*!
|
2
|
+
* Bootstrap Responsive v2.0.2
|
3
|
+
*
|
4
|
+
* Copyright 2012 Twitter, Inc
|
5
|
+
* Licensed under the Apache License v2.0
|
6
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
7
|
+
*
|
8
|
+
* Designed and built with all the love in the world @twitter by @mdo and @fat.
|
9
|
+
*/
|
10
|
+
.clearfix {
|
11
|
+
*zoom: 1;
|
12
|
+
}
|
13
|
+
.clearfix:before,
|
14
|
+
.clearfix:after {
|
15
|
+
display: table;
|
16
|
+
content: "";
|
17
|
+
}
|
18
|
+
.clearfix:after {
|
19
|
+
clear: both;
|
20
|
+
}
|
21
|
+
.hide-text {
|
22
|
+
overflow: hidden;
|
23
|
+
text-indent: 100%;
|
24
|
+
white-space: nowrap;
|
25
|
+
}
|
26
|
+
.input-block-level {
|
27
|
+
display: block;
|
28
|
+
width: 100%;
|
29
|
+
min-height: 28px;
|
30
|
+
/* Make inputs at least the height of their button counterpart */
|
31
|
+
|
32
|
+
/* Makes inputs behave like true block-level elements */
|
33
|
+
|
34
|
+
-webkit-box-sizing: border-box;
|
35
|
+
-moz-box-sizing: border-box;
|
36
|
+
-ms-box-sizing: border-box;
|
37
|
+
box-sizing: border-box;
|
38
|
+
}
|
39
|
+
.hidden {
|
40
|
+
display: none;
|
41
|
+
visibility: hidden;
|
42
|
+
}
|
43
|
+
.visible-phone {
|
44
|
+
display: none;
|
45
|
+
}
|
46
|
+
.visible-tablet {
|
47
|
+
display: none;
|
48
|
+
}
|
49
|
+
.visible-desktop {
|
50
|
+
display: block;
|
51
|
+
}
|
52
|
+
.hidden-phone {
|
53
|
+
display: block;
|
54
|
+
}
|
55
|
+
.hidden-tablet {
|
56
|
+
display: block;
|
57
|
+
}
|
58
|
+
.hidden-desktop {
|
59
|
+
display: none;
|
60
|
+
}
|
61
|
+
@media (max-width: 767px) {
|
62
|
+
.visible-phone {
|
63
|
+
display: block;
|
64
|
+
}
|
65
|
+
.hidden-phone {
|
66
|
+
display: none;
|
67
|
+
}
|
68
|
+
.hidden-desktop {
|
69
|
+
display: block;
|
70
|
+
}
|
71
|
+
.visible-desktop {
|
72
|
+
display: none;
|
73
|
+
}
|
74
|
+
}
|
75
|
+
@media (min-width: 768px) and (max-width: 979px) {
|
76
|
+
.visible-tablet {
|
77
|
+
display: block;
|
78
|
+
}
|
79
|
+
.hidden-tablet {
|
80
|
+
display: none;
|
81
|
+
}
|
82
|
+
.hidden-desktop {
|
83
|
+
display: block;
|
84
|
+
}
|
85
|
+
.visible-desktop {
|
86
|
+
display: none;
|
87
|
+
}
|
88
|
+
}
|
89
|
+
@media (max-width: 480px) {
|
90
|
+
.nav-collapse {
|
91
|
+
-webkit-transform: translate3d(0, 0, 0);
|
92
|
+
}
|
93
|
+
.page-header h1 small {
|
94
|
+
display: block;
|
95
|
+
line-height: 18px;
|
96
|
+
}
|
97
|
+
input[type="checkbox"],
|
98
|
+
input[type="radio"] {
|
99
|
+
border: 1px solid #ccc;
|
100
|
+
}
|
101
|
+
.form-horizontal .control-group > label {
|
102
|
+
float: none;
|
103
|
+
width: auto;
|
104
|
+
padding-top: 0;
|
105
|
+
text-align: left;
|
106
|
+
}
|
107
|
+
.form-horizontal .controls {
|
108
|
+
margin-left: 0;
|
109
|
+
}
|
110
|
+
.form-horizontal .control-list {
|
111
|
+
padding-top: 0;
|
112
|
+
}
|
113
|
+
.form-horizontal .form-actions {
|
114
|
+
padding-left: 10px;
|
115
|
+
padding-right: 10px;
|
116
|
+
}
|
117
|
+
.modal {
|
118
|
+
position: absolute;
|
119
|
+
top: 10px;
|
120
|
+
left: 10px;
|
121
|
+
right: 10px;
|
122
|
+
width: auto;
|
123
|
+
margin: 0;
|
124
|
+
}
|
125
|
+
.modal.fade.in {
|
126
|
+
top: auto;
|
127
|
+
}
|
128
|
+
.modal-header .close {
|
129
|
+
padding: 10px;
|
130
|
+
margin: -10px;
|
131
|
+
}
|
132
|
+
.carousel-caption {
|
133
|
+
position: static;
|
134
|
+
}
|
135
|
+
}
|
136
|
+
@media (max-width: 767px) {
|
137
|
+
body {
|
138
|
+
padding-left: 20px;
|
139
|
+
padding-right: 20px;
|
140
|
+
}
|
141
|
+
.navbar-fixed-top {
|
142
|
+
margin-left: -20px;
|
143
|
+
margin-right: -20px;
|
144
|
+
}
|
145
|
+
.container {
|
146
|
+
width: auto;
|
147
|
+
}
|
148
|
+
.row-fluid {
|
149
|
+
width: 100%;
|
150
|
+
}
|
151
|
+
.row {
|
152
|
+
margin-left: 0;
|
153
|
+
}
|
154
|
+
.row > [class*="span"],
|
155
|
+
.row-fluid > [class*="span"] {
|
156
|
+
float: none;
|
157
|
+
display: block;
|
158
|
+
width: auto;
|
159
|
+
margin: 0;
|
160
|
+
}
|
161
|
+
.thumbnails [class*="span"] {
|
162
|
+
width: auto;
|
163
|
+
}
|
164
|
+
input[class*="span"],
|
165
|
+
select[class*="span"],
|
166
|
+
textarea[class*="span"],
|
167
|
+
.uneditable-input {
|
168
|
+
display: block;
|
169
|
+
width: 100%;
|
170
|
+
min-height: 28px;
|
171
|
+
/* Make inputs at least the height of their button counterpart */
|
172
|
+
|
173
|
+
/* Makes inputs behave like true block-level elements */
|
174
|
+
|
175
|
+
-webkit-box-sizing: border-box;
|
176
|
+
-moz-box-sizing: border-box;
|
177
|
+
-ms-box-sizing: border-box;
|
178
|
+
box-sizing: border-box;
|
179
|
+
}
|
180
|
+
.input-prepend input[class*="span"],
|
181
|
+
.input-append input[class*="span"] {
|
182
|
+
width: auto;
|
183
|
+
}
|
184
|
+
}
|
185
|
+
@media (min-width: 768px) and (max-width: 979px) {
|
186
|
+
.row {
|
187
|
+
margin-left: -20px;
|
188
|
+
*zoom: 1;
|
189
|
+
}
|
190
|
+
.row:before,
|
191
|
+
.row:after {
|
192
|
+
display: table;
|
193
|
+
content: "";
|
194
|
+
}
|
195
|
+
.row:after {
|
196
|
+
clear: both;
|
197
|
+
}
|
198
|
+
[class*="span"] {
|
199
|
+
float: left;
|
200
|
+
margin-left: 20px;
|
201
|
+
}
|
202
|
+
.container,
|
203
|
+
.navbar-fixed-top .container,
|
204
|
+
.navbar-fixed-bottom .container {
|
205
|
+
width: 724px;
|
206
|
+
}
|
207
|
+
.span12 {
|
208
|
+
width: 724px;
|
209
|
+
}
|
210
|
+
.span11 {
|
211
|
+
width: 662px;
|
212
|
+
}
|
213
|
+
.span10 {
|
214
|
+
width: 600px;
|
215
|
+
}
|
216
|
+
.span9 {
|
217
|
+
width: 538px;
|
218
|
+
}
|
219
|
+
.span8 {
|
220
|
+
width: 476px;
|
221
|
+
}
|
222
|
+
.span7 {
|
223
|
+
width: 414px;
|
224
|
+
}
|
225
|
+
.span6 {
|
226
|
+
width: 352px;
|
227
|
+
}
|
228
|
+
.span5 {
|
229
|
+
width: 290px;
|
230
|
+
}
|
231
|
+
.span4 {
|
232
|
+
width: 228px;
|
233
|
+
}
|
234
|
+
.span3 {
|
235
|
+
width: 166px;
|
236
|
+
}
|
237
|
+
.span2 {
|
238
|
+
width: 104px;
|
239
|
+
}
|
240
|
+
.span1 {
|
241
|
+
width: 42px;
|
242
|
+
}
|
243
|
+
.offset12 {
|
244
|
+
margin-left: 764px;
|
245
|
+
}
|
246
|
+
.offset11 {
|
247
|
+
margin-left: 702px;
|
248
|
+
}
|
249
|
+
.offset10 {
|
250
|
+
margin-left: 640px;
|
251
|
+
}
|
252
|
+
.offset9 {
|
253
|
+
margin-left: 578px;
|
254
|
+
}
|
255
|
+
.offset8 {
|
256
|
+
margin-left: 516px;
|
257
|
+
}
|
258
|
+
.offset7 {
|
259
|
+
margin-left: 454px;
|
260
|
+
}
|
261
|
+
.offset6 {
|
262
|
+
margin-left: 392px;
|
263
|
+
}
|
264
|
+
.offset5 {
|
265
|
+
margin-left: 330px;
|
266
|
+
}
|
267
|
+
.offset4 {
|
268
|
+
margin-left: 268px;
|
269
|
+
}
|
270
|
+
.offset3 {
|
271
|
+
margin-left: 206px;
|
272
|
+
}
|
273
|
+
.offset2 {
|
274
|
+
margin-left: 144px;
|
275
|
+
}
|
276
|
+
.offset1 {
|
277
|
+
margin-left: 82px;
|
278
|
+
}
|
279
|
+
.row-fluid {
|
280
|
+
width: 100%;
|
281
|
+
*zoom: 1;
|
282
|
+
}
|
283
|
+
.row-fluid:before,
|
284
|
+
.row-fluid:after {
|
285
|
+
display: table;
|
286
|
+
content: "";
|
287
|
+
}
|
288
|
+
.row-fluid:after {
|
289
|
+
clear: both;
|
290
|
+
}
|
291
|
+
.row-fluid > [class*="span"] {
|
292
|
+
float: left;
|
293
|
+
margin-left: 2.762430939%;
|
294
|
+
}
|
295
|
+
.row-fluid > [class*="span"]:first-child {
|
296
|
+
margin-left: 0;
|
297
|
+
}
|
298
|
+
.row-fluid > .span12 {
|
299
|
+
width: 99.999999993%;
|
300
|
+
}
|
301
|
+
.row-fluid > .span11 {
|
302
|
+
width: 91.436464082%;
|
303
|
+
}
|
304
|
+
.row-fluid > .span10 {
|
305
|
+
width: 82.87292817100001%;
|
306
|
+
}
|
307
|
+
.row-fluid > .span9 {
|
308
|
+
width: 74.30939226%;
|
309
|
+
}
|
310
|
+
.row-fluid > .span8 {
|
311
|
+
width: 65.74585634900001%;
|
312
|
+
}
|
313
|
+
.row-fluid > .span7 {
|
314
|
+
width: 57.182320438000005%;
|
315
|
+
}
|
316
|
+
.row-fluid > .span6 {
|
317
|
+
width: 48.618784527%;
|
318
|
+
}
|
319
|
+
.row-fluid > .span5 {
|
320
|
+
width: 40.055248616%;
|
321
|
+
}
|
322
|
+
.row-fluid > .span4 {
|
323
|
+
width: 31.491712705%;
|
324
|
+
}
|
325
|
+
.row-fluid > .span3 {
|
326
|
+
width: 22.928176794%;
|
327
|
+
}
|
328
|
+
.row-fluid > .span2 {
|
329
|
+
width: 14.364640883%;
|
330
|
+
}
|
331
|
+
.row-fluid > .span1 {
|
332
|
+
width: 5.801104972%;
|
333
|
+
}
|
334
|
+
input,
|
335
|
+
textarea,
|
336
|
+
.uneditable-input {
|
337
|
+
margin-left: 0;
|
338
|
+
}
|
339
|
+
input.span12, textarea.span12, .uneditable-input.span12 {
|
340
|
+
width: 714px;
|
341
|
+
}
|
342
|
+
input.span11, textarea.span11, .uneditable-input.span11 {
|
343
|
+
width: 652px;
|
344
|
+
}
|
345
|
+
input.span10, textarea.span10, .uneditable-input.span10 {
|
346
|
+
width: 590px;
|
347
|
+
}
|
348
|
+
input.span9, textarea.span9, .uneditable-input.span9 {
|
349
|
+
width: 528px;
|
350
|
+
}
|
351
|
+
input.span8, textarea.span8, .uneditable-input.span8 {
|
352
|
+
width: 466px;
|
353
|
+
}
|
354
|
+
input.span7, textarea.span7, .uneditable-input.span7 {
|
355
|
+
width: 404px;
|
356
|
+
}
|
357
|
+
input.span6, textarea.span6, .uneditable-input.span6 {
|
358
|
+
width: 342px;
|
359
|
+
}
|
360
|
+
input.span5, textarea.span5, .uneditable-input.span5 {
|
361
|
+
width: 280px;
|
362
|
+
}
|
363
|
+
input.span4, textarea.span4, .uneditable-input.span4 {
|
364
|
+
width: 218px;
|
365
|
+
}
|
366
|
+
input.span3, textarea.span3, .uneditable-input.span3 {
|
367
|
+
width: 156px;
|
368
|
+
}
|
369
|
+
input.span2, textarea.span2, .uneditable-input.span2 {
|
370
|
+
width: 94px;
|
371
|
+
}
|
372
|
+
input.span1, textarea.span1, .uneditable-input.span1 {
|
373
|
+
width: 32px;
|
374
|
+
}
|
375
|
+
}
|
376
|
+
@media (max-width: 979px) {
|
377
|
+
body {
|
378
|
+
padding-top: 0;
|
379
|
+
}
|
380
|
+
.navbar-fixed-top {
|
381
|
+
position: static;
|
382
|
+
margin-bottom: 18px;
|
383
|
+
}
|
384
|
+
.navbar-fixed-top .navbar-inner {
|
385
|
+
padding: 5px;
|
386
|
+
}
|
387
|
+
.navbar .container {
|
388
|
+
width: auto;
|
389
|
+
padding: 0;
|
390
|
+
}
|
391
|
+
.navbar .brand {
|
392
|
+
padding-left: 10px;
|
393
|
+
padding-right: 10px;
|
394
|
+
margin: 0 0 0 -5px;
|
395
|
+
}
|
396
|
+
.navbar .nav-collapse {
|
397
|
+
clear: left;
|
398
|
+
}
|
399
|
+
.navbar .nav {
|
400
|
+
float: none;
|
401
|
+
margin: 0 0 9px;
|
402
|
+
}
|
403
|
+
.navbar .nav > li {
|
404
|
+
float: none;
|
405
|
+
}
|
406
|
+
.navbar .nav > li > a {
|
407
|
+
margin-bottom: 2px;
|
408
|
+
}
|
409
|
+
.navbar .nav > .divider-vertical {
|
410
|
+
display: none;
|
411
|
+
}
|
412
|
+
.navbar .nav .nav-header {
|
413
|
+
color: #999999;
|
414
|
+
text-shadow: none;
|
415
|
+
}
|
416
|
+
.navbar .nav > li > a,
|
417
|
+
.navbar .dropdown-menu a {
|
418
|
+
padding: 6px 15px;
|
419
|
+
font-weight: bold;
|
420
|
+
color: #999999;
|
421
|
+
-webkit-border-radius: 3px;
|
422
|
+
-moz-border-radius: 3px;
|
423
|
+
border-radius: 3px;
|
424
|
+
}
|
425
|
+
.navbar .dropdown-menu li + li a {
|
426
|
+
margin-bottom: 2px;
|
427
|
+
}
|
428
|
+
.navbar .nav > li > a:hover,
|
429
|
+
.navbar .dropdown-menu a:hover {
|
430
|
+
background-color: #222222;
|
431
|
+
}
|
432
|
+
.navbar .dropdown-menu {
|
433
|
+
position: static;
|
434
|
+
top: auto;
|
435
|
+
left: auto;
|
436
|
+
float: none;
|
437
|
+
display: block;
|
438
|
+
max-width: none;
|
439
|
+
margin: 0 15px;
|
440
|
+
padding: 0;
|
441
|
+
background-color: transparent;
|
442
|
+
border: none;
|
443
|
+
-webkit-border-radius: 0;
|
444
|
+
-moz-border-radius: 0;
|
445
|
+
border-radius: 0;
|
446
|
+
-webkit-box-shadow: none;
|
447
|
+
-moz-box-shadow: none;
|
448
|
+
box-shadow: none;
|
449
|
+
}
|
450
|
+
.navbar .dropdown-menu:before,
|
451
|
+
.navbar .dropdown-menu:after {
|
452
|
+
display: none;
|
453
|
+
}
|
454
|
+
.navbar .dropdown-menu .divider {
|
455
|
+
display: none;
|
456
|
+
}
|
457
|
+
.navbar-form,
|
458
|
+
.navbar-search {
|
459
|
+
float: none;
|
460
|
+
padding: 9px 15px;
|
461
|
+
margin: 9px 0;
|
462
|
+
border-top: 1px solid #222222;
|
463
|
+
border-bottom: 1px solid #222222;
|
464
|
+
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);
|
465
|
+
-moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);
|
466
|
+
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);
|
467
|
+
}
|
468
|
+
.navbar .nav.pull-right {
|
469
|
+
float: none;
|
470
|
+
margin-left: 0;
|
471
|
+
}
|
472
|
+
.navbar-static .navbar-inner {
|
473
|
+
padding-left: 10px;
|
474
|
+
padding-right: 10px;
|
475
|
+
}
|
476
|
+
.btn-navbar {
|
477
|
+
display: block;
|
478
|
+
}
|
479
|
+
.nav-collapse {
|
480
|
+
overflow: hidden;
|
481
|
+
height: 0;
|
482
|
+
}
|
483
|
+
}
|
484
|
+
@media (min-width: 980px) {
|
485
|
+
.nav-collapse.collapse {
|
486
|
+
height: auto !important;
|
487
|
+
overflow: visible !important;
|
488
|
+
}
|
489
|
+
}
|
490
|
+
@media (min-width: 1200px) {
|
491
|
+
.row {
|
492
|
+
margin-left: -30px;
|
493
|
+
*zoom: 1;
|
494
|
+
}
|
495
|
+
.row:before,
|
496
|
+
.row:after {
|
497
|
+
display: table;
|
498
|
+
content: "";
|
499
|
+
}
|
500
|
+
.row:after {
|
501
|
+
clear: both;
|
502
|
+
}
|
503
|
+
[class*="span"] {
|
504
|
+
float: left;
|
505
|
+
margin-left: 30px;
|
506
|
+
}
|
507
|
+
.container,
|
508
|
+
.navbar-fixed-top .container,
|
509
|
+
.navbar-fixed-bottom .container {
|
510
|
+
width: 1170px;
|
511
|
+
}
|
512
|
+
.span12 {
|
513
|
+
width: 1170px;
|
514
|
+
}
|
515
|
+
.span11 {
|
516
|
+
width: 1070px;
|
517
|
+
}
|
518
|
+
.span10 {
|
519
|
+
width: 970px;
|
520
|
+
}
|
521
|
+
.span9 {
|
522
|
+
width: 870px;
|
523
|
+
}
|
524
|
+
.span8 {
|
525
|
+
width: 770px;
|
526
|
+
}
|
527
|
+
.span7 {
|
528
|
+
width: 670px;
|
529
|
+
}
|
530
|
+
.span6 {
|
531
|
+
width: 570px;
|
532
|
+
}
|
533
|
+
.span5 {
|
534
|
+
width: 470px;
|
535
|
+
}
|
536
|
+
.span4 {
|
537
|
+
width: 370px;
|
538
|
+
}
|
539
|
+
.span3 {
|
540
|
+
width: 270px;
|
541
|
+
}
|
542
|
+
.span2 {
|
543
|
+
width: 170px;
|
544
|
+
}
|
545
|
+
.span1 {
|
546
|
+
width: 70px;
|
547
|
+
}
|
548
|
+
.offset12 {
|
549
|
+
margin-left: 1230px;
|
550
|
+
}
|
551
|
+
.offset11 {
|
552
|
+
margin-left: 1130px;
|
553
|
+
}
|
554
|
+
.offset10 {
|
555
|
+
margin-left: 1030px;
|
556
|
+
}
|
557
|
+
.offset9 {
|
558
|
+
margin-left: 930px;
|
559
|
+
}
|
560
|
+
.offset8 {
|
561
|
+
margin-left: 830px;
|
562
|
+
}
|
563
|
+
.offset7 {
|
564
|
+
margin-left: 730px;
|
565
|
+
}
|
566
|
+
.offset6 {
|
567
|
+
margin-left: 630px;
|
568
|
+
}
|
569
|
+
.offset5 {
|
570
|
+
margin-left: 530px;
|
571
|
+
}
|
572
|
+
.offset4 {
|
573
|
+
margin-left: 430px;
|
574
|
+
}
|
575
|
+
.offset3 {
|
576
|
+
margin-left: 330px;
|
577
|
+
}
|
578
|
+
.offset2 {
|
579
|
+
margin-left: 230px;
|
580
|
+
}
|
581
|
+
.offset1 {
|
582
|
+
margin-left: 130px;
|
583
|
+
}
|
584
|
+
.row-fluid {
|
585
|
+
width: 100%;
|
586
|
+
*zoom: 1;
|
587
|
+
}
|
588
|
+
.row-fluid:before,
|
589
|
+
.row-fluid:after {
|
590
|
+
display: table;
|
591
|
+
content: "";
|
592
|
+
}
|
593
|
+
.row-fluid:after {
|
594
|
+
clear: both;
|
595
|
+
}
|
596
|
+
.row-fluid > [class*="span"] {
|
597
|
+
float: left;
|
598
|
+
margin-left: 2.564102564%;
|
599
|
+
}
|
600
|
+
.row-fluid > [class*="span"]:first-child {
|
601
|
+
margin-left: 0;
|
602
|
+
}
|
603
|
+
.row-fluid > .span12 {
|
604
|
+
width: 100%;
|
605
|
+
}
|
606
|
+
.row-fluid > .span11 {
|
607
|
+
width: 91.45299145300001%;
|
608
|
+
}
|
609
|
+
.row-fluid > .span10 {
|
610
|
+
width: 82.905982906%;
|
611
|
+
}
|
612
|
+
.row-fluid > .span9 {
|
613
|
+
width: 74.358974359%;
|
614
|
+
}
|
615
|
+
.row-fluid > .span8 {
|
616
|
+
width: 65.81196581200001%;
|
617
|
+
}
|
618
|
+
.row-fluid > .span7 {
|
619
|
+
width: 57.264957265%;
|
620
|
+
}
|
621
|
+
.row-fluid > .span6 {
|
622
|
+
width: 48.717948718%;
|
623
|
+
}
|
624
|
+
.row-fluid > .span5 {
|
625
|
+
width: 40.170940171000005%;
|
626
|
+
}
|
627
|
+
.row-fluid > .span4 {
|
628
|
+
width: 31.623931624%;
|
629
|
+
}
|
630
|
+
.row-fluid > .span3 {
|
631
|
+
width: 23.076923077%;
|
632
|
+
}
|
633
|
+
.row-fluid > .span2 {
|
634
|
+
width: 14.529914530000001%;
|
635
|
+
}
|
636
|
+
.row-fluid > .span1 {
|
637
|
+
width: 5.982905983%;
|
638
|
+
}
|
639
|
+
input,
|
640
|
+
textarea,
|
641
|
+
.uneditable-input {
|
642
|
+
margin-left: 0;
|
643
|
+
}
|
644
|
+
input.span12, textarea.span12, .uneditable-input.span12 {
|
645
|
+
width: 1160px;
|
646
|
+
}
|
647
|
+
input.span11, textarea.span11, .uneditable-input.span11 {
|
648
|
+
width: 1060px;
|
649
|
+
}
|
650
|
+
input.span10, textarea.span10, .uneditable-input.span10 {
|
651
|
+
width: 960px;
|
652
|
+
}
|
653
|
+
input.span9, textarea.span9, .uneditable-input.span9 {
|
654
|
+
width: 860px;
|
655
|
+
}
|
656
|
+
input.span8, textarea.span8, .uneditable-input.span8 {
|
657
|
+
width: 760px;
|
658
|
+
}
|
659
|
+
input.span7, textarea.span7, .uneditable-input.span7 {
|
660
|
+
width: 660px;
|
661
|
+
}
|
662
|
+
input.span6, textarea.span6, .uneditable-input.span6 {
|
663
|
+
width: 560px;
|
664
|
+
}
|
665
|
+
input.span5, textarea.span5, .uneditable-input.span5 {
|
666
|
+
width: 460px;
|
667
|
+
}
|
668
|
+
input.span4, textarea.span4, .uneditable-input.span4 {
|
669
|
+
width: 360px;
|
670
|
+
}
|
671
|
+
input.span3, textarea.span3, .uneditable-input.span3 {
|
672
|
+
width: 260px;
|
673
|
+
}
|
674
|
+
input.span2, textarea.span2, .uneditable-input.span2 {
|
675
|
+
width: 160px;
|
676
|
+
}
|
677
|
+
input.span1, textarea.span1, .uneditable-input.span1 {
|
678
|
+
width: 60px;
|
679
|
+
}
|
680
|
+
.thumbnails {
|
681
|
+
margin-left: -30px;
|
682
|
+
}
|
683
|
+
.thumbnails > li {
|
684
|
+
margin-left: 30px;
|
685
|
+
}
|
686
|
+
}
|