1/* Custom JS */ 2 3(function (window,$) { 4 const wistiaVideos = []; 5 6 /* ------------------- JS to run after all html is completely loaded ------------------- */ 7 8 $(document).ready(function () { 9 10 11 12 13 14 /* Sync breakpoints from css to be used for sliders and other responsive functionalities 15 -------------------------------------------------------------------------------- */ 16 const _xs = parseFloat(getComputedStyle(document.documentElement).getPropertyValue('--br-xs')), 17 _sm = parseFloat(getComputedStyle(document.documentElement).getPropertyValue('--br-sm')), 18 _md = parseFloat(getComputedStyle(document.documentElement).getPropertyValue('--br-md')), 19 _lg = parseFloat(getComputedStyle(document.documentElement).getPropertyValue('--br-lg')), 20 _xl = parseFloat(getComputedStyle(document.documentElement).getPropertyValue('--br-xl')); 21 22 const br = { 23 xsMin: 0, 24 xsMax: _xs, 25 smMin: _xs + 1, 26 smMax: _sm, 27 mdMin: _sm + 1, 28 mdMax: _md, 29 lgMin: _md + 1, 30 lgMax: _lg, 31 xlMin: _lg + 1, 32 xlMax: _xl, 33 }, 34 isTouchBr = () => { 35 return window.innerWidth <= br.smMax; 36 }; 37 38 39 40 41 /* Class to add to body for lazyloading background images (ie responsive background images) or any image-related stuff that cant have the loading="lazy" attributes but can be in a way lazyloaded with css 42 -------------------------------------------------------------------------------- */ 43 // $(window).on('load',function () { 44 $('html').addClass('doc-images-loaded'); 45 // }); 46 47 48 49 50 51 /* Modernizr - check if browser supports webp. if it does, do some things. 52 -------------------------------------------------------------------------------- */ 53 54 Modernizr.on('webp', function (result) { 55 if (result) { 56 // Has WebP support 57 } else { 58 // No WebP support 59 } 60 }); 61 62 63 64 65 66 /* Video Related Scripts 67 -------------------------------------------------------------------------------- */ 68 /* Wistia - Call function when script needs to be loaded either by hover or waypoints 69 id => wistia video id 70 addToQueue => whether to add to queue or not. this allows the video to play on function call 71 -------------------------------------------------------------------------------- */ 72 function wistiaLoad(id, addToQueue) { 73 addToQueue = addToQueue || false; 74 75 typeof Wistia === 'undefined' && 76 $.getScript('https://fast.wistia.com/assets/external/E-v1.js', function (data, textStatus, jqxhr) { 77 console.log('wistia load:', textStatus); // Success 78 }); 79 80 if (!wistiaVideos[id]) { 81 $.getScript('//fast.wistia.com/embed/medias/' + id + '.jsonp', function (data, textStatus, jqxhr) { 82 console.log('json load:', id); // Success 83 }); 84 wistiaVideos[id] = { 85 onQ: false, 86 wistia: { 87 id: id, 88 onReady: function (video) { 89 console.log('wistia clicked'); 90 $('.wistia_embed[data-wistia-id="' + this.id + '"] .wistia_click_to_play') 91 .first() 92 .trigger('click'); 93 } 94 } 95 }; 96 } 97 98 if (addToQueue) { 99 window._wq = window._wq || []; 100 101 let interval = setInterval(function () { 102 if (!wistiaVideos[id].onQ && window._wq) { 103 console.log('adding to queue'); 104 wistiaVideos[id].onQ = true; 105 _wq.push(wistiaVideos[id].wistia); 106 clearInterval(interval); 107 interval = null; 108 } 109 }, 100); 110 } 111 } 112 // separate download of thumbnailed wistia embeds to avoid conflicts with lazyload setup. wistia is somehow overriding it :| 113 $(window).on('scroll', function () { 114 $('.wistia_embed') 115 .not('.video-button') 116 .each(function () { 117 let video = $(this); 118 if ($(window).scrollTop() + $(window).innerHeight() > video.offset().top) { 119 wistiaLoad(video.data('wistia-id'), false); 120 } 121 }); 122 }); 123 124 // //load it all without filter. will decrease performance the score 125 // $('.wistia_embed').each(function(){ 126 // let video = $(this); 127 // console.log(video); 128 // wistiaLoad(video.data('wistia-id'),false); 129 // }); 130 131 // video buttons only download when about to be clicked 132 $('.wistia_embed') 133 .filter('.video-button') 134 .on('click', function () { 135 let id = $(this).data('wistia-id'); 136 wistiaLoad(id, true); 137 }); 138 139 140 141 142 143 /* Gravity Forms Enhancements 144 add `active` class for gfields when they have focused form fields so styles aren't a nightmare 145 -------------------------------------------------------------------------------- */ 146 const inputselector = '.gfield input, .gfield select, .gfield textarea'; 147 const inputActiveClass = 'active'; 148 const inputFocusClass = 'focus'; 149 150 /* sees if there's a value 151 form => form element 152 inputSelector => inputselector 153 containerSelector => like .gfield 154 */ 155 function scanLabel(form, inputSelector, containerSelector) { 156 inputSelector = inputSelector || 'input,select,textarea'; 157 containerSelector = containerSelector || '.gfield'; 158 let fields = form.find(inputSelector); 159 fields.each(function () { 160 if ($(this).val()) { 161 $(this).closest(containerSelector).addClass(inputActiveClass); 162 } 163 }); 164 } 165 166 /* adds active class baed on passed logic/condition 167 trueLogic => condition to use for class setup 168 fieldTarget => the field to manipulate classes 169 callback => function to call after everything is done. Example 170 function(fieldTarget){ 171 //do something to fieldTarget 172 } 173 dontToggle => if it should run toggleClass if trueLogic is true. by default it uses addClass if trueLogic is true and then removeClass fal
173se. 174 */ 175 function toggleActiveClass(trueLogic, fieldTarget, callback, dontToggle) { 176 callback = callback || function (fieldTarget) {}; 177 178 if (dontToggle) { 179 if (trueLogic) { 180 fieldTarget.addClass(inputActiveClass); 181 } else { 182 fieldTarget.removeClass(inputActiveClass); 183 } 184 } else { 185 if (trueLogic) { 186 fieldTarget.toggleClass(inputActiveClass); 187 } 188 } 189 callback(fieldTarget); 190 } 191 192 scanLabel($('.gform_body'), inputselector); 193 194 ///focus 195 $('body').on('focus', inputselector, function (e) { 196 e.stopImmediatePropagation(); 197 // not select because it is weird 198 if (e.target.tagName.toLowerCase() !== 'select') { 199 const currentValue = e.target.value; // $(this).val() should get accurate value but gravity forms brok the phone field type >:c 200 toggleActiveClass(!currentValue, $(e.target).closest('.gfield'), function (gfieldli) { 201 gfieldli.addClass(inputFocusClass); 202 }); 203 } 204 }); 205 206 //blur 207 $('body').on('blur', inputselector, function (e) { 208 e.stopImmediatePropagation(); 209 // not select because it is weird 210 if (e.target.tagName.toLowerCase() !== 'select') { 211 const currentValue = e.target.value; // $(this).val() should get accurate value but gravity forms brok the phone field type >:c 212 toggleActiveClass(!currentValue, $(e.target).closest('.gfield'), function (gfieldli) { 213 gfieldli.removeClass(inputFocusClass); 214 }); 215 } 216 }); 217 218 //change 219 220 // $('body').on('change', inputselector, function (e) { 221 // e.stopImmediatePropagation(); 222 // // not select because it is weird 223 // // if (e.target.tagName.toLowerCase() == 'select') { 224 225 // let currentValue = e.target.value; 226 227 // toggleActiveClass(currentValue !== '', $(e.target).closest('.gfield'), null,false); 228 // // } 229 // }); 230 231 // alternate solution in case gravity forms trolls us again on the next update 232 window.gform && window.gform.addAction( 'gform_input_change', function( elem, formId, fieldId ) { 233 const currentValue = elem.value; 234 toggleActiveClass(currentValue, $(elem).closest('.gfield'), null, true); 235 }, 10, 3 ); 236 237 /* Hook it all up to gravity forms */ 238 $(document).bind('gform_post_render', function () { 239 scanLabel($(this), inputselector); 240 }); 241 242 243 244 245 /* Setup Up Sliders - https://swiperjs.com/swiper-api 246 -------------------------------------------------------------------------------- */ 247 248 249 //Syncs breakpoints to styles so there's no twilight zone of weird sliders on certain screen sizes >:) 250 function sliderBrArgs(obj){ 251 252 let toReturn = {}; 253 254 if(obj["sm"] !== undefined) { 255 toReturn[br.smMin] = obj["sm"]; 256 } 257 if(obj["md"] !== undefined) { 258 toReturn[br.mdMin] = obj["md"]; 259 } 260 if(obj["lg"] !== undefined) { 261 toReturn[br.lgMin] = obj["lg"]; 262 } 263 if(obj["xl"] !== undefined) { 264 toReturn[br.xlMin] = obj["xl"]; 265 } 266 267 return toReturn; 268 269 } 270 271 272 function setupSliders() { 273 274 275 // Template/ Example for setting up slider 276 277 //Single instance Example. Remember to rename variables uniquely as possible 278 const unqSldr = document.querySelector('#selector-for .slider-element:not(.swiper-initialized'); 279 280 if(unqSldr) { 281 const UniqueSlider = new Swiper(unqSldr,{ 282 loop: true, 283 speed: 1000, 284 autoplay: { 285 delay: 5000, 286 }, 287 navigation: { 288 nextEl: unqSldr.querySelector('.swiper-button-next'), 289 prevEl: unqSldr.querySelector('.swiper-button-prev'), 290 }, 291 scrollbar: { 292 el: unqSldr.querySelector('.swiper-scrollbar') 293 }, 294 paginationClickable: true, 295 pagination: { 296 el: unqSldr.querySelector('.swiper-pagination'), 297 // type: 'custom', 298 // renderCustom: function (swiper, current, total) { 299 // const cPrefix = current > 9 ? '' : '0'; 300 // const tPrefix = total > 9 ? '' : '0' ; 301 // return `${cPrefix}${current} / ${tPrefix}${(total)}`; 302 // } 303 }, 304 slidesPerView: 1, 305 spaceBetween: 30, 306 // autoHeight: true, //add dynamic height 307 // grid: { //use this to allow multiple rows on slider. Refer to swiper documentation for limitations of this settings 308 // rows: 2, // number of sliders per row 309 // fill:'row', //direction of row fill 310 // }, 311 watchSlidesProgress: true, //keep this true so it's easier to style slider stuff and keep track of it 312 observer: true, //keep this true so it's easier to style slider stuff and keep track of it 313 observeParents: true, //keep this true so it's easier to style slider stuff and keep track of it 314 observeSlideChildren: true, //keep this true so it's easier to style slider stuff and keep track of it 315 preventClicks: false, //enable clicking within sliders allowing default behaviors 316 preventClicksPropagation: true, //part 2 of allowing default behaviors for slide 317 simulateTouch: false, //comment out if you want your cursor to do touch device things like swiping etc. 318 edgeSwipeThreshold: 0, // remove swiper threshold it does weird things with arrow's click bounds if sliders are not styled in a certain way. 319 //instead of checking $(window).width and running different slick methods every resize, consolidate all arguments in the responsive property instead 320 //Swiper sets up arguments mobile first. so argue the sliders as
320such 321 breakpoints: sliderBrArgs({ 322 sm:{ // tablet 323 slidesPerView: 2, 324 spaceBetween: 30, 325 // grid: { //use this to allow multiple rows on slider. Refer to swiper documentation for limitations of this settings 326 // rows: 2, 327 // }, 328 }, 329 md:{ //laptop 330 slidesPerView: 3, 331 spaceBetween: 50, 332 // grid: { //use this to allow multiple rows on slider. Refer to swiper documentation for limitations of this settings 333 // rows: 2, 334 // }, 335 }, 336 lg:{ //desktop 337 slidesPerView: 4, 338 spaceBetween: 20, 339 // grid: { //use this to allow multiple rows on slider. Refer to swiper documentation for limitations of this settings 340 // rows: 2, 341 // }, 342 }, 343 xl:{ //hd 344 slidesPerView: 5, 345 spaceBetween: 30, 346 // grid: { //use this to allow multiple rows on slider. Refer to swiper documentation for limitations of this settings 347 // rows: 2, 348 // }, 349 } 350 //no need to 'unslick', let's keep the slider enabled so the layout is still fixed if there is more slides or repeater rows added 351 }) 352 }); 353 354 //additional methods for your slider 355 // UniqueSlider.doSomething(); 356 } 357 358 // Multiple instances Example. 359 $('#selector-for .slider-element.s') 360 .not('.swiper-initialized') 361 .each((i,sldr) => { 362 const slider = new Swiper(sldr,{ 363 loop: true, 364 speed: 1000, 365 autoplay: { 366 delay: 5000, 367 }, 368 navigation: { 369 nextEl: sldr.querySelector('.swiper-button-next'), 370 prevEl: sldr.querySelector('.swiper-button-prev'), 371 }, 372 scrollbar: { 373 el: sldr.querySelector('.swiper-scrollbar') 374 }, 375 pagination: { 376 el: sldr.querySelector('.swiper-pagination'), 377 clickable: true, //make it clickable 378 // type: 'custom', 379 // renderCustom: function (swiper, current, total) { 380 // const cPrefix = current > 9 ? '' : '0'; 381 // const tPrefix = total > 9 ? '' : '0' ; 382 // return `${cPrefix}${current} / ${tPrefix}${(total)}`; 383 // } 384 }, 385 slidesPerView: 1, 386 spaceBetween: 30, 387 // autoHeight: true, //add dynamic height 388 // grid: { //use this to allow multiple rows on slider. Refer to swiper documentation for limitations of this settings 389 // rows: 2, // number of sliders per row 390 // fill:'row', //direction of row fill 391 // }, 392 watchSlidesProgress: true, //keep this true so it's easier to style slider stuff and keep track of it 393 observer: true, //keep this true so it's easier to style slider stuff and keep track of it 394 observeParents: true, //keep this true so it's easier to style slider stuff and keep track of it 395 observeSlideChildren: true, //keep this true so it's easier to style slider stuff and keep track of it 396 preventClicks: false, //enable clicking within sliders allowing default behaviors 397 preventClicksPropagation: true, //part 2 of allowing default behaviors for slide 398 simulateTouch: false, //comment out if you want your cursor to do touch device things like swiping etc. 399 edgeSwipeThreshold: 0, // remove swiper threshold it does weird things with arrow's click bounds if sliders are not styled in a certain way. 400 //instead of checking $(window).width and running different slick methods every resize, consolidate all arguments in the responsive property instead 401 //Swiper sets up arguments mobile first. so argue the sliders as such 402 breakpoints: sliderBrArgs({ 403 sm:{ // tablet 404 slidesPerView: 2, 405 spaceBetween: 30, 406 // grid: { //use this to allow multiple rows on slider. Refer to swiper documentation for limitations of this settings 407 // rows: 2, 408 // }, 409 }, 410 md:{ //laptop 411 slidesPerView: 3, 412 spaceBetween: 50, 413 // grid: { //use this to allow multiple rows on slider. Refer to swiper documentation for limitations of this settings 414 // rows: 2, 415 // }, 416 }, 417 lg:{ //desktop 418 slidesPerView: 4, 419 spaceBetween: 20, 420 // grid: { //use this to allow multiple rows on slider. Refer to swiper documentation for limitations of this settings 421 // rows: 2, 422 // }, 423 }, 424 xl:{ //hd 425 slidesPerView: 5, 426 spaceBetween: 30, 427 // grid: { //use this to allow multiple rows on slider. Refer to swiper documentation for limitations of this settings 428 // rows: 2, 429 // }, 430 } 431 //no need to 'unslick', let's keep the slider enabled so the layout is still fixed if there is more slides or repeater rows added 432 }) 433 }); 434 435 //additional methods for your slider 436 // slider.doSomething(); 437 }); 438 439 440
441 $('.home-section-1 .section-slider') 442 .not('.swiper-initialized') 443 .each((i,sldr) => { 444 const slider = new Swiper(sldr,{ 445 loop: true, 446 speed: 1000, 447 // autoplay: { 448 // delay: 5000, 449 // }, 450 navigation: { 451 nextEl: sldr.querySelector('.swiper-button-next'), 452 prevEl: sldr.querySelector('.swiper-button-prev'), 453 }, 454 // scrollbar: { 455 // el: unqSldr.querySelector('.swiper-scrollbar') 456 // }, 457 paginationClickable: true, 458 pagination: { 459 el: sldr.querySelector('.swiper-pagination'), 460 // type: 'custom', 461 // renderCustom: function (swiper, current, total) { 462 // const cPrefix = current > 9 ? '' : '0'; 463 // const tPrefix = total > 9 ? '' : '0' ; 464 // return `${cPrefix}${current} / ${tPrefix}${(total)}`; 465 // } 466 }, 467 slidesPerView: 1, 468 spaceBetween: 30, 469 autoHeight: true, //add dynamic height 470 // grid: { //use this to allow multiple rows on slider. Refer to swiper documentation for limitations of this settings 471 // rows: 2, // number of sliders per row 472 // fill:'row', //direction of row fill 473 // }, 474 watchSlidesProgress: true, //keep this true so it's easier to style slider stuff and keep track of it 475 observer: true, //keep this true so it's easier to style slider stuff and keep track of it 476 observeParents: true, //keep this true so it's easier to style slider stuff and keep track of it 477 observeSlideChildren: true, //keep this true so it's easier to style slider stuff and keep track of it 478 preventClicks: false, //enable clicking within sliders allowing default behaviors 479 preventClicksPropagation: true, //part 2 of allowing default behaviors for slide 480 simulateTouch: true, //comment out if you want your cursor to do touch device things like swiping etc. 481 edgeSwipeThreshold: 0, // remove swiper threshold it does weird things with arrow's click bounds if sliders are not styled in a certain way. 482 //instead of checking $(window).width and running different slick methods every resize, consolidate all arguments in the responsive property instead 483 //Swiper sets up arguments mobile first. so argue the sliders as such 484 breakpoints: sliderBrArgs({ 485 // sm:{ // tablet 486 // slidesPerView: 1, 487 // spaceBetween: 95, 488 // // autoHeight: true, 489 // // grid: { //use this to allow multiple rows on slider. Refer to swiper documentation for limitations of this settings 490 // // rows: 2, 491 // // }, 492 // }, 493 md:{ //laptop 494 slidesPerView: 2, 495 spaceBetween: 35, 496 // autoHeight: false, 497 // grid: { //use this to allow multiple rows on slider. Refer to swiper documentation for limitations of this settings 498 // rows: 2, 499 // }, 500 }, 501 lg:{ //desktop 502 slidesPerView: 2, 503 spaceBetween: 35, 504 // autoHeight: false, 505 // grid: { //use this to allow multiple rows on slider. Refer to swiper documentation for limitations of this settings 506 // rows: 2, 507 // }, 508 }, 509 xl:{ //hd 510 slidesPerView: 3, 511 spaceBetween: 35, 512 // autoHeight: false, 513 // grid: { //use this to allow multiple rows on slider. Refer to swiper documentation for limitations of this settings 514 // rows: 2, 515 // }, 516 } 517 //no need to 'unslick', let's keep the slider enabled so the layout is still fixed if there is more slides or repeater rows added 518 }) 519 }); 520 521 //additional methods for your slider 522 // slider.doSomething(); 523 }); 524 $('.layout-sidebar .section-slider') 525 .not('.swiper-initialized') 526 .each((i,sldr) => { 527 const slider = new Swiper(sldr,{ 528 loop: true, 529 speed: 1000, 530 // autoplay: { 531 // delay: 5000, 532 // }, 533 navigation: { 534 nextEl: sldr.querySelector('.swiper-button-next'), 535 prevEl: sldr.querySelector('.swiper-button-prev'), 536 }, 537// autoHeight: true, 538 // scrollbar: { 539 // el: unqSldr.querySelector('.swiper-scrollbar') 540 // }, 541 paginationClickable: true, 542 pagination: { 543 el: sldr.querySelector('.swiper-pagination'), 544 // type: 'custom', 545 // renderCustom: function (swiper, current, total) { 546 // const cPrefix = current > 9 ? '' : '0'; 547 // const tPrefix = total > 9 ? '' : '0' ; 548 // return `${cPrefix}${current} / ${tPrefix}${(total)}`; 549 // } 550 }, 551 slidesPerView: 1, 552 spaceBetween: 30, 553 // autoHeight: true, //add dynamic height 554 // grid: { //use this to allow multiple rows on slider. Refer to swiper documentation for limitations of this settings 555 // rows: 2, // number of sliders per row 556 // fill:'row', //direction of row fill 557 // }, 558 watchSlidesProgress: true, //keep this true so it's easier to style slider stuff and keep track of it 559 observer: true, //keep this true so it's easier to style slider stuff and keep track of it 560 observeParents: true, //keep this true so it's easier to style slider stuff and keep track of it 561 observeSlideChildren: true, //keep this true so it's easier to style slider stuff and keep track of it 562 preventClicks: false, //enable clicking within sliders allowing default behaviors 563 preventClicksPropagation: true, //part 2 of allowing default behaviors for slide 564 simulateTouch: true, //comment out if you want your cursor to do touch device things like swiping etc. 565 edgeSwipeThreshold: 0, // remove swiper threshold it does weird things with arrow's click bounds if sliders are not styled in a certain way. 566 //instead of checking $(window).width and running different slick methods every resize, consolidate all arguments in the responsive property instead 567 //Swiper sets up arguments mobile first. so argue the sliders as
567such 568 breakpoints: sliderBrArgs({ 569 // sm:{ // tablet 570 // slidesPerView: 1, 571 // spaceBetween: 95, 572 // // autoHeight: true, 573 // // grid: { //use this to allow multiple rows on slider. Refer to swiper documentation for limitations of this settings 574 // // rows: 2, 575 // // }, 576 // }, 577 // md:{ //laptop 578 // slidesPerView: 2, 579 // spaceBetween: 35, 580 // // autoHeight: false, 581 // // grid: { //use this to allow multiple rows on slider. Refer to swiper documentation for limitations of this settings 582 // // rows: 2, 583 // // }, 584 // }, 585 // lg:{ //desktop 586 // slidesPerView: 2, 587 // spaceBetween: 35, 588 // // autoHeight: false, 589 // // grid: { //use this to allow multiple rows on slider. Refer to swiper documentation for limitations of this settings 590 // // rows: 2, 591 // // }, 592 // }, 593 // xl:{ //hd 594 // slidesPerView: 3, 595 // spaceBetween: 35, 596 // // autoHeight: false, 597 // // grid: { //use this to allow multiple rows on slider. Refer to swiper documentation for limitations of this settings 598 // // rows: 2, 599 // // }, 600 // } 601 //no need to 'unslick', let's keep the slider enabled so the layout is still fixed if there is more slides or repeater rows added 602 }) 603 }); 604 605 //additional methods for your slider 606 // slider.doSomething(); 607 }); 608 609 $('.home-section-3 .section-slider') 610 .not('.swiper-initialized') 611 .each((i,sldr) => { 612 const slider = new Swiper(sldr,{ 613 loop: true, 614 speed: 1000, 615 // autoplay: { 616 // delay: 5000, 617 // }, 618 navigation: { 619 nextEl: sldr.querySelector('.swiper-button-next'), 620 prevEl: sldr.querySelector('.swiper-button-prev'), 621 }, 622 scrollbar: { 623 el: sldr.querySelector('.swiper-scrollbar') 624 }, 625 pagination: { 626 el: sldr.querySelector('.swiper-pagination'), 627 clickable: true, //make it clickable 628 // type: 'custom', 629 // renderCustom: function (swiper, current, total) { 630 // const cPrefix = current > 9 ? '' : '0'; 631 // const tPrefix = total > 9 ? '' : '0' ; 632 // return `${cPrefix}${current} / ${tPrefix}${(total)}`; 633 // } 634 }, 635 slidesPerView: 1, 636 spaceBetween: 30, 637 autoHeight: true, //add dynamic height 638 // grid: { //use this to allow multiple rows on slider. Refer to swiper documentation for limitations of this settings 639 // rows: 2, // number of sliders per row 640 // fill:'row', //direction of row fill 641 // }, 642 watchSlidesProgress: true, //keep this true so it's easier to style slider stuff and keep track of it 643 observer: true, //keep this true so it's easier to style slider stuff and keep track of it 644 observeParents: true, //keep this true so it's easier to style slider stuff and keep track of it 645 observeSlideChildren: true, //keep this true so it's easier to style slider stuff and keep track of it 646 preventClicks: false, //enable clicking within sliders allowing default behaviors 647 preventClicksPropagation: true, //part 2 of allowing default behaviors for slide 648 simulateTouch: false, //comment out if you want your cursor to do touch device things like swiping etc. 649 edgeSwipeThreshold: 0, // remove swiper threshold it does weird things with arrow's click bounds if sliders are not styled in a certain way. 650 //instead of checking $(window).width and running different slick methods every resize, consolidate all arguments in the responsive property instead 651 //Swiper sets up arguments mobile first. so argue the sliders as such 652 }); 653 //additional methods for your slider 654 // slider.doSomething(); 655 }); 656 657 $('.home-section-4 .section-slider') 658 .not('.swiper-initialized') 659 .each((i,sldr) => { 660 const slider = new Swiper(sldr,{ 661 loop: true, 662 speed: 1000, 663 // autoplay: { 664 // delay: 5000, 665 // }, 666 navigation: { 667 nextEl: sldr.querySelector('.swiper-button-next'), 668 prevEl: sldr.querySelector('.swiper-button-prev'), 669 }, 670 scrollbar: { 671 el: sldr.querySelector('.swiper-scrollbar') 672 }, 673 pagination: { 674 el: sldr.querySelector('.swiper-pagination'), 675 clickable: true, //make it clickable 676 // type: 'custom', 677 // renderCustom: function (swiper, current, total) { 678 // const cPrefix = current > 9 ? '' : '0'; 679 // const tPrefix = total > 9 ? '' : '0' ; 680 // return `${cPrefix}${current} / ${tPrefix}${(total)}`; 681 // } 682 }, 683 slidesPerView: 1, 684 spaceBetween: 30, 685 autoHeight: true, //add dynamic height 686 // grid: { //use this to allow multiple rows on slider. Refer to swiper documentation for limitations of this settings 687 // rows: 2, // number of sliders per row 688 // fill:'row', //direction of row fill 689 // }, 690 watchSlidesProgress: true, //keep this true so it's easier to style slider stuff and keep track of it 691 observer: true, //keep this true so it's easier to style slider stuff and keep track of it 692 observeParents: true, //keep this true so it's easier to style slider stuff and keep track of it 693 observeSlideChildren: true, //keep this true so it's easier to style slider stuff and keep track of it 694 preventClicks: false, //enable clicking within sliders allowing default behaviors 695 preventClicksPropagation: true, //part 2 of allowing default behaviors for slide 696 simulateTouch: true, //comment out if you want your cursor to do touch device things like swiping etc. 697 edgeSwipeThreshold: 0, // remove swiper threshold it does weird things with arrow's click bounds if sliders are not styled in a certain way. 698 //instead of checking $(window).width and running different slick methods every resize, consolidate all arguments in the responsive property instead 699 //Swiper sets up arguments mobile first. so argue the sliders as
699such 700 breakpoints: sliderBrArgs({ 701 md:{ //laptop 702 slidesPerView: 3, 703 spaceBetween: 42, 704 // grid: { //use this to allow multiple rows on slider. Refer to swiper documentation for limitations of this settings 705 // rows: 2, 706 // }, 707 arrows: false 708 }, 709 lg:{ //desktop 710 slidesPerView: 3, 711 spaceBetween: 43, 712 // grid: { //use this to allow multiple rows on slider. Refer to swiper documentation for limitations of this settings 713 // rows: 2, 714 // }, 715 }, 716 xl:{ //hd 717 slidesPerView: 3, 718 spaceBetween: 58, 719 // grid: { //use this to allow multiple rows on slider. Refer to swiper documentation for limitations of this settings 720 // rows: 2, 721 // }, 722 } 723 }) 724 725 726 727 728 }); 729 730 //additional methods for your slider 731 // slider.doSomething(); 732 }); 733 734 735 736 737 738 739 740 // Add unique sliders... 741 742 743 744 745 746 747 // ...And then repeating instances 748 // Images/ Awards Slider 749 $('.awards-slider:not(.profile-awards-slider)') 750 .not('.swiper-initialized') 751 .each((i,sldr)=> { 752 753 const slider = new Swiper(sldr,{ 754 loop: true, 755 speed: 1000, 756 autoplay: { 757 delay: 5000, 758 }, 759 navigation: { 760 nextEl: sldr.querySelector('.swiper-button-next'), 761 prevEl: sldr.querySelector('.swiper-button-prev'), 762 }, 763 scrollbar: { 764 el: sldr.querySelector('.swiper-scrollbar') 765 }, 766 pagination: { 767 el: sldr.querySelector('.swiper-pagination'), 768 clickable: true, //make it clickable 769 }, 770 slidesPerView: 1, 771 spaceBetween: 30, 772 centerInsufficientSlides: true, 773 // grid: { //use this to allow multiple rows on slider. Refer to swiper documentation for limitations of this settings 774 // rows: 2, // number of sliders per row 775 // fill:'row', //direction of row fill 776 // }, 777 watchSlidesProgress: true, //keep this true so it's easier to style slider stuff and keep track of it 778 observer: true, //keep this true so it's easier to style slider stuff and keep track of it 779 observeParents: true, //keep this true so it's easier to style slider stuff and keep track of it 780 observeSlideChildren: true, //keep this true so it's easier to style slider stuff and keep track of it 781 preventClicks: false, 782 preventClicksPropagation: true, 783 // simulateTouch: false, 784 edgeSwipeThreshold: 0, 785 // simulateTouch: false, //comment out if you want your cursor to do touch device things 786 breakpoints: sliderBrArgs({ 787 sm:{ 788 slidesPerView: 3, 789 // simulateTouch: false 790 }, 791 md:{ 792 slidesPerView: 4, 793 }, 794 lg:{ 795 slidesPerView: 4, 796 }, 797 xl:{ 798 slidesPerView: 5, 799 } 800 }) 801 }); 802 803 }); 804 $('.profile-awards-slider') 805 .not('.swiper-initialized') 806 .each((i,sldr)=> { 807 808 const slider = new Swiper(sldr,{ 809 loop: true, 810 speed: 1000, 811 autoplay: { 812 delay: 5000, 813 }, 814 navigation: { 815 nextEl: sldr.querySelector('.swiper-button-next'), 816 prevEl: sldr.querySelector('.swiper-button-prev'), 817 }, 818 scrollbar: { 819 el: sldr.querySelector('.swiper-scrollbar') 820 }, 821 pagination: { 822 el: sldr.querySelector('.swiper-pagination'), 823 clickable: true, //make it clickable 824 }, 825 slidesPerView: 1, 826 spaceBetween: 30, 827 centerInsufficientSlides: true, 828 // grid: { //use this to allow multiple rows on slider. Refer to swiper documentation for limitations of this settings 829 // rows: 2, // number of sliders per row 830 // fill:'row', //direction of row fill 831 // }, 832 watchSlidesProgress: true, //keep this true so it's easier to style slider stuff and keep track of it 833 observer: true, //keep this true so it's easier to style slider stuff and keep track of it 834 observeParents: true, //keep this true so it's easier to style slider stuff and keep track of it 835 observeSlideChildren: true, //keep this true so it's easier to style slider stuff and keep track of it 836 preventClicks: false, 837 preventClicksPropagation: true, 838 // simulateTouch: false, 839 edgeSwipeThreshold: 0, 840 // simulateTouch: false, //comment out if you want your cursor to do touch device things 841 breakpoints: sliderBrArgs({ 842 sm:{ 843 slidesPerView: 2, 844 // simulateTouch: false 845 }, 846 md:{ 847 slidesPerView: 2, 848 }, 849 lg:{ 850 slidesPerView: 3, 851 }, 852 xl:{ 853 slidesPerView: 3, 854 } 855 }) 856 }); 857 858 }); 859 860 /* 861 //LEGACY - Slick 862 // make sure that the function only runs when slick is not initialized so it doesn't break 863 $('.class-name') 864 .not('.slick-initialized') 865 .slick({ 866 // dependinng if mobileFirst is set to true or not, the arguments outsife of the responsive property should be the settings for the first breakpoint 867 autoplay: true, 868 dots: true, 869 rows: 0, // for newer version of slick to not wrap items in their own tags. Useful if you intend to style slider blocks with uniform height. do not include if your site uses the old version 870 slidesToShow: 5, 871 sidesToScroll: 1, // set to 1 if sliders designed to have instances offseting vertically on certain columns of the slider is easier to style and less buggy when applied. (ie Troxell Law, Tiano O' Dell, etc) 872 // customPaging: fancyPagination, //add callback if design calls for pagination with fancy numbering for pagination 873 arrows: true, 874 prevArrow: sliderFancyButton('prev'), //NOTE: currently slick arrows set as css selectors have cases where they don't work on certain window sizes. please use this function from now on to avoid issues 875 nextArrow: sliderFancyButton('next'), //NOTE: currently slick arrows set as css selectors have cases where they don't work on certain window sizes. please use this function from now on to avoid issues 876 //instead of checking $(window).width and running different slick methods every resize, consolidate all arguments in the responsive property instead 877 //usually set at max widths of breakpoints. unless mobile first setup is enabled, then set them as the min-widths 878 responsive: [ 879 { 880 // HD 881 breakpoint: br.xlMax, //or br.xlMin if mobile first 882 settings: { 883 //NOTE: best practice is not to set to unslick, in case content updates call for more than those already displayed 884 slidesToShow: 5 885 } 886 }, 887 { 888 //desktop 889 breakpoint: br.lgMax, //or br.lgMin if mobile first 890 settings: { 891 slidesToShow: 4 892 } 893 }, 894 { 895 //laptop 896 breakpoint: br.mdMax, //or br.mdMin if mobile first 897 settings: { 898 slidesToShow: 4 899 } 900 }, 901 { 902 // tablet 903 breakpoint: br.smMax, //or br.smMin if mobile first 904 settings: { 905 slidesToShow: 2 906 } 907 }, 908 { 909 // * Mobile 910 breakpoint: br.xsMax, //or br.xsMin if mobile first 911 settings: { 912 slidesToShow: 1 913 } 914 } 915 ] 916 }); 917 918 // Custom sliders by template sections 919 920 // And then repeating instances 921 $('.awards .awards-slider') 922 .not('.slick-initialized') 923 .slick({ 924 // dependinng if mobileFirst is set to true or not, the arguments outsife of the responsive property should be the settings for the first breakpoint 925 autoplay: true, 926 dots: true, 927 rows: 0, // for newer version of slick to not wrap items in their own tags. Useful if you intend to style slider blocks with uniform height. do not include if your site uses the old version 928 slidesToShow: 5, 929 sidesToScroll: 1, // set to 1 if sliders designed to have instances offseting vertically on certain columns of the slider is easier to style and less buggy when applied. (ie Troxell Law, Tiano O' Dell, etc) 930 // customPaging: fancyPagination, //add callback if design calls for pagination with fancy numbering for pagination
931 arrows: false, 932 prevArrow: sliderFancyButton('prev', 'button-style-diamond button-size-equal button-style-no-radius button-palette-primary button-style-flat'), 933 nextArrow: sliderFancyButton('next', 'button-style-diamond button-size-equal button-style-no-radius button-palette-primary button-style-flat'), 934 // * MobileFirst: true, 935 //instead of checking $(window).width and running different slick methods every resize, consolidate all arguments in the responsive property instead 936 //usually set at max widths of breakpoints. unless mobile first setup is enabled, then set them as the min-widths 937 responsive: [ 938 { 939 // HD 940 breakpoint: br.xlMax, //or br.xlMin if mobile first 941 settings: { 942 //NOTE: best practice is not to set to unslick, in case content updates call for more than those already displayed 943 slidesToShow: 5 944 } 945 }, 946 { 947 //desktop 948 breakpoint: br.lgMax, //or br.lgMin if mobile first 949 settings: { 950 slidesToShow: 4 951 } 952 }, 953 { 954 //laptop 955 breakpoint: br.mdMax, //or br.mdMin if mobile first 956 settings: { 957 slidesToShow: 4 958 } 959 }, 960 { 961 // tablet 962 breakpoint: br.smMax, //or br.smMin if mobile first 963 settings: { 964 slidesToShow: 2 965 } 966 }, 967 { 968 // * Mobile 969 breakpoint: br.xsMax, //or br.xsMin if mobile first 970 settings: { 971 slidesToShow: 1 972 } 973 } 974 ] 975 }); 976 */ 977 } 978 979 // run the function. you can cut and paste this within $(document).ready or $(window).load if any issue persists 980 setupSliders(); 981 982 const gridSliders = $('.section-slider.grid'); 983 function setupGridSliders () { 984 gridSliders.each((i, sldr) => { 985 const slider = $(sldr); 986 987 if (window.innerWidth < 768) { 988 $(sldr).addClass('swiper'); 989 $(sldr).removeClass('grid'); 990 } else { 991 if ($(sldr).hasClass('swiper-initialized')) { 992 const swiperInstance = slider[0].swiper; 993 if (swiperInstance) { 994 swiperInstance.destroy(); 995 } 996 $(sldr).removeClass('swiper-initialized'); 997 $(sldr).removeClass('swiper'); 998 $(sldr).addClass('grid'); 999 } 1000 } 1001 }) 1002 } 1003 1004 setupGridSliders(); 1005 1006 1007 1008 1009 1010 1011 /* Add Sticky Helper so that header can have a different style when scrolling the page further. NOTE: DO NOT USE for setting header as fixed ot sticky when the class is present. header should already be so without the sticky class. 1012 -------------------------------------------------------------------------------- */ 1013 function checkHeader(){ 1014 let stickPoint = $('.layout-header + *').first().offset().top; //can be the banner or main 1015 $(window).scrollTop() > stickPoint 1016 ? $('html').addClass('doc-header-sticky').removeClass('doc-header-not-sticky') 1017 : $('html').removeClass('doc-header-sticky').addClass('doc-header-not-sticky'); 1018 1019 } 1020 checkHeader(); 1021 $(window).on('scroll', checkHeader); 1022 1023 1024 1025 1026 1027 1028 1029 /* Smooth Scroll down to section on click (<a href="#id_of_section_to_be_scrolled_to">). NOTE: will cause animation issues on scroll if scoll-behavior is set to smooth 1030 -------------------------------------------------------------------------------- */ 1031 1032 // mark script 1033 function scrollToTargetElement(){ 1034 // const jumpButtons = document.querySelectorAll('a[href*="#"]:not([href="#"])'); 1035 const jumpButtons = document.querySelectorAll('a[href*="#"]'); 1036 1037 const handleClick = (e)=>{ 1038 let target; 1039 1040 try { 1041 target = document.querySelector(`${e.currentTarget.hash}`); 1042 } catch(e) { 1043 // invalid hash or probably a weird url like google reviews, do nothing 1044 } 1045 1046 if(target){ 1047 e.preventDefault(); //Dont jump to top of screen 1048 target.scrollIntoView({behavior:'smooth'}); 1049 } else { 1050 // PMS/SEO will put empty hash links in the menus sometimes. catch them and prevent default. 1051 if(e.currentTarget.closest('.menu')) { 1052 e.preventDefault(); 1053 } 1054 } 1055 }; 1056 1057 jumpButtons.forEach((jumpButton)=>{ 1058 jumpButton.addEventListener('click',handleClick); 1059 }); 1060 1061 }; 1062 scrollToTargetElement(); 1063 1064 // // old jquery version, no longer cool 1065 // $('a[href*="#"]:not([href="#"])').click(function() { 1066 // const headerOffset = $('.layout-header').outerHeight() || 0;
1067 // if (location.pathname.replace(/^\//, '') == this.pathname.replace(/^\//, '') && location.hostname == this.hostname) { 1068 // let target = $(this.hash); 1069 // target = target.length ? target : $('[name=' + this.hash.slice(1) + ']'); 1070 // if (target.length) { 1071 // $('html, body').animate({ 1072 // scrollTop: target.offset().top - headerOffset 1073 // }, 1000); 1074 // return false; 1075 // } 1076 // } 1077 // }); 1078 1079 1080 1081 1082 1083 1084 /* SVGs for Style friendliness + performance readiness 1085 -------------------------------------------------------------------------------- */ 1086 function loadSVGS() { 1087 $(':is(object, img, picture).inline-svg').each(function () { 1088 const img = $(this); 1089 1090 const svgSource = img.attr('data') ?? img.attr('src'); 1091 1092 if (svgSource && svgSource.toString().split('.').pop() == 'svg') { 1093 const imgID = img.attr('id'); 1094 const imgClass = img.attr('class'); 1095 1096 $.get( 1097 svgSource, 1098 function (data) { 1099 let svg = $(data).find('svg'); 1100 if (!svg) { 1101 return false; 1102 } 1103 if (typeof imgID !== 'undefined') { 1104 svg = svg.attr('id', imgID); 1105 } 1106 if (typeof imgClass !== 'undefined') { 1107 svg = svg.attr('class', imgClass + ' replaced-svg'); 1108 } 1109 svg = svg.removeAttr('xmlns:a'); 1110 img.replaceWith(svg); 1111 }, 1112 'xml' 1113 ); 1114 } 1115 //no more lazyloading background-images. we have plugins for that 1116 }); 1117 console.log('svg loaded'); 1118 1119 $('body').addClass('svgs-loaded'); 1120 } 1121 1122 loadSVGS(); 1123 1124 1125 1126 1127 1128 1129 /* menu toggle 1130 -------------------------------------------------------------------------------- */ 1131 $('.toggle-menu').on('click', function (e) { 1132 e.preventDefault(); 1133 $('html').toggleClass('doc-header-menu-open'), $(this).toggleClass('open'); 1134 if (!$('html').hasClass('doc-header-menu-open')) { 1135 $('.layout-header .menu-item').removeClass('open'); 1136 } 1137 }); 1138 1139 1140 1141 1142 1143 1144 /* menu accordion 1145 -------------------------------------------------------------------------------- */ 1146 // open on tap/click mobile 1147 $('.layout-header .header-nav .menu-item.menu-item-has-children > a').on('click', function (e) { 1148 if (isTouchBr()) { 1149 e.preventDefault(); 1150 $(e.target).closest('.menu-item').siblings().removeClass('open'); 1151 $(e.target).closest('.menu-item').toggleClass('open'); 1152 } 1153 }); 1154 1155 1156 1157 1158 1159 1160 /* widget accordion 1161 -------------------------------------------------------------------------------- */ 1162 $('.widget:not(.widget-style-no-toggle):not(#sidebar-form)').each(function ( i ) { 1163 const widget = $(this), 1164 contentSel = '*', // not just the usual types. let's also make sure we dont neglect the other types 1165 containerSel = 'li,.widget'; 1166 1167 /* add class to elements that can toggle widget/ sub menu */ 1168 widget.find('.sub-menu').siblings('a').addClass('widget-toggle'); 1169 if(!$('body').hasClass('onep21-custom-template')) { 1170 widget.find('.widget-title,.widgettitle,.widget__title').not('.widget-style-no-toggle').addClass('widget-toggle'); 1171 } else{ 1172 widget.addClass('widget-style-no-toggle'); 1173 } 1174 1175 1176 1177 // NOW FOR THE CUSTOMIZING WHICH ONES ARE OPEN PART 1178 1179 1180 /* open first togglable widget on initial load */ 1181 // i < 1 && widget.addClass('open'); 1182 1183 // /* or open all widgets on initial load */ 1184 widget.addClass('open'); 1185 1186 1187 /* open items that contain the current viewed page */ 1188 if(widget.hasClass('open')){ 1189 // // opens all matching 1190 // const currItem = widget.find('.current-menu-ancestor'); 1191 1192 // opens first matching 1193 const currItem = widget.find('.current-menu-ancestor').first(); 1194 1195 if(currItem.children('.widget-toggle')){ 1196 currItem.addClass('open'); 1197 } 1198 } 1199 1200 /* event listener */ 1201 widget.find('.widget-toggle').on('click', function (e) { 1202 e.preventDefault(); 1203 //animate 1204 const toggle = $(this); 1205 const content = toggle.siblings(contentSel).first(); 1206 1207 if (toggle.parent(containerSel).hasClass('open')) { 1208 content.slideUp(500,()=>{ 1209 content.siblings('.widget-toggle').removeClass('open'); 1210 content.parent(containerSel).removeClass('open'); 1211 }); 1212 } else { 1213 content.slideDown(500,()=>{ 1214 content.siblings('.widget-toggle').addClass('open'); 1215 content.parent(containerSel).addClass('open'); 1216 }); 1217 } 1218 }); 1219 }); 1220 1221 1222 1223 1224
1225 /* Scroll Tracker to toggle classes for animations. Replaces waypoint for less reliance on large libraries 1226 triggerElement => jQuery element to track visibility 1227 selectorToAnimate => class of element within trigger element to animate. falls back to `.animate__animated` 1228 classToAdd => class to add to selectorToAnimate 1229 offsetRatio => multiplier for viewport height to offset visibility. defaults to 0. 1230 setting to .5 will trigger script when triggerElement is halfway the viewport height 1231 setting to .99 will trigger script when triggerElement is peaking a few pixels at the bottom of the viewport 1232 setting to 0 (or default) will trigger script when triggerElement is at the very top of the viewport 1233 .8 might work most of the time 1234 callback => function to callback. Example 1235 (trackedEl,isVisible) => { 1236 if(isVisible){ 1237 //trackedEl is visible 1238 }else{ 1239 1240 //trackedEl is not visible 1241 } 1242 1243 } 1244 reverse => set to true or false if reverseing the animation on scroll up is desired 1245 reverseClass => class to add when reversing 1246 -------------------------------------------------------------------------------- */ 1247 1248 function trackVisibility(triggerElement, classToAdd, selectorToAnimate, offsetRatio, callback, reverse, reverseClass) { 1249 selectorToAnimate = selectorToAnimate || '.animate__animated'; 1250 reverseClass = reverseClass || ''; 1251 offsetRatio = offsetRatio ? offsetRatio : 0; 1252 1253 const trackedEl = typeof triggerElement == 'string' ? $(triggerElement) : triggerElement; 1254 1255 if (!trackedEl.length) return; 1256 1257 function checkEl() { 1258 const visibilityStart = window.innerHeight * offsetRatio; 1259 const elementStart = trackedEl.offset().top; 1260 1261 if (window.scrollY + visibilityStart > elementStart) { 1262 trackedEl.addClass('visible'); 1263 1264 if (selectorToAnimate) { 1265 trackedEl.find(selectorToAnimate).addClass(classToAdd); 1266 if (reverseClass) { 1267 trackedEl.find(selectorToAnimate).removeClass(reverseClass); 1268 } 1269 } 1270 1271 if (callback && typeof callback == 'function') { 1272 callback(trackedEl, true); 1273 } 1274 } else { 1275 if (reverse) { 1276 trackedEl.removeClass('visible'); 1277 if (selectorToAnimate) { 1278 trackedEl.find(selectorToAnimate).removeClass(classToAdd); 1279 if (reverseClass) { 1280 trackedEl.find(selectorToAnimate).addClass(reverseClass); 1281 } 1282 } 1283 1284 if (callback && typeof callback == 'function') { 1285 callback(trackedEl, false); 1286 } 1287 } 1288 } 1289 } 1290 1291 // catch animated elements already visibile in the viewport. 1292 checkEl(); 1293 1294 // add event listener for animation on scroll 1295 $(window).on('scroll', checkEl); 1296 } 1297 1298 //trackVisibility Instance - Single Element 1299 //Template -> trackVisibility($('#id'), 'classToAdd', '.elementToAnimate', offsetVal, function(triggerElement){}, reverse, 'reverseClass'); 1300 //Example -> trackVisibility($('#home-section-2'), 'slideInUp', '.animate__animated', .5, null, true,'slideOutDown'); 1301 1302 //trackVisibility Instance - Multiple Elements 1303 //Template -> $('.helper-class').each(function(){ trackVisibility($(this), 'classToAdd', $(this), offsetVal, function(triggerElement){}, reverse, 'reverseClass'); }); 1304 //Example -> $('.inline-svg').each(function(){ trackVisibility($(this), 'inline-svg-stroke', $(this), .5, null, true, 'inline-svg-no-stroke'); }); 1305 1306 1307 1308 /* Fancy Border Animated trackVisibility 1309 Animated fancy-border 1310 Requires: 1311 SCSS: scss/components/fancy.scss .fancy-border + .fancy-border-animated classes 1312 JS: Fancy border Animated trackVisibility 1313 -------------------------------------------------------------------------------- */ 1314 $('.fancy-border-animated').each(function(){ trackVisibility($(this), '', $(this), 0.7, false, true, ''); }); 1315 1316 /* Fancy Letters trackVisibility 1317 Variation of Mr Garret's code to make a string able to animate letter entrance one by one 1318 Requires: 1319 PHP: functions/function-helpers.scss: onep21_fancy_letters. Text must be outputted using this function 1320 SCSS: scss/components/fancy.scss fancy-letters 1321 JS: Fancy Text Animated trackVisibility 1322 -------------------------------------------------------------------------------- */ 1323 $('.fancy-letters').each(function(){ trackVisibility($(this), '', $(this), 0.9, false, true, ''); }); 1324
1325 /* Fancy Background Animated trackVisibility 1326 Animated background 1327 Requires: 1328 SCSS: scss/components/fancy.scss .responsive-background,.responsive-background-wrapper + .responsive-background-animated-on-visible classes 1329 JS: Fancy border Animated trackVisibility 1330 -------------------------------------------------------------------------------- */ 1331 $('.responsive-background-animated-on-visible').each(function(){ trackVisibility($(this), '', $(this), 0.9, false, true, ''); }); 1332 1333 1334 1335 $("#gtranslate_selector option").each(function () { 1336 var val = $(this).val(); 1337 var txt = $(this).html(); 1338 //console.log("<li data-translate='" + val + "'>" + txt + "</li>"); 1339 $(".ilawyer-translate-dropdown ul").append( 1340 //$("<li class='notranslate' data-translate='" + val + "'>" + txt + "</li>"); 1341 $(`<li class="notranslate" data-translate="${val}">${txt}</li>`) 1342 ); 1343 }); 1344 $(".ilawyer-translate").on("click", function (e) { 1345 $(this).next(".ilawyer-translate-dropdown").toggleClass("open"); 1346 }); 1347 $(".ilawyer-translate-dropdown ul li").on("click", function (e) { 1348 var filterText = $(this).text(); 1349 $(this) 1350 .closest(".ilawyer-translate-dropdown") 1351 .prev(".ilawyer-translate") 1352 .find("span") 1353 .text(filterText); 1354 $(this).closest(".ilawyer-translate-dropdown").removeClass("open"); 1355 const dropDownData = $(this).attr("data-translate"); 1356 $("#gtranslate_selector").val(dropDownData).change(); 1357 }); 1358 1359 1360 1361 1362 /* Popup Modals - ie Case Results, Discourage Search Warning 1363 -------------------------------------------------------------------------------- */ 1364 function destroyPopup(){ 1365 ///destrtroy 1366 $('body > #il-popup').fadeOut().removeClass('active').remove(); 1367 $('html').removeClass('doc-popup-active'); 1368 } 1369 1370 function createPopup(contentToPrepend,classes) { 1371 classes = classes || '';
1372 contentToPrepend = contentToPrepend || ''; 1373 1374 //destroy prior one if any 1375 destroyPopup(); 1376 1377 $('body').append(function(){ 1378 let html = `<div id="il-popup" class="popup"> 1379 <div class="popup-overlay popup-destroy"></div> 1380 <div class="popup-body"> 1381 <div class="container container-style-maxed popup-container"> 1382 <div class="popup-frame ${classes}"> 1383 ${contentToPrepend} 1384 <button class="popup-destroy popup-close-button">Close</button> 1385 </div> 1386 </div> 1387 </div> 1388 </div>`; 1389 1390 return html; 1391 }); 1392 1393 let popup = $('body > #il-popup'); 1394 1395 $('html').addClass('doc-popup-active'); 1396 1397 popup.fadeIn(); 1398 popup.addClass('active'); 1399 } 1400 1401 $('body').on('click','.popup-trigger',function(e){ 1402 e.preventDefault(); 1403 1404 const anchor = $(this).attr('data-href') || $(this).attr('href'); 1405 1406 const popupContent = anchor && anchor !== '#' && $( anchor ).length 1407 ? $( anchor ) 1408 : $(this).siblings('.popup-content') 1409 ; 1410 1411 1412 if(popupContent.length){ 1413 createPopup(popupContent.html(),$(this).data('popup-classes')); 1414 } 1415 1416 }); 1417 1418 $('body').on('click','.popup-destroy',function(e){ 1419 e.preventDefault(); 1420 destroyPopup(); 1421 }); 1422 1423 1424 1425 1426 // /* Common Optional Stuff: Accordions - ie FAQs, etc. 1427 1428 // To enable, follow the steps: 1429 // - Uncomment the sass import declaration in the style.scss file 1430 // - Unccoment script for "Common Optional Stuff: Accordions - ie FAQs, etc. 1431 // - To setup markup 1432 // - Add classes/Attrs to the following 1433 // - .accordion-wrapper => element wrapping a group of accordion items 1434 // - .accordion => blocks to hide or show depending on active state 1435 // - .accordion-trigger => set attribute to element that will toggle the accordion 1436 // -------------------------------------------------------------------------------- */ 1437 1438 1439 // function toggleAccordion(toAddToggleClassTo,hash){ 1440 // toAddToggleClassTo = toAddToggleClassTo || null; 1441 // hash = hash || window.location.hash; 1442 1443 // if($(hash).hasClass('accordion')) { 1444 1445 // $('[href="'+hash+'"],[data-href="'+hash+'"]').closest('.accordion-wrapper') 1446 // .find('.accordion-trigger') 1447 // .not('[href="'+hash+'"],[data-href="'+hash+'"]') 1448 // .removeClass('open'); 1449 // $(hash).closest('.accordion-wrapper') 1450 // .find('.accordion') 1451 // .not($(hash)) 1452 // .each((i,acc)=>{ 1453 // $(acc).slideUp(500,()=>{ 1454 // $(acc).removeClass('open'); 1455 // }) 1456 // ; 1457 // }); 1458 1459 1460 // $('.accordion-trigger[href="'+hash+'"],.accordion-trigger[data-href="'+hash+'"]').toggleClass('open'); 1461 1462 1463 // if($(hash).hasClass('open')){ 1464 1465 // if(history.pushState) { 1466 // let noHashURL = window.location.href.replace(/#.*$/, ''); 1467 // window.history.pushState({}, '', noHashURL) 1468 // } else { 1469 // window.location.hash = ''; 1470 // } 1471 1472 // $(hash) 1473 // .slideUp(500,()=>{ 1474 // $(hash).removeClass('open'); 1475 // }) 1476 // ; 1477 // if(toAddToggleClassTo) { 1478 // toAddToggleClassTo.removeClass('open'); 1479 // } 1480 // } else { 1481 // if(history.pushState) { 1482 // history.pushState({}, '', hash); 1483 // } else { 1484 // window.location.hash = hash; 1485 // } 1486 // $(hash) 1487 // .slideDown(500,()=>{ 1488 // $(hash).addClass('open'); 1489 // }) 1490 // ; 1491 // if(toAddToggleClassTo) { 1492 // toAddToggleClassTo.removeClass('open'); 1493 // } 1494 // } 1495 // } 1496 // } 1497 1498 // $('.accordion-trigger').on('click',function(e){ 1499 // e.stopPropagation(); 1500 // e.preventDefault(); 1501 // toggleAccordion(false,$(e.target).attr('href') || $(e.target).attr('data-href')); 1502 // }); 1503 1504 // toggleAccordion(); 1505 1506 1507 1508 1509 1510 1511 // /* Common Optional Stuff: Filter Dropdown - ie Case Results, Attorney Grid, etc. 1512 1513 1514 // To enable, follow the steps: 1515 // - Uncomment the sass import declaration in the style.scss file 1516 // - Unccoment script for "Filter Dropdown - ie Case Results " in main.js 1517 // - If being used for Case Results::after 1518 // -Setup `Case Result Types` on 1519 // - Admin > Theme Options > Other Components if there are no CPTs for case results being used 1520 // - Admin > Case Results > Case Result Types if CPT Case results are enabled 1521 // - Add classes/Attrs to the following 1522 // - .filter-blocks => PARENT wrapper of case results row 1523 // - .filter-block => set as the value for 'part_classes' of includes/repeater-results. 1524 // - If being used for other purposes 1525 // - Use template part includes/helper-filter-dropdown 1526 // - Add classes/Attrs to the following 1527 // - .filter-blocks => PARENT wrapper of the items to be filtered 1528 // - .filter-block => blocks to hide or show depending on active filter 1529 // - [data-filter] => set attribute to applicable filter slugs separated by commas 1530 // -------------------------------------------------------------------------------- */ 1531 // $('.filter-label').on('click',function(e){ 1532 // e.preventDefault(); 1533 // $(this).siblings('.filter-dropdown').first().slideToggle(200); 1534 // }) 1535 1536 // $('.filter .filter-dropdown a').on('click',function(e){ 1537 // e.preventDefault();
1538 // const self = $(this); 1539 // const filterKey = self.attr('data-filter-key'); 1540 // const filterValue = self.attr('href'); 1541 // const blocksWrapper = self.closest('.filter').siblings('.filter-blocks').length 1542 // ? self.closest('.filter').siblings('.filter-blocks') 1543 // : $('.filter-blocks').first(); 1544 // const filterBlock = blocksWrapper.children('.filter-block'); 1545 1546 // const noResultsText = self.closest('.filter').children('.filter-empty-text').html() || 'No results found'; 1547 1548 // blocksWrapper.siblings('.filter-empty').remove(); 1549 1550 // self.closest('li') 1551 // .siblings('li') 1552 // .removeClass('active'); 1553 1554 // self.closest('li').addClass('active'); 1555 1556 // self.closest('.filter-dropdown').slideUp(200); 1557 1558 // self 1559 // .closest('.filter-dropdown').siblings('.filter-label').first() 1560 // .text(( self.attr('data-filter-option-text') || self.text() )); //change the text; 1561 1562 1563 // if(filterValue == '#'){ 1564 1565 // filterBlock.show(); 1566 // window.location.hash = ''; 1567 // }else{ 1568 // // filterBlock 1569 // filterBlock.not('[data-filter-'+filterKey+'*="'+filterValue.replace('#','')+'"]').hide(); 1570 // filterBlock.filter('[data-filter-'+filterKey+'*="'+filterValue.replace('#','')+'"]').show(); 1571 // window.location.hash = filterValue; 1572 1573 // } 1574 1575 // if(!filterBlock.filter(':visible').length) { 1576 // blocksWrapper.after('<div class="filter-empty">'+ noResultsText +'</div>'); 1577 // } 1578 // }); 1579 1580 // //let the id in the window loaction filter 1581 // if($('body').hasClass('template-results') && window.location.hash !== '') { 1582 // $('.filter .filter-dropdown a[href="'+ window.location.hash +'"]').trigger('click'); 1583 // } 1584 1585 1586 1587 1588 // /* Common Optional Stuff: Parallax. :D 1589 // - NOTE: Make sure the elements you add the following attributes to DOES NOT HAVE transform styles. otherwise this will not work as it should. 1590 // - Add classes/Attrs to the following 1591 // - data-parallax-x => factor of how much parallax you want horizontally 1592 // - -250 makes it slowly scroll up 1593 // - 250 makes it slowly scroll down 1594 // - -500 makes it quickly scroll up 1595 // - 500 makes it quickly scroll down 1596 // - -10000 makes itscroll up on the speed of light 1597 // - 10000 makes it scroll down on the speed of light 1598 // - 0 does nothing 1599 // - data-parallax-y => factor of how much parallax you want vertically 1600 // - -250 makes it slowly scroll to the top 1601 // - 250 makes it slowly scroll to the bottom 1602 // - -500 makes it quickly scroll to the top 1603 // - 500 makes it quickly scroll to the bottom 1604 // - -10000 makes it scroll to the top on the speed of light 1605 // - 10000 makes it scroll to the bottom on the speed of light 1606 // - 0 does nothing 1607 // //optional 1608 // - data-parallax-origin => factor of where in the viewport the element is in its original positions. set at .5 by default 1609 // - .5 will return element in its original position when it is in the vertical center of the viewport view 1610 // - 0 will return element in its original position when it is in the top of the viewport view 1611 // - .99 will return element in its original position when it peeks a little bit in the bottom of the viewport 1612 1613 // - data-parallax-pad => how deep outside the viewport you want to start the parallax early so it doesnt start jumping around or parallaxing too late 1614 // - .5 will start parallaxing when the element is half the viewport's height away before it is in view 1615 // - 0 will start parallaxing when the element is in view 1616 // - 1 will start parallaxing when the element is the viewport's height away before it is in view 1617 // -------------------------------------------------------------------------------- */ 1618 1619 1620 // function doParallax(){ 1621 1622 // const 1623 // scrollTop = window.scrollY, //yes 1624 // viewportOffset = window.pageYOffset, //yes 1625 // viewportHeight = window.innerHeight, //yes 1626 // documentHeight = document.documentElement.offsetHeight, // yes 1627 // documentTop = document.documentElement.clientTop, // yes 1628 // parallaxers = document.querySelectorAll('[data-parallax-y],[data-parallax-x],[data-parallax-custom]') 1629 // ; 1630 1631 1632 // if(!parallaxers) return; 1633
1634 // parallaxers.forEach((parallaxer) => { 1635 1636 1637 1638 // parallaxer.style.transform = ''; 1639 // parallaxer.style.setProperty('--parallax-calculation','0'); 1640 1641 1642 // if(!isTouchBr()){ 1643 1644 // const 1645 // height = parallaxer.offsetHeight, 1646 // offset = parallaxer.getBoundingClientRect().top + viewportOffset - documentTop, //¯\_(ã)_/¯ 1647 // paraVX = !isNaN( parseFloat(parallaxer.getAttribute("data-parallax-x")) ) 1648 // ? parseFloat(parallaxer.getAttribute("data-parallax-x")) 1649 // : 0, 1650 // paraVY = !isNaN( parseFloat(parallaxer.getAttribute("data-parallax-y")) ) 1651 // ? parseFloat(parallaxer.getAttribute("data-parallax-y")) 1652 // : 0, 1653 // paraVOrigin = !isNaN( parseFloat(parallaxer.getAttribute("data-parallax-origin")) ) 1654 // ? parseFloat(parallaxer.getAttribute("data-parallax-origin")) 1655 // : .5, 1656 // parallaxPad = !isNaN( parseFloat(parallaxer.getAttribute("data-parallax-pad")) ) 1657 // ? parseFloat(parallaxer.getAttribute("data-parallax-pad")) 1658 // : .5; 1659 1660 // const parallaxStart = scrollTop + (viewportHeight * (1 + parallaxPad)) >= 0 1661 // ? scrollTop + (viewportHeight * (1 + parallaxPad)) 1662 // : 0; 1663 // const parallaxEnd = scrollTop - (viewportHeight * parallaxPad) <= documentHeight 1664 // ? scrollTop - (viewportHeight * parallaxPad) 1665 // : documentHeight; 1666 1667 // const scrollOffset = ( (viewportHeight * paraVOrigin) - (height * paraVOrigin)); 1668 // const calcedTransform = ( ((scrollTop - offset) + scrollOffset) / viewportHeight ); 1669 1670 1671 // const x = Math.round(calcedTransform * paraVX); 1672 // const y = Math.round(calcedTransform * paraVY); 1673 1674 1675 // if (parallaxStart > offset && offset + height > parallaxEnd) { 1676 // if(!parallaxer.hasAttribute('data-parallax-custom')) { 1677 // parallaxer.style.transform = "translateX("+ x + "px)" + "translateY(" +y + "px)"; 1678 // } 1679 // parallaxer.style.setProperty('--parallax-calculation',calcedTransform.toFixed(3)); 1680 // } 1681 // } 1682 1683 // }); 1684 // } 1685 // doParallax(); 1686 // window.addEventListener('scroll', doParallax); 1687 1688 1689 1690 1691 /* .table-wrapper Add a table-wrapper class around tables for better management of horizontal scrolls 1692 -------------------------------------------------------------------------------- */ 1693 $('.content > table, .content > *:not(.table) table').each(function(){ 1694 console.log('a table was wrapped'); 1695 $(this).wrap('<div class="table-wrapper" />'); 1696 }); 1697 1698 1699 1700 1701 1702 1703 /* Run Functions on Resize for sliders consitency 1704 -------------------------------------------------------------------------------- */ 1705 1706 let resizeTimerInternal; 1707 $(window).on('resize', function () { 1708 clearTimeout(resizeTimerInternal); 1709 1710 resizeTimerInternal = setTimeout(function () { 1711 //add functions here to fire on resize eg. setupSliders() 1712 setupSliders(); 1713 setupGridSliders(); 1714 checkHeader(); 1715 }, 100); 1716 }); 1717 1718 1719 1720 1721 1722 1723 /* Run Functions on orientation change too 1724 -------------------------------------------------------------------------------- */ 1725 $(window).on('orientationchange', function () { 1726 $(window).trigger('resize'); 1727 }); 1728 1729 1730 1731 1732 1733 1734 /* End Document Ready 1735 -------------------------------------------------------------------------------- */ 1736 }); 1737 1738 /* ------------------- JS to run after all content (html + images) is completely loaded ------------------- */ 1739 1740 $(window).on('load', function () { 1741 1742 1743 /* 1744 Catch elements, animations, wistia videos, etc. That are already above the fold 1745 -------------------------------------------------------------------------------- */ 1746 $(window).trigger('scroll'); 1747 // $(window).trigger('resize'); 1748 1749 }); 1750 1751 1752 /* ------------------- Vanilla fixes ------------------- */ 1753 window.addEventListener('load', () => { 1754 1755 /* Removes scripts or styles that do not help. ie Ngage svg overrides. not cool ngage. 1756 Note: You will only need this usually post-launch. Do not mess with this script while you are building the site or it is still in staging environment. 1757 url => string. specific and exact url of the styles/scripts that you want to remove: eg: 'https://messenger.ngageics.com/api/customscript/getscript?id=13-38-69-150-245-204-30-134&scriptType=0' 1758 -------------------------------------------------------------------------------- */ 1759 function removeScript(url) { 1760 if(!url) return; 1761 1762 1763 const unwanted = document.querySelector( 1764 `link[href="${url}"]` 1765 ); 1766 if (unwanted) { 1767 unwanted.remove(); 1768 }; 1769 } 1770 1771 window.removeScript = removeScript; 1772 1773 // example of how to use 1774 // removeScript('https://script-that-messes-with-the-very-cute-styles-this-site-has-or-something-with-the-same-energy.com/style.css'); 1775 }); 1776 1777})(window,jQuery);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.