require 'net/http'
require 'rexml/document'
- POSTCODE_ZOOM = 15
- GEONAMES_ZOOM = 12
+ before_filter :set_locale
def search
query = params[:query]
results = Array.new
- if query.match(/^\d{5}(-\d{4})?$/)
+ query.sub(/^\s+/, "")
+ query.sub(/\s+$/, "")
+
+ if query.match(/^[+-]?\d+(\.\d*)?\s*[\s,]\s*[+-]?\d+(\.\d*)?$/)
+ results.push search_latlon(query)
+ elsif query.match(/^\d{5}(-\d{4})?$/)
results.push search_us_postcode(query)
- 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 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)
results.push search_uk_postcode(query)
results.push search_osm_namefinder(query)
- elsif query.match(/[A-Z]\d[A-Z]\s*\d[A-Z]\d/i)
+ elsif query.match(/^[A-Z]\d[A-Z]\s*\d[A-Z]\d$/i)
results.push search_ca_postcode(query)
else
results.push search_osm_namefinder(query)
if results_count == 1
position = results.collect { |s| s[:results] }.compact.flatten[0]
- page.call "setPosition", position[:lat], position[:lon], position[:zoom]
+ page.call "setPosition", position[:lat].to_f, position[:lon].to_f, position[:zoom].to_i
else
page.call "openSidebar"
end
private
+ def search_latlon(query)
+ results = Array.new
+
+ # decode the location
+ if m = query.match(/^([+-]?\d+(\.\d*)?)\s*[\s,]\s*([+-]?\d+(\.\d*)?)$/)
+ lat = m[1].to_f
+ lon = m[3].to_f
+ end
+
+ # generate results
+ if lat < -90 or lat > 90
+ return { :source => "Internal", :url => "http://openstreetmap.org/", :error => "Latitude #{lat} out of range" }
+ elsif lon < -180 or lon > 180
+ return { :source => "Internal", :url => "http://openstreetmap.org/", :error => "Longitude #{lon} out of range" }
+ else
+ results.push({:lat => lat, :lon => lon,
+ :zoom => APP_CONFIG['postcode_zoom'],
+ :name => "#{lat}, #{lon}"})
+
+ return { :source => "Internal", :url => "http://openstreetmap.org/", :results => results }
+ end
+ end
+
def search_us_postcode(query)
results = Array.new
# parse the response
unless response.match(/couldn't find this zip/)
data = response.split(/\s*,\s+/) # lat,long,town,state,zip
- results.push({:lat => data[0], :lon => data[1], :zoom => POSTCODE_ZOOM,
+ results.push({:lat => data[0], :lon => data[1],
+ :zoom => APP_CONFIG['postcode_zoom'],
:prefix => "#{data[2]}, #{data[3]}, ",
:name => data[4]})
end
dataline = response.split(/\n/)[1]
data = dataline.split(/,/) # easting,northing,postcode,lat,long
postcode = data[2].gsub(/'/, "")
- zoom = POSTCODE_ZOOM - postcode.count("#")
+ zoom = APP_CONFIG['postcode_zoom'] - postcode.count("#")
results.push({:lat => data[3], :lon => data[4], :zoom => zoom,
:name => postcode})
end
response = fetch_xml("http://geocoder.ca/?geoit=XML&postal=#{escape_query(query)}")
# parse the response
- unless response.get_elements("geodata/error")
+ if response.get_elements("geodata/error").empty?
results.push({:lat => response.get_text("geodata/latt").to_s,
:lon => response.get_text("geodata/longt").to_s,
- :zoom => POSTCODE_ZOOM,
+ :zoom => APP_CONFIG['postcode_zoom'],
:name => query.upcase})
end
prefix = ""
name = type
else
- prefix = "#{type} "
+ prefix = t "geocoder.results.namefinder.prefix", :type => type
end
if place
distance = format_distance(place.attributes["approxdistance"].to_i)
direction = format_direction(place.attributes["direction"].to_i)
placename = format_name(place.attributes["name"].to_s)
- suffix = ", #{distance} #{direction} of #{placename}"
+ suffix = t "geocoder.results.namefinder.suffix_place", :distance => distance, :direction => direction, :placename => placename
if place.attributes["rank"].to_i <= 30
parent = nil
parentname = format_name(parent.attributes["name"].to_s)
if place.attributes["info"].to_s == "suburb"
- suffix = "#{suffix}, #{parentname}"
+ suffix = t "geocoder.results.namefinder.suffix_suburb", :suffix => suffix, :parentname => parentname
else
parentdistance = format_distance(parent.attributes["approxdistance"].to_i)
parentdirection = format_direction(parent.attributes["direction"].to_i)
- suffix = "#{suffix} (#{parentdistance} #{parentdirection} of #{parentname})"
+ suffix = t "geocoder.results.namefinder.suffix_parent", :suffix => suffix, :parentdistance => parentdistance, :parentdirection => parentdirection, :parentname => parentname
end
end
end
lon = geoname.get_text("lng").to_s
name = geoname.get_text("name").to_s
country = geoname.get_text("countryName").to_s
- results.push({:lat => lat, :lon => lon, :zoom => GEONAMES_ZOOM,
+ results.push({:lat => lat, :lon => lon,
+ :zoom => APP_CONFIG['geonames_zoom'],
:name => name,
:suffix => ", #{country}"})
end
end
def format_distance(distance)
- return "less than 1km" if distance == 0
- return "about #{distance}km"
+ return t "geocoder.results.distance.less_than_1km" if distance == 0
+ return t "geocoder.results.distance.about_distance_km", :distance => distance
end
def format_direction(bearing)
- return "south-west" if bearing >= 22.5 and bearing < 67.5
- return "south" if bearing >= 67.5 and bearing < 112.5
- return "south-east" if bearing >= 112.5 and bearing < 157.5
- return "east" if bearing >= 157.5 and bearing < 202.5
- return "north-east" if bearing >= 202.5 and bearing < 247.5
- return "north" if bearing >= 247.5 and bearing < 292.5
- return "north-west" if bearing >= 292.5 and bearing < 337.5
- return "west"
+ return t "geocoder.results.direction.south_west" if bearing >= 22.5 and bearing < 67.5
+ return t "geocoder.results.direction.south" if bearing >= 67.5 and bearing < 112.5
+ return t "geocoder.results.direction.south_east" if bearing >= 112.5 and bearing < 157.5
+ return t "geocoder.results.direction.east" if bearing >= 157.5 and bearing < 202.5
+ return t "geocoder.results.direction.north_east" if bearing >= 202.5 and bearing < 247.5
+ return t "geocoder.results.direction.north" if bearing >= 247.5 and bearing < 292.5
+ return t "geocoder.results.direction.north_west" if bearing >= 292.5 and bearing < 337.5
+ return t "geocoder.results.direction.west"
end
def format_name(name)