1class Soumission{ 2 constructor(formID){ 3 4 self= this; 5 this.formID = formID; 6 7 this.form = jQuery('#'+formID); 8 this.loadingSpinner = jQuery('#'+this.formID+' .loadingspinner'); 9 this.loadingMessage = jQuery('#'+this.formID+' #loadingmessage') 10 this.zoneAcessoireLists = jQuery('#'+this.formID+' .zoneAcessoireLists'); 11 this.hideOnLoadElements = jQuery('#'+this.formID+' .hideOnLoad'); 12 this.servicesList = jQuery('#'+this.formID+' #service'); 13 this.inputSubmit = jQuery('#'+this.formID+' input.vxp_submit') 14 15 this.lang = this.detectLang(); 16 this.i18n = { 17 fr: { 18 loadingTitle: 'Traitement en cours', 19 processing: 'Demande en traitement...', 20 error: "Une erreur est survenue lors de l'envoi, s.v.p. réessayez plus tard", 21 close: 'Fermer', 22 ok: 'OK', 23 // Messages renvoyés par admin/ajax.php (source de vérité côté serveur) 24 serverSuccess: "Merci pour votre intérêt envers nos services. Votre message a été envoyé et sera traité dans les plus brefs délais.", 25 serverError: "Désolé, Une erreur est survenue lors du traitement de votre demande." 26 }, 27 en: { 28 loadingTitle: 'Processing', 29 processing: 'Processing your request...', 30 error: 'An error occurred while sending, please try again later', 31 close: 'Close', 32 ok: 'OK', 33 serverSuccess: "Thank you for your interest in our services. Your request has been sent and will be processed as soon as possible.", 34 serverError: "Sorry, an error occurred while processing your request." 35 } 36 }; 37 38 self.initForm(); 39 self.setEvents(); 40 41 42 43 } 44 45 detectLang(){ 46 // Marqueur fiable posé par WordPress : <html lang="en_US"> vs <html lang="fr_FR"> 47 var htmlLang = (document.documentElement.getAttribute('lang') || '').toLowerCase(); 48 if(htmlLang.indexOf('en') === 0) return 'en'; 49 // Filet de sécurité : préfixe d'URL /en/ 50 if(window.location.pathname.indexOf('/en/') === 0) return 'en'; 51 return 'fr'; 52 } 53 54 t(key){ 55 var dict = this.i18n[this.lang] || this.i18n.fr; 56 return (dict[key] !== undefined) ? dict[key] : this.i18n.fr[key]; 57 } 58 59 // Traduit le message renvoyé par le serveur (toujours en français) vers la 60 // langue de la page, sans rien changer à la requête envoyée au serveur. 61 translateServerMessage(msg){ 62 if(this.lang === 'fr' || typeof msg !== 'string') return msg; 63 var normalized = msg.trim(); 64 if(normalized === this.i18n.fr.serverSuccess) return this.i18n.en.serverSuccess; 65 if(normalized === this.i18n.fr.serverError) return this.i18n.en.serverError; 66 return msg; // message inconnu : on l'affiche tel quel 67 } 68 69 initForm(){ 70 self = this; 71 72 this.loading = new VXP_loadingModal(this.t('loadingTitle'),this.formID); 73 74 this.loadingSpinner.hide(); 75 this.cloneSelectData(); 76 this.loading.close(); 77 this.zoneAcessoireLists.hide(); 78 this.hideOnLoadElements.hide(); 79 this.servicesList.change(function(){ 80 self.resetServiceZoneList(); 81 var value = jQuery('option:selected',this).attr('value_slug'); 82 83 jQuery('#'+self.formID+' #zonelists_'+value).slideDown(); 84 }) 85 var selected = jQuery('#'+this.formID+' #service').val(); 86 if(selected != '')jQuery('#'+this.formID+' #zonelists_'+selected).show(); 87 88 jQuery('#'+this.formID+' .zoneAcessoireLists select').val(null) 89 var serviceValue = jQuery('#'+this.formID+' #service option:selected').attr('value_slug'); 90 jQuery('#'+this.formID+' #zonelists_'+serviceValue).slideDown(); 91 } 92 setEvents(){ 93 self = this; 94 jQuery('#'+this.formID).attr('action', "javascript: window.vxp_forms['"+this.formID+"'].onSubmit();"); 95 96 97 jQuery('#'+self.formID+' #service_vitre_assurance_avec').change(function(){ 98 var val = jQuery(this).val(); 99 jQuery('#'+self.formID+' #avecassurance').slideUp(); 100 if(val=='oui')jQuery('#'+self.formID+' #avecassurance').slideDown(); 101 102 }) 103 104 jQuery('#'+self.formID+' .succursaleList').change(function(){ 105 this.servicesListeIds = jQuery('option:selected',this).attr('services_ids'); 106 console.log("succursalelist change : "+this.servicesListeIds ); 107 self.resetServiceZoneList(); 108 self.setSuccursaleServices(); 109 }) 110 111 jQuery('#'+self.formID+" input[name='tel']").keyup(function() { 112 jQuery(this).val(jQuery(this).val().replace("(", "")); 113 jQuery(this).val(jQuery(this).val().replace(")", "")); 114 jQuery(this).val(jQuery(this).val().replace(/^(\d{3})(\d{3})(\d)+$/, "$1-$2-$3")); 115 }); 116 117 118 } 119 120 getURLServices( ){ 121 var url_string = window.location.href; 122 var url = new URL(url_string); 123 var vxpServices = url.searchParams.get("vxpServices"); 124 var response = false;
125 if(vxpServices ){ 126 response = vxpServices.split(','); 127 } 128 return response; 129 } 130 131 traduireServieSlugpourID(slug){ 132 var serviceElement = jQuery('#services_src option[value_slug='+slug+']'); 133 var valueID = serviceElement.attr('value_id'); 134 return valueID; 135 } 136 setSuccursaleServices(){ 137 var vxpURLServices = this.getURLServices( ); 138 139 self = this; 140 this.servicesListeIds = jQuery('#'+this.formID+' .succursaleList option:selected').attr('services_ids') 141 this.resetServiceZoneList(); 142 if(this.servicesListeIds!=undefined){ 143 144 this.servicesListeIds = this.servicesListeIds.split(",") 145 146 jQuery('#'+this.formID+' div:not(.serviceLocked) #service:not(.rdv)').val(''); 147 jQuery('#'+this.formID+" div:not(.serviceLocked) #service:not(.rdv) option").each(function() { 148 jQuery(this).remove(); 149 }); 150 var firstOption = jQuery('#'+self.formID+" #services_src option").first(); 151 firstOption.clone().appendTo('#'+self.formID+" #service:not(.rdv)"); 152 jQuery.each( self.servicesListeIds, function( index, value ) { 153 if(!vxpURLServices)jQuery('#'+self.formID+" option[value_slug=" + value + "]").clone().appendTo('#'+self.formID+" #service:not(.rdv)") 154 else { 155 156 console.log(value) 157 console.log(self.traduireServieSlugpourID(value)); 158 console.log(vxpURLServices) 159 if(vxpURLServices.includes(self.traduireServieSlugpourID(value)))jQuery('#'+self.formID+" option[value_slug=" + value + "]").clone().appendTo('#'+self.formID+" #service:not(.rdv)") 160 } 161 }) 162 } 163 164 165 } 166 167 cloneSelectData(){ 168 self = this; 169 jQuery('#'+self.formID+" #service:not(.rdv) option").each(function(){ 170 jQuery(this).clone().appendTo('#'+self.formID+" #services_src"); 171 }) 172 this.setSuccursaleServices(); 173 } 174 175 resetServiceZoneList(){ 176 177 jQuery('#'+this.formID+' div:not(.serviceLocked) .zoneAcessoireLists').hide(); 178 jQuery('#'+this.formID+' div:not(.serviceLocked) .zoneAcessoireLists select').val(null) 179 jQuery('#'+this.formID+' div:not(.serviceLocked) .zoneAcessoireLists input').val(null) 180 jQuery('#'+this.formID+' div:not(.serviceLocked) #service_vitre_assurance_avec').val(null) 181 jQuery('#'+this.formID+" div:not(.serviceLocked) .zoneAcessoireLists input:radio").attr("checked", false); 182 183 } 184 185 onSubmit() { 186 187 this.inputSubmit.prop('disabled',true); 188 window.currentFormID = this.formID; 189 //grecaptcha.reset(); flush 190 // activer pour réactiver grecaptcha : 191 // grecaptcha.execute(); 192 this.secureSubmit(); 193 } 194 195 startLoading(msg){ 196 197 198 199 this.loading.show(msg); 200 /* 201 jQuery('#loadingspinner').show(); 202 jQuery('.vxp_form').fadeTo(1,0.1);*/ 203 this.loadingMessage.html(msg); 204 this.loadingMessage.css('background-color','#ffff00') 205 206 this.loadingSpinner.show(); 207 208 } 209 210 stopLoading(msg){ 211 this.loading.close(msg); 212 this.loadingSpinner.hide() 213 this.loadingMessage.html(msg) 214 this.inputSubmit.prop('disabled',false); 215 216 } 217 218 resetForm(){ 219 var formElement = document.getElementById(this.formID); 220 if(formElement && typeof formElement.reset === 'function') formElement.reset(); 221 this.zoneAcessoireLists.hide(); 222 this.hideOnLoadElements.hide(); 223 this.loadingMessage.html(''); 224 this.loadingMessage.css('background-color',''); 225 this.loadingMessage.css('color',''); 226 } 227 228 showConfirmationModal(message, isError){ 229 jQuery('#vxp_confirmation_modal').remove(); 230 231 var overlay = jQuery( 232 "<div id='vxp_confirmation_modal' role='dialog' aria-modal='true'>"+ 233 "<div class='vxp_confirmation_box'>"+ 234 "<span class='vxp_confirmation_close' aria-label='"+this.t('close')+"' title='"+this.t('close')+"'>×</span>"+ 235 "<div class='vxp_confirmation_message'></div>"+ 236 "<div class='vxp_confirmation_actions'>"+ 237 "<div class='leNouveauBouton"+(isError?" leNouveauBouton-erreur":"")+"'>"+ 238 "<button type='button' class='vxp_confirmation_ok'>"+this.t('ok')+"</button>"+ 239 "</div>"+ 240 "</div>"+ 241 "</div>"+ 242 "</div>" 243 ); 244 245 overlay.find('.vxp_confirmation_message').html(message); 246 247 overlay.css({ 248 display: 'flex', 249 alignItems: 'center', 250 justifyContent: 'center', 251 position: 'fixed', 252 left: '0', 253 top: '0', 254 width: '100%', 255 height: '100%', 256 overflow: 'auto', 257 backgroundColor: 'rgba(0,0,0,0.5)', 258 zIndex: '99999' 259 }); 260 261 overlay.find('.vxp_confirmation_box').css({ 262 position: 'relative', 263 backgroundColor: '#ffffff', 264 color: '#222222', 265 maxWidth: '480px', 266 width: '90%', 267 margin: '20px', 268 padding: '32px 28px 24px', 269 border: isError ? '2px solid #d32f2f' : '2px solid #2e7d32', 270 borderRadius: '6px', 271 boxShadow: '0 8px 30px rgba(0,0,0,0.25)', 272 fontSize: '16px', 273 lineHeight: '1.5', 274 textAlign: 'center' 275 }); 276 277 overlay.find('.vxp_confirmation_close').css({ 278 position: 'absolute', 279 top: '10px', 280 right: '14px', 281 color: '#999999', 282 fontSize: '26px', 283 lineHeight: '1', 284 fontWeight: 'bold', 285 cursor: 'pointer' 286 }); 287 288 overlay.find('.vxp_confirmation_actions').css({ 289 marginTop: '24px', 290 textAlign: 'center' 291 }); 292 // Centre le bouton : le wrapper se réduit à la largeur du bouton et se centre 293 overlay.find('.vxp_confirmation_actions .leNouveauBouton').css({ 294 display: 'inline-block' 295 }); 296 297 // Aucun style inline sur le bouton : son apparence vient entièrement de la 298 // classe .leNouveauBouton du thème (+ .leNouveauBouton-erreur en cas d'erreur). 299 300 jQuery('body').append(overlay); 301 302 function closeModal(){ 303 jQuery(document).off('keydown.vxpConfirmation'); 304 overlay.remove(); 305 } 306 307 overlay.find('.vxp_confirmation_close').on('click', closeModal); 308 overlay.find('.vxp_confirmation_ok').on('click', closeModal); 309 overlay.on('click', function(event){ 310 if(event.target === overlay[0]) closeModal(); 311 }); 312 jQuery(document).on('keydown.vxpConfirmation', function(event){ 313 if(event.key === 'Escape' || event.keyCode === 27) closeModal(); 314 }); 315 } 316 317 serializeFieldsValues(formData){ 318 self = this; 319 var customFields_dataList = {}; 320 customFields_dataList['list']=[]; 321 jQuery('#'+this.formID+" .vxp_custom_fieldsdata").each(function() { 322 if(jQuery(this).val()){ 323 var fieldAttr = {}; 324 var element = jQuery(this); 325 326 if(element.prop('nodeName')=="SELECT") { 327 element = jQuery('option:selected', this); 328 fieldAttr['id']= element.attr('id') ? element.attr('id') : null; 329 fieldAttr['value']= element.val(); 330 fieldAttr['value_slug']= element.attr('value_slug') ? element.attr('value_slug') : null; 331 fieldAttr['value_id']= element.attr('value_id') ? element.attr('value_id') : null; 332 fieldAttr['value_wp_term_ID']= element.attr('value_wp_term_ID') ? element.attr('value_wp_term_ID') : null; 333 fieldAttr['key_id']= element.attr('key_id') ? element.attr('key_id') : null; 334 fieldAttr['key_name']= element.attr('key_name') ? element.attr('key_name') : null; 335 fieldAttr['key_slug']= element.attr('key_slug') ? element.attr('key_slug') : null; 336 fieldAttr['key_wp_term_ID']= element.attr('key_wp_term_ID') ? element.attr('key_wp_term_ID') : null; 337 fieldAttr['wp_taxonomy']= element.attr('wp_taxonomy') ? element.attr('wp_taxonomy') : null; 338 fieldAttr['slug']= element.attr('slug') ? element.attr('slug') : null; 339 340 fieldAttr['parent_name']= element.attr('parent_name') ? element.attr('parent_name') : null; 341 fieldAttr['parent_slug']= element.attr('parent_slug') ? element.attr('parent_slug') : null; 342 fieldAttr['parent_id']= element.attr('parent_id') ? element.attr('parent_id') : null; 343 fieldAttr['parent_wp_term_id']= element.attr('parent_wp_term_id') ? element.attr('parent_wp_term_id') : null; 344 345 346 }else{ 347 element = jQuery('option:selected', this); 348 fieldAttr['id']= element.attr('id') ? element.attr('id') : null; 349 fieldAttr['value']= element.val(); 350 fieldAttr['value_slug']= null; 351 fieldAttr['value_id']= null; 352 fieldAttr['value_wp_term_ID']= null; 353 fieldAttr['key_id']= element.attr('id') ? element.attr('id') : null; 354 fieldAttr['key_name']= element.attr('name') ? element.attr('name') : null; 355 fieldAttr['key_slug']= null; 356 fieldAttr['key_wp_term_ID']= null; 357 fieldAttr['wp_taxonomy']= null; 358 fieldAttr['slug']= element.attr('slug') ? element.attr('slug') : null; 359 fieldAttr['parent_name']= element.attr('parent_name') ? element.attr('parent_name') : null; 360 fieldAttr['parent_slug']= element.attr('parent_slug') ? element.attr('parent_slug') : null; 361 fieldAttr['parent_id']= element.attr('parent_id') ? element.attr('parent_id') : null; 362 fieldAttr['parent_wp_term_id']= element.attr('parent_wp_term_id') ? element.attr('parent_wp_term_id') : null; 363 364 } 365 customFields_dataList['list'].push(fieldAttr); 366 367 368 } 369 370 }); 371 jQuery('#'+this.formID+" #customfields_data").val(encodeURIComponent(JSON.stringify(customFields_dataList))); 372 } 373 374 secureSubmit(token) { 375 self = this; 376 377 var formElement = document.getElementById(this.formID); 378 this.serializeFieldsValues(); 379 var formData = new FormData(formElement); 380 /* 381 jQuery('.toserialize').each(function(){ 382 key = jQuery(this).attr('name'); 383 val = jQuery(this).val(); 384 formData.append(key,val); 385 386 })*/ 387 var params= jQuery('#'+this.formID+' .toserialize').serialize(); 388 if(this.formID=="demandesupport"){ 389 params=formData; 390 var process = false;
391 var content = false; 392 }else { 393 var process = true; 394 var content = "application/x-www-form-urlencoded; charset=UTF-8"; 395 } 396 397 this.startLoading(this.t('processing')); 398 //console.log(params) 399 400 401 402 jQuery.ajax({ 403 url: "https://www.vitrxpert.com/admin/ajax.php", 404 type: 'POST', 405 data:params, 406 processData: process, 407 contentType: content, 408 success: function(msg){ 409 try { 410 var msg = JSON.parse(msg); 411 self.stopLoading(''); 412 // Le serveur peut renvoyer un message d'erreur avec un statut 200 : on le détecte 413 var isServerError = (typeof msg === 'string' && msg.trim() === self.i18n.fr.serverError); 414 if(!isServerError) self.resetForm(); // ne vider le formulaire qu'en cas de vrai succès 415 self.showConfirmationModal(self.translateServerMessage(msg), isServerError); 416 // window.sendFaceBookEvent(eventData) 417 418 // console.log('after sendFaceBookEvent') 419 // safe to use the function 420 421 422 } catch(e) { 423 // Réponse illisible : on garde le formulaire rempli et on affiche l'erreur dans le modal 424 self.stopLoading(''); 425 self.showConfirmationModal(self.t('error'), true); 426 } 427 428 429 }, 430 error: function() { 431 // Ãchec réseau/serveur (ex. 503) : on garde le formulaire rempli et on affiche l'erreur dans le modal 432 self.stopLoading(''); 433 self.showConfirmationModal(self.t('error'), true); 434 } 435 }); 436} 437 438} 439jQuery(document).ready(function ($) { 440 window.vxp_forms = []; 441 jQuery(".vxp_form").each(function(){ 442 formID = jQuery(this).attr('id'); 443 window.vxp_forms[formID] = new Soumission(formID) 444 }) 445}) 446
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.