ropenlayer 0.0.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +9 -0
- data/Manifest.txt +0 -20
- data/PostInstall.txt +1 -2
- data/README.rdoc +161 -23
- data/lib/generators/ropenlayer/install/INSTALL +16 -0
- data/lib/generators/ropenlayer/install/USAGE +7 -0
- data/lib/generators/ropenlayer/install/install_generator.rb +20 -0
- data/lib/generators/ropenlayer/install/templates/config/initializers/ropenlayer.rb +13 -0
- data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/add_point_off.png +0 -0
- data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/add_point_on.png +0 -0
- data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/blank.gif +0 -0
- data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/close.gif +0 -0
- data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/default_marker.png +0 -0
- data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/drag-rectangle-off.png +0 -0
- data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/drag-rectangle-on.png +0 -0
- data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/draw_line_off.png +0 -0
- data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/draw_line_on.png +0 -0
- data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/draw_point_off.png +0 -0
- data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/draw_point_on.png +0 -0
- data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/draw_polygon_off.png +0 -0
- data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/draw_polygon_on.png +0 -0
- data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/edit_map.png +0 -0
- data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/edit_map_active.png +0 -0
- data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/editing_tool_bar.png +0 -0
- data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/layers_switch.png +0 -0
- data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/layers_switch_active.png +0 -0
- data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/move_feature_off.png +0 -0
- data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/move_feature_on.png +0 -0
- data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/navigation_history.png +0 -0
- data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/none_button.png +0 -0
- data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/overview_replacement.gif +0 -0
- data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/pan-panel-NOALPHA.png +0 -0
- data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/pan-panel.png +0 -0
- data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/pan-panel_active.png +0 -0
- data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/pan_off.png +0 -0
- data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/pan_on.png +0 -0
- data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/panning-hand-off.png +0 -0
- data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/panning-hand-on.png +0 -0
- data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/remove_point_off.png +0 -0
- data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/remove_point_on.png +0 -0
- data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/ruler.png +0 -0
- data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/save_features_off.png +0 -0
- data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/save_features_on.png +0 -0
- data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/view_next_off.png +0 -0
- data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/view_next_on.png +0 -0
- data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/view_previous_off.png +0 -0
- data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/view_previous_on.png +0 -0
- data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/zoom-panel-NOALPHA.png +0 -0
- data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/zoom-panel.png +0 -0
- data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/zoom-panel_active.png +0 -0
- data/lib/generators/ropenlayer/install/templates/public/stylesheets/ropenlayer.css +430 -0
- data/lib/generators/ropenlayer/migration/USAGE +10 -0
- data/lib/generators/ropenlayer/migration/migration_generator.rb +22 -0
- data/lib/generators/ropenlayer/migration/templates/migration.rb +31 -0
- data/lib/ropenlayer/acts_as/mapper.rb +147 -0
- data/lib/ropenlayer/acts_as/nodeable.rb +109 -0
- data/lib/ropenlayer/acts_as.rb +138 -0
- data/lib/ropenlayer/category.rb +14 -0
- data/lib/ropenlayer/form_builder.rb +69 -0
- data/lib/ropenlayer/icon.rb +12 -0
- data/lib/ropenlayer/js_helper/jquery.rb +63 -0
- data/lib/ropenlayer/js_helper/prototype.rb +51 -0
- data/lib/ropenlayer/localization.rb +6 -0
- data/lib/ropenlayer/node.rb +38 -0
- data/lib/ropenlayer/openlayer/box_control/base.rb +57 -0
- data/lib/ropenlayer/openlayer/box_control/edit_map.rb +85 -0
- data/lib/ropenlayer/openlayer/box_control/layers_select.rb +17 -0
- data/lib/ropenlayer/openlayer/control.rb +42 -0
- data/lib/ropenlayer/openlayer/feature.rb +119 -0
- data/lib/ropenlayer/openlayer/js.rb +63 -0
- data/lib/ropenlayer/openlayer/layer/base.rb +88 -0
- data/lib/ropenlayer/openlayer/layer/elements_marker.rb +20 -0
- data/lib/ropenlayer/openlayer/layer/elements_vector.rb +35 -0
- data/lib/ropenlayer/openlayer/map.rb +192 -0
- data/lib/ropenlayer.rb +59 -14
- data/ropenlayer.gemspec +11 -8
- metadata +94 -17
- data/lib/ropenlayer/box_control/base.rb +0 -47
- data/lib/ropenlayer/box_control/edit_map.rb +0 -79
- data/lib/ropenlayer/box_control/layers_select.rb +0 -16
- data/lib/ropenlayer/control.rb +0 -40
- data/lib/ropenlayer/js.rb +0 -62
- data/lib/ropenlayer/layer/base.rb +0 -87
- data/lib/ropenlayer/layer/elements_marker.rb +0 -18
- data/lib/ropenlayer/layer/elements_vector.rb +0 -33
- data/lib/ropenlayer/map.rb +0 -176
data/History.txt
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
=== 0.3.0 2011-02-27
|
2
|
+
|
3
|
+
* Major release.
|
4
|
+
* include acts_as_map and acts_as_localizable_on class methods to Rails applications.
|
5
|
+
* make ropenlayer not js framework dependent.
|
6
|
+
* included form builder helpers to provide easily storage new nodes on map
|
7
|
+
* added Ropenlayer::Openlayer::Feature to provide drawing of nodes in map (at the moment, poing, lines and polygons are supported
|
8
|
+
* more facilities to Rails applications (migration and install generators)
|
9
|
+
|
1
10
|
=== 0.0.1 2011-01-11
|
2
11
|
|
3
12
|
* 1 major enhancement:
|
data/Manifest.txt
CHANGED
@@ -1,23 +1,3 @@
|
|
1
|
-
History.txt
|
2
|
-
Manifest.txt
|
3
|
-
PostInstall.txt
|
4
|
-
README.rdoc
|
5
|
-
Rakefile
|
6
|
-
ropenlayer.gemspec
|
7
|
-
lib/ropenlayer.rb
|
8
|
-
lib/ropenlayer/control.rb
|
9
|
-
lib/ropenlayer/js.rb
|
10
|
-
lib/ropenlayer/map.rb
|
11
|
-
lib/ropenlayer/layer/base.rb
|
12
|
-
lib/ropenlayer/layer/elements_marker.rb
|
13
|
-
lib/ropenlayer/layer/elements_vector.rb
|
14
|
-
lib/ropenlayer/box_control/base.rb
|
15
|
-
lib/ropenlayer/box_control/edit_map.rb
|
16
|
-
lib/ropenlayer/box_control/layers_select.rb
|
17
|
-
script/console
|
18
|
-
script/destroy
|
19
|
-
script/generate
|
20
|
-
spec/
|
21
1
|
|
22
2
|
|
23
3
|
|
data/PostInstall.txt
CHANGED
data/README.rdoc
CHANGED
@@ -4,45 +4,186 @@
|
|
4
4
|
* http://gitorious/gnoxys/ropenlayer
|
5
5
|
* http://openlayers.org/
|
6
6
|
|
7
|
-
==
|
7
|
+
== Description:
|
8
8
|
|
9
9
|
Ropenlayer is a wrapper constructor for openlayer javascript library written in ruby. It aims to provide an easy way to build maps and display it on webs.
|
10
10
|
|
11
|
+
Ropenlayer is also an ActsAs extend module for Rails. It provides acts_as_map and acts_as_localizable_on class methods to perform geolicalization maping of objects.
|
12
|
+
|
11
13
|
At the moment, Ropenlayer gem comes with the following features.
|
12
14
|
|
13
|
-
- Create a JS
|
15
|
+
- Create a JS Openlayer.Map object with some options from ruby methods.
|
14
16
|
- Manage layers and controls displayed on the map.
|
15
|
-
- Create, by default, a marker and vectors layers for render items with icons or differents features as polygons or lines. more will come.
|
16
|
-
- Ropenlayer will namescope all the outpus so several maps on same screen are allowed.
|
17
|
+
- Create, by default, a marker and vectors layers for render items with icons or differents features as polygons, point or lines. more will come.
|
18
|
+
- Ropenlayer will namescope all the outpus so several maps, with differents options on same screen are allowed.
|
17
19
|
- Set defaul latitude, longitude and zoom,
|
20
|
+
|
21
|
+
Working on Rails will give also this helpers
|
22
|
+
|
23
|
+
- acts_as_map and acts_as_localizable_on methods which perform all database storage of localization data.
|
24
|
+
- form helpers to provide an easy way to draw and store localizations on the map.
|
18
25
|
|
19
26
|
== Before use ropenlayer
|
20
27
|
|
21
28
|
Ropenlayer is still in alpha stage, so, you should have some skills with javascript and openlayers.
|
22
29
|
|
23
|
-
|
30
|
+
Ropenlayer comes with some rails 3 generator to download latest OpenLayer js and copy images and stylesheets on Rails applications. Also, ropenLayer has big dependencies of some rails classes (ActiveRecord and ActionView), so in order to user database backend or form helpers methods, you need to develops your application on Rails.
|
31
|
+
|
32
|
+
Ropenlayer can work alone without Rails context, but it is not the priority ATM.
|
33
|
+
|
34
|
+
== Install
|
35
|
+
|
36
|
+
On your rails application just define ropenlayer gem
|
37
|
+
|
38
|
+
config.gem 'ropenlayer', '~>0.3.0'
|
39
|
+
|
40
|
+
In order to use acts_as_* behavior methods, generate installer and migration on your application
|
41
|
+
|
42
|
+
$ rails generate ropenlayer:migration
|
43
|
+
$ rake db:migrate
|
44
|
+
|
45
|
+
Will create nodes and localizations table which are managed by Ropenlayer::Node and Ropenlayer::Localization classes, based on ActiveRecord
|
46
|
+
|
47
|
+
$ rails generate ropenlayer:install
|
48
|
+
|
49
|
+
Will create an initializer stored on <your_app/config/initializers/ropenlayer.rb with some options. Will also download latest OpenLayer Js library, and copy default css style for map 'ropenlayer.css', and some images needed on styling and map operations.
|
50
|
+
|
51
|
+
To start using Ropenlayer, include acts_as_map method on your mapper model, for example, team
|
52
|
+
|
53
|
+
class Team < ActiveRecord::Base
|
54
|
+
|
55
|
+
acts_as_map :default_layer => :google_streets,
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
In your view
|
60
|
+
|
61
|
+
<%= @team.ropenlayer_map.to_js %>
|
62
|
+
|
63
|
+
|
64
|
+
If you want to set starting latitude / longitude, zoom, default layer, you can pass it though options Hash. For example, team can have a main office.
|
65
|
+
|
66
|
+
class Team < ActiveRecord
|
67
|
+
|
68
|
+
has_many :offices
|
69
|
+
has_one :main_office, :conditions => { :main => true }
|
70
|
+
|
71
|
+
acts_as_map :default_layer => :google_streets, :longitude => Proc.new{|t| t.main_office.longitude }, :latitude => Proc.new{|t| t.main_office.latitude }, :zoom => 5
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
For more options see Ropenlayer::ActsAs::Mapper
|
76
|
+
|
77
|
+
|
78
|
+
Ropenlayer also can include your relations models on the map. Just give to the nodeable model the ability to be localizable
|
79
|
+
|
80
|
+
class Office < ActiveRecord
|
81
|
+
|
82
|
+
belongs_to :team
|
83
|
+
|
84
|
+
acts_as_localizable_on :team
|
24
85
|
|
25
|
-
|
86
|
+
end
|
26
87
|
|
27
|
-
|
88
|
+
Now, in your mapper model, you can include this relation as nodeable.
|
28
89
|
|
29
|
-
- js_div, use to scope all the variables names to draw js output.
|
30
|
-
- div_id, the dom_id passed as argument to construtor. For example
|
31
90
|
|
32
|
-
|
91
|
+
class Team < ActiveRecord
|
33
92
|
|
34
|
-
|
35
|
-
|
36
|
-
m.js_id
|
37
|
-
=> "olObject_group_map"
|
38
|
-
n.div_id
|
39
|
-
=> "group_map"
|
93
|
+
has_many :offices
|
94
|
+
has_one :main_office, :conditions => { :main => true }
|
40
95
|
|
41
|
-
|
96
|
+
acts_as_map :default_layer => :google_streets, :longitude => Proc.new{|t| t.main_office.longitude }, :latitude => Proc.new{|t| t.main_office.latitude }, :zoom => 5
|
97
|
+
:nodes => [ :offices ]
|
42
98
|
|
43
|
-
|
99
|
+
end
|
100
|
+
|
101
|
+
Ropenlayer will displayed now on team map, offices that have enough localization info. See Ropenlayer::ActsAs::Nodeable for more info
|
102
|
+
|
103
|
+
|
104
|
+
== Working with form
|
105
|
+
|
106
|
+
Ropenlayer comes with some methods built on ActionView::Helpers::FormBuilder, so on your form.
|
107
|
+
|
108
|
+
<%= form_for @team do |f| %>
|
109
|
+
|
110
|
+
<div>
|
111
|
+
<%= f.label :name %>
|
112
|
+
<%= f.input_field :name %>
|
113
|
+
</div>
|
114
|
+
|
115
|
+
<div>
|
116
|
+
<%= f.label :localization %>
|
117
|
+
<%= f.map_localization %>
|
118
|
+
</div>
|
119
|
+
|
120
|
+
<%= f.submit %>
|
121
|
+
|
122
|
+
<% end %>
|
123
|
+
|
124
|
+
This will render a map with automatic localization callbacks to store in hidden fields the zoom, longitude and latitude of the current map state.
|
125
|
+
|
126
|
+
To use this facility, :latitude, :longitude and :zoom options must point to a valid get and set methods on the mapper Class. For example
|
127
|
+
|
128
|
+
class Team < ActiveRecord
|
129
|
+
|
130
|
+
has_many :offices
|
131
|
+
has_one :main_office, :conditions => { :main => true }
|
132
|
+
|
133
|
+
acts_as_map :default_layer => :google_streets, :longitude => :main_office_longitude, :latitude => :main_office_latitude, :zoom => :main_office_zoom
|
134
|
+
:nodes => [ :offices ]
|
135
|
+
|
136
|
+
def main_office_longitude
|
137
|
+
main_office.longitude
|
138
|
+
end
|
139
|
+
|
140
|
+
def main_office_longitude=(value)
|
141
|
+
main_office_longitude = value
|
142
|
+
end
|
143
|
+
|
144
|
+
def main_office_latitude
|
145
|
+
main_office.latitude
|
146
|
+
end
|
147
|
+
|
148
|
+
def main_office_latitude=(value)
|
149
|
+
main_office.latitude = value
|
150
|
+
end
|
151
|
+
|
152
|
+
def main_office_longitude
|
153
|
+
main_office.longitude
|
154
|
+
end
|
155
|
+
|
156
|
+
def main_office_zoom=(value)
|
157
|
+
main_office.zoom = value
|
158
|
+
end
|
159
|
+
|
160
|
+
end
|
161
|
+
|
162
|
+
Also, provides to a form builder method on nodeable class to draw instance position. For example
|
163
|
+
|
164
|
+
<%= form_for [@team, @office] do |f| %>
|
165
|
+
|
166
|
+
<div>
|
167
|
+
<%= f.label :name %>
|
168
|
+
<%= f.input_field :name %>
|
169
|
+
</div>
|
170
|
+
|
171
|
+
<div>
|
172
|
+
<%= f.label :address %>
|
173
|
+
<%= f.input_field :address %>
|
174
|
+
</div>
|
175
|
+
|
176
|
+
<div>
|
177
|
+
<%= f.label :localization %>
|
178
|
+
<%= f.map_nodes_editor :team %>
|
179
|
+
</div>
|
180
|
+
|
181
|
+
<%= f.submit %>
|
182
|
+
|
183
|
+
<% end %>
|
184
|
+
|
185
|
+
This will render a map with automatic localization callbacks to store the position of the node in the map. At the moment, ropenlayer can draw points, lines and polygons. Circles will be next.
|
44
186
|
|
45
|
-
For more information see Ropenlayer::Map
|
46
187
|
|
47
188
|
== DEMO
|
48
189
|
|
@@ -51,10 +192,7 @@ You can take a look to cartac (http://cartac.gnoxys.net) a application we develo
|
|
51
192
|
== REQUIREMENTS:
|
52
193
|
|
53
194
|
* json_pure (~>1.2.3)
|
54
|
-
|
55
|
-
== INSTALL:
|
56
|
-
|
57
|
-
* gem install ropenLayer
|
195
|
+
* rails (~>3.0.3)
|
58
196
|
|
59
197
|
== LICENSE:
|
60
198
|
|
@@ -0,0 +1,16 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
Ropenlayer INSTALLED!
|
4
|
+
|
5
|
+
Remeber to include Js and CSS files in your layout
|
6
|
+
|
7
|
+
<%= javascript_include_tag 'OpenLayers' %>
|
8
|
+
|
9
|
+
and
|
10
|
+
|
11
|
+
<%= stylesheet_link_tag 'ropenlayer' %>
|
12
|
+
|
13
|
+
If you want to use Google Maps layer, you need to include it also. for example
|
14
|
+
|
15
|
+
<script src="http://maps.google.com/maps/api/js?v=3.2.4&sensor=true"></script>
|
16
|
+
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Ropenlayer
|
2
|
+
module Generators
|
3
|
+
class InstallGenerator < Rails::Generators::Base
|
4
|
+
|
5
|
+
source_root File.expand_path('../templates', __FILE__)
|
6
|
+
|
7
|
+
def install
|
8
|
+
copy_file "config/initializers/ropenlayer.rb"
|
9
|
+
|
10
|
+
get "http://openlayers.org/api/OpenLayers.js", "public/javascripts/OpenLayers.js"
|
11
|
+
copy_file "public/stylesheets/ropenlayer.css"
|
12
|
+
directory "public/images/ropenlayer"
|
13
|
+
|
14
|
+
readme "../INSTALL"
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# Use this hook to configure Ropenlayer
|
2
|
+
Ropenlayer.setup do |config|
|
3
|
+
# Default JS Helper
|
4
|
+
# Ropenlayer needs some extra Js functions in order to create and perform some operations over dom elements
|
5
|
+
# Ropenlayer comes with 2 Js helpers bases on both popular javascript frameworks: jquery and prototype
|
6
|
+
# By default, if none is set, Jquery is used. Set default_js_helper to Ropenlayer::JsHelper::Prototype to enable prototype
|
7
|
+
# Of course, you can use custom one. See Ropenlayer::JsHelper::Prototype or Ropenlayer::JsHelper::Jquery to see which methods are called
|
8
|
+
# and configure your helper to provide this funcionality (almost are: hide and show elements, create div and a elements and update / insert html in dom
|
9
|
+
# config.js_helper = Ropenlayer::JsHelper::Prototype
|
10
|
+
end
|
11
|
+
|
12
|
+
|
13
|
+
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/drag-rectangle-off.png
ADDED
Binary file
|
data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/drag-rectangle-on.png
ADDED
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/draw_polygon_off.png
ADDED
Binary file
|
Binary file
|
Binary file
|
Binary file
|
data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/editing_tool_bar.png
ADDED
Binary file
|
Binary file
|
data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/layers_switch_active.png
ADDED
Binary file
|
data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/move_feature_off.png
ADDED
Binary file
|
Binary file
|
data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/navigation_history.png
ADDED
Binary file
|
Binary file
|
data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/overview_replacement.gif
ADDED
Binary file
|
data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/pan-panel-NOALPHA.png
ADDED
Binary file
|
Binary file
|
data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/pan-panel_active.png
ADDED
Binary file
|
Binary file
|
Binary file
|
data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/panning-hand-off.png
ADDED
Binary file
|
Binary file
|
data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/remove_point_off.png
ADDED
Binary file
|
Binary file
|
Binary file
|
data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/save_features_off.png
ADDED
Binary file
|
data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/save_features_on.png
ADDED
Binary file
|
Binary file
|
Binary file
|
data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/view_previous_off.png
ADDED
Binary file
|
data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/view_previous_on.png
ADDED
Binary file
|
data/lib/generators/ropenlayer/install/templates/public/images/ropenlayer/zoom-panel-NOALPHA.png
ADDED
Binary file
|
Binary file
|