1function OnlineInstallVehicleVm() { 2 var self = this; 3 4 self.States = []; 5 self.Mode = ko.observable('plate'); 6 self.PlateState = ko.observable(''); 7 self.PlateNumber = ko.observable(''); 8 self.Vin = ko.observable(''); 9 10 self.PlateNumber.subscribe(function (val) { 11 if (val) { 12 var cleaned = val.replace(/[^a-zA-Z0-9]/g, '').toUpperCase(); 13 if (cleaned !== val) self.PlateNumber(cleaned); 14 } 15 }); 16 17 self.Vin.subscribe(function (val) { 18 if (val) { 19 var cleaned = val.replace(/[^a-zA-Z0-9]/g, '').toUpperCase(); 20 if (cleaned !== val) self.Vin(cleaned); 21 } 22 }); 23 24 self.Year = ko.observable(''); 25 self.Make = ko.observable(''); 26 self.VehicleModel = ko.observable(''); 27 self.Color = ko.observable(''); 28 29 self.YearOptions = ko.observableArray([]); 30 self.MakeOptions = ko.observableArray([]); 31 self.ModelOptions = ko.observableArray([]); 32 self.ColorOptions = ko.observableArray([]); 33 34 self.LookupPerformed = ko.observable(false); 35 self.LookupErrorTitle = ko.observable(''); 36 self.LookupErrorMessage = ko.observable(''); 37 38 self.LookupErrorTitle.subscribe(function (v) { 39 if (v) window.scrollTo({ top: 0, behavior: 'smooth' }); 40 }); 41 42 self._suppressCascade = false; 43 self._loadingLookup = false; 44 45 self.IsManualMode = ko.computed(function () { 46 return self.Mode() === 'manual'; 47 }); 48 49 self.ShowVehicleFields = ko.computed(function () { 50 if (self.Mode() === 'manual') return true; 51 return self.LookupPerformed(); 52 }); 53 54 self.CanLookupPlate = ko.computed(function () { 55 return self.PlateState() !== '' && self.PlateNumber() !== ''; 56 }); 57 58 self.CanLookupVin = ko.computed(function () { 59 return self.Vin() !== '' && self.Vin().length > 0; 60 }); 61 62 self.CanSubmit = ko.computed(function () { 63 return self.ShowVehicleFields(); 64 }); 65 66 self.ShowVehicleFields.subscribe(function (visible) { 67 if (visible) { 68 var $form = $('#vehicleForm'); 69 $form.removeData("validator").removeData("unobtrusiveValidation"); 70 $.validator.unobtrusive.parse($form); 71 } 72 }); 73 74 // Cascade: Year changed â load Makes 75 self.Year.subscribe(function (year) { 76 if (self._suppressCascade) return; 77 self.MakeOptions([]); 78 self.ModelOptions([]); 79 self.Make(''); 80 self.VehicleModel(''); 81 if (year) { 82 self.LoadMakes(year); 83 } 84 }); 85 86 // Cascade: Make changed â load Models 87 self.Make.subscribe(function (makeName) { 88 if (self._suppressCascade) return; 89 self.ModelOptions([]); 90 self.VehicleModel(''); 91 if (makeName && self.Year()) { 92 var selected = self.MakeOptions().find(function (m) { return m.name === makeName; }); 93 if (selected) { 94 self.LoadModels(self.Year(), selected.id); 95 } 96 } 97 }); 98 99 self.SetMode = function (mode) { 100 self.Mode(mode); 101 self.LookupErrorTitle(''); 102 self.LookupErrorMessage(''); 103 self.LookupPerformed(false); 104 self.Year(''); 105 self.Make(''); 106 self.VehicleModel(''); 107 self.Color(''); 108 self.YearOptions([]); 109 self.MakeOptions([]); 110 self.ModelOptions([]); 111 if (mode === 'manual') { 112 self.LoadYears(); 113 self.LogVehicleManualEntry(); 114 } 115 }; 116 117 self.LogVehicleManualEntry = function () { 118 if (typeof logEvent !== 'function' || typeof analyticsEvent === 'undefined') return; 119 120 const analyticsContext = window.onlineInstallAnalyticsContext || {}; 121 logEvent(analyticsEvent.enro_vehicle_manual_entry, { 122 enrollment_id: analyticsContext.enrollment_id || '' 123 }); 124 }; 125 126 self.LoadYears = function (callback) { 127 ajaxHelper({ 128 url: window.location.origin + '/OnlineInstall/GetVehicleYears', 129 type: 'GET', 130 dataType: 'json', 131 spinner: !self._loadingLookup, 132 spinnerSelector: '.vehicle-form', 133 success: function (result) { 134 self.YearOptions(result.sort(function (a, b) { return b - a; }).map(function (y) { return y.toString(); })); 135 if (callback) callback(); 136 } 137 }); 138 }; 139 140 self.LoadMakes = function (year, callback) { 141 ajaxHelper({ 142 url: window.location.origin + '/OnlineInstall/GetVehicleMakes', 143 type: 'GET', 144 dataType: 'json', 145 data: { year: year }, 146 spinner: !self._loadingLookup, 147 spinnerSelector: '.vehicle-form', 148 success: function (result) { 149 self.MakeOptions(result); 150 if (callback) callback(); 151 } 152 }); 153 }; 154 155 self.LoadColors = function (callback) { 156 ajaxHelper({ 157 url: window.location.origin + '/OnlineInstall/GetVehicleC
157olors', 158 type: 'GET', 159 dataType: 'json', 160 success: function (result) { 161 self.ColorOptions(result); 162 if (callback) callback(); 163 } 164 }); 165 }; 166 167 self.LoadModels = function (year, makeId, callback) { 168 ajaxHelper({ 169 url: window.location.origin + '/OnlineInstall/GetVehicleModels', 170 type: 'GET', 171 dataType: 'json', 172 data: { year: year, makeId: makeId }, 173 spinner: !self._loadingLookup, 174 spinnerSelector: '.vehicle-form', 175 success: function (result) { 176 self.ModelOptions(result); 177 if (callback) callback(); 178 } 179 }); 180 }; 181 182 self.LookupVehicle = function () { 183 if (self.Mode() === 'plate' && !self.CanLookupPlate()) return; 184 if (self.Mode() === 'vin' && !self.CanLookupVin()) return; 185 186 self.LookupErrorTitle(''); 187 self.LookupErrorMessage(''); 188 self.LookupPerformed(false); 189 self.LogVehicleLookupAttempt(); 190 191 var data = {}; 192 if (self.Mode() === 'plate') { 193 data.plateNumber = self.PlateNumber(); 194 data.plateState = self.PlateState(); 195 } else { 196 data.vin = self.Vin(); 197 } 198 199 AddSpinner('.vehicle-form'); 200 201 ajaxHelper({ 202 url: window.location.origin + '/OnlineInstall/VehicleLookup', 203 type: 'GET', 204 dataType: 'json', 205 contentType: 'application/json', 206 data: data, 207 success: function (result) { 208 if (result.success) { 209 if (result.vin) self.Vin(result.vin); 210 self._suppressCascade = true; 211 self._loadingLookup = true; 212 self.LoadYears(function () { 213 self.Year(result.year.toString()); 214 self.LoadMakes(result.year.toString(), function () { 215 self._suppressCascade = true; 216 var selectedMake = self.MakeOptions().find(function (m) { return m.name.toUpperCase() === result.make.toUpperCase(); }); 217 if (selectedMake) { 218 self.Make(selectedMake.name); 219 self.LoadModels(result.year.toString(), selectedMake.id, function () { 220 self._suppressCascade = true; 221 var selectedModel = self.ModelOptions().find(function (m) { return m.name.toUpperCase() === result.model.toUpperCase(); }); 222 if (selectedModel) self.VehicleModel(selectedModel.name); 223 self._suppressCascade = false; 224 self._loadingLookup = false; 225 self.LookupPerformed(true); 226 RemoveSpinner('.vehicle-form'); 227 }); 228 } else { 229 self._suppressCascade = false; 230 self._loadingLookup = false; 231 self.LookupPerformed(true); 232 RemoveSpinner('.vehicle-form'); 233 } 234 }); 235 }); 236 } else { 237 self.LookupErrorTitle(result.errorTitle); 238 self.LookupErrorMessage(result.errorMessage); 239 self.LookupPerformed(false); 240 self.LogVehicleLookupFailed(result.failureReason || 'not_found'); 241 RemoveSpinner('.vehicle-form'); 242 } 243 }, 244 error: function () { 245 self.LookupErrorTitle(localizationHelper.error.genericError); 246 self.LookupErrorMessage(''); 247 self.LookupPerformed(false); 248 self.LogVehicleLookupFailed('service_error'); 249 RemoveSpinner('.vehicle-form'); 250 } 251 }); 252 }; 253 254 self.LogVehicleLookupFailed = function (failureReason) { 255 if (self.Mode() !== 'plate' && self.Mode() !== 'vin') return; 256 logEvent(analyticsEvent.enro_vehicle_lookup_failed, { 257 lookup_method: self.Mode(), 258 reason: failureReason, 259 enrollment_id: window.onlineInstallAnalyticsContext.enrollment_id 260 }); 261 }; 262 263 self.LogVehicleLookupAttempt = function () { 264 if (typeof logEvent !== 'function' || typeof analyticsEvent === 'undefined') return; 265 if (self.Mode() !== 'plate' && self.Mode() !== 'vin') return; 266 267 const analyticsContext = window.onlineInstallAnalyticsContext || {}; 268 logEvent(analyticsEvent.enro_vehicle_lookup_attempt, { 269 lookup_method: self.Mode(), 270 enrollment_id: analyticsContext.enrollment_id || '' 271 }); 272 }; 273 274 self.Init = function (mode, plateState, plateNumber, vin, year, make, model, color, errorTitle, errorMessage) { 275 var stateItems = self.States.map(function (s) { 276 return { text: s.text, value: s.value }; 277 }); 278 self.States = stateItems; 279 280 self._suppressCascade = true; 281 282 if (mode) self.Mode(mode); 283 if (plateState) self.PlateState(plateState); 284 if (plateNumber) self.PlateNumber(plateNumber); 285 if (vin) self.Vin(vin); 286 287 self.LoadColors(function () { self.Color(color) }); 288 289 if (mode === 'manual') { 290 self.LoadYears(function () { 291 if (year) self.Year(year); 292 if (year && make) { 293 self.LoadMakes(year, function () { 294 self._suppressCascade = true; 295 self.Make(make); 296 if (year && make) { 297 var selected = self.MakeOptions().find(function (m) { return m.name === make; }); 298 if (selected) { 299 self.LoadModels(year, selected.id, function () { 300 self._suppressCascade = true; 301 if (model) self.VehicleModel(model); 302 if (color) self.Color(color); 303 self._suppressCascade = false; 304 }); 305 } else { 306 self._suppressCascade = false; 307 } 308 } else { 309 self._suppressCascade = false; 310 } 311 }); 312 } else { 313 self._suppressCascade = false; 314 } 315 }); 316 } else if (year && make && model) { 317 self.YearOptions([year]);
318 self.MakeOptions([{ id: '', name: make }]); 319 self.ModelOptions([{ id: '', name: model }]); 320 self.Year(year); 321 self.Make(make); 322 self.VehicleModel(model); 323 if (color) self.Color(color); 324 self.LookupPerformed(true); 325 self._suppressCascade = false; 326 } else { 327 self._suppressCascade = false; 328 } 329 330 if (errorTitle) self.LookupErrorTitle(errorTitle); 331 if (errorMessage) self.LookupErrorMessage(errorMessage); 332 }; 333}
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.