PageSourceSearch

https://koenenswaterworksplumbing.com/

html koenenswaterworksplumbing.com collected 2026-09-29 17:04:48 UTC 163,160 bytes, 3,443 lines download raw bytes

1
2<!DOCTYPE html>
3<html>
4<head>
5    <meta charset="utf-8" />
6    <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover, maximum-scale=1.0" />
7    <meta name="format-detection" content="telephone=no" />
8    <meta property="og:locale" content="en_US" />
9    <meta property="og:type" content="website" />
10        <meta property="og:title" content="Koenen&#39;s Water Works Plumbing Co. LLC - Burlington, WI" />
11            <meta property="og:url" content="https://koenenswaterworksplumbing.com/" />
12                <meta property="og:image" content="https://du9m0k402rjmo.cloudfront.net/images/P_37496/192e9f94-e967-4440-8e62-a13879fad1f2.jpg" />
13            <meta property="og:description" content="Koenen&#39;s Water Works Plumbing is a full-service residential and commercial plumbing, kitchen and bathroom new construction and remodeling company located in Burlington, WI and has been servicing southeastern Wisconsin area since 2021. Prior to the new name, it was previously a staple in the area for 30+ years as Bruesewitz Plumbing dba WaterWorks Plumbing. As a family owned and operated company, we are serious about ensuring your satisfaction. We offer 24/7 emergency services, sending our plumbers to you when you need them most—including Saturdays, Sundays, nights, and holidays.
14
15We provide 24-hour emergency services, plumbing maintenance, commercial plumbing, boiler installation, repair work, faucet repair and installation, new construction, in-floor heating, remodeling, and custom countertops.  We are committed to providing superior customer service and quality workmanship. Our services are designed to meet all of your plumbing, new construction and remodeling needs. From new installations and repairs to remodeling and maintenance, we are here to serve you. Call today!" />
16        <meta name="description" content="Koenen&#39;s Water Works Plumbing is a full-service residential and commercial plumbing, kitchen and bathroom new construction and remodeling company located in Burlington, WI and has been servicing southeastern Wisconsin area since 2021. Prior to the new name, it was previously a staple in the area for 30+ years as Bruesewitz Plumbing dba WaterWorks Plumbing. As a family owned and operated company, we are serious about ensuring your satisfaction. We offer 24/7 emergency services, sending our plumbers to you when you need them most—including Saturdays, Sundays, nights, and holidays.
17
18We provide 24-hour emergency services, plumbing maintenance, commercial plumbing, boiler installation, repair work, faucet repair and installation, new construction, in-floor heating, remodeling, and custom countertops.  We are committed to providing superior customer service and quality workmanship. Our services are designed to meet all of your plumbing, new construction and remodeling needs. From new installations and repairs to remodeling and maintenance, we are here to serve you. Call today!" />
19            <meta name="title" content="Koenen's Water Works Plumbing Co. LLC - Burlington WI" />
20            <meta name="keywords" content="24/7 Emergency Services,Plumbing,Plumber,Remodeler,Repair Work" />
21    <title>Koenen's Water Works Plumbing Co. LLC - Burlington, WI</title>
22    
22<script src="/Scripts/Profile/googleAnalytics.js" type="text/javascript"></script>
vendor: 112 bytes, lines 22-25
22
23    <script type="text/javascript" src="https://www.google.com/recaptcha/api.js" async defer></script>
24
25    
25<script src="https://code.jquery.com/jquery-3.5.0.min.js" integrity="sha256-xNzN2a4ltkB44Mc/Jz3pT4iU1cmeR0FkXs4pru/JxaQ=" crossorigin="anonymous"></script>
25
26    
27    
27<script>window.jQuery || document.write('
27<script src="/scripts/templates/jquery-3.5.0.min.js"><\/script>')</script>
27
28
29    
29<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
29
30    
31    
31<script>if (typeof (Popper) === 'undefined') { document.write('
31<script src="/scripts/templates/popper.min.js"><\/script>') }</script>
31
32
33    <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.1.0/css/all.css" integrity="sha384-lKuwvrZot6UHsBSfcMvOkWwlCMgc0TaWr+30HWe3a4ltaBwTZhyTEggF5tJv8tbt" crossorigin="anonymous">
34
35    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" crossorigin="anonymous">
36
37    
37<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js" integrity="sha384-mrcBkRTg0HmTfecoh1I+48Ptm7cAe18uN+3GsS5SXXGSwzpjIhJZkxEJ5jYaZmE" crossorigin="anonymous"></script>
37
38    
39    
39<script>if (typeof ($.fn.modal) === 'undefined') { document.write('
39<script src="/scripts/templates/bootstrap.min.js"><\/script>') }</script>
39
40
41    
41<script src="/Scripts/Templates/googleMaps.js" type="text/javascript"></script>
41
42    <link href="/Content/Templates/custom-bootstrap.css" type="text/css" rel="stylesheet" />
43    
43<script src="/Scripts/bootbox.min.js" type="text/javascript"></script>
43
44    
44<script src="/Scripts/Profile/jquery.barrating.1.1.4.js" type="text/javascript"></script>
44
45    
45<script src="/Scripts/Templates/cleave.min.js" type="text/javascript"></script>
45
46    
46<script src="/Scripts/Templates/cleave-phone.us.js" type="text/javascript"></script>
46
47    
47<script src="/Scripts/Templates/slick.min.js" type="text/javascript"></script>
47
48    <link href="/Content/Templates/slick.css" type="text/css" rel="stylesheet" />
49    <link href="/Content/Templates/slick-theme.css" type="text/css" rel="stylesheet" />
50    
50<script src="/Scripts/Templates/googleMapsMultiLocation.js" type="text/javascript"></script>
vendor: 66 bytes, lines 50-51
50
51    <script src="https://www.google.com/recaptcha/api.js?render=
516LcokacUAAAAAH_snk3O5bpdYwjpC5XAuXNLrJLH
vendor: 40 bytes, lines 51-52
51" type="text/javascript"></script>
52    
52<script src="https://player.vimeo.com/api/player.js" type="text/javascript"></script>
52
53
54    <link href="/Content/Templates/chatbot.css" type="text/css" rel="stylesheet" />
55
56    <meta name="viewport" content="width=device-width, user-scalable=yes,initial-scale=1, maximum-scale=2" />
57    <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
58    
59    
60    <style>
61        :root {
62            --text_color: 255, 255, 255, 1;
63            --text_color_rgba: rgba(var(--text_color));
64            --customer_color: #031733;
65            --post_text_color: 0, 0, 0, 1;
66            --post_text_color_rgba: rgba(var(--post_text_color));
67        }
68    </style>
69    <link href="/Content/Templates/template_6.css" type="text/css" rel="stylesheet" />
70
71        <link rel="canonical" href="https://koenenswaterworksplumbing.com/">
72
73
74<script type="application/ld+json">
75{
76  "@context": "https://schema.org",
77  "@graph": [
78    {
79      "@type": "LocalBusiness",
80      "@id": "https://koenenswaterworksplumbing.com/#localbusiness",
81      "name": "Koenen's Water Works Plumbing Co. LLC",
82      "url": "https://koenenswaterworksplumbing.com/",
83      "description": "Koenen's Water Works Plumbing is a full-service residential and commercial plumbing, kitchen and bathroom new construction and remodeling company located in Burlington, WI and has been servicing southeastern Wisconsin area since 2021. Prior to the new name, it was previously a staple in the area for 30+ years as Bruesewitz Plumbing dba WaterWorks Plumbing. As a family owned and operated company, we are serious about ensuring your satisfaction. We offer 24/7 emergency services, sending our plumbers to you when you need them most—including Saturdays, Sundays, nights, and holidays.  We provide 24-hour emergency services, plumbing maintenance, commercial plumbing, boiler installation, repair work, faucet repair and installation, new construction, in-floor heating, remodeling, and custom countertops.  We are committed to providing superior customer service and quality workmanship. Our services are designed to meet all of your plumbing, new construction and remodeling needs. From new installations and repairs to remodeling and maintenance, we are here to serve you. Call today!",
84      "image": "https://du9m0k402rjmo.cloudfront.net/images/P_37496/192e9f94-e967-4440-8e62-a13879fad1f2.jpg",
85      "logo": "https://du9m0k402rjmo.cloudfront.net/images/P_37496/192e9f94-e967-4440-8e62-a13879fad1f2.jpg",
86      "address": {
87        "@type": "PostalAddress",
88        "streetAddress": "1201 Milwaukee Ave, Suite B",
89        "addressLocality": "Burlington",
90        "addressRegion": "WI",
91        "postalCode": "53105",
92        "addressCountry": "US"
93      },
94      "telephone": "(262) 763-7385",
95      "email": "[email protected]",
96      "geo": {
97        "@type": "GeoCoordinates",
98        "latitude": 42.6954223,
99        "longitude": -88.2632462
100      },
101      "openingHoursSpecification": [
102        {
103          "@type": "OpeningHoursSpecification",
104          "dayOfWeek": "Monday",
105          "opens": "07:30",
106          "closes": "16:30"
107        },
108        {
109          "@type": "OpeningHoursSpecification",
110          "dayOfWeek": "Tuesday",
111          "opens": "07:30",
112          "closes": "16:30"
113        },
114        {
115          "@type": "OpeningHoursSpecification",
116          "dayOfWeek": "Wednesday",
117          "opens": "07:30",
118          "closes": "16:30"
119        },
120        {
121          "@type": "OpeningHoursSpecification",
122          "dayOfWeek": "Thursday",
123          "opens": "07:30",
124          "closes": "16:30"
125        },
126        {
127          "@type": "OpeningHoursSpecification",
128          "dayOfWeek": "Friday",
129          "opens": "07:30",
130          "closes": "16:30"
131        },
132        {
133          "@type": "OpeningHoursSpecification",
134          "dayOfWeek": "Saturday",
135          "opens": "08:00",
136          "closes": "12:00"
137        }
138      ],
139      "paymentAccepted": "Visa, MasterCard, American Express, Discover, Debit Cards, Personal Checks",
140      "sameAs": [
141        "https://www.yelp.com/biz/koenens-water-works-plumbing-burlington",
142        "https://www.facebook.com/koenenwaterworksplumbing",
143        "https://www.instagram.com/koenenswaterworksplumbing/"
144      ]
145    },
146    {
147      "@type": "WebSite",
148      "@id": "https://koenenswaterworksplumbing.com/#website",
149      "url": "https://koenenswaterworksplumbing.com/",
150      "name": "Koenen's Water Works Plumbing Co. LLC",
151      "description": "Koenen's Water Works Plumbing is a full-service residential and commercial plumbing, kitchen and bathroom new construction and remodeling company located in Burlington, WI and has been servicing southeastern Wisconsin area since 2021. Prior to the new name, it was previously a staple in the area for 30+ years as Bruesewitz Plumbing dba WaterWorks Plumbing. As a family owned and operated company, we are serious about ensuring your satisfaction. We offer 24/7 emergency services, sending our plumbers to you when you need them most—including Saturdays, Sundays, nights, and holidays.  We provide 24-hour emergency services, plumbing maintenance, commercial plumbing, boiler installation, repair work, faucet repair and installation, new construction, in-floor heating, remodeling, and custom countertops.  We are committed to providing superior customer service and quality workmanship. Our services are designed to meet all of your plumbing, new construction and remodeling needs. From new installations and repairs to remodeling and maintenance, we are here to serve you. Call today!",
152      "potentialAction": {
153        "@type": "SearchAction",
154        "target": "https://koenenswaterworksplumbing.com/?s={search_term_string}",
155        "query-input": "required name=search_term_string"
156      }
157    },
158    {
159      "@type": "WebPage",
160      "@id": "https://koenenswaterworksplumbing.com/#webpage",
161      "url": "https://koenenswaterworksplumbing.com/",
162      "name": "Koenen's Water Works Plumbing Co. LLC - Burlington, WI",
163      "description": "Koenen's Water Works Plumbing is a full-service residential and commercial plumbing, kitchen and bathroom new construction and remodeling company located in Burlington, WI and has been servicing southeastern Wisconsin area since 2021. Prior to the new name, it was previously a staple in the area for 30+ years as Bruesewitz Plumbing dba WaterWorks Plumbing. As a family owned and operated company, we are serious about ensuring your satisfaction. We offer 24/7 emergency services, sending our plumbers to you when you need them most—including Saturdays, Sundays, nights, and holidays.  We provide 24-hour emergency services, plumbing maintenance, commercial plumbing, boiler installation, repair work, faucet repair and installation, new construction, in-floor heating, remodeling, and custom countertops.  We are committed to providing superior customer service and quality workmanship. Our services are designed to meet all of your plumbing, new construction and remodeling needs. From new installations and repairs to remodeling and maintenance, we are here to serve you. Call today!",
164      "isPartOf": {
165        "@id": "https://koenenswaterworksplumbing.com/#website"
166      },
167      "about": {
168        "@id": "https://koenenswaterworksplumbing.com/#localbusiness"
169      },
170      "primaryImageOfPage": {
171        "@type": "ImageObject",
172        "url": "https://du9m0k402rjmo.cloudfront.net/images/P_37496/192e9f94-e967-4440-8e62-a13879fad1f2.jpg"
173      },
174      "breadcrumb": {
175        "@type": "BreadcrumbList",
176        "itemListElement": [
177          {
178            "@type": "ListItem",
179            "position": 1,
180            "name": "Home",
181            "item": "https://koenenswaterworksplumbing.com/"
182          }
183        ]
184      }
185    },
186    {
187      "@type": "Service",
188      "@id": "https://koenenswaterworksplumbing.com/#service",
189      "name": "Our Services",
190      "provider": {
191        "@id": "https://koenenswaterworksplumbing.com/#localbusiness"
192      },
193      "serviceType": [
194        "Plumbing Services – We provide full-service residential and commercial plumbing solutions, including expert repair, maintenance, and installation. Our team handles everything from leak diagnosis and drain piping replacement to certified RPZ testing and gas piping. With free estimates and 24-hour emergency service, we’re ready when you need us most.",
195        "Water Systems – Our specialists install and service water heaters, boilers, pressure tanks, and well pumps to ensure consistent water flow and temperature. We also offer water treatment solutions, including iron filtration and water softeners, to improve water quality and protect your plumbing system.",
196        "Sewer & Septic Solutions – We offer advanced drain cleaning and sewer video inspections to identify and resolve blockages. Our team is experienced in septic repairs and installs E-One grinder sewage pumps for efficient waste management in challenging environments.",
197        "Remodeling & Fixtures – From kitchen and bath remodels to custom cabinetry and countertops, we bring your vision to life. Our interactive showroom features Merillat cabinets and a wide selection of materials to help you design your ideal space with expert plumbing integration.",
198        "Seasonal & Specialty Services – We provide winterization services to protect your plumbing during freezing temperatures and offer pool chemical support and repair to keep your recreational systems safe and functional year-round."
199      ],
200      "description": "Professional services offered by Koenen's Water Works Plumbing Co. LLC"
201    }
202  ]
203}
204</script>
204</head>
205<body>
206    <div id="bootstrapCssTest" class="d-none"></div>
207    
207<script>
208        $(function () {
209            
210            if ($('#bootstrapCssTest').is(':visible')) {
211                $("head").prepend('<link rel="stylesheet" href="/content/templates/bootstrap.min.css">');
212            }
213        });
214    </script>
214
215
216    
217
218
219<input type="hidden" id="areaMarkers" />
220
221<!-- NAVBAR -->
222<div class="container-fullwidth fixed-top">
223    
224
225
226
227
228<header class="content-header custom-background-color d-flex flex-wrap align-items-center justify-content-between py-0 px-2">
229
230    
231        <div class="nav-image-mobile-left">
232            <a href="#home-section" id="HomeNav" onclick="DisplayPage('#homePage')">
233                <img src="https://du9m0k402rjmo.cloudfront.net/images/P_37496/192e9f94-e967-4440-8e62-a13879fad1f2.jpg" alt="navbar logo" class="d-line-block align-top nav-logo" />
234            </a>
235        </div>
236    <div class="nav-location pt-2">
237        <ul class="mx-auto p-0 header-address d-flex flex-wrap justify-content-center">
238            
239            <li class="nav-business_name text-center header-item mx-1 px-1 text-font-color">
240                Koenen&#39;s Water Works Plumbing Co. LLC
241            </li>
242
243            
244                    <li class="text-center header-item mx-1 px-1 text-font-color">
245
246                        1201 Milwaukee Ave Suite B
247                    </li>
248
249                <li class="text-center header-item mx-1 px-1 text-font-color">
250                    Burlington, WI 53105
251                </li>
252            <li class="navbar-hours-sm text-center header-item mx-1 px-1">
253                <a href="#" id="navbar-hours-sm" class="text-font-color" onclick="DisplayPage('#contactPage')"><i class="fas fa-clock fa-lg px-1 text-font-color"></i>Click Here for Hours</a>
254            </li>
255
256            
257                <li class="nav-phone-sm text-center header-item mx-1 px-1">
258                    <a id="PhoneNav" href="tel:2627637385" class="phone-nav-mobile text-font-color">
259                        <i class="fas fa-phone fa-inverse fa-xs fa-rotate-90"></i>
260                        (262) 763-7385
261                    </a>
262                </li>
263        </ul>
264    </div>
265
266
267    
268    <div class="navbar-hours pb-1 mx-auto">
269        <a href="#" id="navbar-hours" class="text-font-color" onclick="DisplayPage('#contactPage')"><i class="fas fa-clock fa-lg px-1 text-font-color"></i>Click Here for Hours</a>
270    </div>
271
272
273    
274    <div class="nav-phone-social pb-1 d-flex flex-wrap justify-content-center">
275        
276            <div class="nav-phone flex-column align-self-center mx-1 px-1 pb-1">
277                <a id="PhoneNav" href="tel:2627637385" class="phone-nav-mobile text-font-color">
278                    <i class="fas fa-phone fa-inverse fa-xs fa-rotate-90"></i>
279                    (262) 763-7385
280                </a>
281            </div>
282        <div class="nav-social mx-1 px-1">
283                <div class="mx-auto text-center d-flex flex-wrap justify-content-center">
284                                            <div class="m-1">
285                            <a class="text-font-color social-link-footer" href="https://www.facebook.com/koenenwaterworksplumbing" target="_blank" id="facebook-social-footer" title="Facebook">
286                                <i class="fab fa-facebook-f fa-lg text-font-color"></i>
287                            </a>
288                        </div>
289                                            <div class="m-1">
290                            <a class="text-font-color social-link-footer" href="https://www.yelp.com/biz/koenens-water-works-plumbing-burlington" target="_blank" id="yelp-social-footer" title="Yelp">
291                                <i class="fab fa-yelp fa-lg text-font-color"></i>
292                            </a>
293                        </div>
294                                                                <div class="m-1">
295                            <a class="text-font-color social-link-footer" href="https://www.instagram.com/koenenswaterworksplumbing/" target="_blank" id="instagram-social-footer" title="Instagram">
296                                <i class="fab fa-instagram fa-lg text-font-color"></i>
297                            </a>
298                        </div>
299                                                        </div>
300        </div>
301    </div>
302</header>
303
304
305<nav class="bg-default-color navbar navbar-light bg-light navbar-expand-xl pt-1 pb-2">
306
307    
308        <div class="nav-image bg-default-color bg-light flex-column text-center nav
308-image-desktop">
309            <a href="#home-section" class="navbar-brand ml-3" id="HomeNav" onclick="DisplayPage('#homePage')">
310                <img src="https://du9m0k402rjmo.cloudfront.net/images/P_37496/192e9f94-e967-4440-8e62-a13879fad1f2.jpg" alt="navbar logo" class="d-line-block align-top nav-logo" />
311            </a>
312        </div>
313
314    <button class="navbar-toggler nav-menu collapsed" type="button" data-toggle="collapse" data-target="#navbarToggler" aria-controls="navbarToggler" aria-expanded="false" aria-label="Toggle navigation">
315        <span class="navbar-toggler-icon"></span>
316        <span class="my-1 mx-2 close">X</span>
317    </button>
318
319    <div class="collapse navbar-collapse flex-column mx-auto" id="navbarToggler">
320        
321        <div class="d-none d-xl-block nav-section">
322            <div class="navbar-nav d-flex flex-wrap align-items-center">
323
324
325<div class="col nav-item text-center header-item mx-auto text-nowrap">            <a href="#" id="HomePageNavigationLink" class="nav-link p-3" onclick="DisplayPage('#homePage')">Home</a>
326</div><div class="col nav-item text-center header-item mx-auto text-nowrap">            <a href="#" id="AboutPageNavigationLink" class="nav-link p-3" onclick="DisplayPage('#aboutPage')">About</a>
327</div><div class="col nav-item text-center header-item mx-auto text-nowrap">            <a target="_blank" href="https://koenenswaterworksplumbing.com/optimamedia/products/P_37496/299f942e-f2df-4975-91ff-4afc48b98a3e.pdf" id="DocumentPageNavigationLink" class="nav-link p-3">We are Hiring</a>
328</div><div class="col nav-item text-center header-item mx-auto text-nowrap">            <a href="#" id="ServicesPageNavigationLink" class="nav-link p-3" onclick="DisplayPage('#servicesPage')">Services</a>
329</div><div class="col nav-item text-center header-item mx-auto text-nowrap">            <a href="#" id="PhotosNavigationLink" class="nav-link p-3" onclick="DisplayPage('#imageryPage')">Gallery</a>
330</div><div class="col nav-item text-center header-item mx-auto text-nowrap">            <a href="#" id="PostsPageNavigationLink" class="nav-link p-3" onclick="DisplayPage('#postsPage')">Posts</a>
331</div><div class="col nav-item text-center header-item mx-auto text-nowrap">            <a href="#" id="testimonialsPageNavigationLink" class="nav-link p-3" onclick="DisplayPage('#testimonialsPage')">Testimonials</a>
332</div><div class="col nav-item text-center header-item mx-auto text-nowrap">            <a href="#" id="GSVPageNavigationLink" class="nav-link p-3" onclick="DisplayPage('#gsvPage')">360 Tour</a>
333</div><div class="col nav-item text-center header-item mx-auto text-nowrap">            <a href="#" id="ContactPageNavigationLink" class="nav-link p-3" onclick="DisplayPage('#contactPage')">Contact</a>
334</div>            </div>
335        </div>
336        
337        <div class="d-xs-block d-xl-none">
338            <ul class="navbar-nav mx-auto mr-auto mt-2 mt-xl-0 mb-2">
339                    <li class="nav-item text-center header-item mr-1 ml-1">
340                        Koenen's Water Works Plumbing Co. LLC
341                    </li>
342                
343
344<li class="nav-item text-center header-item mr-1 ml-1 text-nowrap">            <a href="#" id="HomePageNavigationLink" class="nav-link p-3" onclick="DisplayPage('#homePage')">Home</a>
345</li><li class="nav-item text-center header-item mr-1 ml-1 text-nowrap">            <a href="#" id="AboutPageNavigationLink" class="nav-link p-3" onclick="DisplayPage('#aboutPage')">About</a>
346</li><li class="nav-item text-center header-item mr-1 ml-1 text-nowrap">            <a target="_blank" href="https://koenenswaterworksplumbing.com/optimamedia/products/P_37496/299f942e-f2df-4975-91ff-4afc48b98a3e.pdf" id="DocumentPageNavigationLink" class="nav-link p-3">We are Hiring</a>
347</li><li class="nav-item text-center header-item mr-1 ml-1 text-nowrap">            <a href="#" id="ServicesPageNavigationLink" class="nav-link p-3" onclick="DisplayPage('#servicesPage')">Services</a>
348</li><li class="nav-item text-center header-item mr-1 ml-1 text-nowrap">            <a href="#" id="PhotosNavigationLink" class="nav-link p-3" onclick="DisplayPage('#imageryPage')">Gallery</a>
349</li><li class="nav-item text-center header-item mr-1 ml-1 text-nowrap">            <a href="#" id="PostsPageNavigationLink" class="nav-link p-3" onclick="DisplayPage('#postsPage')">Posts</a>
350</li><li class="nav-item text-center header-item mr-1 ml-1 text-nowrap">            <a href="#" id="testimonialsPageNavigationLink" class="nav-link p-3" onclick="DisplayPage('#testimonialsPage')">Testimonials</a>
351</li><li class="nav-item text-center header-item mr-1 ml-1 text-nowrap">            <a href="#" id="GSVPageNavigationLink" class="nav-link p-3" onclick="DisplayPage('#gsvPage')">360 Tour</a>
352</li><li class="nav-item text-center header-item mr-1 ml-1 text-nowrap">            <a href="#" id="ContactPageNavigationLink" class="nav-link p-3" onclick="DisplayPage('#contactPage')">Contact</a>
353</li>            </ul>
354        </div>
355    </div>
356</nav>
357
358</div>
359
360<div id="pages" class="pages-left">
361    <!--Home Page Information-->
362    <div class="content collapse show bg-alt-color" id="homePage">
363
364<div class="d-flex flex-wrap">
365    <div class="w-100 mx-auto home-banner">
366        <div class="parallax w-100">
367                <div class="img-fluid banner-image " style="background-image: url(https://du9m0k402rjmo.
367cloudfront.net/images/P_37496/fde5518d-399a-44cc-bd74-fa1a8de66e46.jpg)"></div>
368            <div class="home-content">
369                <div class="d-flex flex-wrap justify-content-center align-items-center px-2"></div>
370            </div>
371        </div>
372    </div>
373
374    
375        <div class="d-flex align-items-center justify-content-center col-12 text-center description mx-auto slogan p-3 slogan-speakable" style="color: #4A879E; opacity: 0.7">
376            Emergency Services Available 24/7!
377        </div>
378            <div class="slider-attributes-container">
379            <div class="slider slider-attributes mx-auto">
380                    <div>
381                        <div class="image-slider-attributes-border m-5">
382                            <div class="image-slider-attributes-border-inner">
383                                <div class="image-slider-attributes custom-background-color d-flex justify-content-center align-items-center">
384                                    <span class="m-2 text-font-color">Sump Pumps</span>
385                                </div>
386                            </div>
387                        </div>
388                    </div>
389                    <div>
390                        <div class="image-slider-attributes-border m-5">
391                            <div class="image-slider-attributes-border-inner">
392                                <div class="image-slider-attributes custom-background-color d-flex justify-content-center align-items-center">
393                                    <span class="m-2 text-font-color">Water Heaters &amp; Boilers</span>
394                                </div>
395                            </div>
396                        </div>
397                    </div>
398                    <div>
399                        <div class="image-slider-attributes-border m-5">
400                            <div class="image-slider-attributes-border-inner">
401                                <div class="image-slider-attributes custom-background-color d-flex justify-content-center align-items-center">
402                                    <span class="m-2 text-font-color">Iron Filtration &amp; Water Softeners</span>
403                                </div>
404                            </div>
405                        </div>
406                    </div>
407                    <div>
408                        <div class="image-slider-attributes-border m-5">
409                            <div class="image-slider-attributes-border-inner">
410                                <div class="image-slider-attributes custom-background-color d-flex justify-content-center align-items-center">
411                                    <span class="m-2 text-font-color">Pressure Tanks &amp; Well Pumps</span>
412                                </div>
413                            </div>
414                        </div>
415                    </div>
416                    <div>
417                        <div class="image-slider-attributes-border m-5">
418                            <div class="image-slider-attributes-border-inner">
419                                <div class="image-slider-attributes custom-background-color d-flex justify-content-center align-items-center">
420                                    <span class="m-2 text-font-color">E-One Grinder Sewage Pumps</span>
421                                </div>
422                            </div>
423                        </div>
424                    </div>
425                    <div>
426                        <div class="image-slider-attributes-border m-5">
427                            <div class="image-slider-attributes-border-inner">
428                                <div class="image-slider-attributes custom-background-color d-flex justify-content-center align-items-center">
429                                    <span class="m-2 text-font-color">High-End Finishes and Fixtures</span>
430                                </div>
431                            </div>
432                        </div>
433                    </div>
434            </div>
435        </div>
436        <nav id="circle-attributes" class="navbar-attribute custom-background-color w-100">
437            <div class="w-100 d-flex flex-row justify-content-center text-center">
438                <div class="inner py-1">
439                        <div class="col nav-item text-center header-item mx-auto text-wrap">
440                            <span class="nav-link">Sump Pumps</span>
441                        </div>
442                        <div class="col nav-item text-center header-item mx-auto text-wrap">
443                            <span class="nav-link">Water Heaters &amp; Boilers</span>
444                        </div>
445                        <div class="col nav-item text-center header-item mx-auto text-wrap">
446                            <span class="nav-link">Iron Filtration &amp; Water Softeners</span>
447                        </div>
448                        <div class="col nav-item text-center header-item mx-auto text-wrap">
449                            <span class="nav-link">Pressure Tanks &amp; Well Pumps</span>
450                        </div>
451                        <div class="col nav-item text-center header-item mx-auto text-wrap">
452                            <span class="nav-link">E-One Grinder Sewage Pumps</span>
453                        </div>
454                        <div class="col nav-item text-center header-item mx-auto text-wrap">
455                            <span class="nav-link">High-End Finishes and Fixtures</span>
456                        </div>
457                </div>
458            </div>
459        </nav>
460    <div class="w-100 w-lg-75 mx-auto text-center p-4">
461            <div class="p-2 section-header text-center">
462                Established in 1978
463            </div>
464                    <div class="p-2 section-information text-center">
465                Located in Burlington, WI
466            </div>
467    </div>
468
469    
470        <div class="w-100 w-lg-75 mx-auto mt-4 mb-4">
471            <div class="slider slider-single w-100">
472                    <div class="image-slider m-2">
473                        <img alt="Image" src="https://du9m0k402rjmo.cloudfront.net/images/P_37496/9822d27a-a440-4082-bcd3-d75dd86ffc18.jpg" class="img-fluid text-center mx-auto" />
474                    </div>
475                    <div class="image-slider m-2">
476                        <img alt="Image" src="https://du9m0k402rjmo.cloudfront.net/images/P_37496/7b59338d-e022-4c31-ad97-6b1d9d8ee119.jpg" class="img-fluid text-center mx-auto" />
477                    </div>
478                    <div class="image-slider m-2">
479                        <img alt="Image" src="https://du9m0k402rjmo.cloudfront.net/images/P_37496/fc866e35-d2f8-4200-809d-eda7b64a7432.jpg" class="img-fluid text-center mx-auto" />
480                    </div>
481                    <div class="image-slider m-2">
482                        <img alt="Image" src="https://du9m0k402rjmo.cloudfront.net/images/P_37496/8c609b90-a03f-492c-bb86-958eec245e10.jpg" class="img-fluid text-center mx-auto" />
483                    </div>
484                    <div class="image-slider m-2">
485                        <img alt="Image" src="https://du9m0k402rjmo.cloudfront.net/images/P_37496/33871ee3-b0ac-4d37-ae00-b0e0e3590451.jpg" class="img-fluid text-center mx-auto" />
486                    </div>
487                    <div class="image-slider m-2">
488                        <img alt="Image" src="https://du9m0k402rjmo.cloudfront.net/images/P_37496/f54608e7-9e0c-4ce4-9021-80cc3b038433.jpg" class="img-fluid text-center mx-auto" />
489                    </div>
490                    <div class="image-slider m-2">
491                        <img alt="Image" src="https://du9m0k402rjmo.cloudfront.net/images/P_37496/dcdcf430-6cc5-497d-b3dd-90f1031cc18d.jpg" class="img-fluid text-center mx-auto" />
492                    </div>
493                    <div class="image-slider m-2">
494                        <img alt="Image" src="https://du9m0k402rjmo.cloudfront.net/images/P_37496/d30303df-a085-4560-994f-fd8574e85c54.jpg" class="img-fluid text-center mx-auto" />
495                    </div>
496                    <div class="image-slider m-2">
497                        <img alt="Image" src="https://du9m0k402rjmo.cloudfront.net/images/P_37496/1f200740-571d-4846-bb2d-90e1e8d8de35.jpg" class="img-fluid text-center mx-auto" />
498                    </div>
499                    <div class="image-slider m-2">
500                        <img alt="Image" src="https://du9m0k402rjmo.
500cloudfront.net/images/P_37496/406f4b59-1853-4702-9b5f-6da17e60b3e7.jpg" class="img-fluid text-center mx-auto" />
501                    </div>
502                    <div class="image-slider m-2">
503                        <img alt="Image" src="https://du9m0k402rjmo.cloudfront.net/images/P_37496/9bbcdf42-cf59-438b-82bd-e0ce1ff14cfa.jpg" class="img-fluid text-center mx-auto" />
504                    </div>
505                    <div class="image-slider m-2">
506                        <img alt="Image" src="https://du9m0k402rjmo.cloudfront.net/images/P_37496/362f2daf-dfeb-4236-9c80-9df5edda4f02.jpg" class="img-fluid text-center mx-auto" />
507                    </div>
508                    <div class="image-slider m-2">
509                        <img alt="Image" src="https://du9m0k402rjmo.cloudfront.net/images/P_37496/1d44e50f-d2bc-415f-9a0b-95b3dc719ee7.jpg" class="img-fluid text-center mx-auto" />
510                    </div>
511                    <div class="image-slider m-2">
512                        <img alt="Image" src="https://du9m0k402rjmo.cloudfront.net/images/P_37496/4d220349-9ea8-4f89-a169-4998b2fd38da.jpg" class="img-fluid text-center mx-auto" />
513                    </div>
514                    <div class="image-slider m-2">
515                        <img alt="Image" src="https://du9m0k402rjmo.cloudfront.net/images/P_37496/b868af7f-ad95-49b9-99b7-cfa93fa66fe1.jpg" class="img-fluid text-center mx-auto" />
516                    </div>
517                    <div class="image-slider m-2">
518                        <img alt="Image" src="https://du9m0k402rjmo.cloudfront.net/images/P_37496/70af784f-d05d-46dc-999a-23852b90c69b.jpg" class="img-fluid text-center mx-auto" />
519                    </div>
520                    <div class="image-slider m-2">
521                        <img alt="Image" src="https://du9m0k402rjmo.cloudfront.net/images/P_37496/a86ae628-5fa4-49f3-b97d-941128f3bde2.jpg" class="img-fluid text-center mx-auto" />
522                    </div>
523                    <div class="image-slider m-2">
524                        <img alt="Image" src="https://du9m0k402rjmo.cloudfront.net/images/P_37496/0ae8daef-8717-492b-a749-16f1779846e7.png" class="img-fluid text-center mx-auto" />
525                    </div>
526                    <div class="image-slider m-2">
527                        <img alt="Image" src="https://du9m0k402rjmo.cloudfront.net/images/P_37496/d61e30e7-fe2c-4a05-b4cd-f2b08e1703ee.png" class="img-fluid text-center mx-auto" />
528                    </div>
529            </div>
530            <div class="slider slider-nav w-45 mx-auto mt-3 mb-3">
531                    <div class="image-slider-thumbnail">
532                        <img alt="Image" src="https://du9m0k402rjmo.cloudfront.net/images/P_37496/9822d27a-a440-4082-bcd3-d75dd86ffc18.jpg" class="img-fluid text-center mx-auto" />
533                    </div>
534                    <div class="image-slider-thumbnail">
535                        <img alt="Image" src="https://du9m0k402rjmo.cloudfront.net/images/P_37496/7b59338d-e022-4c31-ad97-6b1d9d8ee119.jpg" class="img-fluid text-center mx-auto" />
536                    </div>
537                    <div class="image-slider-thumbnail">
538                        <img alt="Image" src="https://du9m0k402rjmo.cloudfront.net/images/P_37496/fc866e35-d2f8-4200-809d-eda7b64a7432.jpg" class="img-fluid text-center mx-auto" />
539                    </div>
540                    <div class="image-slider-thumbnail">
541                        <img alt="Image" src="https://du9m0k402rjmo.cloudfront.net/images/P_37496/8c609b90-a03f-492c-bb86-958eec245e10.jpg" class="img-fluid text-center mx-auto" />
542                    </div>
543                    <div class="image-slider-thumbnail">
544                        <img alt="Image" src="https://du9m0k402rjmo.cloudfront.net/images/P_37496/33871ee3-b0ac-4d37-ae00-b0e0e3590451.jpg" class="img-fluid text-center mx-auto" />
545                    </div>
546                    <div class="image-slider-thumbnail">
547                        <img alt="Image" src="https://du9m0k402rjmo.cloudfront.net/images/P_37496/f54608e7-9e0c-4ce4-9021-80cc3b038433.jpg" class="img-fluid text-center mx-auto" />
548                    </div>
549                    <div class="image-slider-thumbnail">
550                        <img alt="Image" src="https://du9m0k402rjmo.
550cloudfront.net/images/P_37496/dcdcf430-6cc5-497d-b3dd-90f1031cc18d.jpg" class="img-fluid text-center mx-auto" />
551                    </div>
552                    <div class="image-slider-thumbnail">
553                        <img alt="Image" src="https://du9m0k402rjmo.cloudfront.net/images/P_37496/d30303df-a085-4560-994f-fd8574e85c54.jpg" class="img-fluid text-center mx-auto" />
554                    </div>
555                    <div class="image-slider-thumbnail">
556                        <img alt="Image" src="https://du9m0k402rjmo.cloudfront.net/images/P_37496/1f200740-571d-4846-bb2d-90e1e8d8de35.jpg" class="img-fluid text-center mx-auto" />
557                    </div>
558                    <div class="image-slider-thumbnail">
559                        <img alt="Image" src="https://du9m0k402rjmo.cloudfront.net/images/P_37496/406f4b59-1853-4702-9b5f-6da17e60b3e7.jpg" class="img-fluid text-center mx-auto" />
560                    </div>
561                    <div class="image-slider-thumbnail">
562                        <img alt="Image" src="https://du9m0k402rjmo.cloudfront.net/images/P_37496/9bbcdf42-cf59-438b-82bd-e0ce1ff14cfa.jpg" class="img-fluid text-center mx-auto" />
563                    </div>
564                    <div class="image-slider-thumbnail">
565                        <img alt="Image" src="https://du9m0k402rjmo.cloudfront.net/images/P_37496/362f2daf-dfeb-4236-9c80-9df5edda4f02.jpg" class="img-fluid text-center mx-auto" />
566                    </div>
567                    <div class="image-slider-thumbnail">
568                        <img alt="Image" src="https://du9m0k402rjmo.cloudfront.net/images/P_37496/1d44e50f-d2bc-415f-9a0b-95b3dc719ee7.jpg" class="img-fluid text-center mx-auto" />
569                    </div>
570                    <div class="image-slider-thumbnail">
571                        <img alt="Image" src="https://du9m0k402rjmo.cloudfront.net/images/P_37496/4d220349-9ea8-4f89-a169-4998b2fd38da.jpg" class="img-fluid text-center mx-auto" />
572                    </div>
573                    <div class="image-slider-thumbnail">
574                        <img alt="Image" src="https://du9m0k402rjmo.cloudfront.net/images/P_37496/b868af7f-ad95-49b9-99b7-cfa93fa66fe1.jpg" class="img-fluid text-center mx-auto" />
575                    </div>
576                    <div class="image-slider-thumbnail">
577                        <img alt="Image" src="https://du9m0k402rjmo.cloudfront.net/images/P_37496/70af784f-d05d-46dc-999a-23852b90c69b.jpg" class="img-fluid text-center mx-auto" />
578                    </div>
579                    <div class="image-slider-thumbnail">
580                        <img alt="Image" src="https://du9m0k402rjmo.cloudfront.net/images/P_37496/a86ae628-5fa4-49f3-b97d-941128f3bde2.jpg" class="img-fluid text-center mx-auto" />
581                    </div>
582                    <div class="image-slider-thumbnail">
583                        <img alt="Image" src="https://du9m0k402rjmo.cloudfront.net/images/P_37496/0ae8daef-8717-492b-a749-16f1779846e7.png" class="img-fluid text-center mx-auto" />
584                    </div>
585                    <div class="image-slider-thumbnail">
586                        <img alt="Image" src="https://du9m0k402rjmo.cloudfront.net/images/P_37496/d61e30e7-fe2c-4a05-b4cd-f2b08e1703ee.png" class="img-fluid text-center mx-auto" />
587                    </div>
588            </div>
589        </div>
590            <div class="w-100 p-0 mt-4 mb-4">
591            <iframe id='gbvFrame' src="https://www.google.com/maps/embed?pb=!4v1686837467589!6m8!1m7!1sCAoSLEFGMVFpcE93M2xJQmFHRk1qQVNrY0tVQmFXZVlTc1lfZGVOSnR1RV9tWThS!2m2!1d42.69526939105222!2d-88.26339463412708!3f30.490778227980176!4f-3.414025499493107!5f0.7820865974627469" width="100%" height="450px;" style="border:0;" allowfullscreen="" loading="lazy" referrerpolicy="no-referrer-when-downgrade"></iframe>
592        </div>
593
594            <div class="w-100 mx-auto bg-image-container">
595            <div class="bg-image " style="background-image: url(https://du9m0k402rjmo.cloudfront.net/images/P_37496/f2f8d28d-4acd-4678-962b-9c68803cb4e1.jpg)"></div>
596            <div class="w-lg-40 p-3 mt-md-5 mb-md-5">
597                <div class="mx-auto p-3 testimonial-blurb">
598                    <div class="blurb-review-info">
599    <p class="paragraph-content">
600        <div class="blurb-rating m-2 mt-3">
601                    <img class="star-rating-image" src="/content/profile/images/star_yellow_5.0.png" />
602        </div>
603        <div class="blurb-authordate m-2 mb-3">
604            <span class="blurb-author">
605- Danielle            </span>
606            <span class="blurb-date">
6079/26/2026            </span>
608        </div>
609        <div class="blurb m-2 mt-3 mb-3">
610
611&quot;They helped us with a water softener and hose bib. Communication was great, the customer service was excellent, and the prices were fair. I’d absolutely schedule with them again!&quot;        </div>
612        <div class="blurb-more m-2 mt-3">
613            <div class="d-flex flex-wrap flex-column text-center mx-auto mt-1 mb-1 p-0">
614                <a id="testimonialsBlurbMore" href="#testimonialsPage" class="d-flex align-items-center justify-content-center btn btn-secondary p-2 mr-auto testimonialsBlurbMore" >
615                    See More &nbsp; <i class="fas fa-arrow-right"></i>
616                </a>
617            </div>
618        </div>
619    </p>
620</div>
621                </div>
622            </div>
623        </div>
624</div>
625    </div>
626
627    <!--About Page Information-->
628    <div class="content collapse bg-alt-color" id="aboutPage"></div>
629
630    <!--Services Page Information-->
631    <div class="content collapse bg-alt-color" id="servicesPage"></div>
632
633    <!--Testimonial Page Information-->
634    <div class="content collapse bg-alt-color" id="testimonialsPage"></div>
635
636    <!-- REVIEW MODAL -->
637    <div id="reviewFormParentContainer"></div>
638
639    <!--Contact Page Information-->
640    <div class="content collapse bg-alt-color" id="contactPage"></div>
641
642    <!--Imagery Page Information-->
643    <div class="content collapse bg-alt-color" id="imageryPage"></div>
644
645    <!--Posts Page Information-->
646        <div class="content collapse bg-alt-color" id="postsPage">
647
648
649<div class="d-flex flex-wrap">
650
651    
652    <div class="w-100 mx-auto text-center banner">
653        <div class="parallax w-100 d-flex flex-wrap justify-content-center align-items-center">
654                <div class="banner-image " style="background-image: url(https://du9m0k402rjmo.cloudfront.net/images/P_37496/d2fe696c-612a-4fb1-b37e-a4373cc1b72f.jpg)"></div>
655                    </div>
656    </div>
657
658    
659    <div class="w-100 mx-auto">
660        <div class="d-flex flex-row flex-wrap justify-content-center text-center">
661            <div class="posts-partial-content w-100">
662                
663                <div class="postsInfo" id="testimonialPostsInfo"></div>
664                <div class="text-center m-3">
665                    <button type="button" id="prevPosts" class="btn btn-light btn-md" disabled><i class="fas fa-angle-left"></i> Previous</button>
666                    <button type="button" id="nextPosts" class="btn btn-light btn-md">Next <i class="fas fa-angle-right"></i></button>
667                </div>
668            </div>
669        </div>
670    </div>
671</div>
672        </div>
673
674    <!--Locations Page Information-->
675    <div class="content collapse bg-alt-color" id="locationsPage"></div>
676
677    <!--360 Tour Page-->
678    <div class="content collapse bg-alt-color pt-3" id="gsvPage"></div>
679
680    <!--FAQ Page Information-->
681    <div class="content collapse bg-alt-color" id="faqPage"></div>
682
683    <!--Additional Content Page-->
684    <div class="content collapse bg-alt-color pt-3" id="contentPage"></div>
685
686</div> 
687
688<!--FOOTER Information-->
689<footer id="footer-container" class="footer custom-background-color">
690<div class="d-flex flex-wrap text-center justify-content-center p-3">
691    <div class="footer-content mx-auto">
692
693        <!--Payment Methods -->
694            <div id="paymentTypeDark" class="mx-auto mt-2 mb-2 text-center d-flex flex-wrap justify-content-center paymentType">
695                    <div class="m-2">
696                        <img alt="Payment Image" class="img-fluid text-center mx-auto payment-img" src="/content/Templates/images/payment/visa.png" />
697                    </div>
698                    <div class="m-2">
699                        <img alt="Payment Image" class="img-fluid text-center mx-auto payment-img" src="/content/Templates/images/payment/mastercard.png" />
700                    </div>
701                    <div class="m-2">
702                        <img alt="Payment Image" class="img-fluid text-center mx-auto payment-img" src="/content/Templates/images/payment/americanexpress.png" />
703                    </div>
704                    <div class="m-2">
705                        <img alt="Payment Image" class="img-fluid text-center mx-auto payment-img" src="/content/Templates/images/payment/discover.png" />
706                    </div>
707            </div>
708            <div id="paymentTypeLight" class="mx-auto mt-2 mb-2 text-center d-flex flex-wrap justify-content-center paymentType">
709                    <div class="m-2">
710                        <img alt="Payment Image" class="img-fluid text-center mx-auto payment-img" src="/content/Templates/images/payment/visa_white.png" />
711                    </div>
712                    <div class="m-2">
713                        <img alt="Payment Image" class="img-fluid text-center mx-auto payment-img" src="/content/Templates/images/payment/mastercard_white.png" />
714                    </div>
715                    <div class="m-2">
716                        <img alt="Payment Image" class="img-fluid text-center mx-auto payment-img" src="/content/Templates/images/payment/americanexpress_white.png" />
717                    </div>
718                    <div class="m-2">
719                        <img alt="Payment Image" class="img-fluid text-center mx-auto payment-img" src="/content/Templates/images/payment/discover_white.png" />
720                    </div>
721            </div>
722
723        <div id="footer-address">
724            <div class="d-flex flex-wrap justify-content-center pt-1">
725                <ul class="mx-auto p-0 mt-2 mt-lg-0 mb-2 business-info-footer d-flex flex-wrap justify-content-center">
726                        <li class="text-center mr-1 ml-1 pl-1 pr-1 text-font-color footer-business-name">
727                            Koenen's Water Works Plumbing Co. LLC
728                        </li>
729                                                <li class="text-center header-item mr-1 ml-1 pl-1 pr-1 text-font-color">
730
731                                1201 Milwaukee Ave Suite B
732                            </li>
733                                            <li class="text-center header-item mr-1 ml-1 pl-1 pr-1 text-font-color">
734                            Burlington, WI 53105
735                        </li>
736                </ul>
737            </div>
738        </div>
739                <div class="d-flex flex-wrap flex-column text-center mx-auto mt-1 mb-1 p-0">
740                    <a id="phoneLink" href="tel:2627637385" class="phoneLinkInput d-flex align-items-start justify-content-center btn btn-secondary p-2 mx-auto text-font-color">
741                        (262) 763-7385
742                    </a>
743                </div>
744        <div class="mt-3">
745                <div class="mx-auto mt-2 mb-2 text-center d-flex flex-wrap justify-content-center">
746                                            <div class="m-2">
747                            <a class="text-font-color social-link-footer" href="https://www.facebook.com/koenenwaterworksplumbing" target="_blank" id="facebook-social-footer" title="Facebook">
748                                <i class="fab fa-facebook-f fa-lg"></i>
749                            </a>
750                        </div>
751                                            <div class="m-2">
752                            <a class="text-font-color social-link-footer" href="https://www.yelp.com/biz/koenens-water-works-plumbing-burlington" target="_blank" id="yelp-social-footer" title="Yelp">
753                                <i class="fab fa-yelp fa-lg"></i>
754                            </a>
755                        </div>
756                                                                <div class="m-2">
757                            <a class="text-font-color social-link-footer" href="https://www.instagram.com/koenenswaterworksplumbing/" target="_blank" id="instagram-social-footer" title="Instagram">
758                                <i class="fab fa-instagram fa-lg"></i>
759                            </a>
760                        </div>
761                                                        </div>
762        </div>
763        <div class="text-center tos pt-4">
764            <a class="text-font-color" href="/Home/TermsOfUse" id="tosLink" target="_blank">Terms of Use |</a>
765            <a class="text-font-color" href="/Home/PrivacyPolicy" id="ppLink" target="_blank">Privacy Policy</a>
766        </div>
767        <div class="text-center" style="font-size: 0.75rem; color: #999; padding-top: 0.5rem;">
768            &copy; 2026 American Marketing & Publishing, L.L.C. All rights reserved. Names, logos, and other marks displayed are the property of their respective owners.
769        </div>
770    </div>
771</div>
772</footer>
773
774    <div class="accessibility-img py-2 px-2">
775        <div class="d-flex flex-wrap justify-content-center align-items-center text-center">
776            <a href="/Accessibility?domain=koenenswaterworksplumbing" target="_blank" class="dark">
777                <img src="/Content/Templates/images/accessibility_icon.png" height="60" width="42" />
778            </a>
779        </div>
780    </div>
781
782
783
784
785<div class="chatbot-toggle-container">
786  <button id="chatbot-toggle">
787    <img src="/Content/Templates/images/chat_icon.png" height="60" width="60" />
788  </button>
789</div>
790
791<!-- Chat Window -->
792<div id="chat-window">
793  <!-- Chat Header -->
794  <div class="chat-header">
795    <div class="chat-header-content">
796      <h3 class="chat-header-title">Koenen's Water Works Plumbing Co. LLC Assistant</h3>
797    </div>
798    <button id="close-chat" class="chat-close-btn" aria-label="Close chat">
799      <i class="fas fa-times"></i>
800    </button>
801  </div>
802
803  <!-- Chat Messages -->
804  <div id="chat-messages">
805    <div class="chat-message-container">
806      <div class="chat-message">
807        Hi there! How can we help you today?
808      </div>
809    </div>
810  </div>
811
812  <div id="disclaimer-info">
813    <div class="disclaimer-content">
814      <div class="disclaimer-text">
815        AI Responses not guaranteed; verify before reliance
816      </div>
817    </div>
818  </div>
819
820  <!-- Cost Display -->
821  <div id="cost-info">
822    <div class="cost-info-row">
823      <div class="cost-info-left">
824        <i class="fas fa-dollar-sign fa-xs cost-icon"></i>
825        <span id="cost-display">Cost: $0.00000</span>
826      </div>
827      <span id="percentage-display">0.0% of $0.02</span>
828    </div>
829    <div class="cost-progress-bar">
830      <div id="cost-progress"></div>
831    </div>
832  </div>
833
834  <!-- Chat Input -->
835  <div class="chat-input-container">
836    <form id="chat-form">
837      <input type="text" id="chat-input" placeholder="Type your message..." />
838      <button type="submit" id="send-message">
839        <i class="fas fa-paper-plane"></i>
840      </button>
841    </form>
842    <div id="character-count">0/250</div>
843    <div id="character-limit-message" style="display: none; color: #dc2626; font-size: 12px; margin-top: 4px;">
844      Your message is too long. Please limit your question to 250 characters or less.
845    </div>
846  </div>
847</div>
848
849<!-- Contact Form Window -->
850<div id="contact-form-window">
851  <div class="contact-form-header">
852    <h3 class="contact-form-title">Contact Form</h3>
853    <button id="close-contact-form" class="contact-form-close-btn" aria-label="Close contact form">
854      <i class="fas fa-times"></i>
855    </button>
856  </div>
857
858  <div class="contact-form-content">
859    <form id="chatbot-contact-form">
860      <input type="hidden" id="chat_captcha_alt" name="chat_captcha_alt" value="0uq+DT7YhakT55z49KBSHTQk1QA1eLuwq37R9WIJm8Ln80xBYNHNUaNcNG1Jx3Sg" />
861      <input type="hidden" id="chat_g-Recaptcha-Response-Contact" name="chat_g-Recaptcha-Response-Contact" value="" />
862      <input type="hidden" name="chat_aid" value="2016192a-be3a-414c-a879-4c87f8553d03" />
863      <input type="hidden" name="chat_contactSubject" value="FrontDesk&#8482; Contact Form" />
864      <input type="hidden" name="chat_contactAddress" value="" />
865      <input type="hidden" name="chat_contactZip" value="" />
866      <input type="hidden" name="chat_contactCity" value="" />
867      <input type="hidden" name="chat_contactState" value="" />
868
869      <div class="ai-liability mt-1 mb-1">(Messages sent through this site are subject to third party moderation and are not encrypted or secure. We always try to respond as soon as possible, but off-hours inquiries may take us a little longer to reply.)</div>
870
871      <div class="form-group">
872        <label for="chat_contactName" class="form-label">Name *</label>
873        <input type="text" id="chat_contactName" name="chat_contactName" class="form-input" required />
874      </div>
875
876      <div class="form-group">
877        <label for="chat_contactEmail" class="form-label">Email *</label>
878        <input type="email" id="chat_contactEmail" name="chat_contactEmail" class="form-input" required />
879      </div>
880
881      <div class="form-group">
882        <label for="chat_contactPhone" class="form-label">Phone</label>
883        <input type="tel" id="chat_contactPhone" name="chat_contactPhone" class="form-input" />
884      </div>
885
886      <div class="form-group">
887        <label for="chat_contactMessage" class="form-label">Message *</label>
888        <textarea id="chat_contactMessage" name="chat_contactMessage" rows="4" class="form-textarea" required></textarea>
889      </div>
890
891      <div id="classicCaptcha" class="d-flex flex-column">
892        <div class="g-recaptcha ml-auto mb-3 captcha-responsive" data-sitekey="6LeprWcUAAAAAF533Xd5p6kCrnRs0z4ceJieYgeO"></div>
893      </div>
894
895      <!-- Sticky footer section with reCAPTCHA disclaimer and submit button -->
896      <div class="form-sticky-footer">
897        <div class="grecaptcha-info">
898          This site is protected by reCAPTCHA and the Google
899          <a href="https://policies.google.com/privacy">Privacy Policy</a> and
900          <a href="https://policies.google.com/terms">Terms of Service</a> apply.
901        </div>
902        <button type="submit" id="contact-submit-btn" class="form-submit-btn">Submit</button>
903      </div>
904    </form>
905  </div>
906</div>
907
908<script>
909    // Wrap entire chatbot functionality in a namespace to prevent conflicts
910    window.ChatbotModule = (function() {
911        'use strict';
912
913        // Private variables
914        let isOpen = false;
915        let contactFormOpen = false;
916        let messages = [
917            { role: 'assistant', content: 'Hi there! How can we help you today?' }
918        ];
919        let isLoading = false;
920        let showContactForm = false;
921        let limitReached = false;
922        let apiCost = 0;
923        const maxCost = 0.5;
924        const maxQuestionLength = 250;
925
926        // Private element references
927        let $chatbotToggle;
928        let $chatWindow;
929        let $contactFormWindow;
930        let $closeChat;
931        let $closeContactForm;
932        let $chatMessages;
933        let $chatForm;
934        let $chatInput;
935        let $sendMessage;
936        let $characterCount;
937        let $costDisplay;
938        let $percentageDisplay;
939        let $costProgress;
940        let $contactForm;
941
942        // Initialize element references
943        function initializeElements() {
944            $chatbotToggle = $('#chatbot-toggle');
945            $chatWindow = $('#chat-window');
946            $contactFormWindow = $('#contact-form-window');
947            $closeChat = $('#close-chat');
948            $closeContactForm = $('#close-contact-form');
949            $chatMessages = $('#chat-messages');
950            $chatForm = $('#chat-form');
951            $chatInput = $('#chat-input');
952            $sendMessage = $('#send-message');
953            $characterCount = $('#character-count');
954            $costDisplay = $('#cost-display');
955            $percentageDisplay = $('#percentage-display');
956            $costProgress = $('#cost-progress');
957            $contactForm = $('#chatbot-contact-form');
958        }
959
960        // Initialize
961        function init() {
962            // Initialize element references
963            initializeElements();
964
965            // Load cost from localStorage
966            const savedCost = localStorage.getItem('api_cost');
967            if (savedCost) {
968                apiCost = parseFloat(savedCost);
969
970                // Check if cost limit is reached
971                if (apiCost >= maxCost) {
972                    limitReached = true;
973                    updateChatInputState();
974                }
975            }
976
977            // Initialize character count display
978            updateCharacterCount();
979
980            document.documentElement.style.setProperty('--adaptive-text-color', '#374151');
981            document.documentElement.style.setProperty('--image-invert', 'none');
982
983            setTimeout(updateTextColors, 100);
984
985            // Ensure chatbot stays on top even when modals are opened
986            $(document).on('shown.bs.modal', function (e) {
987              // Temporarily boost chatbot z-index when modals are shown
988              $('.chatbot-toggle-container').css('z-index', '2147483647');
989              $('#chat-window').css('z-index', '2147483646');
990              $('#contact-form-window').css('z-index', '2147483645');
991            });
992
993            // Set up event listeners
994            setupEventListeners();
995        }
996
997        // Event Listeners with namespacing
998        function setupEventListeners() {
999            // Remove any existing chatbot event listeners to prevent duplicates
1000            $chatbotToggle.off('.chatbot');
1001            $closeChat.off('.chatbot');
1002            $closeContactForm.off('.chatbot');
1003            $chatForm.off('.chatbot');
1004            $chatInput.off('.chatbot');
1005            $contactForm.off('.chatbot');
1006
1007            // Toggle chat window
1008            $chatbotToggle.on('click.chatbot', function(e) {
1009                e.preventDefault();
1010                e.stopPropagation();
1011                toggleChat();
1012            });
1013
1014            $closeChat.on('click.chatbot', function(e) {
1015                e.preventDefault();
1016                e.stopPropagation();
1017                closeChat();
1018            });
1019
1020            $closeContactForm.on('click.chatbot', function(e) {
1021                e.preventDefault();
1022                e.stopPropagation();
1023                hideContactForm();
1024            });
1025
1026            // Send message
1027            $chatForm.on('submit.chatbot', function (e) {
1028                e.preventDefault();
1029                e.stopPropagation();
1030
1031                // Check if submit button is disabled
1032                if ($sendMessage.prop('disabled') || $sendMessage.hasClass('disabled')) {
1033                    return false;
1034                }
1035
1036                sendMessage();
1037            });
1038
1039            // Character count - update on every keystroke
1040            $chatInput.on('input.chatbot', function(e) {
1041                // Only handle if this is specifically the chatbot input
1042                if ($(this).attr('id') === 'chat-input') {
1043                    updateCharacterCount();
1044                }
1045            });
1046
1047            // Also check on keyup to catch paste events
1048            $chatInput.on('keyup.chatbot paste.chatbot', function(e) {
1049                // Only handle if this is specifically the chatbot input
1050                if ($(this).attr('id') === 'chat-input') {
1051                    setTimeout(updateCharacterCount, 10);
1052                }
1053            });
1054
1055            // Handle "Enter" key for sending messages
1056            $chatInput.on('keydown.chatbot', function (e) {
1057                // Only handle if this is specifically the chatbot input
1058                if ($(this).attr('id') !== 'chat-input') {
1059                    return;
1060                }
1061
1062                if (e.key === 'Enter' && !e.shiftKey && !limitReached) {
1063                    e.preventDefault();
1064                    e.stopImmediatePropagation();
1065
1066                    // Check if submit button is disabled
1067                    if ($sendMessage.prop('disabled') || $sendMessage.hasClass('disabled')) {
1068                        return false;
1069                    }
1070
1071                    sendMessage();
1072                    return;
1073                }
1074            });
1075
1076            // Contact form submission
1077            $contactForm.on('submit.chatbot', function (e) {
1078                e.preventDefault();
1079                e.stopPropagation();
1080                submitContactForm();
1081            });
1082        }
1083
1084        // Toggle chat window
1085      function toggleChat() {
1086        if (!isOpen) {
1087          // Opening the chat
1088          isOpen = true;
1089
1090          // Hide toggle button on both mobile and desktop
1091          $('.chatbot-toggle-container').addClass('hide-toggle');
1092
1093          // First show the window (still off-screen)
1094          $chatWindow.show();
1095
1096          // Force a reflow to ensure the transition will work
1097          $chatWindow[0].offsetHeight;
1098
1099          // Then add the class that triggers the slide-in animation
1100          setTimeout(function () {
1101            $chatWindow.addClass('show');
1102            scrollToBottom();
1103          }, 10);
1104        } else {
1105          // Closing the chat
1106          isOpen = false;
1107
1108          // Show toggle button again
1109          $('.chatbot-toggle-container').removeClass('hide-toggle');
1110
1111          // Remove the show class to trigger slide-out animation
1112          $chatWindow.removeClass('show');
1113
1114          // Hide the window after the animation completes
1115          setTimeout(function () {
1116            $chatWindow.hide();
1117          }, 300); // Match the CSS transition duration
1118
1119          // Also hide contact form if open
1120          if (contactFormOpen) {
1121            hideContactForm();
1122          }
1123        }
1124      }
1125
1126        // Close chat window
1127      function closeChat() {
1128        if (isOpen) {
1129          isOpen = false;
1130
1131          // Show toggle button again
1132          $('.chatbot-toggle-container').removeClass('hide-toggle');
1133
1134          // Trigger slide-out animation
1135          $chatWindow.removeClass('show');
1136
1137          // Hide after animation
1138          setTimeout(function () {
1139            $chatWindow.hide();
1140          }, 300);
1141
1142          if (contactFormOpen) {
1143            hideContactForm();
1144          }
1145        }
1146      }
1147
1148        // Update character count and submit button state
1149        function updateCharacterCount() {
1150            const count = $chatInput.val().length;
1151            const remaining = maxQuestionLength - count;
1152            const $limitMessage = $('#character-limit-message');
1153
1154            if (count > maxQuestionLength) {
1155                // Over limit - disable submit button and show message
1156                $characterCount.text(`${count}/${maxQuestionLength} (${Math.abs(remaining)} over limit)`).css('color', '#dc2626');
1157                $limitMessage.text(`Your message is too long. Please limit your question to ${maxQuestionLength} characters or less. Your message is currently ${count} characters.`).show();
1158                $chatInput.addClass('over-limit');
1159
1160                // Disable submit button with proper styling
1161                $sendMessage.prop('disabled', true).addClass('disabled');
1162                $sendMessage.css({
1163                    'background-color': '#9ca3af',
1164                    'color': '#6b7280',
1165                    'cursor': 'not-allowed',
1166                    'opacity': '0.5',
1167                    'pointer-events': 'none'
1168                });
1169
1170            } else if (remaining <= 20) {
1171                // Close to limit - show warning but allow submit
1172                $characterCount.text(`${count}/${maxQuestionLength}`).css('color', '#f59e0b');
1173                $limitMessage.hide();
1174                $chatInput.removeClass('over-limit');
1175
1176                // Enable submit button and reset styling
1177                $sendMessage.prop('disabled', false).removeClass('disabled');
1178                $sendMessage.css({
1179                    'background-color': '',
1180                    'color': '',
1181                    'cursor': '',
1182                    'opacity': '',
1183                    'pointer-events': ''
1184                });
1185
1186            } else {
1187                // Within limit - normal state
1188                $characterCount.text(`${count}/${maxQuestionLength}`).css('color', '#6b7280');
1189                $limitMessage.hide();
1190                $chatInput.removeClass('over-limit');
1191
1192                // Enable submit button and reset styling
1193                $sendMessage.prop('disabled', false).removeClass('disabled');
1194                $sendMessage.css({
1195                    'background-color': '',
1196                    'color': '',
1197                    'cursor': '',
1198                    'opacity': '',
1199                    'pointer-events': ''
1200                });
1201            }
1202        }
1203
1204        // Send message
1205        function sendMessage() {
1206            const message = $chatInput.val().trim();
1207            if (!message || isLoading || limitReached) return;
1208
1209            // Double check character limit including whitespace
1210            if (message.length > maxQuestionLength) {
1211                appendMessage('assistant', `Your message is too long. Please limit your question to ${maxQuestionLength} characters or less. Your message is currently ${message.length} characters.`);
1212                return;
1213            }
1214
1215            // Add user message to chat
1216            messages.push({ role: 'user', content: message });
1217            appendMessage('user', message);
1218
1219            // Clear input
1220            $chatInput.val('');
1221            updateCharacterCount();
1222
1223            // Send to API
1224            fetchChatResponse(messages);
1225        }
1226
1227        // Fetch chat response from API
1228        function fetchChatResponse(messages) {
1229            isLoading = true;
1230            showLoadingIndicator();
1231
1232            $.ajax({
1233                url: '/Home/Chat',
1234                type: 'POST',
1235                contentType: 'application/json',
1236                data: JSON.stringify({
1237                    Messages: messages,
1238                    ProfileId: '37496'
1239                }),
1240                headers: {
1241                    'RequestVerificationToken': $('input[name="__RequestVerificationToken"]').val()
1242                },
1243                success: function (response) {
1244                    hideLoadingIndicator();
1245
1246                    if (response.error) {
1247                        appendMessage('assistant', `Error: ${response.error}`);
1248                        console.error('API Error:', response.error);
1249                        isLoading = false;
1250                        return;
1251                    }
1252
1253                    // Update cost
1254                    apiCost = response.Cost;
1255                    localStorage.setItem('api_cost', apiCost.toString());
1256
1257                    // Check if limit reached
1258                    if (response.LimitReached) {
1259                        limitReached = true;
1260                        showContactFormWindow();
1261                        appendMessage('assistant', 'Our AI chat has reached its capacity. Please use the contact form to get in touch directly with us.');
1262                    } else {
1263                        // Check if response contains contact form trigger
1264                        if (response.Message.includes('<start_contact_form>')) {
1265                            const cleanResponse = response.Message.replace('<start_contact_form>', '');
1266                            appendMessage('assistant', cleanResponse);
1267                            showContactFormWindow();
1268                        } else {
1269                            appendMessage('assistant', response.Message);
1270                        }
1271
1272                        // Add response to messages array
1273                        messages.push({ role: 'assistant', content: response.Message });
1274                    }
1275
1276                    isLoading = false;
1277                    updateChatInputState();
1278                },
1279                error: function (xhr, status, error) {
1280                    hideLoadingIndicator();
1281                    appendMessage('assistant', 'Sorry, I encountered an error. Please try again later.');
1282                    console.error('AJAX Error:', error);
1283                    isLoading = false;
1284                }
1285            });
1286        }
1287
1288        // Append message to chat
1289        function appendMessage(role, content) {
1290            content = convertMarkdownLinksToHTML(content);
1291            const rootStyles = getComputedStyle(document.documentElement);
1292            const customerColor = rootStyles.getPropertyValue('--customer_color').trim();
1293            const adaptivefontColor = rootStyles.getPropertyValue('--adaptive-text-color').trim();
1294
1295            const messageClass = role === 'user' ? 'flex-end' : 'flex-start';
1296            const bgColor = role === 'user' ? customerColor : 'white';
1297            const textColor = role === 'user' ? adaptivefontColor : '#374151';
1298            const borderRadius = role === 'user' ? 'border-bottom-right-radius: 0;' : 'border-bottom-left-radius: 0;';
1299            const border = role === 'user' ? '' : 'border: 1px solid #e5e7eb;';
1300
1301            const messageHtml = `
1302                <div style="display: flex; justify-content: ${messageClass}; margin-bottom: 16px;">
1303                    <div style="max-width: 75%; padding: 12px; border-radius: 8px; background-color: ${bgColor}; ${border} ${borderRadius} color: ${textColor}; word-wrap: break-word; overflow-wrap: break-word;">
1304                        ${content}
1305                    </div>
1306                </div>
1307            `;
1308
1309            $chatMessages.append(messageHtml);
1310            scrollToBottom();
1311        }
1312
1313        // Show loading indicator
1314        function showLoadingIndicator() {
1315            const loadingHtml = `
1316                <div id="loading-indicator" style="display: flex; justify-content: flex-start; margin-bottom: 16px;">
1317                    <div style="max-width: 75%; padding: 12px; border-radius: 8px; background-color: white; border: 1px solid #e5e7eb; color: #374151; display: flex; gap: 4px;">
1318                        <div class="loading-dot" style="width: 8px; height: 8px; background-color: #9ca3af; border-radius: 50%;"></div>
1319                        <div class="loading-dot" style="width: 8px; height: 8px; background-color: #9ca3af; border-radius: 50%;"></div>
1320                        <div class="loading-dot" style="width: 8px; height: 8px; background-color: #9ca3af; border-radius: 50%;"></div>
1321                    </div>
1322                </div>
1323            `;
1324
1325            $chatMessages.append(loadingHtml);
1326            animateLoadingDots();
1327            scrollToBottom();
1328
1329            // Disable input while loading
1330            $chatInput.prop('disabled', true);
1331            $sendMessage.prop('disabled', true);
1332        }
1333
1334        // Animate loading dots
1335        function animateLoadingDots() {
1336            if (!$("#loading-indicator").length) return;
1337
1338            $(".loading-dot").each(function (index) {
1339                var $dot = $(this);
1340                setTimeout(function () {
1341                    $dot.animate({ opacity: 0.3 }, 300)
1342                        .animate({ opacity: 1 }, 300);
1343                }, index * 200);
1344            });
1345
1346            setTimeout(function () {
1347                animateLoadingDots();
1348            }, 900);
1349        }
1350
1351        // Hide loading indicator
1352        function hideLoadingIndicator() {
1353            $('#loading-indicator').remove();
1354
1355            // Enable input after loading (unless limit reached)
1356            if (!limitReached) {
1357                $chatInput.prop('disabled', false);
1358                updateCharacterCount(); // This will set the correct submit button state
1359            }
1360        }
1361
1362        // Scroll to bottom of chat
1363        function scrollToBottom() {
1364            $chatMessages.scrollTop($chatMessages[0].scrollHeight);
1365        }
1366
1367        // Update cost display
1368        function updateCostDisplay() {
1369            $("#cost-info").show();
1370            $costDisplay.text(`Cost: $${apiCost.toFixed(5)}`);
1371
1372            const percentage = (apiCost / maxCost) * 100;
1373            $percentageDisplay.text(`${percentage.toFixed(1)}% of $${maxCost.toFixed(2)}`);
1374
1375            $costProgress.css('width', `${percentage}%`);
1376
1377            // Change progress bar color if near limit
1378            if (percentage > 80) {
1379                $costProgress.css("background-color", "#dc2626");
1380            } else {
1381                $costProgress.css("background-color", "#4f46e5");
1382            }
1383
1384            // Update chat input state
1385            updateChatInputState();
1386        }
1387
1388        // Update chat input state based on limit
1389        function updateChatInputState() {
1390            if (limitReached) {
1391                $chatInput.prop('disabled', true);
1392                $sendMessage.prop('disabled', true);
1393                $chatInput.attr('placeholder', 'Chat Unavailable.');
1394            } else {
1395                $chatInput.prop('disabled', false);
1396                updateCharacterCount(); // This will set the correct submit button state
1397                $chatInput.attr('placeholder', 'Type your message...');
1398            }
1399        }
1400
1401        // Show contact form
1402      function showContactFormWindow() {
1403        if (!contactFormOpen) {
1404          contactFormOpen = true;
1405
1406          // Hide toggle button when contact form opens
1407          $('.chatbot-toggle-container').addClass('hide-toggle');
1408
1409          if (isMobile()) {
1410            // On mobile, slide out chat and slide in contact form
1411            $chatWindow.removeClass('show');
1412            setTimeout(function () {
1413              $chatWindow.hide();
1414              $contactFormWindow.show();
1415              // Force reflow
1416              $contactFormWindow[0].offsetHeight;
1417              // Add show class for slide animation
1418              setTimeout(function () {
1419                $contactFormWindow.addClass('show');
1420                $('.contact-form-content').scrollTop(0);
1421              }, 10);
1422            }, 300);
1423          } else {
1424            // Desktop - slide chat to left and slide in contact form
1425            $chatWindow.animate({ right: '390px' }, 300);
1426            $contactFormWindow.show();
1427            setTimeout(function () {
1428              $contactFormWindow.animate({ right: '20px' }, 300);
1429            }, 50);
1430          }
1431        }
1432      }
1433
1434      // Hide contact form - slides out and chat returns to original position
1435      function hideContactForm() {
1436        if (contactFormOpen) {
1437          contactFormOpen = false;
1438
1439          if (isMobile()) {
1440            // Slide out contact form
1441            $contactFormWindow.removeClass('show');
1442
1443            setTimeout(function () {
1444              $contactFormWindow.hide();
1445              // Show chat window again if it was open
1446              if (isOpen) {
1447                $chatWindow.show();
1448                // Force reflow
1449                $chatWindow[0].offsetHeight;
1450                setTimeout(function () {
1451                  $chatWindow.addClass('show');
1452                }, 10);
1453              } else {
1454                // If chat is not open, show toggle button
1455                $('.chatbot-toggle-container').removeClass('hide-toggle');
1456              }
1457            }, 300);
1458          } else {
1459            // Desktop - animate back
1460            $contactFormWindow.animate({ right: '-370px' }, 300, function () {
1461              $contactFormWindow.hide();
1462            });
1463            $chatWindow.animate({ right: '20px' }, 300);
1464
1465            // Only show toggle if both windows are closed
1466            if (!isOpen) {
1467              $('.chatbot-toggle-container').removeClass('hide-toggle');
1468            }
1469          }
1470        }
1471      }
1472
1473      // Submit contact form
1474        function submitContactForm() {
1475            const name = $('#chat_contactName').val();
1476            const email = $('#chat_contactEmail').val();
1477            const phone = $('#chat_contactPhone').val();
1478            const message = $('#chat_contactMessage').val();
1479
1480            // Basic validation
1481            if (!name || !email || !message) {
1482                alert('Please fill out all required fields.');
1483                return;
1484            }
1485
1486            // Email validation
1487            const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
1488            if (!emailRegex.test(email)) {
1489                alert('Please enter a valid email address.');
1490                return;
1491            }
1492
1493            // Message length validation
1494            if (message.length < 10) {
1495                alert('Your message must be at least 10 characters long.');
1496                return;
1497            }
1498
1499            // Disable form during submission
1500            $('#contact-submit-btn').prop('disabled', true).text('Sending...');
1501
1502            var form = $("#chatbot-contact-form");
1503
1504            // Execute reCAPTCHA before submitting
1505            grecaptcha.ready(function() {
1506                grecaptcha.execute('6LcokacUAAAAAH_snk3O5bpdYwjpC5XAuXNLrJLH', {action: 'contact_us'}).then(function(token) {
1507                    // Set the reCAPTCHA token
1508                    $("#chat_g-Recaptcha-Response-Contact").val(token);
1509
1510                    // Submit the form with reCAPTCHA token
1511                    $.ajax({
1512                        url: "/Home/ChatContactPost",
1513                        type: 'POST',
1514                        data: form.serialize(),
1515                        success: function (response) {
1516                            if (typeof response === 'string' && response.indexOf('{"message":') != -1) {
1517                                var jsonData = JSON.parse(response);
1518                                if (jsonData.success) {
1519                                    appendMessage('assistant', 'Thanks for providing your information! We will get back to you soon.');
1520                                    hideContactForm();
1521
1522                                    // Reset the form
1523                                    $('#chat_contactName').val('');
1524                                    $('#chat_contactEmail').val('');
1525                                    $('#chat_contactPhone').val('');
1526                                    $('#chat_contactMessage').val('');
1527                                } else {
1528                                    alert(jsonData.message || 'There was an error processing your request.');
1529                                }
1530                            } else if (response.success) {
1531                                appendMessage('assistant', 'Thanks for providing your information! We will get back to you soon.');
1532                                hideContactForm();
1533
1534                                // Reset the form
1535                                $('#chat_contactName').val('');
1536                                $('#chat_contactEmail').val('');
1537                                $('#chat_contactPhone').val('');
1538                                $('#chat_contactMessage').val('');
1539
1540                            } else {
1541                                alert(response.message || 'There was an error processing your request.');
1542                            }
1543
1544                            $('#contact-submit-btn').prop('disabled', false).text('Submit');
1545                        },
1546                        error: function (xhr, status, error) {
1547                            alert('Failed to submit your information. Please try again.');
1548                            console.error('AJAX Error:', error);
1549                            $('#contact-submit-btn').prop('disabled', false).text('Submit');
1550                        }
1551                    });
1552                });
1553            });
1554        }
1555
1556        function convertMarkdownLinksToHTML(text) {
1557            return text.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (match, linkText, url) => {
1558                // Add target="_blank" for http/https links
1559                if (url.startsWith('http://') || url.startsWith('https://')) {
1560                    return `<a href="${url}" target="_blank" rel="noopener noreferrer">${linkText}</a>`;
1561                }
1562                // Keep tel: and mailto: links as-is
1563                return `<a href="${url}">${linkText}</a>`;
1564            });
1565        }
1566
1567        function getLuminance(hex) {
1568            // Remove # if present
1569            hex = hex.replace('#', '');
1570
1571            // Convert hex to RGB
1572            const r = parseInt(hex.substr(0, 2), 16) / 255;
1573            const g = parseInt(hex.substr(2, 2), 16) / 255;
1574            const b = parseInt(hex.substr(4, 2), 16) / 255;
1575
1576            // Calculate relative luminance
1577            const rLum = r <= 0.03928 ? r / 12.92 : Math.pow((r + 0.055) / 1.055, 2.4);
1578            const gLum = g <= 0.03928 ? g / 12.92 : Math.pow((g + 0.055) / 1.055, 2.4);
1579            const bLum = b <= 0.03928 ? b / 12.92 : Math.pow((b + 0.055) / 1.055, 2.4);
1580
1581            return 0.2126 * rLum + 0.7152 * gLum + 0.0722 * bLum;
1582        }
1583
1584        function isLightColor(hex) {
1585            const luminance = getLuminance(hex);
1586            return luminance > 0.5; // Threshold for light vs dark
1587        }
1588
1589        function updateTextColors() {
1590            const rootStyles = getComputedStyle(document.documentElement);
1591            let customerColor = rootStyles.getPropertyValue('--customer_color').trim();
1592
1593            // Check if customer color is not set or is empty
1594            if (!customerColor || customerColor === '') {
1595                const defaultColor = '#f3f3f3';
1596
1597                // Set the default customer color
1598                document.documentElement.style.setProperty('--customer_color', defaultColor);
1599                customerColor = defaultColor;
1600            }
1601
1602            const isLight = isLightColor(customerColor);
1603            const textColor = isLight ? '#000000b3' : '#ffffff';
1604
1605            const $chatbotToggle = $('#chatbot-toggle');
1606            if (isLight) {
1607                $chatbotToggle.removeClass('dark-background').addClass('light-background');
1608            } else {
1609                $chatbotToggle.removeClass('light-background').addClass('dark-background');
1610            }
1611
1612            // Update the CSS custom property
1613            document.documentElement.style.setProperty('--adaptive-text-color', textColor);
1614        }
1615
1616        function isMobile() {
1617            return window.innerWidth <= 768;
1618        }
1619
1620        // Public interface
1621        return {
1622            init: init
1623        };
1624    })();
1625
1626    // Initialize the chatbot module when document is ready
1627    $(document).ready(function () {
1628        if (window.ChatbotModule) {
1629            window.ChatbotModule.init();
1630        }
1631    });
1632</script>
1632
1633<!-- Modal -->
1634<div class="modal" id="carouselImageryPhotoModal">
1635    <div class="modal-dialog modal-dialog-centered modal-lg">
1636        <div class="modal-content">
1637            <div class="modal-header"><button type="button" class="close" data-dismiss="modal">&times;</button></div>
1638            <div class="modal-body">
1639                    <div class="w-100 w-lg-75 mx-auto mt-4 mb-4">
1640                        <div class="slider slider-imagery w-100">
1641                                <div class="image-slider m-2">
1642                                    <img alt="Image" src="https://du9m0k402rjmo.cloudfront.net/images/P_37496/9822d27a-a440-4082-bcd3-d75dd86ffc18.jpg" class="img-fluid text-center mx-auto" />
1643                                </div>
1644                                <div class="image-slider m-2">
1645                                    <img alt="Image" src="https://du9m0k402rjmo.cloudfront.net/images/P_37496/7b59338d-e022-4c31-ad97-6b1d9d8ee119.jpg" class="img-fluid text-center mx-auto" />
1646                                </div>
1647                                <div class="image-slider m-2">
1648                                    <img alt="Image" src="https://du9m0k402rjmo.cloudfront.net/images/P_37496/fc866e35-d2f8-4200-809d-eda7b64a7432.jpg" class="img-fluid text-center mx-auto" />
1649                                </div>
1650                                <div class="image-slider m-2">
1651                                    <img alt="Image" src="https://du9m0k402rjmo.cloudfront.net/images/P_37496/8c609b90-a03f-492c-bb86-958eec245e10.jpg" class="img-fluid text-center mx-auto" />
1652                                </div>
1653                                <div class="image-slider m-2">
1654                                    <img alt="Image" src="https://du9m0k402rjmo.cloudfront.net/images/P_37496/33871ee3-b0ac-4d37-ae00-b0e0e3590451.jpg" class="img-fluid text-center mx-auto" />
1655                                </div>
1656                                <div class="image-slider m-2">
1657                                    <img alt="Image" src="https://du9m0k402rjmo.cloudfront.net/images/P_37496/f54608e7-9e0c-4ce4-9021-80cc3b038433.jpg" class="img-fluid text-center mx-auto" />
1658                                </div>
1659                                <div class="image-slider m-2">
1660                                    <img alt="Image" src="https://du9m0k402rjmo.cloudfront.net/images/P_37496/dcdcf430-6cc5-497d-b3dd-90f1031cc18d.jpg" class="img-fluid text-center mx-auto" />
1661                                </div>
1662                                <div class="image-slider m-2">
1663                                    <img alt="Image" src="https://du9m0k402rjmo.cloudfront.net/images/P_37496/d30303df-a085-4560-994f-fd8574e85c54.jpg" class="img-fluid text-center mx-auto" />
1664                                </div>
1665                                <div class="image-slider m-2">
1666                                    <img alt="Image" src="https://du9m0k402rjmo.cloudfront.net/images/P_37496/1f200740-571d-4846-bb2d-90e1e8d8de35.jpg" class="img-fluid text-center mx-auto" />
1667                                </div>
1668                                <div class="image-slider m-2">
1669                                    <img alt="Image" src="https://du9m0k402rjmo.cloudfront.net/images/P_37496/406f4b59-1853-4702-9b5f-6da17e60b3e7.jpg" class="img-fluid text-center mx-auto" />
1670                                </div>
1671                                <div class="image-slider m-2">
1672                                    <img alt="Image" src="https://du9m0k402rjmo.cloudfront.net/images/P_37496/9bbcdf42-cf59-438b-82bd-e0ce1ff14cfa.jpg" class="img-fluid text-center mx-auto" />
1673                                </div>
1674                                <div class="image-slider m-2">
1675                                    <img alt="Image" src="https://du9m0k402rjmo.cloudfront.net/images/P_37496/362f2daf-dfeb-4236-9c80-9df5edda4f02.jpg" class="img-fluid text-center mx-auto" />
1676                                </div>
1677                                <div class="image-slider m-2">
1678                                    <img alt="Image" src="https://du9m0k402rjmo.
1678cloudfront.net/images/P_37496/1d44e50f-d2bc-415f-9a0b-95b3dc719ee7.jpg" class="img-fluid text-center mx-auto" />
1679                                </div>
1680                                <div class="image-slider m-2">
1681                                    <img alt="Image" src="https://du9m0k402rjmo.cloudfront.net/images/P_37496/4d220349-9ea8-4f89-a169-4998b2fd38da.jpg" class="img-fluid text-center mx-auto" />
1682                                </div>
1683                                <div class="image-slider m-2">
1684                                    <img alt="Image" src="https://du9m0k402rjmo.cloudfront.net/images/P_37496/b868af7f-ad95-49b9-99b7-cfa93fa66fe1.jpg" class="img-fluid text-center mx-auto" />
1685                                </div>
1686                                <div class="image-slider m-2">
1687                                    <img alt="Image" src="https://du9m0k402rjmo.cloudfront.net/images/P_37496/70af784f-d05d-46dc-999a-23852b90c69b.jpg" class="img-fluid text-center mx-auto" />
1688                                </div>
1689                                <div class="image-slider m-2">
1690                                    <img alt="Image" src="https://du9m0k402rjmo.cloudfront.net/images/P_37496/a86ae628-5fa4-49f3-b97d-941128f3bde2.jpg" class="img-fluid text-center mx-auto" />
1691                                </div>
1692                                <div class="image-slider m-2">
1693                                    <img alt="Image" src="https://du9m0k402rjmo.cloudfront.net/images/P_37496/0ae8daef-8717-492b-a749-16f1779846e7.png" class="img-fluid text-center mx-auto" />
1694                                </div>
1695                                <div class="image-slider m-2">
1696                                    <img alt="Image" src="https://du9m0k402rjmo.cloudfront.net/images/P_37496/d61e30e7-fe2c-4a05-b4cd-f2b08e1703ee.png" class="img-fluid text-center mx-auto" />
1697                                </div>
1698                        </div>
1699                    </div>
1700            </div>
1701        </div>
1702    </div>
1703</div>
1704
1705<!-- Modal -->
1706<div class="modal" id="carouselImageryVideoModal">
1707    <div class="modal-dialog modal-dialog-centered modal-xl">
1708        <div class="modal-content">
1709            <div class="modal-header"><button type="button" class="close" data-dismiss="modal">&times;</button></div>
1710            <div class="modal-body">
1711            </div>
1712        </div>
1713    </div>
1714</div>
1715
1716<div id="loadingImg" class="loader" style="display:none !important">
1717    <i class="fas fa-circle"></i>
1718    <i class="fas fa-circle"></i>
1719    <i class="fas fa-circle"></i>
1720</div>
1721
1722<script type="text/javascript">
1723    var isMobile = false;
1724    var isTablet = false;
1725    var pageSize = 5;
1726    var pageIndex = 0;
1727    var notReputation = false;
1728    var hasbanner = true;
1729    var keepPostUp = false;
1730    var listOfSites = "";
1731    var numOfReviews = 131;
1732    var numOfFilteredReviews = 131;
1733    var testimonialPageBackgroundColor = '#031733';
1734    var numOfPosts = 20;
1735    var postsPageIndex = 0;
1736    var geocode = null;
1737    var isSubmittingReview = false; //global flag to track submission
1738
1739    $(document).ready(function () {
1740
1741        if ($(window).width() < 576) {
1742            $("#gallerysection").addClass("pr-3");
1743            $("#gallerysection").addClass("pl-3");
1744        }
1745        else {
1746            $("#gallerysection").removeClass("pr-3");
1747            $("#gallerysection").removeClass("pl-3");
1748        }
1749
1750        if($("#contact_us_phone").length > 0){
1751            var cleave = new Cleave('#contact_us_phone', {
1752                phone: true,
1753                phoneRegionCode: 'US'
1754            });
1755        }
1756
1757        // Load the review modal async on page load
1758        $.get('/Home/GetReviewModalContent', { id: 37496, template: "Template_6"}, function (data) {
1759            if (data != "") {
1760                $("#reviewFormParentContainer").append(data);
1761                $('#starRating').barrating({
1762                    theme: 'bootstrap-stars',
1763                    deselectable: true,
1764                    onSelect: function (value, text, event) {
1765                        $('.br-widget').removeClass('error');
1766                        $('.alert').alert('close');
1767                    }
1768                });
1769
1770            }
1771        });
1772
1773        checkMobile();
1774        checkTablet();
1775        bgSlider();
1776        initializeCarousel();
1777        checkHashRoute();
1778
1779        PauseVideoPlayer();
1780
1781        if(hasbanner){
1782            GetPostsBanner();
1783        }
1784
1785        $(window).on('hashchange', function(){
1786            checkHashRoute();
1787        });
1788
1789        document.addEventListener("visibilitychange", function () {
1790            if (document["hidden"]) {
1791                PauseVideoPlayer();
1792            }
1793        });
1794
1795        var navMain = $("#navbarToggler");
1796        navMain.on("click", "a", null, function () {
1797            navMain.collapse('hide');
1798        });
1799
1800        $(window).scroll(function () {
1801            var scroll = $(window).scrollTop();
1802            if (('True' == 'False') || ('True' == 'True' && window.outerWidth > 767.98)) { /*false=center/true=left*/
1803                if (scroll > 150){
1804                    $(".content").addClass("page-section-adjust");
1805                    $(".nav-logo").addClass("nav-logo-adjust");
1806                    $(".nav-location").addClass("nav-item-adjust");
1807                }
1808                else if(scroll <= 150){
1809                    $(".content").removeClass("page-section-adjust");
1810                    $(".nav-logo").removeClass("nav-logo-adjust");
1811                    $(".nav-location").removeClass("nav-item-adjust");
1812                }
1813            }
1814        });
1815
1816        $("#carouselImageryVideoModal").on('shown.bs.modal', function (e) {
1817            $("video").each(function () { this.pause() }); //stop html5 video from playing
1818        });
1819
1820        $("#carouselImageryVideoModal").on('hidden.bs.modal', function (e) {
1821            $("video").each(function () { this.pause() }); //stop html5 video from playing
1822            $('.slider-video').slick('unslick'); //destroy slider to prevent video from playing after closing
1823        });
1824
1825        $(document).on("click", "#btnContactPost", function (e) {
1826            $("#btnContactPost").prop('disabled', true);
1827            $("#btnContactPost").css('font-weight', 'normal');
1828            contactUsPost(e);
1829        });
1830
1831
1832        var analyticsCategory = "Desktop";
1833        if (isMobile == true) {
1834            analyticsCategory = "Mobile";
1835        }
1836
1837        if (testimonialPageBackgroundColor != null && testimonialPageBackgroundColor != '' && testimonialPageBackgroundColor != "#F5F5F5") {
1838            //set footer background color
1839            $('.custom-background-color').css('background-color', testimonialPageBackgroun
1839dColor);
1840            //set footer text color appropriately
1841            setFooterColor(testimonialPageBackgroundColor);
1842        }
1843        else {
1844            //set footer background color to white
1845            var white = "#FFFFFF";
1846            $('.custom-background-color').css('background-color', white);
1847            //set footer text color appropriately
1848            setFooterColor(white);
1849        }
1850
1851        $("#HomePageNavigationLink").click(function(e){
1852            $('html, body').animate({ scrollTop: 0 }, 'fast');
1853        });
1854
1855        $(".business-name").click(function(e){
1856            $('html, body').animate({ scrollTop: 0 }, 'fast');
1857        });
1858
1859        $(".testimonialsBlurbMore").click(function(e){
1860            $('html, body').animate({ scrollTop: 0 }, 'fast');
1861        });
1862
1863        $('#starRating').barrating({
1864            theme: 'bootstrap-stars',
1865            deselectable: true,
1866            onSelect: function (value, text, event) {
1867                $('.br-widget').removeClass('error');
1868                $('.alert').alert('close');
1869            }
1870        });
1871
1872        if(numOfPosts > 0){
1873            GetPostsData(0);
1874        }
1875
1876        $(document).on('click', "#nextPosts", function (e) {
1877            ScrollForPosts(e);
1878            GetPostsData(1);
1879        });
1880
1881        $(document).on('click', "#prevPosts", function (e) {
1882            ScrollForPosts(e);
1883            GetPostsData(-1);
1884        });
1885
1886        $(document).on('click', "#postReview", function (e) {
1887            e.preventDefault();
1888            e.stopPropagation();
1889
1890            if (isSubmittingReview) {
1891                console.log('Review submission already in progress - blocking duplicate submission');
1892                return false;
1893            }
1894
1895            var $button = $(this);
1896            var $form = $("#postReviewForm");
1897            var $modal = $("#reviewFormSection");
1898
1899            isSubmittingReview = true;
1900            console.log('Starting review submission');
1901
1902            setProcessingState($button, $form, true);
1903
1904            var alertType = "success";
1905
1906            if(validateReview("#postReview")) {
1907                console.log('Review validation passed');
1908                ShowLoading();
1909
1910                grecaptcha.ready(function() {
1911                    grecaptcha.execute('6LcokacUAAAAAH_snk3O5bpdYwjpC5XAuXNLrJLH', {action: 'testimonial_review'}).then(function(token) {
1912                        $("#g-Recaptcha-Response-Review").attr("value", token);
1913
1914                        var rating = null;
1915                        var selectElement = document.getElementById('starRating');
1916                        var selectRating = selectElement ? selectElement.value : null;
1917                        var selectedOption = $('#starRating option:selected').val();
1918                        var barRating = null;
1919                        var reviewerAlias = $('#review_alias').val() || '';
1920                        var reviewHeading = $('#review_heading').val() || '';
1921                        var antiForgeryToken = $('input[name="__RequestVerificationToken"]').val();
1922                        var recaptchaToken = $('#g-Recaptcha-Response-Review').val();
1923                        var timeToPost = $('#phoneNumber_alternative').val();
1924
1925                        var reviewText = $('#review').val() || '';
1926                        var profileId = 37496;
1927
1928                        console.log('Trying to get rating value...');
1929
1930                        var selectRating = $('#starRating')[0] ? $('#starRating')[0].value : null;
1931                        console.log('Select element direct value:', selectRating);
1932
1933                        var jqueryRating = $('#starRating').val();
1934                        console.log('jQuery val() result:', jqueryRating, typeof jqueryRating);
1935
1936                        if (typeof $('#starRating').barrating === 'function') {
1937                            try {
1938                                var barResult = $('#starRating').barrating('show');
1939
1940                                if (barResult && typeof barResult === 'string') {
1941                                    barRating = barResult;
1942                                } else if (barResult && typeof barResult === 'number') {
1943                                    barRating = barResult.toString();
1944                                }
1945                            } catch (e) {
1946                                console.log('Error getting barrating value:', e);
1947                            }
1948                        }
1949
1950                        var selectedOption = $('#starRating option:selected').val();
1951                        console.log('Selected option value:', selectedOption);
1952
1953                        var jqueryResult = $('#starRating').val();
1954                        var jqueryRating = null;
1955
1956                        if (jqueryResult && typeof jqueryResult === 'string') {
1957                            jqueryRating = jqueryResult;
1958                        } else if (jqueryResult && typeof jqueryResult === 'number') {
1959                            jqueryRating = jqueryResult.toString();
1960                        }
1961
1962                        if (barRating && barRating !== "" && barRating !== "0") {
1963                            rating = barRating;
1964                        } else if (selectRating && selectRating !== "" && selectRating !== "0") {
1965                            rating = selectRating;
1966                        } else if (selectedOption && selectedOption !== "" && selectedOption !== "0") {
1967                            rating = selectedOption;
1968                        } else if (jqueryRating && jqueryRating !== "" && jqueryRating !== "0") {
1969                            rating = jqueryRating;
1970                        }
1971
1972                        if (rating && typeof rating !== 'string') {
1973                            console.log('WARNING: Rating is not a string, converting:', rating, typeof rating);
1974                            rating = String(rating);
1975                        }
1976
1977                        if (rating && typeof rating === 'object') {
1978                            console.error('CRITICAL ERROR: Rating is still an object!', rating);
1979                            rating = null;
1980                        }
1981
1982                        console.log('Validation check - rating found:', rating, typeof rating);
1983                        console.log('Final rating value:', rating, typeof rating);
1984
1985                        console.log('Form values before sending:');
1986                        console.log('- Review text:', reviewText);
1987                        console.log('- Rating:', rating);
1988                        console.log('- Profile ID:', profileId);
1989                        console.log('- Reviewer alias:', reviewerAlias);
1990                        console.log('- Review heading:', reviewHeading);
1991                        console.log('- Anti-forgery token:', antiForgeryToken ? 'Present' : 'Missing');
1992
1993                        // Build form data
1994                        var formDataArray = [
1995                            { name: 'profile_id', value: profileId },
1996                            { name: 'review', value: reviewText },
1997                            { name: 'review_rating', value: rating },
1998                            { name: 'reviewer_alias', value: reviewerAlias },
1999                            { name: 'review_heading', value: reviewHeading },
2000                            { name: '__RequestVerificationToken', value: antiForgeryToken },
2001                            { name: 'g-Recaptcha-Response-Review', value: recaptchaToken },
2002                            { name: 'phoneNumber_alternative', value: timeToPost },
2003                            { name: '_t', value: new Date().getTime() }
2004                        ];
2005
2006                        var formData = formDataArray
2007                            .filter(item => item.value !== undefined && item.value !== null && item.value !== '')
2008                            .map(item => encodeURIComponent(item.name) + '=' + encodeURIComponent(item.value))
2009                            .join('&');
2010
2011                        console.log('Manual form data built:', formData);
2012
2013                        $.ajax({
2014                            url: "/Home/ReviewPost",
2015                            type: "POST",
2016                            data: formData,
2017                            contentType: "application/x-www-form-urlencoded; charset=UTF-8",
2018                            dataType: "json",
2019                            success: function(data) {
2020                                console.log('Review submission response:', data);
2021
2022                                if (!data.message || data.message.trim() === '') {
2023                                    data.message = data.success ?
2024                                        'Thank you for your review! It has been submitted successfully.' :
2025                                        'There was an issue submitting your review. Please check all fields and try again.';
2026                                }
2027
2028                                alertType = data.success ? "success" : "warning";
2029
2030                                if (!data.success) {
2031                                    recaptchaReviewIncomplete();
2032                                    showClassicCaptcha("review");
2033                                }
2034
2035                                $form.find('.alert').remove();
2036
2037                                var alertHtml = '<div class="alert alert-' + alertType + ' alert-dismissible" role="alert">' +
2038                                                '<button type="button" class="close" data-dismiss="alert" aria-label="Close">' +
2039                                                '<span aria-hidden="true">&times;</span></button>' +
2040                                                data.message + '</div>';
2041
2042                                $form.prepend(alertHtml);
2043
2044                                $modal.find('.modal-body').scrollTop(0);
2045
2046                                if(alertType === "success") {
2047                                    // Auto-hide modal after showing success message
2048                                    setTimeout(function () {
2049                                        $modal.modal('hide');
2050                                        ClearReviewFields();
2051                                    }, 3000);
2052                                }
2053
2054                                // Fade out alert after delay
2055                                setTimeout(function() {
2056                                    $form.find('.alert').fadeOut(500, function() {
2057                                        $(this).remove();
2058                                    });
2059                                }, 6000);
2060                            },
2061                            error: function(xhr, status, error) {
2062                                console.error('AJAX Error:', status, error);
2063                                console.error('Response Text:', xhr.responseText);
2064
2065                                $form.find('.alert').remove();
2066                                var errorHtml = '<div class="alert alert-danger alert-dismissible" role="alert">' +
2067                                                '<button type="button" class="close" data-dismiss="alert" aria-label="Close">' +
2068                                                '<span aria-hidden="true">&times;</span></button>' +
2069                                                'An error occurred while submitting your review. Please try again.</div>';
2070                                $form.prepend(errorHtml);
2071
2072                                $modal.find('.modal-body').scrollTop(0);
2073                            },
2074                            complete: function() {
2075                                // Reset states
2076                                console.log('Resetting processing state');
2077                                setProcessingState($button, $form, false);
2078                                HideLoading();
2079                                isSubmittingReview = false;
2080                                console.log('Review submission completed');
2081                            }
2082                        });
2083
2084                    }).catch(function(error) {
2085                        console.error('reCAPTCHA Error:', error);
2086
2087                        $form.find('.alert').remove();
2088                        var captchaErrorHtml = '<div class="alert alert-danger alert-dismissible" role="alert">
2088' +
2089                                                '<button type="button" class="close" data-dismiss="alert" aria-label="Close">' +
2090                                                '<span aria-hidden="true">&times;</span></button>' +
2091                                                'Security verification failed. Please refresh the page and try again.</div>';
2092                        $form.prepend(captchaErrorHtml);
2093
2094                        $modal.find('.modal-body').scrollTop(0);
2095                        setProcessingState($button, $form, false);
2096                        HideLoading();
2097                        isSubmittingReview = false;
2098                    });
2099                });
2100            } else {
2101                console.log('Review validation failed');
2102
2103                var missingFields = [];
2104                if (!$('#review').val() || $('#review').val().trim() === '') {
2105                    missingFields.push('review text');
2106                }
2107
2108                var rating = null;
2109                var selectRating = $('#starRating')[0] ? $('#starRating')[0].value : null;
2110                var jqueryRating = $('#starRating').val();
2111                var selectedOption = $('#starRating option:selected').val();
2112                var barRating = null;
2113
2114                if (typeof $('#starRating').barrating === 'function') {
2115                    try {
2116                        barRating = $('#starRating').barrating('show');
2117                    } catch (e) {
2118                        // Ignore error
2119                    }
2120                }
2121
2122                if (barRating && barRating !== "" && barRating !== "0") {
2123                    rating = barRating;
2124                } else if (selectRating && selectRating !== "" && selectRating !== "0") {
2125                    rating = selectRating;
2126                } else if (selectedOption && selectedOption !== "" && selectedOption !== "0") {
2127                    rating = selectedOption;
2128                } else if (typeof jqueryRating === 'string' && jqueryRating !== "" && jqueryRating !== "0") {
2129                    rating = jqueryRating;
2130                }
2131
2132                console.log('Validation check - rating found:', rating);
2133
2134                if (!rating || rating === "" || rating === "0") {
2135                    missingFields.push('rating');
2136                }
2137
2138                var validationMessage = 'Please fill out the following required fields: ' + missingFields.join(' and ') + '.';
2139                console.log('Validation message:', validationMessage);
2140
2141                $form.find('.alert').remove();
2142                var validationHtml = '<div class="alert alert-warning alert-dismissible" role="alert">' +
2143                                    '<button type="button" class="close" data-dismiss="alert" aria-label="Close">' +
2144                                    '<span aria-hidden="true">&times;</span></button>' +
2145                                    validationMessage + '</div>';
2146                $form.prepend(validationHtml);
2147
2148                $modal.find('.modal-body').scrollTop(0);
2149                setProcessingState($button, $form, false);
2150                isSubmittingReview = false;
2151
2152                return false;
2153            }
2154        });
2155
2156        $('#reviewFormSection').on('hidden.bs.modal', function () {
2157            console.log('Modal hidden - resetting submission state');
2158            isSubmittingReview = false;
2159            setProcessingState($("#postReview"), $("#postReviewForm"), false);
2160            $(this).find('.alert').remove();
2161        });
2162
2163        $('#reviewFormSection').on('show.bs.modal', function () {
2164            console.log('Modal shown - ensuring clean state');
2165            isSubmittingReview = false;
2166            setProcessingState($("#postReview"), $("#postReviewForm"), false);
2167
2168            $("#postReview").prop('disabled', false);
2169            $("#postReview").css('font-weight', 'bold');
2170
2171            setTimeout(function () {
2172                console.log('=== STAR RATING DEBUG ===');
2173                console.log('Star rating element:', $('#starRating')[0]);
2174                console.log('Star rating jQuery object:', $('#starRating'));
2175                console.log('Star rating direct value:', $('#starRating')[0] ? $('#starRating')[0].value : 'N/A');
2176                console.log('Star rating jQuery val():', $('#starRating').val());
2177                console.log('Star rating selected option:', $('#starRating option:selected').val());
2178                console.log('Barrating plugin available:', typeof $('#starRating').barrating === 'function');
2179                if (typeof $('#starRating').barrating === 'function') {
2180                    try {
2181                        console.log('Barrating current value:', $('#starRating').barrating('show'));
2182                    } catch (e) {
2183                        console.log('Error getting barrating value:', e);
2184                    }
2185                }
2186                console.log('=== END STAR RATING DEBUG ===');
2187            }, 100);
2188        });
2189
2190        // Prevent modal from closing during submission
2191        $('#reviewFormSection').on('hide.bs.modal', function (e) {
2192            if (isSubmittingReview) {
2193                console.log('Preventing modal close during submission');
2194                e.preventDefault();
2195                return false;
2196            }
2197        });
2198
2199        $('a').on('click', function () {
2200            if (this.id !== "undefined" && this.id !== "") {
2201                gtag('event', 'Link Click', {
2202                    'event_category': analyticsCategory,
2203                    'event_label': this.id
2204                });
2205            }
2206        });
2207
2208        $('#PhoneNav').on('click', function () {
2209            gtag('event', 'Link Click', {
2210                'event_category': analyticsCategory,
2211                'event_label': "CustomerBusinessPhoneLinkTemplate6"
2212            });
2213        });
2214        $('.phoneLinkInput').on('click', function () {
2215            gtag('event', 'Link Click', {
2216                'event_category': analyticsCategory,
2217                'event_label': "CustomerBusinessPhoneLinkTemplate6-1"
2218            });
2219        });
2220        $('#contactPhoneLink').on('click', function () {
2221            gtag('event', 'Link Click', {
2222                'event_category': analyticsCategory,
2223                'event_label': "CustomerBusinessPhoneLinkTemplate6-2"
2224            });
2225        });
2226        $('#contactPrimaryPhoneLink').on('click', function () {
2227            gtag('event', 'Link Click', {
2228                'event_category': analyticsCategory,
2229                'event_label': "CustomerBusinessPhoneLinkTemplate6-3"
2230            });
2231        });
2232        $('#contactSecondaryPhoneLink').on('click', function () {
2233            gtag('event', 'Link Click', {
2234                'event_category': analyticsCategory,
2235                'event_label': "CustomerBusinessPhoneLinkTemplate6-4"
2236            });
2237        });
2238        $('#contactMobilePhoneLink').on('click', function () {
2239            gtag('event', 'Link Click', {
2240                'event_category': analyticsCategory,
2241                'event_label': "CustomerBusinessPhoneLinkTemplate6-5"
2242            });
2243        });
2244        $('#contactFaxPhoneLink').on('click', function () {
2245            gtag('event', 'Link Click', {
2246                'event_category': analyticsCategory,
2247                'event_label': "CustomerBusinessPhoneLinkTemplate6-6"
2248            });
2249        });
2250        $('#contactTollfreePhoneLink').on('click', function () {
2251            gtag('event', 'Link Click', {
2252                'event_category': analyticsCategory,
2253                'event_label': "CustomerBusinessPhoneLinkTemplate6-7"
2254            });
2255        });
2256        $('#contactPhoneC1').on('click', function () {
2257            gtag('event', 'Link Click', {
2258                'event_category': analyticsCategory,
2259                'event_label': "CustomerContactPhoneLinkTemplate6-8"
2260            });
2261        });
2262        $('#contactPhoneC2').on('click', function () {
2263            gtag('event', 'Link Click', {
2264                'event_category': analyticsCategory,
2265                'event_label': "CustomerContactPhoneLinkTemplate6-9"
2266            });
2267        });
2268        $('#contactPhoneC3').on('click', function () {
2269            gtag('event', 'Link Click', {
2270                'event_category': analyticsCategory,
2271                'event_label': "CustomerContactPhoneLinkTemplate6-10"
2272            });
2273        });
2274        $('#contactPhoneC4').on('click', function () {
2275            gtag('event', 'Link Click', {
2276                'event_category': analyticsCategory,
2277                'event_label': "CustomerContactPhoneLinkTemplate6-11"
2278            });
2279        });
2280        $('#contactPhoneC5').on('click', function () {
2281            gtag('event', 'Link Click', {
2282                'event_category': analyticsCategory,
2283                'event_label': "CustomerContactPhoneLinkTemplate6-12"
2284            });
2285        });
2286        $('#contactEmail').on('click', function () {
2287            gtag('event', 'Link Click', {
2288                'event_category': analyticsCategory,
2289                'event_label': "CustomerBusinessEmailLinkTemplate6"
2290            });
2291        });
2292        $('#writeReviewBt').on('click', function () {
2293            gtag('event', 'Button Click', {
2294                'event_category': analyticsCategory,
2295                'event_label': "WriteReviewButtonTemplate6"
2296            });
2297        });
2298        $(document).on('click', '#postReview', function () {
2299            gtag('event', 'Button Click', {
2300                'event_category': analyticsCategory,
2301                'event_label': "PostReviewButtonTemplate6"
2302            });
2303        });
2304        $('#nextReview').on('click', function () {
2305            gtag('event', 'Button Click', {
2306                'event_category': analyticsCategory,
2307                'event_label': "ShowNextReviewsButtonTemplate6"
2308            });
2309        });
2310        $('#prevReview').on('click', function () {
2311            gtag('event', 'Button Click', {
2312                'event_category': analyticsCategory,
2313                'event_label': "ShowPreviousReviewsButtonTemplate6"
2314            });
2315        });
2316        $('#google-social').on('click', function () {
2317            gtag('event', 'Link Click', {
2318                'event_category': analyticsCategory,
2319                'event_label': "CustomerGoogleSocialLinkTemplate6-1"
2320            });
2321        });
2322        $('#facebook-social').on('click', function () {
2323            gtag('event', 'Link Click', {
2324                'event_category': analyticsCategory,
2325                'event_label': "CustomerFacebookSocialLinkTemplate6-1"
2326            });
2327        });
2328        $('#yelp-social').on('click', function () {
2329            gtag('event', 'Link Click', {
2330                'event_category': analyticsCategory,
2331                'event_label': "CustomerYelpSocialLinkTemplate6-1"
2332            });
2333        });
2334        $('#twitter-social').on('click', function () {
2335            gtag('event', 'Link Click', {
2336                'event_category': analyticsCategory,
2337                'event_label': "CustomerTwitterSocialLinkTemplate6-1"
2338            });
2339        });
2340        $('#linkedin-social').on('click', function () {
2341            gtag('event', 'Link Click', {
2342                'event_category': analyticsCategory,
2343                'event_label': "CustomerLinkedinSocialLinkTemplate6-1"
2344            });
2345        });
2346        $('#instagram-social').on('click', function () {
2347            gtag('event', 'Link Click', {
2348                'event_category': analyticsCategory,
2349                'event_label': "CustomerInstagramSocialLinkTemplate6-1"
2350            });
2351        });
2352        $('#google-social-footer').on('click', function () {
2353            gtag('event', 'Link Click', {
2354                'event_category': analyticsCategory,
2355                'event_label': "CustomerGoogleSocialLinkTemplate6-2"
2356            });
2357        });
2358        $('#facebook-social-footer').on('click', function () {
2359            gtag('event', 'Link Click', {
2360                'event_category': analyticsCategory,
2361                'event_label': "CustomerFacebookSocialLinkTemplate6-2"
2362            });
2363        });
2364        $('#yelp-social-footer').on('click', function () {
2365            gtag('event', 'Link Click', {
2366                'event_category': analyticsCategory,
2367                'event_label': "CustomerYelpSocialLinkTemplate6-2"
2368            });
2369        });
2370        $('#twitter-social-footer').on('click', function () {
2371            gtag('event', 'Link Click', {
2372                'event_category': analyticsCategory,
2373                'event_label': "CustomerTwitterSocialLinkTemplate6-2"
2374            });
2375        });
2376        $('#linkedin-social-footer').on('click', function () {
2377            gtag('event', 'Link Click', {
2378                'event_category': analyticsCategory,
2379                'event_label': "CustomerLinkedinSocialLinkTemplate6-2"
2380            });
2381        });
2382        $('#instagram-social-footer').on('click', function () {
2383            gtag('event', 'Link Click', {
2384                'event_category': analyticsCategory,
2385                'event_label': "CustomerInstagramSocialLinkTemplate6-2"
2386            });
2387        });
2388        $('#contactEmailFooter').on('click', function () {
2389            gtag('event', 'Link Click', {
2390                'event_category': analyticsCategory,
2391                'event_label': "CustomerBusinessEmailLinkTemplate6-2"
2392            });
2393        });
2394        $('#btnContactPost').on('click', function () {
2395            gtag('event', 'Link Click', {
2396                'event_category': analyticsCategory,
2397                'event_label': "CustomerContactLeadPostTemplate6"
2398            });
2399        });
2400        $("#external-review-link").on('click', function () {
2401            gtag('event', 'Link Click', {
2402                'event_category': analyticsCategory,
2403                'event_label': "CustomerExternalReviewLinkTemplate6"
2404            });
2405        });
2406        $('#video').on('click', function () {
2407            gtag('event', 'Video Click', {
2408                'event_category': analyticsCategory,
2409                'event_label': "CustomerVideoTemplate6"
2410            });
2411        });
2412        $('#website-social').on('click', function () {
2413            gtag('event', 'Link Click', {
2414                'event_category': analyticsCategory,
2415                'event_label': "CustomerWebsiteSocialLinkTemplate6-1"
2416            });
2417        });
2418        $('#website-social-footer').on('click', function () {
2419            gtag('event', 'Link Click', {
2420                'event_category': analyticsCategory,
2421                'event_label': "CustomerWebsiteSocialLinkTemplate6-2"
2422            });
2423        });
2424        $('#photos-image-element').on('click', function () {
2425            gtag('event', 'Link Click', {
2426                'event_category': analyticsCategory,
2427                'event_label': "CustomerWebsiteImageryPhotoTemplate6"
2428            });
2429        });
2430        $('#HomePageNavigationLink').on('click', function () {
2431            gtag('event', 'Link Click', {
2432                'event_category': analyticsCategory,
2433                'event_label': "CustomerHomePageNavLinkTemplate6"
2434            });
2435        });
2436        $('#ContactPageNavigationLink').on('click', function () {
2437            gtag('event', 'Link Click', {
2438                'event_category': analyticsCategory,
2439                'event_label': "CustomerContactPageNavLinkTemplate6"
2440            });
2441        });
2442        $('#PhotosNavigationLink').on('click', function () {
2443            gtag('event', 'Link Click', {
2444                'event_category': analyticsCategory,
2445                'event_label': "CustomerPhotosPageNavLinkTemplate6"
2446            });
2447        });
2448        $('#testimoinalsPageNavigationLink').on('click', function () {
2449            gtag('event', 'Link Click', {
2450                'event_category': analyticsCategory,
2451                'event_label': "CustomerTestimonialsPageNavLinkTemplate6"
2452            });
2453        });
2454        $('#ServicesPageNavigationLink').on('click', function () {
2455            gtag('event', 'Link Click', {
2456                'event_category': analyticsCategory,
2457                'event_label': "CustomerServicesPageNavLinkTemplate6"
2458            });
2459        });
2460        $('#AboutPageNavigationLink').on('click', function () {
2461            gtag('event', 'Link Click', {
2462                'event_category': analyticsCategory,
2463                'event_label': "CustomerAboutPageNavLinkTemplate6"
2464            });
2465        });
2466        $('#GSVPageNavigationLink').on('click', function () {
2467            gtag('event', 'Link Click', {
2468                'event_category': analyticsCategory,
2469                'event_label': "CustomerGSVTourPageNavLinkTemplate3"
2470            });
2471        });
2472        //unable to directly track cross domain iFrame clicks. Track only first click on the iFrame itself
2473        var monitor = setInterval(function () {
2474            var elem = document.activeElement;
2475            if (elem && elem.tagName == "IFRAME" && elem.id == "googleMapEmbed") {
2476                gtag('event', 'iFrame Click', {
2477                    'event_category': analyticsCategory,
2478                    'event_label': "GoogleDirectionsTemplate6"
2479                });
2480                clearInterval(monitor);
2481            }
2482        }, 1000);
2483    });
2484
2485    var servicesRendered = false;
2486    var aboutRendered = false;
2487    var testimonialsRendered = false;
2488    var contactRendered = false;
2489    var photosRendered = false;
2490    var locationsRendered = false;
2491    var gsvRendered = false;
2492    var faqRendered = false;
2493    var contentRendered = false;
2494
2495    function DisplayPage(page) {
2496
2497        PauseVideoPlayer();
2498
2499        if (!$(page).hasClass("show")) {
2500            $("#pages div.collapse.show").collapse("hide");
2501        }
2502        $(page).collapse("show");
2503
2504        if(page == "#homePage")
2505        {
2506            var carousel = $(".slick-slider");
2507            if(carousel != null)
2508            {
2509                carousel.slick('refresh');
2510            }
2511        }
2512
2513        if (page == "#testimonialsPage") {
2514             // Load Testimonials via Ajax if not already loaded
2515            if (!testimonialsRendered) {
2516                ShowLoading();
2517                $.get('/Home/GetTestimonialsContent', {id: 37496, template: "Template_6"}, function (data) {
2518                    if (data != "")
2519                    {
2520                        $("#testimonialsPage").append(data);
2521                    }
2522                }).always(function() {
2523                    HideLoading();
2524                    testimonialsRendered = true;
2525                    GetReviewData(0);
2526                });
2527            }
2528
2529            $("html, body").animate({ scrollTop: 0 }, "fast");
2530        }
2531
2532        if (page == "#aboutPage") {
2533            // Load About via Ajax if not already loaded
2534            if (!aboutRendered) {
2535                ShowLoading();
2536                $.get('/Home/GetAboutContent', { id: 37496, template: "Template_6"}, function (data) {
2537                    if (data != "")
2538                    {
2539                        $("#aboutPage").append(data);
2540                        $.getScript("https://maps.googleapis.com/maps/api/js?key=AIzaSyB2UoPWVWPR8WrIFK_zqJ5nTN1NvGm9dqY&callback=initMap");
2541                    }
2542                }).always(function() {
2543                    HideLoading();
2544                    aboutRendered = true;
2545                });
2546            }
2547        }
2548
2549        if (page == "#servicesPage") {
2550            // Load Services via Ajax if not already loaded
2551            if (!servicesRendered) {
2552                ShowLoading();
2553                $.get('/Home/GetServicesContent', { id: 37496, template: "Template_6"}, function (data) {
2554                    if (data != "")
2555                    {
2556                        $("#servicesPage").append(data);
2557                    }
2558                }).always(function() {
2559                    HideLoading();
2560                    servicesRendered = true;
2561                });
2562            }
2563        }
2564
2565        if (page == "#imageryPage") {
2566            // Load photos via Ajax if not already loaded
2567            if (!photosRendered) {
2568                ShowLoading();
2569                $.get('/Home/GetPhotosContent', { id: 37496, template: "Template_6"}, function (data) {
2570                    if (data != "")
2571                    {
2572                        $("#imageryPage").append(data);
2573                    }
2574                }).always(function() {
2575                    HideLoading();
2576                    photosRendered = true;
2577                });
2578            }
2579        }
2580
2581        if (page == "#contactPage") {
2582            // Load Contact via Ajax if not already loaded
2583            if (!contactRendered) {
2584                ShowLoading();
2585                $.get('/Home/GetContactContent', { id: 37496, template: "Template_6"}, function (data) {
2586                    if (data != "")
2587                    {
2588                        $("#contactPage").append(data);
2589                    }
2590                }).always(function() {
2591                    HideLoading();
2592                    contactRendered = true;
2593                });
2594            }
2595        }
2596
2597         if (page == "#locationsPage") {
2598            // Load Locations via Ajax if not already loaded
2599             if (!locationsRendered) {
2600                 ShowLoading();
2601
2602                 $.get('/Home/GetLocationsContent', { id: 37496, template: "Template_6" }, function (data) {
2603                     if (data != "")
2604                     {
2605                        $("#locationsPage").append(data);
2606                     }
2607                 }).always(function() {
2608                    HideLoading();
2609                    locationsRendered = true;
2610                 });
2611             }
2612         }
2613
2614        if (page == "#gsvPage") {
2615            // Load GSV via Ajax if not already loaded
2616            if (!gsvRendered) {
2617                ShowLoading();
2618                $.get('/Home/Get360TourContent', { id: 37496, template: "Template_6"}, function (data) {
2619                    if (data != "")
2620                    {
2621                        $("#gsvPage").append(data);
2622                    }
2623                }).always(function() {
2624                    HideLoading();
2625                    gsvRendered = true;
2626                });
2627            }
2628        }
2629
2630        if (page == "#faqPage") {
2631            // Load Faqs via Ajax if not already loaded
2632            if (!faqRendered) {
2633                ShowLoading();
2634
2635                $.get('/Home/GetFAQContent', { id: 37496, template: "Template_6" }, function (data) {
2636                    if (data != "") {
2637                        $("#faqPage").append(data);
2638                    }
2639                }).always(function () {
2640                    HideLoading();
2641                    faqRendered = true;
2642                });
2643            }
2644        }
2645
2646        if (page == "#contentPage") {
2647            if (!contentRendered) {
2648                ShowLoading();
2649
2650                $.get('/Home/GetAdditionalContentContent', { id: 37496, template: "Template_6" }, function (data) {
2651                    if (data != "") {
2652                        $("#contentPage").append(data);
2653                    }
2654                }).always(function () {
2655                    HideLoading();
2656                    contentRendered = true;
2657                });
2658            }
2659        }
2660    }
2661
2662    function nextReview() {
2663        ScrollForReviews();
2664        GetReviewData(1);
2665    }
2666
2667    function prevReview() {
2668        ScrollForReviews();
2669        GetReviewData(-1);
2670    }
2671
2672    function GetReviewData(i)
2673    {
2674        if(i != 0){
2675            ShowLoading();
2676        }
2677        pageIndex = pageIndex + i;
2678        $.get('/Home/GetEnhancedTestimonialReviewInfo', {id: 37496, pageIndex: pageIndex, pageSize: pageSize, notReputation: notReputation, file: '_TemplateReviewContent'}, function (data) {
2679            if (data != "")
2680            {
2681                $(".reviewInfo").html(data);
2682            }
2683        }).always(function() {
2684            HideLoading();
2685        });
2686        SetPaginationButtons();
2687    }
2688
2689    function GetPostsData(i)
2690    {
2691        if(i != 0){
2692            ShowLoading();
2693        }
2694        postsPageIndex = postsPageIndex + i;
2695        $.get('/Home/GetTestimonialPostsInfo', {id: 37496, program_id: 17, profileDomain: 'https://koenenswaterworksplumbing.com/', subdomain: 'koenenswaterworksplumbing', testimonialSSL : 'False', domainSSL : 'True', pageIndex: postsPageIndex, pageSize: pageSize, file: '_TestimonialPostsContent'}, function (data) {
2696            if (data != "")
2697            {
2698                $(".postsInfo").html(data);
2699            }
2700        }).always(function() {
2701            HideLoading();
2702        });
2703        SetPostsPaginationButtons();
2704    }
2705
2706    function GetPostsBanner()
2707    {
2708        ShowLoading();
2709        var bannerObj = {"id":475650,"urgency_item_type_id":15,"urgency_status_id":4,"delay_reason":null,"delay_notification_sent":null,"created":"2026-09-01T09:14:48","created_by":"bbcb7930-ba94-11ec-939c-005056b02f53","created_note":"AMPLibrary.Optima2.Urgency.UrgencyItem.AddUrgencyItem()","modified":"2026-09-01T17:03:45","modified_by":"Personiv User17","modified_note":"AMPLibrary.Optima2.Urgency.UrgencyItem.UpdateUrgencyItem()","deleted":null,"deleted_by":null,"deleted_note":null,"profile_review_id":null,"review_response":null,"profile_review_response_image_id":null,"google_post_title":"🚽💧 Upgrade Your Flush, Save Your Cash! 💧🚽","google_post_start":"2026-09-01T09:14:00","google_post_end":"2027-08-31T00:00:00","google_post_body":"🚽 Did you know your toilet could be wasting thousands of gallons of water each year without you even realizing it? \r\n\r\nOlder or inefficient toilets can quietly drive up your water bill and waste valuable water every day. If your toilet is constantly running, requires multiple flushes, or is simply outdated, it may be time for an upgrade. \r\n\r\n💧 A water-saving toilet can help: ✅ Lower utility bills \r\n\r\n✅ Reduce water waste \r\n\r\n✅ Improve efficiency \r\n\r\n✅ Deliver reliable performance with every flush \r\n\r\nAt Koenen's Water Works Plumbing, we can help you choose and install the right toilet for your home and budget. \r\n\r\n📞 Ready to save water and money? Give us a call today! \r\n\r\n📍 Proudly serving Southeast Wisconsin \r\n\r\n#KoenensWaterWorks #BurlingtonWI #WaterSavingToilets #PlumbingTips #HomeEfficiency #SaveWater #LowerUtilityBills #LocalPlumber","google_post_network_path":"\\\\w19-amp-imagery\\optima_media\\googlepost\\P_37496\\36f42927-1f88-4d14-8520-7aef4d8e0b34.jpeg","google_post_web_path":"https://du9m0k402rjmo.
2709cloudfront.net/googlepost/P_37496\\36f42927-1f88-4d14-8520-7aef4d8e0b34.jpeg","google_post_filename":"36f42927-1f88-4d14-8520-7aef4d8e0b34.jpeg","google_post_option":"Call Now","google_post_link":"???? Upgrade Your Flush, Save Your Cash! ????","completed_notification_sent":null,"completed_feedback":null,"post_display_date":"2026-09-01T00:00:00","post_to_google":true,"post_to_testimonial":true,"attention_grabber":"WATER\r\nWISE","deleted_reason":null,"urgency_google_post_option_id":6,"post_feature":true,"post_feature_expiration":"2027-08-31T00:00:00","crm_post_id":132675,"ignore_end_dates":false,"hide_start_date":true,"hide_expiration_date":true,"google_post_submitted":false,"keep_feature_post_up":false,"api_status":null,"api_message":null,"api_posted":null};
2710        $.ajax({
2711            method: "POST",
2712            url: "/Home/GetPostBanner",
2713            data:JSON.stringify(
2714            {
2715                banner: bannerObj,
2716                testimonialPageColor: (true) ? 'transparent' :'#F5F5F5',
2717                postsColor: '#F5F5F5'
2718            }),
2719            contentType: 'application/json',
2720            success: function (data) {
2721                if(isMobile || isTablet){
2722                    setTimeout(function(){
2723                        $(".home-content").prepend(data);
2724                    }, 5000);
2725                }
2726                else{
2727                    $(".home-content").prepend(data);
2728                }
2729
2730                //remove banner after 30 seconds regardless of mobile/tablet/desktop
2731                 if (!keepPostUp) {
2732                    setTimeout(function () {
2733                        $("#posts-banner-alert").remove();
2734                    }, 30000);
2735                }
2736            }
2737        }).always(function() {
2738            HideLoading();
2739        });
2740    }
2741
2742    function SetPaginationButtons()
2743    {
2744        //look ahead by one
2745        if(((pageIndex + 1) * pageSize) >= numOfReviews){
2746            $("#nextReview").hide();
2747        }
2748        else{
2749            $("#nextReview").show();
2750            $("#nextReview").prop('disabled', false);
2751        }
2752
2753        if(pageIndex <= 0) {
2754            pageIndex = 0;
2755            $("#prevReview").hide();
2756        }
2757        else if (pageIndex > 0){
2758            $("#prevReview").show();
2759            $("#prevReview").prop('disabled', false);
2760        }
2761    }
2762
2763    function SetPostsPaginationButtons()
2764    {
2765        //look ahead by one
2766        if(((postsPageIndex + 1) * pageSize) >= numOfPosts){
2767            $("#nextPosts").hide();
2768        }
2769        else{
2770            $("#nextPosts").show();
2771            $("#nextPosts").prop('disabled', false);
2772        }
2773
2774        if(postsPageIndex <= 0) {
2775            postsPageIndex = 0;
2776            $("#prevPosts").hide();
2777        }
2778        else if (postsPageIndex > 0){
2779            $("#prevPosts").show();
2780            $("#prevPosts").prop('disabled', false);
2781        }
2782    }
2783
2784    function ShowLoading()
2785    {
2786        $("#loadingImg").show();
2787    }
2788
2789    function HideLoading()
2790    {
2791        $("#loadingImg").hide();
2792    }
2793
2794    function checkMobile() {
2795        var windowsize = $(window).width();
2796        switch (true) {
2797        case /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent):
2798            isMobile = true;
2799            break;
2800        case windowsize < 800:
2801            isMobile = true;
2802            break;
2803        default:
2804            isMobile = false;
2805      }
2806    }
2807
2808    function checkTablet() {
2809        var windowsize = $(window).width();
2810        switch (true) {
2811        case (windowsize >= 800) && (windowsize < 1200):
2812            isTablet = true;
2813            break;
2814        default:
2815            isTablet = false;
2816      }
2817    }
2818
2819    function DisplayPhoto(imageUrl){
2820        bootbox.alert({
2821            message:'<img class="img-fluid d-block mx-auto" src="' + imageUrl + '" />',
2822            size: "large",
2823            backdrop: true,
2824            buttons: {
2825                ok: {
2826                    className: 'btn-outline-dark',
2827                    label: 'Close'
2828                }
2829            }
2830        });
2831    }
2832
2833    function DisplayPhotoSlider(index){
2834        if(!$(".slider-imagery").hasClass("slick-initialized"))
2835        {
2836            $('.slider-imagery').slick({
2837                slidesToShow: 1,
2838                slidesToScroll: 1,
2839                arrows: true,
2840                fade: false,
2841                adaptiveHeight: false,
2842                infinite: true,
2843                useTransform: true,
2844                speed: 400,
2845                cssEase: 'cubic-bezier(0.77, 0, 0.18, 1)',
2846                autoplay: true,
2847            });
2848        }
2849
2850        $(".slider-imagery").slick('slickGoTo', index);
2851
2852        $("#carouselImageryPhotoModal").modal('show');
2853    }
2854
2855    function DisplayVideoSlider(index) {
2856
2857        if(!$(".slider-video").hasClass("slick-initialized"))
2858        {
2859            $('.slider-video').slick({
2860                slidesToShow: 1,
2861                slidesToScroll: 1,
2862                arrows: true,
2863                fade: false,
2864                adaptiveHeight: false,
2865                infinite: true,
2866                useTransform: true,
2867                speed: 400,
2868                cssEase: 'cubic-bezier(0.77, 0, 0.18, 1)',
2869            });
2870        }
2871
2872        PauseVideoPlayer();
2873
2874        //arrow onclick tracker
2875        var el = document.querySelectorAll(".slick-arrow");
2876        for (var i = 0; i < el.length; i++) {
2877            el[i].onclick = function () {
2878                PauseVideoPlayer();
2879            };
2880        }
2881
2882
2883        $(".slider-video").slick('slickGoTo', index);
2884
2885        $("#carouselImageryVideoModal").modal('show');
2886    }
2887
2888    function PauseVideoPlayer() {
2889
2890        var videos = document.querySelectorAll('video');
2891        var iframes = document.querySelectorAll('iframe');
2892
2893        //mp4
2894        Array.prototype.forEach.call(videos, video => {
2895            video.pause();
2896        });
2897
2898        //youtube
2899        Array.prototype.forEach.call(iframes, iframe => {
2900            iframe.contentWindow.postMessage(JSON.stringify({
2901                event: 'command',
2902                func: 'pauseVideo'
2903            }), '*');
2904        });
2905
2906        //wistia + vimeo
2907        Array.prototype.forEach.call(iframes, iframe => {
2908            iframe.contentWindow.postMessage(JSON.stringify({
2909                "method": "pause",
2910                "value": "true"
2911            }), '*');
2912        });
2913    }
2914
2915    function setFooterColor(hexColor)
2916    {
2917        //set footer text color based on background color
2918        var r = parseInt(hexColor.substr(1,2),16);
2919        var g = parseInt(hexColor.substr(3,2),16);
2920        var b = parseInt(hexColor.substr(5,2),16);
2921        var rgb = ((r*299)+(g*587)+(b*114))/1000;
2922
2923        var textColor = (rgb >= 128) ? 'black' : 'white';
2924        //text needs to be black
2925        if(textColor == 'black')
2926        {
2927            //set payment method icons
2928            if ($('.paymentType').hasClass('light')) {
2929                $('.paymentType').removeClass('light');
2930                $('.paymentType').remove('#paymentTypeLight');
2931            }
2932            if (!$('.paymentType').hasClass('dark')) {
2933                $('.paymentType').addClass('dark');
2934                $('.paymentType').remove('#paymentTypeLight');
2935                $('.paymentType').add('#paymentTypeDark');
2936            }
2937        }
2938        //text needs to be white
2939        else if(textColor == 'white')
2940        {
2941            //mobile menu hamburger
2942            if ($('.navbar-toggler').hasClass('dark')) {
2943                $('.navbar-toggler').css('background-color', 'transparent');
2944            }
2945            if (!$('.navbar-toggler').hasClass('light')) {
2946                $('.navbar-toggler').css('background-color', 'white');
2947            }
2948
2949            //set payment method icons
2950            if ($('.paymentType').hasClass('dark')) {
2951                $('.paymentType').removeClass('dark');
2952                $('.paymentType').remove('#paymentTypeDark');
2953            }
2954            if (!$('.paymentType').hasClass('light')) {
2955                $('.paymentType').addClass('light');
2956                $('.paymentType').remove('#paymentTypeDark');
2957                $('.paymentType').add('#paymentTypeLight');
2958            }
2959        }
2960    }
2961
2962    function checkHashRoute()
2963    {
2964        if ((location.hash != null) && (location.hash != "") && (location.hash == '#homePage' || location.hash == '#aboutPage' || location.hash == '#servicesPage' || location.hash == '#testimonialsPage' || location.hash == '#contactPage' || location.hash == '#locationsPage' || location.hash == '#faqPage' || location.hash == '#gsvPage' || location.hash == '#contentPage') ) {
2965            DisplayPage(location.hash);
2966        }
2967    }
2968
2969  function contactUsPost(event) {
2970    var _contactForm = $("#ContactPostForm");
2971
2972    // Clear previous validation states
2973    $('.validation-error-message').remove();
2974    _contactForm.find('.validation-error').removeClass('validation-error');
2975    $("#contactResponseMessage").empty();
2976
2977    if (_contactForm[0].checkValidity()) {
2978      contactUsSubmit(event);
2979    } else {
2980      var firstInvalidField = null;
2981
2982      _contactForm.find('input[required], textarea[required], select[required]').each(function () {
2983        var $field = $(this);
2984
2985        if (!this.checkValidity()) {
2986          var fieldId = $field.attr('id') || $field.attr('name');
2987          var fieldLabel = getFieldLabel(fieldId);
2988
2989          $field.addClass('validation-error');
2990
2991          var errorMessage = getCustomErrorMessage($field, fieldLabel);
2992          $field.after(`<div class="validation-error-message">${errorMessage}</div>`);
2993
2994          if (!firstInvalidField) {
2995            firstInvalidField = $field;
2996          }
2997        }
2998      });
2999
3000      // Focus first invalid field
3001      if (firstInvalidField) {
3002        firstInvalidField.focus();
3003      }
3004
3005      // Re-enable submit button
3006      $("#btnContactPost").prop('disabled', false);
3007      $("#btnContactPost").css('font-weight', 'bold');
3008    }
3009  }
3010
3011  function getFieldLabel(fieldId) {
3012    var labels = {
3013      'contact_us_phone': 'Phone Number',
3014      'contact_us_address': 'Address',
3015      'contact_us_city': 'City',
3016      'contact_us_state': 'State',
3017      'contact_us_zip': 'ZIP Code',
3018      'contact_us_subject': 'Subject',
3019      'contact_us_name': 'Name',
3020      'contact_us_email': 'Email',
3021      'contact_us_message': 'Message'
3022    };
3023    return labels[fieldId] || 'This field';
3024  }
3025
3026  function getCustomErrorMessage($field, fieldLabel) {
3027    if ($field.prop('required') && !$field.val().trim()) {
3028      return `${fieldLabel} required`;
3029    }
3030
3031    if ($field.attr('type') === 'email' && $field.val()) {
3032      return `Please enter a valid email address.`;
3033    }
3034
3035    return `Please enter a valid ${fieldLabel.toLowerCase()}.`;
3036  }
3037
3038    function contactUsSubmit(event) {
3039        event.preventDefault();
3040
3041        var form = $("#ContactPostForm");
3042        grecaptcha.ready(function() {
3043            grecaptcha.execute('6LcokacUAAAAAH_snk3O5bpdYwjpC5XAuXNLrJLH', {action: 'contact_us'}).then(function(token) {
3044                $("#g-Recaptcha-Response-Contact").attr("value", token); //add token for server side validation
3045                $.ajax({
3046                    type: "POST",
3047                    url: "/Home/ContactPost",
3048                    data: form.serialize(),
3049                    success: function(data){
3050                        if (data.indexOf('{"message":') != -1) {
3051                            var jsonData = JSON.parse(data);
3052                            if (!jsonData.success) {
3053                                $("#contactResponseMessage").html('<div class="alert alert-warning alert-dissmisable" role="alert"><button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>' + jsonData.message + '</div>');
3054                                recaptchaContactUsInComplete();
3055                                showClassicCaptcha("contact");
3056                            }
3057                            else{
3058                                $("#contactResponseMessage").html('<div class="alert alert-success alert-dissmisable" role="alert"><button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>' + jsonData.message + '</div>');
3059                                recaptchaContactUsComplete();
3060                            }
3061                        }
3062                    }
3063                });
3064            });
3065        });
3066    }
3067
3068    function bgSlider() {
3069        var index = 0;
3070        var opacity = 'False';
3071
3072        $imageEls = $('.parallax .parallax-image'); // Get the images to be cycled.
3073
3074        setInterval(function () {
3075            // Get the next index.  If at end, restart to the beginning.
3076            index = index + 1 < $imageEls.length ? index + 1 : 0;
3077
3078            // Show the next
3079            if (opacity == 'True') {
3080                $imageEls.eq(index).addClass('opacity');
3081            }
3082            else {
3083                $imageEls.eq(index).addClass('show');
3084            }
3085
3086            // Hide the previous
3087            if (opacity == 'True') {
3088                $imageEls.eq(index - 1).removeClass('opacity');
3089            }
3090            else {
3091                $imageEls.eq(index - 1).removeClass('show');
3092            }
3093        }, 5000);
3094    }
3095
3096    function initializeCarousel(){
3097        //https://codepen.io/dolce/pen/QarQde
3098        $('.slider-single').slick({
3099            slidesToShow: 1,
3100            slidesToScroll: 1,
3101            arrows: true,
3102            fade: false,
3103            adaptiveHeight: false,
3104            infinite: true,
3105            useTransform: true,
3106            speed: 400,
3107            cssEase: 'cubic-bezier(0.77, 0, 0.18, 1)',
3108            autoplay: true,
3109        });
3110
3111        $('.slider-nav')
3112        .on('init', function(event, slick) {
3113 	        $('.slider-nav .slick-slide.slick-current').addClass('is-active');
3114        })
3115        .slick({
3116 	        slidesToShow: 5,
3117 	        slidesToScroll: 5,
3118 	        dots: false,
3119 	        focusOnSelect: false,
3120 	        infinite: true,
3121        });
3122
3123        $('.slider-attributes')
3124        .on('init', function(event, slick) {
3125            $('.slider-attributes .slick-slide.slick-current').addClass('is-active');
3126        })
3127        .slick({
3128 	        slidesToShow: 3,
3129 	        slidesToScroll: 3,
3130 	        dots: false,
3131 	        focusOnSelect: false,
3132 	        infinite: true
3133        });
3134
3135        $('.slider-single').on('afterChange', function(event, slick, currentSlide) {
3136            $('.slider-nav').slick('slickGoTo', currentSlide);
3137            var currrentNavSlideElem = '.slider-nav .slick-slide[data-slick-index="' + currentSlide + '"]';
3138            $('.slider-nav .slick-slide.is-active').removeClass('is-active');
3139            $(currrentNavSlideElem).addClass('is-active');
3140
3141            if (currentSlide > 6) {
3142                var m = parseInt(currentSlide / 6);
3143                var d = 6 * m;
3144                var currentAttributeSlide = currentSlide - d;
3145            }
3146            else if (currentSlide >= 3 && currentSlide <= 6)
3147            {
3148                var m = parseInt(currentSlide / 3);
3149                var d = 3 * m;
3150                var currentAttributeSlide = currentSlide - d;
3151            }
3152            else {
3153                currentAttributeSlide = currentSlide;
3154            }
3155
3156            if (6 > 3) {
3157            $('.slider-attributes').slick('slickGoTo', currentAttributeSlide);
3158            var currrentNavAttributeSlideElem = '.slider-attributes .slick-slide[data-slick-index="' + currentAttributeSlide + '"]';
3159            $('.slider-attributes .slick-slide.is-active').removeClass('is-active');
3160            $(currrentNavAttributeSlideElem).addClass('is-active');
3161            }
3162        });
3163
3164        $('.slider-nav').on('click', '.slick-slide', function(event) {
3165            event.preventDefault();
3166            var goToSingleSlide = $(this).data('slick-index');
3167            $('.slider-single').slick('slickGoTo', goToSingleSlide);
3168        });
3169
3170        $('.slider-attributes').on('click', '.slick-slide', function(event) {
3171            event.preventDefault();
3172            var goToSingleSlide = $(this).data('slick-index');
3173            $('.slider-single').slick('slickGoTo', goToSingleSlide);
3174        });
3175    }
3176
3177    function ScrollForReviews(){
3178        // target element
3179        var $id = $(".review-partial-content");
3180        if ($id.length === 0) {
3181            return;
3182        }
3183
3184        // prevent standard hash navigation (avoid blinking in IE)
3185        //e.preventDefault();
3186
3187        // top position relative to the document
3188        var pos = $id.offset().top - $('.navbar').height();
3189
3190        // animated top scrolling
3191        // .stop() keeps from scrolling to top then to element
3192        $('body, html').stop().animate({ scrollTop: pos }, 500);
3193    }
3194
3195    function ScrollForPosts(e){
3196        // target element
3197        var $id = $(".posts-partial-content");
3198        if ($id.length === 0) {
3199            return;
3200        }
3201
3202        // prevent standard hash navigation (avoid blinking in IE)
3203        e.preventDefault();
3204
3205        // top position relative to the document
3206        var pos = $id.offset().top - $('.navbar').height();
3207
3208        // animated top scrolling
3209        // .stop() keeps from scrolling to top then to element
3210        $('body, html').stop().animate({ scrollTop: pos }, 500);
3211    }
3212
3213    function recaptchaContactUsInComplete(){
3214        $("#btnContactPost").prop('disabled', false);
3215        $("#btnContactPost").css('font-weight', 'bold');
3216    }
3217
3218  function recaptchaContactUsComplete() {
3219    $("#btnContactPost").prop('disabled', false);
3220    $("#btnContactPost").css('font-weight', 'normal');
3221    $("#ContactPostForm").trigger("reset");
3222  }
3223
3224    function recaptchaReviewIncomplete(){
3225        $("#postReview").prop('disabled', false);
3226        $("#postReview").css('font-weight', 'bold');
3227    }
3228
3229    function recaptchaReviewComplete(){
3230        $("#postReview").css('font-weight', 'normal');
3231        $("#postReviewForm").trigger("reset");
3232        $("#postReview").prop('disabled', false);
3233    }
3234
3235    function showClassicCaptcha(type) {
3236        if(type === "review"){
3237            $("#classicCaptchaReview").show();
3238        }
3239        else{
3240            $("#classicCaptcha").show();
3241        }
3242    }
3243
3244    function ClearReviewFields() {
3245        $('#starRating').barrating('clear');
3246        $("#review").val("");
3247        $("#review_alias").val("");
3248        $("#review_heading").val("");
3249        $("#reviewCaptcha").val("");
3250    }
3251
3252    function resetReviewButton($button) {
3253        var $buttonText = $button.find('.button-text');
3254        var $spinner = $button.find('.spinner');
3255
3256        $button.prop('disabled', false);
3257
3258        if ($buttonText.length && $spinner.length) {
3259            $buttonText.show();
3260            $spinner.hide();
3261        } else {
3262            var originalText = $button.data('original-text');
3263            if (originalText) {
3264                $button.html(originalText);
3265            }
3266        }
3267    }
3268
3269    function setProcessingState($button, $form, isProcessing) {
3270        var $buttonText = $button.find('.button-text');
3271        var $spinner = $button.find('.spinner');
3272
3273        if (isProcessing) {
3274            $button.prop('disabled', true);
3275            $form.addClass('review-form-processing');
3276            $form.find('input, textarea, select').not('#profile_id, #g-Recaptcha-Response-Review, [type="hidden"]').prop('disabled', true);
3277
3278            if ($buttonText.length && $spinner.length) {
3279                $buttonText.hide();
3280                $spinner.show();
3281            } else {
3282                $button.data('original-text', $button.html());
3283                $button.html('<i class="fas fa-spinner fa-spin"></i> Processing...');
3284            }
3285        } else {
3286            $button.prop('disabled', false);
3287            $form.removeClass('review-form-processing');
3288            $form.find('input, textarea, select').prop('disabled', false);
3289
3290            if ($buttonText.length && $spinner.length) {
3291                $buttonText.show();
3292                $spinner.hide();
3293            } else {
3294                var originalText = $button.data('original-text');
3295                if (originalText) {
3296                    $button.html(originalText);
3297                }
3298            }
3299        }
3300    }
3301
3302    function ClearReviewFields() {
3303        console.log('Clearing review fields');
3304        $('#starRating').barrating('clear');
3305        $("#review").val("");
3306        $("#review_alias").val("");
3307        $("#review_heading").val("");
3308        $("#reviewCaptcha").val("");
3309
3310        $("#postReviewForm input, #postReviewForm textarea").removeClass('error');
3311        $("#postReviewForm .br-widget").removeClass('error');
3312    }
3313
3314    function validateReview(btn) {
3315        var $form = $("#postReviewForm");
3316        var isValid = true;
3317
3318        console.log('Starting validation...');
3319
3320        $form.find('input, textarea').removeClass('error');
3321        $form.find('.br-widget').removeClass('error');
3322
3323        var reviewText = $('#review').val();
3324        console.log('Review text length:', reviewText ? reviewText.trim().length : 0);
3325
3326        if (!reviewText || reviewText.trim().length === 0) {
3327            console.log('Review text validation failed - empty or whitespace only');
3328            $('#review').addClass('error');
3329            $('#review').focus();
3330            isValid = false;
3331        } else {
3332            console.log('Review text validation passed');
3333        }
3334
3335        var rating = null;
3336        var selectRating = $('#starRating')[0] ? $('#starRating')[0].value : null;
3337        var jqueryRating = $('#starRating').val();
3338        var selectedOption = $('#starRating option:selected').val();
3339        var barRating = null;
3340
3341        if (typeof $('#starRating').barrating === 'function') {
3342            try {
3343                var barResult = $('#starRating').barrating('show');
3344                if (barResult && typeof barResult === 'string') {
3345                    barRating = barResult;
3346                } else if (barResult && typeof barResult === 'number') {
3347                    barRating = barResult.toString();
3348                }
3349            } catch (e) {
3350                console.log('Error getting barrating value:', e);
3351            }
3352        }
3353
3354        if (jqueryRating && typeof jqueryRating === 'string') {
3355        } else if (jqueryRating && typeof jqueryRating === 'number') {
3356            jqueryRating = jqueryRating.toString();
3357        } else {
3358            jqueryRating = null;
3359        }
3360
3361        if (barRating && barRating !== "" && barRating !== "0") {
3362            rating = barRating;
3363        } else if (selectRating && selectRating !== "" && selectRating !== "0") {
3364            rating = selectRating;
3365        } else if (selectedOption && selectedOption !== "" && selectedOption !== "0") {
3366            rating = selectedOption;
3367        } else if (jqueryRating && jqueryRating !== "" && jqueryRating !== "0") {
3368            rating = jqueryRating;
3369        }
3370
3371        if (rating && typeof rating !== 'string') {
3372            console.log('WARNING: Rating is not a string, converting:', rating, typeof rating);
3373            rating = String(rating);
3374        }
3375
3376        if (rating && typeof rating === 'object') {
3377            console.error('CRITICAL ERROR: Rating is still an object!', rating);
3378            rating = null;
3379        }
3380
3381        console.log('Validation - Final rating value:', rating, typeof rating);
3382
3383        if (!rating || rating === "" || rating === "0") {
3384            console.log('Rating validation failed');
3385            $('.br-widget').addClass('error');
3386            isValid = false;
3387        } else {
3388            console.log('Rating validation passed with value:', rating);
3389        }
3390
3391        console.log('Validation result:', isValid);
3392        return isValid;
3393    }
3394
3395    function validateReviewLength() {
3396        var text = $('#review').val();
3397        var success = true;
3398
3399        if (text.trim().length == 0) {
3400            $('#review').addClass('error');
3401            success = false;
3402        }
3403        return success;
3404    }
3405
3406    function validateRating() {
3407        var rating = null;
3408
3409        // Use the same rating detection logic
3410        var selectRating = $('#starRating')[0] ? $('#starRating')[0].value : null;
3411        var jqueryRating = $('#starRating').val();
3412        var selectedOption = $('#starRating option:selected').val();
3413        var barRating = null;
3414
3415        if (typeof $('#starRating').barrating === 'function') {
3416            try {
3417                barRating = $('#starRating').barrating('show');
3418            } catch (e) {
3419                console.log('Error getting barrating value in validateRating:', e);
3420            }
3421        }
3422
3423        // Determine which rating to use
3424        if (barRating && barRating !== "" && barRating !== "0") {
3425            rating = barRating;
3426        } else if (selectRating && selectRating !== "" && selectRating !== "0") {
3427            rating = selectRating;
3428        } else if (selectedOption && selectedOption !== "" && selectedOption !== "0") {
3429            rating = selectedOption;
3430        } else if (typeof jqueryRating === 'string' && jqueryRating !== "" && jqueryRating !== "0") {
3431            rating = jqueryRating;
3432        }
3433
3434        var success = true;
3435        if (!rating || rating === "" || rating === "0") {
3436            $('.br-widget').addClass('error');
3437            success = false;
3438        }
3439        return success;
3440    }
3441</script>
3441
3442</body>
3443</html>

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.