$("#sidebar_title").html(I18n.t('site.sidebar.search_results'));
$("#sidebar_content").load($(this).attr("action"), {
query: $("#query").val(),
+ zoom: map.getZoom(),
minlon: bounds.getWest(),
minlat: bounds.getSouth(),
maxlon: bounds.getEast(),
before_filter :authorize_web
before_filter :set_locale
- before_filter :convert_latlon, :only => [:search]
def search
- @query = params[:query]
- @sources = Array.new
+ normalize_params
- @query.sub(/^\s+/, "")
- @query.sub(/\s+$/, "")
-
- if @query.match(/^[+-]?\d+(\.\d*)?\s*[\s,]\s*[+-]?\d+(\.\d*)?$/)
- @sources.push "latlon"
- elsif @query.match(/^\d{5}(-\d{4})?$/)
+ @sources = []
+ if params[:lat] && params[:lon]
+ @sources.push "osm_nominatim_reverse"
+ @sources.push "geonames_reverse"
+ elsif params[:query].match(/^\d{5}(-\d{4})?$/)
@sources.push "us_postcode"
@sources.push "osm_nominatim"
- elsif @query.match(/^(GIR 0AA|[A-PR-UWYZ]([0-9]{1,2}|([A-HK-Y][0-9]|[A-HK-Y][0-9]([0-9]|[ABEHMNPRV-Y]))|[0-9][A-HJKS-UW])\s*[0-9][ABD-HJLNP-UW-Z]{2})$/i)
+ elsif params[:query].match(/^(GIR 0AA|[A-PR-UWYZ]([0-9]{1,2}|([A-HK-Y][0-9]|[A-HK-Y][0-9]([0-9]|[ABEHMNPRV-Y]))|[0-9][A-HJKS-UW])\s*[0-9][ABD-HJLNP-UW-Z]{2})$/i)
@sources.push "uk_postcode"
@sources.push "osm_nominatim"
- elsif @query.match(/^[A-Z]\d[A-Z]\s*\d[A-Z]\d$/i)
+ elsif params[:query].match(/^[A-Z]\d[A-Z]\s*\d[A-Z]\d$/i)
@sources.push "ca_postcode"
@sources.push "osm_nominatim"
else
end
end
- def search_latlon
- # get query parameters
- query = params[:query]
-
- # create result array
- @results = Array.new
-
- # decode the location
- if m = query.match(/^\s*([+-]?\d+(\.\d*)?)\s*[\s,]\s*([+-]?\d+(\.\d*)?)\s*$/)
- lat = m[1].to_f
- lon = m[3].to_f
- end
-
- # generate results
- if lat < -90 or lat > 90
- @error = "Latitude #{lat} out of range"
- render :action => "error"
- elsif lon < -180 or lon > 180
- @error = "Longitude #{lon} out of range"
- render :action => "error"
- else
- @results.push({:lat => lat, :lon => lon,
- :zoom => POSTCODE_ZOOM,
- :name => "#{lat}, #{lon}"})
-
- render :action => "results"
- end
- end
-
def search_us_postcode
# get query parameters
query = params[:query]
render :action => "error"
end
- def description
- @sources = Array.new
-
- @sources.push({ :name => "osm_nominatim" })
- @sources.push({ :name => "geonames" })
- end
-
- def description_osm_nominatim
+ def search_osm_nominatim_reverse
# get query parameters
lat = params[:lat]
lon = params[:lon]
# parse the response
response.elements.each("reversegeocode/result") do |result|
+ lat = result.attributes["lat"].to_s
+ lon = result.attributes["lon"].to_s
+ object_type = result.attributes["osm_type"]
+ object_id = result.attributes["osm_id"]
description = result.get_text.to_s
- @results.push({:prefix => "#{description}"})
+ @results.push({:lat => lat, :lon => lon,
+ :zoom => zoom,
+ :name => description,
+ :type => object_type, :id => object_id})
end
render :action => "results"
render :action => "error"
end
- def description_geonames
+ def search_geonames_reverse
# get query parameters
lat = params[:lat]
lon = params[:lon]
response.elements.each("geonames/countrySubdivision") do |geoname|
name = geoname.get_text("adminName1").to_s
country = geoname.get_text("countryName").to_s
- @results.push({:prefix => "#{name}, #{country}"})
+ @results.push({:lat => lat, :lon => lon,
+ :zoom => GEONAMES_ZOOM,
+ :name => name,
+ :suffix => ", #{country}"})
end
render :action => "results"
return URI.escape(query, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]", false, 'N'))
end
- def convert_latlon
- @query = params[:query]
+ def normalize_params
+ query = params[:query]
+ return unless query
- if latlon = @query.match(/^([NS])\s*(\d{1,3}(\.\d*)?)\W*([EW])\s*(\d{1,3}(\.\d*)?)$/).try(:captures) # [NSEW] decimal degrees
- params[:query] = nsew_to_decdeg(latlon)
- elsif latlon = @query.match(/^(\d{1,3}(\.\d*)?)\s*([NS])\W*(\d{1,3}(\.\d*)?)\s*([EW])$/).try(:captures) # decimal degrees [NSEW]
- params[:query] = nsew_to_decdeg(latlon)
+ query.strip!
- elsif latlon = @query.match(/^([NS])\s*(\d{1,3})°?\s*(\d{1,3}(\.\d*)?)?['′]?\W*([EW])\s*(\d{1,3})°?\s*(\d{1,3}(\.\d*)?)?['′]?$/).try(:captures) # [NSEW] degrees, decimal minutes
- params[:query] = ddm_to_decdeg(latlon)
- elsif latlon = @query.match(/^(\d{1,3})°?\s*(\d{1,3}(\.\d*)?)?['′]?\s*([NS])\W*(\d{1,3})°?\s*(\d{1,3}(\.\d*)?)?['′]?\s*([EW])$/).try(:captures) # degrees, decimal minutes [NSEW]
- params[:query] = ddm_to_decdeg(latlon)
+ if latlon = query.match(/^([NS])\s*(\d{1,3}(\.\d*)?)\W*([EW])\s*(\d{1,3}(\.\d*)?)$/).try(:captures) # [NSEW] decimal degrees
+ params.merge!(nsew_to_decdeg(latlon)).delete(:query)
+ elsif latlon = query.match(/^(\d{1,3}(\.\d*)?)\s*([NS])\W*(\d{1,3}(\.\d*)?)\s*([EW])$/).try(:captures) # decimal degrees [NSEW]
+ params.merge!(nsew_to_decdeg(latlon)).delete(:query)
- elsif latlon = @query.match(/^([NS])\s*(\d{1,3})°?\s*(\d{1,2})['′]?\s*(\d{1,3}(\.\d*)?)?["″]?\W*([EW])\s*(\d{1,3})°?\s*(\d{1,2})['′]?\s*(\d{1,3}(\.\d*)?)?["″]?$/).try(:captures) # [NSEW] degrees, minutes, decimal seconds
- params[:query] = dms_to_decdeg(latlon)
- elsif latlon = @query.match(/^(\d{1,3})°?\s*(\d{1,2})['′]?\s*(\d{1,3}(\.\d*)?)?["″]\s*([NS])\W*(\d{1,3})°?\s*(\d{1,2})['′]?\s*(\d{1,3}(\.\d*)?)?["″]?\s*([EW])$/).try(:captures) # degrees, minutes, decimal seconds [NSEW]
- params[:query] = dms_to_decdeg(latlon)
- else
- return
+ elsif latlon = query.match(/^([NS])\s*(\d{1,3})°?\s*(\d{1,3}(\.\d*)?)?['′]?\W*([EW])\s*(\d{1,3})°?\s*(\d{1,3}(\.\d*)?)?['′]?$/).try(:captures) # [NSEW] degrees, decimal minutes
+ params.merge!(ddm_to_decdeg(latlon)).delete(:query)
+ elsif latlon = query.match(/^(\d{1,3})°?\s*(\d{1,3}(\.\d*)?)?['′]?\s*([NS])\W*(\d{1,3})°?\s*(\d{1,3}(\.\d*)?)?['′]?\s*([EW])$/).try(:captures) # degrees, decimal minutes [NSEW]
+ params.merge!(ddm_to_decdeg(latlon)).delete(:query)
+
+ elsif latlon = query.match(/^([NS])\s*(\d{1,3})°?\s*(\d{1,2})['′]?\s*(\d{1,3}(\.\d*)?)?["″]?\W*([EW])\s*(\d{1,3})°?\s*(\d{1,2})['′]?\s*(\d{1,3}(\.\d*)?)?["″]?$/).try(:captures) # [NSEW] degrees, minutes, decimal seconds
+ params.merge!(dms_to_decdeg(latlon)).delete(:query)
+ elsif latlon = query.match(/^(\d{1,3})°?\s*(\d{1,2})['′]?\s*(\d{1,3}(\.\d*)?)?["″]\s*([NS])\W*(\d{1,3})°?\s*(\d{1,2})['′]?\s*(\d{1,3}(\.\d*)?)?["″]?\s*([EW])$/).try(:captures) # degrees, minutes, decimal seconds [NSEW]
+ params.merge!(dms_to_decdeg(latlon)).delete(:query)
+
+ elsif latlon = query.match(/^\s*([+-]?\d+(\.\d*)?)\s*[\s,]\s*([+-]?\d+(\.\d*)?)\s*$/)
+ params.merge!({:lat => latlon[1].to_f, :lon => latlon[3].to_f}).delete(:query)
end
end
captures[0].downcase != 's' ? lat = captures[1].to_f : lat = -(captures[1].to_f)
captures[3].downcase != 'w' ? lon = captures[4].to_f : lon = -(captures[4].to_f)
end
- return "#{lat}, #{lon}"
+ {:lat => lat, :lon => lon}
end
def ddm_to_decdeg(captures)
captures[0].downcase != 's' ? lat = captures[1].to_f + captures[2].to_f/60 : lat = -(captures[1].to_f + captures[2].to_f/60)
captures[4].downcase != 'w' ? lon = captures[5].to_f + captures[6].to_f/60 : lon = -(captures[5].to_f + captures[6].to_f/60)
end
- return "#{lat}, #{lon}"
+ {:lat => lat, :lon => lon}
end
def dms_to_decdeg(captures)
captures[0].downcase != 's' ? lat = captures[1].to_f + (captures[2].to_f + captures[3].to_f/60)/60 : lat = -(captures[1].to_f + (captures[2].to_f + captures[3].to_f/60)/60)
captures[5].downcase != 'w' ? lon = captures[6].to_f + (captures[7].to_f + captures[8].to_f/60)/60 : lon = -(captures[6].to_f + (captures[7].to_f + captures[8].to_f/60)/60)
end
- return "#{lat}, #{lon}"
+ {:lat => lat, :lon => lon}
end
end
+++ /dev/null
-<% @sources.each do |source| %>
- <% if source[:types] %>
- <h4><%= raw(t("geocoder.description.title.#{source[:name]}", :types => t("geocoder.description.types.#{source[:types]}"))) %></h4>
- <% else %>
- <h4><%= raw(t("geocoder.description.title.#{source[:name]}")) %></h4>
- <% end %>
- <div class='search_results_entry inner12' id='<%= "description_#{source[:name]}_#{source[:types]}" %>'>
- <%= image_tag "searching.gif", :class => "search_searching" %>
- </div>
- <script type="text/javascript">
- $("#description_<%= source[:name] %>_<%= source[:types] %>").load("<%= raw url_for :action => "description_#{source[:name]}", :lat => params[:lat], :lon => params[:lon], :zoom => params[:zoom], :types => source[:types], :max => source[:max] %>");
- </script>
-<% end %>
<%= image_tag "searching.gif", :class => "search_searching" %>
</div>
<script type="text/javascript">
- $("#search_<%= source %>").load("<%= raw url_for :action => "search_#{source}", :query => @query, :minlat => params[:minlat], :minlon => params[:minlon], :maxlat => params[:maxlat], :maxlon => params[:maxlon] %>");
+ $("#search_<%= source %>").load("<%= raw url_for params.merge(:action => "search_#{source}") %>");
</script>
<% end %>
</div>
<p class='search_help deemphasize'>
<%= raw(t 'site.search.search_help') %>
- <%= link_to t('site.search.where_am_i'), { :controller => :geocoder, :action => :description }, { :id => "describe_location", :title => t('site.search.where_am_i_title') } %>
+ <%= link_to t('site.search.where_am_i'), { :controller => :geocoder, :action => :search }, { :id => "describe_location", :title => t('site.search.where_am_i_title') } %>
</p>
</div>
<% end %>
geocoder:
search:
title:
- latlon: 'Results from <a href="http://openstreetmap.org/">Internal</a>'
us_postcode: 'Results from <a href="http://geocoder.us/">Geocoder.us</a>'
uk_postcode: 'Results from <a href="http://www.npemap.org.uk/">NPEMap / FreeThe Postcode</a>'
ca_postcode: 'Results from <a href="http://geocoder.ca/">Geocoder.CA</a>'
osm_nominatim: 'Results from <a href="http://nominatim.openstreetmap.org/">OpenStreetMap Nominatim</a>'
geonames: 'Results from <a href="http://www.geonames.org/">GeoNames</a>'
+ osm_nominatim_reverse: 'Results from <a href="http://nominatim.openstreetmap.org/">OpenStreetMap Nominatim</a>'
+ geonames_reverse: 'Results from <a href="http://www.geonames.org/">GeoNames</a>'
search_osm_nominatim:
prefix_format: "%{name}"
prefix:
# geocoder
match '/geocoder/search' => 'geocoder#search', :via => :post
- match '/geocoder/search_latlon' => 'geocoder#search_latlon', :via => :get
match '/geocoder/search_us_postcode' => 'geocoder#search_us_postcode', :via => :get
match '/geocoder/search_uk_postcode' => 'geocoder#search_uk_postcode', :via => :get
match '/geocoder/search_ca_postcode' => 'geocoder#search_ca_postcode', :via => :get
match '/geocoder/search_osm_nominatim' => 'geocoder#search_osm_nominatim', :via => :get
match '/geocoder/search_geonames' => 'geocoder#search_geonames', :via => :get
- match '/geocoder/description' => 'geocoder#description', :via => :post
- match '/geocoder/description_osm_nominatim' => 'geocoder#description_osm_nominatim', :via => :get
- match '/geocoder/description_geonames' => 'geocoder#description_geonames', :via => :get
+ match '/geocoder/search_osm_nominatim_reverse' => 'geocoder#search_osm_nominatim_reverse', :via => :get
+ match '/geocoder/search_geonames_reverse' => 'geocoder#search_geonames_reverse', :via => :get
# export
match '/export/start' => 'export#start', :via => :get
{ :path => "/geocoder/search", :method => :post },
{ :controller => "geocoder", :action => "search" }
)
- assert_routing(
- { :path => "/geocoder/search_latlon", :method => :get },
- { :controller => "geocoder", :action => "search_latlon" }
- )
assert_routing(
{ :path => "/geocoder/search_us_postcode", :method => :get },
{ :controller => "geocoder", :action => "search_us_postcode" }
{ :path => "/geocoder/search_geonames", :method => :get },
{ :controller => "geocoder", :action => "search_geonames" }
)
-
- assert_routing(
- { :path => "/geocoder/description", :method => :post },
- { :controller => "geocoder", :action => "description" }
- )
assert_routing(
- { :path => "/geocoder/description_osm_nominatim", :method => :get },
- { :controller => "geocoder", :action => "description_osm_nominatim" }
+ { :path => "/geocoder/search_osm_nominatim_reverse", :method => :get },
+ { :controller => "geocoder", :action => "search_osm_nominatim_reverse" }
)
assert_routing(
- { :path => "/geocoder/description_geonames", :method => :get },
- { :controller => "geocoder", :action => "description_geonames" }
+ { :path => "/geocoder/search_geonames_reverse", :method => :get },
+ { :controller => "geocoder", :action => "search_geonames_reverse" }
)
end
].each do |code|
post :search, :query => code
assert_response :success
- assert_equal ['latlon'], assigns(:sources)
- assert_equal code, assigns(:query)
+ assert_equal ['osm_nominatim_reverse', 'geonames_reverse'], assigns(:sources)
+ assert_nil @controller.params[:query]
+ assert_in_delta 50.06773, @controller.params[:lat]
+ assert_in_delta 14.37742, @controller.params[:lon]
end
end
].each do |code|
post :search, :query => code
assert_response :success
- assert_equal ['latlon'], assigns(:sources)
- assert_equal "50.06773, 14.37742", assigns(:query)
+ assert_equal ['osm_nominatim_reverse', 'geonames_reverse'], assigns(:sources)
+ assert_nil @controller.params[:query]
+ assert_in_delta 50.06773, @controller.params[:lat]
+ assert_in_delta 14.37742, @controller.params[:lon]
end
end
].each do |code|
post :search, :query => code
assert_response :success
- assert_equal ['latlon'], assigns(:sources)
- assert_equal "50.06773, -14.37742", assigns(:query)
+ assert_equal ['osm_nominatim_reverse', 'geonames_reverse'], assigns(:sources)
+ assert_nil @controller.params[:query]
+ assert_in_delta 50.06773, @controller.params[:lat]
+ assert_in_delta -14.37742, @controller.params[:lon]
end
end
].each do |code|
post :search, :query => code
assert_response :success
- assert_equal ['latlon'], assigns(:sources)
- assert_equal "-50.06773, 14.37742", assigns(:query)
+ assert_equal ['osm_nominatim_reverse', 'geonames_reverse'], assigns(:sources)
+ assert_nil @controller.params[:query]
+ assert_in_delta -50.06773, @controller.params[:lat]
+ assert_in_delta 14.37742, @controller.params[:lon]
end
end
].each do |code|
post :search, :query => code
assert_response :success
- assert_equal ['latlon'], assigns(:sources)
- assert_equal "-50.06773, -14.37742", assigns(:query)
+ assert_equal ['osm_nominatim_reverse', 'geonames_reverse'], assigns(:sources)
+ assert_nil @controller.params[:query]
+ assert_in_delta -50.06773, @controller.params[:lat]
+ assert_in_delta -14.37742, @controller.params[:lon]
end
end
].each do |code|
post :search, :query => code
assert_response :success
- assert_equal ['latlon'], assigns(:sources)
- assert_latlon_equal_round "50.06773, 14.37742", assigns(:query), 5
+ assert_equal ['osm_nominatim_reverse', 'geonames_reverse'], assigns(:sources)
+ assert_nil @controller.params[:query]
+ assert_in_delta 50.06773, @controller.params[:lat]
+ assert_in_delta 14.37742, @controller.params[:lon]
end
end
].each do |code|
post :search, :query => code
assert_response :success
- assert_equal ['latlon'], assigns(:sources)
- assert_latlon_equal_round "50.06773, -14.37742", assigns(:query), 5
+ assert_equal ['osm_nominatim_reverse', 'geonames_reverse'], assigns(:sources)
+ assert_nil @controller.params[:query]
+ assert_in_delta 50.06773, @controller.params[:lat]
+ assert_in_delta -14.37742, @controller.params[:lon]
end
end
].each do |code|
post :search, :query => code
assert_response :success
- assert_equal ['latlon'], assigns(:sources)
- assert_latlon_equal_round "-50.06773, 14.37742", assigns(:query), 5
+ assert_equal ['osm_nominatim_reverse', 'geonames_reverse'], assigns(:sources)
+ assert_nil @controller.params[:query]
+ assert_in_delta -50.06773, @controller.params[:lat]
+ assert_in_delta 14.37742, @controller.params[:lon]
end
end
].each do |code|
post :search, :query => code
assert_response :success
- assert_equal ['latlon'], assigns(:sources)
- assert_latlon_equal_round "-50.06773, -14.37742", assigns(:query), 5
+ assert_equal ['osm_nominatim_reverse', 'geonames_reverse'], assigns(:sources)
+ assert_nil @controller.params[:query]
+ assert_in_delta -50.06773, @controller.params[:lat]
+ assert_in_delta -14.37742, @controller.params[:lon]
end
end
].each do |code|
post :search, :query => code
assert_response :success
- assert_equal ['latlon'], assigns(:sources)
- assert_equal "50.06773, 14.37742", assigns(:query)
+ assert_equal ['osm_nominatim_reverse', 'geonames_reverse'], assigns(:sources)
+ assert_nil @controller.params[:query]
+ assert_in_delta 50.06773, @controller.params[:lat]
+ assert_in_delta 14.37742, @controller.params[:lon]
end
end
].each do |code|
post :search, :query => code
assert_response :success
- assert_equal ['latlon'], assigns(:sources)
- assert_equal "50.06773, -14.37742", assigns(:query)
+ assert_equal ['osm_nominatim_reverse', 'geonames_reverse'], assigns(:sources)
+ assert_nil @controller.params[:query]
+ assert_in_delta 50.06773, @controller.params[:lat]
+ assert_in_delta -14.37742, @controller.params[:lon]
end
end
].each do |code|
post :search, :query => code
assert_response :success
- assert_equal ['latlon'], assigns(:sources)
- assert_equal "-50.06773, 14.37742", assigns(:query)
+ assert_equal ['osm_nominatim_reverse', 'geonames_reverse'], assigns(:sources)
+ assert_nil @controller.params[:query]
+ assert_in_delta -50.06773, @controller.params[:lat]
+ assert_in_delta 14.37742, @controller.params[:lon]
end
end
].each do |code|
post :search, :query => code
assert_response :success
- assert_equal ['latlon'], assigns(:sources)
- assert_equal "-50.06773, -14.37742", assigns(:query)
+ assert_equal ['osm_nominatim_reverse', 'geonames_reverse'], assigns(:sources)
+ assert_nil @controller.params[:query]
+ assert_in_delta -50.06773, @controller.params[:lat]
+ assert_in_delta -14.37742, @controller.params[:lon]
end
end
assert_response :success
assert_equal ['osm_nominatim'], assigns(:sources)
end
-
-private
-
- ##
- # this is a test helper for rounding latlon strings to a specified precision, e.g., at a precision
- # of 5, "50.06773333333334, -14.377416666666667" will become "50.06773, -14.37742"
- def assert_latlon_equal_round(expected, actual, precision)
- assert_equal expected.split(',').map {|i| i.to_f.round(precision)}.join(', '), actual.split(',').map {|i| i.to_f.round(precision)}.join(', ')
- end
end