radiant-location-extension 1.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'http://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in ..gemspec
4
+ gemspec
data/README ADDED
@@ -0,0 +1,74 @@
1
+ = Location
2
+
3
+ == Introduction
4
+
5
+ Location is a plugin that will allow you to create relatively robust list of locations (stores, churches, etc.). This uses the Directory extension by Loren Johnson as a starting point but makes a number of different decisions. First it uses Geokit (http://geokit.rubyforge.org) to handle the heavy lifting. Second, the JavaScript is completely rewritten to use version 2 of the Google Maps API and to make some additional API changes (this is still TODO)
6
+
7
+ == Settings
8
+
9
+ You may enable or disable visible features for editing locations by setting these options in your environment using Radiant::Config or using the Settings extension:
10
+
11
+ Key Default Value Possible Values
12
+ =========================================================================
13
+ locations.use_groups? false true/false
14
+ locations.use_website_urls? false true/false
15
+ locations.use_page_paths? false true/false
16
+ locations.allow_manual_geocoding? false true/false
17
+
18
+ geokit.default_formula sphere sphere/flat
19
+ geokit.default_units miles miles/kms
20
+
21
+ geokit.geocoders.proxy_addr nil [IP Address or hostname of Proxy Server]
22
+ geokit.geocoders.proxy_port nil [Port of Proxy server]
23
+ geokit.geocoders.proxy_user nil [username for Proxy]
24
+ geokit.geocoders.proxy_pass nil [password for Proxy]
25
+ geokit.geocoders.timeout nil [number in seconds]
26
+ geokit.geocoders.yahoo nil [Yahoo Geocoder API Key]
27
+ geokit.geocoders.google [api code] [Google Maps API Key]
28
+ geokit.geocoders.geocoder_us false [Geocoder.us API Key]
29
+ geokit.geocoders.geocoder_ca false [Geocoder.ca API Key]
30
+ geokit.geocoders.provider_order 'google us' [space-separated list of geocoding services: google yahoo us ca ip]
31
+
32
+ == Geokit Modifications
33
+
34
+ I've made a few modifications to GeoKit to get it to work inside the extension and to maintain certain Radiant paradigms.
35
+
36
+ * Geokit is included as a library to the extension rather than as a plugin
37
+ * All references to the configuration values have been changed to use Radiant::Config
38
+
39
+ == Finding Results in space
40
+
41
+ To process search requests for locations you must create a Location Page. use <r:location> to find and return locations.
42
+
43
+ The parameters you can use to "find" locations are:
44
+
45
+ === start point
46
+
47
+ The start point is some point in space relative to which we will find locations. This allows a user to say "Find location near Main Street and First Street, My Town, BC, Canada".
48
+
49
+ When a start value is specified (using either *address* or *lat*&*lng*), then it will be always be used to calculate a distance to each returned location. If a distance is requested, we will return all the locations with that distance of the start point.
50
+
51
+ ==== *address*
52
+
53
+ If supplied, this will be an address that will be geocoded using the configured geocode providers. Once a latitude & longitude are calculated, they form the start point for the request.
54
+
55
+ ==== *lat* & *lng*
56
+
57
+ If both parameters are supplied, they are used as the start point. They always take precedence over *address*.
58
+
59
+ === *distance*
60
+
61
+ When specified, all the locations within this distance of the start point are returned. If no distance is specified, _all_ locations are returned
62
+
63
+ === *units*
64
+
65
+ The units are used for calculating distance from a location to the start point. The default value is "km"
66
+
67
+ === *count*
68
+
69
+ The number of results to return. Defaults to returning ALL results
70
+
71
+ === *offset*
72
+
73
+ The number of the first result to return. This allows you to build pagination into your code
74
+
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env rake
2
+ require 'bundler/gem_tasks'
3
+ require 'rdoc/task'
4
+
5
+ desc 'Generate documentation for the location extension.'
6
+ Rake::RDocTask.new(:rdoc) do |rdoc|
7
+ rdoc.rdoc_dir = 'rdoc'
8
+ rdoc.title = 'LocationExtension'
9
+ rdoc.options << '--line-numbers' << '--inline-source'
10
+ rdoc.rdoc_files.include('README')
11
+ rdoc.rdoc_files.include('lib/**/*.rb')
12
+ end
13
+
14
+ # Load any custom rakefiles for extension
15
+ Dir[File.dirname(__FILE__) + '/tasks/*.rake'].sort.each { |f| require f }
Binary file
Binary file
@@ -0,0 +1,3 @@
1
+ class Admin::LocationsController < Admin::ResourceController
2
+ model_class 'Location'
3
+ end
Binary file
@@ -0,0 +1,2 @@
1
+ module Admin::LocationHelper
2
+ end
@@ -0,0 +1,24 @@
1
+ class Location < ActiveRecord::Base
2
+ # Associations
3
+ belongs_to :created_by, :class_name => 'User'
4
+ belongs_to :updated_by, :class_name => 'User'
5
+
6
+ acts_as_mappable :default_units => :kms
7
+ before_validation :geocode_address
8
+
9
+ default_scope :order => 'name'
10
+
11
+ after_save :clear_page_cache
12
+ private
13
+ def geocode_address
14
+ unless self.manual_geocode
15
+ geo=GeoKit::Geocoders::MultiGeocoder.geocode self.full_address
16
+ errors.add(:full_address, "Could not Geocode address") if !geo.success
17
+ self.lat, self.lng = geo.lat,geo.lng if geo.success
18
+ end
19
+ end
20
+
21
+ def clear_page_cache
22
+ Radiant::Cache.clear
23
+ end
24
+ end
@@ -0,0 +1,105 @@
1
+ class LocationFinderPage < Page
2
+ include Radiant::Taggable
3
+ include GeoKit::Geocoders
4
+ description 'A page to show locations.'
5
+
6
+ desc %{
7
+ The root location element.
8
+
9
+ Retrieves locations based on the supplied parameters. Permitted parameters are:
10
+
11
+ * *origin* -- The address from which to start searching
12
+ * *lat* & *lng* -- The coordinates of the origin from which to start searching. These override the *origign* attribute
13
+ * *distance* -- Find all the locations within the supplied distance
14
+ * *units* -- The units to use for distance calculations (km or miles)
15
+ * *limit* -- Limits the number of locations to show
16
+ * *offset* -- The number of the first result (for pagination)
17
+
18
+ Attributes:
19
+ * *group* -- When supplied, it will show only those locations in the given group
20
+ }
21
+ tag "location" do |tag|
22
+ unless tag.attr["group"].blank?
23
+ @options[:conditions] = {:group => tag.attr['group']}
24
+ end
25
+
26
+ tag.locals.location = Location.find(:first, @options)
27
+ tag.expand if tag.locals.location
28
+ end
29
+
30
+ tag "location:if_distance" do |tag|
31
+ if tag.locals.location.respond_to?("distance")
32
+ tag.expand
33
+ end
34
+ end
35
+ tag "location:unless_distance" do |tag|
36
+ if !tag.locals.location.respond_to?("distance")
37
+ tag.expand
38
+ end
39
+ end
40
+ tag "location:distance" do |tag|
41
+
42
+ pre = tag.attr.include?('precision') ? tag.attr['precision'].to_i : 1
43
+
44
+ pre
45
+
46
+ # "%0.#{pre}f" % (tag.locals.location.distance || 0)
47
+
48
+ end
49
+
50
+ def process(request,response)
51
+ # Parameters
52
+ # origin = Address string (if lat and lng are defined they are used preferentially)
53
+ # lat = latitude of origin
54
+ # lng = longitude of origin
55
+ # distance = distance to search within
56
+ # units = the units to apply to the distance (km or miles)
57
+ # count = the number of results to return
58
+ # offset = The result number to start with
59
+
60
+ @origin = request.parameters["origin"]
61
+ @lat = request.parameters["lat"]
62
+ @lng = request.parameters["lng"]
63
+ @distance = request.parameters["distance"]
64
+ @units = request.parameters["units"]
65
+ @count = request.parameters["count"]
66
+ @offset = request.parameters["offset"]
67
+
68
+ if @lat.blank? || @lng.blank?
69
+ unless @origin.blank?
70
+ geocode = MultiGeocoder.geocode(@origin)
71
+ logger.debug("geocode: #{geocode}")
72
+ @origin_geo = geocode if geocode.success
73
+ else
74
+ @origin_geo = nil;
75
+ end
76
+ else
77
+ @origin_geo = [@lat.to_f, @lng.to_f]
78
+ end
79
+
80
+ @options = {}
81
+ unless @origin_geo.nil?
82
+ @options[:origin] = @origin_geo
83
+ @options[:order] = "distance"
84
+ end
85
+ unless @distance.blank?
86
+ @options[:within] = @distance
87
+ end
88
+ unless @units.blank?
89
+ @options[:units] = @units
90
+ end
91
+ unless @count.blank?
92
+ @options[:limit] = @count
93
+ end
94
+ unless @offset.blank?
95
+ @options[:offset] = @offset
96
+ end
97
+
98
+ super request, response
99
+ end
100
+
101
+ def cache?
102
+ false
103
+ end
104
+
105
+ end
@@ -0,0 +1,109 @@
1
+ module LocationsTags
2
+ include Radiant::Taggable
3
+ include GeoKit::Geocoders
4
+
5
+
6
+ desc %{
7
+ The root location element.
8
+
9
+ Retrieves locations based on the supplied parameters. Permitted parameters are:
10
+
11
+ * *limit* -- Limits the number of locations to show
12
+ * *offset* -- The number of the first result (for pagination)
13
+
14
+ Attributes:
15
+ * *group* -- When supplied, it will show only those locations in the given group
16
+ }
17
+ tag "locations" do |tag|
18
+ options = {}
19
+ unless tag.attr['limit'].blank?
20
+ options[:limit] = tag.attr['limit'].to_i.to_s
21
+ options[:offset] = tag.attr['offset']
22
+ end
23
+
24
+ unless tag.attr["group"].blank?
25
+ options[:conditions] = {:group => tag.attr['group']}
26
+ end
27
+
28
+ options = options.merge(@options)
29
+
30
+ tag.locals.locations = Location.find(:all, options)
31
+ tag.expand
32
+ end
33
+
34
+ desc %{
35
+ loops through each of the locations
36
+ }
37
+ tag "locations:each" do |tag|
38
+ st = tag.attr.include?('offset') ? tag.attr['offset'].to_i : 0
39
+ en = tag.attr.include?('length') ? tag.attr['length'].to_i - st : -1
40
+ each_location tag, st, en
41
+ end
42
+ tag "locations:first" do |tag|
43
+ tag.locals.locations.first
44
+ end
45
+ tag "locations:last" do |tag|
46
+ tag.locals.locations.last
47
+ end
48
+ tag "locations:count" do |tag|
49
+ tag.locals.locations.length
50
+ end
51
+ tag "locations:each:has_next?" do |tag|
52
+ (tag.locals.locations.length - tag.locals.location_index) > 1
53
+ end
54
+ tag "locations:each:index" do |tag|
55
+ tag.locals.location_index
56
+ end
57
+ tag "locations:each:location" do |tag|
58
+ tag.expand if tag.locals.location
59
+ end
60
+ tag "location" do |tag|
61
+ unless tag.attr["id"].blank?
62
+ tag.locals.location = Location.find(tag.attr["id"].to_i)
63
+ end
64
+ tag.expand if tag.locals.location
65
+ end
66
+
67
+ [:full_address, :group, :website_url, :name, :lat, :lng].each do |method|
68
+ desc %{ returns the #{method} attribute of the current Location}
69
+ tag("location:#{method.to_s}") do |tag|
70
+ tag.locals.location.send(method)
71
+ end
72
+ end
73
+
74
+ desc %{Allows you to use page tags (such as <r:slug>, <r:title>, etc.) for the page associated with the location.}
75
+ tag "location:page" do |tag|
76
+ if tag.locals.location.page_path?
77
+ tag.locals.page = Page.find_by_url tag.locals.location.page_path
78
+ tag.expand
79
+ end
80
+ end
81
+ tag "location:unless_page" do |tag|
82
+ unless Page.find_by_url tag.locals.location.page_path
83
+ tag.expand
84
+ end
85
+ end
86
+ tag "location:if_page" do |tag|
87
+ if Page.find_by_url tag.locals.location.page_path
88
+ tag.expand
89
+ end
90
+ end
91
+ # tag "location:map" do |tag|
92
+ # #content = '<script type="text/javascript" src="http://www.google.com/jsapi?key=#{Radiant::Config['geokit.geocoders.google']}"></script>'
93
+ #
94
+ # end
95
+
96
+ private
97
+ def each_location(tag, first=0, last=-1)
98
+ rng = Range.new first, last
99
+ offset = ((first < 0) ? tag.locals.location.length : 0) + first
100
+ result = []
101
+
102
+ tag.locals.locations[rng].each_with_index do |item, idx|
103
+ tag.locals.location_index = offset + idx
104
+ tag.locals.location = item
105
+ result << tag.expand
106
+ end
107
+ result
108
+ end
109
+ end
Binary file
Binary file
@@ -0,0 +1,11 @@
1
+ %tr.node.level-1
2
+ %td.location-title
3
+ = image("location", :class => "icon", :alt => 'page-icon', :title => '')
4
+ = link_to location.name , edit_admin_location_url(location)
5
+ %td.info
6
+ = h location.full_address
7
+
8
+ - if config['locations.use_groups?']
9
+ %td
10
+ = location.group
11
+ %td.remove= link_to 'Remove', remove_admin_location_path(location)
@@ -0,0 +1,59 @@
1
+ - include_stylesheet 'admin/location'
2
+
3
+ - render_region :main do |main|
4
+ - main.edit_header do
5
+ %h1 Edit Location
6
+ - main.edit_form do
7
+ - form_tag admin_location_path(@location), :method => :put do
8
+ = hidden_field 'location', 'lock_version'
9
+ = render_region :form_top
10
+ - render_region :form do |form|
11
+ - form.edit_title do
12
+ %p.title
13
+ %label{ :for => "location_name" } Name
14
+ = text_field "location", "name", :class => 'textbox', :maxlength => 100
15
+ - form.edit_full_address do
16
+ %p.address
17
+ %label{:for=>"location_full_address"} Full Address
18
+ = text_area "location", "full_address", :class => 'textbox', :size => '30x3'
19
+ %span.help Required. The address is used for determining the latitude and longitude for searching and showing on the map. the preferred format is: "123 1 Ave, MyCity, AB, Canada, T0M 0R0"
20
+ - form.edit_group do
21
+ - if config['locations.use_groups?']
22
+ %p.groups
23
+ %label.optional{:for=>"location_group"} Group
24
+ = text_field "location", "group", :class => 'textbox', :maxlength => 100
25
+ %span.help Optional. Assigning a group allows you to show and search locations within a specific group.
26
+ - form.edit_website_url do
27
+ - if config['locations.use_website_urls?']
28
+ %p.urls
29
+ %label.optional{:for=>"location_website_url"} Website URL
30
+ = text_field "location", "website_url", :class => 'textbox', :maxlength => 100
31
+ %span.help Optional.
32
+ - form.edit_page_path do
33
+ - if config['locations.use_page_paths?']
34
+ %p.page_path
35
+ %label.optional{:for=>"location_page_path"} Page path
36
+ = text_field "location", "page_path", :class => 'textbox', :maxlength => 100
37
+ %span.help Optional. Associate a page on your site with this location. Example: /locations/office
38
+ - form.edit_geocode do
39
+ - if config['locations.allow_manual_geocoding?']
40
+ %p.geocode
41
+ %label{:for=>"location_latitude"} Latitude
42
+ = text_field "location", "lat", :class => 'textbox', :maxlength => 100
43
+ %label{:for=>"location_longitude"} Longitude
44
+ = text_field "location", "lng", :class => 'textbox', :maxlength => 100
45
+ %label
46
+ = check_box "location", "manual_geocode"
47
+ Manually Geocode this Location
48
+ %span.help Auto-generated. Required if 'Manually Geocode this Location' is selected. The latitude and longitude are typically geocoded automatically. However some locations (particularly rural locations) cannot be easily geocoded. If you choose "manual geocoding" you will be able to set the latitude and longitude manually.
49
+
50
+ - render_region :form_bottom do |form_bottom|
51
+ - form_bottom.edit_timestamp do
52
+ = updated_stamp @location
53
+ - form_bottom.edit_buttons do
54
+ %p.buttons
55
+ = save_model_button(@location)
56
+ = save_model_and_continue_editing_button(@location)
57
+ or
58
+ = link_to "Cancel", admin_locations_url
59
+