simple-address-generator 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.
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +29 -0
- data/Rakefile +2 -0
- data/lib/rails/generators/simple_address_generator/USAGE +6 -0
- data/lib/rails/generators/simple_address_generator/simple_address_generator_generator.rb +30 -0
- data/lib/rails/generators/simple_address_generator/templates/address.rb +43 -0
- data/lib/rails/generators/simple_address_generator/templates/addresses/_form.html.erb +53 -0
- data/lib/rails/generators/simple_address_generator/templates/addresses/edit.html.erb +6 -0
- data/lib/rails/generators/simple_address_generator/templates/addresses/index.html.erb +40 -0
- data/lib/rails/generators/simple_address_generator/templates/addresses/new.html.erb +5 -0
- data/lib/rails/generators/simple_address_generator/templates/addresses/show.html.erb +63 -0
- data/lib/rails/generators/simple_address_generator/templates/addresses_controller.rb +85 -0
- data/lib/rails/generators/simple_address_generator/templates/gmaps4rails/gmaps4rails.base.js.coffee +502 -0
- data/lib/rails/generators/simple_address_generator/templates/gmaps4rails/gmaps4rails.googlemaps.js.coffee +263 -0
- data/lib/rails/generators/simple_address_generator/templates/icon-1.png +0 -0
- data/lib/simple-address-generator.rb +10 -0
- data/lib/simple-address-generator/version.rb +7 -0
- metadata +67 -0
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Chim Kan
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# Simple::Address::Generator
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'simple-address-generator'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install simple-address-generator
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
module SimpleAddressGenerator
|
2
|
+
module Generators
|
3
|
+
class SimpleAddressGeneratorGenerator < Rails::Generators::Base
|
4
|
+
source_root File.expand_path('../templates', __FILE__)
|
5
|
+
|
6
|
+
def create_address_model
|
7
|
+
generate("model", "address address_line_1:string address_line_2:string city:string state:string postal_code:string country:string telephone_number:string latitude:float longitude:float category_id:integer")
|
8
|
+
rake("db:migrate")
|
9
|
+
end
|
10
|
+
|
11
|
+
def generate_everything_else
|
12
|
+
directory "gmaps4rails", "app/assets/javascripts/gmaps4rails/"
|
13
|
+
directory "addresses", "app/views/"
|
14
|
+
copy_file "addresses_controller.rb", "app/controllers/addresses_controller.rb"
|
15
|
+
copy_file "address.rb", "app/models/address.rb"
|
16
|
+
copy_file "icon-1.png", "app/assets/images/icon-1.png"
|
17
|
+
end
|
18
|
+
|
19
|
+
def insert_routes
|
20
|
+
route("resources :addresses")
|
21
|
+
end
|
22
|
+
|
23
|
+
def add_gems
|
24
|
+
gem("geocoder")
|
25
|
+
gem("gmaps4rails")
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
class Address < ActiveRecord::Base
|
2
|
+
attr_accessible :address_line_1, :address_line_2, :city, :country, :full_name, :postal_code, :state, :telephone_number, :full_address, :latitude, :longitude, :gmaps, :category_id
|
3
|
+
attr_accessor :gmaps
|
4
|
+
|
5
|
+
geocoded_by :full_address
|
6
|
+
|
7
|
+
after_validation :geocode
|
8
|
+
|
9
|
+
acts_as_gmappable
|
10
|
+
|
11
|
+
|
12
|
+
def full_address
|
13
|
+
[self.address_line_1, self.address_line_2, self.city, self.state, self.country, self.postal_code].compact.join(", ")
|
14
|
+
end
|
15
|
+
|
16
|
+
def gmaps4rails_address
|
17
|
+
#describe how to retrieve the address from your model, if you use directly a db column, you can dry your code, see wiki
|
18
|
+
full_address
|
19
|
+
end
|
20
|
+
|
21
|
+
def gmaps4rails_infowindow
|
22
|
+
"#{full_address}"
|
23
|
+
end
|
24
|
+
|
25
|
+
def gmaps4rails_title
|
26
|
+
# add here whatever text you desire
|
27
|
+
"Testing"
|
28
|
+
end
|
29
|
+
|
30
|
+
def gmaps4rails_marker_picture
|
31
|
+
{
|
32
|
+
"picture" => "/assets/icon-#{self.category_id}.png",
|
33
|
+
"width" => 30,
|
34
|
+
"height" => 30,
|
35
|
+
"marker_anchor" => [ 5, 10],
|
36
|
+
"shadow_width" => "110",
|
37
|
+
"shadow_height" => "110",
|
38
|
+
"shadow_anchor" => [5, 10]
|
39
|
+
}
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
<%= form_for(@address) do |f| %>
|
2
|
+
<% if @address.errors.any? %>
|
3
|
+
<div id="error_explanation">
|
4
|
+
<h2><%= pluralize(@address.errors.count, "error") %> prohibited this address from being saved:</h2>
|
5
|
+
|
6
|
+
<ul>
|
7
|
+
<% @address.errors.full_messages.each do |msg| %>
|
8
|
+
<li><%= msg %></li>
|
9
|
+
<% end %>
|
10
|
+
</ul>
|
11
|
+
</div>
|
12
|
+
<% end %>
|
13
|
+
|
14
|
+
<div class="field">
|
15
|
+
<%= f.label :full_name %><br />
|
16
|
+
<%= f.text_field :full_name %>
|
17
|
+
</div>
|
18
|
+
<div class="field">
|
19
|
+
<%= f.label :address_line_1 %><br />
|
20
|
+
<%= f.text_field :address_line_1 %>
|
21
|
+
</div>
|
22
|
+
<div class="field">
|
23
|
+
<%= f.label :address_line_2 %><br />
|
24
|
+
<%= f.text_field :address_line_2 %>
|
25
|
+
</div>
|
26
|
+
<div class="field">
|
27
|
+
<%= f.label :city %><br />
|
28
|
+
<%= f.text_field :city %>
|
29
|
+
</div>
|
30
|
+
<div class="field">
|
31
|
+
<%= f.label :state %><br />
|
32
|
+
<%= f.text_field :state %>
|
33
|
+
</div>
|
34
|
+
<div class="field">
|
35
|
+
<%= f.label :postal_code %><br />
|
36
|
+
<%= f.text_field :postal_code %>
|
37
|
+
</div>
|
38
|
+
<div class="field">
|
39
|
+
<%= f.label :country %><br />
|
40
|
+
<%= f.text_field :country %>
|
41
|
+
</div>
|
42
|
+
<div class="field">
|
43
|
+
<%= f.label :telephone_number %><br />
|
44
|
+
<%= f.text_field :telephone_number %>
|
45
|
+
</div>
|
46
|
+
<div class="field">
|
47
|
+
<%= f.label :category_id %><br />
|
48
|
+
<%= f.text_field :category_id %>
|
49
|
+
</div>
|
50
|
+
<div class="actions">
|
51
|
+
<%= f.submit %>
|
52
|
+
</div>
|
53
|
+
<% end %>
|
@@ -0,0 +1,40 @@
|
|
1
|
+
<h1>Listing addresses</h1>
|
2
|
+
|
3
|
+
<table>
|
4
|
+
<tr>
|
5
|
+
<th>Full name</th>
|
6
|
+
<th>Address line 1</th>
|
7
|
+
<th>Address line 2</th>
|
8
|
+
<th>City</th>
|
9
|
+
<th>State</th>
|
10
|
+
<th>Postal code</th>
|
11
|
+
<th>Country</th>
|
12
|
+
<th>Telephone number</th>
|
13
|
+
<th></th>
|
14
|
+
<th></th>
|
15
|
+
<th></th>
|
16
|
+
</tr>
|
17
|
+
|
18
|
+
<% @addresses.each do |address| %>
|
19
|
+
<tr>
|
20
|
+
<td><%= address.full_name %></td>
|
21
|
+
<td><%= address.address_line_1 %></td>
|
22
|
+
<td><%= address.address_line_2 %></td>
|
23
|
+
<td><%= address.city %></td>
|
24
|
+
<td><%= address.state %></td>
|
25
|
+
<td><%= address.postal_code %></td>
|
26
|
+
<td><%= address.country %></td>
|
27
|
+
<td><%= address.telephone_number %></td>
|
28
|
+
<td><%= link_to 'Show', address %></td>
|
29
|
+
<td><%= link_to 'Edit', edit_address_path(address) %></td>
|
30
|
+
<td><%= link_to 'Destroy', address, confirm: 'Are you sure?', method: :delete %></td>
|
31
|
+
</tr>
|
32
|
+
<% end %>
|
33
|
+
</table>
|
34
|
+
|
35
|
+
<br />
|
36
|
+
<p>
|
37
|
+
<%= gmaps("map_options" => { "center_longitude" => 180, "zoom" => 1, "auto_adjust" => true}, "markers" => {"data" => @json, "options" => {"rich_marker" => true } }) %>
|
38
|
+
</p>
|
39
|
+
|
40
|
+
<%= link_to 'New Address', new_address_path %>
|
@@ -0,0 +1,63 @@
|
|
1
|
+
<p id="notice"><%= notice %></p>
|
2
|
+
|
3
|
+
<p>
|
4
|
+
<b>Full name:</b>
|
5
|
+
<%= @address.full_name %>
|
6
|
+
</p>
|
7
|
+
|
8
|
+
<p>
|
9
|
+
<b>Address line 1:</b>
|
10
|
+
<%= @address.address_line_1 %>
|
11
|
+
</p>
|
12
|
+
|
13
|
+
<p>
|
14
|
+
<b>Address line 2:</b>
|
15
|
+
<%= @address.address_line_2 %>
|
16
|
+
</p>
|
17
|
+
|
18
|
+
<p>
|
19
|
+
<b>City:</b>
|
20
|
+
<%= @address.city %>
|
21
|
+
</p>
|
22
|
+
|
23
|
+
<p>
|
24
|
+
<b>State:</b>
|
25
|
+
<%= @address.state %>
|
26
|
+
</p>
|
27
|
+
|
28
|
+
<p>
|
29
|
+
<b>Postal code:</b>
|
30
|
+
<%= @address.postal_code %>
|
31
|
+
</p>
|
32
|
+
|
33
|
+
<p>
|
34
|
+
<b>Country:</b>
|
35
|
+
<%= @address.country %>
|
36
|
+
</p>
|
37
|
+
|
38
|
+
<p>
|
39
|
+
<b>Telephone number:</b>
|
40
|
+
<%= @address.telephone_number %>
|
41
|
+
</p>
|
42
|
+
|
43
|
+
<p>
|
44
|
+
<b>Latitude:</b>
|
45
|
+
<%= @address.latitude %>
|
46
|
+
</p>
|
47
|
+
|
48
|
+
<p>
|
49
|
+
<b>Longitude:</b>
|
50
|
+
<%= @address.longitude %>
|
51
|
+
</p>
|
52
|
+
|
53
|
+
<p>
|
54
|
+
<b>Full Address:</b>
|
55
|
+
<%= @address.full_address %>
|
56
|
+
</p>
|
57
|
+
|
58
|
+
<p>
|
59
|
+
<%= gmaps("map_options" => { "center_longitude" => 180, "zoom" => 1, "auto_adjust" => true}, "markers" => {"data" => @json, "options" => {"rich_marker" => true } }) %>
|
60
|
+
</p>
|
61
|
+
|
62
|
+
<%= link_to 'Edit', edit_address_path(@address) %> |
|
63
|
+
<%= link_to 'Back', addresses_path %>
|
@@ -0,0 +1,85 @@
|
|
1
|
+
class AddressesController < ApplicationController
|
2
|
+
# GET /addresses
|
3
|
+
# GET /addresses.json
|
4
|
+
def index
|
5
|
+
@addresses = Address.all
|
6
|
+
@json = @addresses.to_gmaps4rails
|
7
|
+
|
8
|
+
respond_to do |format|
|
9
|
+
format.html # index.html.erb
|
10
|
+
format.json { render json: @addresses }
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# GET /addresses/1
|
15
|
+
# GET /addresses/1.json
|
16
|
+
def show
|
17
|
+
@address = Address.find(params[:id])
|
18
|
+
@json = @address.to_gmaps4rails
|
19
|
+
|
20
|
+
respond_to do |format|
|
21
|
+
format.html # show.html.erb
|
22
|
+
format.json { render json: @address }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# GET /addresses/new
|
27
|
+
# GET /addresses/new.json
|
28
|
+
def new
|
29
|
+
@address = Address.new
|
30
|
+
|
31
|
+
respond_to do |format|
|
32
|
+
format.html # new.html.erb
|
33
|
+
format.json { render json: @address }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# GET /addresses/1/edit
|
38
|
+
def edit
|
39
|
+
@address = Address.find(params[:id])
|
40
|
+
end
|
41
|
+
|
42
|
+
# POST /addresses
|
43
|
+
# POST /addresses.json
|
44
|
+
def create
|
45
|
+
@address = Address.new(params[:address])
|
46
|
+
|
47
|
+
respond_to do |format|
|
48
|
+
if @address.save
|
49
|
+
format.html { redirect_to @address, notice: 'Address was successfully created.' }
|
50
|
+
format.json { render json: @address, status: :created, location: @address }
|
51
|
+
else
|
52
|
+
format.html { render action: "new" }
|
53
|
+
format.json { render json: @address.errors, status: :unprocessable_entity }
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# PUT /addresses/1
|
59
|
+
# PUT /addresses/1.json
|
60
|
+
def update
|
61
|
+
@address = Address.find(params[:id])
|
62
|
+
|
63
|
+
respond_to do |format|
|
64
|
+
if @address.update_attributes(params[:address])
|
65
|
+
format.html { redirect_to @address, notice: 'Address was successfully updated.' }
|
66
|
+
format.json { head :no_content }
|
67
|
+
else
|
68
|
+
format.html { render action: "edit" }
|
69
|
+
format.json { render json: @address.errors, status: :unprocessable_entity }
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# DELETE /addresses/1
|
75
|
+
# DELETE /addresses/1.json
|
76
|
+
def destroy
|
77
|
+
@address = Address.find(params[:id])
|
78
|
+
@address.destroy
|
79
|
+
|
80
|
+
respond_to do |format|
|
81
|
+
format.html { redirect_to addresses_url }
|
82
|
+
format.json { head :no_content }
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
data/lib/rails/generators/simple_address_generator/templates/gmaps4rails/gmaps4rails.base.js.coffee
ADDED
@@ -0,0 +1,502 @@
|
|
1
|
+
Gmaps = {}
|
2
|
+
|
3
|
+
Gmaps.triggerOldOnload = ->
|
4
|
+
Gmaps.oldOnload() if typeof(Gmaps.oldOnload) == 'function'
|
5
|
+
|
6
|
+
Gmaps.loadMaps = ->
|
7
|
+
#loop through all variable names.
|
8
|
+
#there should only be maps inside so it trigger their load function
|
9
|
+
for key, value of Gmaps
|
10
|
+
searchLoadIncluded = key.search(/load/)
|
11
|
+
if searchLoadIncluded == -1
|
12
|
+
load_function_name = "load_" + key
|
13
|
+
Gmaps[load_function_name]()
|
14
|
+
|
15
|
+
window.Gmaps = Gmaps
|
16
|
+
|
17
|
+
class @Gmaps4Rails
|
18
|
+
|
19
|
+
constructor: ->
|
20
|
+
#map config
|
21
|
+
@map = null #DEPRECATED: will still contain a copy of serviceObject below as transition
|
22
|
+
@serviceObject = null #contains the map we're working on
|
23
|
+
@visibleInfoWindow = null #contains the current opened infowindow
|
24
|
+
@userLocation = null #contains user's location if geolocalization was performed and successful
|
25
|
+
|
26
|
+
#empty slots
|
27
|
+
@geolocationFailure = -> false #triggered when geolocation fails. If customized, must be like= function(navigator_handles_geolocation){} where 'navigator_handles_geolocation' is a boolean
|
28
|
+
@callback = -> false #to let user set a custom callback function
|
29
|
+
@customClusterer = -> false #to let user set custom clusterer pictures
|
30
|
+
@infobox = -> false #to let user use custom infoboxes
|
31
|
+
@jsTemplate = false #to let user create infowindows client side
|
32
|
+
|
33
|
+
@default_map_options =
|
34
|
+
id: 'map'
|
35
|
+
draggable: true
|
36
|
+
detect_location: false # should the browser attempt to use geolocation detection features of HTML5?
|
37
|
+
center_on_user: false # centers map on the location detected through the browser
|
38
|
+
center_latitude: 0
|
39
|
+
center_longitude: 0
|
40
|
+
zoom: 7
|
41
|
+
maxZoom: null
|
42
|
+
minZoom: null
|
43
|
+
auto_adjust : true # adjust the map to the markers if set to true
|
44
|
+
auto_zoom: true # zoom given by auto-adjust
|
45
|
+
bounds: [] # adjust map to these limits. Should be [{"lat": , "lng": }]
|
46
|
+
raw: {} # raw json to pass additional options
|
47
|
+
|
48
|
+
@default_markers_conf =
|
49
|
+
#Marker config
|
50
|
+
title: ""
|
51
|
+
#MarkerImage config
|
52
|
+
picture : ""
|
53
|
+
width: 22
|
54
|
+
length: 32
|
55
|
+
draggable: false # how to modify: <%= gmaps( "markers" => { "data" => @object.to_gmaps4rails, "options" => { "draggable" => true }}) %>
|
56
|
+
#clustering config
|
57
|
+
do_clustering: false # do clustering if set to true
|
58
|
+
randomize: false # Google maps can't display two markers which have the same coordinates. This randomizer enables to prevent this situation from happening.
|
59
|
+
max_random_distance: 100 # in meters. Each marker coordinate could be altered by this distance in a random direction
|
60
|
+
list_container: null # id of the ul that will host links to all markers
|
61
|
+
offset: 0 # used when adding_markers to an existing map. Because new markers are concated with previous one, offset is here to prevent the existing from being re-created.
|
62
|
+
raw: {} # raw json to pass additional options
|
63
|
+
|
64
|
+
#Stored variables
|
65
|
+
@markers = [] # contains all markers. A marker contains the following: {"description": , "longitude": , "title":, "latitude":, "picture": "", "width": "", "length": "", "sidebar": "", "serviceObject": google_marker}
|
66
|
+
@boundsObject = null # contains current bounds from markers, polylines etc...
|
67
|
+
@polygons = [] # contains raw data, array of arrays (first element could be a hash containing options)
|
68
|
+
@polylines = [] # contains raw data, array of arrays (first element could be a hash containing options)
|
69
|
+
@circles = [] # contains raw data, array of hash
|
70
|
+
@markerClusterer = null # contains all marker clusterers
|
71
|
+
@markerImages = []
|
72
|
+
|
73
|
+
#tnitializes the map
|
74
|
+
initialize : ->
|
75
|
+
@serviceObject = @createMap()
|
76
|
+
@map = @serviceObject #beware, soon deprecated
|
77
|
+
if (@map_options.detect_location == true or @map_options.center_on_user == true)
|
78
|
+
@findUserLocation(this)
|
79
|
+
#resets sidebar if needed
|
80
|
+
@resetSidebarContent()
|
81
|
+
|
82
|
+
findUserLocation : (map_object) ->
|
83
|
+
if (navigator.geolocation)
|
84
|
+
#try to retrieve user's position
|
85
|
+
positionSuccessful = (position) ->
|
86
|
+
map_object.userLocation = map_object.createLatLng(position.coords.latitude, position.coords.longitude)
|
87
|
+
#change map's center to focus on user's geoloc if asked
|
88
|
+
if(map_object.map_options.center_on_user == true)
|
89
|
+
map_object.centerMapOnUser()
|
90
|
+
positionFailure = ->
|
91
|
+
map_object.geolocationFailure(true)
|
92
|
+
|
93
|
+
navigator.geolocation.getCurrentPosition( positionSuccessful, positionFailure)
|
94
|
+
else
|
95
|
+
#failure but the navigator doesn't handle geolocation
|
96
|
+
map_object.geolocationFailure(false)
|
97
|
+
|
98
|
+
|
99
|
+
#////////////////////////////////////////////////////
|
100
|
+
#//////////////////// DIRECTIONS ////////////////////
|
101
|
+
#////////////////////////////////////////////////////
|
102
|
+
|
103
|
+
create_direction : ->
|
104
|
+
directionsDisplay = new google.maps.DirectionsRenderer()
|
105
|
+
directionsService = new google.maps.DirectionsService()
|
106
|
+
|
107
|
+
directionsDisplay.setMap(@serviceObject)
|
108
|
+
#display panel only if required
|
109
|
+
if @direction_conf.display_panel
|
110
|
+
directionsDisplay.setPanel(document.getElementById(@direction_conf.panel_id))
|
111
|
+
|
112
|
+
directionsDisplay.setOptions
|
113
|
+
suppressMarkers: false
|
114
|
+
suppressInfoWindows: false
|
115
|
+
suppressPolylines: false
|
116
|
+
|
117
|
+
request =
|
118
|
+
origin: @direction_conf.origin
|
119
|
+
destination: @direction_conf.destination
|
120
|
+
waypoints: @direction_conf.waypoints
|
121
|
+
optimizeWaypoints: @direction_conf.optimizeWaypoints
|
122
|
+
unitSystem: google.maps.DirectionsUnitSystem[@direction_conf.unitSystem]
|
123
|
+
avoidHighways: @direction_conf.avoidHighways
|
124
|
+
avoidTolls: @direction_conf.avoidTolls
|
125
|
+
region: @direction_conf.region
|
126
|
+
travelMode: google.maps.DirectionsTravelMode[@direction_conf.travelMode]
|
127
|
+
language: "en"
|
128
|
+
|
129
|
+
directionsService.route request, (response, status) ->
|
130
|
+
if (status == google.maps.DirectionsStatus.OK)
|
131
|
+
directionsDisplay.setDirections(response)
|
132
|
+
|
133
|
+
#////////////////////////////////////////////////////
|
134
|
+
#///////////////////// CIRCLES //////////////////////
|
135
|
+
#////////////////////////////////////////////////////
|
136
|
+
|
137
|
+
#Loops through all circles
|
138
|
+
#Loops through all circles and draws them
|
139
|
+
create_circles : ->
|
140
|
+
for circle in @circles
|
141
|
+
@create_circle circle
|
142
|
+
|
143
|
+
create_circle : (circle) ->
|
144
|
+
#by convention, default style configuration could be integrated in the first element
|
145
|
+
if circle == @circles[0]
|
146
|
+
@circles_conf.strokeColor = circle.strokeColor if circle.strokeColor?
|
147
|
+
@circles_conf.strokeOpacity = circle.strokeOpacity if circle.strokeOpacity?
|
148
|
+
@circles_conf.strokeWeight = circle.strokeWeight if circle.strokeWeight?
|
149
|
+
@circles_conf.fillColor = circle.fillColor if circle.fillColor?
|
150
|
+
@circles_conf.fillOpacity = circle.fillOpacity if circle.fillOpacity?
|
151
|
+
|
152
|
+
if circle.lat? and circle.lng?
|
153
|
+
# always check if a config is given, if not, use defaults
|
154
|
+
# NOTE: is there a cleaner way to do this? Maybe a hash merge of some sort?
|
155
|
+
newCircle = new google.maps.Circle
|
156
|
+
center: @createLatLng(circle.lat, circle.lng)
|
157
|
+
strokeColor: circle.strokeColor || @circles_conf.strokeColor
|
158
|
+
strokeOpacity: circle.strokeOpacity || @circles_conf.strokeOpacity
|
159
|
+
strokeWeight: circle.strokeWeight || @circles_conf.strokeWeight
|
160
|
+
fillOpacity: circle.fillOpacity || @circles_conf.fillOpacity
|
161
|
+
fillColor: circle.fillColor || @circles_conf.fillColor
|
162
|
+
clickable: circle.clickable || @circles_conf.clickable
|
163
|
+
zIndex: circle.zIndex || @circles_conf.zIndex
|
164
|
+
radius: circle.radius
|
165
|
+
|
166
|
+
circle.serviceObject = newCircle
|
167
|
+
newCircle.setMap(@serviceObject)
|
168
|
+
|
169
|
+
# clear circles
|
170
|
+
clear_circles : ->
|
171
|
+
for circle in @circles
|
172
|
+
@clear_circle circle
|
173
|
+
|
174
|
+
clear_circle : (circle) ->
|
175
|
+
circle.serviceObject.setMap(null)
|
176
|
+
|
177
|
+
hide_circles : ->
|
178
|
+
for circle in @circles
|
179
|
+
@hide_circle circle
|
180
|
+
|
181
|
+
hide_circle : (circle) ->
|
182
|
+
circle.serviceObject.setMap(null)
|
183
|
+
|
184
|
+
show_circles : ->
|
185
|
+
for circle in @circles
|
186
|
+
@show_circle @circle
|
187
|
+
|
188
|
+
show_circle : (circle) ->
|
189
|
+
circle.serviceObject.setMap(@serviceObject)
|
190
|
+
|
191
|
+
#////////////////////////////////////////////////////
|
192
|
+
#///////////////////// POLYGONS /////////////////////
|
193
|
+
#////////////////////////////////////////////////////
|
194
|
+
|
195
|
+
#polygons is an array of arrays. It loops.
|
196
|
+
create_polygons : ->
|
197
|
+
for polygon in @polygons
|
198
|
+
@create_polygon(polygon)
|
199
|
+
|
200
|
+
#creates a single polygon, triggered by create_polygons
|
201
|
+
create_polygon : (polygon) ->
|
202
|
+
polygon_coordinates = []
|
203
|
+
|
204
|
+
#Polygon points are in an Array, that's why looping is necessary
|
205
|
+
for point in polygon
|
206
|
+
latlng = @createLatLng(point.lat, point.lng)
|
207
|
+
polygon_coordinates.push(latlng)
|
208
|
+
#first element of an Array could contain specific configuration for this particular polygon. If no config given, use default
|
209
|
+
if point == polygon[0]
|
210
|
+
strokeColor = point.strokeColor || @polygons_conf.strokeColor
|
211
|
+
strokeOpacity = point.strokeOpacity || @polygons_conf.strokeOpacity
|
212
|
+
strokeWeight = point.strokeWeight || @polygons_conf.strokeWeight
|
213
|
+
fillColor = point.fillColor || @polygons_conf.fillColor
|
214
|
+
fillOpacity = point.fillOpacity || @polygons_conf.fillOpacity
|
215
|
+
clickable = point.clickable || @polygons_conf.clickable
|
216
|
+
|
217
|
+
#Construct the polygon
|
218
|
+
new_poly = new google.maps.Polygon
|
219
|
+
paths: polygon_coordinates
|
220
|
+
strokeColor: strokeColor
|
221
|
+
strokeOpacity: strokeOpacity
|
222
|
+
strokeWeight: strokeWeight
|
223
|
+
fillColor: fillColor
|
224
|
+
fillOpacity: fillOpacity
|
225
|
+
clickable: clickable
|
226
|
+
map: @serviceObject
|
227
|
+
|
228
|
+
#save polygon in list
|
229
|
+
polygon.serviceObject = new_poly
|
230
|
+
|
231
|
+
#////////////////////////////////////////////////////
|
232
|
+
#/////////////////// POLYLINES //////////////////////
|
233
|
+
#////////////////////////////////////////////////////
|
234
|
+
|
235
|
+
#replace old markers with new markers on an existing map
|
236
|
+
replacePolylines : (new_polylines) ->
|
237
|
+
#reset previous polylines and kill them from map
|
238
|
+
@destroy_polylines()
|
239
|
+
#set new polylines
|
240
|
+
@polylines = new_polylines
|
241
|
+
#create
|
242
|
+
@create_polylines()
|
243
|
+
#.... and adjust map boundaries
|
244
|
+
@adjustMapToBounds()
|
245
|
+
|
246
|
+
destroy_polylines : ->
|
247
|
+
for polyline in @polylines
|
248
|
+
#delete polylines from map
|
249
|
+
polyline.serviceObject.setMap(null)
|
250
|
+
#empty array
|
251
|
+
@polylines = []
|
252
|
+
|
253
|
+
#polylines is an array of arrays. It loops.
|
254
|
+
create_polylines : ->
|
255
|
+
for polyline in @polylines
|
256
|
+
@create_polyline polyline
|
257
|
+
|
258
|
+
#creates a single polyline, triggered by create_polylines
|
259
|
+
create_polyline : (polyline) ->
|
260
|
+
polyline_coordinates = []
|
261
|
+
|
262
|
+
#2 cases here, either we have a coded array of LatLng or we have an Array of LatLng
|
263
|
+
for element in polyline
|
264
|
+
#if we have a coded array
|
265
|
+
if element.coded_array?
|
266
|
+
decoded_array = new google.maps.geometry.encoding.decodePath(element.coded_array)
|
267
|
+
#loop through every point in the array
|
268
|
+
for point in decoded_array
|
269
|
+
polyline_coordinates.push(point)
|
270
|
+
|
271
|
+
#or we have an array of latlng
|
272
|
+
else
|
273
|
+
#by convention, a single polyline could be customized in the first array or it uses default values
|
274
|
+
if element == polyline[0]
|
275
|
+
strokeColor = element.strokeColor || @polylines_conf.strokeColor
|
276
|
+
strokeOpacity = element.strokeOpacity || @polylines_conf.strokeOpacity
|
277
|
+
strokeWeight = element.strokeWeight || @polylines_conf.strokeWeight
|
278
|
+
clickable = element.clickable || @polylines_conf.clickable
|
279
|
+
zIndex = element.zIndex || @polylines_conf.zIndex
|
280
|
+
|
281
|
+
#add latlng if positions provided
|
282
|
+
if element.lat? && element.lng?
|
283
|
+
latlng = @createLatLng(element.lat, element.lng)
|
284
|
+
polyline_coordinates.push(latlng)
|
285
|
+
|
286
|
+
# Construct the polyline
|
287
|
+
new_poly = new google.maps.Polyline
|
288
|
+
path: polyline_coordinates
|
289
|
+
strokeColor: strokeColor
|
290
|
+
strokeOpacity: strokeOpacity
|
291
|
+
strokeWeight: strokeWeight
|
292
|
+
clickable: clickable
|
293
|
+
zIndex: zIndex
|
294
|
+
|
295
|
+
#save polyline
|
296
|
+
polyline.serviceObject = new_poly
|
297
|
+
new_poly.setMap(@serviceObject)
|
298
|
+
|
299
|
+
#////////////////////////////////////////////////////
|
300
|
+
#///////////////////// MARKERS //////////////////////
|
301
|
+
#////////////////////////////////////////////////////
|
302
|
+
|
303
|
+
#creates, clusterizes and adjusts map
|
304
|
+
create_markers : ->
|
305
|
+
@createServiceMarkersFromMarkers()
|
306
|
+
@clusterize()
|
307
|
+
|
308
|
+
#create google.maps Markers from data provided by user
|
309
|
+
createServiceMarkersFromMarkers : ->
|
310
|
+
for marker, index in @markers
|
311
|
+
if not @markers[index].serviceObject?
|
312
|
+
#extract options, test if value passed or use default
|
313
|
+
Lat = @markers[index].lat
|
314
|
+
Lng = @markers[index].lng
|
315
|
+
|
316
|
+
#alter coordinates if randomize is true
|
317
|
+
if @markers_conf.randomize
|
318
|
+
LatLng = @randomize(Lat, Lng)
|
319
|
+
#retrieve coordinates from the array
|
320
|
+
Lat = LatLng[0]
|
321
|
+
Lng = LatLng[1]
|
322
|
+
|
323
|
+
#save object
|
324
|
+
@markers[index].serviceObject = @createMarker
|
325
|
+
"marker_picture": if @markers[index].picture then @markers[index].picture else @markers_conf.picture
|
326
|
+
"marker_width": if @markers[index].width then @markers[index].width else @markers_conf.width
|
327
|
+
"marker_height": if @markers[index].height then @markers[index].height else @markers_conf.length
|
328
|
+
"marker_title": if @markers[index].title then @markers[index].title else null
|
329
|
+
"marker_anchor": if @markers[index].marker_anchor then @markers[index].marker_anchor else null
|
330
|
+
"shadow_anchor": if @markers[index].shadow_anchor then @markers[index].shadow_anchor else null
|
331
|
+
"shadow_picture": if @markers[index].shadow_picture then @markers[index].shadow_picture else null
|
332
|
+
"shadow_width": if @markers[index].shadow_width then @markers[index].shadow_width else null
|
333
|
+
"shadow_height": if @markers[index].shadow_height then @markers[index].shadow_height else null
|
334
|
+
"marker_draggable": if @markers[index].draggable then @markers[index].draggable else @markers_conf.draggable
|
335
|
+
"rich_marker": if @markers[index].rich_marker then @markers[index].rich_marker else null
|
336
|
+
"zindex": if @markers[index].zindex then @markers[index].zindex else null
|
337
|
+
"Lat": Lat
|
338
|
+
"Lng": Lng
|
339
|
+
"index": index
|
340
|
+
|
341
|
+
#add infowindowstuff if enabled
|
342
|
+
@createInfoWindow(@markers[index])
|
343
|
+
#create sidebar if enabled
|
344
|
+
@createSidebar(@markers[index])
|
345
|
+
|
346
|
+
@markers_conf.offset = @markers.length
|
347
|
+
|
348
|
+
#creates Image Anchor Position or return null if nothing passed
|
349
|
+
createImageAnchorPosition : (anchorLocation) ->
|
350
|
+
if (anchorLocation == null)
|
351
|
+
return null
|
352
|
+
else
|
353
|
+
return @createPoint(anchorLocation[0], anchorLocation[1])
|
354
|
+
|
355
|
+
|
356
|
+
#replace old markers with new markers on an existing map
|
357
|
+
replaceMarkers : (new_markers) ->
|
358
|
+
@clearMarkers()
|
359
|
+
#reset previous markers
|
360
|
+
@markers = new Array
|
361
|
+
#reset current bounds
|
362
|
+
@boundsObject = @createLatLngBounds()
|
363
|
+
#reset sidebar content if exists
|
364
|
+
@resetSidebarContent()
|
365
|
+
#add new markers
|
366
|
+
@markers_conf.offset = 0
|
367
|
+
@addMarkers(new_markers)
|
368
|
+
|
369
|
+
#add new markers to on an existing map
|
370
|
+
addMarkers : (new_markers) ->
|
371
|
+
#update the list of markers to take into account
|
372
|
+
@markers = @markers.concat(new_markers)
|
373
|
+
#put markers on the map
|
374
|
+
@create_markers()
|
375
|
+
@adjustMapToBounds()
|
376
|
+
|
377
|
+
#////////////////////////////////////////////////////
|
378
|
+
#///////////////////// SIDEBAR //////////////////////
|
379
|
+
#////////////////////////////////////////////////////
|
380
|
+
|
381
|
+
#//creates sidebar
|
382
|
+
createSidebar : (marker_container) ->
|
383
|
+
if (@markers_conf.list_container)
|
384
|
+
ul = document.getElementById(@markers_conf.list_container)
|
385
|
+
li = document.createElement('li')
|
386
|
+
aSel = document.createElement('a')
|
387
|
+
aSel.href = 'javascript:void(0);'
|
388
|
+
html = if marker_container.sidebar? then marker_container.sidebar else "Marker"
|
389
|
+
aSel.innerHTML = html
|
390
|
+
currentMap = this
|
391
|
+
aSel.onclick = @sidebar_element_handler(currentMap, marker_container.serviceObject, 'click')
|
392
|
+
li.appendChild(aSel)
|
393
|
+
ul.appendChild(li)
|
394
|
+
|
395
|
+
#moves map to marker clicked + open infowindow
|
396
|
+
sidebar_element_handler : (currentMap, marker, eventType) ->
|
397
|
+
return () ->
|
398
|
+
currentMap.map.panTo(marker.position)
|
399
|
+
google.maps.event.trigger(marker, eventType)
|
400
|
+
|
401
|
+
|
402
|
+
resetSidebarContent : ->
|
403
|
+
if @markers_conf.list_container isnt null
|
404
|
+
ul = document.getElementById(@markers_conf.list_container)
|
405
|
+
ul.innerHTML = ""
|
406
|
+
|
407
|
+
#////////////////////////////////////////////////////
|
408
|
+
#////////////////// MISCELLANEOUS ///////////////////
|
409
|
+
#////////////////////////////////////////////////////
|
410
|
+
|
411
|
+
#to make the map fit the different LatLng points
|
412
|
+
adjustMapToBounds : ->
|
413
|
+
#FIRST_STEP: retrieve all bounds
|
414
|
+
#create the bounds object only if necessary
|
415
|
+
if @map_options.auto_adjust or @map_options.bounds isnt null
|
416
|
+
@boundsObject = @createLatLngBounds()
|
417
|
+
|
418
|
+
#if autodjust is true, must get bounds from markers polylines etc...
|
419
|
+
if @map_options.auto_adjust
|
420
|
+
#from markers
|
421
|
+
@extendBoundsWithMarkers()
|
422
|
+
|
423
|
+
#from polylines:
|
424
|
+
for polyline in @polylines
|
425
|
+
polyline_points = polyline.serviceObject.latLngs.getArray()[0].getArray()
|
426
|
+
for point in polyline_points
|
427
|
+
@boundsObject.extend point
|
428
|
+
|
429
|
+
#from polygons:
|
430
|
+
for polygon in @polygons
|
431
|
+
polygon_points = polygon.serviceObject.latLngs.getArray()[0].getArray()
|
432
|
+
for point in polygon_points
|
433
|
+
@boundsObject.extend point
|
434
|
+
|
435
|
+
#from circles
|
436
|
+
for circle in @circles
|
437
|
+
@boundsObject.extend(circle.serviceObject.getBounds().getNorthEast())
|
438
|
+
@boundsObject.extend(circle.serviceObject.getBounds().getSouthWest())
|
439
|
+
|
440
|
+
#in every case, I've to take into account the bounds set up by the user
|
441
|
+
for bound in @map_options.bounds
|
442
|
+
#create points from bounds provided
|
443
|
+
#TODO:only works with google maps
|
444
|
+
bound = @createLatLng(bound.lat, bound.lng)
|
445
|
+
@boundsObject.extend bound
|
446
|
+
|
447
|
+
#SECOND_STEP: ajust the map to the bounds
|
448
|
+
if @map_options.auto_adjust or @map_options.bounds.length > 0
|
449
|
+
|
450
|
+
#if autozoom is false, take user info into account
|
451
|
+
if !@map_options.auto_zoom
|
452
|
+
map_center = @boundsObject.getCenter()
|
453
|
+
@map_options.center_latitude = map_center.lat()
|
454
|
+
@map_options.center_longitude = map_center.lng()
|
455
|
+
@serviceObject.setCenter(map_center)
|
456
|
+
else
|
457
|
+
@fitBounds()
|
458
|
+
|
459
|
+
#////////////////////////////////////////////////////
|
460
|
+
#///////////////// KML //////////////////
|
461
|
+
#////////////////////////////////////////////////////
|
462
|
+
|
463
|
+
create_kml : ->
|
464
|
+
for kml in @kml
|
465
|
+
kml.serviceObject = @createKmlLayer kml
|
466
|
+
|
467
|
+
#////////////////////////////////////////////////////
|
468
|
+
#///////////////// Basic functions //////////////////
|
469
|
+
#///////////////////tests coded//////////////////////
|
470
|
+
|
471
|
+
#//basic function to check existence of a variable
|
472
|
+
exists : (var_name) ->
|
473
|
+
return (var_name != "" and typeof var_name != "undefined")
|
474
|
+
|
475
|
+
|
476
|
+
#randomize
|
477
|
+
randomize : (Lat0, Lng0) ->
|
478
|
+
#distance in meters between 0 and max_random_distance (positive or negative)
|
479
|
+
dx = @markers_conf.max_random_distance * @random()
|
480
|
+
dy = @markers_conf.max_random_distance * @random()
|
481
|
+
Lat = parseFloat(Lat0) + (180/Math.PI)*(dy/6378137)
|
482
|
+
Lng = parseFloat(Lng0) + ( 90/Math.PI)*(dx/6378137)/Math.cos(Lat0)
|
483
|
+
return [Lat, Lng]
|
484
|
+
|
485
|
+
mergeObjectWithDefault : (object1, object2) ->
|
486
|
+
copy_object1 = {}
|
487
|
+
for key, value of object1
|
488
|
+
copy_object1[key] = value
|
489
|
+
|
490
|
+
for key, value of object2
|
491
|
+
unless copy_object1[key]?
|
492
|
+
copy_object1[key] = value
|
493
|
+
return copy_object1
|
494
|
+
|
495
|
+
mergeWithDefault : (objectName) ->
|
496
|
+
default_object = @["default_" + objectName]
|
497
|
+
object = @[objectName]
|
498
|
+
@[objectName] = @mergeObjectWithDefault(object, default_object)
|
499
|
+
return true
|
500
|
+
|
501
|
+
#gives a value between -1 and 1
|
502
|
+
random : -> return(Math.random() * 2 -1)
|
@@ -0,0 +1,263 @@
|
|
1
|
+
#######################################################################################################
|
2
|
+
############################################## Google maps ##########################################
|
3
|
+
#######################################################################################################
|
4
|
+
|
5
|
+
class @Gmaps4RailsGoogle extends Gmaps4Rails
|
6
|
+
|
7
|
+
constructor: ->
|
8
|
+
super
|
9
|
+
#Map settings
|
10
|
+
@map_options =
|
11
|
+
disableDefaultUI: false
|
12
|
+
disableDoubleClickZoom: false
|
13
|
+
type: "ROADMAP" # HYBRID, ROADMAP, SATELLITE, TERRAIN
|
14
|
+
|
15
|
+
#markers + info styling
|
16
|
+
@markers_conf =
|
17
|
+
clusterer_gridSize: 50
|
18
|
+
clusterer_maxZoom: 5
|
19
|
+
custom_cluster_pictures: null
|
20
|
+
custom_infowindow_class: null
|
21
|
+
|
22
|
+
@mergeWithDefault("map_options")
|
23
|
+
@mergeWithDefault("markers_conf")
|
24
|
+
|
25
|
+
@kml_options =
|
26
|
+
clickable: true
|
27
|
+
preserveViewport: false
|
28
|
+
suppressInfoWindows: false
|
29
|
+
|
30
|
+
#Polygon Styling
|
31
|
+
@polygons_conf = # default style for polygons
|
32
|
+
strokeColor: "#FFAA00"
|
33
|
+
strokeOpacity: 0.8
|
34
|
+
strokeWeight: 2
|
35
|
+
fillColor: "#000000"
|
36
|
+
fillOpacity: 0.35
|
37
|
+
clickable: false
|
38
|
+
|
39
|
+
#Polyline Styling
|
40
|
+
@polylines_conf = #default style for polylines
|
41
|
+
strokeColor: "#FF0000"
|
42
|
+
strokeOpacity: 1
|
43
|
+
strokeWeight: 2
|
44
|
+
clickable: false
|
45
|
+
zIndex: null
|
46
|
+
|
47
|
+
#Circle Styling
|
48
|
+
@circles_conf = #default style for circles
|
49
|
+
fillColor: "#00AAFF"
|
50
|
+
fillOpacity: 0.35
|
51
|
+
strokeColor: "#FFAA00"
|
52
|
+
strokeOpacity: 0.8
|
53
|
+
strokeWeight: 2
|
54
|
+
clickable: false
|
55
|
+
zIndex: null
|
56
|
+
|
57
|
+
#Direction Settings
|
58
|
+
@direction_conf =
|
59
|
+
panel_id: null
|
60
|
+
display_panel: false
|
61
|
+
origin: null
|
62
|
+
destination: null
|
63
|
+
waypoints: [] #[{location: "toulouse,fr", stopover: true}, {location: "Clermont-Ferrand, fr", stopover: true}]
|
64
|
+
optimizeWaypoints: false
|
65
|
+
unitSystem: "METRIC" #IMPERIAL
|
66
|
+
avoidHighways: false
|
67
|
+
avoidTolls: false
|
68
|
+
region: null
|
69
|
+
travelMode: "DRIVING" #WALKING, BICYCLING
|
70
|
+
|
71
|
+
#////////////////////////////////////////////////////
|
72
|
+
#/////////////// Basic Objects //////////////
|
73
|
+
#////////////////////////////////////////////////////
|
74
|
+
|
75
|
+
createPoint : (lat, lng) ->
|
76
|
+
return new google.maps.Point(lat, lng)
|
77
|
+
|
78
|
+
createLatLng : (lat, lng) ->
|
79
|
+
return new google.maps.LatLng(lat, lng)
|
80
|
+
|
81
|
+
createLatLngBounds : ->
|
82
|
+
return new google.maps.LatLngBounds()
|
83
|
+
|
84
|
+
createMap : ->
|
85
|
+
defaultOptions =
|
86
|
+
maxZoom: @map_options.maxZoom
|
87
|
+
minZoom: @map_options.minZoom
|
88
|
+
zoom: @map_options.zoom
|
89
|
+
center: @createLatLng(@map_options.center_latitude, @map_options.center_longitude)
|
90
|
+
mapTypeId: google.maps.MapTypeId[@map_options.type]
|
91
|
+
mapTypeControl: @map_options.mapTypeControl
|
92
|
+
disableDefaultUI: @map_options.disableDefaultUI
|
93
|
+
disableDoubleClickZoom: @map_options.disableDoubleClickZoom
|
94
|
+
draggable: @map_options.draggable
|
95
|
+
|
96
|
+
mergedOptions = @mergeObjectWithDefault @map_options.raw, defaultOptions
|
97
|
+
|
98
|
+
return new google.maps.Map document.getElementById(@map_options.id), mergedOptions
|
99
|
+
|
100
|
+
|
101
|
+
createMarkerImage : (markerPicture, markerSize, origin, anchor, scaledSize) ->
|
102
|
+
return new google.maps.MarkerImage(markerPicture, markerSize, origin, anchor, scaledSize)
|
103
|
+
|
104
|
+
createSize : (width, height) ->
|
105
|
+
return new google.maps.Size(width, height)
|
106
|
+
|
107
|
+
#////////////////////////////////////////////////////
|
108
|
+
#////////////////////// Markers /////////////////////
|
109
|
+
#////////////////////////////////////////////////////
|
110
|
+
|
111
|
+
createMarker : (args) ->
|
112
|
+
markerLatLng = @createLatLng(args.Lat, args.Lng)
|
113
|
+
#Marker sizes are expressed as a Size of X,Y
|
114
|
+
if args.marker_picture == "" and args.rich_marker == null
|
115
|
+
defaultOptions = {position: markerLatLng, map: @serviceObject, title: args.marker_title, draggable: args.marker_draggable, zIndex: args.zindex}
|
116
|
+
mergedOptions = @mergeObjectWithDefault @markers_conf.raw, defaultOptions
|
117
|
+
return new google.maps.Marker mergedOptions
|
118
|
+
|
119
|
+
if (args.rich_marker != null)
|
120
|
+
return new RichMarker({
|
121
|
+
position: markerLatLng
|
122
|
+
map: @serviceObject
|
123
|
+
draggable: args.marker_draggable
|
124
|
+
content: args.rich_marker
|
125
|
+
flat: if args.marker_anchor == null then false else args.marker_anchor[1]
|
126
|
+
anchor: if args.marker_anchor == null then 0 else args.marker_anchor[0]
|
127
|
+
zIndex: args.zindex
|
128
|
+
})
|
129
|
+
|
130
|
+
#default behavior
|
131
|
+
#calculate MarkerImage anchor location
|
132
|
+
imageAnchorPosition = @createImageAnchorPosition args.marker_anchor
|
133
|
+
shadowAnchorPosition = @createImageAnchorPosition args.shadow_anchor
|
134
|
+
#create or retrieve existing MarkerImages
|
135
|
+
markerImage = @createOrRetrieveImage(args.marker_picture, args.marker_width, args.marker_height, imageAnchorPosition)
|
136
|
+
shadowImage = @createOrRetrieveImage(args.shadow_picture, args.shadow_width, args.shadow_height, shadowAnchorPosition)
|
137
|
+
defaultOptions = {position: markerLatLng, map: @serviceObject, icon: markerImage, title: args.marker_title, draggable: args.marker_draggable, shadow: shadowImage, zIndex: args.zindex}
|
138
|
+
mergedOptions = @mergeObjectWithDefault @markers_conf.raw, defaultOptions
|
139
|
+
return new google.maps.Marker mergedOptions
|
140
|
+
|
141
|
+
#checks if obj is included in arr Array and returns the position or false
|
142
|
+
includeMarkerImage : (arr, obj) ->
|
143
|
+
for object, index in arr
|
144
|
+
return index if object.url == obj
|
145
|
+
return false
|
146
|
+
|
147
|
+
#checks if MarkerImage exists before creating a new one
|
148
|
+
#returns a MarkerImage or false if ever something wrong is passed as argument
|
149
|
+
createOrRetrieveImage : (currentMarkerPicture, markerWidth, markerHeight, imageAnchorPosition) ->
|
150
|
+
return null if (currentMarkerPicture == "" or currentMarkerPicture == null )
|
151
|
+
|
152
|
+
test_image_index = @includeMarkerImage(@markerImages, currentMarkerPicture)
|
153
|
+
switch test_image_index
|
154
|
+
when false
|
155
|
+
markerImage = @createMarkerImage(currentMarkerPicture, @createSize(markerWidth, markerHeight), null, imageAnchorPosition, null )
|
156
|
+
@markerImages.push(markerImage)
|
157
|
+
return markerImage
|
158
|
+
break
|
159
|
+
else
|
160
|
+
return @markerImages[test_image_index] if typeof test_image_index == 'number'
|
161
|
+
return false
|
162
|
+
|
163
|
+
#clear markers
|
164
|
+
clearMarkers : ->
|
165
|
+
for marker in @markers
|
166
|
+
@clearMarker marker
|
167
|
+
|
168
|
+
#show and hide markers
|
169
|
+
showMarkers : ->
|
170
|
+
for marker in @markers
|
171
|
+
@showMarker marker
|
172
|
+
|
173
|
+
hideMarkers : ->
|
174
|
+
for marker in @markers
|
175
|
+
@hideMarker marker
|
176
|
+
|
177
|
+
clearMarker : (marker) ->
|
178
|
+
marker.serviceObject.setMap(null)
|
179
|
+
|
180
|
+
showMarker : (marker) ->
|
181
|
+
marker.serviceObject.setVisible(true)
|
182
|
+
|
183
|
+
hideMarker : (marker) ->
|
184
|
+
marker.serviceObject.setVisible(false)
|
185
|
+
|
186
|
+
extendBoundsWithMarkers : ->
|
187
|
+
for marker in @markers
|
188
|
+
@boundsObject.extend(marker.serviceObject.position)
|
189
|
+
|
190
|
+
#////////////////////////////////////////////////////
|
191
|
+
#/////////////////// Clusterer //////////////////////
|
192
|
+
#////////////////////////////////////////////////////
|
193
|
+
|
194
|
+
createClusterer : (markers_array) ->
|
195
|
+
return new MarkerClusterer( @serviceObject, markers_array, { maxZoom: @markers_conf.clusterer_maxZoom, gridSize: @markers_conf.clusterer_gridSize, styles: @customClusterer() })
|
196
|
+
|
197
|
+
clearClusterer : ->
|
198
|
+
@markerClusterer.clearMarkers()
|
199
|
+
|
200
|
+
#creates clusters
|
201
|
+
clusterize : ->
|
202
|
+
if @markers_conf.do_clustering == true
|
203
|
+
#first clear the existing clusterer if any
|
204
|
+
@clearClusterer() if @markerClusterer != null
|
205
|
+
|
206
|
+
markers_array = new Array
|
207
|
+
for marker in @markers
|
208
|
+
markers_array.push(marker.serviceObject)
|
209
|
+
|
210
|
+
@markerClusterer = @createClusterer(markers_array)
|
211
|
+
|
212
|
+
#////////////////////////////////////////////////////
|
213
|
+
#/////////////////// INFO WINDOW ////////////////////
|
214
|
+
#////////////////////////////////////////////////////
|
215
|
+
|
216
|
+
#// creates infowindows
|
217
|
+
createInfoWindow : (marker_container) ->
|
218
|
+
if typeof(@jsTemplate) == "function" or marker_container.description?
|
219
|
+
marker_container.description = @jsTemplate(marker_container) if typeof(@jsTemplate) == "function"
|
220
|
+
if @markers_conf.custom_infowindow_class != null
|
221
|
+
#creating custom infowindow
|
222
|
+
boxText = document.createElement("div")
|
223
|
+
boxText.setAttribute("class", @markers_conf.custom_infowindow_class) #to customize
|
224
|
+
boxText.innerHTML = marker_container.description
|
225
|
+
marker_container.infowindow = new InfoBox(@infobox(boxText))
|
226
|
+
currentMap = this
|
227
|
+
google.maps.event.addListener(marker_container.serviceObject, 'click', @openInfoWindow(currentMap, marker_container.infowindow, marker_container.serviceObject))
|
228
|
+
else
|
229
|
+
#create default infowindow
|
230
|
+
marker_container.infowindow = new google.maps.InfoWindow({content: marker_container.description })
|
231
|
+
#add the listener associated
|
232
|
+
currentMap = this
|
233
|
+
google.maps.event.addListener(marker_container.serviceObject, 'click', @openInfoWindow(currentMap, marker_container.infowindow, marker_container.serviceObject))
|
234
|
+
|
235
|
+
openInfoWindow : (currentMap, infoWindow, marker) ->
|
236
|
+
return ->
|
237
|
+
# Close the latest selected marker before opening the current one.
|
238
|
+
currentMap.visibleInfoWindow.close() if currentMap.visibleInfoWindow != null
|
239
|
+
infoWindow.open(currentMap.serviceObject, marker)
|
240
|
+
currentMap.visibleInfoWindow = infoWindow
|
241
|
+
|
242
|
+
#////////////////////////////////////////////////////
|
243
|
+
#///////////////// KML //////////////////
|
244
|
+
#////////////////////////////////////////////////////
|
245
|
+
|
246
|
+
createKmlLayer : (kml) ->
|
247
|
+
kml_options = kml.options || {}
|
248
|
+
kml_options = @mergeObjectWithDefault(kml_options, @kml_options)
|
249
|
+
kml = new google.maps.KmlLayer( kml.url, kml_options)
|
250
|
+
kml.setMap(@serviceObject)
|
251
|
+
return kml
|
252
|
+
|
253
|
+
|
254
|
+
#////////////////////////////////////////////////////
|
255
|
+
#/////////////////// Other methods //////////////////
|
256
|
+
#////////////////////////////////////////////////////
|
257
|
+
|
258
|
+
fitBounds : ->
|
259
|
+
@serviceObject.fitBounds(@boundsObject) unless @boundsObject.isEmpty()
|
260
|
+
|
261
|
+
centerMapOnUser : ->
|
262
|
+
@serviceObject.setCenter(@userLocation)
|
263
|
+
|
Binary file
|
metadata
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: simple-address-generator
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Chim Kan
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-05-07 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: ! 'simple-address-generator allows you to create a complete Address model
|
15
|
+
with fields and two main plugins that geocode address into coordinates and a Google
|
16
|
+
Maps view with custom makers. To use, just add this gem to your Gemfile and then
|
17
|
+
in your Rails 3 application, run: rails g simple-address-generator. Then run rails
|
18
|
+
s and see in your browser http://localhost:3000/addresses.'
|
19
|
+
email: designium+simple@gmail.com
|
20
|
+
executables: []
|
21
|
+
extensions: []
|
22
|
+
extra_rdoc_files: []
|
23
|
+
files:
|
24
|
+
- lib/rails/generators/simple_address_generator/simple_address_generator_generator.rb
|
25
|
+
- lib/rails/generators/simple_address_generator/templates/address.rb
|
26
|
+
- lib/rails/generators/simple_address_generator/templates/addresses/_form.html.erb
|
27
|
+
- lib/rails/generators/simple_address_generator/templates/addresses/edit.html.erb
|
28
|
+
- lib/rails/generators/simple_address_generator/templates/addresses/index.html.erb
|
29
|
+
- lib/rails/generators/simple_address_generator/templates/addresses/new.html.erb
|
30
|
+
- lib/rails/generators/simple_address_generator/templates/addresses/show.html.erb
|
31
|
+
- lib/rails/generators/simple_address_generator/templates/addresses_controller.rb
|
32
|
+
- lib/rails/generators/simple_address_generator/templates/gmaps4rails/gmaps4rails.base.js.coffee
|
33
|
+
- lib/rails/generators/simple_address_generator/templates/gmaps4rails/gmaps4rails.googlemaps.js.coffee
|
34
|
+
- lib/rails/generators/simple_address_generator/templates/icon-1.png
|
35
|
+
- lib/rails/generators/simple_address_generator/USAGE
|
36
|
+
- lib/simple-address-generator/version.rb
|
37
|
+
- lib/simple-address-generator.rb
|
38
|
+
- Gemfile
|
39
|
+
- LICENSE
|
40
|
+
- Rakefile
|
41
|
+
- README.md
|
42
|
+
homepage: ''
|
43
|
+
licenses: []
|
44
|
+
post_install_message: ! '***************************************'
|
45
|
+
rdoc_options: []
|
46
|
+
require_paths:
|
47
|
+
- lib
|
48
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
55
|
+
none: false
|
56
|
+
requirements:
|
57
|
+
- - ! '>='
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '0'
|
60
|
+
requirements: []
|
61
|
+
rubyforge_project:
|
62
|
+
rubygems_version: 1.8.11
|
63
|
+
signing_key:
|
64
|
+
specification_version: 3
|
65
|
+
summary: simple-address-generator allows you to create a complete Address model integrated
|
66
|
+
to Google Maps.
|
67
|
+
test_files: []
|