Commit cb39785801b897d6dd856bed8d9762929c4cb96e
Committed by
Fabio Teixeira
1 parent
79818886
Exists in
master
and in
27 other branches
city_state_auto_complete: City/State auto-complete for user signup
(AI3003) - Add autocomplete to state and city fields in person create - Created helper to share logic between maps and signup autocomplete Signed-off-by: Fabio Teixeira <fabio1079@gmail.com> Signed-off-by: Gustavo Jaruga <darksshades@gmail.com> Signed-off-by: David Carlos <ddavidcarlos1392@gmail.com> Signed-off-by: Matheus Faria <matheus.sousa.faria@gmail.com>
Showing
8 changed files
with
134 additions
and
20 deletions
Show diff stats
app/controllers/my_profile/maps_controller.rb
| ... | ... | @@ -31,23 +31,11 @@ class MapsController < MyProfileController |
| 31 | 31 | end |
| 32 | 32 | |
| 33 | 33 | def search_city |
| 34 | - | |
| 35 | - term = params[:term]; | |
| 36 | - | |
| 37 | - regions = NationalRegion.search_city(term + "%", true).map {|r|{ :label => r.city , :category => r.state}} | |
| 38 | - | |
| 39 | - render :json => regions | |
| 40 | - | |
| 34 | + render :json => MapsHelper.search_city(params[:term]) | |
| 41 | 35 | end |
| 42 | 36 | |
| 43 | 37 | def search_state |
| 44 | - | |
| 45 | - term = params[:term]; | |
| 46 | - | |
| 47 | - regions = NationalRegion.search_state(term + "%", true).map {|r|{ :label => r.state}} | |
| 48 | - | |
| 49 | - render :json => regions | |
| 50 | - | |
| 38 | + render :json => MapsHelper.search_state(params[:term]) | |
| 51 | 39 | end |
| 52 | 40 | |
| 53 | 41 | end | ... | ... |
app/controllers/public/account_controller.rb
| ... | ... | @@ -291,6 +291,23 @@ class AccountController < ApplicationController |
| 291 | 291 | render :text => user_data.to_json, :layout => false, :content_type => "application/javascript" |
| 292 | 292 | end |
| 293 | 293 | |
| 294 | + def search_cities | |
| 295 | + if request.xhr? and params[:state_name] and params[:city_name] | |
| 296 | + render :json => MapsHelper.search_city(params[:city_name], params[:state_name]) | |
| 297 | + else | |
| 298 | + render :json => [].to_json | |
| 299 | + end | |
| 300 | + end | |
| 301 | + | |
| 302 | + def search_state | |
| 303 | + if request.xhr? and params[:state_name] | |
| 304 | + render :json => MapsHelper.search_state(params[:state_name]) | |
| 305 | + else | |
| 306 | + render :json => [].to_json | |
| 307 | + end | |
| 308 | + end | |
| 309 | + | |
| 310 | + | |
| 294 | 311 | protected |
| 295 | 312 | |
| 296 | 313 | def redirect? | ... | ... |
| ... | ... | @@ -0,0 +1,14 @@ |
| 1 | +module MapsHelper | |
| 2 | + def self.search_city term, state="" | |
| 3 | + cities = if state.empty? | |
| 4 | + NationalRegion.search_city(term + "%", true) | |
| 5 | + else | |
| 6 | + NationalRegion.search_city(term + "%", true, state) | |
| 7 | + end | |
| 8 | + cities.map {|r|{ :label => r.city , :category => r.state}} | |
| 9 | + end | |
| 10 | + | |
| 11 | + def self.search_state term | |
| 12 | + NationalRegion.search_state(term + "%", true).map {|r|{ :label => r.state}} | |
| 13 | + end | |
| 14 | +end | ... | ... |
app/models/national_region.rb
| ... | ... | @@ -12,7 +12,7 @@ class NationalRegion < ActiveRecord::Base |
| 12 | 12 | adtional_contions = ""; |
| 13 | 13 | |
| 14 | 14 | if like |
| 15 | - operator = "like" | |
| 15 | + operator = "ilike" | |
| 16 | 16 | find_return = :all |
| 17 | 17 | end |
| 18 | 18 | |
| ... | ... | @@ -41,7 +41,7 @@ class NationalRegion < ActiveRecord::Base |
| 41 | 41 | find_return = :first |
| 42 | 42 | |
| 43 | 43 | if like |
| 44 | - operator = "like" | |
| 44 | + operator = "ilike" | |
| 45 | 45 | find_return = :all |
| 46 | 46 | end |
| 47 | 47 | ... | ... |
app/views/profile_editor/_person_form.rhtml
| ... | ... | @@ -19,8 +19,8 @@ |
| 19 | 19 | <%= optional_field(@person, 'birth_date', labelled_form_field(_('Birth date'), '<div class="select-birth-date">' + pick_date(:profile_data, :birth_date, {:start_year => (Date.today.year - 100), :end_year => (Date.today.year - 5)}) + '</div>')) %> |
| 20 | 20 | <%= optional_field(@person, 'nationality', f.text_field(:nationality, :rel => _('Nationality'))) %> |
| 21 | 21 | <%= optional_field(@person, 'country', select_country(_('Country'), 'profile_data', 'country', {:class => 'type-select'})) %> |
| 22 | -<%= optional_field(@person, 'state', f.text_field(:state, :rel => _('State'))) %> | |
| 23 | -<%= optional_field(@person, 'city', f.text_field(:city, :rel => _('City'))) %> | |
| 22 | +<%= optional_field(@person, 'state', f.text_field(:state, :id => 'state_field', :rel => _('State'))) %> | |
| 23 | +<%= optional_field(@person, 'city', f.text_field(:city, :id => 'city_field', :rel => _('City'))) %> | |
| 24 | 24 | <%= optional_field(@person, 'zip_code', labelled_form_field(_('ZIP code'), text_field(:profile_data, :zip_code, :rel => _('ZIP code')))) %> |
| 25 | 25 | <%= optional_field(@person, 'address', labelled_form_field(_('Address (street and number)'), text_field(:profile_data, :address, :rel => _('Address')))) %> |
| 26 | 26 | <%= optional_field(@person, 'address_reference', labelled_form_field(_('Address reference'), text_field(:profile_data, :address_reference, :rel => _('Address reference')))) %> |
| ... | ... | @@ -36,6 +36,7 @@ |
| 36 | 36 | </div> |
| 37 | 37 | <% end %> |
| 38 | 38 | |
| 39 | +<%= javascript_include_tag('city_state_validation') %> | |
| 39 | 40 | <script type='text/javascript'> |
| 40 | 41 | function toggle_text_field(id, span_id) { |
| 41 | 42 | if ($(id).value == "Others") { | ... | ... |
app/views/shared/_organization_custom_fields.rhtml
| ... | ... | @@ -13,8 +13,8 @@ |
| 13 | 13 | <%= optional_field(profile, 'address_reference', labelled_form_field(_('Address reference'), text_field(object_name, :address_reference))) %> |
| 14 | 14 | <%= optional_field(profile, 'district', labelled_form_field(_('District'), text_field(object_name, :district))) %> |
| 15 | 15 | <%= optional_field(profile, 'zip_code', labelled_form_field(_('ZIP code'), text_field(object_name, :zip_code))) %> |
| 16 | -<%= optional_field(profile, 'city', f.text_field(:city)) %> | |
| 17 | -<%= optional_field(profile, 'state', f.text_field(:state)) %> | |
| 16 | +<%= optional_field(profile, 'city', f.text_field(:city, :id =>'city_field')) %> | |
| 17 | +<%= optional_field(profile, 'state', f.text_field(:state,:id =>'state_field')) %> | |
| 18 | 18 | <%= optional_field(profile, 'country', select_country(_('Country'), object_name, 'country', {:class => 'type-select'})) %> |
| 19 | 19 | <%= optional_field(profile, 'tag_list', f.text_field(:tag_list)) %> |
| 20 | 20 | |
| ... | ... | @@ -29,3 +29,4 @@ |
| 29 | 29 | <%= optional_field(profile, 'acronym', f.text_field(:acronym)) %> |
| 30 | 30 | <%= optional_field(profile, 'foundation_year', f.text_field(:foundation_year)) %> |
| 31 | 31 | <% end %> |
| 32 | +<%= javascript_include_tag('city_state_validation') %> | ... | ... |
| ... | ... | @@ -0,0 +1,55 @@ |
| 1 | +(function($){ | |
| 2 | + $('[id$="_country"]').change(function(){ | |
| 3 | + var country_selected = $('[id$="_country"] option:selected').val() | |
| 4 | + if(country_selected == "BR") | |
| 5 | + { | |
| 6 | + $('#state_field').autocomplete({ | |
| 7 | + source : function(request, response){ | |
| 8 | + $.ajax({ | |
| 9 | + type: "GET", | |
| 10 | + url: '/account/search_state', | |
| 11 | + data: {state_name: request.term}, | |
| 12 | + success: function(result){ | |
| 13 | + response(result); | |
| 14 | + }, | |
| 15 | + error: function(ajax, stat, errorThrown) { | |
| 16 | + console.log('Link not found : ' + errorThrown); | |
| 17 | + } | |
| 18 | + }); | |
| 19 | + }, | |
| 20 | + | |
| 21 | + minLength: 3 | |
| 22 | + }); | |
| 23 | + | |
| 24 | + $('#city_field').autocomplete({ | |
| 25 | + source : function(request, response){ | |
| 26 | + $.ajax({ | |
| 27 | + type: "GET", | |
| 28 | + url: '/account/search_cities', | |
| 29 | + data: {city_name: request.term, state_name: $("#state_field").val()}, | |
| 30 | + success: function(result){ | |
| 31 | + response(result); | |
| 32 | + }, | |
| 33 | + error: function(ajax, stat, errorThrown) { | |
| 34 | + console.log('Link not found : ' + errorThrown); | |
| 35 | + } | |
| 36 | + }); | |
| 37 | + }, | |
| 38 | + | |
| 39 | + minLength: 3 | |
| 40 | + }); | |
| 41 | + } | |
| 42 | + else | |
| 43 | + { | |
| 44 | + if ($('#state_field').data('autocomplete')) { | |
| 45 | + $('#state_field').autocomplete("destroy"); | |
| 46 | + $('#state_field').removeData('autocomplete'); | |
| 47 | + } | |
| 48 | + | |
| 49 | + if ($('#city_field').data('autocomplete')) { | |
| 50 | + $('#city_field').autocomplete("destroy"); | |
| 51 | + $('#city_field').removeData('autocomplete'); | |
| 52 | + } | |
| 53 | + } | |
| 54 | + }) | |
| 55 | +})(jQuery); | ... | ... |
test/functional/account_controller_test.rb
| ... | ... | @@ -917,6 +917,30 @@ class AccountControllerTest < ActionController::TestCase |
| 917 | 917 | assert @response.body.blank? |
| 918 | 918 | end |
| 919 | 919 | |
| 920 | + should "Search for state" do | |
| 921 | + create_state_and_city | |
| 922 | + | |
| 923 | + xhr :get, :search_state, :state_name=>"Rio Grande" | |
| 924 | + | |
| 925 | + json_response = ActiveSupport::JSON.decode(@response.body) | |
| 926 | + label = json_response[0]['label'] | |
| 927 | + | |
| 928 | + assert_equal label, "Rio Grande do Sul" | |
| 929 | + end | |
| 930 | + | |
| 931 | + should "Search for city" do | |
| 932 | + create_state_and_city | |
| 933 | + | |
| 934 | + xhr :get, :search_cities, :state_name=>"Rio Grande do Sul", :city_name=>"Lavras" | |
| 935 | + | |
| 936 | + json_response = ActiveSupport::JSON.decode(@response.body) | |
| 937 | + label = json_response[0]['label'] | |
| 938 | + category = json_response[0]['category'] | |
| 939 | + | |
| 940 | + assert_equal category, "Rio Grande do Sul" | |
| 941 | + assert_equal label, "Lavras do Sul" | |
| 942 | + end | |
| 943 | + | |
| 920 | 944 | protected |
| 921 | 945 | def new_user(options = {}, extra_options ={}) |
| 922 | 946 | data = {:profile_data => person_data} |
| ... | ... | @@ -945,4 +969,18 @@ class AccountControllerTest < ActionController::TestCase |
| 945 | 969 | environment.min_signup_delay = 0 |
| 946 | 970 | environment.save! |
| 947 | 971 | end |
| 972 | + | |
| 973 | + def create_state_and_city | |
| 974 | + city = 'Lavras do Sul' | |
| 975 | + state = 'Rio Grande do Sul' | |
| 976 | + | |
| 977 | + parent_region = fast_create(NationalRegion, :name => state, | |
| 978 | + :national_region_code => '43', | |
| 979 | + :national_region_type_id => NationalRegionType::STATE) | |
| 980 | + | |
| 981 | + fast_create(NationalRegion, :name => city, | |
| 982 | + :national_region_code => '431150', | |
| 983 | + :national_region_type_id => NationalRegionType::CITY, | |
| 984 | + :parent_national_region_code => parent_region.national_region_code) | |
| 985 | + end | |
| 948 | 986 | end | ... | ... |