1(async (lawndoc) => { 2 3 function getCompanyData () { 4 return fetch(`https://api.lawnbot.biz/company/${lawnbotConfig.companyId}/bot/${lawnbotConfig.botId}`) 5 .then(response => response.json()) 6 } 7 8 let company = await getCompanyData(); 9 10 let loaded = false; 11 12 let zipCode = null; 13 14 let addiValidation = false; 15 let nameValidation = false; 16 let phoneValidation = false; 17 let emailValidation = false; 18 19 const __13__ = (str) => { 20 var input = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; 21 var output = 'NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm'; 22 var index = x => input.indexOf(x); 23 var translate = x => index(x) > -1 ? output[index(x)] : x; 24 return str.split('').map(translate).join(''); 25 } 26 const __ = 'NVmnFlPfiKpUKzfjJMNv443T53hAy11D7Cska0f'; 27 const ___ = __13__(__); 28 let autocomplete; 29 const head = lawndoc.getElementsByTagName('HEAD')[0]; 30 const body = lawndoc.getElementsByTagName('BODY')[0]; 31 let frame; 32 const toCapitalizedWords = (name) => { 33 var words = name.match(/[A-Za-z][a-z]*/g) || []; 34 35 return words.map(capitalize).join(" "); 36 } 37 38 const capitalize = (word) => { 39 return word.charAt(0).toUpperCase() + word.substring(1); 40 } 41 const generateElement = (type, properties) => { 42 43 const el = lawndoc.createElement(type); 44 for(i in properties) { 45 el[i] = properties[i]; 46 } 47 return el; 48 } 49 50 const serialize = (obj) => { 51 var str = []; 52 for (var p in obj) 53 if (obj.hasOwnProperty(p)) { 54 str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p])); 55 } 56 return str.join("&"); 57 } 58 59 const openBot = (event) => { 60 61 event.preventDefault(); 62 document.getElementById("button").value = "Submitting..." 63 64 const payload = {} 65 fields.forEach(el => { 66 if (el.id === 'googlelocate') { 67 if (el.value.indexOf('USA') > -1) { 68 el.value = el.value.replace('USA', `${zipCode} USA`) 69 } else { 70 el.value += ` ${zipCode}`; 71 } 72 } 73 payload[el.id] = el.value; 74 }) 75 76 const urlString = `?${serialize(payload)}`; 77 frame = generateElement('iframe', {id: 'bot', className: 'iframe', width: '80%', height: '100%', frameBorder: "0", src: `https://sales.lawnbot.biz/${lawnbotConfig.companyId}/${lawnbotConfig.botId}`+urlString}) 78 79 frame.onload = () => { 80 81 lawndoc.getElementById("button").value = "Submit"; 82 container.remove(); 83 console.log("LOADED"); 84 85 } 86 87 lightboxContainer.appendChild(frame); 88 console.log("apened bot to lightboxContainer"); 89 90 return false; 91 } 92 93 const generateForm = () => { 94 95 const container = generateElement('div', {id: 'lawnbot-formwrap', className: 'animate'}); 96 const leftContainer = generateElement('div', {className: 'lawnbot_left_container'}); 97 98 const title = generateElement('h1', {className: 'lawnbot_title'}) 99 const titleText = document.createTextNode("Buy Online\nin 3 Easy Steps!"); 100 101 const formInstructionsDetails = generateElement('div', {className: 'lawnbot_instructions_details'}); 102 103 const formInstructionsDiv1 = generateElement('div', {className: 'lawnbot_instructions_div'}); 104 const formImg = generateElement('img', {className: 'lawnbot_img'}); 105 formImg.src = scriptInfo.pluginUrl + "lightbox/assets/notebook.svg"; 106 const formInstructionsTitle = generateElement('h3', {className: 'lawnbot_instructions_title'}) 107 const formInstructionsTitleText = document.createTextNode("Fill The Form"); 108 const formInstructions = generateElement('p', {className: 'lawnbot_instructions'}); 109 const formInstructionsText = document.createTextNode("Fill out your information in the form below."); 110 111 const formInstructionsDiv2 = generateElement('div', {className: 'lawnbot_instructions_div'}); 112 const measureImg = generateElement('img', {className: 'lawnbot_img'}); 113 measureImg.src = scriptInfo.pluginUrl + "/lightbox/assets/Measure.svg"; 114 const measureInstructionsTitle = generateElement('h3', {className: 'lawnbot_instructions_title'}) 115 const measureInstructionsTitleText = document.createTextNode("Measure Your Lawn"); 116 const measureInstructions = generateElement('p', {className: 'lawnbot_instructions'}); 117 const measureInstructionsText = document.createTextNode("Measure your lawn online on your phone or desktop"); 118 119 const formInstructionsDiv3 = generateElement('div', {className: 'lawnbot_instructions_div'}); 120 const priceImg = generateElement('img', {className: 'lawnbot_img'}); 121 priceImg.src = scriptInfo.pluginUrl + "/lightbox/assets/price.svg";
122 const priceInstructionsTitle = generateElement('h3', {className: 'lawnbot_instructions_title'}) 123 const priceInstructionsTitleText = document.createTextNode("Get An Instant Quote!"); 124 const priceInstructions = generateElement('p', {className: 'lawnbot_instructions'}); 125 const priceInstructionsText = document.createTextNode("Get your quote within minutes."); 126 127 const clientLogo = generateElement('img', {className: 'lawnbot_clientLogo'}); 128 clientLogo.src = company.companyLogo; 129 130 131 const form = generateElement('form', {className: 'lawnbot-form', action: "#bot", id: "form"}); 132 const formDiv = generateElement('div', {className: 'lawnbot_form_container'}); 133 names = ["Name", "Address", "Phone", "Email"]; 134 const fields = ["customerName", "googlelocate", "phonenumber", "customerEmail"].map( (val, index) => { 135 136 //let placeholder = val === 'customerAddi' ? 'location' : val; 137 let placeholder = names[index]; 138 const span = generateElement('span', {className: 'lawnbot_input_field'}); 139 const input = generateElement('input', {id: val, className: 'lawnbot_input_field', type: 'text', name: `input-${val}`, value: "", size: "40", placeholder: toCapitalizedWords(placeholder), required: "required", autocomplete: `disable-autofill-${val}`}); 140 const validation_div = generateElement('div', {id: `error_${val}`, className: 'lawnbot_form_input_error'}) 141 //span.appendChild(input); 142 formDiv.appendChild(input); 143 formDiv.appendChild(validation_div); 144 return input; 145 }); 146 147 form.addEventListener('submit', openBot); 148 149 fields[0].onblur = ValidateName; 150 fields[1].onblur = ValidateAddi; 151 fields[3].onblur = ValidateEmail; 152 fields[2].onblur = ValidatePhone; 153 fields[2].onkeyup = ValidatePhone; 154 fields[3].onkeyup = ValidateEmail; 155 156 const hidden = generateElement('input', {name: 'source', id: 'source', type: 'hidden', value: 'contactForm'}); 157 fields.push(hidden); 158 form.appendChild(hidden); 159 const btn = generateElement('input', {id: 'button', className: 'lawnbot_form_button', value: 'Get My Instant Quote', type: 'submit', disabled: true}); 160 161 162 container.appendChild(leftContainer); 163 164 leftContainer.appendChild(title).appendChild(titleText); 165 166 leftContainer.appendChild(formInstructionsDetails); 167 168 formInstructionsDetails.appendChild(formInstructionsDiv1); 169 formInstructionsDiv1.appendChild(formImg); 170 formInstructionsDiv1.appendChild(formInstructionsTitle).appendChild(formInstructionsTitleText);; 171 formInstructionsDiv1.appendChild(formInstructions).appendChild(formInstructionsText); 172 173 formInstructionsDetails.appendChild(formInstructionsDiv2); 174 formInstructionsDiv2.appendChild(measureImg); 175 formInstructionsDiv2.appendChild(measureInstructionsTitle).appendChild(measureInstructionsTitleText); 176 formInstructionsDiv2.appendChild(measureInstructions).appendChild(measureInstructionsText); 177 178 formInstructionsDetails.appendChild(formInstructionsDiv3); 179 formInstructionsDiv3.appendChild(priceImg); 180 formInstructionsDiv3.appendChild(priceInstructionsTitle).appendChild(priceInstructionsTitleText); 181 formInstructionsDiv3.appendChild(priceInstructions).appendChild(priceInstructionsText); 182 183 container.appendChild(form); 184 form.appendChild(clientLogo); 185 form.appendChild(formDiv); 186 187 formDiv.appendChild(btn); 188 189 const setupGooglePlaces = () => { 190 var options = { 191 types: [] 192 } 193 let autocomplete = new google.maps.places.Autocomplete(fields[1], options); 194 google.maps.event.addListener(autocomplete, 'place_changed', function() { 195 const address = document.getElementById("googlelocate"); 196 var place = autocomplete.getPlace(); 197 console.log(place); 198 for (var i = 0; i < place.address_components.length; i++) { 199 for (var j = 0; j < place.address_components[i].types.length; j++) { 200 if (place.address_components[i].types[j] == "postal_code") { 201 zipCode = place.address_components[i].long_name; 202 const event = new Event('click'); 203 ValidateAddi(event); 204 205 } 206 } 207 } 208 209 }); 210 }; 211 212 213 if (!loaded) { 214 if(window.google && window.google.maps && window.google.maps.places) { 215 setupGooglePlaces(); 216 loaded = true; 217 } else { 218 const gpscript = generateElement('script', {src: `https://maps.googleapis.com/ma
218ps/api/js?v=3.exp&key=${___}&libraries=places`, type: 'text/javascript'}); 219 gpscript.addEventListener('load', () => { 220 setupGooglePlaces(); 221 }) 222 head.appendChild(gpscript); 223 loaded = true; 224 } 225 } 226 return {container, fields}; 227 } 228 229 // let link = generateElement('link', {rel: 'stylesheet', type: 'text/css', href: '/loader/lawnbot-lightbox.css'}); 230 const fontLink = generateElement('link', {rel: 'stylesheet', href: 'https://fonts.googleapis.com/css2?family=Nanum+Gothic&display=swap'} ); 231 const meta = generateElement('meta', {name: "viewport", content: "width=device-width, initial-scale=1.0" }); 232 head.appendChild(fontLink); 233 head.appendChild(meta); 234 // head.appendChild(link); 235 236 let {container, fields} = generateForm(); 237 let lightboxContainer = generateElement('div', {className: 'lightbox', id: 'lead-capture'}); 238 const close = generateElement('a', {href: '#!', className: 'lightboxClose'}); 239 const closeImg = generateElement('img', {className: 'lawnbot_closeImg'}); 240 closeImg.src = scriptInfo.pluginUrl + '/lightbox/assets/close.svg'; 241 242 243 close.addEventListener("click", (e) => { 244 245 e.preventDefault(); 246 if (frame) { 247 frame.remove(); 248 } 249 container.remove(); 250 lightboxContainer.remove(); 251 252 window.history.back(); 253 254 255 } ); 256 257 function enableButton(button, event) { 258 event.preventDefault(); 259 260 if (nameValidation === true && addiValidation === true && phoneValidation === true && emailValidation === true) { 261 button.disabled = false; 262 263 } else { 264 button.disabled = true; 265 } 266 } 267 268 function ValidateName(event) { 269 event.preventDefault(); 270 const field = document.getElementById("customerName"); 271 const button = document.getElementById("button"); 272 const validation = document.getElementById("error_customerName"); 273 274 if (field.value === "") { 275 field.style.border = 'red solid'; 276 validation.innerHTML = "Name Can Not Be Empty"; 277 nameValidation = false; 278 enableButton(button, event); 279 280 } else { 281 field.style.border = 'green solid'; 282 validation.innerHTML = ""; 283 nameValidation = true; 284 enableButton(button, event); 285 286 } 287 } 288 289 function ValidateAddi(event) { 290 event.preventDefault(); 291 const field = document.getElementById("googlelocate"); 292 const button = document.getElementById("button"); 293 const validation = document.getElementById("error_googlelocate"); 294 295 field.style.border = 'red solid'; 296 297 let addi = field.value; 298 299 if (zipCode === null) { 300 zipCode = addi.split(",").map(s => s.trim().match(/^\d{5}-\d{4}|\d{5}|[A-Z]\d[A-Z] \d[A-Z]\d$/)).filter(e => e); 301 if (zipCode.length) { 302 zipCode = zipCode[0][0]; 303 zipCode = zipCode.slice(zipCode.length - 5); 304 zipCode = zipCode.split(' ')[0]; 305 } 306 } 307 308 309 if (!zipCode && loaded) { 310 validation.innerHTML = "Address must contain postal code"; 311 addiValidation = false; 312 enableButton(button, event); 313 return; 314 } 315 for(var i=0; i < company.zipCodes.length; i++) { 316 if (company.zipCodes[i] === zipCode || company.zipCodes[i] === 'null') { 317 //console.log(data.zipCodes[i]); 318 // console.log('GOTTT IT'); 319 field.style.border = 'green solid'; 320 validation.innerHTML = ''; 321 addiValidation = true; 322 enableButton(button, event); 323 break; 324 } else { 325 addiValidation = false;
326 enableButton(button, event); 327 validation.innerHTML = "We currently don't service this address" 328 } 329 } 330 331 if (field.value === ""){ 332 field.style.border = 'red solid'; 333 addiValidation = false; 334 enableButton(button, event); 335 validation.innerHTML = "Address can not be empty" 336 } 337 338 } 339 340 function ValidatePhone(event) { 341 342 event.preventDefault(); 343 const field = document.getElementById("phonenumber"); 344 const button = document.getElementById("button"); 345 346 const validation = document.getElementById("error_phonenumber"); 347 348 let phone = field.value; 349 if (phone === '') { 350 validation.innerHTML = "Phone number required" 351 phoneValidation = false; 352 enableButton(button, event); 353 } 354 var v = /^\(?([0-9]{3})\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$/; 355 var v2 = /^\+(?:[0-9]â?){6,14}[0-9]$/; 356 if (v.test(phone) || v2.test(phone)) { 357 field.style.border = 'green solid'; 358 validation.innerHTML = "" 359 phoneValidation = true 360 enableButton(button, event); 361 } else { 362 field.style.border = 'red solid'; 363 phoneValidation = false; 364 enableButton(button, event); 365 validation.innerHTML = "Invalid phone number" 366 } 367 } 368 369 function ValidateEmail(event) { 370 event.preventDefault(); 371 const field = document.getElementById("customerEmail"); 372 const button = document.getElementById('button'); 373 374 const validation = document.getElementById("error_customerEmail"); 375 376 let email = field.value; 377 378 if (email === '') { 379 validation.innerHTML = "Email required"; 380 emailValidation = false; 381 enableButton(button, event); 382 } 383 384 var v = /^([a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5})$/; 385 if (v.test(email)) { 386 field.style.border = 'green solid'; 387 validation.innerHTML = ''; 388 emailValidation = true; 389 enableButton(button, event); 390 } else { 391 field.style.border = 'red solid'; 392 validation.innerHTML = 'Invalid email address'; 393 emailValidation = false; 394 enableButton(button, event); 395 } 396 397 } 398 399 launcher = (event) => { 400 event.preventDefault(); 401 body.appendChild(lightboxContainer); 402 lightboxContainer.appendChild(container); 403 lightboxContainer.appendChild(close).appendChild(closeImg); 404 window.location = '#lead-capture'; 405 } 406 407 window.lawnbotLauncher = () => { 408 const myEvent = new Event("launch"); 409 launcher(myEvent); 410 } 411 412 lawnbotTriggers.forEach(trigger => { 413 414 if (trigger[0] === '.') { 415 trigger = trigger.substring(1); 416 const triggerBtn = lawndoc.getElementsByClassName(trigger); 417 for (let x of triggerBtn) { 418 x.addEventListener('click', (event) => { 419 launcher(event) 420 }) 421 } 422 423 424 } else if (trigger[0] === '#') { 425 trigger = trigger.substring(1); 426 const triggerBtn = lawndoc.getElementById(trigger); 427 if (triggerBtn) { 428 triggerBtn.addEventListener('click', (event) => { 429 launcher(event); 430 }); 431 } 432 433 } 434 }) 435 436})(document)
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.