More search improvements - a "Where am I?" link that does a reverse
authorTom Hughes <tom@compton.nu>
Fri, 24 Aug 2007 18:53:30 +0000 (18:53 +0000)
committerTom Hughes <tom@compton.nu>
Fri, 24 Aug 2007 18:53:30 +0000 (18:53 +0000)
search, and various cleanups to the previous changes.

app/controllers/geocoder_controller.rb
app/views/geocoder/_results.rhtml
app/views/site/_search.rhtml
app/views/site/index.rhtml
config/routes.rb
public/stylesheets/site.css

index f557668..6c4afeb 100644 (file)
@@ -21,15 +21,32 @@ class GeocoderController < ApplicationController
     results_count = count_results(results)
 
     render :update do |page|
+      page.replace_html :search_results_content, :partial => 'results', :object => results
+
       if results_count == 1
         position = results.collect { |s| s[:results] }.compact.flatten[0]
         page.call "setPosition", position[:lat], position[:lon], position[:zoom]
       else
-        page.replace_html :search_results_content, :partial => 'results', :object => results
         page.call "openSearchResults"
       end
     end
   end
+  
+  def description
+    results = Array.new
+
+    lat = params[:lat]
+    lon = params[:lon]
+
+    results.push description_osm_namefinder("cities", lat, lon, 2)
+    results.push description_osm_namefinder("towns", lat, lon, 4)
+    results.push description_osm_namefinder("places", lat, lon, 10)
+
+    render :update do |page|
+      page.replace_html :search_results_content, :partial => 'results', :object => results
+      page.call "openSearchResults"
+    end
+  end
 
 private
 
@@ -151,6 +168,34 @@ private
     return { :source => "GeoNames", :url => "http://www.geonames.org/", :error => "Error contacting ws.geonames.org: #{ex.to_s}" }
   end
 
+  def description_osm_namefinder(types, lat, lon, max)
+    results = Array.new
+
+    # ask OSM namefinder
+    response = fetch_xml("http://www.frankieandshadow.com/osm/search.xml?find=#{types}+near+#{lat},#{lon}&max=#{max}")
+
+    # parse the response
+    response.elements.each("searchresults/named") do |named|
+      lat = named.attributes["lat"].to_s
+      lon = named.attributes["lon"].to_s
+      zoom = named.attributes["zoom"].to_s
+      place = named.elements["place/named"] || named.elements["nearestplaces/named"]
+      type = named.attributes["info"].to_s
+      name = named.attributes["name"].to_s
+      description = named.elements["description"].to_s
+      distance = format_distance(place.attributes["approxdistance"].to_i)
+      direction = format_direction(360 - place.attributes["direction"].to_i)
+      prefix = "#{distance} #{direction} of #{type} "
+      results.push({:lat => lat, :lon => lon, :zoom => zoom,
+                    :prefix => prefix.capitalize, :name => name,
+                    :description => description})
+    end
+
+    return { :type => types.capitalize, :source => "OpenStreetMap Namefinder", :url => "http://www.frankieandshadow.com/osm/", :results => results }
+  rescue Exception => ex
+    return { :type => types.capitalize, :source => "OpenStreetMap Namefinder", :url => "http://www.frankieandshadow.com/osm/", :error => "Error contacting www.frankieandshadow.com: #{ex.to_s}" }
+  end
+
   def fetch_text(url)
     return Net::HTTP.get(URI.parse(url))
   end
index 477f2a0..9bcc5d8 100644 (file)
@@ -1,5 +1,6 @@
 <% results.each do |source| %>
-<p class="search_results_heading">Results from <%= link_to source[:source], source[:url] %></p>
+<% type = source[:type] || "Results" %>
+<p class="search_results_heading"><%= type %> from <%= link_to source[:source], source[:url] %></p>
 <% if source[:results] %>
 <% if source[:results].empty? %>
 <p class="search_results_entry">No results found</p>
index aa92942..14f8fa5 100644 (file)
@@ -12,6 +12,7 @@
 <script type="text/javascript">
 <!--
   function startSearch() {
+    $("search_results_content").innerHTML = "<p class='search_results_entry'>Searching...</p>";
     $("search_field").style.display = "none";
     $("search_active").style.display = "inline";
   }
     <%= onclose %>
   }
 
+  function describeLocation() {
+    var position = getPosition();
+
+    <%= remote_function(:loading => "startSearch()",
+                        :complete => "endSearch()",
+                        :url => { :controller => :geocoder, :action => :description },
+                        :with => "'lat=' + position.lat + '&lon=' + position.lon") %>
+  }
+
   <% if params[:query] %>
   <%= remote_function(:loading => "startSearch()",
                       :complete => "endSearch()",
@@ -42,6 +52,7 @@
 <% content_for "optionals" do %>
   <div class="optionalbox">
     <span class="oboxheader">Search</span>
+    <span class="whereami"><a href="javascript:describeLocation()">Where am I?</a></span>
     <div class="search_form">
     <span id="search_field">
     <% form_remote_tag(:loading => "startSearch()",
index 85adb7d..9f50880 100644 (file)
     handleResize();
   }
 
+  function getPosition() {
+    return mercatorToLonLat(map.getCenter());
+  }
+
   function setPosition(lat, lon, zoom) {
     var centre = lonLatToMercator(new OpenLayers.LonLat(lon, lat));
 
index 45a4d60..b9d5d41 100644 (file)
@@ -107,6 +107,7 @@ ActionController::Routing::Routes.draw do |map|
 
   # geocoder
   map.connect '/geocoder/search', :controller => 'geocoder', :action => 'search'
+  map.connect '/geocoder/description', :controller => 'geocoder', :action => 'description'
 
   # messages
 
index 4d02c1c..edaf46c 100644 (file)
@@ -338,8 +338,15 @@ hides rule from IE5-Mac \*/
 .oboxheader {
   font-size: 14px;
   font-weight: bold;
-  line-height: 1.4em;
-  text-align: top;
+  line-height: 22px;
+  vertical-align: bottom;
+}
+
+.whereami {
+  position: absolute;
+  right: 21px;
+  line-height: 22px;
+  vertical-align: bottom;
 }
 
 .optionalbox form {