refinerycms-map 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,5 @@
1
+ class Admin::MapLocationsController < Admin::BaseController
2
+
3
+ crudify :map_location, :order => "state, city"
4
+
5
+ end
@@ -0,0 +1,25 @@
1
+ class MapLocationsController < ApplicationController
2
+
3
+ before_filter :find_locations, :find_page
4
+ before_filter :find_location, :only => [:show]
5
+
6
+ protected
7
+
8
+ def find_locations
9
+ if params[:q]
10
+ coords = Geocode.find_address(params[:q])
11
+ @map_locations = MapLocation.nearest_to(coords.latitude, coords.longitude, 50)
12
+ else
13
+ @map_locations = MapLocation.all
14
+ end
15
+ end
16
+
17
+ def find_location
18
+ @map_location = MapLocation.find(params[:id])
19
+ end
20
+
21
+ def find_page
22
+ @page = Page.find_by_link_url("/map")
23
+ end
24
+
25
+ end
@@ -0,0 +1,59 @@
1
+ class MapLocation < ActiveRecord::Base
2
+
3
+ validates_presence_of :title, :address, :city, :state, :zipcode
4
+
5
+ has_friendly_id :title, :use_slug => true
6
+
7
+ acts_as_indexed :fields => [:title, :address, :city, :state, :zipcode]
8
+
9
+ default_scope :order => "state, city, title"
10
+
11
+ before_save :set_lat_and_lng
12
+
13
+ # for will_paginate
14
+ def self.per_page
15
+ 20
16
+ end
17
+
18
+ ##
19
+ # Returns a scope which queries for the nearest locations to the requested
20
+ # coordinates (latitude and longitude in decimal format).
21
+ #
22
+ # This method uses a variation of the Haversine Formula. Conversions have
23
+ # already been made to radians and the Earth's radius (3956mi) has already
24
+ # been baked in. The variation arises where the distance is not calculated
25
+ # against every instance in the database, instead a rough box is drawn
26
+ # around the source point that encapsulates the desired radius. Only those
27
+ # objects within the box are calculated for distance.
28
+ #
29
+ def self.nearest_to(latitude, longitude, radius = 100)
30
+ latitude_delta = radius.to_f / 69.0
31
+ longitude_delta = radius.to_f / (Math.cos(latitude) * 69.0).abs
32
+ scoped({
33
+ :select => "*, 7912 * ASIN(SQRT(POWER(SIN((#{latitude} - lat) * 0.00872664626), 2) + COS(#{latitude} * 0.0174532925) * COS(#{latitude} * 0.0174532925) * POWER(SIN((#{longitude} - lng) * 0.00872664626), 2))) as distance_from_source",
34
+ :order => 'distance_from_source ASC',
35
+ :conditions => "lat BETWEEN #{latitude - latitude_delta} AND #{latitude + latitude_delta} AND lng BETWEEN #{longitude - longitude_delta} AND #{longitude + longitude_delta}"
36
+ })
37
+ end
38
+
39
+ def full_address
40
+ "%s, %s, %s %s" % [self.address, self.city, self.state, self.zipcode]
41
+ end
42
+
43
+
44
+ private
45
+
46
+
47
+ def set_lat_and_lng
48
+ if address_changed? || city_changed? || state_changed? || zipcode_changed?
49
+ Geocode.find_address(self.full_address).tap do |coordinate|
50
+ self.lat = coordinate.latitude
51
+ self.lng = coordinate.longitude
52
+ end
53
+ end
54
+ end
55
+
56
+ def lat=(input); write_attribute(:lat, input); end
57
+ def lng=(input); write_attribute(:lng, input); end
58
+
59
+ end
@@ -0,0 +1,54 @@
1
+ <% form_for [:admin, @map_location] do |f| %>
2
+ <%= f.error_messages %>
3
+
4
+ <div class='hemisquare'>
5
+ <div class='field'>
6
+ <%= f.label :title %>
7
+ <%= f.text_field :title, :class => "larger widest" %>
8
+ </div>
9
+
10
+ <div class='field'>
11
+ <%= f.label :address %>
12
+ <%= f.text_field :address %>
13
+ </div>
14
+
15
+ <div class='field'>
16
+ <%= f.label :city %>
17
+ <%= f.text_field :city %>
18
+ </div>
19
+
20
+ <div class='field'>
21
+ <%= f.label :state %>
22
+ <%= f.text_field :state %>
23
+ </div>
24
+
25
+ <div class='field'>
26
+ <%= f.label :zipcode %>
27
+ <%= f.text_field :zipcode %>
28
+ </div>
29
+
30
+ <div class='field'>
31
+ <%= f.label :phone %>
32
+ <%= f.text_field :phone %>
33
+ </div>
34
+
35
+ <div class='field'>
36
+ <%= f.label :url %>
37
+ <%= f.text_field :url %>
38
+ </div>
39
+ </div>
40
+
41
+ <div class='hemisquare right_side'>
42
+ <br/><br/><br/><br/><br/><br/><br/>
43
+ <%= image_tag "http://maps.google.com/maps/api/staticmap?size=400x400&markers=#{@map_location.full_address.parameterize('+')}&zoom=14&sensor=false", :class => "location_map" %>
44
+ </div>
45
+
46
+ <div class='clearfix'></div>
47
+
48
+ <%= render :partial => "/shared/admin/form_actions",
49
+ :locals => {
50
+ :f => f,
51
+ :continue_editing => false
52
+ } %>
53
+
54
+ <% end %>
@@ -0,0 +1,16 @@
1
+ <li class='clearfix record <%= cycle("on", "on-hover") %>'>
2
+ <span class='title'>
3
+ <%=h map_location.title %>
4
+ <span class="preview"><%=h map_location.full_address %></span>
5
+ </span>
6
+ <span class='actions'>
7
+ <%= link_to refinery_icon_tag('application_go.png'), map_location_url(map_location),
8
+ :title => t('.view_live'),
9
+ :target => "_blank" %>
10
+ <%= link_to refinery_icon_tag('application_edit.png'), edit_admin_map_location_path(map_location),
11
+ :title => t('.edit') %>
12
+ <%= link_to refinery_icon_tag('delete.png'), admin_map_location_path(map_location),
13
+ :class => "cancel confirm-delete",
14
+ :title => t('.delete') %>
15
+ </span>
16
+ </li>
@@ -0,0 +1 @@
1
+ <%= render :partial => "form" %>
@@ -0,0 +1,28 @@
1
+ <div id='actions'>
2
+ <ul>
3
+ <li>
4
+ <%= render :partial => "/shared/admin/search", :locals => {:url => admin_map_locations_url} %>
5
+ </li>
6
+ <li>
7
+ <%= link_to t('.create'), new_admin_map_location_url, :class => "add_icon" %>
8
+ </li>
9
+ </ul>
10
+ </div>
11
+ <div id='records'>
12
+ <%= "<h2>#{t('admin.search_results_for', :query => params[:search])}</h2>" if searching? %>
13
+ <% if @map_locations.any? %>
14
+ <%= will_paginate @map_locations, :previous_label => '&laquo;', :next_label => '&raquo;' %>
15
+ <ul>
16
+ <%= render :partial => "map_location", :collection => @map_locations %>
17
+ </ul>
18
+ <%= will_paginate @map_locations, :previous_label => '&laquo;', :next_label => '&raquo;' %>
19
+ <% else %>
20
+ <% unless searching? %>
21
+ <p>
22
+ <strong><%= t('.no_items_yet') %></strong>
23
+ </p>
24
+ <% else %>
25
+ <p><%= t('admin.search_no_results') %></p>
26
+ <% end %>
27
+ <% end %>
28
+ </div>
@@ -0,0 +1 @@
1
+ <%= render :partial => "form" %>
@@ -0,0 +1,10 @@
1
+ <% content_for :body_content_left do %>
2
+ <%= @page[:body] if @map_locations.empty? %>
3
+ <%= render :partial => 'map', :locals => {:width => 500, :height => 500} %>
4
+ <% end %>
5
+
6
+ <% content_for :body_content_right do %>
7
+ <%= render :partial => 'locations' %>
8
+ <% end %>
9
+
10
+ <%= render :partial => "/shared/content_page" %>
@@ -0,0 +1,9 @@
1
+ <% content_for :body_content_title, "<h1>#{@map_location.title}</h1>" %>
2
+ <% content_for :body_content_left do %>
3
+ <h2>Map Goes Here</h2>
4
+ <% end %>
5
+ <% content_for :body_content_right do %>
6
+ <h3>Location Details Go Here</h3>
7
+ <% end %>
8
+
9
+ <%= render :partial => "/shared/content_page" %>
@@ -0,0 +1,31 @@
1
+ en:
2
+ plugins:
3
+ map:
4
+ title: Map
5
+ admin:
6
+ map_locations:
7
+ map_location:
8
+ view_live: "View this location live on the map<br/><em>(opens in a new window)</em>"
9
+ edit: "Edit this location"
10
+ delete: "Remove this location forever"
11
+ index:
12
+ actions: Actions
13
+ create: "Create Location"
14
+ news_item: Location
15
+ no_items: "Sorry, no results found."
16
+ no_items_yet: 'There are no locations yet. Click "Create Location" to add one.'
17
+ map_locations:
18
+ show:
19
+ back_to_index: "Back to the map"
20
+ activerecord:
21
+ attributes:
22
+ map_location:
23
+ title: Title
24
+ address: Address
25
+ city: City
26
+ state: State
27
+ zipcode: Zip Code
28
+ phone: Phone Number
29
+ url: Url
30
+ models:
31
+ map_location: Location
data/config/routes.rb ADDED
@@ -0,0 +1,7 @@
1
+ ActionController::Routing::Routes.draw do |map|
2
+ map.resources :map_locations, :as => :map
3
+
4
+ map.namespace(:admin, :path_prefix => (defined?(REFINERY_GEM_VERSION) ? 'admin' : 'refinery')) do |admin|
5
+ admin.resources :map_locations, :as => :map
6
+ end
7
+ end
@@ -0,0 +1,37 @@
1
+ class MapGenerator < Rails::Generator::NamedBase
2
+
3
+ def initialize(*runtime_args)
4
+ # set first argument to the table's name so that the user doesn't have to pass it in.
5
+ runtime_args[0] = ["map_locations"]
6
+ super(*runtime_args)
7
+ end
8
+
9
+ def banner
10
+ "Usage: script/generate map"
11
+ end
12
+
13
+ def manifest
14
+ record do |m|
15
+ m.migration_template 'migration.rb', 'db/migrate',
16
+ :migration_file_name => "create_structure_for_map",
17
+ :assigns => {
18
+ :migration_name => "CreateStructureForMap",
19
+ :table_name => "map_locations",
20
+ :attributes => [
21
+ Rails::Generator::GeneratedAttribute.new("title", "string"),
22
+ Rails::Generator::GeneratedAttribute.new("address", "string"),
23
+ Rails::Generator::GeneratedAttribute.new("city", "string"),
24
+ Rails::Generator::GeneratedAttribute.new("state", "string"),
25
+ Rails::Generator::GeneratedAttribute.new("zipcode", "string"),
26
+ Rails::Generator::GeneratedAttribute.new("phone", "string"),
27
+ Rails::Generator::GeneratedAttribute.new("url", "string"),
28
+ ]
29
+ }
30
+ m.file "jquery.jmapping.min.js", "public/javascripts/jquery.jmapping.min.js"
31
+ m.file "jquery.metadata.js", "public/javascripts/jquery.metadata.js"
32
+ m.file "mapiconmaker.js", "public/javascripts/mapiconmaker.js"
33
+ m.file "markermanager.js", "public/javascripts/markermanager.js"
34
+ end
35
+ end
36
+
37
+ end if defined?(Rails::Generator::NamedBase)
@@ -0,0 +1,20 @@
1
+ /*
2
+ * jMapping v1.4.0 - jQuery plugin for creating Google Maps
3
+ *
4
+ * Copyright (c) 2009-2010 Brian Landau (Viget Labs)
5
+ * MIT License: http://www.opensource.org/licenses/mit-license.php
6
+ *
7
+ */
8
+ if(GMap2){GMap2.prototype.centerAndZoomOnBounds=function(bounds){this.setCenter(bounds.getCenter(),this.getBoundsZoomLevel(bounds));};}
9
+ (function($){$.jMapping=function(map_elm,options){var settings,gmarkers,mapped,map,markerManager,places,bounds,jMapper;map_elm=(typeof map_elm=="string")?$(map_elm).get(0):map_elm;if(!($(map_elm).data('jMapping'))){settings=$.extend(true,{},$.jMapping.defaults);$.extend(true,settings,options);gmarkers={};var init=function(doUpdate){var info_window_selector,min_zoom,bounds_zoom_level;info_window_selector=[settings.side_bar_selector,settings.location_selector,settings.info_window_selector].join(' ');$(info_window_selector).hide();places=getPlaces();bounds=getBounds(doUpdate);if(doUpdate){gmarkers={};markerManager.clearMarkers();map.checkResize();map.centerAndZoomOnBounds(bounds);}else{map=createMap();markerManager=new MarkerManager(map);}
10
+ places.each(function(){var marker=createMarker(this);if(!(settings.link_selector===false)){setupLink(this);}
11
+ $(document).trigger('markerCreated.jMapping',[marker]);});bounds_zoom_level=map.getBoundsZoomLevel(bounds);min_zoom=(bounds_zoom_level<7)?0:(bounds_zoom_level-7);markerManager.addMarkers(gmarkersArray(),min_zoom);markerManager.refresh();if(!(settings.link_selector===false)&&!doUpdate){attachMapsEventToLinks();}};var createMap=function(){map=new GMap2(map_elm);if($.isFunction(settings.map_config)){settings.map_config(map);}else{map.setMapType(G_NORMAL_MAP);map.addControl(new GSmallMapControl());}
12
+ map.centerAndZoomOnBounds(bounds);if(typeof settings.default_zoom_level=="number"){map.setZoom(settings.default_zoom_level);}
13
+ return map;};var getPlaces=function(){return $(settings.side_bar_selector+' '+settings.location_selector);};var getPlacesData=function(doUpdate){return places.map(function(){if(doUpdate){$(this).data('metadata',false);}
14
+ return $(this).metadata(settings.metadata_options);});};var getBounds=function(doUpdate){var places_data=getPlacesData(doUpdate);var newBounds=new GLatLngBounds($.jMapping.makeGLatLng(places_data[0].point),$.jMapping.makeGLatLng(places_data[0].point));for(var i=1,len=places_data.length;i<len;i++){newBounds.extend($.jMapping.makeGLatLng(places_data[i].point));}
15
+ return newBounds;};var setupLink=function(place_elm){var $place_elm=$(place_elm),location_data=$place_elm.metadata(settings.metadata_options),link=$place_elm.find(settings.link_selector);link.attr('href',("#"+location_data.id));};var chooseIconOptions=function(category){if(settings.category_icon_options){if($.isFunction(settings.category_icon_options)){return settings.category_icon_options(category);}else{return settings.category_icon_options[category]||settings.category_icon_options['default'];}}else{return{};}};var createMarker=function(place_elm){var $place_elm=$(place_elm),place_data,point,marker,$info_window_elm,custom_icon,icon_options;place_data=$place_elm.metadata(settings.metadata_options);point=$.jMapping.makeGLatLng(place_data.point);if(settings.category_icon_options){icon_options=chooseIconOptions(place_data.category);if(typeof icon_options==="string"){custom_icon=new GIcon(G_DEFAULT_ICON,icon_options);}else if(icon_options instanceof GIcon){custom_icon=icon_options;}else{if(!icon_options.style)icon_options.style='Marker';custom_icon=MapIconMaker['create'+icon_options.style+'Icon'](icon_options);}
16
+ marker=new GMarker(point,{icon:custom_icon});}else{marker=new GMarker(point);}
17
+ $info_window_elm=$place_elm.find(settings.info_window_selector);if($info_window_elm.length>0){marker.bindInfoWindowHtml($info_window_elm.html(),{maxWidth:settings.info_window_max_width});}
18
+ gmarkers[parseInt(place_data.id,10)]=marker;return marker;};var attachMapsEventToLinks=function(){var location_link_selector=[settings.side_bar_selector,settings.location_selector,settings.link_selector].join(' ');$(location_link_selector).live('click',function(e){e.preventDefault();var marker_index=parseInt($(this).attr('href').split('#')[1],10);GEvent.trigger(gmarkers[marker_index],"click");});};var gmarkersArray=function(){var marker_arr=[];$.each(gmarkers,function(key,value){marker_arr.push(value);});return marker_arr;};if(GBrowserIsCompatible()){if($(document).trigger('beforeMapping.jMapping',[settings])!=false){init();mapped=true;}else{mapped=false;}
19
+ jMapper={gmarkers:gmarkers,settings:settings,mapped:mapped,map:map,markerManager:markerManager,gmarkersArray:gmarkersArray,getBounds:getBounds,getPlacesData:getPlacesData,getPlaces:getPlaces,update:function(){if($(document).trigger('beforeUpdate.jMapping',[this])!=false){init(true);this.map=map;this.gmarkers=gmarkers;this.markerManager=markerManager;$(document).trigger('afterUpdate.jMapping',[this]);}}};$(document).trigger('afterMapping.jMapping',[jMapper]);return jMapper;}else{mapped=false;return null;}}else{return $(map_elm).data('jMapping');}};$.extend($.jMapping,{defaults:{side_bar_selector:'#map-side-bar:first',location_selector:'.map-location',link_selector:'a.map-link',info_window_selector:'.info-box',info_window_max_width:425,metadata_options:{type:'attr',name:'data-jmapping'}},makeGLatLng:function(place_point){return new GLatLng(place_point.lat,place_point.lng);}});$.fn.jMapping=function(options){if((options=='update')&&$(this[0]).data('jMapping')){$(this[0]).data('jMapping').update();}else{if(options=='update')options={};$(this[0]).data('jMapping',$.jMapping(this[0],options));}
20
+ return this;};})(jQuery);
@@ -0,0 +1,148 @@
1
+ /*
2
+ * Metadata - jQuery plugin for parsing metadata from elements
3
+ *
4
+ * Copyright (c) 2006 John Resig, Yehuda Katz, J�örn Zaefferer, Paul McLanahan
5
+ *
6
+ * Dual licensed under the MIT and GPL licenses:
7
+ * http://www.opensource.org/licenses/mit-license.php
8
+ * http://www.gnu.org/licenses/gpl.html
9
+ *
10
+ * Revision: $Id: jquery.metadata.js 3640 2007-10-11 18:34:38Z pmclanahan $
11
+ *
12
+ */
13
+
14
+ /**
15
+ * Sets the type of metadata to use. Metadata is encoded in JSON, and each property
16
+ * in the JSON will become a property of the element itself.
17
+ *
18
+ * There are four supported types of metadata storage:
19
+ *
20
+ * attr: Inside an attribute. The name parameter indicates *which* attribute.
21
+ *
22
+ * class: Inside the class attribute, wrapped in curly braces: { }
23
+ *
24
+ * elem: Inside a child element (e.g. a script tag). The
25
+ * name parameter indicates *which* element.
26
+ * html5: Values are stored in data-* attributes.
27
+ *
28
+ * The metadata for an element is loaded the first time the element is accessed via jQuery.
29
+ *
30
+ * As a result, you can define the metadata type, use $(expr) to load the metadata into the elements
31
+ * matched by expr, then redefine the metadata type and run another $(expr) for other elements.
32
+ *
33
+ * @name $.metadata.setType
34
+ *
35
+ * @example <p id="one" class="some_class {item_id: 1, item_label: 'Label'}">This is a p</p>
36
+ * @before $.metadata.setType("class")
37
+ * @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label"
38
+ * @desc Reads metadata from the class attribute
39
+ *
40
+ * @example <p id="one" class="some_class" data="{item_id: 1, item_label: 'Label'}">This is a p</p>
41
+ * @before $.metadata.setType("attr", "data")
42
+ * @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label"
43
+ * @desc Reads metadata from a "data" attribute
44
+ *
45
+ * @example <p id="one" class="some_class"><script>{item_id: 1, item_label: 'Label'}</script>This is a p</p>
46
+ * @before $.metadata.setType("elem", "script")
47
+ * @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label"
48
+ * @desc Reads metadata from a nested script element
49
+ *
50
+ * @example <p id="one" class="some_class" data-item_id="1" data-item_label="Label">This is a p</p>
51
+ * @before $.metadata.setType("html5")
52
+ * @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label"
53
+ * @desc Reads metadata from a series of data-* attributes
54
+ *
55
+ * @param String type The encoding type
56
+ * @param String name The name of the attribute to be used to get metadata (optional)
57
+ * @cat Plugins/Metadata
58
+ * @descr Sets the type of encoding to be used when loading metadata for the first time
59
+ * @type undefined
60
+ * @see metadata()
61
+ */
62
+
63
+ (function($) {
64
+
65
+ $.extend({
66
+ metadata : {
67
+ defaults : {
68
+ type: 'class',
69
+ name: 'metadata',
70
+ cre: /({.*})/,
71
+ single: 'metadata'
72
+ },
73
+ setType: function( type, name ){
74
+ this.defaults.type = type;
75
+ this.defaults.name = name;
76
+ },
77
+ get: function( elem, opts ){
78
+ var settings = $.extend({},this.defaults,opts);
79
+ // check for empty string in single property
80
+ if ( !settings.single.length ) settings.single = 'metadata';
81
+
82
+ var data = $.data(elem, settings.single);
83
+ // returned cached data if it already exists
84
+ if ( data ) return data;
85
+
86
+ data = "{}";
87
+
88
+ var getData = function(data) {
89
+ if(typeof data != "string") return data;
90
+
91
+ if( data.indexOf('{') < 0 ) {
92
+ data = eval("(" + data + ")");
93
+ }
94
+ }
95
+
96
+ var getObject = function(data) {
97
+ if(typeof data != "string") return data;
98
+
99
+ data = eval("(" + data + ")");
100
+ return data;
101
+ }
102
+
103
+ if ( settings.type == "html5" ) {
104
+ var object = {};
105
+ $( elem.attributes ).each(function() {
106
+ var name = this.nodeName;
107
+ if(name.match(/^data-/)) name = name.replace(/^data-/, '');
108
+ else return true;
109
+ object[name] = getObject(this.nodeValue);
110
+ });
111
+ } else {
112
+ if ( settings.type == "class" ) {
113
+ var m = settings.cre.exec( elem.className );
114
+ if ( m )
115
+ data = m[1];
116
+ } else if ( settings.type == "elem" ) {
117
+ if( !elem.getElementsByTagName ) return;
118
+ var e = elem.getElementsByTagName(settings.name);
119
+ if ( e.length )
120
+ data = $.trim(e[0].innerHTML);
121
+ } else if ( elem.getAttribute != undefined ) {
122
+ var attr = elem.getAttribute( settings.name );
123
+ if ( attr )
124
+ data = attr;
125
+ }
126
+ object = getObject(data.indexOf("{") < 0 ? "{" + data + "}" : data);
127
+ }
128
+
129
+ $.data( elem, settings.single, object );
130
+ return object;
131
+ }
132
+ }
133
+ });
134
+
135
+ /**
136
+ * Returns the metadata object for the first member of the jQuery object.
137
+ *
138
+ * @name metadata
139
+ * @descr Returns element's metadata object
140
+ * @param Object opts An object contianing settings to override the defaults
141
+ * @type jQuery
142
+ * @cat Plugins/Metadata
143
+ */
144
+ $.fn.metadata = function( opts ){
145
+ return $.metadata.get( this[0], opts );
146
+ };
147
+
148
+ })(jQuery);
@@ -0,0 +1,227 @@
1
+ /**
2
+ * @name MapIconMaker
3
+ * @version 1.1
4
+ * @author Pamela Fox
5
+ * @copyright (c) 2008 Pamela Fox
6
+ * @homepage http://gmaps-utility-library.googlecode.com/svn/trunk/mapiconmaker
7
+ * @fileoverview This gives you static functions for creating dynamically
8
+ * sized and colored marker icons using the Charts API marker output.
9
+ */
10
+
11
+ /*
12
+ * Licensed under the Apache License, Version 2.0 (the "License");
13
+ * you may not use this file except in compliance with the License.
14
+ * You may obtain a copy of the License at
15
+ *
16
+ * http://www.apache.org/licenses/LICENSE-2.0
17
+ *
18
+ * Unless required by applicable law or agreed to in writing, software
19
+ * distributed under the License is distributed on an "AS IS" BASIS,
20
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21
+ * See the License for the specific language governing permissions and
22
+ * limitations under the License.
23
+ */
24
+
25
+ /**
26
+ * @name MarkerIconOptions
27
+ * @class This class represents optional arguments to {@link createMarkerIcon},
28
+ * {@link createFlatIcon}, or {@link createLabeledMarkerIcon}. Each of the
29
+ * functions use a subset of these arguments. See the function descriptions
30
+ * for the list of supported options.
31
+ * @property {Number} [width=32] Specifies, in pixels, the width of the icon.
32
+ * The width may include some blank space on the side, depending on the
33
+ * height of the icon, as the icon will scale its shape proportionately.
34
+ * @property {Number} [height=32] Specifies, in pixels, the height of the icon.
35
+ * @property {String} [primaryColor="#ff0000"] Specifies, as a hexadecimal
36
+ * string, the color used for the majority of the icon body.
37
+ * @property {String} [cornerColor="#ffffff"] Specifies, as a hexadecimal
38
+ * string, the color used for the top corner of the icon. If you'd like the
39
+ * icon to have a consistent color, make the this the same as the
40
+ * {@link primaryColor}.
41
+ * @property {String} [strokeColor="#000000"] Specifies, as a hexadecimal
42
+ * string, the color used for the outside line (stroke) of the icon.
43
+ * @property {String} [shadowColor="#000000"] Specifies, as a hexadecimal
44
+ * string, the color used for the shadow of the icon.
45
+ * @property {String} [label=""] Specifies a character or string to display
46
+ * inside the body of the icon. Generally, one or two characters looks best.
47
+ * @property {String} [labelColor="#000000"] Specifies, as a hexadecimal
48
+ * string, the color used for the label text.
49
+ * @property {Number} [labelSize=0] Specifies, in pixels, the size of the label
50
+ * text. If set to 0, the text auto-sizes to fit the icon body.
51
+ * @property {String} [shape="circle"] Specifies shape of the icon. Current
52
+ * options are "circle" for a circle or "roundrect" for a rounded rectangle.
53
+ * @property {Boolean} [addStar = false] Specifies whether to add a star to the
54
+ * edge of the icon.
55
+ * @property {String} [starPrimaryColor="#FFFF00"] Specifies, as a hexadecimal
56
+ * string, the color used for the star body.
57
+ * @property {String} [starStrokeColor="#0000FF"] Specifies, as a hexadecimal
58
+ * string, the color used for the outside line (stroke) of the star.
59
+ */
60
+
61
+ /**
62
+ * This namespace contains functions that you can use to easily create
63
+ * dynamically sized, colored, and labeled icons.
64
+ * @namespace
65
+ */
66
+ var MapIconMaker = {};
67
+
68
+ /**
69
+ * Creates an icon based on the specified options in the
70
+ * {@link MarkerIconOptions} argument.
71
+ * Supported options are: width, height, primaryColor,
72
+ * strokeColor, and cornerColor.
73
+ * @param {MarkerIconOptions} [opts]
74
+ * @return {GIcon}
75
+ */
76
+ MapIconMaker.createMarkerIcon = function (opts) {
77
+ var width = opts.width || 32;
78
+ var height = opts.height || 32;
79
+ var primaryColor = opts.primaryColor || "#ff0000";
80
+ var strokeColor = opts.strokeColor || "#000000";
81
+ var cornerColor = opts.cornerColor || "#ffffff";
82
+
83
+ var baseUrl = "http://chart.apis.google.com/chart?cht=mm";
84
+ var iconUrl = baseUrl + "&chs=" + width + "x" + height +
85
+ "&chco=" + cornerColor.replace("#", "") + "," +
86
+ primaryColor.replace("#", "") + "," +
87
+ strokeColor.replace("#", "") + "&ext=.png";
88
+ var icon = new GIcon(G_DEFAULT_ICON);
89
+ icon.image = iconUrl;
90
+ icon.iconSize = new GSize(width, height);
91
+ icon.shadowSize = new GSize(Math.floor(width * 1.6), height);
92
+ icon.iconAnchor = new GPoint(width / 2, height);
93
+ icon.infoWindowAnchor = new GPoint(width / 2, Math.floor(height / 12));
94
+ icon.printImage = iconUrl + "&chof=gif";
95
+ icon.mozPrintImage = iconUrl + "&chf=bg,s,ECECD8" + "&chof=gif";
96
+ iconUrl = baseUrl + "&chs=" + width + "x" + height +
97
+ "&chco=" + cornerColor.replace("#", "") + "," +
98
+ primaryColor.replace("#", "") + "," +
99
+ strokeColor.replace("#", "");
100
+ icon.transparent = iconUrl + "&chf=a,s,ffffff11&ext=.png";
101
+
102
+ icon.imageMap = [
103
+ width / 2, height,
104
+ (7 / 16) * width, (5 / 8) * height,
105
+ (5 / 16) * width, (7 / 16) * height,
106
+ (7 / 32) * width, (5 / 16) * height,
107
+ (5 / 16) * width, (1 / 8) * height,
108
+ (1 / 2) * width, 0,
109
+ (11 / 16) * width, (1 / 8) * height,
110
+ (25 / 32) * width, (5 / 16) * height,
111
+ (11 / 16) * width, (7 / 16) * height,
112
+ (9 / 16) * width, (5 / 8) * height
113
+ ];
114
+ for (var i = 0; i < icon.imageMap.length; i++) {
115
+ icon.imageMap[i] = parseInt(icon.imageMap[i]);
116
+ }
117
+
118
+ return icon;
119
+ };
120
+
121
+
122
+ /**
123
+ * Creates a flat icon based on the specified options in the
124
+ * {@link MarkerIconOptions} argument.
125
+ * Supported options are: width, height, primaryColor,
126
+ * shadowColor, label, labelColor, labelSize, and shape..
127
+ * @param {MarkerIconOptions} [opts]
128
+ * @return {GIcon}
129
+ */
130
+ MapIconMaker.createFlatIcon = function (opts) {
131
+ var width = opts.width || 32;
132
+ var height = opts.height || 32;
133
+ var primaryColor = opts.primaryColor || "#ff0000";
134
+ var shadowColor = opts.shadowColor || "#000000";
135
+ var label = MapIconMaker.escapeUserText_(opts.label) || "";
136
+ var labelColor = opts.labelColor || "#000000";
137
+ var labelSize = opts.labelSize || 0;
138
+ var shape = opts.shape || "circle";
139
+ var shapeCode = (shape === "circle") ? "it" : "itr";
140
+
141
+ var baseUrl = "http://chart.apis.google.com/chart?cht=" + shapeCode;
142
+ var iconUrl = baseUrl + "&chs=" + width + "x" + height +
143
+ "&chco=" + primaryColor.replace("#", "") + "," +
144
+ shadowColor.replace("#", "") + "ff,ffffff01" +
145
+ "&chl=" + label + "&chx=" + labelColor.replace("#", "") +
146
+ "," + labelSize;
147
+ var icon = new GIcon(G_DEFAULT_ICON);
148
+ icon.image = iconUrl + "&chf=bg,s,00000000" + "&ext=.png";
149
+ icon.iconSize = new GSize(width, height);
150
+ icon.shadowSize = new GSize(0, 0);
151
+ icon.iconAnchor = new GPoint(width / 2, height / 2);
152
+ icon.infoWindowAnchor = new GPoint(width / 2, height / 2);
153
+ icon.printImage = iconUrl + "&chof=gif";
154
+ icon.mozPrintImage = iconUrl + "&chf=bg,s,ECECD8" + "&chof=gif";
155
+ icon.transparent = iconUrl + "&chf=a,s,ffffff01&ext=.png";
156
+ icon.imageMap = [];
157
+ if (shapeCode === "itr") {
158
+ icon.imageMap = [0, 0, width, 0, width, height, 0, height];
159
+ } else {
160
+ var polyNumSides = 8;
161
+ var polySideLength = 360 / polyNumSides;
162
+ var polyRadius = Math.min(width, height) / 2;
163
+ for (var a = 0; a < (polyNumSides + 1); a++) {
164
+ var aRad = polySideLength * a * (Math.PI / 180);
165
+ var pixelX = polyRadius + polyRadius * Math.cos(aRad);
166
+ var pixelY = polyRadius + polyRadius * Math.sin(aRad);
167
+ icon.imageMap.push(parseInt(pixelX), parseInt(pixelY));
168
+ }
169
+ }
170
+
171
+ return icon;
172
+ };
173
+
174
+
175
+ /**
176
+ * Creates a labeled marker icon based on the specified options in the
177
+ * {@link MarkerIconOptions} argument.
178
+ * Supported options are: primaryColor, strokeColor,
179
+ * starPrimaryColor, starStrokeColor, label, labelColor, and addStar.
180
+ * @param {MarkerIconOptions} [opts]
181
+ * @return {GIcon}
182
+ */
183
+ MapIconMaker.createLabeledMarkerIcon = function (opts) {
184
+ var primaryColor = opts.primaryColor || "#DA7187";
185
+ var strokeColor = opts.strokeColor || "#000000";
186
+ var starPrimaryColor = opts.starPrimaryColor || "#FFFF00";
187
+ var starStrokeColor = opts.starStrokeColor || "#0000FF";
188
+ var label = MapIconMaker.escapeUserText_(opts.label) || "";
189
+ var labelColor = opts.labelColor || "#000000";
190
+ var addStar = opts.addStar || false;
191
+
192
+ var pinProgram = (addStar) ? "pin_star" : "pin";
193
+ var baseUrl = "http://chart.apis.google.com/chart?cht=d&chdp=mapsapi&chl=";
194
+ var iconUrl = baseUrl + pinProgram + "'i\\" + "'[" + label +
195
+ "'-2'f\\" + "hv'a\\]" + "h\\]o\\" +
196
+ primaryColor.replace("#", "") + "'fC\\" +
197
+ labelColor.replace("#", "") + "'tC\\" +
198
+ strokeColor.replace("#", "") + "'eC\\";
199
+ if (addStar) {
200
+ iconUrl += starPrimaryColor.replace("#", "") + "'1C\\" +
201
+ starStrokeColor.replace("#", "") + "'0C\\";
202
+ }
203
+ iconUrl += "Lauto'f\\";
204
+
205
+ var icon = new GIcon(G_DEFAULT_ICON);
206
+ icon.image = iconUrl + "&ext=.png";
207
+ icon.iconSize = (addStar) ? new GSize(23, 39) : new GSize(21, 34);
208
+ return icon;
209
+ };
210
+
211
+
212
+ /**
213
+ * Utility function for doing special chart API escaping first,
214
+ * and then typical URL escaping. Must be applied to user-supplied text.
215
+ * @private
216
+ */
217
+ MapIconMaker.escapeUserText_ = function (text) {
218
+ if (text === undefined) {
219
+ return null;
220
+ }
221
+ text = text.replace(/@/, "@@");
222
+ text = text.replace(/\\/, "@\\");
223
+ text = text.replace(/'/, "@'");
224
+ text = text.replace(/\[/, "@[");
225
+ text = text.replace(/\]/, "@]");
226
+ return encodeURIComponent(text);
227
+ };
@@ -0,0 +1,44 @@
1
+ class <%= migration_name %> < ActiveRecord::Migration
2
+
3
+ def self.up
4
+ create_table :<%= table_name %> do |t|
5
+ <% attributes.each do |attribute| -%>
6
+ t.<%= attribute.type %> :<%= attribute.name %>
7
+ <% end -%>
8
+ t.decimal :lat, :precision => 9, :scale => 6, :default => 0.0
9
+ t.decimal :lng, :precision => 9, :scale => 6, :default => 0.0
10
+ t.timestamps
11
+ end
12
+
13
+ add_index :<%= table_name %>, :id
14
+
15
+ User.find(:all).each do |user|
16
+ user.plugins.create(:name => "Map", :position => (user.plugins.maximum(:position) || -1) + 1)
17
+ end
18
+
19
+ page = Page.create(:title => "Map",
20
+ :link_url => "/map",
21
+ :menu_match => "^/map.*$",
22
+ :deletable => false,
23
+ :position => Page.count)
24
+
25
+ RefinerySetting.find_or_set(:default_page_parts, ["Body", "Side Body"]).each do |default_page_part|
26
+ page.parts.create(:title => default_page_part, :body => nil)
27
+ end
28
+
29
+ end
30
+
31
+ def self.down
32
+ UserPlugin.destroy_all({:name => "Map"})
33
+
34
+ Page.find_all_by_link_url("/map").each do |page|
35
+ page.link_url, page.menu_match = nil
36
+ page.deletable = true
37
+ page.destroy
38
+ end
39
+ Page.destroy_all({:link_url => "/map"})
40
+
41
+ drop_table :<%= table_name %>
42
+ end
43
+
44
+ end
data/lib/gemspec.rb ADDED
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env ruby
2
+ require File.expand_path('../map.rb', __FILE__)
3
+ version = ::Refinery::Map.version
4
+ raise "Could not get version so gemspec can not be built" if version.nil?
5
+ files = Dir.glob("**/*").flatten.reject do |file|
6
+ file =~ /\.gem(spec)?$/
7
+ end
8
+
9
+ gemspec = <<EOF
10
+ Gem::Specification.new do |s|
11
+ s.name = %q{refinerycms-map}
12
+ s.version = %q{#{version}}
13
+ s.description = %q{A RefineryCMS plugin that displays an interactive Google map with flaggable locations.}
14
+ s.date = %q{#{Time.now.strftime('%Y-%m-%d')}}
15
+ s.summary = %q{Ruby on Rails map engine for RefineryCMS.}
16
+ s.email = %q{lab@envylabs.com}
17
+ s.homepage = %q{http://github.com/envylabs/refinerycms-map}
18
+ s.authors = %w(Envy\\ Labs)
19
+ s.require_paths = %w(lib)
20
+
21
+ s.files = [
22
+ '#{files.join("',\n '")}'
23
+ ]
24
+ #{"s.test_files = [
25
+ '#{Dir.glob("test/**/*.rb").join("',\n '")}'
26
+ ]" if File.directory?("test")}
27
+ end
28
+ EOF
29
+
30
+ File.open(File.expand_path("../../refinerycms-map.gemspec", __FILE__), 'w').puts(gemspec)
data/lib/map.rb ADDED
@@ -0,0 +1,9 @@
1
+ module Refinery
2
+ module Map
3
+ class << self
4
+ def version
5
+ %q{0.0.1}
6
+ end
7
+ end
8
+ end
9
+ end
data/license.md ADDED
@@ -0,0 +1,21 @@
1
+ # MIT License
2
+
3
+ Copyright (c) 2005-2010 [Resolve Digital Ltd.](http://www.resolvedigital.co.nz)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/rails/init.rb ADDED
@@ -0,0 +1,13 @@
1
+ Refinery::Plugin.register do |plugin|
2
+ plugin.title = "Map"
3
+ plugin.description = "Provides a Google map with location markers"
4
+ plugin.version = 1.0
5
+ plugin.menu_match = /(admin|refinery)\/map(_locations)?$/
6
+ plugin.url = '/refinery/map'
7
+ plugin.activity = {
8
+ :class => MapLocation,
9
+ :title => 'title',
10
+ :url_prefix => 'edit'
11
+ }
12
+ plugin.directory = directory
13
+ end
data/readme.md ADDED
@@ -0,0 +1,39 @@
1
+ # Refinery CMS Map Plugin
2
+
3
+ ## About
4
+
5
+ __This plugin adds a Google map with any number of flagged locations.__
6
+
7
+ Key features:
8
+
9
+ * Admin interface allows you to set the locations that will be displayed on the map.
10
+ * Clicking a location on the map shows address, phone number, and url for that location.
11
+
12
+ ## How do I use it?
13
+
14
+ To install the map plugin, you can either include the gem or install as a plugin.
15
+
16
+ ## Requirements
17
+
18
+ [RefineryCMS](http://refinerycms.com) version 0.9.7 or later.
19
+
20
+ ### Gem Installation using Bundler
21
+
22
+ Include the latest [gem](http://rubygems.org/gems/refinerycms-map) into your Refinery CMS application's Gemfile:
23
+
24
+ gem "refinerycms-map", '~> 0.0.1', :require => "map"
25
+
26
+ Then type the following at command line inside your Refinery CMS application's root directory:
27
+
28
+ bundle install
29
+ script/generate map
30
+ rake db:migrate
31
+
32
+ ### Rails Engine Installation
33
+
34
+ If you do not want to install the engine via bundler then you can install it as an engine inside your application's vendor directory.
35
+ Type the following at command line inside your Refinery CMS application's root directory:
36
+
37
+ script/plugin install git://github.com/envylabs/refinerycms-map.git
38
+ script/generate map
39
+ rake db:migrate
@@ -0,0 +1,4 @@
1
+ require 'test_helper'
2
+
3
+ class MapLocationTest < ActiveSupport::TestCase
4
+ end
metadata ADDED
@@ -0,0 +1,89 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: refinerycms-map
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Envy Labs
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-07-29 00:00:00 -04:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description: A RefineryCMS plugin that displays an interactive Google map with flaggable locations.
23
+ email: lab@envylabs.com
24
+ executables: []
25
+
26
+ extensions: []
27
+
28
+ extra_rdoc_files: []
29
+
30
+ files:
31
+ - app/controllers/admin/map_locations_controller.rb
32
+ - app/controllers/map_locations_controller.rb
33
+ - app/models/map_location.rb
34
+ - app/views/admin/map_locations/_form.html.erb
35
+ - app/views/admin/map_locations/_map_location.html.erb
36
+ - app/views/admin/map_locations/edit.html.erb
37
+ - app/views/admin/map_locations/index.html.erb
38
+ - app/views/admin/map_locations/new.html.erb
39
+ - app/views/map_locations/index.html.erb
40
+ - app/views/map_locations/show.html.erb
41
+ - config/locales/en.yml
42
+ - config/routes.rb
43
+ - generators/map/map_generator.rb
44
+ - generators/map/templates/jquery.jmapping.min.js
45
+ - generators/map/templates/jquery.metadata.js
46
+ - generators/map/templates/mapiconmaker.js
47
+ - generators/map/templates/migration.rb
48
+ - lib/gemspec.rb
49
+ - lib/map.rb
50
+ - license.md
51
+ - rails/init.rb
52
+ - readme.md
53
+ - test/unit/map_location_test.rb
54
+ has_rdoc: true
55
+ homepage: http://github.com/envylabs/refinerycms-map
56
+ licenses: []
57
+
58
+ post_install_message:
59
+ rdoc_options: []
60
+
61
+ require_paths:
62
+ - lib
63
+ required_ruby_version: !ruby/object:Gem::Requirement
64
+ none: false
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ hash: 3
69
+ segments:
70
+ - 0
71
+ version: "0"
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ hash: 3
78
+ segments:
79
+ - 0
80
+ version: "0"
81
+ requirements: []
82
+
83
+ rubyforge_project:
84
+ rubygems_version: 1.3.7
85
+ signing_key:
86
+ specification_version: 3
87
+ summary: Ruby on Rails map engine for RefineryCMS.
88
+ test_files:
89
+ - test/unit/map_location_test.rb