open_porch 0.5.0

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.
Files changed (223) hide show
  1. data/Gemfile +41 -0
  2. data/Gemfile.lock +130 -0
  3. data/README.md +170 -0
  4. data/Rakefile +19 -0
  5. data/VERSION +1 -0
  6. data/app/controllers/admin/areas/base_controller.rb +11 -0
  7. data/app/controllers/admin/areas/issues_controller.rb +67 -0
  8. data/app/controllers/admin/areas/memberships_controller.rb +7 -0
  9. data/app/controllers/admin/areas/posts_controller.rb +44 -0
  10. data/app/controllers/admin/areas_controller.rb +89 -0
  11. data/app/controllers/admin/base_controller.rb +16 -0
  12. data/app/controllers/admin/user_activity_controller.rb +29 -0
  13. data/app/controllers/admin/users_controller.rb +57 -0
  14. data/app/controllers/application_controller.rb +15 -0
  15. data/app/controllers/areas/base_controller.rb +25 -0
  16. data/app/controllers/areas/issues_controller.rb +35 -0
  17. data/app/controllers/areas/posts_controller.rb +28 -0
  18. data/app/controllers/areas_controller.rb +30 -0
  19. data/app/controllers/passwords_controller.rb +42 -0
  20. data/app/controllers/registrations_controller.rb +42 -0
  21. data/app/controllers/sessions_controller.rb +33 -0
  22. data/app/controllers/users_controller.rb +77 -0
  23. data/app/helpers/open_porch_helper.rb +24 -0
  24. data/app/mailers/user_mailer.rb +35 -0
  25. data/app/models/address.rb +57 -0
  26. data/app/models/area.rb +171 -0
  27. data/app/models/area_activity.rb +24 -0
  28. data/app/models/email_message.rb +104 -0
  29. data/app/models/issue.rb +66 -0
  30. data/app/models/issue_number.rb +22 -0
  31. data/app/models/membership.rb +27 -0
  32. data/app/models/post.rb +64 -0
  33. data/app/models/session_user.rb +69 -0
  34. data/app/models/user.rb +140 -0
  35. data/app/models/user_activity.rb +31 -0
  36. data/app/models/user_authority_check.rb +14 -0
  37. data/app/views/admin/areas/_form.html.haml +8 -0
  38. data/app/views/admin/areas/_nav.html.haml +12 -0
  39. data/app/views/admin/areas/edit.html.haml +22 -0
  40. data/app/views/admin/areas/edit_borders.html.haml +44 -0
  41. data/app/views/admin/areas/index.html.haml +61 -0
  42. data/app/views/admin/areas/issues/_post.html.haml +15 -0
  43. data/app/views/admin/areas/issues/add_posts.js.rjs +3 -0
  44. data/app/views/admin/areas/issues/edit.html.haml +37 -0
  45. data/app/views/admin/areas/issues/index.html.haml +31 -0
  46. data/app/views/admin/areas/issues/remove_posts.js.rjs +3 -0
  47. data/app/views/admin/areas/issues/show.html.haml +13 -0
  48. data/app/views/admin/areas/memberships/index.html.haml +17 -0
  49. data/app/views/admin/areas/new.html.haml +6 -0
  50. data/app/views/admin/areas/new.js.haml +4 -0
  51. data/app/views/admin/areas/posts/_edit.html.haml +6 -0
  52. data/app/views/admin/areas/posts/_post_status.html.haml +1 -0
  53. data/app/views/admin/areas/posts/destroy.js.rjs +1 -0
  54. data/app/views/admin/areas/posts/edit.js.rjs +1 -0
  55. data/app/views/admin/areas/posts/show.js.rjs +1 -0
  56. data/app/views/admin/areas/posts/toggle_reviewed_by.js.rjs +1 -0
  57. data/app/views/admin/areas/posts/update.js.rjs +5 -0
  58. data/app/views/admin/areas/show.html.haml +5 -0
  59. data/app/views/admin/user_activity/show.html.haml +5 -0
  60. data/app/views/admin/users/_form.html.haml +21 -0
  61. data/app/views/admin/users/edit.html.haml +5 -0
  62. data/app/views/admin/users/index.html.haml +31 -0
  63. data/app/views/admin/users/new.html.haml +5 -0
  64. data/app/views/areas/issues/index.html.haml +31 -0
  65. data/app/views/areas/issues/show.html.haml +22 -0
  66. data/app/views/areas/posts/_post.html.haml +8 -0
  67. data/app/views/areas/posts/_posts_search_form.html.haml +8 -0
  68. data/app/views/areas/posts/index.html.haml +27 -0
  69. data/app/views/areas/posts/new.html.haml +10 -0
  70. data/app/views/areas/show.html.haml +47 -0
  71. data/app/views/layouts/_account_nav.html.haml +18 -0
  72. data/app/views/layouts/_flash_message.html.haml +4 -0
  73. data/app/views/layouts/_footer.html.haml +9 -0
  74. data/app/views/layouts/_head.html.haml +16 -0
  75. data/app/views/layouts/admin/_nav.html.haml +13 -0
  76. data/app/views/layouts/admin.html.haml +15 -0
  77. data/app/views/layouts/application.html.haml +14 -0
  78. data/app/views/layouts/area_editor.html.haml +11 -0
  79. data/app/views/passwords/edit.html.haml +9 -0
  80. data/app/views/passwords/new.html.haml +13 -0
  81. data/app/views/registrations/_address_form.html.haml +7 -0
  82. data/app/views/registrations/create.html.haml +49 -0
  83. data/app/views/registrations/index.html.haml +30 -0
  84. data/app/views/registrations/new.html.haml +17 -0
  85. data/app/views/sessions/new.html.haml +18 -0
  86. data/app/views/stylesheets/common.sass +239 -0
  87. data/app/views/stylesheets/content.sass +193 -0
  88. data/app/views/stylesheets/reset.sass +46 -0
  89. data/app/views/stylesheets/structure.sass +11 -0
  90. data/app/views/stylesheets/typography.sass +57 -0
  91. data/app/views/user_mailer/email_verification.html.erb +5 -0
  92. data/app/views/user_mailer/email_verification.text.erb +7 -0
  93. data/app/views/user_mailer/new_issue.html.erb +32 -0
  94. data/app/views/user_mailer/new_issue.text.erb +26 -0
  95. data/app/views/user_mailer/password_reset.html.erb +7 -0
  96. data/app/views/user_mailer/password_reset.text.erb +6 -0
  97. data/app/views/users/_form.html.haml +5 -0
  98. data/app/views/users/edit.html.haml +11 -0
  99. data/app/views/users/new.html.haml +41 -0
  100. data/app/views/users/show.html.haml +30 -0
  101. data/bin/open_porch_engine +135 -0
  102. data/config/application.rb +43 -0
  103. data/config/boot.rb +13 -0
  104. data/config/database_example.yml +59 -0
  105. data/config/environment.rb +5 -0
  106. data/config/environments/development.rb +26 -0
  107. data/config/environments/production.rb +49 -0
  108. data/config/environments/test.rb +35 -0
  109. data/config/initializers/backtrace_silencers.rb +7 -0
  110. data/config/initializers/email_regex.rb +38 -0
  111. data/config/initializers/geokit_config.rb +61 -0
  112. data/config/initializers/inflections.rb +20 -0
  113. data/config/initializers/meta_search.rb +7 -0
  114. data/config/initializers/mime_types.rb +5 -0
  115. data/config/initializers/open_porch.rb +41 -0
  116. data/config/initializers/sass.rb +1 -0
  117. data/config/initializers/secret_token.rb +7 -0
  118. data/config/initializers/session_store.rb +8 -0
  119. data/config/initializers/states_provinces.rb +2 -0
  120. data/config/initializers/will_paginate.rb +2 -0
  121. data/config/locales/en.yml +5 -0
  122. data/config/open_porch_example.yml +23 -0
  123. data/config/routes.rb +54 -0
  124. data/config/schedule.rb +9 -0
  125. data/config.ru +4 -0
  126. data/db/migrate/01_create_areas.rb +21 -0
  127. data/db/migrate/02_create_users.rb +28 -0
  128. data/db/migrate/03_create_memberships.rb +14 -0
  129. data/db/migrate/04_create_posts.rb +20 -0
  130. data/db/migrate/05_create_issue_numbers.rb +13 -0
  131. data/db/migrate/06_create_issues.rb +21 -0
  132. data/db/migrate/20110204173301_add_published_to_areas.rb +10 -0
  133. data/db/migrate/20110204194840_create_user_activities.rb +13 -0
  134. data/db/migrate/20110208163604_add_zip_to_areas.rb +11 -0
  135. data/db/migrate/20110209175723_add_counters_to_areas.rb +11 -0
  136. data/db/migrate/20110209182244_remove_subject_from_issues.rb +9 -0
  137. data/db/migrate/20110209190146_add_reviewer_info_to_posts.rb +9 -0
  138. data/db/migrate/20110215173144_add_email_validation_key_to_users.rb +13 -0
  139. data/db/migrate/20110215182716_remove_published_from_areas.rb +10 -0
  140. data/db/migrate/20110215211012_create_area_activities.rb +19 -0
  141. data/db/migrate/20110215213802_create_email_messages.rb +19 -0
  142. data/db/migrate/20110217165018_change_send_mode_to_string.rb +17 -0
  143. data/db/migrate/20110223160609_denormalize_user_info_in_posts.rb +19 -0
  144. data/db/seeds.rb +7 -0
  145. data/doc/README_FOR_APP +2 -0
  146. data/lib/generators/open_porch_generator.rb +37 -0
  147. data/lib/open_porch/engine.rb +20 -0
  148. data/lib/open_porch.rb +3 -0
  149. data/lib/tasks/.gitkeep +0 -0
  150. data/lib/tasks/open_porch.rake +10 -0
  151. data/lib/tasks/postageapp_tasks.rake +78 -0
  152. data/open_porch.gemspec +335 -0
  153. data/public/404.html +26 -0
  154. data/public/422.html +26 -0
  155. data/public/500.html +26 -0
  156. data/public/favicon.ico +0 -0
  157. data/public/images/icons/ajax-loader.gif +0 -0
  158. data/public/images/icons/calendar.png +0 -0
  159. data/public/images/icons/post_new.png +0 -0
  160. data/public/images/icons/post_reviewed.png +0 -0
  161. data/public/javascripts/application.js +3 -0
  162. data/public/javascripts/google_maps.js +153 -0
  163. data/public/javascripts/highcharts.js +162 -0
  164. data/public/javascripts/highcharts_init.js +30 -0
  165. data/public/javascripts/issue_edit.js +57 -0
  166. data/public/javascripts/jquery-ui.min.js +191 -0
  167. data/public/javascripts/jquery.js +154 -0
  168. data/public/javascripts/rails.js +137 -0
  169. data/public/javascripts/region_editor.js +616 -0
  170. data/public/javascripts/user_activity.js +29 -0
  171. data/public/robots.txt +5 -0
  172. data/public/stylesheets/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  173. data/public/stylesheets/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  174. data/public/stylesheets/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  175. data/public/stylesheets/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  176. data/public/stylesheets/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  177. data/public/stylesheets/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  178. data/public/stylesheets/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  179. data/public/stylesheets/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  180. data/public/stylesheets/images/ui-icons_222222_256x240.png +0 -0
  181. data/public/stylesheets/images/ui-icons_2e83ff_256x240.png +0 -0
  182. data/public/stylesheets/images/ui-icons_454545_256x240.png +0 -0
  183. data/public/stylesheets/images/ui-icons_888888_256x240.png +0 -0
  184. data/public/stylesheets/images/ui-icons_cd0a0a_256x240.png +0 -0
  185. data/public/stylesheets/jquery-ui.css +362 -0
  186. data/script/rails +6 -0
  187. data/test/dummy/area.rb +5 -0
  188. data/test/dummy/area_activity.rb +7 -0
  189. data/test/dummy/issue.rb +4 -0
  190. data/test/dummy/membership.rb +4 -0
  191. data/test/dummy/post.rb +12 -0
  192. data/test/dummy/user.rb +29 -0
  193. data/test/dummy/user_activity.rb +11 -0
  194. data/test/functional/admin/areas/issues_controller_test.rb +48 -0
  195. data/test/functional/admin/areas/memberships_controller_test.rb +45 -0
  196. data/test/functional/admin/areas/posts_controller_test.rb +54 -0
  197. data/test/functional/admin/areas_controller_test.rb +134 -0
  198. data/test/functional/admin/base_controller_test.rb +8 -0
  199. data/test/functional/admin/user_activity_controller_test.rb +28 -0
  200. data/test/functional/admin/users_controller_test.rb +144 -0
  201. data/test/functional/areas/issues_controller_test.rb +33 -0
  202. data/test/functional/areas/posts_controller_test.rb +50 -0
  203. data/test/functional/areas_controller_test.rb +12 -0
  204. data/test/functional/passwords_controller_test.rb +64 -0
  205. data/test/functional/registrations_controller_test.rb +64 -0
  206. data/test/functional/sessions_controller_test.rb +120 -0
  207. data/test/functional/users_controller_test.rb +144 -0
  208. data/test/performance/browsing_test.rb +9 -0
  209. data/test/test_helper.rb +92 -0
  210. data/test/unit/address_test.rb +25 -0
  211. data/test/unit/area_activity_test.rb +57 -0
  212. data/test/unit/area_test.rb +92 -0
  213. data/test/unit/email_message_test.rb +8 -0
  214. data/test/unit/issue_number_test.rb +25 -0
  215. data/test/unit/issue_test.rb +154 -0
  216. data/test/unit/membership_test.rb +20 -0
  217. data/test/unit/post_test.rb +69 -0
  218. data/test/unit/session_user_test.rb +65 -0
  219. data/test/unit/user_activity_test.rb +31 -0
  220. data/test/unit/user_mailer_test.rb +20 -0
  221. data/test/unit/user_test.rb +61 -0
  222. data/vendor/plugins/.gitkeep +0 -0
  223. metadata +456 -0
@@ -0,0 +1,616 @@
1
+ (function($){
2
+ $.fn.RegionEditor = function(options) {
3
+ var editor = this;
4
+ var EDIT_MODE = 0;
5
+ var CREATE_MODE = 1;
6
+ var defaults = {
7
+ mode: EDIT_MODE,
8
+ regions : [],
9
+ selected_region_id: 0,
10
+ selected_polygon: null,
11
+ vertices: [],
12
+ map_options: {
13
+ zoom: 14,
14
+ mapTypeControl: false,
15
+ streetViewControl: false,
16
+ scaleControl: false,
17
+ mapTypeId: google.maps.MapTypeId.ROADMAP
18
+ },
19
+ map_style: 'width:100%;height:500px',
20
+ colors : {
21
+ red: '#aa4643',
22
+ blue: '#4572a7'
23
+ }
24
+ };
25
+
26
+ var options = $.extend(defaults, options);
27
+ var map = initialize_google_map();
28
+ $.each(options.regions, add_region); // Add all the regions to the map
29
+ if(options.selected_polygon == null) {
30
+ switch_to_mode(CREATE_MODE);
31
+ alert("Click on the map to add points to the region. When you're done close the region by clicking on the first marker")
32
+ }
33
+
34
+ return this.each(function() {
35
+ obj = $(this);
36
+ });
37
+
38
+
39
+ // -------------------------
40
+ // Initialize Google Map
41
+ // -------------------------
42
+ function initialize_google_map() {
43
+ var map_container = $('<div id="google_map" style ="'+options.map_style+'"></div>');
44
+ editor.append(map_container);
45
+
46
+ // Setting the center of the map
47
+ options.map_options.center = new google.maps.LatLng(options.center.lat, options.center.lng);
48
+
49
+
50
+ // Creating the map
51
+ var map = new google.maps.Map(map_container.get(0), options.map_options);
52
+ render_controls(map);
53
+
54
+ // Adjusting the zoom level if bounds were provided
55
+ if (options.bounds != null) {
56
+ map.fitBounds(new google.maps.LatLngBounds(
57
+ new google.maps.LatLng(options.bounds[0][0], options.bounds[0][1]),
58
+ new google.maps.LatLng(options.bounds[1][0], options.bounds[1][1])
59
+ ));
60
+ }
61
+
62
+ // Right click to add a new point to the selected region (EDIT_MODE)
63
+ google.maps.event.addDomListener(map, 'rightclick', function(event) {
64
+ if(options.mode == EDIT_MODE) {
65
+ if(confirm('Add new point?')) {
66
+ add_new_point_to_polygon(event.latLng);
67
+ }
68
+ }
69
+ });
70
+
71
+ // Add the click event to add a point to a new region (CREATE_MODE)
72
+ google.maps.event.addListener(map, 'click', function(event) {
73
+ if(options.mode == CREATE_MODE) {
74
+ add_point_to_new_region(event.latLng);
75
+ }
76
+ });
77
+
78
+ return map;
79
+ }
80
+
81
+ // -------------------------
82
+ // Adds controls to the map
83
+ // -------------------------
84
+ function render_controls(map){
85
+ // --- Save changes ---
86
+ options.save_btn = $('<div class="editor_button save disabled">Save changes</div>').css('margin-left', '5px');
87
+ google.maps.event.addDomListener(options.save_btn.get(0), 'click', function() {
88
+ if(!options.save_btn.hasClass('disabled')) {
89
+ ajax_update(options.selected_polygon);
90
+ }
91
+ });
92
+ map.controls[google.maps.ControlPosition.TOP_RIGHT].push(options.save_btn.get(0));
93
+
94
+ // --- Reset polygon ---
95
+ options.reset_btn = $('<div class="editor_button reset disabled">Reset region</div>').css('margin-left', '5px');
96
+ google.maps.event.addDomListener(options.reset_btn.get(0), 'click', function() {
97
+ if(!options.save_btn.hasClass('disabled')) {
98
+ reset_polygon(options.selected_polygon);
99
+ prepare_for_edit(options.selected_polygon);
100
+ }
101
+ });
102
+ map.controls[google.maps.ControlPosition.TOP_RIGHT].push(options.reset_btn.get(0));
103
+
104
+ // --- New region ---
105
+ options.new_region_btn = $('<div class="editor_button reset">New region</div>').css('margin-left', '5px');
106
+ google.maps.event.addDomListener(options.new_region_btn.get(0), 'click', function() {
107
+ switch(options.mode) {
108
+ case EDIT_MODE:
109
+ if(options.selected_polygon.has_changed) {
110
+ if(confirm('This region has changed. Discard changes?')) {
111
+ switch_to_mode(CREATE_MODE);
112
+ }
113
+ } else {
114
+ switch_to_mode(CREATE_MODE);
115
+ }
116
+ break;
117
+ case CREATE_MODE:
118
+ if(options.selected_polygon == null) {
119
+ document.location = options.create_url;
120
+ } else {
121
+ switch_to_mode(EDIT_MODE);
122
+ prepare_for_edit(options.selected_polygon);
123
+ }
124
+ break;
125
+ }
126
+ });
127
+ map.controls[google.maps.ControlPosition.TOP_RIGHT].push(options.new_region_btn.get(0));
128
+ }
129
+
130
+ // -------------------------
131
+ // Changes between edit and create modes
132
+ // -------------------------
133
+ function switch_to_mode(mode) {
134
+ switch(mode) {
135
+
136
+ case CREATE_MODE:
137
+ reset_polygon(options.selected_polygon);
138
+ options.new_region_btn.html('Cancel');
139
+ options.mode = CREATE_MODE;
140
+ // Create the temporary polyline that will hold the region coordinates
141
+ options.tmp_poly = new google.maps.Polyline({
142
+ strokeColor: options.colors.red,
143
+ strokeOpacity: 1.0,
144
+ strokeWeight: 3
145
+ });
146
+ options.tmp_poly.setMap(map);
147
+ break;
148
+
149
+ case EDIT_MODE:
150
+ delete_vertices();
151
+ options.tmp_poly.setMap(null);
152
+ options.new_region_btn.html('New region');
153
+ options.mode = EDIT_MODE;
154
+ break;
155
+ }
156
+ }
157
+
158
+ // -------------------------
159
+ // Adds a new region to the map
160
+ // -------------------------
161
+ function add_region(index, region) {
162
+ // Prepare the coordinates for the polygon
163
+ var coordinates = new Array();
164
+ $.each(region.points, function(){
165
+ coordinates.push(new google.maps.LatLng(this[0], this[1]));
166
+ });
167
+
168
+ // Create the polygon
169
+ var polygon = new google.maps.Polygon({
170
+ paths: coordinates,
171
+ region_id: region.id,
172
+ region_index: index,
173
+ is_selected: false,
174
+ has_changed: false
175
+ });
176
+ polygon.setMap(map);
177
+ set_polygon_style(polygon, 'mouseout');
178
+
179
+ // Activate it if it's the seleted polygon
180
+ if(region.id == options.selected_region_id) {
181
+ prepare_for_edit(polygon);
182
+ $('.region_details').html(options.regions[options.selected_polygon.region_index].name);
183
+ }
184
+
185
+ // mouseover event
186
+ google.maps.event.addListener(polygon, 'mouseover', function(event) {
187
+ if(!polygon.is_selected && options.mode == EDIT_MODE) {
188
+ set_polygon_style(polygon, 'mouseover');
189
+ }
190
+ $('.region_details').html(options.regions[polygon.region_index].name);
191
+ });
192
+
193
+ // mouseout event
194
+ google.maps.event.addListener(polygon, 'mouseout', function() {
195
+ if(!polygon.is_selected && options.mode == EDIT_MODE) {
196
+ set_polygon_style(polygon, 'mouseout');
197
+ }
198
+ if(options.selected_polygon != null){
199
+ $('.region_details').html(options.regions[options.selected_polygon.region_index].name)
200
+ }
201
+
202
+ });
203
+ // click event
204
+ google.maps.event.addListener(polygon, 'click', function() {
205
+ if(!polygon.is_selected && options.mode == EDIT_MODE) {
206
+ if(options.selected_polygon.has_changed) {
207
+ if(confirm('This region has changed. Discard changes?')) {
208
+ reset_polygon(options.selected_polygon);
209
+ prepare_for_edit(polygon);
210
+ }
211
+ } else {
212
+ reset_polygon(options.selected_polygon);
213
+ prepare_for_edit(polygon);
214
+ }
215
+ }
216
+ });
217
+
218
+ }
219
+
220
+ // -------------------------
221
+ // Changes the color of a polygon as well as any other options passed in style_options
222
+ // -------------------------
223
+ function set_polygon_style(polygon, style, style_options) {
224
+ switch(style) {
225
+ case 'mouseout':
226
+ defaults = {
227
+ strokeColor: options.colors.blue,
228
+ strokeOpacity: 0.8,
229
+ strokeWeight: 2,
230
+ fillColor: options.colors.blue,
231
+ fillOpacity: 0.1
232
+ }
233
+ break;
234
+ case 'mouseover':
235
+ defaults = {
236
+ strokeColor: options.colors.red, //"#FF0000",
237
+ strokeOpacity: 0.8,
238
+ strokeWeight: 2,
239
+ }
240
+ break;
241
+ case 'selected':
242
+ defaults = {
243
+ strokeColor: options.colors.red, //"#FF0000",
244
+ strokeOpacity: 0.8,
245
+ strokeWeight: 2,
246
+ fillColor: options.colors.red, //"#FF0000",
247
+ fillOpacity: 0.35
248
+ }
249
+ break;
250
+ }
251
+ style_options = $.extend(defaults, style_options);
252
+ polygon.setOptions(style_options);
253
+ }
254
+
255
+ // -------------------------
256
+ // Adds handlers to each vertex of a polygon so it can be edited
257
+ // -------------------------
258
+ function prepare_for_edit(polygon) {
259
+ // Add vertex handlers to the polygon
260
+ polygon.getPath().forEach(function(latlng, index){
261
+ var vertex = new BorderHandler(map, polygon, index, options);
262
+ options.vertices.push(vertex);
263
+
264
+ // Shift + click to delete this vertex
265
+ google.maps.event.addDomListener(vertex.marker, 'click', function(event) {
266
+ if(event.shiftKey) {
267
+ delete_point(polygon, index);
268
+ // [TODO] Finish region snap
269
+ // } else {
270
+ // if(vertex.circle == null) {
271
+ // vertex.create_circle();
272
+ // } else {
273
+ // vertex.delete_circle();
274
+ // }
275
+ }
276
+ });
277
+
278
+ });
279
+
280
+ set_polygon_style(polygon, 'selected', { is_selected: true });
281
+ options.selected_polygon = polygon;
282
+ }
283
+
284
+ // -------------------------
285
+ // Deletes all the vertices from the map
286
+ // -------------------------
287
+ function delete_vertices(){
288
+ for (v in options.vertices) {
289
+ if(options.mode == EDIT_MODE) {
290
+ options.vertices[v].marker.setMap(null);
291
+ } else if(options.mode == CREATE_MODE) {
292
+ options.vertices[v].setMap(null);
293
+ }
294
+ }
295
+ options.vertices = new Array();
296
+ }
297
+
298
+ // -------------------------
299
+ // Returns a polygon to it's original coordinates
300
+ // -------------------------
301
+ function reset_polygon(polygon) {
302
+ if(polygon == null){
303
+ return;
304
+ }
305
+ var coordinates = new Array();
306
+ $.each(options.regions[polygon.region_index].points, function(){
307
+ coordinates.push(new google.maps.LatLng(this[0], this[1]));
308
+ });
309
+ polygon.setPath(coordinates);
310
+ delete_vertices();
311
+ set_polygon_changed_status(polygon, false)
312
+ set_polygon_style(polygon, 'mouseout', { is_selected: false });
313
+ }
314
+
315
+ // -------------------------
316
+ // Saves the changes on the selected polygon
317
+ // -------------------------
318
+ function ajax_update(polygon) {
319
+ new_points = new Array();
320
+ polygon.getPath().forEach(function(point, index){
321
+ new_points.push([point.lat(), point.lng()]);
322
+ });
323
+
324
+ $.post(
325
+ options.update_url,
326
+ {
327
+ authenticity_token: $('meta[name=csrf-token]').attr('content'),
328
+ areas: [
329
+ {
330
+ id: polygon.region_id,
331
+ coordinates: new_points
332
+ }
333
+ ]
334
+ },
335
+ function(){
336
+ // Update the regions array with the new saved coordinates
337
+ options.regions[polygon.region_index].points = new_points;
338
+
339
+ // Reset buttons state
340
+ set_polygon_changed_status(polygon, false)
341
+
342
+ // Notify the user
343
+ obj.prepend($('<div class="flash_message notice">Saved!</div>'));
344
+ setTimeout(function(){
345
+ $('.flash_message.notice').fadeOut('slow', function(){$(this).remove()});
346
+ }, 5000);
347
+ }
348
+ );
349
+ }
350
+
351
+ // -------------------------
352
+ // Creates a new polygon
353
+ // -------------------------
354
+ function ajax_create(region_name) {
355
+ var polyline = options.tmp_poly;
356
+ new_points = new Array();
357
+ polyline.getPath().forEach(function(point, index){
358
+ new_points.push([point.lat(), point.lng()]);
359
+ });
360
+
361
+ $.post(
362
+ options.create_url,
363
+ {
364
+ authenticity_token: $('meta[name=csrf-token]').attr('content'),
365
+ area: {
366
+ coordinates: new_points,
367
+ name: region_name
368
+ }
369
+ },
370
+ function(region_id){
371
+ document.location = options.create_url+'/'+region_id+'/edit_borders';
372
+ },
373
+ 'json'
374
+ );
375
+ }
376
+
377
+
378
+
379
+ // -------------------------
380
+ // Adds a new point to the selected polygon
381
+ // -------------------------
382
+ function add_new_point_to_polygon(latLng) {
383
+ var polygon = options.selected_polygon;
384
+ var path = polygon.getPath();
385
+ var distance = {value: 10000, points: null};
386
+ var point_indexes = null;
387
+ var poly = null;
388
+ var flightPlanCoordinates = [
389
+ path.getAt(0),
390
+ path.getAt(1)
391
+ ];
392
+
393
+ // Collect the distances between the new point and every polygon vertex
394
+ path.forEach(function(poly_latLng, index){
395
+ points = [index, index + 1];
396
+ if(index + 1 >= path.getLength()) {
397
+ points = [index, 0];
398
+ }
399
+ p1 = path.getAt(points[0]);
400
+ p2 = path.getAt(points[1]);
401
+ d = dotLineLength(latLng.lat(), latLng.lng(), p1.lat(), p1.lng(), p2.lat(), p2.lng(), true);
402
+ if(d < distance.value) {
403
+ distance = {value: d, points: points};
404
+ }
405
+ });
406
+
407
+ var coordinates = new Array();
408
+ var added_new_coordinate = false;
409
+ path.forEach(function(poly_latLng, index){
410
+ coordinates.push(poly_latLng);
411
+
412
+ points = [index, index + 1];
413
+ if(index + 1 >= path.getLength()) {
414
+ points = [index, 0];
415
+ }
416
+
417
+ if(!added_new_coordinate && (points[0] == distance.points[0] && points[1] == distance.points[1])) {
418
+ coordinates.push(latLng);
419
+ added_new_coordinate = true;
420
+ }
421
+ });
422
+ polygon.setPath(coordinates);
423
+ set_polygon_changed_status(polygon, true)
424
+ delete_vertices();
425
+ prepare_for_edit(polygon)
426
+ }
427
+
428
+ // -------------------------
429
+ // Deletes a point from a polygon
430
+ // -------------------------
431
+ function delete_point(polygon, index) {
432
+ if(polygon.getPath().getLength() == 3) {
433
+ alert('Cannot delete this point. A region must have at least 3 points.');
434
+ } else if(confirm('Delete this point?')) {
435
+ polygon.getPath().removeAt(index);
436
+ delete_vertices(polygon);
437
+ prepare_for_edit(polygon);
438
+ set_polygon_changed_status(polygon, true)
439
+ }
440
+ }
441
+
442
+ // -------------------------
443
+ // Sets the changed status of a polygon and the control buttons
444
+ // -------------------------
445
+ function set_polygon_changed_status(polygon, changed) {
446
+ if(changed) {
447
+ polygon.has_changed = true;
448
+ options.save_btn.removeClass('disabled');
449
+ options.reset_btn.removeClass('disabled');
450
+ } else {
451
+ options.save_btn.addClass('disabled');
452
+ options.reset_btn.addClass('disabled');
453
+ polygon.has_changed = false;
454
+ }
455
+ }
456
+
457
+ function add_point_to_new_region(latLng) {
458
+ options.tmp_poly.getPath().push(latLng);
459
+ // Add a new marker at the new plotted point on the polyline.
460
+ var marker = new google.maps.Marker({
461
+ position: latLng,
462
+ map: map,
463
+ animation: google.maps.Animation.DROP,
464
+ clickable: (options.vertices.length == 0)
465
+ });
466
+
467
+ options.vertices.push(marker);
468
+
469
+ // Click to delete this vertex
470
+ google.maps.event.addDomListener(marker, 'click', function(event) {
471
+ if(options.tmp_poly.getPath().getLength() < 3) {
472
+ alert('Please add at least 3 points to the region before closing it.');
473
+ } else {
474
+ var region_name = prompt('Enter the name of the new region.');
475
+ if(region_name == null) {
476
+ switch_to_mode(EDIT_MODE);
477
+ prepare_for_edit(polygon);
478
+ } else {
479
+ ajax_create(region_name);
480
+ }
481
+
482
+ }
483
+ });
484
+
485
+ }
486
+
487
+ };
488
+ })(jQuery);
489
+
490
+
491
+ /* --------------------------------------------------------------
492
+ * Creates a draggable marker and binds it to a vertext in a polygon
493
+ * @params
494
+ * {google.maps.Map} map: The map on which to attach the vertex widget. *
495
+ * {google.maps.Polygon} polygon: The polygon to which this vertex marker will bind to
496
+ * {int} index: The index of the point on the polygon to bind to
497
+ * Ref: http://code.google.com/apis/maps/articles/mvcfun.html
498
+ --------------------------------------------------------------*/
499
+ function BorderHandler(map, polygon, index, options) {
500
+ var me = this;
501
+ this.map = map;
502
+ this.circle = null;
503
+ this.set('map', map);
504
+ this.set('position', polygon.getPath().getAt(index));
505
+ this.set('marker', new google.maps.Marker({draggable: true, title: 'index: '+index}));
506
+ this.marker.bindTo('map', this);
507
+ this.marker.bindTo('position', this)
508
+
509
+ google.maps.event.addListener(this.marker, 'drag', function() {
510
+ if(polygon.has_changed == false) {
511
+ polygon.has_changed = true;
512
+ options.save_btn.removeClass('disabled');
513
+ options.reset_btn.removeClass('disabled');
514
+ }
515
+ // update the polygon vertex
516
+ polygon.getPath().setAt(index, this.get('position'));
517
+
518
+ // Update the center of the circle
519
+ if(me.circle != null) {
520
+ me.circle.set('center', this.get('position'))
521
+ }
522
+ });
523
+ }
524
+
525
+ BorderHandler.prototype = new google.maps.MVCObject();
526
+
527
+ BorderHandler.prototype.create_circle = function(){
528
+ if(this.circle == null) {
529
+ this.circle = new RadiusWidget();
530
+ this.circle.bindTo('map', this);
531
+ this.circle.bindTo('center', this, 'position');
532
+ this.bindTo('distance', this.circle);
533
+ this.bindTo('bounds', this.circle);
534
+ }
535
+ }
536
+
537
+ BorderHandler.prototype.delete_circle = function(){
538
+ if(this.circle != null) {
539
+ this.circle.unbind('map');
540
+ this.circle.circle.setMap(null);
541
+ this.circle.sizer.setMap(null);
542
+ this.circle = null;
543
+ };
544
+ }
545
+
546
+
547
+ /* --------------------------------------------------------------
548
+ * A radius widget that adds a circle to a map and centers on a marker.
549
+ --------------------------------------------------------------*/
550
+ function RadiusWidget() {
551
+ this.circle = new google.maps.Circle({
552
+ strokeWeight: 2
553
+ });
554
+ this.set('distance', 1);
555
+ this.bindTo('bounds', this.circle);
556
+ this.circle.bindTo('center', this);
557
+ this.circle.bindTo('map', this);
558
+ this.circle.bindTo('radius', this);
559
+ this.addSizer_();
560
+ }
561
+ RadiusWidget.prototype = new google.maps.MVCObject();
562
+
563
+ // Update the radius when the distance has changed.
564
+ RadiusWidget.prototype.distance_changed = function() {
565
+ this.set('radius', this.get('distance') * 1000);
566
+ };
567
+
568
+ RadiusWidget.prototype.addSizer_ = function() {
569
+ var me = this;
570
+ this.sizer = new google.maps.Marker({
571
+ draggable: true,
572
+ title: 'Drag me!'
573
+ });
574
+
575
+ this.sizer.bindTo('map', this);
576
+ this.sizer.bindTo('position', this, 'sizer_position');
577
+
578
+ google.maps.event.addListener(this.sizer, 'drag', function() {
579
+ var pos = me.get('sizer_position');
580
+ var center = me.get('center');
581
+ var distance = google.maps.geometry.spherical.computeDistanceBetween(center, pos) / 1000
582
+ me.set('distance', distance);
583
+ });
584
+ };
585
+
586
+ RadiusWidget.prototype.center_changed = function() {
587
+ var bounds = this.get('bounds');
588
+
589
+ // Bounds might not always be set so check that it exists first.
590
+ if (bounds) {
591
+ var lng = bounds.getNorthEast().lng();
592
+
593
+ // Put the sizer at center, right on the circle.
594
+ var position = new google.maps.LatLng(this.get('center').lat(), lng);
595
+ this.set('sizer_position', position);
596
+ }
597
+ };
598
+
599
+ dotLineLength = function(x, y, x0, y0, x1, y1, o){
600
+ function lineLength(x, y, x0, y0){
601
+ return Math.sqrt((x -= x0) * x + (y -= y0) * y);
602
+ }
603
+ if(o && !(o = function(x, y, x0, y0, x1, y1){
604
+ if(!(x1 - x0)) return {x: x0, y: y};
605
+ else if(!(y1 - y0)) return {x: x, y: y0};
606
+ var left, tg = -1 / ((y1 - y0) / (x1 - x0));
607
+ return {x: left = (x1 * (x * tg - y + y0) + x0 * (x * - tg + y - y1)) / (tg * (x1 - x0) + y0 - y1), y: tg * left - tg * x + y};
608
+ }(x, y, x0, y0, x1, y1), o.x >= Math.min(x0, x1) && o.x <= Math.max(x0, x1) && o.y >= Math.min(y0, y1) && o.y <= Math.max(y0, y1))){
609
+ var l1 = lineLength(x, y, x0, y0), l2 = lineLength(x, y, x1, y1);
610
+ return l1 > l2 ? l2 : l1;
611
+ }
612
+ else {
613
+ var a = y0 - y1, b = x1 - x0, c = x0 * y1 - y0 * x1;
614
+ return Math.abs(a * x + b * y + c) / Math.sqrt(a * a + b * b);
615
+ }
616
+ };
@@ -0,0 +1,29 @@
1
+ function get_user_activity(user_name, url, delay) {
2
+ $.ajax({
3
+ type: "GET",
4
+ url: "/admin/user_activity/" + user_name,
5
+ data: {
6
+ url : url,
7
+ authenticity_token: $('meta[name=csrf-token]').attr('content')
8
+ },
9
+ success: function(data){
10
+ setTimeout('get_user_activity(\''+ user_name +'\', \''+ url +'\', \''+ delay +'\')', delay);
11
+ $('#user_activity').html(data);
12
+ }
13
+ });
14
+ }
15
+
16
+
17
+ function update_user_activity(user_name, url, delay) {
18
+ $.ajax({
19
+ type: "PUT",
20
+ url: "/admin/user_activity/" + user_name,
21
+ data: ({
22
+ url : url,
23
+ authenticity_token: $('meta[name=csrf-token]').attr('content')
24
+ }),
25
+ success: function(data){
26
+ setTimeout('update_user_activity(\''+ user_name +'\', \''+ url +'\', \''+ delay +'\')', delay);
27
+ }
28
+ });
29
+ }
data/public/robots.txt ADDED
@@ -0,0 +1,5 @@
1
+ # See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file
2
+ #
3
+ # To ban all spiders from the entire site uncomment the next two lines:
4
+ # User-Agent: *
5
+ # Disallow: /