pg_ltree 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/Rakefile +29 -0
  4. data/lib/pg_ltree/ltree.rb +190 -0
  5. data/lib/pg_ltree/scoped_for.rb +45 -0
  6. data/lib/pg_ltree/version.rb +8 -0
  7. data/lib/pg_ltree.rb +5 -0
  8. data/lib/tasks/pg_ltree_tasks.rake +4 -0
  9. data/test/doc/_index.html +88 -0
  10. data/test/doc/class_list.html +58 -0
  11. data/test/doc/css/common.css +1 -0
  12. data/test/doc/css/full_list.css +57 -0
  13. data/test/doc/css/style.css +339 -0
  14. data/test/doc/file_list.html +57 -0
  15. data/test/doc/frames.html +26 -0
  16. data/test/doc/index.html +88 -0
  17. data/test/doc/js/app.js +219 -0
  18. data/test/doc/js/full_list.js +181 -0
  19. data/test/doc/js/jquery.js +4 -0
  20. data/test/doc/method_list.html +57 -0
  21. data/test/doc/top-level-namespace.html +102 -0
  22. data/test/dummy/README.rdoc +28 -0
  23. data/test/dummy/Rakefile +6 -0
  24. data/test/dummy/app/assets/javascripts/application.js +13 -0
  25. data/test/dummy/app/assets/stylesheets/application.css +15 -0
  26. data/test/dummy/app/controllers/application_controller.rb +5 -0
  27. data/test/dummy/app/helpers/application_helper.rb +2 -0
  28. data/test/dummy/app/models/not_uniq_tree_node.rb +6 -0
  29. data/test/dummy/app/models/tree_node.rb +3 -0
  30. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  31. data/test/dummy/bin/bundle +3 -0
  32. data/test/dummy/bin/rails +4 -0
  33. data/test/dummy/bin/rake +4 -0
  34. data/test/dummy/bin/setup +29 -0
  35. data/test/dummy/config/application.rb +26 -0
  36. data/test/dummy/config/boot.rb +5 -0
  37. data/test/dummy/config/database.yml.example +14 -0
  38. data/test/dummy/config/environment.rb +5 -0
  39. data/test/dummy/config/environments/development.rb +41 -0
  40. data/test/dummy/config/environments/production.rb +79 -0
  41. data/test/dummy/config/environments/test.rb +42 -0
  42. data/test/dummy/config/initializers/assets.rb +11 -0
  43. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  44. data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
  45. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  46. data/test/dummy/config/initializers/inflections.rb +16 -0
  47. data/test/dummy/config/initializers/mime_types.rb +4 -0
  48. data/test/dummy/config/initializers/session_store.rb +3 -0
  49. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  50. data/test/dummy/config/locales/en.yml +23 -0
  51. data/test/dummy/config/routes.rb +56 -0
  52. data/test/dummy/config/secrets.yml +22 -0
  53. data/test/dummy/config.ru +4 -0
  54. data/test/dummy/db/migrate/20150809114511_enable_postgres_ltree.rb +13 -0
  55. data/test/dummy/db/migrate/20150809114528_create_tree_node.rb +7 -0
  56. data/test/dummy/db/migrate/20150809114547_create_not_uniq_tree_node.rb +8 -0
  57. data/test/dummy/db/schema.rb +29 -0
  58. data/test/dummy/log/development.log +718 -0
  59. data/test/dummy/log/test.log +34557 -0
  60. data/test/dummy/public/404.html +67 -0
  61. data/test/dummy/public/422.html +67 -0
  62. data/test/dummy/public/500.html +66 -0
  63. data/test/dummy/public/favicon.ico +0 -0
  64. data/test/pg_ltree/ltree_test.rb +154 -0
  65. data/test/pg_ltree/scoped_for_test.rb +157 -0
  66. data/test/pg_ltree_test.rb +7 -0
  67. data/test/test_helper.rb +26 -0
  68. metadata +199 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f6149a7caa97eb49d20b3f8b9c144d98ee6af04e
4
+ data.tar.gz: ab7a5c2f1d37d3f55c2c49bda92eb8f0fe43e4c2
5
+ SHA512:
6
+ metadata.gz: 2226c78595c239d7db0e29dc69d91ff93a1a2c4a47903fe531c88efe7d7022a24eef7b873afd5efb1610d60b6d32f3d9f22fe115f1983a6908d701e2cfe33d4e
7
+ data.tar.gz: 1a2df813b90353f92db7ab1b4f5c0dc2f65af997a6c337a8df45ab906cce7ae676c6f3d53873ce3164905b4241704cece1a8744adaa54a71a3ea7dbc48394d75
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2015 Andrei Panamarenka
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,29 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'PgLtree'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.rdoc')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ Bundler::GemHelper.install_tasks
18
+
19
+ require 'rake/testtask'
20
+
21
+ Rake::TestTask.new(:test) do |t|
22
+ t.libs << 'lib'
23
+ t.libs << 'test'
24
+ t.pattern = 'test/**/*_test.rb'
25
+ t.verbose = false
26
+ end
27
+
28
+
29
+ task default: :test
@@ -0,0 +1,190 @@
1
+ module PgLtree
2
+ # Implementatios Postgres ltree for ActiveRecord
3
+ #
4
+ # @see [ActiveRecord::Base]
5
+ # @see http://www.postgresql.org/docs/current/static/ltree.html
6
+ #
7
+ # @author a.ponomarenko
8
+ module Ltree
9
+
10
+ # Initialzie ltree for active model
11
+ #
12
+ # @param column [String] ltree column name
13
+ def ltree(column = :path)
14
+ cattr_accessor :ltree_path_column
15
+
16
+ self.ltree_path_column = column
17
+
18
+ has_and_belongs_to_many column.to_s.tableize.to_sym,
19
+       class_name: self.class.name,
20
+       association_foreign_key: 'path'
21
+
22
+ extend ClassMethods
23
+ include InstanceMethods
24
+ end
25
+
26
+ # Define class methods
27
+ module ClassMethods
28
+ # Get roots
29
+ #
30
+ # @return [ActiveRecord::Relation] relations of node's roots
31
+ def roots
32
+ at_depth 1
33
+ end
34
+
35
+ # Get nodes on the level
36
+ #
37
+ # @param depth [Integer] Depth of the nodes
38
+ # @return [ActiveRecord::Relation] relations of nodes for the depth
39
+ def at_depth(depth)
40
+ where "NLEVEL(#{ltree_path_column}) = ?", depth
41
+ end
42
+
43
+ # Get all leaves
44
+ #
45
+ # @return [ActiveRecord::Relation] relations of node's leaves
46
+ def leaves
47
+ subquery =
48
+ select("COUNT(subquery.#{ltree_path_column}) = 1")
49
+ .from("#{table_name} AS subquery")
50
+ .where("subquery.#{ltree_path_column} <@ #{table_name}.#{ltree_path_column}").to_sql
51
+ where subquery
52
+ end
53
+
54
+ # Get all with nodes when path liked the lquery
55
+ #
56
+ # @param lquery [String] ltree query
57
+ # @return [ActiveRecord::Relation] relations of node'
58
+ def where_path_liked(lquery)
59
+ where "#{ltree_path_column} ~ ?", lquery
60
+ end
61
+ end
62
+
63
+ # Define instance methods
64
+ module InstanceMethods
65
+
66
+ # Get default scope of ltree
67
+ #
68
+ # @return current class
69
+ def ltree_scope
70
+ self.class
71
+ end
72
+
73
+ # Get lTree column
74
+ #
75
+ # @return [String] ltree column name
76
+ def ltree_path_column
77
+ ltree_scope.ltree_path_column
78
+ end
79
+
80
+ # Get lTree value
81
+ #
82
+ # @return [String] ltree current value
83
+ def ltree_path
84
+ public_send ltree_path_column
85
+ end
86
+
87
+ # Get lTree previous value
88
+ #
89
+ # @return [String] ltree previous value
90
+ def ltree_path_was
91
+ public_send :"#{ltree_path_column}_was"
92
+ end
93
+
94
+ # Check what current node is root
95
+ #
96
+ # @return [Boolean] True - for root node, False - for childen node
97
+ def root?
98
+ depth == 1
99
+ end
100
+
101
+ # Get node depth
102
+ #
103
+ # @return [Integer] node depth
104
+ def depth
105
+ ltree_scope.distinct.pluck("NLEVEL('#{ltree_path}')").first || nil
106
+ end
107
+
108
+ # Get root of the node
109
+ #
110
+ # return [Object] root node
111
+ def root
112
+ ltree_scope.where("#{ltree_path_column} = SUBPATH(?, 0, 1)", ltree_path).first
113
+ end
114
+
115
+ # Get parent of the node
116
+ #
117
+ # return [Object] root node
118
+ def parent
119
+ ltree_scope.find_by "#{ltree_path_column} = SUBPATH(?, 0, NLEVEL(?) - 1)", ltree_path, ltree_path
120
+ end
121
+
122
+ # Get leaves of the node
123
+ #
124
+ # @return [ActiveRecord::Relation]
125
+ def leaves
126
+ ltree_scope.leaves.where("#{ltree_path_column} <@ ?", ltree_path).where.not ltree_path_column => ltree_path
127
+ end
128
+
129
+ # Check what current node have leaves
130
+ #
131
+ # @return [Boolean] True - if node have leaves, False - if node doesn't have leaves
132
+ def leaf?
133
+ leaves.count == 0
134
+ end
135
+
136
+ # Get self and ancestors
137
+ #
138
+ # @return [ActiveRecord::Relation]
139
+ def self_and_ancestors
140
+ ltree_scope.where("#{ltree_path_column} @> ?", ltree_path)
141
+ end
142
+
143
+ # Get ancestors
144
+ #
145
+ # @return [ActiveRecord::Relation]
146
+ def ancestors
147
+ self_and_ancestors.where.not ltree_path_column => ltree_path
148
+ end
149
+
150
+ # Get self and descendents
151
+ #
152
+ # @return [ActiveRecord::Relation]
153
+ def self_and_descendents
154
+ ltree_scope.where("#{ltree_path_column} <@ ?", ltree_path)
155
+ end
156
+
157
+ # Get descendents
158
+ #
159
+ # @return [ActiveRecord::Relation]
160
+ def descendents
161
+ self_and_descendents.where.not ltree_path_column => ltree_path
162
+ end
163
+
164
+ # Get self and siblings
165
+ #
166
+ # @return [ActiveRecord::Relation]
167
+ def self_and_siblings
168
+ ltree_scope.where(
169
+ "SUBPATH(?, 0, NLEVEL(?) - 1) @> #{ltree_path_column} AND nlevel(#{ltree_path_column}) = NLEVEL(?)",
170
+ ltree_path, ltree_path, ltree_path
171
+ )
172
+ end
173
+
174
+ # Get siblings
175
+ #
176
+ # @return [ActiveRecord::Relation]
177
+ def siblings
178
+ self_and_siblings.where.not ltree_path_column => ltree_path
179
+ end
180
+
181
+ # Get children
182
+ #
183
+ # @return [ActiveRecord::Relation]
184
+ def children
185
+ ltree_scope.where "? @> #{ltree_path_column} AND nlevel(#{ltree_path_column}) = NLEVEL(?) + 1",
186
+ ltree_path, ltree_path
187
+ end
188
+ end
189
+ end
190
+ end
@@ -0,0 +1,45 @@
1
+ module PgLtree
2
+ # Narrowing the Scope for ActiveRecord Model
3
+ # @note When model have composite uniq key (for example: state + path), you should use this module for narrowing the scope
4
+ #
5
+ # @author a.ponomarenko
6
+ module ScopedFor
7
+
8
+ # Define base instance scope for model by columns
9
+ #
10
+ # @param columns [Array] List of scoped fields
11
+ def ltree_scoped_for(columns = [])
12
+ cattr_accessor :ltree_scoped_for
13
+
14
+ self.ltree_scoped_for = Array.wrap(columns)
15
+
16
+ extend ClassMethods
17
+ include InstanceMethods
18
+ end
19
+
20
+ # Define class methods
21
+ module ClassMethods
22
+ # Get all leaves
23
+ #
24
+ # @return [ActiveRecord::Relation] relations of node's leaves
25
+ def leaves
26
+ subquery =
27
+ select("COUNT(subquery.#{ltree_path_column}) = (SELECT COUNT(DISTINCT #{ltree_scoped_for.first}) FROM #{table_name})")
28
+ .from("#{table_name} AS subquery")
29
+ .where("subquery.#{ltree_path_column} <@ #{table_name}.#{ltree_path_column}").to_sql
30
+ where subquery
31
+ end
32
+ end
33
+
34
+ # Define instance methods
35
+ module InstanceMethods
36
+
37
+ # Get default scope of ltree
38
+ #
39
+ # @return current class
40
+ def ltree_scope
41
+ self.class.where *(ltree_scoped_for.map { |column| { column => public_send(column) } })
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,8 @@
1
+ # Organise ActiveRecord model into a tree structure with PostgreSQL LTree
2
+ #
3
+ # @author a.ponomarenko
4
+ module PgLtree
5
+
6
+ # Gem Version
7
+ VERSION = "1.0.0"
8
+ end
data/lib/pg_ltree.rb ADDED
@@ -0,0 +1,5 @@
1
+ require "pg_ltree/ltree"
2
+ require "pg_ltree/scoped_for"
3
+ require "pg_ltree/version"
4
+
5
+ ActiveRecord::Base.extend(PgLtree::Ltree)
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :pg_ltree do
3
+ # # Task goes here
4
+ # end
@@ -0,0 +1,88 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
4
+ <head>
5
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
6
+ <title>
7
+ Documentation by YARD 0.8.7.6
8
+
9
+ </title>
10
+
11
+ <link rel="stylesheet" href="css/style.css" type="text/css" charset="utf-8" />
12
+
13
+ <link rel="stylesheet" href="css/common.css" type="text/css" charset="utf-8" />
14
+
15
+ <script type="text/javascript" charset="utf-8">
16
+ hasFrames = window.top.frames.main ? true : false;
17
+ relpath = '';
18
+ framesUrl = "frames.html#!_index.html";
19
+ </script>
20
+
21
+
22
+ <script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
23
+
24
+ <script type="text/javascript" charset="utf-8" src="js/app.js"></script>
25
+
26
+
27
+ </head>
28
+ <body>
29
+ <div id="header">
30
+ <div id="menu">
31
+
32
+
33
+ <div class="noframes"><span class="title">(</span><a href="." target="_top">no frames</a><span class="title">)</span></div>
34
+ </div>
35
+
36
+ <div id="search">
37
+
38
+ <a class="full_list_link" id="class_list_link"
39
+ href="class_list.html">
40
+ Class List
41
+ </a>
42
+
43
+ <a class="full_list_link" id="method_list_link"
44
+ href="method_list.html">
45
+ Method List
46
+ </a>
47
+
48
+ <a class="full_list_link" id="file_list_link"
49
+ href="file_list.html">
50
+ File List
51
+ </a>
52
+
53
+ </div>
54
+ <div class="clear"></div>
55
+ </div>
56
+
57
+ <iframe id="search_frame"></iframe>
58
+
59
+ <div id="content"><h1 class="noborder title">Documentation by YARD 0.8.7.6</h1>
60
+ <div id="listing">
61
+ <h1 class="alphaindex">Alphabetic Index</h1>
62
+
63
+ <div class="clear"></div>
64
+ <h2>Namespace Listing A-Z</h2>
65
+
66
+
67
+
68
+
69
+ <table>
70
+ <tr>
71
+ <td valign='top' width="33%">
72
+
73
+ </td>
74
+ </tr>
75
+ </table>
76
+
77
+ </div>
78
+
79
+ </div>
80
+
81
+ <div id="footer">
82
+ Generated on Sun Aug 9 21:09:19 2015 by
83
+ <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
84
+ 0.8.7.6 (ruby-2.2.0).
85
+ </div>
86
+
87
+ </body>
88
+ </html>
@@ -0,0 +1,58 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
+ <html>
4
+ <head>
5
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
6
+
7
+ <link rel="stylesheet" href="css/full_list.css" type="text/css" media="screen" charset="utf-8" />
8
+
9
+ <link rel="stylesheet" href="css/common.css" type="text/css" media="screen" charset="utf-8" />
10
+
11
+
12
+
13
+ <script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
14
+
15
+ <script type="text/javascript" charset="utf-8" src="js/full_list.js"></script>
16
+
17
+
18
+ <title>Class List</title>
19
+ <base id="base_target" target="_parent" />
20
+ </head>
21
+ <body>
22
+ <script type="text/javascript" charset="utf-8">
23
+ var hasFrames = false;
24
+ try {
25
+ hasFrames = window.top.frames.main ? true : false;
26
+ } catch (e) { }
27
+ if (hasFrames) {
28
+ document.getElementById('base_target').target = 'main';
29
+ document.body.className = 'frames';
30
+ }
31
+ </script>
32
+ <div id="content">
33
+ <h1 id="full_list_header">Class List</h1>
34
+ <div id="nav">
35
+
36
+ <span><a target="_self" href="class_list.html">
37
+ Classes
38
+ </a></span>
39
+
40
+ <span><a target="_self" href="method_list.html">
41
+ Methods
42
+ </a></span>
43
+
44
+ <span><a target="_self" href="file_list.html">
45
+ Files
46
+ </a></span>
47
+
48
+ </div>
49
+ <div id="search">Search: <input type="text" /></div>
50
+
51
+ <ul id="full_list" class="class">
52
+ <li><span class='object_link'><a href="top-level-namespace.html" title="Top Level Namespace (root)">Top Level Namespace</a></span></li>
53
+
54
+
55
+ </ul>
56
+ </div>
57
+ </body>
58
+ </html>
@@ -0,0 +1 @@
1
+ /* Override this file with custom rules */
@@ -0,0 +1,57 @@
1
+ body {
2
+ margin: 0;
3
+ font-family: "Lucida Sans", "Lucida Grande", Verdana, Arial, sans-serif;
4
+ font-size: 13px;
5
+ height: 101%;
6
+ overflow-x: hidden;
7
+ }
8
+
9
+ h1 { padding: 12px 10px; padding-bottom: 0; margin: 0; font-size: 1.4em; }
10
+ .clear { clear: both; }
11
+ #search { position: absolute; right: 5px; top: 9px; padding-left: 24px; }
12
+ #content.insearch #search, #content.insearch #noresults { background: url(data:image/gif;base64,R0lGODlhEAAQAPYAAP///wAAAPr6+pKSkoiIiO7u7sjIyNjY2J6engAAAI6OjsbGxjIyMlJSUuzs7KamppSUlPLy8oKCghwcHLKysqSkpJqamvT09Pj4+KioqM7OzkRERAwMDGBgYN7e3ujo6Ly8vCoqKjY2NkZGRtTU1MTExDw8PE5OTj4+PkhISNDQ0MrKylpaWrS0tOrq6nBwcKysrLi4uLq6ul5eXlxcXGJiYoaGhuDg4H5+fvz8/KKiohgYGCwsLFZWVgQEBFBQUMzMzDg4OFhYWBoaGvDw8NbW1pycnOLi4ubm5kBAQKqqqiQkJCAgIK6urnJyckpKSjQ0NGpqatLS0sDAwCYmJnx8fEJCQlRUVAoKCggICLCwsOTk5ExMTPb29ra2tmZmZmhoaNzc3KCgoBISEiIiIgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCAAAACwAAAAAEAAQAAAHaIAAgoMgIiYlg4kACxIaACEJCSiKggYMCRselwkpghGJBJEcFgsjJyoAGBmfggcNEx0flBiKDhQFlIoCCA+5lAORFb4AJIihCRbDxQAFChAXw9HSqb60iREZ1omqrIPdJCTe0SWI09GBACH5BAkIAAAALAAAAAAQABAAAAdrgACCgwc0NTeDiYozCQkvOTo9GTmDKy8aFy+NOBA7CTswgywJDTIuEjYFIY0JNYMtKTEFiRU8Pjwygy4ws4owPyCKwsMAJSTEgiQlgsbIAMrO0dKDGMTViREZ14kYGRGK38nHguHEJcvTyIEAIfkECQgAAAAsAAAAABAAEAAAB2iAAIKDAggPg4iJAAMJCRUAJRIqiRGCBI0WQEEJJkWDERkYAAUKEBc4Po1GiKKJHkJDNEeKig4URLS0ICImJZAkuQAhjSi/wQyNKcGDCyMnk8u5rYrTgqDVghgZlYjcACTA1sslvtHRgQAh+QQJCAAAACwAAAAAEAAQAAAHZ4AAgoOEhYaCJSWHgxGDJCQARAtOUoQRGRiFD0kJUYWZhUhKT1OLhR8wBaaFBzQ1NwAlkIszCQkvsbOHL7Y4q4IuEjaqq0ZQD5+GEEsJTDCMmIUhtgk1lo6QFUwJVDKLiYJNUd6/hoEAIfkECQgAAAAsAAAAABAAEAAAB2iAAIKDhIWGgiUlh4MRgyQkjIURGRiGGBmNhJWHm4uen4ICCA+IkIsDCQkVACWmhwSpFqAABQoQF6ALTkWFnYMrVlhWvIKTlSAiJiVVPqlGhJkhqShHV1lCW4cMqSkAR1ofiwsjJyqGgQAh+QQJCAAAACwAAAAAEAAQAAAHZ4AAgoOEhYaCJSWHgxGDJCSMhREZGIYYGY2ElYebi56fhyWQniSKAKKfpaCLFlAPhl0gXYNGEwkhGYREUywag1wJwSkHNDU3D0kJYIMZQwk8MjPBLx9eXwuETVEyAC/BOKsuEjYFhoEAIfkECQgAAAAsAAAAABAAEAAAB2eAAIKDhIWGgiUlh4MRgyQkjIURGRiGGBmNhJWHm4ueICImip6CIQkJKJ4kigynKaqKCyMnKqSEK05StgAGQRxPYZaENqccFgIID4KXmQBhXFkzDgOnFYLNgltaSAAEpxa7BQoQF4aBACH5BAkIAAAALAAAAAAQABAAAAdogACCg4SFggJiPUqCJSWGgkZjCUwZACQkgxGEXAmdT4UYGZqCGWQ+IjKGGIUwPzGPhAc0NTewhDOdL7Ykji+dOLuOLhI2BbaFETICx4MlQitdqoUsCQ2vhKGjglNfU0SWmILaj43M5oEAOwAAAAAAAAAAAA==) no-repeat center left; }
13
+ #full_list { padding: 0; list-style: none; margin-left: 0; }
14
+ #full_list ul { padding: 0; }
15
+ #full_list li { padding: 5px; padding-left: 12px; margin: 0; font-size: 1.1em; list-style: none; }
16
+ #noresults { padding: 7px 12px; }
17
+ #content.insearch #noresults { margin-left: 7px; }
18
+ ul.collapsed ul, ul.collapsed li { display: none; }
19
+ ul.collapsed.search_uncollapsed { display: block; }
20
+ ul.collapsed.search_uncollapsed li { display: list-item; }
21
+ li a.toggle { cursor: default; position: relative; left: -5px; top: 4px; text-indent: -999px; width: 10px; height: 9px; margin-left: -10px; display: block; float: left; background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAYAAABb0P4QAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAK8AAACvABQqw0mAAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTM5jWRgMAAAAVdEVYdENyZWF0aW9uIFRpbWUAMy8xNC8wOeNZPpQAAAE2SURBVDiNrZTBccIwEEXfelIAHUA6CZ24BGaWO+FuzZAK4k6gg5QAdGAq+Bxs2Yqx7BzyL7Llp/VfzZeQhCTc/ezuGzKKnKSzpCxXJM8fwNXda3df5RZETlIt6YUzSQDs93sl8w3wBZxCCE10GM1OcWbWjB2mWgEH4Mfdyxm3PSepBHibgQE2wLe7r4HjEidpnXMYdQPKEMJcsZ4zs2POYQOcaPfwMVOo58zsAdMt18BuoVDPxUJRacELbXv3hUIX2vYmOUvi8C8ydz/ThjXrqKqqLbDIAdsCKBd+Wo7GWa7o9qzOQHVVVXeAbs+yHHCH4aTsaCOQqunmUy1yBUAXkdMIfMlgF5EXLo2OpV/c/Up7jG4hhHcYLgWzAZXUc2b2ixsfvc/RmNNfOXD3Q/oeL9axJE1yT9IOoUu6MGUkAAAAAElFTkSuQmCC) no-repeat bottom left; }
22
+ li.collapsed a.toggle { opacity: 0.5; cursor: default; background-position: top left; }
23
+ li { color: #888; cursor: pointer; }
24
+ li.deprecated { text-decoration: line-through; font-style: italic; }
25
+ li.r1 { background: #f0f0f0; }
26
+ li.r2 { background: #fafafa; }
27
+ li:hover { background: #ddd; }
28
+ li small:before { content: "("; }
29
+ li small:after { content: ")"; }
30
+ li small.search_info { display: none; }
31
+ a:link, a:visited { text-decoration: none; color: #05a; }
32
+ li.clicked { background: #05a; color: #ccc; }
33
+ li.clicked a:link, li.clicked a:visited { color: #eee; }
34
+ li.clicked a.toggle { opacity: 0.5; background-position: bottom right; }
35
+ li.collapsed.clicked a.toggle { background-position: top right; }
36
+ #search input { border: 1px solid #bbb; -moz-border-radius: 3px; -webkit-border-radius: 3px; }
37
+ #nav { margin-left: 10px; font-size: 0.9em; display: none; color: #aaa; }
38
+ #nav a:link, #nav a:visited { color: #358; }
39
+ #nav a:hover { background: transparent; color: #5af; }
40
+ .frames #nav span:after { content: ' | '; }
41
+ .frames #nav span:last-child:after { content: ''; }
42
+
43
+ .frames #content h1 { margin-top: 0; }
44
+ .frames li { white-space: nowrap; cursor: normal; }
45
+ .frames li small { display: block; font-size: 0.8em; }
46
+ .frames li small:before { content: ""; }
47
+ .frames li small:after { content: ""; }
48
+ .frames li small.search_info { display: none; }
49
+ .frames #search { width: 170px; position: static; margin: 3px; margin-left: 10px; font-size: 0.9em; color: #888; padding-left: 0; padding-right: 24px; }
50
+ .frames #content.insearch #search { background-position: center right; }
51
+ .frames #search input { width: 110px; }
52
+ .frames #nav { display: block; }
53
+
54
+ #full_list.insearch li { display: none; }
55
+ #full_list.insearch li.found { display: list-item; padding-left: 10px; }
56
+ #full_list.insearch li a.toggle { display: none; }
57
+ #full_list.insearch li small.search_info { display: block; }