diff --git a/app/controllers/addresses_controller.rb b/app/controllers/addresses_controller.rb new file mode 100644 index 0000000..366b9ea --- /dev/null +++ b/app/controllers/addresses_controller.rb @@ -0,0 +1,11 @@ +class AddressesController < ApplicationController + respond_to :json + def index + @address = Address.find_lat_lng("#{params[:address]}, #{params[:city_state]}") + unless @address.blank? + respond_with @address + else + render :json => {"errors" => {"address" => ["Could not find address."]}} + end + end +end diff --git a/app/controllers/hydrants_controller.rb b/app/controllers/hydrants_controller.rb index 5ded29a..9d6a520 100644 --- a/app/controllers/hydrants_controller.rb +++ b/app/controllers/hydrants_controller.rb @@ -1,6 +1,15 @@ class HydrantsController < ApplicationController respond_to :json + def index + @hydrants = Hydrant.find_closest(params[:lat], params[:lng]) + unless @hydrants.blank? + respond_with @hydrants + else + render(:json => {"errors" => {"address" => ["Could not find address."]}}) + end + end + def update @hydrant = Hydrant.find(params[:id]) if @hydrant.update_attributes(params[:hydrant]) diff --git a/app/controllers/javascripts_controller.rb b/app/controllers/javascripts_controller.rb new file mode 100644 index 0000000..2081b8a --- /dev/null +++ b/app/controllers/javascripts_controller.rb @@ -0,0 +1,4 @@ +class JavascriptsController < ApplicationController + def main + end +end diff --git a/app/controllers/main_controller.rb b/app/controllers/main_controller.rb index 68f8f37..6519d7b 100644 --- a/app/controllers/main_controller.rb +++ b/app/controllers/main_controller.rb @@ -1,14 +1,2 @@ class MainController < ApplicationController - def index - @zoom = 15 - # Default coordinates: Boston center - @lat, @lng = 42.358431, -71.059773 - @hydrants = [] - address, city_state = params[:address], params[:city_state] - if address && city_state - @zoom = 18 - @lat, @lng = Address.find_lat_lng("#{address}, #{city_state}") - @hydrants = Hydrant.find_closest(@lat, @lng) - end - end end diff --git a/app/views/javascripts/main.js.erb b/app/views/javascripts/main.js.erb new file mode 100644 index 0000000..1e655eb --- /dev/null +++ b/app/views/javascripts/main.js.erb @@ -0,0 +1,297 @@ +$(function() { + var map; + var latlng = new google.maps.LatLng(42.358431, -71.059773); + var myOptions = { + mapTypeControl: false, + scaleControl: true, + scaleControlOptions: { + position: google.maps.ControlPosition.BOTTOM_CENTER + }, + zoom: 15, + center: latlng, + mapTypeId: google.maps.MapTypeId.ROADMAP + }; + var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions); + var activeHydrantId; + var activeMarker; + var activeInfoWindow; + function addMarker(hydrantId, point, color) { + var image = new google.maps.MarkerImage(color, + new google.maps.Size(27.0, 37.0), + new google.maps.Point(0, 0), + new google.maps.Point(13.0, 18.0) + ); + var shadow = new google.maps.MarkerImage('/images/markers/shadow.png', + new google.maps.Size(46.0, 37.0), + new google.maps.Point(0, 0), + new google.maps.Point(13.0, 18.0) + ); + var marker = new google.maps.Marker({ + position: point, + map: map, + icon: image, + shadow: shadow + }); + google.maps.event.addListener(marker, 'click', function() { + if(activeInfoWindow) { + activeInfoWindow.close(); + } + $.get('<%= forms_path %>', { + 'hydrant_id': hydrantId + }, function(data) { + var infoWindow = new google.maps.InfoWindow({ + content: data, + maxWidth: 350 + }); + infoWindow.open(map, marker); + activeHydrantId = hydrantId; + activeMarker = marker; + activeInfoWindow = infoWindow; + }); + }); + } + $('#location_form').submit(function() { + if($('#address').val() === '') { + $('#address').focus(); + $('#address_label').addClass('error', 500); + $('#address').addClass('error', 500); + } else { + $.get('<%= address_path :format => "json" %>', { + 'commit': $('#location_submit').val(), + 'utf8': '✓', + 'authenticity_token': $('#location_form input[name="authenticity_token"]').val(), + 'city_state': $('#city_state').val(), + 'address': $('#address').val() + }, function(data) { + if(data.errors) { + $('#address').focus(); + $('#address_label').addClass('error', 500); + $('#address').addClass('error', 500); + } else { + map.setZoom(18); + latlng = new google.maps.LatLng(data[0], data[1]); + map.setCenter(latlng); + $.get('<%= hydrants_path :format => "json" %>', { + 'commit': $('#location_submit').val(), + 'utf8': '✓', + 'authenticity_token': $('#location_form input[name="authenticity_token"]').val(), + 'lat': data[0], + 'lng': data[1] + }, function(data) { + // This should never happen, but just in case + if(data.errors) { + $('#address').focus(); + $('#address_label').addClass('error', 500); + $('#address').addClass('error', 500); + } else { + $(data).each(function(index, hydrant) { + hydrant = hydrant.hydrant; + point = new google.maps.LatLng(hydrant.lat, hydrant.lng); + color = '/images/markers/' + (hydrant.user_id ? "green" : "red") + '.png'; + addMarker(hydrant.id, point, color); + }); + } + }); + } + }); + } + return false; + }); + $('#combo_form input[type="radio"]').live('click', function() { + var self = $(this); + if('new' == self.val()) { + $('#user_forgot_password_fields').slideUp(); + $('#sign_in_fields').slideUp(); + $('#sign_up_fields').slideDown(); + $('#combo_form').data('state', 'sign_up'); + } else if('existing' == self.val()) { + $('#sign_up_fields').slideUp(); + $('#sign_in_fields').slideDown(function() { + $('#combo_form').data('state', 'sign_in'); + $('#user_forgot_password_link').click(function() { + $('#sign_in_fields').slideUp(); + $('#user_forgot_password_fields').slideDown(function() { + $('#user_remembered_password').click(function() { + $('#user_forgot_password_fields').slideUp(); + $('#sign_in_fields').slideDown(); + $('#combo_form').data('state', 'sign_in'); + }); + }); + $('#combo_form').data('state', 'user_forgot_password'); + }); + }); + } + }); + $('#combo_form').live('submit', function() { + var errors = [] + if(!/[\w\.%\+\]+@[\w\]+\.+[\w]{2,}/.test($('#user_email').val())) { + errors.push($('#user_email')); + $('#user_email_label').addClass('error', 500); + $('#user_email').addClass('error', 500); + } else { + $('#user_email_label').removeClass('error'); + $('#user_email').removeClass('error'); + } + if(!$(this).data('state') || $(this).data('state') === 'sign_up') { + if($('#user_name').val() === '') { + errors.push($('#user_name')); + $('#user_name_label').addClass('error', 500); + $('#user_name').addClass('error', 500); + } else { + $('#user_name_label').removeClass('error'); + $('#user_name').removeClass('error'); + } + if($('#user_password_confirmation').val().length < 6 || $('#user_password_confirmation').val().length > 20) { + errors.push($('#user_password_confirmation')); + $('#user_password_confirmation_label').addClass('error', 500); + $('#user_password_confirmation').addClass('error', 500); + } else { + $('#user_password_confirmation_label').removeClass('error'); + $('#user_password_confirmation').removeClass('error'); + } + if(errors.length > 0) { + errors[0].focus(); + } else { + $.post('<%= user_registration_path :format => "json" %>', { + 'commit': $('#sign_up_submit').val(), + 'utf8': '✓', + 'authenticity_token': $('input[name="authenticity_token"]').val(), + 'user': { + 'email': $('#user_email').val(), + 'name': $('#user_name').val(), + 'organization': $('#user_organization').val(), + 'voice_number': $('#user_voice_number').val(), + 'sms_number': $('#user_sms_number').val(), + 'password': $('#user_password_confirmation').val(), + 'password_confirmation': $('#user_password_confirmation').val() + } + }, function(data) { + if(data.errors) { + if(data.errors.email) { + errors.push($('#user_email')); + $('#user_email_label').addClass('error', 500); + $('#user_email').addClass('error', 500); + } + if(data.errors.name) { + errors.push($('#user_name')); + $('#user_name_label').addClass('error', 500); + $('#user_name').addClass('error', 500); + } + if(data.errors.organization) { + errors.push($('#user_organization')); + $('#user_organization_label').addClass('error', 500); + $('#user_organization').addClass('error', 500); + } + if(data.errors.voice_number) { + errors.push($('#user_voice_number')); + $('#user_voice_number_label').addClass('error', 500); + $('#user_voice_number').addClass('error', 500); + } + if(data.errors.sms_number) { + errors.push($('#user_sms_number')); + $('#user_sms_number_label').addClass('error', 500); + $('#user_sms_number').addClass('error', 500); + } + if(data.errors.password) { + errors.push($('#user_password_confirmation')); + $('#user_password_confirmation_label').addClass('error', 500); + $('#user_password_confirmation').addClass('error', 500); + } + errors[0].focus(); + } else { + $.get('<%= forms_path %>', { + 'hydrant_id': activeHydrantId + }, function(data) { + activeInfoWindow.setContent(data); + }); + } + }); + } + } else if($(this).data('state') === 'sign_in') { + if($('#user_password').val().length < 6 || $('#user_password').val().length > 20) { + errors.push($('#user_password')); + $('#user_password_label').addClass('error', 500); + $('#user_password').addClass('error', 500); + } else { + $('#user_password_label').removeClass('error'); + $('#user_password').removeClass('error'); + } + if(errors.length > 0) { + errors[0].focus(); + } else { + $.post('<%= user_session_path :format => "json" %>', { + 'commit': $('#sign_in_submit').val(), + 'utf8': '✓', + 'authenticity_token': $('input[name="authenticity_token"]').val(), + 'user': { + 'email': $('#user_email').val(), + 'password': $('#user_password').val(), + 'remember_me': $('#user_remember_me').val() + } + }, function(data) { + if(data.errors) { + $('#user_password').focus(); + $('#user_password_label').addClass('error', 500); + $('#user_password').addClass('error', 500); + } else { + $.get('<%= forms_path %>', { + 'hydrant_id': activeHydrantId + }, function(data) { + activeInfoWindow.setContent(data); + }); + } + }); + } + } else if($(this).data('state') === 'user_forgot_password') { + if(errors.length > 0) { + errors[0].focus(); + } else { + $.post('<%= user_password_path :format => "json" %>', { + 'commit': $('#user_forgot_password_submit').val(), + 'utf8': '✓', + 'authenticity_token': $('input[name="authenticity_token"]').val(), + 'user': { + 'email': $('#user_email').val() + } + }, function(data) { + if(data.errors) { + $('#user_email').focus(); + $('#user_email_label').addClass('error', 500); + $('#user_email').addClass('error', 500); + } else { + $('#user_forgot_password_fields').slideUp(); + $('#sign_in_fields').slideDown(); + } + }); + } + } + return false; + }); + $('#adoption_form').live('submit', function() { + $.post('<%= hydrant_path :format => "json" %>', { + 'id': $('#hydrant_id').val(), + 'commit': $('#adoption_form_submit').val(), + 'utf8': '✓', + 'authenticity_token': $('input[name="authenticity_token"]').val(), + '_method': 'put', + 'hydrant': { + 'user_id': $('#hydrant_user_id').val(), + 'name': $('#hydrant_name').val() + } + }, function(data) { + $.get('<%= forms_path %>', { + 'hydrant_id': activeHydrantId + }, function(data) { + activeInfoWindow.setContent(data); + image = new google.maps.MarkerImage('/images/markers/green.png', + new google.maps.Size(27.0, 37.0), + new google.maps.Point(0, 0), + new google.maps.Point(13.0, 18.0) + ); + activeMarker.setIcon(image); + activeMarker.setAnimation(google.maps.Animation.BOUNCE); + }); + }); + return false; + }); +}); diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index b990c40..ce3c692 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -7,271 +7,7 @@ <%= javascript_include_tag "https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js" %> <%= javascript_include_tag "https://ajax.googleapis.com/ajax/libs/jqueryui/1/jquery-ui.min.js" %> <%= javascript_include_tag "https://github.com/scottschiller/Snowstorm/raw/master/snowstorm-min.js" %> - + <%= javascript_include_tag javascripts_main_path %> <%= csrf_meta_tag %> diff --git a/app/views/main/index.html.erb b/app/views/main/index.html.erb index 22f00b7..f1d246a 100644 --- a/app/views/main/index.html.erb +++ b/app/views/main/index.html.erb @@ -8,7 +8,7 @@ <%= select_tag "city_state", ''.html_safe, :tabindex => 10 %> <%= label_tag "address", "Address", :id => "address_label" %> <%= text_field_tag "address", params[:address], :tabindex => 11 %> - <%= submit_tag "Find Fire Hydrants", :tabindex => 12 %> + <%= submit_tag "Find Fire Hydrants", :id => "location_submit", :tabindex => 12 %> <% end %>
<%= image_tag "logos/cfa.png", :alt => "Code for America", :title => "Code for America" %> diff --git a/config/routes.rb b/config/routes.rb index 36070a4..d82e47e 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -5,7 +5,12 @@ AdoptAHydrant::Application.routes.draw do :sessions => 'sessions', } resource :user + get 'hydrants' => 'hydrants#index' resource :hydrant + scope 'javascripts', :controller => 'javascripts', :as => 'javascripts' do + get 'main', :action => 'main', :as => 'main' + end + get 'address' => 'addresses#index', :as => 'address' get 'sitemap' => 'sitemaps#index', :as => 'sitemap' get 'forms' => 'forms#index', :as => 'forms' root :to => 'main#index' diff --git a/public/javascripts/.gitkeep b/public/javascripts/.gitkeep deleted file mode 100644 index e69de29..0000000