1 2 3<!DOCTYPE html> 4<html id="ctl00_ctl00_mainhtml" xmlns="http://www.w3.org/1999/xhtml" lang="en"> 5<head id="ctl00_ctl00_Head1"> 6 7
7<script type="text/javascript"> 8 if (window.name == "refresh") 9 { 10 window.stop(); 11 window.location.replace(window.location.pathname + window.location.search + window.location.hash); 12 window.name = ""; 13 } 14 </script>
14 15 16 <link rel="preconnect" href="https://fonts.googleapis.com" /><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="" /><meta name="viewport" content="width=device-width, initial-scale=1" /> 17 18 <link rel="stylesheet" type="text/css" href="https://media-sixrivers.mynews360.com/css/smartBanner.css?v=1.14.5.35260" media="screen" /> 19 <link rel="stylesheet" type="text/css" href="https://media-sixrivers.mynews360.com/css/common.css?v=1.14.5.35260" /> 20 <link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css?family=Roboto:400,400i,700,700i,900,900i&display=swap" /> 21 <link rel="stylesheet" type="text/css" href="https://media-sixrivers.mynews360.com/css/fontawesome/fontawesome.min.css?v=1.14.5.35260" /> 22 <link rel="stylesheet" type="text/css" href="https://media-sixrivers.mynews360.com/css/fontawesome/brands.min.css?v=1.14.5.35260" /> 23 24 25
25<script type="text/javascript" src="https://media-sixrivers.mynews360.com/js/jquery.js?v=1.14.5.35260"></script>
25 26 27
27<script type="text/javascript"> 28 var _fbClientId = "309214499646406", 29 _fbTarget = window.location.pathname, 30 _baseUri = "https://timesnews.mynews360.com/", 31 _webUri = "https://johnsoncitypress.com", 32 _mediaUrl = "https://media-sixrivers.mynews360.com/", 33 _logoTemplate = "https://media-sixrivers.mynews360.com/logo/%%TEAM_ID%%/213", 34 _schoolTemplate = "https://media-sixrivers.mynews360.com/logo/%%SCHOOL_ID%%/school/%%SPORT_ID%%/213", 35 _MTS_PHOTO_TEMPLATE = "https://media-sixrivers.mynews360.com/image/%%IMG_ID%%/%%SIZE%%/%%TEAM_ID%%/%%USER_ID%%/%%TYPE%%/213", 36 _portalId = 213, 37 _portalName = "Johnson City Press", 38 _portalUrl = "https://johnsoncitypress.com/", 39 _twitterName = "", 40 _facebookName = "", 41 _region = "Johnson City", 42 _MTS_widgetsReady = false, 43 _MTS_userId = -1, 44 _MTS_thirdPartyId = null, 45 _MTS_urlRegex = new RegExp("[|+<>\\*%&:\\?\\/\\\\\'.\"\\r\\n#]", "g"), 46 _isAdmin = false, 47 _warnAboutRejected = false, 48 _MTS_cssList = [], 49 _MTS_jsList = [], 50 _MTS_pageVP = "~/newsHome.aspx", 51 _MTS_pageId = 0, 52 _MTS_histCount = 0, 53 _MTS_sportsEnabled = false, 54 _MTS_uploadLimit = 41943040, 55 56 _hasAlerts = false, 57 _registrationPop = false, 58 _targetList = "team,".split(','); 59 </script>
59 60 61 62 <!--[if lt IE 9]> 63 <link rel="stylesheet" type="text/css" href="../../../../../%3C%25=SportsApp.Core.MediaUrl%20%25%3Ecss/?pid=<%=_portal.Id %>&ie=1&v=<%=SportsApp.Core.Version %>" /> 64 <![endif]--> 65
66<script type="text/javascript"> 67 var _pageName = "Johnson City Press | News | Local News News"; 68 var _ga_sport = ""; 69 var _ga_school = ""; 70 var _ga_guid = ""; 71 var _ga_author = ""; 72 var _ga_pagetype = "newshome"; 73 var _ga_tags = ""; 74</script>
vendor: 67 bytes, lines 74-76
74 75 76<script async src="https://www.googletagmanager.com/gtag/js?id=
76G-ZJ4C47N33G
vendor: 13 bytes, line 76
76"></script>
77<script type="text/javascript"> 78
vendor: 144 bytes, lines 78-82
78window.dataLayer = window.dataLayer || []; 79 function gtag() { dataLayer.push(arguments); } 80 gtag('js', new Date()); 81 82 gtag('config', '
82G-ZJ4C47N33G
vendor: 5 bytes, line 82
82');
83</script>
83 84 85 86<style> 87#silktide-wrapper { 88 --focus: 0 0 0 2px #ffffff, 0 0 0 4px #000000, 0 0 0 6px #ffffff; 89 --boxShadow: -5px 5px 10px 0px #00000012, 0px 0px 50px 0px #0000001a; 90 --fontFamily: Helvetica Neue, Segoe UI, Arial, sans-serif; 91 --primaryColor: white; 92 --backgroundColor: #050505; 93 --textColor: #F4F0DF; 94 --backdropBackgroundColor: #00000033; 95 --backdropBackgroundBlur: 0px; 96 --cookieIconColor: #050505; 97 --cookieIconBackgroundColor: white; 98} 99</style>
100<script> 101 // Initialize the dataLayer 102 window.dataLayer = window.dataLayer || []; 103 104 // Create the gtag function that pushes to the dataLayer 105 function gtag() { 106 dataLayer.push(arguments); 107 } 108 109 // Set consent defaults 110 gtag('consent', 'default', { 111 analytics_storage: localStorage.getItem('silktideCookieChoice_analytics') === 'true' ? 'granted' : 'denied', 112 ad_storage: localStorage.getItem('silktideCookieChoice_marketing') === 'true' ? 'granted' : 'denied', 113 ad_user_data: localStorage.getItem('silktideCookieChoice_marketing') === 'true' ? 'granted' : 'denied', 114 ad_personalization: localStorage.getItem('silktideCookieChoice_marketing') === 'true' ? 'granted' : 'denied', 115 functionality_storage: localStorage.getItem('silktideCookieChoice_necessary') === 'true' ? 'granted' : 'denied', 116 security_storage: localStorage.getItem('silktideCookieChoice_necessary') === 'true' ? 'granted' : 'denied' 117 }); 118</script>
118 119 120<!--Google Consent Default Config-->
121<script> 122 // Define dataLayer and the gtag function 123 window.dataLayer = window.dataLayer || []; 124 function gtag(){dataLayer.push(arguments);} 125 126 // Set default consent to 'granted' as a placeholder 127 if(localStorage.getItem('consentMode') === null){ 128 gtag('consent', 'default', { 129 'ad_storage': 'granted', 130 'ad_user_data': 'granted', 131 'ad_personalization': 'granted', 132 'analytics_storage': 'granted', 133 'personalization_storage': 'granted', 134 'security_storage': 'granted', 135 'functionality_storage': 'granted', 136 }); 137 // To further redact your ads data when ad_storage is denied, set ads_data_redaction to true 138 gtag('set', 'ads_data_redaction', true); 139 } else { 140 gtag('consent', 'default', JSON.parse(localStorage.getItem('consentMode'))); 141 } 142</script>
142 143 144<style> 145/* 146 Silktide Consent Manager - https://silktide.com/consent-manager/ 147*/ 148 149/* -------------------------------- 150 Global Styles - These elements exist in the main DOM and styling is limited to positioning and animation 151-------------------------------- */ 152/* Wrapper (Global) */ 153#silktide-wrapper { 154 position: fixed; 155 bottom: 0; 156 right: 0; 157 width: 100%; 158 height: 100%; 159 z-index: 99999; 160 pointer-events: none; 161 border: 0px; 162 display: flex; 163 justify-content: center; 164 align-items: center; 165 overscroll-behavior: contain; 166 overflow-y: auto; 167 } 168 169/* Backdrop (Global) */ 170#silktide-backdrop-global { 171 position: fixed; 172 top: 0; 173 left: 0; 174 width: 100%; 175 height: 100%; 176 pointer-events: auto; 177 border: 0px; 178 display: none; 179} 180 181/* -------------------------------- 182 Links 183-------------------------------- */ 184#silktide-wrapper a { 185 all: unset; 186 display: inline-block; 187 color: var(--primaryColor); 188 text-decoration: underline; 189} 190 191#silktide-wrapper a:hover { 192 cursor: pointer; 193 color: var(--textColor); 194} 195 196/* -------------------------------- 197 Focus Styles 198-------------------------------- */ 199#silktide-wrapper a:focus, 200#silktide-wrapper #silktide-banner button:focus, 201#silktide-wrapper #silktide-modal button:focus, 202#silktide-wrapper #silktide-cookie-icon:focus { 203 outline: none; 204 box-shadow: var(--focus); 205 border-radius: 5px; 206} 207 208#silktide-wrapper #silktide-cookie-icon:focus { 209 border-radius: 50%; 210} 211 212/* -------------------------------- 213 General Styles 214-------------------------------- */ 215 216#silktide-wrapper .st-button { 217 color: var(--backgroundColor); 218 background-color: var(--primaryColor); 219 border: 2px solid var(--primaryColor); 220 padding: 10px 20px; 221 text-decoration: none; 222 text-align: center; 223 display: inline-block; 224 font-size: 16px; 225 line-height: 24px; 226 cursor: pointer; 227 border-radius: 5px; 228} 229 230#silktide-wrapper .st-button--primary { 231} 232 233#silktide-wrapper .st-button--primary:hover { 234 background-color: var(--backgroundColor); 235 color: var(--primaryColor); 236} 237 238#silktide-wrapper .st-button--secondary { 239 background-color: var(--backgroundColor); 240 color: var(--primaryColor); 241} 242 243#silktide-wrapper .st-button--secondary:hover { 244 background-color: var(--primaryColor); 245 color: var(--backgroundColor); 246} 247 248/* -------------------------------- 249 Banner 250-------------------------------- */ 251#silktide-banner { 252 font-family: var(--fontFamily); 253 color: var(--textColor); 254 background-color: var(--backgroundColor); 255 box-sizing: border-box; 256 padding: 32px; 257 border-radius: 5px; 258 pointer-events: auto; 259 border: 0px; 260 position: fixed; 261 bottom: 16px; 262 right: 16px; 263 width: 600px; 264 overflow: auto; 265 max-width: calc(100% - 32px); 266 max-height: calc(100vh - 32px); 267 transform: translate(0, -20px); 268 opacity: 0; 269 animation: silktide-slideInDown 350ms ease-out forwards; 270 animation-delay: 0.3s; 271 box-shadow: -5px 5px 10px 0px #00000012, 0px 0px 50px 0px #0000001a; 272} 273 274#silktide-banner:focus { 275 border-radius: 50%; 276} 277 278#silktide-banner.center { 279 top: 50%; 280 left: 50%; 281 bottom: auto; 282 right: auto; 283 position: fixed; 284 transform: translate(-50%, calc(-50% - 20px)); 285 animation: silktide-slideInDown-center 350ms ease-out forwards; 286} 287 288#silktide-banner.bottomLeft { 289 bottom: 16px; 290 left: 16px; 291 position: fixed; 292} 293 294#silktide-banner.bottomCenter { 295 bottom: 16px; 296 left: 50%; 297 position: fixed; 298 transform: translate(-50%, -20px); 299 animation: silktide-slideInDown-bottomCenter 350ms ease-out forwards; 300} 301 302#silktide-banner .preferences { 303 display: flex; 304 gap: 5px; 305 border: none; 306 padding: 15px 0px; 307 background-color: transparent; 308 color: var(--primaryColor); 309 cursor: pointer; 310 font-size: 16px; 311} 312 313#silktide-banner .preferences span { 314 display: block; 315 white-space: nowrap; 316 text-decoration: underline; 317} 318 319#silktide-banner .preferences span:hover { 320 color: var(--textColor); 321} 322 323#silktide-banner .preferences:after { 324 display: block; 325 content: '>'; 326 text-decoration: none; 327} 328 329#silktide-banner p { 330 font-size: 16px; 331 line-height: 24px; 332 margin: 0px 0px 15px; 333} 334 335#silktide-banner a { 336 display: inline-block; 337 color: var(--primaryColor); 338 text-decoration: underline; 339 background-color: var(--backgroundColor); 340} 341 342#silktide-banner a:hover {
343 color: var(--textColor); 344} 345 346#silktide-banner a.silktide-logo { 347 display: flex; 348 align-items: center; 349 justify-content: center; 350 fill: var(--primaryColor); /* passed down to svg > path */ 351 margin-left: auto; 352 width: 48px; 353 height: 48px; 354} 355 356 357#silktide-banner .actions { 358 display: flex; 359 gap: 16px; 360 flex-direction: column; 361 margin-top: 24px; 362} 363 364@media (min-width: 600px) { 365 #silktide-banner .actions { 366 flex-direction: row; 367 align-items: center; 368 } 369} 370 371#silktide-banner .actions-row { 372 display: flex; 373 gap: 16px; 374 flex-direction: row; 375 align-items: center; 376 justify-content: space-between; 377 flex-grow: 1; 378} 379 380/* -------------------------------- 381 Modal 382-------------------------------- */ 383#silktide-modal { 384 display: none; 385 pointer-events: auto; 386 overflow: auto; 387 width: 800px; 388 max-width: 100%; 389 max-height: 100%; 390 border: 0px; 391 transform: translate(0px, -20px); 392 opacity: 0; 393 animation: silktide-slideInUp-center 350ms ease-out forwards; 394 box-shadow: -5px 5px 10px 0px #00000012, 0px 0px 50px 0px #0000001a; 395 font-family: var(--fontFamily); 396 color: var(--textColor); 397 flex-direction: column; 398 padding: 30px; 399 background-color: var(--backgroundColor); 400 border-radius: 5px; 401 box-sizing: border-box; 402} 403 404/* -------------------------------- 405 Modal - Header 406-------------------------------- */ 407#silktide-modal .silk-header { 408 display: flex; 409 justify-content: space-between; 410 align-items: center; 411 margin-bottom: 20px; 412 gap: 16px; 413} 414 415#silktide-modal h1 { 416 font-family: var(--fontFamily); 417 color: var(--textColor); 418 font-size: 24px; 419 font-weight: 500; 420 margin: 0px; 421} 422 423#silktide-modal .modal-close { 424 display: inline-flex; 425 border: none; 426 padding: 13px; 427 border: 0px; 428 cursor: pointer; 429 background: var(--backgroundColor); 430 color: var(--primaryColor); 431} 432 433#silktide-modal .modal-close svg { 434 fill: var(--primaryColor); 435} 436 437/* -------------------------------- 438 Modal - Content 439-------------------------------- */ 440 441#silktide-modal section { 442 flex: 1; 443 margin-top: 32px; 444} 445 446#silktide-modal section::-webkit-scrollbar {
447 display: block; /* Force scrollbars to show */ 448 width: 5px; /* Width of the scrollbar */ 449} 450 451#silktide-modal section::-webkit-scrollbar-thumb { 452 background-color: var(--textColor); /* Color of the scrollbar thumb */ 453 border-radius: 10px; /* Rounded corners for the thumb */ 454} 455 456#silktide-modal p { 457 font-size: 16px; 458 line-height: 24px; 459 color: var(--textColor); 460 margin: 0px 0px 15px; 461} 462 463#silktide-modal p:last-of-type { 464 margin: 0px; 465} 466 467#silktide-modal fieldset { 468 padding: 0px; 469 border: none; 470 margin: 0px 0px 32px; 471} 472 473#silktide-modal fieldset:last-of-type { 474 margin: 0px; 475} 476 477#silktide-modal legend { 478 padding: 0px; 479 margin: 0px 0px 10px; 480 font-weight: 700; 481 color: var(--textColor); 482 font-size: 16px; 483} 484 485#silktide-modal .cookie-type-content { 486 display: flex; 487 justify-content: space-between; 488 align-items: flex-start; 489 gap: 24px; 490} 491 492/* -------------------------------- 493 Modal - Switches 494-------------------------------- */ 495#silktide-modal .switch { 496 flex-shrink: 0; 497 position: relative; 498 display: inline-block; 499 height: 34px; 500 width: 74px; 501 cursor: pointer; 502} 503 504#silktide-modal .switch:focus-within { 505 outline: none; 506 box-shadow: var(--focus); 507 border-radius: 25px; 508} 509 510#silktide-modal .switch input { 511 opacity: 0; 512 position: absolute; 513} 514 515/* Unchecked Switch Styles */ 516#silktide-modal .switch__pill { 517 position: relative; 518 display: block; 519 height: 34px; 520 width: 74px; 521 background: var(--textColor); 522 border-radius: 25px; 523} 524 525#silktide-modal .switch__dot { 526 position: absolute; 527 top: 2px; 528 left: 2px; 529 display: block; 530 height: 30px; 531 width: 30px; 532 background: var(--backgroundColor); 533 border-radius: 50%; 534 transition: left 150ms ease-out; 535} 536 537#silktide-modal .switch__off, 538#silktide-modal .switch__on { 539 text-transform: uppercase; 540 font-size: 15px; 541 font-weight: 500; 542 color: var(--backgroundColor); 543 position: absolute; 544 top: 7px; 545 right: 8px; 546 transition: right 150ms ease-out, opacity 150ms ease-out; 547} 548 549#silktide-modal .switch__off { 550 opacity: 1; 551} 552 553#silktide-modal .switch__on { 554 opacity: 0; 555} 556 557/* Checked Switch Styles */ 558#silktide-modal .switch input:checked + .switch__pill { 559 background: var(--primaryColor); 560} 561 562#silktide-modal .switch input:checked ~ .switch__dot { 563 left: calc(100% - 32px); 564} 565 566#silktide-modal .switch input:checked ~ .switch__off { 567 right: calc(100% - 32px); 568 opacity: 0; 569} 570 571#silktide-modal .switch input:checked ~ .switch__on { 572 right: calc(100% - 34px); 573 opacity: 1; 574} 575 576/* Disabled Switch Styles */ 577#silktide-modal .switch input:disabled + .switch__pill { 578 opacity: 0.65; 579 cursor: not-allowed; 580} 581 582/* -------------------------------- 583 Modal - Footer 584-------------------------------- */ 585#silktide-modal .silk-footer { 586 display: flex; 587 flex-direction: column; 588 gap: 16px; 589 margin-top: 24px; 590} 591 592@media (min-width: 600px) { 593 #silktide-modal .silk-footer { 594 flex-direction: row; 595 align-items: center; 596 } 597} 598 599#silktide-modal .silk-footer a { 600 margin-left: auto; 601 padding: 14px 0px; 602} 603 604/* Cookie Icon */ 605#silktide-cookie-icon { 606 display: none !important; 607 position: fixed; 608 bottom: 10px; 609 left: 10px; 610 justify-content: center; 611 align-items: center; 612 width: 60px; 613 height: 60px; 614 border-radius: 50%; 615 padding: 0px; 616 border: none; 617 background-color: var(--cookieIconColor); 618 cursor: pointer; 619 box-shadow: 0px 0px 6px 0px #0000001a; 620 pointer-events: auto; 621 animation: silktide-fadeIn 0.3s ease-in-out forwards; 622} 623 624#silktide-cookie-icon.bottomRight { 625 left: auto; 626 right: 10px; 627} 628 629#silktide-cookie-icon svg { 630 fill: var(--cookieIconBackgroundColor); 631} 632 633/* -------------------------------- 634 Backdrop 635-------------------------------- */ 636#silktide-backdrop { 637 display: none; 638 position: absolute; 639 top: 0; 640 left: 0; 641 width: 100%; 642 height: 100%; 643 background-color: var(--backdropBackgroundColor); 644 backdrop-filter: blur(var(--backdropBackgroundBlur)); 645 pointer-events: all; 646} 647 648/* -------------------------------- 649 Animations 650-------------------------------- */ 651@keyframes silktide-fadeIn { 652 from { 653 opacity: 0; 654 } 655 to { 656 opacity: 1; 657 } 658} 659 660@keyframes silktide-slideInDown { 661 from { 662 opacity: 0; 663 transform: translateY(-20px); 664 } 665 to { 666 opacity: 1; 667 transform: translateY(0); 668 } 669} 670 671@keyframes silktide-slideInDown-center { 672 from { 673 opacity: 0; 674 transform: translate(-50%, calc(-50% - 20px)); 675 } 676 to { 677 opacity: 1; 678 transform: translate(-50%, -50%); 679 } 680} 681 682@keyframes silktide-slideInDown-bottomCenter { 683 from { 684 opacity: 0; 685 transform: translate(-50%, -20px); 686 } 687 to { 688 opacity: 1; 689 transform: translate(-50%, 0); 690 } 691} 692 693@keyframes silktide-slideInUp-center { 694 from { 695 opacity: 0; 696 transform: translate(0px, 20px); 697 } 698 to { 699 opacity: 1; 700 transform: translate(0px, 0px); 701 } 702} 703 704</style>
705<script> 706// Silktide Consent Manager - https://silktide.com/consent-manager/ 707 708class SilktideCookieBanner { 709 constructor(config) { 710 this.config = config; // Save config to the instance 711 712 this.wrapper = null; 713 this.banner = null; 714 this.modal = null; 715 this.cookieIcon = null; 716 this.backdrop = null; 717 718 this.createWrapper(); 719 720 if (this.shouldShowBackdrop()) { 721 this.createBackdrop(); 722 } 723 724 this.createCookieIcon(); 725 this.createModal(); 726 727 if (this.shouldShowBanner()) { 728 this.createBanner(); 729 this.showBackdrop(); 730 } else { 731 this.showCookieIcon(); 732 } 733 734 this.setupEventListeners(); 735 736 if (this.hasSetInitialCookieChoices()) { 737 this.loadRequiredCookies(); 738 this.runAcceptedCookieCallbacks(); 739 } 740 } 741 742 destroyCookieBanner() { 743 // Remove all cookie banner elements from the DOM 744 if (this.wrapper && this.wrapper.parentNode) { 745 this.wrapper.parentNode.removeChild(this.wrapper); 746 } 747 748 // Restore scrolling 749 this.allowBodyScroll(); 750 751 // Clear all references 752 this.wrapper = null; 753 this.banner = null; 754 this.modal = null; 755 this.cookieIcon = null; 756 this.backdrop = null; 757 } 758 759 // ---------------------------------------------------------------- 760 // Wrapper 761 // ---------------------------------------------------------------- 762 createWrapper() { 763 this.wrapper = document.createElement('div'); 764 this.wrapper.id = 'silktide-wrapper'; 765 document.body.insertBefore(this.wrapper, document.body.firstChild); 766 } 767 768 // ---------------------------------------------------------------- 769 // Wrapper Child Generator 770 // ---------------------------------------------------------------- 771 createWrapperChild(htmlContent, id) { 772 // Create child element 773 const child = document.createElement('div'); 774 child.id = id; 775 child.innerHTML = htmlContent; 776 777 // Ensure wrapper exists 778 if (!this.wrapper || !document.body.contains(this.wrapper)) { 779 this.createWrapper(); 780 } 781 782 // Append child to wrapper 783 this.wrapper.appendChild(child); 784 return child; 785 } 786 787 // ---------------------------------------------------------------- 788 // Backdrop 789 // ---------------------------------------------------------------- 790 createBackdrop() { 791 this.backdrop = this.createWrapperChild(null, 'silktide-backdrop'); 792 } 793 794 showBackdrop() { 795 if (this.backdrop) { 796 this.backdrop.style.display = 'block'; 797 }
798 // Trigger optional onBackdropOpen callback 799 if (typeof this.config.onBackdropOpen === 'function') { 800 this.config.onBackdropOpen(); 801 } 802 } 803 804 hideBackdrop() { 805 if (this.backdrop) { 806 this.backdrop.style.display = 'none'; 807 } 808 809 // Trigger optional onBackdropClose callback 810 if (typeof this.config.onBackdropClose === 'function') { 811 this.config.onBackdropClose(); 812 } 813 } 814 815 shouldShowBackdrop() { 816 return this.config?.background?.showBackground || false; 817 } 818 819 // update the checkboxes in the modal with the values from localStorage 820 updateCheckboxState(saveToStorage = false) { 821 const preferencesSection = this.modal.querySelector('#cookie-preferences'); 822 const checkboxes = preferencesSection.querySelectorAll('input[type="checkbox"]'); 823 824 checkboxes.forEach((checkbox) => { 825 const [, cookieId] = checkbox.id.split('cookies-'); 826 const cookieType = this.config.cookieTypes.find(type => type.id === cookieId); 827 828 if (!cookieType) return; 829 830 if (saveToStorage) { 831 // Save the current state to localStorage and run callbacks 832 const currentState = checkbox.checked; 833 834 if (cookieType.required) { 835 localStorage.setItem( 836 `silktideCookieChoice_${cookieId}${this.getBannerSuffix()}`, 837 'true' 838 ); 839 } else { 840 localStorage.setItem( 841 `silktideCookieChoice_${cookieId}${this.getBannerSuffix()}`, 842 currentState.toString() 843 ); 844 845 // Run appropriate callback 846 if (currentState && typeof cookieType.onAccept === 'function') { 847 cookieType.onAccept(); 848 } else if (!currentState && typeof cookieType.onReject === 'function') { 849 cookieType.onReject(); 850 } 851 } 852 } else { 853 // When reading values (opening modal) 854 if (cookieType.required) { 855 checkbox.checked = true; 856 checkbox.disabled = true; 857 } else { 858 const storedValue = localStorage.getItem( 859 `silktideCookieChoice_${cookieId}${this.getBannerSuffix()}` 860 ); 861 862 if (storedValue !== null) { 863 checkbox.checked = storedValue === 'true'; 864 } else { 865 checkbox.checked = !!cookieType.defaultValue; 866 } 867 } 868 } 869 }); 870 } 871 872 setInitialCookieChoiceMade() { 873 window.localStorage.setItem(`silktideCookieBanner_InitialChoice${this.getBannerSuffix()}`, 1); 874 } 875 876 // ---------------------------------------------------------------- 877 // Consent Handling 878 // ---------------------------------------------------------------- 879 handleCookieChoice(accepted) { 880 // We set that an initial choice was made regardless of what it was so we don't show the banner again 881 this.setInitialCookieChoiceMade(); 882 883 this.removeBanner(); 884 this.hideBackdrop(); 885 this.toggleModal(false); 886 this.showCookieIcon(); 887 888 this.config.cookieTypes.forEach((type) => { 889 // Set localStorage and run accept/reject callbacks 890 if (type.required == true) { 891 localStorage.setItem(`silktideCookieChoice_${type.id}${this.getBannerSuffix()}`, 'true'); 892 if (typeof type.onAccept === 'function') { type.onAccept() } 893 } else { 894 localStorage.setItem( 895 `silktideCookieChoice_${type.id}${this.getBannerSuffix()}`, 896 accepted.toString(), 897 ); 898 899 if (accepted) { 900 if (typeof type.onAccept === 'function') { type.onAccept(); } 901 } else { 902 if (typeof type.onReject === 'function') { type.onReject(); } 903 } 904 } 905 }); 906 907 // Trigger optional onAcceptAll/onRejectAll callbacks 908 if (accepted && typeof this.config.onAcceptAll === 'function') { 909 if (typeof this.config.onAcceptAll === 'function') { this.config.onAcceptAll(); } 910 } else if (typeof this.config.onRejectAll === 'function') { 911 if (typeof this.config.onRejectAll === 'function') { this.config.onRejectAll(); } 912 } 913 914 // finally update the checkboxes in the modal with the values from localStorage 915 this.updateCheckboxState(); 916 } 917 918 getAcceptedCookies() { 919 return (this.config.cookieTypes || []).reduce((acc, cookieType) => { 920 acc[cookieType.id] = 921 localStorage.getItem(`silktideCookieChoice_${cookieType.id}${this.getBannerSuffix()}`) === 922 'true'; 923 return acc; 924 }, {}); 925 } 926 927 runAcceptedCookieCallbacks() { 928 if (!this.config.cookieTypes) return; 929 930 const acceptedCookies = this.getAcceptedCookies();
931 this.config.cookieTypes.forEach((type) => { 932 if (type.required) return; // we run required cookies separately in loadRequiredCookies 933 if (acceptedCookies[type.id] && typeof type.onAccept === 'function') { 934 if (typeof type.onAccept === 'function') { type.onAccept(); } 935 } 936 }); 937 } 938 939 runRejectedCookieCallbacks() { 940 if (!this.config.cookieTypes) return; 941 942 const rejectedCookies = this.getRejectedCookies(); 943 this.config.cookieTypes.forEach((type) => { 944 if (rejectedCookies[type.id] && typeof type.onReject === 'function') { 945 if (typeof type.onReject === 'function') { type.onReject(); } 946 } 947 }); 948 } 949 950 /** 951 * Run through all of the cookie callbacks based on the current localStorage values 952 */ 953 runStoredCookiePreferenceCallbacks() { 954 this.config.cookieTypes.forEach((type) => { 955 const accepted = 956 localStorage.getItem(`silktideCookieChoice_${type.id}${this.getBannerSuffix()}`) === 'true'; 957 // Set localStorage and run accept/reject callbacks 958 if (accepted) { 959 if (typeof type.onAccept === 'function') { type.onAccept(); } 960 } else { 961 if (typeof type.onReject === 'function') { type.onReject(); } 962 } 963 }); 964 } 965 966 loadRequiredCookies() { 967 if (!this.config.cookieTypes) return;
968 this.config.cookieTypes.forEach((cookie) => { 969 if (cookie.required && typeof cookie.onAccept === 'function') { 970 if (typeof cookie.onAccept === 'function') { cookie.onAccept(); } 971 } 972 }); 973 } 974 975 // ---------------------------------------------------------------- 976 // Banner 977 // ---------------------------------------------------------------- 978 getBannerContent() { 979 const bannerDescription = 980 this.config.text?.banner?.description || 981 "<p>We use cookies on our site to enhance your user experience, provide personalized content, and analyze our traffic.</p>"; 982 983 // Accept button 984 const acceptAllButtonText = this.config.text?.banner?.acceptAllButtonText || 'Accept all'; 985 const acceptAllButtonLabel = this.config.text?.banner?.acceptAllButtonAccessibleLabel; 986 const acceptAllButton = `<button class="accept-all st-button st-button--primary"${ 987 acceptAllButtonLabel && acceptAllButtonLabel !== acceptAllButtonText 988 ? ` aria-label="${acceptAllButtonLabel}"` 989 : '' 990 }>${acceptAllButtonText}</button>`; 991 992 // Reject button 993 const rejectNonEssentialButtonText = this.config.text?.banner?.rejectNonEssentialButtonText || 'Reject non-essential'; 994 const rejectNonEssentialButtonLabel = this.config.text?.banner?.rejectNonEssentialButtonAccessibleLabel; 995 const rejectNonEssentialButton = `<button class="reject-all st-button st-button--primary"${ 996 rejectNonEssentialButtonLabel && rejectNonEssentialButtonLabel !== rejectNonEssentialButtonText 997 ? ` aria-label="${rejectNonEssentialButtonLabel}"` 998 : '' 999 }>${rejectNonEssentialButtonText}</button>`; 1000 1001 // Preferences button 1002 const preferencesButtonText = this.config.text?.banner?.preferencesButtonText || 'Preferences'; 1003 const preferencesButtonLabel = this.config.text?.banner?.preferencesButtonAccessibleLabel; 1004 const preferencesButton = `<button class="preferences"${ 1005 preferencesButtonLabel && preferencesButtonLabel !== preferencesButtonText 1006 ? ` aria-label="${preferencesButtonLabel}"` 1007 : '' 1008 }><span>${preferencesButtonText}</span></button>`; 1009 1010 1011 // Silktide logo link 1012 const silktideLogo = ` 1013 <a class="silktide-logo" href="https://silktide.com/consent-manager" target="_blank" rel="noreferrer" aria-label="Visit the Silktide Consent Manager page"> 1014 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="25" viewBox="0 0 24 25" fill="inherit"> 1015 <path fill-rule="evenodd" clip-rule="evenodd" d="M14.1096 16.7745C13.8895 17.2055 13.3537 17.3805 12.9129 17.1653L8.28443 14.9055L2.73192 17.7651L11.1025 21.9814C11.909 22.3876 12.8725 22.3591 13.6524 21.9058L20.4345 17.9645C21.2845 17.4704 21.7797 16.5522 21.7164 15.5872L21.7088 15.4704C21.6487 14.5561 21.0962 13.7419 20.2579 13.3326L15.6793 11.0972L10.2283 13.9045L13.71 15.6043C14.1507 15.8195 14.3297 16.3434 14.1096 16.7745ZM8.2627 12.9448L13.7136 10.1375L10.2889 8.46543C9.84803 8.25021 9.66911 7.72629 9.88916 7.29524C10.1093 6.86417 10.6451 6.68921 11.0859 6.90442L15.6575 9.13647L21.2171 6.27325L12.8808 2.03496C12.0675 1.62147 11.0928 1.65154 10.3078 2.11432L3.54908 6.09869C2.70732 6.59492 2.21846 7.50845 2.28139 8.46761L2.29003 8.59923C2.35002 9.51362 2.9026 10.3278 3.7409 10.7371L8.2627 12.9448ZM6.31884 13.9458L2.94386 12.2981C1.53727 11.6113 0.610092 10.2451 0.509431 8.71094L0.500795 8.57933C0.3952 6.96993 1.21547 5.4371 2.62787 4.60447L9.38662 0.620092C10.7038 -0.156419 12.3392 -0.206861 13.7039 0.486938L23.3799 5.40639C23.4551 5.44459 23.5224 5.4918 23.5811 5.54596C23.7105 5.62499 23.8209 5.73754 23.897 5.87906C24.1266 6.30534 23.9594 6.83293 23.5234 7.05744L17.6231 10.0961L21.0549 11.7716C22.4615 12.4583 23.3887 13.8245 23.4893 15.3587L23.497 15.4755C23.6033 17.0947 22.7724 18.6354 21.346 19.4644L14.5639 23.4057C13.2554 24.1661 11.6386 24.214 10.2854 23.5324L0.621855 18.6649C0.477299 18.592 0.361696 18.4859 0.279794 18.361C0.210188 18.2968 0.150054 18.2204 0.10296 18.133C-0.126635 17.7067 0.0406445 17.1792 0.47659 16.9546L6.31884 13.9458Z" fill="inherit"/> 1016 </svg> 1017 </a> 1018 `; 1019 1020 const bannerContent = ` 1021 ${bannerDescription} 1022 <div class="actions"> 1023 ${acceptAllButton} 1024 ${rejectNonEssentialButton} 1025 <div class="actions-row"> 1026 ${preferencesButton} 1027 1028 </div> 1029 </div> 1030 `; 1031 1032 return bannerContent; 1033 } 1034 1035 hasSetInitialCookieChoices() { 1036 return !!localStorage.getItem(`silktideCookieBanner_InitialChoice${this.getBannerSuffix()}`); 1037 } 1038 1039 createBanner() { 1040 // Create banner element 1041 this.banner = this.createWrapperChild(this.getBannerContent(), 'silktide-banner'); 1042 1043 // Add positioning class from config 1044 if (this.banner && this.config.position?.banner) { 1045 this.banner.classList.add(this.config.position.banner); 1046 } 1047 1048 // Trigger optional onBannerOpen callback 1049 if (this.banner && typeof this.config.onBannerOpen === 'function') { 1050 this.config.onBannerOpen(); 1051 } 1052 } 1053 1054 removeBanner() { 1055 if (this.banner && this.banner.parentNode) { 1056 this.banner.parentNode.removeChild(this.banner); 1057 this.banner = null; 1058 1059 // Trigger optional onBannerClose callback 1060 if (typeof this.config.onBannerClose === 'function') { 1061 this.config.onBannerClose(); 1062 } 1063 } 1064 } 1065 1066 shouldShowBanner() { 1067 if (this.config.showBanner === false) { 1068 return false;
1069 } 1070 return ( 1071 localStorage.getItem(`silktideCookieBanner_InitialChoice${this.getBannerSuffix()}`) === null 1072 ); 1073 } 1074 1075 // ---------------------------------------------------------------- 1076 // Modal 1077 // ---------------------------------------------------------------- 1078 getModalContent() { 1079 const preferencesTitle = 1080 this.config.text?.preferences?.title || 'Customize your cookie preferences'; 1081 1082 const preferencesDescription = 1083 this.config.text?.preferences?.description || 1084 "<p>We respect your right to privacy. You can choose not to allow some types of cookies. Your cookie preferences will apply across our website.</p>"; 1085 1086 // Preferences button 1087 const preferencesButtonLabel = this.config.text?.banner?.preferencesButtonAccessibleLabel; 1088 1089 const closeModalButton = `<button class="modal-close"${preferencesButtonLabel ? ` aria-label="${preferencesButtonLabel}"` : ''}> 1090 <svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"> 1091 <path d="M19.4081 3.41559C20.189 2.6347 20.189 1.36655 19.4081 0.585663C18.6272 -0.195221 17.3591 -0.195221 16.5782 0.585663L10 7.17008L3.41559 0.59191C2.6347 -0.188974 1.36655 -0.188974 0.585663 0.59191C-0.195221 1.37279 -0.195221 2.64095 0.585663 3.42183L7.17008 10L0.59191 16.5844C-0.188974 17.3653 -0.188974 18.6335 0.59191 19.4143C1.37279 20.1952 2.64095 20.1952 3.42183 19.4143L10 12.8299L16.5844 19.4081C17.3653 20.189 18.6335 20.189 19.4143 19.4081C20.1952 18.6272 20.1952 17.3591 19.4143 16.5782L12.8299 10L19.4081 3.41559Z"/> 1092 </svg> 1093 </button>`; 1094 1095 1096 const cookieTypes = this.config.cookieTypes || []; 1097 const acceptedCookieMap = this.getAcceptedCookies(); 1098 1099 // Accept button 1100 const acceptAllButtonText = this.config.text?.banner?.acceptAllButtonText || 'Accept all'; 1101 const acceptAllButtonLabel = this.config.text?.banner?.acceptAllButtonAccessibleLabel; 1102 const acceptAllButton = `<button class="preferences-accept-all st-button st-button--primary"${ 1103 acceptAllButtonLabel && acceptAllButtonLabel !== acceptAllButtonText 1104 ? ` aria-label="${acceptAllButtonLabel}"` 1105 : '' 1106 }>${acceptAllButtonText}</button>`; 1107 1108 // Reject button 1109 const rejectNonEssentialButtonText = this.config.text?.banner?.rejectNonEssentialButtonText || 'Reject non-essential'; 1110 const rejectNonEssentialButtonLabel = this.config.text?.banner?.rejectNonEssentialButtonAccessibleLabel; 1111 const rejectNonEssentialButton = `<button class="preferences-reject-all st-button st-button--primary"${ 1112 rejectNonEssentialButtonLabel && rejectNonEssentialButtonLabel !== rejectNonEssentialButtonText 1113 ? ` aria-label="${rejectNonEssentialButtonLabel}"` 1114 : '' 1115 }>${rejectNonEssentialButtonText}</button>`; 1116 1117 // Credit link 1118 const creditLinkText = this.config.text?.preferences?.creditLinkText || ''; 1119 const creditLinkAccessibleLabel = this.config.text?.preferences?.creditLinkAccessibleLabel; 1120 const creditLink = `<a href="https://silktide.com/consent-manager" target="_blank" rel="noreferrer"${ 1121 creditLinkAccessibleLabel && creditLinkAccessibleLabel !== creditLinkText 1122 ? ` aria-label="${creditLinkAccessibleLabel}"` 1123 : '' 1124 }>${creditLinkText}</a>`; 1125 1126 1127 1128 const modalContent = ` 1129 <div class="silk-header"> 1130 <h1>${preferencesTitle}</h1> 1131 ${closeModalButton} 1132 </div> 1133 ${preferencesDescription} 1134 <section id="cookie-preferences"> 1135 ${cookieTypes 1136 .map((type) => { 1137 const accepted = acceptedCookieMap[type.id]; 1138 let isChecked = false; 1139 1140 // if it's accepted then show as checked 1141 if (accepted) { 1142 isChecked = true; 1143 } 1144 1145 // if nothing has been accepted / rejected yet, then show as checked if the default value is true 1146 if (!accepted && !this.hasSetInitialCookieChoices()) { 1147 isChecked = type.defaultValue; 1148 } 1149 1150 return ` 1151 <fieldset> 1152 <legend>${type.name}</legend> 1153 <div class="cookie-type-content"> 1154 <div class="cookie-type-description">${type.description}</div> 1155 <label class="switch" for="cookies-${type.id}"> 1156 <input type="checkbox" id="cookies-${type.id}" ${ 1157 type.required ? 'checked disabled' : isChecked ? 'checked' : '' 1158 } />
1159 <span class="switch__pill" aria-hidden="true"></span> 1160 <span class="switch__dot" aria-hidden="true"></span> 1161 <span class="switch__off" aria-hidden="true">Off</span> 1162 <span class="switch__on" aria-hidden="true">On</span> 1163 </label> 1164 </div> 1165 </fieldset> 1166 `; 1167 }) 1168 .join('')} 1169 </section> 1170 <div class="silk-footer"> 1171 ${acceptAllButton} 1172 ${rejectNonEssentialButton} 1173 ${creditLink} 1174 </div> 1175 `; 1176 1177 return modalContent; 1178 } 1179 1180 createModal() { 1181 // Create banner element 1182 this.modal = this.createWrapperChild(this.getModalContent(), 'silktide-modal'); 1183 } 1184 1185 toggleModal(show) { 1186 if (!this.modal) return; 1187 1188 this.modal.style.display = show ? 'flex' : 'none'; 1189 1190 if (show) { 1191 this.showBackdrop(); 1192 this.hideCookieIcon(); 1193 this.removeBanner(); 1194 this.preventBodyScroll(); 1195 1196 // Focus the close button 1197 const modalCloseButton = this.modal.querySelector('.modal-close'); 1198 modalCloseButton.focus(); 1199 1200 // Trigger optional onPreferencesOpen callback 1201 if (typeof this.config.onPreferencesOpen === 'function') { 1202 this.config.onPreferencesOpen(); 1203 } 1204 1205 this.updateCheckboxState(false); // read from storage when opening 1206 } else { 1207 // Set that an initial choice was made when closing the modal 1208 this.setInitialCookieChoiceMade(); 1209 1210 // Save current checkbox states to storage 1211 this.updateCheckboxState(true); 1212 1213 this.hideBackdrop(); 1214 this.showCookieIcon(); 1215 this.allowBodyScroll(); 1216 1217 // Trigger optional onPreferencesClose callback 1218 if (typeof this.config.onPreferencesClose === 'function') { 1219 this.config.onPreferencesClose(); 1220 } 1221 } 1222 } 1223 1224 // ---------------------------------------------------------------- 1225 // Cookie Icon 1226 // ---------------------------------------------------------------- 1227 getCookieIconContent() { 1228 return ` 1229 <svg width="38" height="38" viewBox="0 0 38 38" fill="none" xmlns="http://www.w3.org/2000/svg"> 1230 <path d="M19.1172 1.15625C19.0547 0.734374 18.7344 0.390624 18.3125 0.328124C16.5859 0.0859365 14.8281 0.398437 13.2813 1.21875L7.5 4.30469C5.96094 5.125 4.71875 6.41406 3.95313 7.98437L1.08594 13.8906C0.320314 15.4609 0.0703136 17.2422 0.375001 18.9609L1.50781 25.4297C1.8125 27.1562 2.64844 28.7344 3.90625 29.9531L8.61719 34.5156C9.875 35.7344 11.4766 36.5156 13.2031 36.7578L19.6875 37.6719C21.4141 37.9141 23.1719 37.6016 24.7188 36.7812L30.5 33.6953C32.0391 32.875 33.2813 31.5859 34.0469 30.0078L36.9141 24.1094C37.6797 22.5391 37.9297 20.7578 37.625 19.0391C37.5547 18.625 37.2109 18.3125 36.7969 18.25C32.7734 17.6094 29.5469 14.5703 28.6328 10.6406C28.4922 10.0469 28.0078 9.59375 27.4063 9.5C23.1406 8.82031 19.7734 5.4375 19.1094 1.15625H19.1172ZM15.25 10.25C15.913 10.25 16.5489 10.5134 17.0178 10.9822C17.4866 11.4511 17.75 12.087 17.75 12.75C17.75 13.413 17.4866 14.0489 17.0178 14.5178C16.5489 14.9866 15.913 15.25 15.25 15.25C14.587 15.25 13.9511 14.9866 13.4822 14.5178C13.0134 14.0489 12.75 13.413 12.75 12.75C12.75 12.087 13.0134 11.4511 13.4822 10.9822C13.9511 10.5134 14.587 10.25 15.25 10.25ZM10.25 25.25C10.25 24.587 10.5134 23.9511 10.9822 23.4822C11.4511 23.0134 12.087 22.75 12.75 22.75C13.413 22.75 14.0489 23.0134 14.5178 23.4822C14.9866 23.9511 15.25 24.587 15.25 25.25C15.25 25.913 14.9866 26.5489 14.5178 27.0178C14.0489 27.4866 13.413 27.75 12.75 27.75C12.087 27.75 11.4511 27.4866 10.9822 27.0178C10.5134 26.5489 10.25 25.913 10.25 25.25ZM27.75 20.25C28.413 20.25 29.0489 20.5134 29.5178 20.9822C29.9866 21.4511 30.25 22.087 30.25 22.75C30.25 23.413 29.9866 24.0489 29.5178 24.5178C29.0489 24.9866 28.413 25.25 27.75 25.25C27.087 25.25 26.4511 24.9866 25.9822 24.5178C25.5134 24.0489 25.25 23.413 25.25 22.75C25.25 22.087 25.5134 21.4511 25.9822 20.9822C26.4511 20.5134 27.087 20.25 27.75 20.25Z" /> 1231 </svg> 1232 `; 1233 } 1234 1235 createCookieIcon() { 1236 this.cookieIcon = document.createElement('button'); 1237 this.cookieIcon.id = 'silktide-cookie-icon'; 1238 this.cookieIcon.title = 'Manage your cookie preferences for this site'; 1239 this.cookieIcon.innerHTML = this.getCookieIconContent(); 1240 1241 if (this.config.text?.banner?.preferencesButtonAccessibleLabel) { 1242 this.cookieIcon.ariaLabel = this.config.text?.banner?.preferencesButtonAccessibleLabel; 1243 } 1244 1245 // Ensure wrapper exists 1246 if (!this.wrapper || !document.body.contains(this.wrapper)) { 1247 this.createWrapper(); 1248 } 1249 1250 // Append child to wrapper 1251 this.wrapper.appendChild(this.cookieIcon); 1252 1253 // Add positioning class from config 1254 if (this.cookieIcon && this.config.cookieIcon?.position) { 1255 this.cookieIcon.classList.add(this.config.cookieIcon.position); 1256 } 1257 1258 // Add color scheme class from config 1259 if (this.cookieIcon && this.config.cookieIcon?.colorScheme) { 1260 this.cookieIcon.classList.add(this.config.cookieIcon.colorScheme); 1261 } 1262 } 1263 1264 showCookieIcon() { 1265 if (this.cookieIcon) { 1266 this.cookieIcon.style.display = 'flex'; 1267 } 1268 } 1269 1270 hideCookieIcon() { 1271 if (this.cookieIcon) { 1272 this.cookieIcon.style.display = 'none'; 1273 } 1274 } 1275 1276 /** 1277 * This runs if the user closes the modal without making a choice for the first time 1278 * We apply the default values and the necessary values as default 1279 */ 1280 handleClosedWithNoChoice() {
1281 this.config.cookieTypes.forEach((type) => { 1282 let accepted = true; 1283 // Set localStorage and run accept/reject callbacks 1284 if (type.required == true || type.defaultValue) { 1285 localStorage.setItem( 1286 `silktideCookieChoice_${type.id}${this.getBannerSuffix()}`, 1287 accepted.toString(), 1288 ); 1289 } else { 1290 accepted = false; 1291 localStorage.setItem( 1292 `silktideCookieChoice_${type.id}${this.getBannerSuffix()}`, 1293 accepted.toString(), 1294 ); 1295 } 1296 1297 if (accepted) { 1298 if (typeof type.onAccept === 'function') { type.onAccept(); } 1299 } else { 1300 if (typeof type.onReject === 'function') { type.onReject(); } 1301 } 1302 // set the flag to say that the cookie choice has been made 1303 this.setInitialCookieChoiceMade(); 1304 this.updateCheckboxState(); 1305 }); 1306 } 1307 1308 // ---------------------------------------------------------------- 1309 // Focusable Elements 1310 // ---------------------------------------------------------------- 1311 getFocusableElements(element) { 1312 return element.querySelectorAll( 1313 'button, a[href], input, select, textarea, [tabindex]:not([tabindex="-1"])', 1314 ); 1315 } 1316 1317 // ---------------------------------------------------------------- 1318 // Event Listeners 1319 // ---------------------------------------------------------------- 1320 setupEventListeners() { 1321 // Check Banner exists before trying to add event listeners 1322 if (this.banner) { 1323 // Get the buttons 1324 const acceptButton = this.banner.querySelector('.accept-all'); 1325 const rejectButton = this.banner.querySelector('.reject-all'); 1326 const preferencesButton = this.banner.querySelector('.preferences'); 1327 1328 // Add event listeners to the buttons 1329 acceptButton?.addEventListener('click', () => this.handleCookieChoice(true)); 1330 rejectButton?.addEventListener('click', () => this.handleCookieChoice(false)); 1331 preferencesButton?.addEventListener('click', () => { 1332 this.showBackdrop(); 1333 this.toggleModal(true); 1334 }); 1335 1336 // Focus Trap 1337 const focusableElements = this.getFocusableElements(this.banner); 1338 const firstFocusableEl = focusableElements[0]; 1339 const lastFocusableEl = focusableElements[focusableElements.length - 1]; 1340 1341 // Add keydown event listener to handle tab navigation 1342 this.banner.addEventListener('keydown', (e) => { 1343 if (e.key === 'Tab') { 1344 if (e.shiftKey) { 1345 if (document.activeElement === firstFocusableEl) {
1346 lastFocusableEl.focus(); 1347 e.preventDefault(); 1348 } 1349 } else { 1350 if (document.activeElement === lastFocusableEl) { 1351 firstFocusableEl.focus(); 1352 e.preventDefault(); 1353 } 1354 } 1355 } 1356 }); 1357 1358 // Set initial focus 1359 if (this.config.mode !== 'wizard') { 1360 acceptButton?.focus(); 1361 } 1362 } 1363 1364 // Check Modal exists before trying to add event listeners 1365 if (this.modal) { 1366 const closeButton = this.modal.querySelector('.modal-close'); 1367 const acceptAllButton = this.modal.querySelector('.preferences-accept-all'); 1368 const rejectAllButton = this.modal.querySelector('.preferences-reject-all'); 1369 1370 closeButton?.addEventListener('click', () => { 1371 this.toggleModal(false); 1372 1373 const hasMadeFirstChoice = this.hasSetInitialCookieChoices(); 1374 1375 if (hasMadeFirstChoice) { 1376 // run through the callbacks based on the current localStorage state 1377 this.runStoredCookiePreferenceCallbacks(); 1378 } else { 1379 // handle the case where the user closes without making a choice for the first time 1380 this.handleClosedWithNoChoice(); 1381 } 1382 }); 1383 acceptAllButton?.addEventListener('click', () => this.handleCookieChoice(true)); 1384 rejectAllButton?.addEventListener('click', () => this.handleCookieChoice(false)); 1385 1386 // Banner Focus Trap 1387 const focusableElements = this.getFocusableElements(this.modal); 1388 const firstFocusableEl = focusableElements[0]; 1389 const lastFocusableEl = focusableElements[focusableElements.length - 1]; 1390 1391 this.modal.addEventListener('keydown', (e) => { 1392 if (e.key === 'Tab') { 1393 if (e.shiftKey) { 1394 if (document.activeElement === firstFocusableEl) {
1395 lastFocusableEl.focus(); 1396 e.preventDefault(); 1397 } 1398 } else { 1399 if (document.activeElement === lastFocusableEl) { 1400 firstFocusableEl.focus(); 1401 e.preventDefault(); 1402 } 1403 } 1404 } 1405 if (e.key === 'Escape') { 1406 this.toggleModal(false); 1407 } 1408 }); 1409 1410 closeButton?.focus(); 1411 1412 // Update the checkbox event listeners 1413 const preferencesSection = this.modal.querySelector('#cookie-preferences'); 1414 const checkboxes = preferencesSection.querySelectorAll('input[type="checkbox"]'); 1415 1416 checkboxes.forEach(checkbox => { 1417 checkbox.addEventListener('change', (event) => { 1418 const [, cookieId] = event.target.id.split('cookies-'); 1419 const isAccepted = event.target.checked; 1420 const previousValue = localStorage.getItem( 1421 `silktideCookieChoice_${cookieId}${this.getBannerSuffix()}` 1422 ) === 'true'; 1423 1424 // Only proceed if the value has actually changed 1425 if (isAccepted !== previousValue) { 1426 // Find the corresponding cookie type 1427 const cookieType = this.config.cookieTypes.find(type => type.id === cookieId); 1428 1429 if (cookieType) { 1430 // Update localStorage 1431 localStorage.setItem( 1432 `silktideCookieChoice_${cookieId}${this.getBannerSuffix()}`, 1433 isAccepted.toString() 1434 ); 1435 1436 // Run the appropriate callback only if the value changed 1437 if (isAccepted && typeof cookieType.onAccept === 'function') { 1438 cookieType.onAccept(); 1439 } else if (!isAccepted && typeof cookieType.onReject === 'function') { 1440 cookieType.onReject(); 1441 } 1442 } 1443 } 1444 }); 1445 }); 1446 } 1447 1448 // Check Cookie Icon exists before trying to add event listeners 1449 if (this.cookieIcon) { 1450 1451 this.cookieIcon.addEventListener('click', () => { 1452 // If modal is not found, create it 1453 if (!this.modal) { 1454 this.createModal(); 1455 this.toggleModal(true); 1456 this.hideCookieIcon(); 1457 } 1458 // If modal is hidden, show it 1459 else if (this.modal.style.display === 'none' || this.modal.style.display === '') { 1460 this.toggleModal(true); 1461 this.hideCookieIcon(); 1462 } 1463 // If modal is visible, hide it 1464 else { 1465 this.toggleModal(false); 1466 } 1467 }); 1468 } 1469 } 1470 1471 getBannerSuffix() { 1472 if (this.config.bannerSuffix) { 1473 return '_' + this.config.bannerSuffix; 1474 } 1475 return ''; 1476 } 1477 1478 preventBodyScroll() { 1479 document.body.style.overflow = 'hidden'; 1480 // Prevent iOS Safari scrolling 1481 document.body.style.position = 'fixed'; 1482 document.body.style.width = '100%'; 1483 } 1484 1485 allowBodyScroll() { 1486 document.body.style.overflow = ''; 1487 document.body.style.position = ''; 1488 document.body.style.width = ''; 1489 } 1490} 1491 1492(function () { 1493 window.silktideCookieBannerManager = {}; 1494 1495 let config = {}; 1496 let cookieBanner; 1497 1498 function updateCookieBannerConfig(userConfig = {}) { 1499 config = {...config, ...userConfig}; 1500 1501 // If cookie banner exists, destroy and recreate it with new config 1502 if (cookieBanner) { 1503 cookieBanner.destroyCookieBanner(); // We'll need to add this method 1504 cookieBanner = null; 1505 } 1506 1507 // Only initialize if document.body exists 1508 if (document.body) { 1509 initCookieBanner(); 1510 } else { 1511 // Wait for DOM to be ready 1512 document.addEventListener('DOMContentLoaded', initCookieBanner, {once: true}); 1513 } 1514 } 1515 1516 function initCookieBanner() { 1517 if (!cookieBanner) { 1518 cookieBanner = new SilktideCookieBanner(config); // Pass config to the CookieBanner instance 1519 } 1520 } 1521 1522 function injectScript(url, loadOption) { 1523 // Check if script with this URL already exists 1524 const existingScript = document.querySelector(`script[src="${url}"]`); 1525 if (existingScript) { 1526 return; // Script already exists, don't add it again 1527 } 1528 1529 const script = document.createElement('script'); 1530 script.src = url; 1531 1532 // Apply the async or defer attribute based on the loadOption parameter 1533 if (loadOption === 'async') { 1534 script.async = true; 1535 } else if (loadOption === 'defer') { 1536 script.defer = true; 1537 } 1538 1539 document.head.appendChild(script); 1540 } 1541 1542 window.silktideCookieBannerManager.initCookieBanner = initCookieBanner; 1543 window.silktideCookieBannerManager.updateCookieBannerConfig = updateCookieBannerConfig; 1544 window.silktideCookieBannerManager.injectScript = injectScript; 1545 1546 if (document.readyState === 'loading') { 1547 document.addEventListener('DOMContentLoaded', initCookieBanner, {once: true}); 1548 } else {
1549 initCookieBanner(); 1550 } 1551})(); 1552</script>
vendor: 1 bytes, line 1552
1552
1553<script> 1554silktideCookieBannerManager.updateCookieBannerConfig({ 1555 showBanner: false, // <--- THIS HIDES THE POPUP ON LOAD 1556 background: { 1557 showBackground: true 1558 }, 1559 cookieIcon: { 1560 position: "bottomLeft" 1561 }, 1562 cookieTypes: [ 1563 { 1564 id: "necessary", 1565 name: "Necessary", 1566 description: "<p>These cookies are necessary for the website to function properly and cannot be switched off. They help with things like logging in and setting your privacy preferences.</p>", 1567 required: true, 1568 onAccept: function() { 1569 //console.log('Add logic for the required Necessary here'); 1570 //Remaining cookies 1571 } 1572 }, 1573 { 1574 id: "analytics", 1575 name: "Analytics", 1576 description: "<p>These cookies help us improve the site by tracking which pages are most popular and how visitors move around the site.</p>", 1577 defaultValue: true, 1578 onAccept: function() { 1579 gtag('consent', 'update', { 1580 analytics_storage: 'granted', 1581 }); 1582 // Dynamic Refresh: No IDs required 1583 if (window.google_tag_manager) { 1584 Object.keys(google_tag_manager).forEach(id => { 1585 if (id.startsWith('G-') || id.startsWith('GT-')) { 1586 gtag('config', id, { 'update_config': true }); 1587 } 1588 }); 1589 } 1590 dataLayer.push({ 1591 'event': 'consent_accepted_analytics', 1592 }); 1593 }, 1594 onReject: function() { 1595 gtag('consent', 'update', { 1596 analytics_storage: 'denied', 1597 }); 1598 } 1599 }, 1600 { 1601 id: "advertising", 1602 name: "Advertising", 1603 description: "<p>These cookies provide extra features and personalization to improve your experience. They may be set by us or by partners whose services we use.</p>", 1604 defaultValue: true, 1605 onAccept: function() { 1606 gtag('consent', 'update', { 1607 ad_storage: 'granted', 1608 ad_user_data: 'granted', 1609 ad_personalization: 'granted', 1610 }); 1611 // Dynamic Refresh: No IDs required 1612 if (window.google_tag_manager) { 1613 Object.keys(google_tag_manager).forEach(id => { 1614 if (id.startsWith('G-') || id.startsWith('GT-')) { 1615 gtag('config', id, { 'update_config': true }); 1616 } 1617 }); 1618 } 1619 dataLayer.push({ 1620 'event': 'consent_accepted_advertising', 1621 }); 1622 }, 1623 onReject: function() { 1624 gtag('consent', 'update', { 1625 ad_storage: 'denied', 1626 ad_user_data: 'denied', 1627 ad_personalization: 'denied', 1628 }); 1629 } 1630 } 1631 ], 1632 text: { 1633 banner: { 1634 description: "<p>We use cookies on our site to enhance your user experience, provide personalized content, and analyze our traffic. <a href=\"/privacy-policy/\" target=\"_blank\">Cookie Policy.</a></p>", 1635 acceptAllButtonText: "Accept all", 1636 acceptAllButtonAccessibleLabel: "Accept all cookies", 1637 rejectNonEssentialButtonText: "Reject non-essential", 1638 rejectNonEssentialButtonAccessibleLabel: "Reject non-essential", 1639 preferencesButtonText: "Preferences", 1640 preferencesButtonAccessibleLabel: "Toggle preferences" 1641 }, 1642 preferences: { 1643 title: "Customize your cookie preferences", 1644 description: "<p>We respect your right to privacy. You can choose not to allow some types of cookies. Your cookie preferences will apply across our website.</p>", 1645 creditLinkText: "", 1646 creditLinkAccessibleLabel: "" 1647 } 1648 }, 1649 position: { 1650 banner: "bottomLeft" 1651 } 1652}); 1653</script>
1653 1654 1655<!-- Clarity (restricted)-->
1656<script> 1657window._MTS_ClarityProjectId = "wc67nnmzc4"; 1658</script>
1658 1659
1660<script> 1661 1662 var ClarityAllowedUsers = [2]; 1663 var ClarityExcludedPaths = [ 1664 /^\/news\/\d+\//, 1665 /^\/contact-us/ 1666 ]; 1667 1668 var ClarityProjectId = window._MTS_ClarityProjectId || ""; 1669 1670 var ClarityIsExcluded = ClarityExcludedPaths.some(function (pattern) { 1671 return pattern.test(window.location.pathname); 1672 }); 1673 1674 if ( 1675 ClarityProjectId && 1676 typeof window._MTS_userId !== "undefined" && 1677 window._MTS_userId > 0 && 1678 (window._isAdmin === true || ClarityAllowedUsers.includes(window._MTS_userId)) && 1679 !ClarityIsExcluded 1680 ) { 1681 var rawUrl = window._MTS_SITEURL || "UnknownSite"; 1682 var siteUrl = rawUrl 1683 .replace(/^(https?:\/\/)?(www\.)?/, "") 1684 .split(".")[0] 1685 .substring(0, 16); 1686 1687 var clarityUserId = window._MTS_userId.toString(); 1688 var friendlyName = siteUrl + " - " + clarityUserId; 1689 1690 (function (c, l, a, r, i, t, y) { 1691 c[a] = c[a] || function () { 1692 (c[a].q = c[a].q || []).push(arguments); 1693 }; 1694 t = l.createElement(r); 1695 t.async = 1; 1696 t.src = "https://www.clarity.ms/tag/" + i; 1697 y = l.getElementsByTagName(r)[0]; 1698 y.parentNode.insertBefore(t, y); 1699 })(window, document, "clarity", "script", ClarityProjectId); 1700 1701 window.clarity("identify", clarityUserId, undefined, undefined, friendlyName); 1702 window.clarity("set", "site", siteUrl); 1703 window.clarity("set", "userId", clarityUserId); 1704 window.clarity("set", "isAdmin", window._isAdmin === true ? "true" : "false"); 1705 window.clarity("set", "_MTS_userId", _MTS_userId); 1706 } 1707</script>
1707 1708 1709 1710 1711 1712<!-- Favicon --> 1713<link rel="icon" type="image/x-icon" href="https://d1gpmunylt23vy.cloudfront.net/360_SixRivers_Live/0/0/0/0/133/715/133715_original" /> 1714 1715<!-- Apple Touch Icon --> 1716<link rel="apple-touch-icon" sizes="180x180" href="https://d1gpmunylt23vy.cloudfront.net/360_SixRivers_Live/0/0/0/0/133/715/133715_original" /> 1717 1718 1719<!-- Android Chrome Icons --> 1720<link rel="icon" type="image/png" sizes="192x192" href="https://d1gpmunylt23vy.cloudfront.net/360_SixRivers_Live/0/0/0/0/133/715/133715_original" /> 1721<link rel="icon" type="image/png" sizes="512x521" href="https://d1gpmunylt23vy.cloudfront.net/360_SixRivers_Live/0/0/0/0/133/715/133715_original" /> 1722<style> 1723 1724.mailer{ 1725display: none; 1726} 1727 1728html body { 1729 font-family: georgia, serif; 1730} 1731 1732#item_136 .navType:after { 1733 content: unset; 1734} 1735 1736.menuDropBgShow { 1737 box-shadow: 0px 0px 1px var(--six-main-black); 1738 margin-top: -1px; 1739 min-height: unset !important; 1740} 1741 1742.navigation_menu_widget .section_navigation_widget { 1743 background: var(--six-main-black); 1744} 1745 1746.navigation_menu_widget .section_navigation_widget a[title="Donate"] { 1747 background: var(--six-main-red) !important; 1748} 1749 1750.navigation_menu_widget .section_navigation_widget .sectionDropItem { 1751 color: var(--six-black); 1752 background: var(--six-white); 1753 font-size: 20px; 1754} 1755 1756.navigation_menu_widget .section_navigation_widget .sectionItem, 1757.navigation_menu_widget .section_navigation_widget .sectionLabel, 1758.navigation_menu_widget .section_navigation_widget .dropLink { 1759 background: var(--six-main-black) !important; 1760 color: var(--six-white) !important; 1761 font-size: 20px; 1762 font-weight: 600; 1763} 1764 1765.header .headerMainItems { 1766 padding: 10px !important; 1767} 1768 1769#nextStoryTitle, 1770#previousStoryTitle { 1771 display: none !important; 1772} 1773 1774.adPlaceholder, 1775.adBannerPlaceholder { 1776 background: var(--six-black); 1777} 1778 1779.adPlaceholder { 1780 margin: 0px auto 20px auto; 1781 width: 300px; 1782 height: 250px; 1783} 1784 1785.adBannerPlaceholder { 1786 width: 728px; 1787 height: 90px; 1788 margin: 40px auto; 1789 max-width: 100% 1790} 1791 1792.navigation_menu_widget a.item, 1793.navigation_menu_widget div.item, 1794body p { 1795 font-family: arial, sans-serif !important; 1796} 1797 1798body, 1799.masterMcWrap { 1800 background: var(--six-white); 1801} 1802 1803body .dropNavBtn i.fa-bars { 1804 text-align: center; 1805} 1806 1807body .mts_cc_heading { 1808 font-family: georgia, serif; 1809 font-size: 30px; 1810 font-weight: bold; 1811 color: var(--six-black); 1812 padding: 0px 0px 0px 0px; 1813 line-height: 1.125; 1814} 1815 1816body .news_panel_widget #news .item .photoText .photoAuthor, 1817body .news_panel_widget #news .item .photoTextw .photoAuthor, 1818body .news_panel_widget #news .item .photoText .photoDate, 1819body .news_panel_widget #news .item .photoTextw .photoDate { 1820 color: var(--six-main-black); 1821 font-family: arial; 1822} 1823 1824.trending_media_widget .trendingListCont { 1825 margin-top: 10px; 1826} 1827 1828a.trendingLink { 1829 font-size: 24px; 1830 display: flex; 1831 color: var(--six-black) !important; 1832} 1833 1834.trendingCount { 1835 font-weight: bold; 1836 line-height: .875; 1837} 1838 1839.header .section_navigation_widget.showSecNav { 1840 position: absolute !important; 1841 left: 0 !important; 1842} 1843 1844.header .searchCtr { 1845 transform: translateY(0px); 1846 -webkit-transform: translateY(0px); 1847 -moz-transform: translateY(0px); 1848} 1849 1850.header .searchCtr.showSearch { 1851 transform: translateY(calc(100%)); 1852 -webkit-transform: translateY(calc(100%)); 1853 -moz-transform: translateY(calc(100%)); 1854} 1855 1856body .section_navigation_widget .mts_cc_heading, 1857body .desktopNavSection .sectionLabel { 1858 display: none !important; 1859} 1860 1861body .navigation_menu_widget a.mdItem .dropDownElement .item, 1862body .navigation_menu_widget .mdItem .dropDownElement .item { 1863 color: #000000; 1864} 1865 1866.sectionDropItem[title="Opinions Main"], 1867.sectionDropItem[title="News Main"], 1868.sectionDropItem[title="Living Main"], 1869.sectionDropItem[title="Sports Main"], 1870.sectionDropItem[title="Tri-Cities Scene Main"] { 1871 font-weight: bold; 1872} 1873 1874.backToTop { 1875 background: #eeeeee; 1876 border: solid 1px #000000; 1877 border-radius: 5px; 1878 position: sticky; 1879 bottom: 20px; 1880 left: calc(100% - 20px); 1881 z-index: 151; 1882 aspect-ratio: 1/1; 1883 display: flex; 1884 flex-direction: column; 1885 color: var(--six-main-black); 1886 align-items: center; 1887 justify-content: center; 1888 text-transform: uppercase; 1889 gap: 5px; 1890 padding: 10px; 1891 width: 48px; 1892 height: 48px; 1893 text-align: center; 1894 cursor: pointer; 1895 transition: background 250ms; 1896 margin-top: 20px; 1897} 1898 1899.backToTop:hover { 1900 background: #dddddd; 1901} 1902 1903.backToTop i { 1904 font-size: 20px; 1905} 1906 1907.backToTop span { 1908 font-family: arial, sans-serif; 1909 font-size: 14px; 1910 font-weight: 600; 1911 display: none; 1912} 1913 1914.srAd { 1915 margin: 0px auto 20px auto; 1916} 1917 1918@media (min-width: 768px) { 1919 .backToTop { 1920 width: 96px; 1921 height: 96px; 1922 } 1923 1924 .backToTop span { 1925 display: block; 1926 } 1927} 1928 1929@media (min-width: 1024px) { 1930 .header #navbar { 1931 align-self: center; 1932 } 1933 1934 .header .headerMainItems { 1935 padding: 5px !important; 1936 } 1937 1938 .mainNav, 1939 .navigation_menu_widget { 1940 height: calc(100%); 1941 } 1942 1943 .header .searchCtr.showSearch { 1944 transform: translateY(calc(100% + 14px)) !important; 1945 -webkit-transform: translateY(calc(100% + 14px)) !important; 1946 -moz-transform: translateY(calc(100% + 14px)) !important; 1947 } 1948} 1949</style> 1950
1951<script> 1952$(document).one('widgetsloaded', function() { 1953 const url = window.location.href; 1954 const targetPaths = ['/admin', '/layout-admin', '/news/editor', '/archive/search']; 1955 1956 if (targetPaths.some(path => url.includes(path))) { 1957 document.body.style.fontFamily = "roboto, sans-serif"; 1958 } 1959 1960 let searchBtn = $(".searchBtn"); 1961 searchBtn.on("click", function() { 1962 1963 }); 1964 1965 let headerWidth = $("header").width(); 1966 let navWidth = $(".navigationContainer").width(); 1967 let navPos = $(".navigationContainer").scrollLeft(); 1968 let leftVal = headerWidth - (navPos + navWidth); 1969 1970 // Wait until the element exists in the DOM 1971 function watchSectionNav() { 1972 const target = document.querySelector(".section_navigation_widget"); 1973 if (!target) { 1974 requestAnimationFrame(watchSectionNav); 1975 return; 1976 } 1977 1978 // Create a MutationObserver 1979 const observer = new MutationObserver(mutations => { 1980 mutations.forEach(mutation => { 1981 if (mutation.attributeName === "class") { 1982 if (target.classList.contains("showSecNav")) { 1983 target.style.left = `${-leftVal}px`; 1984 } else { 1985 target.removeAttribute("style") // runs on removal too 1986 } 1987 } 1988 }); 1989 }); 1990 1991 // Start observing class attribute changes 1992 observer.observe(target, { attributes: true, attributeFilter: ["class"] }); 1993 } 1994 1995 watchSectionNav(); 1996}); 1997</script>
1997 1998
1999<script> 2000$(document).one('widgetsloaded', function() { 2001 //Set last visited page for URL redirect based on login 2002 if (!window.location.pathname.includes('/user/login')) 2003 { 2004 let urlQuery = `?target=${window.location.pathname + window.location.search + window.location.hash}`; 2005 localStorage.setItem('lastVisitedURL', urlQuery); 2006 } 2007 2008 let lastVisitedUrl = localStorage.getItem('lastVisitedURL'); 2009 console.log(lastVisitedUrl); 2010 $("a[href='/user/login']").attr("href", `/user/login/${lastVisitedUrl}`); 2011 2012(function() { 2013 const targetSrc = "https://media-sixrivers.mynews360.com/noimage/block/213/"; 2014 2015 function checkImages() { 2016 document.querySelectorAll('.blockImgCtr img').forEach(img => { 2017 if (img.src === targetSrc) { 2018 const parent = img.closest('.blockImgCtr'); 2019 if (parent) parent.style.display = 'none'; 2020 } 2021 }); 2022 } 2023 2024 // Run immediately in case elements already exist 2025 checkImages(); 2026 2027 // Watch for new elements being added to the DOM 2028 const observer = new MutationObserver(() => checkImages()); 2029 observer.observe(document.body, { childList: true, subtree: true }); 2030})(); 2031}); 2032</script>
2032 2033 2034<!-- GOOGLE ADS TAG (gtag.js) -->
vendor: 65 bytes, lines 2034-2035
2034 2035<script async src="https://www.googletagmanager.com/gtag/js?id=
2035G-K9ZBRND062
vendor: 13 bytes, lines 2035-2036
2035"></script> 2036
2036<script>
vendor: 127 bytes, line 2036
2036window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', '
2036G-K9ZBRND062
vendor: 4 bytes, line 2036
2036');
2036</script>
2036 2037 2038<!--//DIDNA AD CONFIGURATION-->
2039<script> 2040const url = window.location.href; 2041const targetPaths = ['/admin', '/layout-admin', '/news/editor', '/archive/search', '/manage', '/mtsAdmin', '/upload-ad', '/photos', '/mtsadmin']; 2042 2043var DIDNA_CONFIG = { 2044 pageTargeting: { 2045 pos: ['rectangle-one', 'cube-one', 'cube-two', 'sidebar-top'] 2046 } 2047}; 2048</script>
vendor: 1 bytes, line 2048
2048
2049<script async='async' type='text/javascript' src='https://storage.googleapis.com/didna_hb/six_rivers_media/johnsoncitypresscom/didna_config.js'></script>
2049 2050 2051<!--BROADSTREET AD--> 2052<style> 2053.broadstreet-dynamic-scrolling + broadstreet-zone-container { 2054 height: 0; 2055} 2056</style>
2057<script src="https://cdn.broadstreetads.com/init-2.min.js"></script>
vendor: 1 bytes, line 2057
2057
2058<script>broadstreet.watch({ networkId: 9387 })</script>
2058 2059
2060<script> 2061$(document).one("widgetsloaded", function() { 2062 if (!targetPaths.some(path => url.includes(path))) { 2063 let body = $("body"); 2064 let mainContent = $(".masterMcWrap"); 2065 let broadstreet = `<broadstreet-zone zone-id="170347" uri-keywords="true" soft-keywords="true"></broadstreet-zone>`; 2066 2067 $(broadstreet).prependTo(body); 2068 2069 let backToTop = `<div class="backToTop"><i class="fas fa-chevron-up"></i><span>Back to top</span></div>`; 2070 $(backToTop).appendTo(mainContent); 2071 } 2072 2073 $(".backToTop").on("click", function() { 2074 window.scrollTo({ 2075 top : 0, 2076 behavior : "smooth" 2077 }); 2078 }); 2079}); 2080</script>
2080 2081
2082<script> 2083//User login / logout 2084$(document).one("widgetsloaded", function( ) { 2085 let user = _MTS_userId; 2086 let login = (user !== null && user > -1 && user !== undefined ? `<a href="/signout.aspx" class="sectionItem">Logout</a>` : `<a href="/live-content/subscribe" class="sectionItem">Subscribe</a><a href="/user/login" class="sectionItem">Login</a>`); 2087 let dNav = $(".desktopNavSection").first(); 2088 let mNav = $(".mobileNavSection").first(); 2089 $(login).prependTo(dNav); 2090 $(login).prependTo(mNav); 2091}); 2092</script>
2092 2093
2094<script> 2095$(document).one("widgetsloaded", function() { 2096function updateMenuHeight() { 2097 const menu = document.querySelector('.menuDropBgShow'); 2098 const sportsList = document.querySelector('.sportsList'); 2099 if (!menu || !sportsList) return; 2100 2101 const visibleSubLists = Array.from(sportsList.querySelectorAll('.subList')) 2102 .filter(el => el.offsetParent !== null); // visible only 2103 2104 // Set height based on number of visible subList items 2105 menu.style.height = `${visibleSubLists.length * 50}px`; 2106 } 2107 2108 // Observe DOM changes (for menuDropBgShow or subList updates) 2109 const observer = new MutationObserver(() => { 2110 updateMenuHeight(); 2111 }); 2112 2113 observer.observe(document.body, { 2114 childList: true, 2115 subtree: true, 2116 attributes: true, 2117 attributeFilter: ['style', 'class'] 2118 }); 2119 2120 // Run initially if elements are already present 2121 let match = window.matchMedia("(min-width: 1024px)").matches; 2122 if(match) { 2123 updateMenuHeight(); 2124 } 2125 2126//ADJUST NAVIGATION HOVER TITLE TO REFLECT TARGET ATTRIBUTE 2127const cleanNonBlankNavTitles = () => { 2128 document.querySelectorAll('a.desktopNavItem:not([target="_blank"])').forEach(anchor => { 2129 if (anchor.title && /in new tab$/i.test(anchor.title)) { 2130 anchor.title = anchor.title.replace(/\s*in new tab$/i, ''); 2131 } 2132 }); 2133}; 2134 2135// Run immediately 2136cleanNonBlankNavTitles(); 2137 2138// Watch for dynamically added anchors 2139const titleObserver = new MutationObserver(() => cleanNonBlankNavTitles()); 2140titleObserver.observe(document.body, { childList: true, subtree: true }); 2141 2142 document.querySelectorAll('.sectionDropItem').forEach(el => { 2143 const href = el.getAttribute('href'); 2144 if (href && (href.startsWith('http://') || href.startsWith('https://'))) { 2145 el.setAttribute('target', '_blank'); 2146 } 2147 }); 2148}); 2149</script>
2149 2150
2151<script> 2152//SET PROPER URL TO "NOT A SUBSCRIBER" LINK ON LOGIN PAGE 2153$(document).one("widgetsloaded", function() { 2154if (window.location.href.includes('/user/login')) { 2155 const subObserver = new MutationObserver(() => { 2156 const subElement = document.querySelector('[title="Not a Subscriber"]'); 2157 if (subElement) { 2158 subElement .setAttribute('href', '/live-content/subscribe'); 2159 subObserver.disconnect(); // stop watching once done 2160 } 2161 }); 2162 2163 subObserver.observe(document.body, { 2164 childList: true, 2165 subtree: true 2166 }); 2167} 2168}); 2169</script>
2169 2170
2171<script> 2172$(document).one("widgetsloaded", function() { 2173 let userProfileUpdate = window.location.href.includes("/user/edit"); 2174 if (userProfileUpdate) { 2175 let link = "https://sixrivers.newzware.com/ss70v2/sixrivers/common/template.jsp?autoLogout=N&nwmodule=main&nwpage=main&skin=jcp"; 2176 let modBtn = $("#newPasswordField a"); 2177 modBtn.attr("href", link).attr("target", "_blank").addClass("mts_cc_button button").css({"padding": "10px 20px"}); 2178 2179 let coverageContainer = $("#coverageContainer"); 2180 let parentRows = [ 2181 "#changeEmail", 2182 "#changeName", 2183 "#changeTwoFactor", 2184 "#changeGender", 2185 "#changeDOB", 2186 "#changeZip" 2187 ]; 2188 2189 for(i = 0; i < parentRows.length; i++) { 2190 $(`${parentRows[i]}`).closest(".setRow").hide(); 2191 } 2192 2193 coverageContainer.hide(); 2194 } 2195}); 2196</script>
2196 2197 2198 2199 2200 2201 2202 2203 <link rel="shortcut icon" href="https://media-sixrivers.mynews360.com/images/custom/213/favicon.ico" /> 2204 2205 <link rel="stylesheet" type="text/css" href="https://media-sixrivers.mynews360.com/css/?custom=true&pid=213" /> 2206 2207 <link rel="stylesheet" type="text/css" href="https://media-sixrivers.mynews360.com/css/oneColumn.css?v=1.14.5.35260" /> 2208 <link rel="Stylesheet" type="text/css" href="https://media-sixrivers.mynews360.com/css/?v=1.14.5.35260&pid=213" /> 2209 2210
2210<script type="text/javascript"> 2211 _MTS_cssList.push("css/jQueryExtensions/jquery-ui.css", "css/popUpDialog.css"); 2212 _MTS_jsList.push("js/signin.js", "js/popUpDialog.js", "js/oneCol.js"); 2213 var _timeout = 1140000; 2214 var _sessionTimeout = 1200000; 2215 var __redirectTo = "/news-category/news/local-news/1/6/"; 2216 var _COMMON_isTablet = false; 2217 var _encodedPathAndQuery = "%2fnews-category%2fnews%2flocal-news%2f1%2f6%2f", 2218 _MTS_SEOALT = "Local News news on Johnson City Press.", 2219 _homePageUrl = "/"; 2220 </script>
2220 2221 2222
2222<script type="text/javascript"> 2223 2224 _MTS_SEOALT = "Local News news on Johnson City Press."; 2225 2226 var _MTS_PHOTO_PER_AD = ""; 2227 var _MTS_ITEM_ADS = 2228 [ 2229 2230 ]; 2231 </script>
2231 2232 2233 2234 2235<title> 2236 Johnson City Press | News | Local News News 2237</title><meta name="description" content="Get the latest Local News news on Johnson City Press" /></head> 2238 2239 2240<body > 2241 2242 <div class="sitewideUserAlert"> 2243 <p id="userAlertMessage"></p> 2244 <div class="sitewideUserAlertButtons"> 2245 <button id="hideSiteWide">Okay</button> 2246 <button id="closeSiteWide">Close and Never Show Again</button> 2247 </div> 2248 </div> 2249 2250 2251 2252 2253 2254 <div class="plBackground"></div> 2255 <div id="fb-root"></div> 2256 2257 2258 2259 <noscript>You must have javascript enabled to view this site.</noscript> 2260 2261 <div class="alwaysMobileBg"></div> 2262 2263 <div class="busySpinnerBg"> 2264 <div class="closeSpinner"><i class="fas fa-times"></i></div> 2265 <img class="busySpinner" src="https://media-sixrivers.mynews360.com/images/busySpinner.gif" alt="Loading" /> 2266 </div> 2267 2268 2269 <div class="navigation_admin_menu_widget"> 2270 <input type="hidden" name="id" value="" /> 2271 <input type="hidden" name="abovethefold" value="true" /> 2272 </div> 2273 2274 <div class="custom_header_widget"> 2275 <input type="hidden" name="abovethefold" value="true" /> 2276 </div> 2277 2278
2279<script type="text/javascript"> 2280 _MTS_jsList.push("js/content/mobileSelectors.js"); 2281</script>
2281 2282 <div class="emailRejected" style="display: none;"> 2283 <div class="rejectTop"> 2284 <div class="rejectedTitle">Email Rejected!</div> 2285 <div class="rejectHide">x</div> 2286 </div> 2287 <div class="rejectedInfo"> 2288 We attempted to send a notification to your email address but we were unable to verify that you provided a valid email address. 2289 Please visit <a title="Link to my profile" class="emailLink" href="/user/edit/">my profile</a> to update your email address if you wish to receive notifications. 2290 Otherwise, <a title="Disable notifications" class="emailLink" href="javascript:fireEmailRejected()"> disable notifications</a> and hide this message. 2291 </div> 2292 </div> 2293 2294 2295 2296 <div class="masterMcWrap" role="main"> 2297 <div id="logged_nav"> 2298 2299 2300 </div> 2301 <div id="timeout"> 2302 <div class="tText n"> 2303 Your session was unable to be renewed and will be expiring in <span id="tTimer">0</span> seconds. 2304 Click <span id="tRenew">here</span> to attempt to renew your session. 2305 2306 <div id="tStatus"></div> 2307 </div> 2308 </div> 2309 2310 2311 2312 <div id='mts_r_0' class='widget_region' style='text-align:center'><input type='hidden' name='reg_width' value='100.00' /><input type='hidden' name='reg_margin_left' value='0.00' /><input type='hidden' name='reg_margin_right' value='0.00' /><input type='hidden' name='reg_width_med' value='100.00' /><input type='hidden' name='reg_margin_left_med' value='0.00' /><input type='hidden' name='reg_margin_right_med' value='0.00' /><input type='hidden' name='reg_width_tablet' value='100.00' /><input type='hidden' name='reg_margin_left_tablet' value='0.00' /><input type='hidden' name='reg_margin_right_tablet' value='0.00' /><input type='hidden' name='reg_pixel' value='False' /><input type='hidden' name='reg_innerSec' value='False' /><div id='mts_c_0' class='widget_column' style='display:inline-block;vertical-align:top;text-align:initial;'><input type='hidden' name='col_width' value='100.00' /><input type='hidden' name='col_margin_left' value='0.00' /><input type='hidden' name='col_margin_right' value='0.00' /><input type='hidden' name='col_width_med' value='100.00' /><input type='hidden' name='col_margin_left_med' value='0.00' /><input type='hidden' name='col_margin_right_med' value='0.00' /><input type='hidden' name='col_width_tablet' value='100.00' /><input type='hidden' name='col_margin_left_tablet' value='0.00' /><input type='hidden' name='col_margin_right_tablet' value='0.00' /><input type='hidden' name='col_pixel' value='False' /><div class='custom_break_widget'><style> 2313.news_panel_widget .item { 2314 padding: 20px 0px; 2315} 2316 2317@media (min-width: 1366px) { 2318 .masterMcWrap .innerSec { 2319 width: 1300px; 2320 } 2321} 2322</style></div><div class='custom_break_widget'><style> 2323html, body {visibility: hidden; opacity: 0;} 2324</style> 2325
2326<script> 2327$(document).one("widgetsloaded", function() { 2328 setTimeout(function() { 2329 $("html, body").css({"visibility": "visible", "opacity": "1"}) 2330 }, 2) 2331}) 2332</script>
2332</div><div class='custom_break_widget'><div id="ad-139731" style="margin: 20px auto 40px auto;"></div>
2333<script> 2334var didna = window.didna || {cmd: []}; 2335didna.cmd.push(function(){ 2336 didna.createAdUnits({ 2337 id: "ad-139731", 2338 "adUnitPath": "/22870547579/johnsoncitypress.com", 2339 "size": [728, 90], 2340 "sizeMap": [ 2341 [[1200, 0], [[1170, 90], [970, 250], [970, 90], [728, 90]]], 2342 [[992, 0], [[970, 90], [728, 90]]], 2343 [[768, 0], [[728, 90], [320, 50]]], 2344 [[320, 0], [[320, 50]]] 2345 ], 2346 targeting:{'pos': "rectangle-one"} 2347 }); 2348}); 2349</script>
2349</div></div></div><div class='innerSec group'><div id='mts_r_1' class='widget_region' style='text-align:center'><input type='hidden' name='reg_width' value='100.00' /><input type='hidden' name='reg_margin_left' value='0.00' /><input type='hidden' name='reg_margin_right' value='0.00' /><input type='hidden' name='reg_width_med' value='100.00' /><input type='hidden' name='reg_margin_left_med' value='0.00' /><input type='hidden' name='reg_margin_right_med' value='0.00' /><input type='hidden' name='reg_width_tablet' value='100.00' /><input type='hidden' name='reg_margin_left_tablet' value='0.00' /><input type='hidden' name='reg_margin_right_tablet' value='0.00' /><input type='hidden' name='reg_pixel' value='False' /><input type='hidden' name='reg_innerSec' value='True' /><div id='mts_c_1' class='widget_column' style='display:inline-block;vertical-align:top;text-align:initial;'><input type='hidden' name='col_width' value='-320.00' /><input type='hidden' name='col_margin_left' value='0.00' /><input type='hidden' name='col_margin_right' value='0.00' /><input type='hidden' name='col_width_med' value='-320.00' /><input type='hidden' name='col_margin_left_med' value='0.00' /><input type='hidden' name='col_margin_right_med' value='0.00' /><input type='hidden' name='col_width_tablet' value='-320.00' /><input type='hidden' name='col_margin_left_tablet' value='0.00' /><input type='hidden' name='col_margin_right_tablet' value='0.00' /><input type='hidden' name='col_pixel' value='False' /><div class='news_panel_widget'><input type='hidden' name='type' value='7' /><input type='hidden' name='category' value='News' /><input type='hidden' name='subcategory' value='Local News' /><input type='hidden' name='itemCount' value='5' /><input type='hidden' name='showMore' value='Hidden' /></div><div class='custom_break_widget'><div id="ad-139732" style="margin: 20px auto 40px auto;"></div>
2350<script> 2351var didna = window.didna || {cmd: []}; 2352 didna.cmd.push(function(){ 2353 didna.createAdUnits({ 2354 id: "ad-139732", 2355 "adUnitPath": "/22870547579/johnsoncitypress.com", 2356 "size": [728, 90], 2357 "sizeMap": [ 2358 [[1200, 0], [[970, 250], [970, 90], [728, 90]]], 2359 [[992, 0], [[970, 90], [728, 90]]], 2360 [[768, 0], [[728, 90], [320, 50]]], 2361 [[320, 0], [[320, 50]]] 2362 ], 2363 targeting:{'pos': "rectangle-two"} 2364 }); 2365 }); 2366</script>
2366</div><div class='news_panel_widget'><input type='hidden' name='type' value='7' /><input type='hidden' name='category' value='News' /><input type='hidden' name='subcategory' value='Local News' /><input type='hidden' name='itemStart' value='6' /><input type='hidden' name='itemCount' value='5' /><input type='hidden' name='hideHeader' value='true' /><input type='hidden' name='showMore' value='Hidden' /></div><div class='custom_break_widget'><div id="ad-1397313" style="margin: 20px auto 40px auto;"></div>
2367<script> 2368var didna = window.didna || {cmd: []}; 2369didna.cmd.push(function(){ 2370 didna.createAdUnits({ 2371 id: "ad-1397313", 2372 "adUnitPath": "/22870547579/johnsoncitypress.com", 2373 "size": [728, 90], 2374 "sizeMap": [ 2375 [[1200, 0], [[970, 250], [970, 90], [728, 90]]], 2376 [[992, 0], [[970, 90], [728, 90]]], 2377 [[768, 0], [[728, 90], [320, 50]]], 2378 [[320, 0], [[320, 50]]] 2379 ], 2380 targeting:{'pos': "rectangle-three"} 2381 }); 2382}); 2383</script>
2383 2384 2385</div><div class='news_panel_widget'><input type='hidden' name='type' value='7' /><input type='hidden' name='category' value='News' /><input type='hidden' name='subcategory' value='Local News' /><input type='hidden' name='itemStart' value='11' /><input type='hidden' name='itemCount' value='5' /><input type='hidden' name='hideHeader' value='true' /><input type='hidden' name='showMore' value='Hidden' /></div><div class='custom_break_widget'><div id="ad-13973134" style="margin: 20px auto 40px auto;"></div>
2386<script> 2387var didna = window.didna || {cmd: []}; 2388didna.cmd.push(function(){ 2389 didna.createAdUnits({ 2390 id: "ad-13973134", 2391 "adUnitPath": "/22870547579/johnsoncitypress.com", 2392 "size": [728, 90], 2393 "sizeMap": [ 2394 [[1200, 0], [[970, 250], [970, 90], [728, 90]]], 2395 [[992, 0], [[970, 90], [728, 90]]], 2396 [[768, 0], [[728, 90], [320, 50]]], 2397 [[320, 0], [[320, 50]]] 2398 ], 2399 targeting:{'pos': "rectangle-four"} 2400 }); 2401}); 2402</script>
2402</div><div class='news_panel_widget'><input type='hidden' name='type' value='7' /><input type='hidden' name='category' value='News' /><input type='hidden' name='subcategory' value='Local News' /><input type='hidden' name='itemStart' value='16' /><input type='hidden' name='itemCount' value='5' /><input type='hidden' name='hideHeader' value='true' /></div></div><div id='mts_c_2' class='widget_column' style='display:inline-block;vertical-align:top;text-align:initial;'><input type='hidden' name='col_width' value='300.00' /><input type='hidden' name='col_margin_left' value='20.00' /><input type='hidden' name='col_margin_right' value='0.00' /><input type='hidden' name='col_width_med' value='300.00' /><input type='hidden' name='col_margin_left_med' value='20.00' /><input type='hidden' name='col_margin_right_med' value='0.00' /><input type='hidden' name='col_width_tablet' value='300.00' /><input type='hidden' name='col_margin_left_tablet' value='20.00' /><input type='hidden' name='col_margin_right_tablet' value='0.00' /><input type='hidden' name='col_pixel' value='True' /><div class='custom_break_widget'><!--HALF PAGE AD CODE(300x600):--> 2403<div id="ad-1397311" class="srAd"></div>
2404<script> 2405var didna = window.didna || {cmd: []}; 2406didna.cmd.push(function(){ 2407 didna.createAdUnits({ 2408 id: "ad-1397311", 2409 "adUnitPath": "/22870547579/johnsoncitypress.com/homepage", 2410 "size": [300, 600], 2411 "sizeMap": [ 2412 [[1200, 0], [[300, 600]]], 2413 [[992, 0], [[300, 600]]], 2414 [[768, 0], [[300, 600]]], 2415 [[320, 0], [[300, 600]]] 2416 ], 2417 targeting: { 'pos': "half-page" } 2418 }); 2419}); 2420</script>
2420</div><div class='trending_media_widget'><input type='hidden' name='types' value='NewsItem' /><input type='hidden' name='searchType' value='Views' /><input type='hidden' name='itemCount' value='5' /><input type='hidden' name='displayType' value='text' /><input type='hidden' name='renameHeader' value='Trending' /><input type='hidden' name='taggedTypes' value='Category' /></div><div class='custom_break_widget'><!--CUBE ONE AD CODE:--> 2421<div id="ad-1397309" style="margin: 20px auto;"></div>
2422<script> 2423var didna = window.didna || {cmd: []}; 2424didna.cmd.push(function(){ 2425 didna.createAdUnits({ 2426 id: "ad-1397309", 2427 adUnitPath: "/22870547579/johnsoncitypress.com/homepage", 2428 size: [300, 250], 2429 sizeMap: [ 2430 [[992, 0], [[300, 250]]], 2431 [[320, 0], [[300, 250]]] 2432 ], 2433 targeting: { pos: "cube-one" } 2434 }); 2435}); 2436</script>
2436</div><div class='custom_break_widget'><style> 2437.thingsToDo { 2438 font-family: arial, sans-serif; 2439 display: flex; 2440 gap: 10px; 2441 align-items: center; 2442 justify-content: center; 2443 padding: 20px; 2444} 2445 2446.ttdInfo { 2447 display: flex; 2448 flex-direction: column; 2449 gap: 5px; 2450} 2451 2452.ttdHeader { 2453 font-size: 20px; 2454 font-weight: 600; 2455} 2456 2457.thingsToDo p { 2458 margin: 0; 2459} 2460 2461.thingsToDo i { 2462 background: var(--six-main-black); 2463 color: var(--six-white); 2464 font-size: 48px; 2465 width: 50%; 2466 aspect-ratio: 1/1; 2467 display: flex; 2468 justify-content: center; 2469 align-items: center; 2470} 2471 2472.viewAllEvents { 2473 background: var(--six-black); 2474 color: var(--six-white); 2475 text-align: center; 2476 padding: 10px 20px; 2477 width: 100%; 2478 max-width: 150px; 2479 margin: 20px auto; 2480 display: block; 2481 font-family: arial, sans-serif; 2482} 2483 2484@media (min-width: 768px) { 2485 padding: 0px; 2486} 2487</style> 2488 2489<div class="thingsToDo"> 2490 <i class="fas fa-calendar-alt"></i> 2491 <div class="ttdInfo"> 2492 <div class="ttdHeader">Things to do</div> 2493 <p>Plan your week with our local event calendar</p> 2494 </div> 2495</div> 2496<a class="viewAllEvents" href="/live-content/local-events">View All</a> 2497</div><div class='custom_break_widget'><div id="ad-1397324" class="srAd"></div>
2498<script> 2499var didna = window.didna || {cmd: []}; 2500didna.cmd.push(function(){ 2501 didna.createAdUnits({ 2502 id: "ad-1397324", 2503 "adUnitPath": "/22870547579/johnsoncitypress.com/news", 2504 "size": [300, 600], 2505 "sizeMap": [ 2506 [[1200, 0], [[300, 600]]], 2507 [[992, 0], [[300, 600]]], 2508 [[768, 0], [[300, 600]]], 2509 [[320, 0], [[300, 600]]] 2510 ], 2511 targeting: { 'pos': "sidebar-bottom" } 2512 }); 2513}); 2514</script>
2514</div><div class='custom_break_widget'>
2514<script> 2515//THIS SCRIPT WILL HANDLE ALL TRENDING NEWS WIDGETS ON THE PAGE, BUT MUST BE PLACED IMMEDIATELY AFTER THE LAST INSTANCE IN THE LAYOUT MANAGER 2516$(document).on("widgetsloaded", function() { 2517 //Add number list to trending widgets 2518 let trending = $(".trendingListCont"); 2519 let item = trending.find(".trendingRow"); 2520 2521 trending.each(function() { 2522 if ($(this).find(".trendingCount").length < 1) { 2523 let i = 0; 2524 $(this).find(item).each(function() { 2525 i += 1; 2526 $(this).find(".trendingLink").prepend(`<span class="trendingCount" style="margin-right: 10px; font-size: 24px;">${i}.</span>`); 2527 }); 2528 i = 0 2529 } 2530 }); 2531 2532}); 2533</script>
2533</div></div></div></div> 2534 </div> 2535 2536 2537 2538 <div class="fullAdView"> 2539 </div> 2540 <div class="fullPageAd"> 2541 2542 2543 <div class="adOptions"> 2544 <div class="adCounter"> 2545 <div class="loadingAd">Loading...</div> <img class="mts_lazy" width="324" height="20" data-original="https://media-sixrivers.mynews360.com/images/ajax-loader.gif" alt="" /> 2546 </div> 2547 <div id="skipAd" class="adBtn"> 2548 View Page in Progress 2549 </div> 2550 </div> 2551 </div> 2552 2553 2554 2555 2556 <h1 class="heading"> 2557 The latest Local News news on Johnson City Press. 2558</h1> 2559 2560 2561 2562 <div id='mts_r_0' class='widget_region' style='text-align:center'><input type='hidden' name='reg_width' value='100.00' /><input type='hidden' name='reg_margin_left' value='0.00' /><input type='hidden' name='reg_margin_right' value='0.00' /><input type='hidden' name='reg_width_med' value='100.00' /><input type='hidden' name='reg_margin_left_med' value='0.00' /><input type='hidden' name='reg_margin_right_med' value='0.00' /><input type='hidden' name='reg_width_tablet' value='100.00' /><input type='hidden' name='reg_margin_left_tablet' value='0.00' /><input type='hidden' name='reg_margin_right_tablet' value='0.00' /><input type='hidden' name='reg_pixel' value='False' /><input type='hidden' name='reg_innerSec' value='False' /><div id='mts_c_0_3' class='widget_column' style='text-align: initial;'><input type='hidden' name='col_width' value='100.00' /><input type='hidden' name='col_margin_left' value='0.00' /><input type='hidden' name='col_margin_right' value='0.00' /><input type='hidden' name='col_width_med' value='100.00' /><input type='hidden' name='col_margin_left_med' value='0.00' /><input type='hidden' name='col_margin_right_med' value='0.00' /><input type='hidden' name='col_width_tablet' value='100.00' /><input type='hidden' name='col_margin_left_tablet' value='0.00' /><input type='hidden' name='col_margin_right_tablet' value='0.00' /><input type='hidden' name='col_pixel' value='False' /><div class='custom_break_widget'><style> 2563.customFooterInner { 2564 background: var(--six-main-black); 2565 color: var(--six-white); 2566 width: 100%; 2567 display: flex; 2568 flex-direction: column; 2569 justify-content: center; 2570 align-items: center; 2571 padding: 50px 30px; 2572 gap: 30px; 2573} 2574 2575.footerContent { 2576 max-width: 1280px; 2577 display: flex; 2578 flex-direction: column; 2579 gap: 40px; 2580} 2581 2582.footerBlock, 2583.footerInfoBlock,
2584.footerPubBlock { 2585 display: flex; 2586 flex-direction: column; 2587} 2588 2589.footerBlock { 2590 gap: 20px; 2591} 2592 2593.footerInfoBlock { 2594 gap: 10px; 2595} 2596 2597.footerPubBlock { 2598 gap: 30px; 2599} 2600 2601.footerLogoMain { 2602 width: 300px; 2603 max-width: 100%; 2604} 2605 2606.footerLogoImage { 2607 width:100%; 2608} 2609 2610.footerShareInfo { 2611 display: flex; 2612 flex-direction: row; 2613 font-size: 24px; 2614 gap: 20px; 2615} 2616 2617.footerHeading { 2618 font-size: 32px; 2619 font-family: georgia, serif; 2620} 2621 2622.footerContent a.footerLink, 2623.footerContent a.fa-brands, 2624.footerContent a.sixRiversFooterLink { 2625 color: var(--six-white); 2626} 2627 2628.footerContent a.footerLink:hover, 2629.footerContent a.fa-brands:hover { 2630 color: var(--six-main-red); 2631} 2632 2633.borderTop { 2634 border-top: solid 1px var(--six-white); 2635 padding-top: 20px; 2636} 2637 2638.footerPubImage { 2639 max-width:100%; 2640} 2641 2642@media (min-width: 768px) { 2643 .customFooterInner { 2644 gap: 40px; 2645 } 2646 2647 .footerContent { 2648 flex-direction: row; 2649 } 2650 2651 .footerContent .footerBlock { 2652 width: calc(33.333% - 14px); 2653 } 2654} 2655 2656</style> 2657 2658<div class="customFooter"> 2659 <div class="customFooterInner"> 2660 <div class="footerContent"> 2661 <div class="footerBlock"> 2662 <a class="footerLogoMain" href="/"> 2663 <img class="footerLogoImage" src="https://media-sixrivers.mynews360.com//images/custom/213/logo.png" alt="" /> 2664 </a> 2665 <div class="footerInfoBlock"> 2666 <span>Johnson City Press</span> 2667 <span>105 East Walnut Street Suite 10</span> 2668 <span>Johnson City, TN 37601</span> 2669 <span>Phone: <a class="mts_cc_text" href="tel:4237221330" title="Call Johnson City Phone Number">423-722-1330</a></span> 2670 <span>Email: <a class="mts_cc_text" href="mailto:[email protected]" title="E-mail Johnson city at [email protected]">[email protected]</a></span> 2671 </div> 2672 <div class="footerShareInfo"> 2673 <a class="fa-brands fa-facebook-f" href="https://www.facebook.com/JohnsonCityPress/" target="_blank"></a> 2674 <a class="fa-brands fa-x-twitter" href="http://twitter.com/jcpress/" target="_blank"></a> 2675 <a class="fa-brands fa-linkedin" href="https://www.linkedin.com/company/johnsoncitypress/" target="_blank"></a> 2676 <a class="fa-brands fa-youtube" href="https://www.youtube.com/channel/UCYZixCNzcgknXLPdHUXQPXw" target="_blank"></a> 2677 <a class="fa-brands fa-tiktok" href="https://www.tiktok.com/@johnsoncitypress" target="_blank"></a> 2678 <a class="fa-brands fa-instagram" href="https://www.instagram.com/johnson_city_press/" target="_blank"></a> 2679 </div> 2680 </div> 2681 <div class="footerBlock"> 2682 <div class="footerHeading"><a class="sixRiversFooterLink" href="https://www.sixriversmedia.com/" target="_blank">Six Rivers Media LLC</a></div> 2683 <div class="footerPubBlock"> 2684 <a class="footerPubLink" title="Johnson City Press link" href="https://www.timesnews.net/" target="_blank"><img class="footerPubImage" src="https://d1gpmunylt23vy.cloudfront.net/360_SixRivers_Live/0/0/0/0/118/575/118575_original" alt="Johnson City Press Logo" /></a> 2685 <a class="footerPubLink" title="The Tomahawk link" href="https://www.thetomahawk.com/" target="_blank"><img class="footerPubImage" src="https://d1gpmunylt23vy.cloudfront.net/360_SixRivers_Live/0/0/0/0/27/545/27545_original" alt="The Tomahawk Logo" /></a> 2686 <a class="footerPubLink" title="The Erwin Record link" href="https://www.erwinrecord.net/" target="_blank"><img class="footerPubImage" src="https://d1gpmunylt23vy.cloudfront.net/360_SixRivers_Live/0/0/0/0/27/543/27543_original" alt="The Erwin Logo" /></a> 2687 </div> 2688 </div> 2689 <div class="footerBlock"> 2690 <div class="footerHeading">Quick Links:</div> 2691 <div class="footerInfoBlock"> 2692 <a class="footerLink" href="/live-content/about us">About Us</a> 2693 <a class="footerLink" href="https://www.sixriversmedia.com/contact-us/#johnson_city_press" target="_blank">Contact Us</a> 2694 <!--<a class="footerLink" href="/live-content/archives">Archives</a>--> 2695 <a class="footerLink" href="https://sixrivers.newzware.com/myad/sixrivers/common/template.jsp" target="_blank">Advertise</a> 2696 <!--<a class="footerLink" href="/live-content/faq">FAQ</a>--> 2697 <a class="footerLink" href="/live-content/subscribe">Subscribe</a> 2698 </div> 2699 </div> 2700 </div> 2701 <div class="footerContent borderTop"> 2702 <div class="copyright"> 2703 © 2025 Johnson City Press 105 East Walnut Street Suite 10 Johnson City, TN 37601 | <a class="footerLink" href="/live-content/terms of use">Terms of Use</a> | <a class="footerLink" href="/live-content/privacy policy">Privacy Policy</a> | <a class="footerLink" href="#" onclick="document.getElementById('silktide-cookie-icon').click(); return false;">Cookie Preferences 2704 </a> 2705 </div> 2706 </div> 2707 </div> 2708</div></div></div></div> 2709 2710
2710<script type="text/javascript"> 2711 _MTS_cssList.push("css/plugins/chosen/chosen.min.css"); 2712 _MTS_jsList.push("js/ajax.js", "js/jQueryExtensions/jquery-ui.js", "js/jQueryExtensions/touch-punch.js", "js/jQueryExtensions/jquery.lazyload.js", "js/plugins/chosen/chosen.jquery.min.js", "js/common.js"); 2713 2714 _MTS_jsList.push("js/smartBanner.js"); 2715 2716 _imageSizes = {"SiteWideMxW":1280,"SiteWideMxH":720,"SlideShowMxW":864,"SlideShowMxH":486,"ThumbnailMxW":600,"ThumbnailMxH":337,"TeamLogoMxW":250,"TeamLogoMxH":250}; 2717 var _MTS_adSlot = ""; 2718 _MTS_VERSION = "1.14.5.35260"; 2719 2720 2721 2722 </script>
2722 2723 2724 2725
2725<script type="text/javascript" src="https://media-sixrivers.mynews360.com/js/widgets/main.js?v=1.14.5.35260&weburi=https://johnsoncitypress.com/&portalid=213&mediauri=https://media-sixrivers.mynews360.com/"></script>
2725 2726 2727</body> 2728</html> 2729
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.