1/** 2 * Javascript to be used sitewide 3 * 4 */ 5 6(function ($) { 7 var $window = $(window); 8 var start_Width = window.innerWidth; 9 10 $(document).on("ready", function () { 11 SmoothScrollAnchors(); 12 ResponsiveIFRAMES(); 13 ResponsiveFlickrEmbed(); 14 $(".container").VideoOverlayClick(); 15 $(".container-fluid").VideoOverlayClick(); 16 VimeoOverlayImage(); 17 simpleInfoAccordion(); 18 ResponsiveTables(); 19 LivestreamBannerSectionInit(); 20 loadAudioPlayers(); 21 MobileSelects(); 22 closeMobileSelects(); 23 subsplashDarkMode(); 24 initPrintListeners(); 25 // // check value of Site Settings > Show Popup and init popup 26 // fetch("/wp-json/isc/v1/fields/popup/") 27 // .then(function (response) { 28 // return response.json(); 29 // }) 30 // .then(function (data) { 31 // if (data == true) { 32 // initPopup(); 33 // } else if (data != false && data != '[""]') { 34 // var parsedData = JSON.parse(data); 35 // var postType = ga_post_type; 36 37 // if (jQuery.inArray(postType, parsedData) !== -1 && jQuery.inArray("", parsedData) !== 0) { 38 // initPopup(); 39 // } else if ($("body").hasClass("year_end_popup_active")) { 40 // initPopup(); 41 // } 42 // } else if ($("body").hasClass("year_end_popup_active")) { 43 // initPopup(); 44 // } 45 // }) 46 // .catch(function (error) { 47 // console.log(error); 48 // }); 49 50 //this is for bloggers that were using blockquotes before the redesign 51 var blockquoteChangeDate = new Date("2017-11-06"); 52 var blogPublishDate = new Date( 53 $(".blog_meta_wrapper .article_meta").attr("datetime") 54 ); 55 if ( 56 $("main").find(".page-blog_wrapper").length != 1 || 57 blogPublishDate > blockquoteChangeDate 58 ) { 59 $(".container").ShareBlockquote(); 60 } else { 61 $(".container").BloggerOldBlockquote(); 62 } 63 //end blockquotes 64 65 RegisterVelocityEffects(); 66 animatedDropDowns(); 67 }); 68 $(window).on("load", function () {}); 69 $(window).on("resize", function () { 70 clearTimeout(window.resizedFinished); 71 window.resizedFinished = setTimeout(function () { 72 if (start_Width != window.innerWidth) { 73 //only run if widths change 74 MobileSelects(); 75 start_Width = window.innerWidth; 76 } 77 closeMobileSelects(); 78 }, 250); 79 }); 80 81 $(window) 82 .off("ajax_return_data") 83 .on("ajax_return_data", function () { 84 loadAudioPlayers(); 85 simpleInfoAccordion(); 86 }); 87 window.DoesQueryStringParamExist = function (key) { 88 key = key.replace(/[*+?^$.\[\]{}()|\\\/]/g, "\\$&"); // escape RegEx meta chars 89 var match = location.search.match(new RegExp("[?&]" + key)); 90 return match != null; 91 }; 92 93 window.GetQueryStringParam = function (key) { 94 key = key.replace(/[*+?^$.\[\]{}()|\\\/]/g, "\\$&"); // escape RegEx meta chars 95 var match = location.search.match( 96 new RegExp("[?&]" + key + "=([^&]+)(&|$)") 97 ); 98 return match && decodeURIComponent(match[1].replace(/\+/g, " ")); 99 }; 100 101 function SmoothScrollAnchors() { 102 // rewritten for Chrome bug NOVEMBER 10, 2017 103 //https://css-tricks.com/snippets/jquery/smooth-scrolling/ 104 // Select all links with hashes 105 $('a[href*="#"]') 106 // Remove links that don't actually link to anything 107 .not('[href="#"]') 108 .not('[href="#0"]') 109 .not("[data-toggle]") 110 .not(".coursehash a") 111 .not(".popup-photo") 112 .not(".popup-breakout") 113 .click(function (event) { 114 // Grab height of fixed header 115 var headHeight = $("header").outerHeight(); 116 // On-page links 117 if ( 118 location.pathname.replace(/^\//, "") == 119 this.pathname.replace(/^\//, "") && 120 location.hostname == this.hostname 121 ) { 122 // Figure out element to scroll to 123 var target = $(this.hash); 124 target = target.length 125 ? target 126 : $("[name=" + this.hash.slice(1) + "]"); 127 // Does a scroll target exist? 128 if (target.length) { 129 // Only prevent default if animation is actually gonna happen 130 event.preventDefault(); 131 $("html, body").animate( 132 { 133 scrollTop: target.offset().top - headHeight, 134 }, 135 1000, 136 function () { 137 // Callback after animation 138 if (history.replaceState) { 139 history.replaceState(null, null, target.selector); 140 } else { 141 location.hash = target.selector; 142 } 143 // Don't scroll on focus! 144 $.fn.focusNoScroll = function () { 145 var x = window.scrollX, 146 y = window.scrollY; 147 this.focus(); 148 window.scrollTo(x, y); 149 return this; //chainability 150 }; 151 // Must change focus, but don't scroll! 152 var $target = $(target);
153 $target.focusNoScroll(); 154 if ($target.is(":focus")) { 155 // Checking if the target was focused 156 return false; 157 } else { 158 $target.attr("tabindex", "-1"); // Adding tabindex for elements not focusable 159 $target.focusNoScroll(); // Set focus again 160 } 161 } 162 ); 163 } 164 } 165 }); 166 } 167 //workaround for new Chrome bug with focus 168 $.fn.focusNoScroll = function () { 169 var x = window.scrollX, 170 y = window.scrollY; 171 this.focus(); 172 window.scrollTo(x, y); 173 return this; 174 }; 175 176 $.fn.VideoOverlayClick = function () { 177 this.each(function () { 178 var video_element = $(this).find(".vid-play-inline"); 179 if ($(video_element).length > 0) { 180 $(video_element).each(function () { 181 $(".vid-cover", this).click(function () { 182 $(this).find(".vid-graphic").hide(); 183 var embedCode = $(this).find(".vid-code").data("embed"); 184 $(this).find(".vid-code").html(embedCode); 185 $(this).find(".vid-code").fitVids(); 186 var videoContainer = $(this).find(".vid-code iframe"); 187 var videoCode = videoContainer.attr("src"); 188 if (videoCode.indexOf("connect.haivision.com") == -1) { 189 if (videoCode.indexOf("?")) { 190 //if (videoCode.search('vimeo.com') > 0) { 191 $(this) 192 .find("iframe") 193 .attr( 194 "src", 195 $(this).find("iframe").attr("src") + "&autoplay=1&rel=0" 196 ); 197 } else { 198 $(this) 199 .find("iframe") 200 .attr( 201 "src", 202 $(this).find("iframe").attr("src") + "?autoplay=1&rel=0" 203 ); 204 } 205 } 206 }); 207 }); 208 } 209 }); 210 }; 211 212 window.VimeoOverlayImage = function () { 213 if ($("span[data-vimeo-id]").length > 0) { 214 $("span[data-vimeo-id]").each(function (index) { 215 var vimeoId = $(this).data("vimeo-id"); 216 // Endpoint: https://vimeo.com/api/oembed.json?url=https%3A//vimeo.com/ 217 $.getJSON( 218 "https://vimeo.com/api/oembed.json?url=https%3A//vimeo.com/" + 219 vimeoId, 220 { 221 format: "json", 222 width: "960", 223 }, 224 function (data) { 225 $("span[data-vimeo-id=" + vimeoId + "]").css({ 226 "background-image": "url(" + data.thumbnail_url + ")", 227 }); 228 } 229 ); 230 }); 231 } 232 }; 233 234 $.fn.ShareBlockquote = function () { 235 var quote = ""; 236 var url_link; 237 this.each(function () { 238 var blockquote_element = $(this).find("blockquote").not(".twitter-tweet"); 239 if ($(blockquote_element).length > 0) 240 $(blockquote_element).each(function () { 241 if ($(this).find(".blockquote-share").length < 1) { 242 quote = $(this).text(); 243 var shareHTML = 244 '<div class="blockquote-share">\ 245 <span class="s-options">\ 246 <a class="blockquote_tw" data-quote="' + 247 quote + 248 '" href="javascript:void(0);">\ 249 <i class="fa fa-twitter"></i>\ 250 </a>\ 251 <a class="blockquote_fb" data-quote="' + 252 quote + 253 '" href="javascript:void(0);">\ 254 <i class="fa fa-facebook"></i>\ 255 </a>\ 256 </span>\ 257 </div>'; 258 259 $(this).append(shareHTML); 260 } 261 }); 262 }); 263 264 $(".blockquote_fb") 265 .unbind("click") 266 .click(function () { 267 url_link = window.location.href; 268 window.open( 269 "http://www.facebook.com/sharer/sharer.php?u=" + 270 url_link + 271 ""e=" + 272 '"' + 273 $(this).data("quote") + 274 '"', 275 "Share on Facebook", 276 "width=600,height=500,scrollbars=yes,titlebar=no,toolbar=no,location=no,status=no,menubar=no,scrollbars=no" 277 ); 278 }); 279 $(".blockquote_tw") 280 .unbind("click") 281 .click(function () { 282 url_link = window.location.href; 283 quote_text = $(this).data("quote"); 284 quote_texts = quote_text.replace(";", " -"); 285 286 window.open( 287 "http://twitter.com/share?text=" + 288 '"' + 289 quote_texts + 290 '"' + 291 "&url=" + 292 url_link, 293 "Share on Twitter", 294 "width=600,height=500,scrollbars=yes,titlebar=no,toolbar=no,location=no,status=no,menubar=no,scrollbars=no" 295 ); 296 }); 297 }; 298 299 $.fn.BloggerOldBlockquote = function () { 300 this.each(function () { 301 var blockquote_element = $(this).find("blockquote").not(".twitter-tweet"); 302 if ($(blockquote_element).length > 0) 303 $(blockquote_element).each(function () { 304 $(this).addClass("past_blockquote"); 305 }); 306 }); 307 }; 308 309 function RegisterVelocityEffects() {
310 $(".fadeup").velocity("transition.slideUpIn", { 311 stagger: 200, 312 drag: true, 313 duration: 1200, 314 }); 315 } 316 317 function simpleInfoAccordion() { 318 $(".accordion-simple") 319 .find(".accordion-toggle") 320 .off("click") 321 .on("click", function () { 322 $(this).next().slideToggle("slow"); 323 if ($(this).find(".acc-arrow").hasClass("acc-down-arrow")) { 324 $(this).find(".acc-arrow").removeClass("acc-down-arrow"); 325 } else { 326 $(this).find(".acc-arrow").addClass("acc-down-arrow"); 327 } 328 }); 329 } 330 331 window.ResponsiveTables = function () { 332 if ($(".entry-content table").length > 0) { 333 $(".entry-content table").each(function () { 334 if (!$(this).parent().hasClass("table-responsive")) { 335 $(this).wrap('<div class="table-responsive"></div>'); 336 } 337 }); 338 } 339 }; 340 341 window.ResponsiveIFRAMES = function () { 342 // this fitvids resizes all youtube and vimeo iframes and makes them responsive 343 $(".container").fitVids(); 344 $(".container-fluid").fitVids(); 345 }; 346 347 window.ResponsiveFlickrEmbed = function () { 348 var flickrFrames = $( 349 'a[href*="flickr"]:not(.img_caption),a[href*="flickr"] img, img[src*="staticflickr"],a[data-flickr-embed="true"]' 350 ); 351 if (flickrFrames.length > 0) { 352 $(flickrFrames).each(function (index) { 353 $(this).css({ width: "100%" }); 354 }); 355 } 356 }; 357 window.LivestreamBannerSectionInit = function () { 358 if ($(".livestream_banner_section").length > 0) { 359 $(".livestream_banner_section").velocity("slideDown", { 360 delay: 700, 361 duration: 1000, 362 easing: "easeOutQuart", 363 }); 364 $(".livesteam_banner_close").click(function () { 365 $("body").removeClass("livestream_banner_active"); 366 $(".livestream_banner_section").velocity("slideUp", { 367 duration: 1000, 368 easing: "easeOutQuart", 369 }); 370 }); 371 } 372 }; 373 window.subsplashDarkMode = function () { 374 var wp_tgc_subsplash_mode = getCookie("wp_tgc_subsplash_mode"); 375 if (wp_tgc_subsplash_mode) { 376 $("body").addClass("subsplash_dark_mode"); 377 } else { 378 $("body").removeClass("subsplash_dark_mode"); 379 } 380 }; 381 window.luthernewsletterCallback = function luthernewsletterCallback() { 382 if ($(".luther_newsletter_form").length > 0) { 383 //for each newsletter add the recaptcha and callback if it hasn't been added yet 384 $(".luther_newsletter_form .g-recaptcha:not(.reCaptcha_rendered)").each( 385 function (index, el) { 386 //adding this class to pickup on if it already has reCaptcha enabled 387 $(this).addClass("reCaptcha_rendered"); 388 var object = $(this); 389 var object_ID = object.attr("id"); 390 391 //this adds the reCaptcha and sets the widget id on each form 392 var widgetId = grecaptcha.render(object.attr("id"), { 393 sitekey: "6LecGD4UAAAAACClySulfNhGtPVGlQXGaY_X8gM9", 394 isolated: true, 395 callback: function (token) { 396 object.parents("form").find(".g-recaptcha-response").val(token); 397 var $form = object.parents("form"); 398 var $form_wrapper = $($form).parent(".mc_embed_signup_wrap"); 399 $(".mce-success-response", $form_wrapper).hide(); 400 $(".mce-error-response", $form_wrapper).hide(); 401 mailchimpAPI($form); 402 function mailchimpAPI($form) { 403 $.fn.form = function () { 404 var formData = {}; 405 $form.find("[name]").each(function () { 406 formData[this.name] = this.value; 407 }); 408 return formData; 409 }; 410 411 var group_ids = []; 412 $(".mch-groups.groups input:checkbox:checked").map(function () { 413 group_ids.push($(this).attr("name")); 414 }); 415 var list_ids = []; 416 $(".mch-groups.lists input:checkbox:checked").map(function () { 417 list_ids.push($(this).attr("name")); 418 }); 419 420 var email_value = $($form).find('input[name="EMAIL"]').val(); 421 422 // var formdata = $form.form(); 423 // var has_MCLISTID = formdata.MCLISTID; 424 //if fields are empty stop and show the error message - this is also happening serverside 425 // if ((group_ids == '' && !has_MCLISTID) || (group_ids == '' && list_ids == '') || email_value == '') { 426 if ((group_ids == "" && list_ids == "") || email_value == "") { 427 $(".mce-error-response", $form_wrapper).show(); 428 } else { 429 var $form_widget_id = $( 430 ".reCaptcha_rendered", 431 $form_wrapper 432 ).attr("data-widget-id"); 433 grecaptcha.execute($form_widget_id); 434 $(".btn", $form_wrapper) 435 .prop("disabled", true) 436 .css({ cursor: "not-allowed" }); 437 $.ajax({ 438 url: $form.attr("action"), 439 type: "POST", 440 dataType: "json", 441 data: { 442 action: "mailchimpsubscribe", 443 groups: group_ids, 444 lists: list_ids, 445 formData: $form.form(), 446 }, 447 success: function (result) { 448 if (!result.success) { 449 $(".mce-error-response", $form_wrapper).show(); 450 $(".mce-success-response", $form_wrapper).hide(); 451 } else { 452 $(".mce-error-response", $form_wrapper).hide(); 453 $(".mce-success-response", $form_wrapper).show(); 454 } 455 $(".btn", $form_wrapper) 456 .prop("disabled", false) 457 .css({ cursor: "pointer" }); 458 grecaptcha.reset($form_widget_id); 459 }, 460 error: function (result) { 461 $(".mce-success-response", $form_wrapper).hide(); 462 $(".mce-error-response", $form_wrapper).show(); 463 464 grecaptcha.reset($form_widget_id); 465 }, 466 }); 467 } 468 } 469 }, 470 }); 471 $(this).attr("data-widget-id", widgetId); //adding the widget id 472 } 473 ); 474 } 475 }; 476 window.newsletterCallback = function newsletterCallback() { 477 if ($(".newsletter_signup_form").length > 0) { 478 //for each newsletter add the recaptcha and callback if it hasn't been added yet 479 $(".newsletter_signup_form .g-recaptcha:not(.reCaptcha_rendered)").each( 480 function (index, el) { 481 //adding this class to pickup on if it already has reCaptcha enabled 482 $(this).addClass("reCaptcha_rendered"); 483 var object = $(this); 484 var object_ID = object.attr("id"); 485 486 //this adds the reCaptcha and sets the widget id on each form 487 var widgetId = grecaptcha.render(object.attr("id"), { 488 sitekey: "6LecGD4UAAAAACClySulfNhGtPVGlQXGaY_X8gM9", 489 isolated: true, 490 callback: function (token) { 491 object.parents("form").find(".g-recaptcha-response").val(token); 492 var $form = object.parents("form"); 493 var $form_wrapper = $($form).parent( 494 ".stay_up_to_date_form_wrapper" 495 ); 496 497 mailchimpAPI($form); 498 function mailchimpAPI($form) { 499 $.fn.form = function () { 500 var formData = {}; 501 $form.find("[name]").each(function () { 502 formData[this.name] = this.value; 503 }); 504 return formData; 505 }; 506 507 var group_ids = []; 508 $(".mch-groups input:checkbox:checked").map(function () { 509 group_ids.push($(this).attr("name")); 510 }); 511 var email_value = $($form).find('input[name="EMAIL"]').val(); 512 513 var formdata = $form.form(); 514 var has_MCLISTID = formdata.MCLISTID; 515 //if fields are empty stop and show the error message - this is also happening serverside 516 if ((group_ids == "" && !has_MCLISTID) || email_value == "") { 517 $(".stay_up_to_date_unsuccess", $form_wrapper).collapse( 518 "show" 519 ); 520 } else { 521 var $form_widget_id = $( 522 ".reCaptcha_rendered", 523 $form_wrapper 524 ).attr("data-widget-id"); 525 grecaptcha.execute($form_widget_id); 526 $(".button", $form_wrapper) 527 .prop("disabled", true) 528 .css({ cursor: "not-allowed" }); 529 $.ajax({ 530 url: $form.attr("action"), 531 type: "POST", 532 dataType: "json", 533 data: { 534 action: "mailchimpsubscribe", 535 groups: group_ids, 536 formData: $form.form(), 537 }, 538 success: function (result) { 539 if (!result.success) { 540 $(".stay_up_to_date_unsuccess", $form_wrapper).html( 541 result.data 542 ); 543 $(".stay_up_to_date_success", $form_wrapper).collapse( 544 "hide" 545 ); 546 $(".stay_up_to_date_unsuccess", $form_wrapper).collapse( 547 "show" 548 ); 549 } else { 550 $(".stay_up_to_date_unsuccess", $form_wrapper).collapse( 551 "hide" 552 ); 553 $(".stay_up_to_date_success", $form_wrapper).html( 554 result.data 555 ); 556 $(".stay_up_to_date_success", $form_wrapper).collapse( 557 "show" 558 ); 559 560 // if its a drawer, hide it after 4 seconds and remove it so it doesn't come in again 561 if ( 562 $($form_wrapper)
563 .closest(".newsletter_signup_form") 564 .hasClass("is_drawer") 565 ) { 566 var newsDrawer = $("body").find( 567 ".stay_up_to_date.newsletter_signup_form.is_drawer.come_in" 568 ); 569 setTimeout(function () { 570 $(newsDrawer).hide(400); 571 setTimeout(function () { 572 $(newsDrawer).remove(); 573 newsDrawer.length = 0; 574 }, 1200); 575 }, 4000); 576 } 577 } 578 $(".button", $form_wrapper) 579 .prop("disabled", false) 580 .css({ cursor: "pointer" }); 581 grecaptcha.reset($form_widget_id); 582 }, 583 error: function (result) { 584 $(".stay_up_to_date_success", $form_wrapper).html( 585 result.data 586 ); 587 $(".stay_up_to_date_success", $form_wrapper).collapse( 588 "show" 589 ); 590 591 grecaptcha.reset($form_widget_id); 592 }, 593 }); 594 } 595 } 596 }, 597 }); 598 $(this).attr("data-widget-id", widgetId); //adding the widget id 599 } 600 ); 601 602 $(".newsletter_signup_form .form-control").focus(function () { 603 $(this) 604 .parents(".stay_up_to_date_form_wrapper") 605 .find(".stay_up_to_date_unsuccess.show") 606 .collapse("hide"); 607 $(this) 608 .parents(".stay_up_to_date_form_wrapper") 609 .find(".stay_up_to_date_success.show") 610 .collapse("hide"); 611 }); 612 } 613 }; 614 //campaign monitor form submit 615 //https://stackoverflow.com/questions/50405977/how-to-verify-google-recaptcha-v3-response 616 $(".js-cm-form") 617 .off("submit") 618 .on("submit", function (event) { 619 event.preventDefault(); 620 621 const formElem = $(this); 622 const callback = formElem.data("iscCallback"); 623 const emailField = formElem.find('input[type="email"]'); 624 const errorText = $(".mce-error-response").html(); 625 const errorElem = formElem.find(".mce-error-response"); 626 const successElem = formElem.find(".mce-success-response"); 627 const recaptchaAction = formElem.find("[name='action']").val(); 628 const isDrawer = formElem.closest(".is_drawer"); 629 630 formElem.addClass("disabled"); 631 632 if ( 633 (formElem.find("input:checkbox").length && 634 !formElem.find("input:checkbox:checked").length) || 635 !emailField.val() 636 ) { 637 successElem.hide(); 638 errorElem.show(); 639 formElem.removeClass("disabled"); 640 return; 641 } 642 643 grecaptcha.ready(() => { 644 grecaptcha 645 .execute("6LdvjuIUAAAAAEJrlUeMsNppRpsCOwCAeUy2xWvb", { 646 action: recaptchaAction, 647 }) 648 .then((token) => { 649 formElem.find('[name="token"]').val(token); 650 $.ajax({ 651 url: "https://www.thegospelcoalition.org/wp-content/themes/sage/tgc-ajax.php?action=cmsubscribe", 652 type: "POST", 653 dataType: "json", 654 data: formElem.serialize(), 655 success: (result) => { 656 formElem.removeClass("disabled"); 657 errorElem.hide(); 658 successElem.show(); 659 emailField.val(""); 660 if (typeof callback === "function") { 661 callback(); 662 } 663 setTimeout(() => { 664 if (isDrawer) { 665 $(isDrawer) 666 .find(".newsletter_drawer_close") 667 .trigger("click"); 668 } 669 }, 4000); 670 }, 671 error: (result) => { 672 formElem.removeClass("disabled"); 673 successElem.hide(); 674 errorElem.html( 675 result.responseText.substr( 676 0, 677 result.responseText.indexOf("{") 678 ) 679 ); 680 errorElem.show(); 681 682 setTimeout(() => { 683 errorElem.hide(); 684 errorElem.html(errorText); 685 }, 4000); 686 }, 687 }); 688 }); 689 }); 690 }); 691 692 function closeMobileSelects() { 693 $(document) 694 .off("click", ".select_closebtn") 695 .on("click", ".select_closebtn", function (e) { 696 e.preventDefault(); 697 $("select").select2("close"); 698 }); 699 } 700 window.MobileSelects = function () { 701 if ( 702 $("select.select2-hidden-accessible").length > 0 && 703 $("select").hasClass("select2-hidden-accessible") 704 ) { 705 var select2_selects = $("select.select2-hidden-accessible") 706 .not(".playback-rate") 707 .not(".select2_plain"); 708 $(select2_selects).each(function () { 709 //$(this).css({ 'min-width': '100%' }); 710 711 var minResSearch = 712 $(this).data("search-limit") != undefined 713 ? $(this).data("search-limit") 714 : 10; 715 $(this).select2("destroy").select2({ 716 dropdownCssClass: "custom_select_dd", 717 selectionCssClass: "custom_selection", 718 minimumResultsForSearch: minResSearch, 719 }); 720 721 if (window.innerWidth < 768) { 722 //if mobile 723 $(this) 724 .off("select2:open") 725 .on("select2:open", function (e) { 726 $(".select2-container").not(".select2").hide(); 727 setTimeout(function () { 728 $(".select2-container").not(".select2").fadeIn(500); 729 }, 200); 730 731 if ( 732 !$(".select2-container") 733 .not(".select2") 734 .hasClass("custom_select_open") 735 ) { 736 var labeltxt = $(this).parent().find(".sort_label").text(); 737 if (!labeltxt || labeltxt == "") { 738 labeltxt = $(this).parent().find(".filter-label").text(); 739 } 740 if (!labeltxt || labeltxt == "") { 741 labeltxt = ""; 742 } 743 var heading = 744 '<div class="select_list_header d-flex align-items-center justify-content-between d-md-none">\ 745 <div class="select_list_header_text">' + 746 labeltxt + 747 '</div>\ 748 <a href="#" class="select_closebtn">Ã</a>\ 749 </div>'; 750 var checkcontainerExists = setInterval(function () { 751 if ($(".select2-container").not(".select2").length > 0) { 752 if ( 753 !$(".select2-search").hasClass("select2-search--hide") 754 ) { 755 $(".select2-container") 756 .not(".select2") 757 .addClass("has_search_field"); 758 } 759 $(".select2-container") 760 .not(".select2") 761 .addClass("custom_select_open") 762 .prepend(heading); 763 clearInterval(checkcontainerExists); 764 } 765 }, 50); 766 } 767 }); 768 $(this) 769 .off("select2:closing") 770 .on("select2:closing", function (e) { 771 $("body").find(".select_list_header").remove(); 772 }); 773 $(this) 774 .off("select2:close") 775 .on("select2:close", function (e) { 776 $(this).select2("destroy").select2({ 777 dropdownCssClass: "custom_select_dd", 778 selectionCssClass: "custom_selection", 779 minimumResultsForSearch: 11, 780 }); 781 }); 782 } 783 }); 784 } 785 }; 786 787 function initPopup() { 788 //if(!getCookie('yet_popup_closed') && window.location.href.indexOf("donate") == -1){ 789 var noYearEndArray = ["donate", "global2022", "global-appeal"]; 790 var windowLocation = window.location.href; 791 //debugger; 792 if ( 793 !getCookie("yet_popup_closed") && 794 !noYearEndArray.some((substring) => windowLocation.includes(substring)) 795 ) { 796 var $popup = $("#year-end-takeover"); 797 setTimeout(function () { 798 $popup.css("visibility", "visible").fadeTo(1000, 1); 799 }, 2000); 800 $popup.find(".close").click(function () { 801 $popup.hide();
802 setCookie("yet_popup_closed", true, 1); 803 }); 804 $popup.find(".yet_button_group a").click(function () { 805 $popup.hide(); 806 setCookie("yet_popup_closed", true, 1); 807 }); 808 } 809 } 810 function injectPrintImages() { 811 document.querySelectorAll(".article-graphic").forEach(function (wrap) { 812 // Avoid duplicating 813 var ancestor = wrap.closest(".article-image-graphic-wrap"); 814 if (!ancestor) return; 815 816 // Only inject if not already present in the parent 817 if (ancestor.parentNode.querySelector(".article-background-print-img")) 818 return; 819 820 var bg = wrap.querySelector(".article-background"); 821 if (!bg) return; 822 823 var style = window.getComputedStyle(bg); 824 var bgImage = style.backgroundImage; 825 826 var match = bgImage && bgImage.match(/url\(["']?(.*?)["']?\)/i); 827 if (!match || !match[1]) return; 828 829 var img = document.createElement("img"); 830 img.src = match[1]; 831 img.alt = ""; // or set via data-attr if you want 832 img.className = "article-background-print-img"; 833 img.style.display = "none"; 834 835 ancestor.parentNode.insertBefore(img, ancestor); 836 }); 837 } 838 839 function initPrintListeners() { 840 window.addEventListener("beforeprint", injectPrintImages); 841 842 if (window.matchMedia) { 843 var mql = window.matchMedia("print"); 844 mql.addListener(function (e) { 845 if (e.matches) { 846 injectPrintImages(); 847 } 848 }); 849 } 850 } 851})(jQuery); 852function animatedDropDowns() { 853 $ = jQuery; 854 if ($(".anim_dropdown").length > 0) { 855 $(".anim_dropdown_btn") 856 .unbind("click") 857 .on("click", function () { 858 var dropdown = $(this).parent().find(".anim_dropdown"); 859 if ($(dropdown).is(":visible")) { 860 $(this).parent().removeClass("drop_open"); 861 $(dropdown).velocity("slideUp", 500, [250, 30]); 862 } else { 863 $(this).parent().addClass("drop_open"); 864 $(dropdown).velocity("slideDown", 1000, [500, 30]); 865 } 866 }); 867 } 868} 869function GetGuid() { 870 function s4() { 871 return Math.floor((1 + Math.random()) * 0x10000) 872 .toString(16) 873 .substring(1); 874 } 875 return ( 876 s4() + 877 s4() + 878 "-" + 879 s4() + 880 "-" + 881 s4() + 882 "-" + 883 s4() + 884 "-" + 885 s4() + 886 s4() + 887 s4() 888 ); 889} 890var waitForFinalEvent = (function () { 891 var timers = {}; 892 return function (callback, ms, uniqueId) { 893 if (!uniqueId) { 894 uniqueId = "Don't call this twice without a uniqueId"; 895 } 896 if (timers[uniqueId]) { 897 clearTimeout(timers[uniqueId]); 898 } 899 timers[uniqueId] = setTimeout(callback, ms); 900 }; 901})(); 902function loadAudioPlayers() { 903 var $ = jQuery; 904 905 // old player 906 var speedDefaults = [ 907 { 908 rate: 0.5, 909 title: "Playback Speed 0.5x", 910 label: ".5x", 911 }, 912 { 913 rate: 1, 914 title: "Playback Speed 1x", 915 label: "1x", 916 }, 917 { 918 rate: 1.5, 919 title: "Playback Speed 1.5x", 920 label: "1.5x", 921 }, 922 { 923 rate: 2, 924 title: "Playback Speed 2x", 925 label: "2x", 926 }, 927 ]; 928 if ($("audio.sitewide_player").length > 0) { 929 //https://github.com/mediaelement/mediaelement/blob/master/docs/api.md#methods 930 $("audio.sitewide_player").mediaelementplayer({ 931 features: ["playpause", "current", "progress", "duration", "download"], 932 success: function (mediaElement, domObject, instance) { 933 $(".mejs-playpause-button").addClass( 934 "GTM_audio_event_play GTM_sitewide_player" 935 ); 936 var buttons = '<select class="playback-rate">'; 937 for (var i = 0; i < speedDefaults.length; i++) { 938 buttons += '<option class="playback-rate-button"'; 939 buttons += speedDefaults[i].rate == 1 ? ' selected="selected"' : ""; 940 buttons += ' value="' + speedDefaults[i].rate + '"'; 941 buttons += ' title="' + speedDefaults[i].title + '"'; 942 buttons += ' aria-label="' + speedDefaults[i].title + '"'; 943 buttons += ' tab-index="0">'; 944 buttons += speedDefaults[i].label; 945 buttons += "</option>"; 946 } 947 buttons += "</select>"; 948 949 var $els = $(".mejs-container"); 950 951 for (i = 0; i < $els.length; i++) { 952 var audioTag = $($els[i]).find("audio")[0]; 953 $(buttons) 954 .find(".playback-rate-button") 955 .attr("aria-controls", audioTag.id); 956 var $controls = $($els[i]).find(".mejs-controls"); 957 if ( 958 $controls.length > 0 && 959 $controls.find(".playback-rate").length == 0 960 ) { 961 $controls.find(".mejs-time-rail").after(buttons); 962 963 $controls 964 .find(".mejs-time, .mejs-time-rail") 965 .prependTo($controls) 966 .wrapAll( 967 '<div class="swp_time_wrapper swp_time_' + audioTag.id + '"/>' 968 ); 969 $controls 970 .find(".mejs-playpause-button,.playback-rate, .select2") 971 .wrapAll('<div class="swp_playback_controls"/>'); 972 $controls 973 .find(".mejs-playpause-button") 974 .before('<a href="#" class="swp_rewind"></a>') 975 .after('<a href="#" class="swp_fastforward"></a>'); 976 if ( 977 script_vars.postType == "conference_media" || 978 script_vars.is_podcast 979 ) { 980 var downloadSvg = 981 '<svg xmlns="http://www.w3.org/2000/svg" width="11" height="11" viewbox="0 0 11 11"><path id="download" d="M8.8,5.983l-3.3,3.3-3.3-3.3L2.8,5.376,5.07,7.642V0H5.93V7.642L8.2,5.376ZM11,10.141H0V11H11Zm0,0" fill="#fff"></path></svg>'; 982 var audioSrc = audioTag.getAttribute("src"); 983 $controls 984 .find(".swp_playback_controls") 985 .append( 986 '<a download href="' + 987 audioSrc + 988 '" class="download-audio">' + 989 downloadSvg + 990 "</a>" 991 ); 992 } 993 } 994 } 995 996 $(".playback-rate").select2({ 997 minimumResultsForSearch: -1, 998 dropdownCssClass: "playback_speed_drop", 999 closeOnSelect: true, 1000 }); 1001 1002 $(".sitewide_player + .download").each(function (index, el) { 1003 $(this).appendTo($(this).prev().find(".mejs-time-rail")); 1004 }); 1005 1006 mediaElement.addEventListener( 1007 "ended", 1008 function (e) { 1009 mediaElement.currentTime = 0; 1010 mediaElement.pause(); 1011 mediaElement.load(); 1012 }, 1013 false 1014 ); 1015 mediaElement.addEventListener("playing", function (e) {}, false); 1016 }, 1017 }); 1018 $("body").on("click", ".swp_rewind", function (e) { 1019 e.preventDefault(); 1020 var selectEl = $(this), 1021 audioElm = selectEl 1022 .parent() 1023 .closest(".sitewide_player") 1024 .find(".mejs-mediaelement") 1025 .find("audio")[0]; 1026 audioElm.currentTime -= 15; 1027 }); 1028 $("body").on("click", ".swp_fastforward", function (e) { 1029 e.preventDefault(); 1030 var selectEl = $(this), 1031 audioElm = selectEl 1032 .parent() 1033 .closest(".sitewide_player") 1034 .find(".mejs-mediaelement") 1035 .find("audio")[0]; 1036 audioElm.currentTime += 30; 1037 }); 1038 1039 $("body").on("change", ".playback-rate", function (e) { 1040 var selectEl = $(this), 1041 audioElm = selectEl 1042 .parent() 1043 .closest(".sitewide_player") 1044 .find(".mejs-mediaelement") 1045 .find("audio")[0], 1046 rate = selectEl.val(); 1047 audioElm.setPlaybackRate(rate); 1048 }); 1049 } else if ($("audio.js-player").length > 0) { 1050 //new player 1051 1052 //var controls = ["progress", "current-time", "duration", "rewind", "play", "fast-forward", "settings", "download"]; 1053 1054 var controls = ` 1055<div class="plyr__controls flex-column"> 1056 <div class="plyr__progress w-100"> 1057 <input data-plyr="seek" type="range" min="0" max="100" step="0.01" value="
10570" aria-label="Seek"> 1058 <progress class="plyr__progress__buffer" min="0" max="100" value="0">% buffered</progress> 1059 <span role="tooltip" class="plyr__tooltip">00:00</span> 1060 </div> 1061 <div class="w-100"> 1062 <div class="d-flex justify-content-between"> 1063 <div class="plyr__time plyr__time--current" aria-label="Current time"></div> 1064 <div class="plyr__time plyr__time--duration" aria-label="Duration"></div> 1065 </div> 1066 </div> 1067 <div class="position-relative d-flex w-100 justify-content-center custom-controls"> 1068 <button type="button" class="plyr__control" data-plyr="rewind"> 1069 <img role="presentation" src="https://www.thegospelcoalition.org/wp-content/themes/luther/images/audio-player/rewind.svg" /> 1070 </button> 1071 <button type="button" class="plyr__control" aria-label="Play, {title}" data-plyr="play"> 1072 <img class="icon--pressed" role="presentation" src="https://www.thegospelcoalition.org/wp-content/themes/luther/images/audio-player/pause-btn.svg"/> 1073 <img class="icon--not-pressed" role="presentation" src="https://www.thegospelcoalition.org/wp-content/themes/luther/images/audio-player/play-btn.svg"/> 1074 </button> 1075 <button type="button" class="plyr__control" data-plyr="fast-forward"> 1076 <img role="presentation" src="https://www.thegospelcoalition.org/wp-content/themes/luther/images/audio-player/fast-forward.svg" /> 1077 </button> 1078 <div class="position-absolute d-flex h-100 justify-content-end align-items-center speed-download-container"> 1079 <div class="d-flex speed-download"> 1080 <select class="playback-rate"> 1081 <option title="Playback Rate 0.5x" value="0.5">0.5x</option> 1082 <option title="Playback Rate 1x" value="1" selected>1x</option> 1083 <option title="Playback Rate 1.5x" value="1.5">1.5x</option> 1084 <option title="Playback Rate 2x" value="2">2x</option> 1085 </select> 1086 <a class="plyr__controls__item plyr__control plyr_download" href="" target="_blank" download="" data-plyr="download"><svg aria-hidden="true" focusable="false"><use xlink:href="#plyr-download"></use></svg><span class="plyr__sr-only">Download</span></a> 1087 </div> 1088 </div> 1089 </div> 1090 1091</div> 1092`; 1093 1094 const players = Plyr.setup(".js-player", { 1095 controls: controls, 1096 seekTime: 15, 1097 }); 1098 1099 $(".playback-rate").select2({ 1100 minimumResultsForSearch: -1, 1101 dropdownCssClass: "speed-dropdown", 1102 }); 1103 1104 window.player = players; 1105 1106 function secondsToTime(e) { 1107 var h = Math.floor(e / 3600) 1108 .toString() 1109 .padStart(2, "0"), 1110 m = Math.floor((e % 3600) / 60) 1111 .toString() 1112 .padStart(2, "0"), 1113 s = Math.floor(e % 60) 1114 .toString() 1115 .padStart(2, "0"); 1116 return h + ":" + m + ":" + s; 1117 } 1118 1119 players.forEach((p) => { 1120 // On first play, lazy-load from data-src into the <audio> and start playing. 1121 p.on("play", (evt) => { 1122 const inst = evt.detail?.plyr; 1123 if (!inst) return; 1124 1125 const media = inst.media; // <audio> element 1126 // If nothing loaded yet, hydrate it from data-src 1127 if (!media.currentSrc || media.currentSrc === "") { 1128 const dataSrc = media.getAttribute("data-src"); 1129 if (dataSrc) { 1130 const sourceEl = media.querySelector("source") || media; 1131 sourceEl.src = dataSrc; 1132 1133 // Must reload after changing <source>/<audio> src 1134 media.addEventListener( 1135 "loadedmetadata", 1136 () => { 1137 // kick playback once metadata is ready 1138 media.play().catch(() => {}); 1139 // set download button href 1140 const $dl = $(inst.elements.container).find(".plyr_download"); 1141 if ($dl.length) $dl.attr("href", media.currentSrc || dataSrc); 1142 }, 1143 { once: true } 1144 ); 1145 media.load(); 1146 return; // we'll resume in loadedmetadata 1147 } 1148 } 1149 1150 // Pause other players
1151 players.forEach((other) => { 1152 if (other !== inst) other.pause(); 1153 }); 1154 1155 // Keep download href in sync 1156 const $dl = $(inst.elements.container).find(".plyr_download"); 1157 if ($dl.length) $dl.attr("href", media.currentSrc); 1158 }); 1159 1160 p.on("ready", (evt) => { 1161 const inst = evt.detail?.plyr; 1162 if (!inst) return; 1163 const media = inst.media; 1164 1165 // Duration fallback 1166 const $container = $(inst.elements.container); 1167 const durationEl = $container.find(".plyr__time--duration"); 1168 let duration = media.duration; 1169 1170 if (!duration || isNaN(duration)) { 1171 const fallback = $container.find("audio").attr("data-duration"); 1172 if (fallback) durationEl.text(fallback); 1173 } else { 1174 const durationText = secondsToTime(duration); 1175 if (!durationEl.text()) durationEl.text(durationText); 1176 } 1177 1178 media.playbackRate = 1; 1179 }); 1180 1181 // Keep download link synced when metadata arrives (covers lazy-load case) 1182 p.on("loadedmetadata", (evt) => { 1183 const inst = evt.detail?.plyr; 1184 if (!inst) return; 1185 const $dl = $(inst.elements.container).find(".plyr_download"); 1186 if ($dl.length) $dl.attr("href", inst.media.currentSrc); 1187 }); 1188 }); 1189 1190 // Fast-forward +15s 1191 $('[data-plyr="fast-forward"]') 1192 .off("click") 1193 .on("click", function () { 1194 var audio = $(this).closest(".plyr").find("audio")[0]; 1195 audio.currentTime += 15; 1196 }); 1197 $(".playback-rate") 1198 .off("select2:select") 1199 .on("select2:select", function () { 1200 var selectEl = $(this); 1201 var audioTag = selectEl.closest(".plyr").find("audio")[0]; 1202 audioTag.playbackRate = parseFloat(selectEl.val()); 1203 }); 1204 //add source to download button 1205 $(".plyr_download").each(function () { 1206 var source = 1207 $(this).closest(".plyr").find("audio").attr("data-src") || ""; 1208 if (source) $(this).attr("href", source); 1209 }); 1210 } else if ($("audio:not('#conference-media-player')").length > 0) { 1211 $("audio").mediaelementplayer({ 1212 features: ["playpause", "current", "progress", "duration"], 1213 success: function (mediaElement, domObject) { 1214 $(".mejs-playpause-button").addClass("GTM_audio_event_play"); 1215 var buttons = '<select class="playback-rate">'; 1216 for (var i = 0; i < speedDefaults.length; i++) { 1217 buttons += '<option class="playback-rate-button"'; 1218 buttons += speedDefaults[i].rate == 1 ? ' selected="selected"' : ""; 1219 buttons += ' value="' + speedDefaults[i].rate + '"'; 1220 buttons += ' title="' + speedDefaults[i].title + '"'; 1221 buttons += ' aria-label="' + speedDefaults[i].title + '"'; 1222 buttons += ' tab-index="0">'; 1223 buttons += speedDefaults[i].label; 1224 buttons += "</option>"; 1225 } 1226 buttons += "</select>"; 1227 1228 var $els = $(".mejs-container"); 1229 1230 for (i = 0; i < $els.length; i++) { 1231 var audioTag = $($els[i]).find("audio")[0]; 1232 $(buttons) 1233 .find(".playback-rate-button") 1234 .attr("aria-controls", audioTag.id); 1235 var $controls = $($els[i]).find(".mejs-controls"); 1236 if ( 1237 $controls.length > 0 && 1238 $controls.find(".playback-rate").length == 0 1239 ) { 1240 $controls.find(".mejs-time-rail").after(buttons); 1241 } 1242 } 1243 $(".playback-rate").select2({ minimumResultsForSearch: -1 }); 1244 $(".luther-mejs-container + .download").each(function (index, el) { 1245 $(this).appendTo($(this).prev().find(".mejs-time-rail")); 1246 }); 1247 $("body").on("change", ".playback-rate", function () { 1248 var selectEl = $(this), 1249 audioTag = selectEl 1250 .parent() 1251 .siblings(".mejs-mediaelement") 1252 .find("audio")[0], 1253 rate = selectEl.val(); 1254 audioTag.setPlaybackRate(rate); 1255 }); 1256 mediaElement.addEventListener("playing", function (e) {}, false); 1257 }, 1258 }); 1259 } 1260} 1261 1262//https://themergency.com/an-alternative-to-jquerys-getscript-function.html 1263jQuery.initLoadScript = function (url, arg1, arg2) { 1264 var cache = false, 1265 callback = null; 1266 //arg1 and arg2 can be interchangable 1267 if ($.isFunction(arg1)) { 1268 callback = arg1; 1269 cache = arg2 || cache; 1270 } else {
1271 cache = arg1 || cache; 1272 callback = arg2 || callback; 1273 } 1274 var load = true; 1275 //check all existing script tags in the page for the url 1276 jQuery('script[type="text/javascript"]').each(function () { 1277 return (load = url != $(this).attr("src")); 1278 }); 1279 if (load) { 1280 //didn't find it in the page, so load it 1281 jQuery.ajax({ 1282 type: "GET", 1283 url: url, 1284 success: callback, 1285 dataType: "script", 1286 cache: cache, 1287 }); 1288 } else { 1289 //already loaded so just call the callback 1290 if (jQuery.isFunction(callback)) { 1291 callback.call(this); 1292 } 1293 } 1294}; 1295 1296function setCookie(name, value, days) { 1297 var expires = ""; 1298 if (days) { 1299 var date = new Date(); 1300 date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000); 1301 expires = "; expires=" + date.toUTCString(); 1302 } 1303 document.cookie = name + "=" + (value || "") + expires + "; path=/"; 1304} 1305 1306function getCookie(name) { 1307 var nameEQ = name + "="; 1308 var ca = document.cookie.split(";"); 1309 for (var i = 0; i < ca.length; i++) { 1310 var c = ca[i]; 1311 while (c.charAt(0) == " ") c = c.substring(1, c.length); 1312 if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length); 1313 } 1314 return null; 1315} 1316 1317function eraseCookie(name) { 1318 document.cookie = name + "=; Path=/; Expires=Thu, 01 Jan 1970 00:00:01 GMT;"; 1319}
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.