marbu 0.1.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/Rakefile +13 -0
- data/Readme.md +58 -0
- data/bin/marbu-web +20 -0
- data/bin/marbu-web-mongo-config.rb +8 -0
- data/lib/core_ext/array.rb +7 -0
- data/lib/core_ext/enumerable.rb +25 -0
- data/lib/core_ext/hash.rb +35 -0
- data/lib/core_ext/indifferent_access.rb +11 -0
- data/lib/core_ext/object.rb +25 -0
- data/lib/core_ext/open_struct.rb +3 -0
- data/lib/core_ext/string.rb +25 -0
- data/lib/marbu/builder.rb +48 -0
- data/lib/marbu/builders/mongodb.rb +106 -0
- data/lib/marbu/exceptions.rb +7 -0
- data/lib/marbu/formatters/base.rb +6 -0
- data/lib/marbu/formatters/dummy.rb +9 -0
- data/lib/marbu/formatters/formatters.rb +3 -0
- data/lib/marbu/formatters/one_line.rb +9 -0
- data/lib/marbu/models/db/db.rb +3 -0
- data/lib/marbu/models/db/mongodb/exceptions.rb +59 -0
- data/lib/marbu/models/db/mongodb/mongodb.rb +54 -0
- data/lib/marbu/models/db/mongodb/structure.rb +40 -0
- data/lib/marbu/models/exception_link.rb +11 -0
- data/lib/marbu/models/models.rb +3 -0
- data/lib/marbu/models/mrf/base.rb +133 -0
- data/lib/marbu/models/mrf/code.rb +32 -0
- data/lib/marbu/models/mrf/finalize.rb +9 -0
- data/lib/marbu/models/mrf/map.rb +7 -0
- data/lib/marbu/models/mrf/map_reduce_finalize.rb +107 -0
- data/lib/marbu/models/mrf/misc.rb +65 -0
- data/lib/marbu/models/mrf/mrf.rb +8 -0
- data/lib/marbu/models/mrf/query.rb +39 -0
- data/lib/marbu/models/mrf/reduce.rb +7 -0
- data/lib/marbu/server/public/css/style.css +149 -0
- data/lib/marbu/server/public/images/remove.png +0 -0
- data/lib/marbu/server/public/js/builder.js +200 -0
- data/lib/marbu/server/views/_builder_col_code.haml +8 -0
- data/lib/marbu/server/views/_builder_col_emit_keys.haml +13 -0
- data/lib/marbu/server/views/_builder_col_emit_values.haml +12 -0
- data/lib/marbu/server/views/_builder_data_samples.haml +8 -0
- data/lib/marbu/server/views/_builder_misc.haml +20 -0
- data/lib/marbu/server/views/_collection_nested_list.haml +0 -0
- data/lib/marbu/server/views/_footer.haml +2 -0
- data/lib/marbu/server/views/_header.haml +3 -0
- data/lib/marbu/server/views/_header_col.haml +6 -0
- data/lib/marbu/server/views/builder.haml +37 -0
- data/lib/marbu/server/views/layout.haml +19 -0
- data/lib/marbu/server/views/mapreduce.haml +9 -0
- data/lib/marbu/server/views/root.haml +11 -0
- data/lib/marbu/server/views/sample_data.haml +17 -0
- data/lib/marbu/server.rb +199 -0
- data/lib/marbu/server_sinatra.rb +168 -0
- data/lib/marbu/version.rb +3 -0
- data/lib/marbu.rb +65 -0
- data/spec/constants.rb +149 -0
- data/spec/rubymine-server.rb +0 -0
- data/spec/spec_helper.rb +63 -0
- data/spec/unit/builders/builder_spec.rb +5 -0
- data/spec/unit/builders/mongodb_spec.rb +52 -0
- data/spec/unit/models/base_spec.rb +33 -0
- data/spec/unit/models/map_reduce_finalize_spec.rb +28 -0
- data/spec/unit/models/map_spec.rb +22 -0
- data/spec/unit/models/query_spec.rb +23 -0
- metadata +209 -0
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
module Marbu
|
|
2
|
+
module Models
|
|
3
|
+
class Base
|
|
4
|
+
attr_accessor :keys, :values
|
|
5
|
+
attr_reader :code
|
|
6
|
+
|
|
7
|
+
def initialize(ext_options = {})
|
|
8
|
+
# keep_if weeds out nil arguments
|
|
9
|
+
options = default_options.merge( ext_options.keep_if{|k,v| v} )
|
|
10
|
+
|
|
11
|
+
@keys = options[:keys].map{ |k| Key.new(k) }
|
|
12
|
+
@values = options[:values].map{ |v| Value.new(v) }
|
|
13
|
+
self.code = options[:code]
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def default_options
|
|
17
|
+
{
|
|
18
|
+
:keys => [],
|
|
19
|
+
:values => [],
|
|
20
|
+
:code => Code.new
|
|
21
|
+
}
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def code=(code)
|
|
25
|
+
if( code.is_a?(Code) )
|
|
26
|
+
@code = code
|
|
27
|
+
elsif( code.is_a?(Hash) )
|
|
28
|
+
@code = Code.new(code)
|
|
29
|
+
else
|
|
30
|
+
raise Exception.new("Don't know this Code type: #{code.class}")
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def serializable_hash
|
|
35
|
+
{
|
|
36
|
+
:keys => keys.collect(&:serializable_hash),
|
|
37
|
+
:values => values.collect(&:serializable_hash),
|
|
38
|
+
:code => code.serializable_hash
|
|
39
|
+
}.delete_if{|k,v|v.blank?}
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def add_key(name, function = nil)
|
|
43
|
+
add(:key, name, function)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def add_value(name, function = nil)
|
|
47
|
+
add(:value, name, function)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def present?
|
|
51
|
+
@keys.present? || code.present?
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def blank?
|
|
55
|
+
!present?
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
private
|
|
59
|
+
def add(type, name, function)
|
|
60
|
+
function = Misc::DOCUMENT_OFFSET + name.to_s unless function
|
|
61
|
+
case type
|
|
62
|
+
when :key then @keys << Key.new({:name => name, :function => function})
|
|
63
|
+
when :value then @values << Value.new({:name => name, :function => function})
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
class KeyValueBase
|
|
69
|
+
attr_accessor :name, :function
|
|
70
|
+
|
|
71
|
+
def initialize(params)
|
|
72
|
+
#params.keys.each do |k|
|
|
73
|
+
# send("#{k}=".to_sym, params[k]) if respond_to?(k)
|
|
74
|
+
#end
|
|
75
|
+
|
|
76
|
+
self.name = params[:name]
|
|
77
|
+
self.function = params[:function]
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def name=(name)
|
|
81
|
+
@name = name.to_s
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def serializable_hash
|
|
85
|
+
# don't return nil values in hash
|
|
86
|
+
{
|
|
87
|
+
:name => @name,
|
|
88
|
+
:function => @function
|
|
89
|
+
}.keep_if{|k,v| v}
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def present?
|
|
93
|
+
name.present? && function.present?
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def blank?
|
|
97
|
+
!present?
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
class Key < KeyValueBase
|
|
102
|
+
attr_reader :exchangeable
|
|
103
|
+
|
|
104
|
+
def initialize( ext_options = {} )
|
|
105
|
+
options = default_options.merge( ext_options.delete_if{|k,v|v.nil?} )
|
|
106
|
+
|
|
107
|
+
self.exchangeable = options.delete(:exchangeable)
|
|
108
|
+
super(options)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def default_options
|
|
112
|
+
{
|
|
113
|
+
:exchangeable => true
|
|
114
|
+
}
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def exchangeable=(e)
|
|
118
|
+
# make sure it's a boolean
|
|
119
|
+
if( !!e == e )
|
|
120
|
+
@exchangeable = e
|
|
121
|
+
else
|
|
122
|
+
raise Exception.new("Hey, I need a boolean!")
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
return self
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
class Value < KeyValueBase
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
module Marbu
|
|
2
|
+
module Models
|
|
3
|
+
class Code
|
|
4
|
+
attr_accessor :text, :type
|
|
5
|
+
|
|
6
|
+
JS = "JS"
|
|
7
|
+
|
|
8
|
+
def initialize( ext_params = {} )
|
|
9
|
+
params = default_params.merge( ext_params.keep_if{|k,v|v} )
|
|
10
|
+
@text = params[:text]
|
|
11
|
+
@type = params[:type]
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def default_params
|
|
15
|
+
{
|
|
16
|
+
:type => JS
|
|
17
|
+
}
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def serializable_hash
|
|
21
|
+
{
|
|
22
|
+
:text => text,
|
|
23
|
+
:type => type
|
|
24
|
+
}.delete_if{|k,v|v.blank?}
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def present?
|
|
28
|
+
text.present?
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
require 'mongoid'
|
|
4
|
+
|
|
5
|
+
module Marbu
|
|
6
|
+
module Models
|
|
7
|
+
# represents one complete MapReduce-Model
|
|
8
|
+
# this model can be stored in a database and read again
|
|
9
|
+
# the builder will use MapReduce-Models to build actual mapreduce code
|
|
10
|
+
class MapReduceFinalize
|
|
11
|
+
include Mongoid::Fields::Serializable
|
|
12
|
+
attr_reader :map, :reduce, :finalize, :query, :misc
|
|
13
|
+
|
|
14
|
+
def initialize(ext_params = {})
|
|
15
|
+
# TODO: deep copy necessary why?
|
|
16
|
+
params = default_params.merge( Marshal.load(Marshal.dump(ext_params)) )
|
|
17
|
+
|
|
18
|
+
self.map = params[:map]
|
|
19
|
+
self.reduce = params[:reduce]
|
|
20
|
+
self.finalize = params[:finalize]
|
|
21
|
+
self.query = params[:query]
|
|
22
|
+
self.misc = params[:misc]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def default_params
|
|
26
|
+
{
|
|
27
|
+
:map => Map.new,
|
|
28
|
+
:reduce => Reduce.new,
|
|
29
|
+
:finalize => Finalize.new,
|
|
30
|
+
:query => Query.new,
|
|
31
|
+
:misc => Misc.new
|
|
32
|
+
}
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def map=(map)
|
|
36
|
+
@map = general_setter(map, Marbu::Models::Map)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def reduce=(reduce)
|
|
40
|
+
@reduce = general_setter(reduce, Marbu::Models::Reduce)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def finalize=(finalize)
|
|
44
|
+
@finalize = general_setter(finalize, Marbu::Models::Finalize)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def query=(query)
|
|
48
|
+
@query = general_setter(query, Marbu::Models::Query)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def misc=(misc)
|
|
52
|
+
@misc = general_setter(misc, Marbu::Models::Misc)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def serializable_hash
|
|
56
|
+
{
|
|
57
|
+
:map => map.serializable_hash,
|
|
58
|
+
:reduce => reduce.serializable_hash,
|
|
59
|
+
:finalize => finalize.serializable_hash,
|
|
60
|
+
:query => query.serializable_hash,
|
|
61
|
+
:misc => misc.serializable_hash
|
|
62
|
+
}.delete_if{|k,v|v.blank?}
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# return true if we have a map and a reduce function defined
|
|
66
|
+
def mapreduce?
|
|
67
|
+
!(map.nil? && reduce.nil?)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def query_only?
|
|
71
|
+
force_query || (!mapreduce? && !query.nil?)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def eql?(other)
|
|
75
|
+
serializable_hash == other.serializable_hash
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def ==(other)
|
|
79
|
+
eql?(other)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# TODO: please remove after Mongoid gets non-intrusive de/serialization
|
|
83
|
+
def serialize(object)
|
|
84
|
+
object.serializable_hash
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def deserialize(object)
|
|
88
|
+
MapReduceFinalize.new(object.symbolize_keys_rec)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
private
|
|
92
|
+
def general_setter(var, klass)
|
|
93
|
+
if( var.is_a?(klass) )
|
|
94
|
+
ret_val = var
|
|
95
|
+
elsif( var.is_a?( ::Hash ) )
|
|
96
|
+
ret_val = klass.new(var)
|
|
97
|
+
elsif( var.nil? )
|
|
98
|
+
ret_val = klass.new
|
|
99
|
+
else
|
|
100
|
+
raise Exception.new("Unsupported var type: #{var.class}")
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
return ret_val
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
module Marbu
|
|
2
|
+
module Models
|
|
3
|
+
class Misc
|
|
4
|
+
attr_accessor :database, :input_collection, :output_collection, :output_operation
|
|
5
|
+
# if filter_data is true, a query will be created depending on the filter parameters in filter_model
|
|
6
|
+
# if filter_data is false, no query will generated
|
|
7
|
+
# this is necessary for multiple sequentiell map_reduces: some will work on already filtered data (so no filter needed)
|
|
8
|
+
# while others will grab data from other collections which need to be filtered first
|
|
9
|
+
attr_reader :filter_data
|
|
10
|
+
attr_accessor :value, :document_offset
|
|
11
|
+
|
|
12
|
+
VALUE = :value
|
|
13
|
+
DOCUMENT_OFFSET = VALUE.to_s + "."
|
|
14
|
+
|
|
15
|
+
def initialize( ext_params = {} )
|
|
16
|
+
params = default_params.merge( ext_params.delete_if{|k,v|v.blank?} )
|
|
17
|
+
|
|
18
|
+
self.database = params[:database]
|
|
19
|
+
self.input_collection = params[:input_collection]
|
|
20
|
+
self.output_collection = params[:output_collection]
|
|
21
|
+
self.output_operation = params[:output_operation]
|
|
22
|
+
self.filter_data = params[:filter_data]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def default_params
|
|
26
|
+
{
|
|
27
|
+
:value => VALUE,
|
|
28
|
+
:document_offset => DOCUMENT_OFFSET,
|
|
29
|
+
:filter_data => false,
|
|
30
|
+
:output_operation => "replace"
|
|
31
|
+
}
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def filter_data=(fd)
|
|
35
|
+
if( !!fd == fd )
|
|
36
|
+
@filter_data = fd
|
|
37
|
+
else
|
|
38
|
+
raise Exception.new("Need a boolean value!")
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def present?
|
|
43
|
+
database.present? || input_collection.present? || output_collection.present?
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def blank?
|
|
47
|
+
!present?
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def serializable_hash
|
|
51
|
+
{
|
|
52
|
+
:database => database,
|
|
53
|
+
:input_collection => input_collection,
|
|
54
|
+
:output_collection => output_collection,
|
|
55
|
+
:output_operation => output_operation,
|
|
56
|
+
:filter_data => filter_data
|
|
57
|
+
}.delete_if{|k,v|v.blank?}
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def collection
|
|
61
|
+
Marbu.connection.db(database).collection(input_collection)
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
require 'marbu/models/mrf/base'
|
|
2
|
+
require 'marbu/models/mrf/map'
|
|
3
|
+
require 'marbu/models/mrf/reduce'
|
|
4
|
+
require 'marbu/models/mrf/finalize'
|
|
5
|
+
require 'marbu/models/mrf/query'
|
|
6
|
+
require 'marbu/models/mrf/misc'
|
|
7
|
+
require 'marbu/models/mrf/code'
|
|
8
|
+
require 'marbu/models/mrf/map_reduce_finalize'
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
module Marbu
|
|
4
|
+
module Models
|
|
5
|
+
class Query
|
|
6
|
+
DEFAULT_DATE_FIELDS = [:created_at]
|
|
7
|
+
|
|
8
|
+
attr_accessor :condition, :datetime_fields
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def initialize( ext_params = {} )
|
|
12
|
+
params = default_params.merge( ext_params.keep_if{|k,v|v} )
|
|
13
|
+
@condition = params[:condition]
|
|
14
|
+
@datetime_fields = params[:datetime_fields]
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def default_params
|
|
18
|
+
{
|
|
19
|
+
:datetime_fields => DEFAULT_DATE_FIELDS
|
|
20
|
+
}
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def present?
|
|
24
|
+
condition.present? || !datetime_fields.eql?(DEFAULT_DATE_FIELDS)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def blank?
|
|
28
|
+
!present?
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def serializable_hash
|
|
32
|
+
{
|
|
33
|
+
:condition => condition,
|
|
34
|
+
:datetime_fields => datetime_fields
|
|
35
|
+
}.delete_if{|k,v|v.blank?}
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
body {
|
|
2
|
+
padding: 0;
|
|
3
|
+
margin: 0;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
.clearfix:after {
|
|
7
|
+
content: ".";
|
|
8
|
+
display: block;
|
|
9
|
+
clear: both;
|
|
10
|
+
visibility: hidden;
|
|
11
|
+
line-height: 0;
|
|
12
|
+
height: 0;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.clearfix {
|
|
16
|
+
display: inline-block;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
html[xmlns] .clearfix {
|
|
20
|
+
display: block;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
* html .clearfix {
|
|
24
|
+
height: 1%;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
/* builder */
|
|
31
|
+
.builder .col {
|
|
32
|
+
display: block;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.builder .row {
|
|
36
|
+
display: block;
|
|
37
|
+
margin: 0 0 15px 0;
|
|
38
|
+
border: 1px dotted #777;
|
|
39
|
+
position: relative;
|
|
40
|
+
background: #ddd;
|
|
41
|
+
border-radius: 10px;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.builder .row.submit {
|
|
45
|
+
text-align: center;
|
|
46
|
+
padding: 20px 0 0 0;
|
|
47
|
+
border: none;
|
|
48
|
+
border-radius: 0;
|
|
49
|
+
background: none;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.builder .col legend {
|
|
53
|
+
font-weight: bold;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.builder .col label {
|
|
57
|
+
font-size: 0.8em;
|
|
58
|
+
color: #333;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.builder .col .pair {
|
|
62
|
+
/* float: left;*/
|
|
63
|
+
/* margin-right: 2%;*/
|
|
64
|
+
/* width: 45%;*/
|
|
65
|
+
margin: 0 auto 15px auto;
|
|
66
|
+
padding: 5px 10px 5px 5px;
|
|
67
|
+
float: left;
|
|
68
|
+
width: 40%;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.builder .col .pair > a:last-child {
|
|
72
|
+
display: none;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.builder .col .pair:last-child {
|
|
76
|
+
margin-right: 0;
|
|
77
|
+
margin-bottom: 0;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.builder .col .add-remove-element:first-child .pair:first-child > a:last-child {
|
|
81
|
+
display: block;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
.add-remove {
|
|
86
|
+
clear: both;
|
|
87
|
+
margin: 0 0 20px 0;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
.add-remove a.remove {
|
|
92
|
+
background: url('/images/remove.png') 0 0 no-repeat;
|
|
93
|
+
width: 20px;
|
|
94
|
+
height: 20px;
|
|
95
|
+
padding: 0;
|
|
96
|
+
text-indent: -9999em;
|
|
97
|
+
top: 5px;
|
|
98
|
+
right: 5px;
|
|
99
|
+
display: block;
|
|
100
|
+
position: absolute;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
#container .pulldown {
|
|
104
|
+
margin: 0 .5em 40px .5em;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
a[data-type="pulldown"] {
|
|
108
|
+
text-align: left;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
#sample_data .ui-content .ui-btn,
|
|
112
|
+
#sample_data .ui-content .ui-collapsible {
|
|
113
|
+
cursor: pointer;
|
|
114
|
+
display: block;
|
|
115
|
+
margin: 0.5em 5px;
|
|
116
|
+
padding: 0;
|
|
117
|
+
position: relative;
|
|
118
|
+
text-align: left;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
#sample_data .ui-content .ui-btn.tablink {
|
|
122
|
+
display: inline-block;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
#sample_data .ui-collapsible-heading {
|
|
126
|
+
margin: 0;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
#sample_data .ui-collapsible-content {
|
|
130
|
+
padding-left: 30px;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
#sample_data a .example {
|
|
134
|
+
font-weight: normal;
|
|
135
|
+
margin-left: 10px;
|
|
136
|
+
font-size: .7em;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
#sample_data .tree {
|
|
140
|
+
display: none;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
#sample_data #sample_data_param_1 {
|
|
144
|
+
display: block;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.add_remove_button_wrapper > * {
|
|
148
|
+
float: left;
|
|
149
|
+
}
|
|
Binary file
|