1/* 2 * Contact form country -> state/province behaviour. 3 * 4 * US -> "State" label, US states 5 * CA -> "Province" label, Canadian provinces 6 * other -> field hidden and cleared; IndexController substitutes '---' for Salesforce 7 * 8 * Hiding the field would leave a hole in the grid, so city and the two ZIPs widen from 9 * col-md-4 to col-md-6: country + city on one row, the ZIPs on the next. Every field 10 * shares one Bootstrap 3 .row, and that grid floats, so unequal column heights make the 11 * next column snag rather than wrap cleanly -- the country SumoSelect is taller than the 12 * city text input. The ZIP row therefore has to clear the floats above it explicitly. 13 * 14 * The blade renders both lists with a data-country attribute; this filters them. 15 * global.js initialises SumoSelect on an 800ms timer, so the first pass lands before 16 * the plugin reads the <select> and needs no reload. Later passes go through sumo.reload(). 17 */ 18(function ($) { 19 'use strict'; 20 21 var COUNTRIES_WITH_STATES = ['US', 'CA']; 22 23 function hasStates(country) { 24 return $.inArray($.trim(country || ''), COUNTRIES_WITH_STATES) !== -1; 25 } 26 27 // Called by the per-brand submit handlers in custom*.js. 28 // Accepts either a selector string or the form element/jQuery object itself, 29 // so callers scoped to `this` can pass the submitted form directly. 30 window.stateIsRequired = function (form) { 31 return hasStates($(form).find('select[name="country"]').val()); 32 }; 33 34 $(function () { 35 var $country = $('#country'), 36 $state = $('#state'), 37 $field = $('#state_field'), 38 $label = $('#state_label'), 39 $zip = $('#zip_field'), 40 $addressCols = $('#city_field, #zip_field, #service_zip_field'); 41 42 if (!$country.length || !$state.length || !$field.length) return; 43 44 // Snapshot every option once; the select is rebuilt from this on each change. 45 var options = $state.find('option').map(function () { 46 return { 47 value: this.value, 48 text: $(this).text(), 49 country: $(this).attr('data-country') || '' 50 }; 51 }).get(); 52 53 function render(reload) { 54 var country = $.trim($country.val() || ''), 55 previous = $state.val(); 56 57 $state.empty(); 58 $.each(options, function (i, opt) { 59 if (opt.country === '' || opt.country === country) { 60 $state.append( 61 $('<option>', { value: opt.value, text: opt.text }) 62 .attr('data-country', opt.country || null) 63 ); 64 } 65 }); 66 67 // Keep the current selection only if it exists in the new list. 68 $state.val($state.find('option').filter(function () { 69 return this.value === previous; 70 }).length ? previous : ''); 71 72 $label.text($label.attr('data-label-' + country) || $label.attr('data-label-default')); 73 74 var showState = hasStates(country); 75 if (showState) { 76 $field.show(); 77 } else { 78 $state.val('').removeClass('invalid'); 79 $field.hide(); 80 } 81 $addressCols.toggleClass('col-md-4', showState).toggleClass('col-md-6', !showState); 82 // Drop the ZIP pair below the country/city floats instead of snagging beside them. 83 // No-op under 992px, where the col-md-* columns are not floated. 84 $zip.css('clear', showState ? '' : 'left'); 85 86 if (reload && $state[0].sumo) $state[0].sumo.reload(); 87 } 88 89 render(false); 90 $country.on('change', function () { render(true); }); 91 }); 92})(jQuery);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.