CINXE.COM

ASPET | Registration

<!DOCTYPE html> <html lang="en" class="no-js"> <head id="head1"><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><meta http-equiv="X-UA-Compatible" content="IE=edge;chrome=1" /><title> ASPET | Registration </title> <!--[if lt IE 9]> <script src="/Scripts/respond.min.js"></script> <script src="/Scripts/html5shiv-printshiv.min.js"></script> <![endif]--> <meta property="og:title" content="Registration" /><meta property="og:url" content="https://www.aspet.org/aspet/meetings-awards/meetingsannual-meeting/annual-meeting-archives/aspet-2024/registration" /><meta property="og:type" content="website" /><meta property="og:site_name" content="www" /><script type="text/javascript" src="https://kit.fontawesome.com/22dafce408.js"></script><meta name="Generator" content="Sitefinity 13.3.7649.0 PE" /><link rel="canonical" href="https://www.aspet.org/aspet/meetings-awards/meetingsannual-meeting/annual-meeting-archives/aspet-2024/registration" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><script type="text/javascript"> (function() {var _rdDeviceWidth = (window.innerWidth > 0) ? window.innerWidth : screen.width;var _rdDeviceHeight = (window.innerHeight > 0) ? window.innerHeight : screen.height;var _rdOrientation = (window.width > window.height) ? 'landscape' : 'portrait';})(); </script><link href="/Telerik.Web.UI.WebResource.axd?d=PMrIT5dOWaVYIcpFWUE4nLkUvQsn23x2K5DJi4spgl2j_o6PywHdaTYhPrkazUlOaOu0vMxQYU_Bx29WG2G3n4Mw3JOt3a5nqIgO3fMbRyf9doxy01Ik3WZf_fVOAJaQ0&amp;t=638688043200174603&amp;compress=0&amp;_TSM_CombinedScripts_=%3b%3bTelerik.Sitefinity.Resources%2c+Version%3d13.3.7649.0%2c+Culture%3dneutral%2c+PublicKeyToken%3db28c218413bdf563%3aen%3a04d52e12-2411-4be3-a9b1-e2f5f38b19e1%3a7a90d6a%3bTelerik.Web.UI%2c+Version%3d2021.1.119.45%2c+Culture%3dneutral%2c+PublicKeyToken%3d121fae78165ba3d4%3aen%3aa0d12491-c9c2-4851-b575-66251a466dfe%3a580b2269%3aeb8d8a8e" type="text/css" rel="stylesheet" /><link href="/Sitefinity/Public/ResponsiveDesign/layout_transformations.css?pageDataId=44d713f3-9998-6662-b1a8-ff0000ef3f42&amp;pageSiteNode=43D713F3-9998-6662-B1A8-FF0000EF3F42/284b0bd2-4837-459a-a1d4-e17303e917d8/SitefinitySiteMap" type="text/css" rel="stylesheet" /><style type="text/css" media="all">.page_banner{ max-width:100%; height:auto; margin-top:2%; padding-top:2%; } .accordion__label { padding: 3.125em 0 ; border:1px solid #ffffff !important; border-bottom:1px solid #dadada !important; text-transform:uppercase; text-rendering: optimizeLegibility; width:80%; } .accordion__content { border:1px solid #ffffff !important; } .accordion__label.is-active { color: #915EA8; border-bottom: 1px solid #bababa !important; background: transparent !important; border-bottom-right-radius: none !important; border-bottom-left-radius: none !important; } .accordion__label:focus { outline: none !important; } table { width: 100%; border-collapse:collapse; } tr:nth-of-type(odd){ background:#f7fbfe; } th { background:#f7fbfe; color:white: font-weight:bold; } td, th{ padding:6px; border:1px solid #ccc; text-align:left; } .2023logo { width:100%; } .division_specific_banner{ display:none } .divider_1{ margin-top:2%; margin-bottom:5%; } .date_container { display:flex; justify-content:space-between; gap:5px; } .date_cover{ display:flex; box-sizing:border-box; flex-direction:column; height:3.125em ; width:3.125em; padding:3px; background:#fff; text-align:center; border:1px solid #dadada; } .month_box{ display:block; color:#444; font-size:.875em; line-height:.875em; text-transform:uppercase; } date_box { display:block; color:#444; font-size:1.625em; line-height:1.625em; } .button{ letter-spacing:.2em; } h2{ font-weight:300; text-transform:uppercase; } @media only screen and (max-width: 760px), (min-device-width:768px) and (max-device-width:1024px) { table {width:100%;font-size:2vmin !important;} thead{display:none} tr: nth-of-type(2n) (background-color: inherit;} tr td: first-child {background: #f0f0f0; font-weight:bold; font-size: 1.3em;} tbody td {display:block; text-align:center;} tbody td:before { content: attr(data-th); display: block: text-align:center; } } @media (min-width: 1596px) { .sfContentBlock .sf-Long-text { display: block; -webkit-user-select: none; margin: auto; cursor: zoom-in; background-color: hsl(0, 0%, 90%); transition: background-color 300ms; } } @media (max-width: 767.97px) { .sfContentBlock .sf-Long-text { display: block; -webkit-user-select: none; margin: auto; cursor: zoom-in; background-color: hsl(0, 0%, 90%); transition: background-color 300ms; } } @media only screen and (max-width: 760px), (min-device-width:768px) and (max-device-width:1024px) { .sfContentBlock .sf-Long-text { display: block; -webkit-user-select: none; margin: auto; cursor: zoom-in; background-color: hsl(0, 0%, 90%); transition: background-color 300ms; } html, body{ overflow:hidden; } } </style><style type="text/css" media="all">@media only screen and (max-width:600px){ p{ font-size:1em; } .interior-layout__title{ width:100% !important; } h2 { font-size:1.5em !important; margin-bottom:2% !important; padding-bottom:2% !important; } h3 { font-size:1.2em !important; } h4, .h4 { font-size:1em !important; } .accordion__label{ width:100% !important; } #ContentPlaceholder_C015_Col00{ margin:-4em !important; } } </style><link href="../../../../../Sitefinity/WebsiteTemplates/Site_Theme/App_Themes/Site_Theme/Global/public.css" type="text/css" rel="stylesheet" media="only screen and (-moz-min-device-pixel-ratio: 2), only screen and (-o-min-device-pixel-ratio: 2/1), only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min-device-pixel-ratio: 2)" /><link href="../../../../../Sitefinity/WebsiteTemplates/Site_Theme/App_Themes/Site_Theme/Global/public.css" type="text/css" rel="stylesheet" media="only screen and (min-width: 240px) and (max-width: 320px)" /><link href="../../../../../Sitefinity/WebsiteTemplates/Site_Theme/App_Themes/Site_Theme/Global/public.css" type="text/css" rel="stylesheet" media="only screen and (min-width: 320px) and (max-width: 480px)" /><link href="../../../../../Sitefinity/WebsiteTemplates/Site_Theme/App_Themes/Site_Theme/Global/public.css" type="text/css" rel="stylesheet" media="only screen and (min-width: 480px) and (max-width : 960px)" /></head> <body> <form method="post" action="./registration" id="aspnetForm"> <div class="aspNetHidden"> <input type="hidden" name="ctl04_TSM" id="ctl04_TSM" value="" /> <input type="hidden" name="ctl05_TSSM" id="ctl05_TSSM" value="" /> <input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" /> <input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" /> <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="sN4CQC+YJKT7drBs639BZwWNYfyIByW/671Ucz+oImt25jA3nw79vDuxO3wwZhoYFvpMIknr3002eBsi/K2kDb3P+Za3AVqWAgb3fEgKUdvFA28YqFz5JKwyEtiBn5iPr2CMrcKNI1cCp+E2kQP+3mSGLSzmj4qi1OZe8KP59oHhz0LSpDKcg6xZr36FcrEcPMLFlPAuL/S2HTGfjTEIRoZsggvwu0arbpivu8hkuw4=" /> </div> <script type="text/javascript"> //<![CDATA[ var theForm = document.forms['aspnetForm']; if (!theForm) { theForm = document.aspnetForm; } function __doPostBack(eventTarget, eventArgument) { if (!theForm.onsubmit || (theForm.onsubmit() != false)) { theForm.__EVENTTARGET.value = eventTarget; theForm.__EVENTARGUMENT.value = eventArgument; theForm.submit(); } } //]]> </script> <script src="/WebResource.axd?d=pynGkmcFUV13He1Qd6_TZO9PWP5WhXeCmZzwFv3KZaxNGfyI0DArO29MLIOwE5PBTXD9mrdh5eP_mn_dhV9S1g2&amp;t=638628063619783110" type="text/javascript"></script> <script type="text/javascript"> //<![CDATA[ var __cultureInfo = {"name":"en","numberFormat":{"CurrencyDecimalDigits":2,"CurrencyDecimalSeparator":".","IsReadOnly":true,"CurrencyGroupSizes":[3],"NumberGroupSizes":[3],"PercentGroupSizes":[3],"CurrencyGroupSeparator":",","CurrencySymbol":"$","NaNSymbol":"NaN","CurrencyNegativePattern":0,"NumberNegativePattern":1,"PercentPositivePattern":1,"PercentNegativePattern":1,"NegativeInfinitySymbol":"-∞","NegativeSign":"-","NumberDecimalDigits":2,"NumberDecimalSeparator":".","NumberGroupSeparator":",","CurrencyPositivePattern":0,"PositiveInfinitySymbol":"∞","PositiveSign":"+","PercentDecimalDigits":2,"PercentDecimalSeparator":".","PercentGroupSeparator":",","PercentSymbol":"%","PerMilleSymbol":"‰","NativeDigits":["0","1","2","3","4","5","6","7","8","9"],"DigitSubstitution":1},"dateTimeFormat":{"AMDesignator":"AM","Calendar":{"MinSupportedDateTime":"\/Date(-62135578800000)\/","MaxSupportedDateTime":"\/Date(253402300799999)\/","AlgorithmType":1,"CalendarType":1,"Eras":[1],"TwoDigitYearMax":2029,"IsReadOnly":true},"DateSeparator":"/","FirstDayOfWeek":0,"CalendarWeekRule":0,"FullDateTimePattern":"dddd, MMMM d, yyyy h:mm:ss tt","LongDatePattern":"dddd, MMMM d, yyyy","LongTimePattern":"h:mm:ss tt","MonthDayPattern":"MMMM d","PMDesignator":"PM","RFC1123Pattern":"ddd, dd MMM yyyy HH\u0027:\u0027mm\u0027:\u0027ss \u0027GMT\u0027","ShortDatePattern":"M/d/yyyy","ShortTimePattern":"h:mm tt","SortableDateTimePattern":"yyyy\u0027-\u0027MM\u0027-\u0027dd\u0027T\u0027HH\u0027:\u0027mm\u0027:\u0027ss","TimeSeparator":":","UniversalSortableDateTimePattern":"yyyy\u0027-\u0027MM\u0027-\u0027dd HH\u0027:\u0027mm\u0027:\u0027ss\u0027Z\u0027","YearMonthPattern":"MMMM yyyy","AbbreviatedDayNames":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"ShortestDayNames":["Su","Mo","Tu","We","Th","Fr","Sa"],"DayNames":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"AbbreviatedMonthNames":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec",""],"MonthNames":["January","February","March","April","May","June","July","August","September","October","November","December",""],"IsReadOnly":true,"NativeCalendarName":"Gregorian Calendar","AbbreviatedMonthGenitiveNames":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec",""],"MonthGenitiveNames":["January","February","March","April","May","June","July","August","September","October","November","December",""]},"eras":[1,"A.D.",null,0]};//]]> </script> <script src="/Telerik.Web.UI.WebResource.axd?_TSM_HiddenField_=ctl04_TSM&amp;compress=0&amp;_TSM_CombinedScripts_=%3b%3bSystem.Web.Extensions%2c+Version%3d4.0.0.0%2c+Culture%3dneutral%2c+PublicKeyToken%3d31bf3856ad364e35%3aen%3a95047a2c-8908-49e3-b68e-d249be89f134%3aea597d4b%3ab25378d2%3bTelerik.Web.UI%2c+Version%3d2021.1.119.45%2c+Culture%3dneutral%2c+PublicKeyToken%3d121fae78165ba3d4%3aen%3aa0d12491-c9c2-4851-b575-66251a466dfe%3aa1a4383a" type="text/javascript"></script> <div class="aspNetHidden"> <input type="hidden" name="__VIEWSTATEGENERATOR" id="__VIEWSTATEGENERATOR" value="D61A044E" /> </div><script type="text/javascript"> //<![CDATA[ Sys.WebForms.PageRequestManager._initialize('ctl00$ctl04', 'aspnetForm', [], [], [], 90, 'ctl00'); //]]> </script> <input type="hidden" name="ctl00$ctl04" id="ctl04" /> <script type="text/javascript"> //<![CDATA[ Sys.Application.setServerId("ctl04", "ctl00$ctl04"); Sys.Application._enableHistoryInScriptManager(); //]]> </script> <iframe id="__historyFrame" src="/ScriptResource.axd?d=qUQ1_T3GVy9s82u8MT1klZpdgjl9yWqNX-oOvuFR9Tm5VUuT-SM5vTFRg502DsxvjHIxPSLDn4pwq3G0qHIj6p_Z85pRqEbhRpdgiLL7rGg1" style="display:none;"> </iframe> <header class="page-header" role="banner"> <h1 class="header-logo"> <link href="/Stylesheets/ASPETAnnual2024/98e612f3-9998-6662-b1a8-ff0000ef3f42?version=312" rel="stylesheet" type="text/css" /> </h1> <button class="header-toggle" data-toggle-target=".header-content, body"> <img src="/images/default-source/page-layout-images/icon-menu.png" alt="" /> </button> <div class="header-content"> <div class="header-utility"> </div> <nav class="page-nav"> <div class="sf_cols page-bounds"> <div class="sf_colsOut " style="" data-placeholder-label="Page Bounds"> <div id="NavigationPlaceholder_TAAA1E201078_Col00" class="sf_colsIn sf_1col_1in_100"> <div > <div class="sfContentBlock sf-Long-text" ><div class="header-logo"><a href="/annual-meeting/meeting" class="fade-in"><img src="https://www.aspet.org/images/default-source/meeting-and-event-images/2024logo.png" alt="Full Color__ASPET2024_Logo_Final" /></a> </div></div> </div> <div > <div class="sfContentBlock sf-Long-text" ><button class="page-header__toggle">Menu <span class="toggle-indicator"> <span class="toggle-indicator__piece toggle-indicator__piece--1"></span><span class="toggle-indicator__piece toggle-indicator__piece--2"></span><span class="toggle-indicator__piece toggle-indicator__piece--3"></span></span> </button></div> </div><div class="sf_cols page-header__content"> <div class="sf_colsOut " style="width: 100%;" data-placeholder-label="Page Header Content"> <div id="NavigationPlaceholder_TAAA1E201077_Col00" class="sf_colsIn sf_1col_1in_100"> <div class="header-utility__item no-margin" > <div class="sfContentBlock sf-Long-text" ><div class="header-utility"><div class="header-user"><div class="header-user__actions"><a href="/aspet/membership-community/aspet-membership/apply-for-membership" class="button button--tiny">Join</a> <a href="/aspet/membership-community/aspet-membership/renew-your-aspet-membership" class="button button--tiny">Renew</a> </div></div><ul class="header-utility__list"><li class="header-utility__item"><a href="/aspet" class="header-utility__link">aspet.org</a> </li></ul></div><div class="header-search"><form class="header-search__form" action="#search-page" role="search"><label class="header-search__label" for="search"><em class="fa-solid fa-magnifying-glass"></em></label> <input class="header-search__input" id="search" name="s" placeholder="Search ASPET" type="text" /><button type="submit" class="header-search__submit"><span class="fa fa-search"></span></button></form></div><div style="position:static !important;"></div><div style="position:static !important;"></div></div> </div> <div class="header-nav "> <ul id="NavigationPlaceholder_T5EE3C0DE045_ctl00_ctl00_navigationUl"> <li> <a href="/aspet/meetings-awards/meetingsannual-meeting/annual-meeting-archives/aspet-2024/abstracts">Abstracts</a> </li> <li> <a href="/aspet/meetings-awards/meetingsannual-meeting/annual-meeting-archives/aspet-2024/aspet-2024-annual-meeting-program">Program</a> <ul id="NavigationPlaceholder_T5EE3C0DE045_ctl00_ctl00_ctl00_ctl01_childNodesContainer"> <li> <a href="/aspet/meetings-awards/meetingsannual-meeting/annual-meeting-archives/aspet-2024/aspet-2024-annual-meeting-program/aspet-committee-and-board-meetings">ASPET Committee and Board Meetings</a> </li> <li> <a href="/aspet/meetings-awards/meetingsannual-meeting/annual-meeting-archives/aspet-2024/aspet-2024-annual-meeting-program/explore-dc">Explore DC</a> </li> <li> <a href="/aspet/meetings-awards/meetingsannual-meeting/annual-meeting-archives/aspet-2024/aspet-2024-annual-meeting-program/division-town-halls">ASPET Town Halls</a> </li> <li> <a href="/aspet/meetings-awards/meetingsannual-meeting/annual-meeting-archives/aspet-2024/aspet-2024-annual-meeting-program/opportunities-for-students-postdocs">Opportunities for Students/Postdocs</a> </li> <li> <a href="/aspet/meetings-awards/meetingsannual-meeting/annual-meeting-archives/aspet-2024/aspet-2024-annual-meeting-program/aspet-capitol-hill-day">ASPET Capitol Hill Day</a> </li> <li> <a href="/aspet/meetings-awards/meetingsannual-meeting/annual-meeting-archives/aspet-2024/aspet-2024-annual-meeting-program/program-details">Program Details</a> </li> <li> <a href="/aspet/meetings-awards/meetingsannual-meeting/annual-meeting-archives/aspet-2024/aspet-2024-annual-meeting-program/keynote-speakers">Keynote Speakers</a> </li> <li> <a href="/aspet/meetings-awards/meetingsannual-meeting/annual-meeting-archives/aspet-2024/aspet-2024-annual-meeting-program/online-programming">Online Programming</a> </li> </ul> </li> <li class="is-current"> <a href="/aspet/meetings-awards/meetingsannual-meeting/annual-meeting-archives/aspet-2024/registration">Registration</a> </li> <li> <a href="/aspet/meetings-awards/meetingsannual-meeting/annual-meeting-archives/aspet-2024/hotel-travel">Hotel & Travel</a> </li> <li> <a href="/aspet/meetings-awards/meetingsannual-meeting/annual-meeting-archives/aspet-2024/policies">Policies</a> </li> <li> <a href="/aspet/meetings-awards/meetingsannual-meeting/annual-meeting-archives/aspet-2024/partners">Partners</a> <ul id="NavigationPlaceholder_T5EE3C0DE045_ctl00_ctl00_ctl00_ctl05_childNodesContainer"> <li> <a href="/aspet/meetings-awards/meetingsannual-meeting/annual-meeting-archives/aspet-2024/partners/thank-you-to-our-sponsors">Thank You to Our Sponsors</a> </li> </ul> </li> </ul> </nav> </div> </div> </div> </div> </div> </div> </nav> </div> </header> <div class="division_specific_banner"> </div> <div> </div> <section class="content" role="main"> <div class="sf_cols "> <div class="sf_colsOut title-block" style="" data-placeholder-label="Title Block Container"> <div id="ContentPlaceholder_T76CE7C69010_Col00" class="sf_colsIn sf_1col_1in_100"><div class="sf_cols "> <div class="sf_colsOut title-block__background" style="" data-placeholder-label="Tile Block Photo"> <div id="ContentPlaceholder_T76CE7C69011_Col00" class="sf_colsIn sf_1col_1in_100"> <div > <div class="sfContentBlock sf-Long-text" ><img src="/images/default-source/meeting-and-event-images/aspet2024/page-panners/registration.jpg" alt="Registration" /></div> </div> </div> </div> </div><div class="sf_cols "> <div class="sf_colsOut title-block__content page-bounds" style="" data-placeholder-label="Title Block Content"> <div id="ContentPlaceholder_T76CE7C69012_Col00" class="sf_colsIn sf_1col_1in_100"> <h1>Registration</h1><div id="ContentPlaceholder_T76CE7C69006"> <div class="breadcrumb"> <span id="ContentPlaceholder_T76CE7C69006_ctl00_ctl00_BreadcrumbLabel" class="sfBreadcrumbLabel" style="display:none;"></span> <div id="ctl00_ContentPlaceholder_T76CE7C69006_ctl00_ctl00_Breadcrumb" class="RadSiteMap RadSiteMap_Default"> <!-- 2021.1.119.45 --><input id="ctl00_ContentPlaceholder_T76CE7C69006_ctl00_ctl00_Breadcrumb_ClientState" name="ctl00_ContentPlaceholder_T76CE7C69006_ctl00_ctl00_Breadcrumb_ClientState" type="hidden" /> </div> </div> </div> </div> </div> </div> </div> </div> </div><div class="sf_cols interior-layout page-bounds"> <div class="sf_colsOut interior-layout__title" style="width: 25%;" data-placeholder-label="Title"> <div id="ContentPlaceholder_T76CE7C69009_Col00" class="sf_colsIn sf_4cols_1in_25"><div id="ContentPlaceholder_C009_Col00" class="sf_colsIn container" data-sf-element="Container"> <div > <div class="sfContentBlock sf-Long-text" ><!--<div class="divider_1"> <h2>Registration</h2> </div>--></div> </div> </div> </div> </div> <div class="sf_colsOut interior-layout__nav" style="width: 25%;" data-placeholder-label="Navigation"> <div id="ContentPlaceholder_T76CE7C69009_Col01" class="sf_colsIn sf_4cols_2in_25"> <div class="interior-nav "> <h5 class="interior-nav__title" data-toggle-target="next">In This Section</h5> <nav class="interior-nav__nav"> <ul id="ContentPlaceholder_T76CE7C69007_ctl00_ctl00_navigationUl"> <li> <a href="/aspet/meetings-awards/meetingsannual-meeting/annual-meeting-archives/aspet-2024/abstracts">Abstracts</a> </li> <li> <a href="/aspet/meetings-awards/meetingsannual-meeting/annual-meeting-archives/aspet-2024/aspet-2024-annual-meeting-program">Program</a> <ul id="ContentPlaceholder_T76CE7C69007_ctl00_ctl00_ctl00_ctl01_childNodesContainer"> <li> <a href="/aspet/meetings-awards/meetingsannual-meeting/annual-meeting-archives/aspet-2024/aspet-2024-annual-meeting-program/aspet-committee-and-board-meetings">ASPET Committee and Board Meetings</a> </li> <li> <a href="/aspet/meetings-awards/meetingsannual-meeting/annual-meeting-archives/aspet-2024/aspet-2024-annual-meeting-program/explore-dc">Explore DC</a> </li> <li> <a href="/aspet/meetings-awards/meetingsannual-meeting/annual-meeting-archives/aspet-2024/aspet-2024-annual-meeting-program/division-town-halls">ASPET Town Halls</a> </li> <li> <a href="/aspet/meetings-awards/meetingsannual-meeting/annual-meeting-archives/aspet-2024/aspet-2024-annual-meeting-program/opportunities-for-students-postdocs">Opportunities for Students/Postdocs</a> </li> <li> <a href="/aspet/meetings-awards/meetingsannual-meeting/annual-meeting-archives/aspet-2024/aspet-2024-annual-meeting-program/aspet-capitol-hill-day">ASPET Capitol Hill Day</a> </li> <li> <a href="/aspet/meetings-awards/meetingsannual-meeting/annual-meeting-archives/aspet-2024/aspet-2024-annual-meeting-program/program-details">Program Details</a> </li> <li> <a href="/aspet/meetings-awards/meetingsannual-meeting/annual-meeting-archives/aspet-2024/aspet-2024-annual-meeting-program/keynote-speakers">Keynote Speakers</a> </li> <li> <a href="/aspet/meetings-awards/meetingsannual-meeting/annual-meeting-archives/aspet-2024/aspet-2024-annual-meeting-program/online-programming">Online Programming</a> </li> </ul> </li> <li class="is-current"> <a href="/aspet/meetings-awards/meetingsannual-meeting/annual-meeting-archives/aspet-2024/registration">Registration</a> </li> <li> <a href="/aspet/meetings-awards/meetingsannual-meeting/annual-meeting-archives/aspet-2024/hotel-travel">Hotel & Travel</a> </li> <li> <a href="/aspet/meetings-awards/meetingsannual-meeting/annual-meeting-archives/aspet-2024/policies">Policies</a> </li> <li> <a href="/aspet/meetings-awards/meetingsannual-meeting/annual-meeting-archives/aspet-2024/partners">Partners</a> <ul id="ContentPlaceholder_T76CE7C69007_ctl00_ctl00_ctl00_ctl05_childNodesContainer"> <li> <a href="/aspet/meetings-awards/meetingsannual-meeting/annual-meeting-archives/aspet-2024/partners/thank-you-to-our-sponsors">Thank You to Our Sponsors</a> </li> </ul> </li> </ul> </nav> </div> </div> </div> <div class="sf_colsOut interior-layout__main" style="width: 25%;" data-placeholder-label="Main"> <div id="ContentPlaceholder_T76CE7C69009_Col02" class="sf_colsIn sf_4cols_3in_25"> <div > <div class="sfContentBlock sf-Long-text" ><div style="margin-bottom:2%;padding-bottom:2%;"><div class="cta-hero__actions"><p><a target="_blank" href="https://www.mylibralounge.com/sites/aspet2024/attendee/en/welcome/?lib_SGU=4F8618BA-0D28-43A9-A6DF-F0F916CEAFEF&amp;lib_CST=E48B78E7-8553-4474-9099-A923BF6239B8" class="button button--action" title="Register today for the ASPET 2024 Annual Meeting!">Register Now</a></p></div><div class="divider_1"><p><a href="https://www.aspet.org/aspet/membership-community/aspet-membership/apply-for-membership ">Become an ASPET member today to enjoy the lower registration rate.</a></p></div><!--<p><strong><a href="https://www.aspet.org/aspet/membership-community/aspet-membership/apply-for-membership " class="button button--action button--secondary ">Renew or Join</a> </strong></p>--> <p>The ASPET Annual Meeting is <em>the </em>place to discover and to present the highest quality, innovative science in pharmacology and experimental therapeutics. The ASPET 2024 Annual Meeting will build on the success of our re-designed 2023 meeting that warmly welcomed more than 1,000 participants to the home for pharmacology. </p><p>You don&rsquo;t want to miss this! </p></div></div> </div> <div > <div class="sfContentBlock sf-Long-text" ><div class="divider_2"><h3>ASPET Registration Fee Includes</h3><p>The ASPET registration fee includes in-person access to all:</p><ul><li>general sessions</li><li>keynotes</li><li>educational and scientific sessions</li><li>poster sessions</li><li>career development activities</li><li>exhibits</li></ul><p>In addition, attendees receive one ticket to attend:</p><ul><li>the opening event at an off-site location</li><li>the business meeting breakfast </li><li>the awards lunch</li><li>three poster receptions </li></ul><p>Registration also provides access to the virtual Award Lecture Series presented live online in April 2024. </p><p>Registrants will also receive access to recordings of select sessions, an attendee directory, meeting abstracts and communication tools to network with abstract authors and other attendees.</p></div></div> </div><div class="sf_cols" data-sf-element="Row"> <div class="sf_colsOut sf_1col_1_100"> <div id="ContentPlaceholder_C026_Col00" class="sf_colsIn sf_1col_1in_100" data-sf-element="Column 1"> <div > <div class="sfContentBlock sf-Long-text" ><div class="divider_2"></div></div> </div> <div > <div class="sfContentBlock sf-Long-text" ><table><tbody><tr><td>&nbsp;</td><td><p><strong>DISCOUNTED </strong><br />On or before <br />Feb. 8, 2024</p></td><td><p><strong>ADVANCE</strong><br />Between<br />Feb. 9<br />and<br />Apr. 18</p></td><td><p><strong>FULL PRICE</strong><br />On or after<br />Apr. 19, 2024 </p></td></tr><tr style=""><td><strong>ASPET Member Discounts *</strong> </td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>Regular, Affiliate, and Emeritus </td><td>$475</td><td>$650 </td><td>$800 </td></tr><tr><td>Postdoctoral Scientist </td><td>$295</td><td>$470 </td><td>$620 </td></tr><tr s=""><td>Graduate Student and Post-baccalaureate </td><td>$100</td><td>$160 </td><td>$225</td></tr><tr><td>Undergraduate Student </td><td>$30</td><td>$60 </td><td style="">$85 </td></tr><tr><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td style=""><strong>Non-Member Rates</strong></td><td><em></em> </td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td style="">Non-member </td><td>$695 </td><td>$870 </td><td>$1,020 </td></tr><tr><td>Postdoctoral Scientist ** </td><td>$410 </td><td>$585 </td><td>$735 </td></tr><tr><td>Graduate Student *** </td><td>$160 </td><td>$220 </td><td>$285</td></tr><tr><td>Undergraduate Student **** </td><td>$60 </td><td>$110 </td><td>$135 </td></tr><tr><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td><strong>One-day Pass</strong></td><td>$350</td><td>$525 </td><td>$675 </td></tr><!-- <tr> <td> <p style="text-align:right;"><strong><em>Deepest discounted rates ended 2/8/2023</em></strong></p> </td> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> </tr> <tr> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> </tr> <tr> <td><strong>Virtual Only Tickets&nbsp;</strong>(included in all above rates)<strong> </strong></td> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> </tr> <tr> <td>Virtual Program Only</td> <td>&nbsp;</td> <td>$125</td> <td>$125</td> </tr> <tr> <td>Virtual Program Only - Graduate Student Discount</td> <td>&nbsp;</td> <td>$50</td> <td>$50</td> </tr> <tr> <td>Virtual Program Only - Undergraduate Student Discount</td> <td>$25</td> <td>$25</td> </tr>--> </tbody></table></div> </div> <div > <div class="sfContentBlock sf-Long-text" ><div class="divider_2"></div></div> </div> <div > <div class="sfContentBlock sf-Long-text" ><div class="space-b-050 space-t-050 space-b-250-m space-t-250-m"></div><div class="space-r-300"></div><div class="space-b-050 space-t-050 space-b-250-m space-t-250-m"></div><div class="space-r-300"></div><div class="space-r-300"></div><div></div></div> </div> <div > <div class="sfContentBlock sf-Long-text" ><div style="margin-left:auto;margin-right:auto;padding-left:2%;padding-right:2%;"><h3>Eligibility Requirements</h3><p>*You must be an ASPET member with <strong>2024 </strong>dues paid in full. Have your membership username and password ready.</p><p>** <strong>Postdoctoral Scientists:</strong> Any qualified person who has received their Ph.D. or equivalent degree in pharmacology or a related field within the past five years.</p><p>*** <strong>Graduate Students:</strong>&nbsp;Must be enrolled in a graduate or professional degree program and have not yet earned a doctoral degree.&nbsp; For non-members, when registering online, enter the name and email address of your department head. &nbsp; Postdoctoral fellows, hospital residents, interns, and laboratory technicians do not qualify as students.</p><p>**** <strong>Undergraduate Students</strong>: Must be enrolled in an undergraduate degree program and have not yet earned a baccalaureate degree. For non-members, when registering online, enter the name and email address of your department head.</p></div></div> </div> <div > <div class="sfContentBlock sf-Long-text" ><div style="margin-top:2%;padding-top:2%;"><table style="margin-right:auto;margin-left:auto;width:60%;"><tbody><tr colspan="2" style=""><th><p><strong>Important Dates</strong></p><strong></strong></th><th></th></tr><tr style=""><td style=""><p><strong>February 8</strong></p></td><td><p>Deepest registration discounts end</p></td></tr><tr><td><p><strong>April 18</strong></p></td><td><p>Advance registration discounts end</p></td></tr></tbody></table></div></div> </div> <div > <div class="sfContentBlock sf-Long-text" ><div class="divider_2"><h3>Attention ASPET Emeritus Members</h3><p>We welcome our retired members to continue to join us at your home for pharmacology. If the registration fees create a hardship to your participation, please contact us at meetings@aspet.org for a 50% discount for eligible ASPET members with emeritus membership status.<br /></p><div></div></div></div> </div> <div > <div class="sfContentBlock sf-Long-text" ><div class="divider_2"><h3>Cancellation Policy</h3><p>Requests for cancellation received on or before February 8 will receive a full refund. For requests received between February 9 and April 18 a processing fee will be deducted from all refunds ($50 for students, $100 for all other registration categories.) All refunds are processed after the meeting.&nbsp; No refunds for cancellations will be accepted after April 18. Virtual meeting registration fees are non-refundable.&nbsp; Refund requests must be in writing. Please email <a href="mailto:meetings@aspet.org">meetings@aspet.org</a>.</p><p>Substitutions will be accepted with any difference in registration fees based on membership or other special discounts being paid in full at the time of substitution. For example, if the canceling registrant received discounts for membership and for being an awardee, the fees paid by the original registrant will be transferred to the replacement and the replacement, if not a member or an awardee will need to pay the difference in fees up to the amount of their own applicable categories as a non-member and non-awardee.</p><p>&nbsp;</p></div></div> </div> <div > <div class="sfContentBlock sf-Long-text" ><div class="divider_2"><h3>Onsite Registration</h3><p>Badge pick-up will take place in the Independence Foyer of the Hyatt Regency Crystal City during the hours below.</p><p></p></div></div> </div> <div > <div class="sfContentBlock sf-Long-text" ><div style="margin-top:2%;padding-top:2%;"><table style="margin-right:auto;margin-left:auto;width:60%;"><tbody><tr><th>TENTATIVE SCHEDULE </th><th></th></tr><tr><td><p><strong>Wednesday, May 15</strong></p></td><td>5:00 pm - 7:00 pm </td></tr><tr><td><strong>Thursday, May 16</strong> </td><td>9:00 am - 7:30 pm </td></tr><tr><td><strong>Friday, May 17</strong></td><td>7:30 am - 7:00 pm<br /></td></tr><tr><td><strong>Saturday, May 18</strong></td><td>7:30 am - 6:00 pm</td></tr><tr><td><strong>Sunday, May 19</strong></td><td>7:30 am - 12:30 pm</td></tr></tbody></table></div></div> </div><div class="sf_cols" data-sf-element="Row"> <div class="sf_colsOut sf_1col_1_100"> <div id="ContentPlaceholder_C015_Col00" class="sf_colsIn sf_1col_1in_100" data-sf-element="Column 1"><div class="sf_cols" data-sf-element="Row"> <div class="sf_colsOut sf_1col_1_100"> <div id="ContentPlaceholder_C031_Col00" class="sf_colsIn sf_1col_1in_100" data-sf-element="Column 1"> </div> </div> </div> </div> </div> </div> </div> </div> </div> </div> </div> <div class="sf_colsOut interior-layout__aside" style="width: 25%;" data-placeholder-label="Aside"> <div id="ContentPlaceholder_T76CE7C69009_Col03" class="sf_colsIn sf_4cols_4in_25"> <div > <div class="sfContentBlock sf-Long-text" ><!--<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aspernatur quos perferendis incidunt maxime debitis a consectetur nihil laboriosam, molestiae provident pariatur autem earum quibusdam eius cupiditate amet reprehenderit possimus voluptatum?</p> <p>Nisi dignissimos enim unde hic beatae accusamus autem accusantium eaque dicta harum? Quia corporis totam minus odio voluptates cumque illum, eos doloribus laborum veritatis aperiam et ex, suscipit eum ipsam?</p>--></div> </div> <div > <div class="sfContentBlock sf-Long-text" ><h5><span class="quicklinks__icon"><em class="fa-thin fa-calendar-circle-exclamation"></em></span> Important Dates</h5><div style="display:flex;flex-direction:column;justify-content:space-between;"><!-- <div style="margin-bottom:1em;"> <div class="date_container"> <div class="date_cover"> <div class="month_box"> <p>Dec </p> </div> <div class="date_box"> <p>11</p> </div> </div> <div style="flex-basis:80%;"> <p>Abstract Deadline Extended</p> </div> </div> </div> <div style="margin-bottom:1em;"> <div class="date_container"> <div class="date_cover"> <div class="month_box"> <p>Dec </p> </div> <div class="date_box"> <p>15</p> </div> </div> <div style="flex-basis:80%;"> <p>Last day to apply for the ASPET Mentoring Network </p> </div> </div> </div> <div style="margin-bottom:1em;"> <div class="date_container"> <div class="date_cover"> <div class="month_box"> <p>Feb </p> </div> <div class="date_box"> <p>8</p> </div> </div> <div style="flex-basis:80%;"> <p>Registration Discounts End </p> </div> </div> </div> <div style="margin-bottom:1em;"> <div class="date_container"> <div class="date_cover"> <div class="month_box"> <p>Feb</p> </div> <div class="date_box"> <p>22</p> </div> </div> <div style="flex-basis:80%;"> <p>The abstract submission deadline for the poster presentation ends today.</p> </div> </div> </div> <div style="margin-bottom:1em;"> <div class="date_container"> <div class="date_cover" style="width:3.25em !important;"> <div class="month_box"> <p>Apr </p> </div> <div class="date_box"> <p>&nbsp;</p> </div> </div> <div style="flex-basis:80%;"> <p>Online VIP award lectures and division town halls </p> </div> </div> </div>--> <div style="margin-bottom:1em;"><div class="date_container"><div class="date_cover"><div class="month_box"><p>May </p></div><div class="date_box"><p>16-19</p></div></div><div style="flex-basis:80%;"><p>ASPET Annual Meeting in Arlington, VA </p></div></div></div><div style="margin-bottom:1em;"><div class="date_container"><div class="date_cover"><div class="month_box"><p>May</p></div><div class="date_box"><p>19-20</p></div></div><div style="flex-basis:80%;"><p>ADDC/ASPET Colloquium </p></div></div></div><div style="margin-bottom:1em;"><div class="date_container"><div class="date_cover"><div class="month_box"><p>April </p></div><div class="date_box"><p>3-6</p></div></div><div style="flex-basis:80%;"><p>ASPET 2025 Annual Meeting <br />Portland, OR </p></div></div></div><div style="margin-bottom:1em;"><div class="date_container"><div class="date_cover"><div class="month_box"><p>May</p></div><div class="date_box"><p>17-20</p></div></div><div style="flex-basis:80%;"><p>ASPET 2026 Annual Meeting <br />Minneapolis, MN </p></div></div></div></div></div> </div> </div> </div> </div><div class="sf_cols"> <div class="sf_colsOut page-footer" style="width: 100%;" data-placeholder-label="Page Footer"> <div id="ContentPlaceholder_TAAA1E201086_Col00" class="sf_colsIn sf_1col_1in_100"> <div > <div class="sfContentBlock sf-Long-text" ><div class="page-bounds"><div class="page-footer__content"><div class="footer-contact"><div class="footer-logo"><a href="/annual-meeting/meeting"><img src="https://www.aspet.org/images/default-source/meeting-and-event-images/2024logo.png" alt="2024 Annual Meeting" /></a> </div><p>1801 Rockville Pike, Suite 210, Rockville, Maryland 20852-1633 <br />Phone: (301) 634-7060 <br />Fax: (301) 634-7061 &nbsp;&nbsp;<a target="_blank" href="https://www.aspet.org">aspet.org</a> <br /><a href="mailto:Meetings@aspet.org?subject=ASPET Annual Meeting">Meeting Questions</a><br /></p></div><div class="footer-social"><span class="screenreaders-only">Visit us on</span> <a target="_blank" href="https://www.facebook.com/ASPETpage/" class="footer-social__icon"><em class="fa-brands fa-facebook-f"></em><span class="screenreaders-only">Facebook</span></a> <a target="_blank" href="https://twitter.com/aspet" class="footer-social__icon"><em class="fa-brands fa-twitter"></em><span class="screenreaders-only">Twitter</span></a> <a target="_blank" href="https://www.linkedin.com/company/2530899" class="footer-social__icon"><em class="fa-brands fa-linkedin-in"></em><span class="screenreaders-only">LinkedIn</span></a> </div><div class="footer-utility"><ul class="footer-utility__list"><li class="footer-utility__item"><a href="/aspet/about-us/about-the-aspet-website" class="footer-utility__link">Privacy Policy</a> </li><li class="footer-utility__item"><a href="/reference/annual-2023-home-page/annual-site-map" class="footer-utility__link">Site Map</a> </li><li class="footer-utility__item"><a href="/aspet/about-us/about-the-aspet-website#cookies" class="footer-utility__link">Cookie Policy</a> </li></ul></div></div><div class="footer-copyright">&copy; 2024 American Society for Pharmacology and Experimental Therapeutics</div></div></div> </div> </div> </div> </div><div class="sf_cols" data-sf-element="Row"> <div class="sf_colsOut sf_1col_1_100"> <div id="ContentPlaceholder_C021_Col00" class="sf_colsIn sf_1col_1in_100" data-sf-element="Column 1"> <div > <div class="sfContentBlock sf-Long-text" ><div class="space-b-050 space-t-050 space-b-250-m space-t-250-m"></div><div class="space-r-300"></div><div class="space-b-050 space-t-050 space-b-250-m space-t-250-m"></div><div class="space-r-300"></div><div class="space-r-300"></div><div></div></div> </div> </div> </div> </div> <div > <div class="sfContentBlock sf-Long-text" ><div class="space-b-050 space-t-050 space-b-250-m space-t-250-m"></div><div class="space-r-300"></div><div class="space-b-050 space-t-050 space-b-250-m space-t-250-m"></div><div class="space-r-300"></div><div class="space-r-300"></div><div></div></div> </div> </section> <footer class="page-footer" role="contentinfo"> <div class="grid page-width"> <div class="grid__unit grid__unit--1-4-l"> </div> <div class="grid__unit grid__unit--1-2-l"> </div> <div class="grid__unit grid__unit--1-4-l"> <div class="footer-social clear-smaller"> </div> </div> </div> </footer> <link rel="stylesheet" href="https://use.typekit.net/hjd8wmq.css"> <link href="https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,300;0,400;1,300;1,400&family=Roboto:ital@0;1&display=swap" rel="stylesheet"> <link rel="shortcut icon" href="/ResourcePackages/Bootstrap/assets/images/ASPET 2023 favicon.ico"> <script type="text/javascript"> //<![CDATA[ window.__TsmHiddenField = $get('ctl04_TSM');(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); })(window,document,'script','dataLayer','GTM-TJLTMW');//]]> </script> <script type="text/javascript">/*SEARCH CODE*/ function doSearch(event, element) { if (event.keyCode == 13) { var keyword = element ? element.value : document.getElementById("search").value; if (!!keyword && keyword.length > 0) { if (event && event.preventDefault) { event.preventDefault(); } else { event.returnValue = false; } window.location = "/search-results?keywords=" + encodeURIComponent(keyword); } } } document.addEventListener("DOMContentLoaded", function (event) { var searchEL = document.getElementById('search'); if (searchEL != null) { searchEL.addEventListener("keydown", doSearch); } }); </script><script type="text/javascript" src="/Scripts/Annual2023-scripts/lodash.custom.min.js"></script><script type="text/javascript" src="/Scripts/Annual2023-scripts/prism.min.js"></script><script type="text/javascript">/* common RD UI utilities * dependencies: lodash */ var RDJS = (function (window, document) { 'use strict'; /* =helper functions * ================= */ // quick no-effort polyfill for Element.matches if (!Element.prototype.matches) { Element.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector; } // cast to array, because _.toArray and _.castArray are inadequate when // the argument could be either a node or nodeList. Also doubles as // an array copier function toArray(collection) { var result = []; if (collection) { if (typeof collection.length === 'number') { for (var i = 0; i < collection.length; i++) { result.push(collection[i]); } } else { result.push(collection); } } return result; } // get all elements not contained within certain parents // because css selectors are currently inadequate to solve this problem // in the general case function getElementsWithoutParent(selector, parentBlacklist, currentParent) { if (!currentParent) { currentParent = document.documentElement; } var result = []; if (!currentParent.children) { return result; } for (var i = 0; i < currentParent.children.length; i++) { if (currentParent.children[i].matches(selector)) { result.push(currentParent.children[i]); } if (!currentParent.children[i].matches(parentBlacklist)) { result = result.concat(getElementsWithoutParent(selector, parentBlacklist, currentParent.children[i])); } } return result; } // return a valid url-encoded string of parameters from an object // currently does not support nested objects function objectToParameters(obj) { var parts = []; for (var key in obj) { if (obj.hasOwnProperty(key)) { parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(obj[key])); } } return parts.join('&'); } // produce a valid html id (with some additional considerations) from an // arbitrary string. Providing a value for 'defaultId' will cover cases where // the string is blank or consists entirely of characters we will strip out function generateHtmlId(str, defaultId) { // sanitize our id value a bit. The html5 spec is /very/ permissive about // what can be in an id (pretty much anything but spaces goes), but strip // out some additional characters in case we're using this as a url fragment var idString = str .trim() .replace(/\s+/g, '-') .replace(/[\.\?\$\/ #&%@,]/g, '') .toLowerCase(); idString = idString || defaultId || ''; // in case str was empty or all special chars // if we have an id conflict, increment until we don't. We could append // some kind of random value, but we want this to produce the same // linkable hash each run var tryCount = 0; var existingElement = document.getElementById(idString); while (existingElement) { tryCount++; existingElement = document.getElementById(idString + '-' + String(tryCount)); } if (tryCount > 0) { idString += '-' + String(tryCount); } return idString; } // xhr helper function xhr(method, url, callback, data) { var _validMethods = ['GET', 'POST', 'HEAD', 'PUT', 'DELETE', 'CONNECT', 'OPTIONS', 'TRACE', 'PATCH'], xhr = new XMLHttpRequest(); if (!method) { console.error('No method provided to xhr'); return false; } method = method.toUpperCase(); if (!_validMethods.includes(method)) { console.error(method + ' is not a valid http request method'); return false; } if (!url) { console.error('No url provided to xhr'); return false; } xhr.onreadystatechange = function () { if (xhr.readyState === XMLHttpRequest.DONE) { if (xhr.status === 200) { if (callback && typeof callback === 'function') { callback(xhr.responseText); } else { console.log(xhr.responseText); } } else { console.error('XHR returned a status of ' + xhr.status); console.log(xhr); } } }; xhr.open(method, url); if (method === 'POST' && data) { xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); if (typeof data === 'object') { xhr.send(objectToParameters(data)); } else { xhr.send(data); } } else { xhr.send(); } } /* =toggles * ======== * * a one-to-many class toggler activated on click * * default elements: * <el data-toggle-target="[keyword|selector]" /> * * external toggle interactions * <el data-toggle-exit="esc outside" /> */ var toggles = (function () { var toggleList = [], togglePrototype = { origin: null, targets: [], activeClass: 'is-active', deactivateOnEsc: false, deactivateOnOutside: false, useFragments: false, // make toggle go activate: function activate(force) { _.forEach([this.origin].concat(this.targets), function (el, i) { if (typeof force === 'boolean') { el.classList.toggle(this.activeClass, force); } else { el.classList.toggle(this.activeClass); } // if this is the origin, set control state if (i === 0) { el.setAttribute('aria-expanded', (el.classList.contains(this.activeClass)).toString()); // if this is a toggle, set aria hidden state } else { el.setAttribute('aria-hidden', (!el.classList.contains(this.activeClass)).toString()); } }.bind(this)); // focus first target as a convenience to kb/sr users if (this.origin.classList.contains(this.activeClass) && this.targets.length > 0) { this.targets[0].focus(); } // write url fragment, if applicable if (this.useFragments && this.origin.id) { if (this.origin.classList.contains(this.activeClass)) { window.history.replaceState(null, '', '#' + encodeURIComponent(this.origin.id)); } else { window.history.replaceState(null, '', window.location.href.split('#')[0]); } } if (typeof this.onActivate === 'function') { this.onActivate(this); } return this; }, // get targets, generate a11y attributes, and add event listeners init: function init() { this.targets = toArray(this.targets); // set up ids this.origin.id = this.origin.id || generateHtmlId(this.origin.textContent.substr(0, 24), 'toggle'); _.forEach(this.targets, function generateTargetId(target) { target.id = target.id || generateHtmlId(this.origin.textContent.substr(0, 24) + '-pane', 'pane'); }.bind(this)); // set initial a11y attributes this.origin.setAttribute('role', 'button'); this.origin.setAttribute('aria-expanded', (this.origin.classList.contains(this.activeClass)).toString()); this.origin.setAttribute('aria-controls', this.targets[0].id); _.forEach(this.targets, function linkTargetToOrigin(target) { target.setAttribute('aria-labelledby', this.origin.id); target.setAttribute('aria-hidden', (!this.origin.classList.contains(this.activeClass)).toString()); }.bind(this)); // make toggle focusable if it isn't a focusable element by default this.origin.setAttribute('tabindex', '0'); // allow programmatic focus on first target content element if (this.targets.length > 0) { this.targets[0].setAttribute('tabindex', '-1'); } // bind listeners this.origin.addEventListener('click', function (ev) { ev.preventDefault(); this.activate(); }.bind(this)); this.origin.addEventListener('keydown', function (ev) { // bind spacebar and return in case we're not using a native // button element that includes these interactions implicitly if (ev.keyCode === 13 || ev.keyCode === 32) { ev.preventDefault(); this.activate(); } }.bind(this)); if (typeof this.onInit === 'function') { this.onInit(this); } return this; }, // optional callbacks onActivate: null, onInit: null }; // private: parses a target string and returns a matching array function findTargets(el) { var targetString = el.getAttribute('data-toggle-target'); if (!targetString) { return []; } else if (targetString === 'next') { return [el.nextElementSibling]; } else if (targetString === 'parent') { return [el.parentNode]; } else if (targetString === 'parentparent') { return [el.parentNode.parentNode]; } else if (targetString === 'parentnext') { return [el.parentNode.nextElementSibling]; } else if (targetString === 'parentparentnext') { return [el.parentNode.parentNode.nextElementSibling]; } return toArray(document.querySelectorAll(targetString)); } // public: make node or nodeList toggleable function add(els, options) { options = options || {}; els = toArray(els); _.forEach(els, function (el) { var toggle = _.assign(Object.create(togglePrototype), { origin: el }, options); toggleList.push(toggle); toggle.init(); }); return list(); } // public: returns an array of all toggles on the page function list() { return toggleList; } // public: returns all toggle objects whose origins match a given css selector function find(selector) { var result = []; _.forEach(list(), function (toggle) { if (toggle.origin.matches(selector)) { result.push(toggle); } }); return result; } // public: returns a single toggle object whose origin matches a given css selector function get(selector) { var result = null; _.forEach(list(), function (toggle) { if (toggle.origin.matches(selector)) { result = toggle; return false; } }); return result; } // public: initialize by adding default elements function init() { _.forEach(document.querySelectorAll('[data-toggle-target]'), function addNewToggle(el) { var options = { targets: findTargets(el), deactivateOnEsc: (/\besc\b/.test(el.getAttribute('data-toggle-exit'))), deactivateOnOutside: (/\boutside\b/.test(el.getAttribute('data-toggle-exit'))), useFragments: Boolean(el.getAttribute('data-toggle-fragment')), }; add(el, options); }); // open any toggles that match url fragment if (window.location.hash) { var urlFragment = decodeURIComponent(window.location.hash.substr(1)); _.forEach(list(), function matchGroupFragment(group) { _.forEach([group.origin].concat(group.targets), function matchElementFragment(el) { if (el.id === urlFragment) { group.activate(true); } }); }); } // add global close listeners document.documentElement.addEventListener('keyup', function (ev) { if (ev.keyCode === 27) { _.forEach(list(), function (toggle) { if (toggle.deactivateOnEsc) { toggle.activate(false); } }); } }); document.body.addEventListener('click', function (ev) { _.forEach(list().filter(function (toggle) { return toggle.deactivateOnOutside; }), function (toggle) { var deactivate = true, els = [toggle.origin].concat(toggle.targets); for (var i = els.length - 1; i >= 0; i--) { if (els[i] === ev.target || els[i].contains(ev.target)) { deactivate = false; break; } } if (deactivate) { toggle.activate(false); } }); }); } return { add: add, list: list, find: find, get: get, init: init }; }()); /* =tabs * ===== * * a class switcher wherein only one element (or pair of elements) * may be active at a time * * default elements: * <el class="tabs [is-automated]?"> * <el class="tabs__tab" /> * <el class="tabs__pane" /> * </el> */ var tabs = (function () { var tabGroupList = [], tabGroupPrototype = { // preferences automated: false, slideDuration: 5000, useFragments: false, // calculated attributes active: 0, count: 0, // elements container: null, tabs: null, panes: null, nextTriggers: null, previousTriggers: null, playTriggers: null, pauseTriggers: null, // default (overrideable) selectors used in init() containerSelector: '.tabs', tabSelector: '.tabs__tab', paneSelector: '.tabs__pane', nextSelector: '.tabs__next', previousSelector: '.tabs__previous', playSelector: '.tabs__play', pauseSelector: '.tabs__pause', // classes activeClass: 'is-active', lastActiveClass: 'is-last-active', nextClass: 'is-next', previousClass: 'is-previous', initClass: 'is-enhanced', playingClass: 'is-playing', // utility timer: null, changeTo: function changeTo(index, interruptTimer, isFirstLoad) { if (index === 'next') { index = this.getNextIndex(); } else if (index === 'previous') { index = this.getPreviousIndex(); } else if (typeof index !== 'number' || index < 0 || index >= this.count) { console.warn('given index not recognized'); return this; } if (interruptTimer && this.automated) { this.pause(); } // reset state classes to blank slate _.forEach(this.tabs.concat(this.panes), function (el) { el.classList.remove(this.activeClass); el.classList.remove(this.lastActiveClass); el.classList.remove(this.nextClass); el.classList.remove(this.previousClass); }.bind(this)); // reset aria attributes to defaults _.forEach(this.tabs, function (tab) { tab.setAttribute('aria-selected', 'false'); }.bind(this)); _.forEach(this.panes, function (pane) { pane.setAttribute('aria-hidden', 'true'); }.bind(this)); // mark the tab we're changing /from/ for the purposes of animation if (this.active !== index) { if (this.tabs[this.active]) { this.tabs[this.active].classList.add(this.lastActiveClass); } if (this.panes[this.active]) { this.panes[this.active].classList.add(this.lastActiveClass); } } // make it so this.active = index; // add all state classes and aria states if (this.tabs[index]) { this.tabs[index].classList.add(this.activeClass); this.tabs[index].setAttribute('aria-selected', 'true'); } if (this.panes[index]) { this.panes[index].classList.add(this.activeClass); this.panes[index].setAttribute('aria-hidden', 'false'); } if (this.tabs[this.getNextIndex()]) { this.tabs[this.getNextIndex()].classList.add(this.nextClass); } if (this.panes[this.getNextIndex()]) { this.panes[this.getNextIndex()].classList.add(this.nextClass); } if (this.tabs[this.getPreviousIndex()]) { this.tabs[this.getPreviousIndex()].classList.add(this.previousClass); } if (this.panes[this.getPreviousIndex()]) { this.panes[this.getPreviousIndex()].classList.add(this.previousClass); } // handle fragment ids // no need to do this on initial page load, because either it's loading the default // (first) tab or we're loading from an existing fragment specifier if (this.useFragments && this.tabs[index] && this.tabs[index].id && !isFirstLoad) { window.history.replaceState(null, '', '#' + encodeURIComponent(this.tabs[index].id)); } // focus first element inside selected pane for a better screen-reader experience if (!isFirstLoad && !this.automated && this.panes[index] && this.panes[index].children.length > 0) { this.panes[index].children[0].setAttribute('tabindex', '-1'); this.panes[index].children[0].focus(); } if (interruptTimer && this.automated) { this.play(); } if (typeof this.onChange === 'function') { this.onChange(this); } return this; }, play: function play() { this.container.classList.add(this.playingClass); if (this.timer > 0) { return false; } this.timer = setInterval(function () { this.changeTo('next'); }.bind(this), this.slideDuration); if (typeof this.onPlay === 'function') { this.onPlay(this); } return this; }, pause: function pause() { this.container.classList.remove(this.playingClass); clearInterval(this.timer); this.timer = 0; if (typeof this.onPause === 'function') { this.onPause(this); } return this; }, getNextIndex: function getNextIndex() { return (this.active + 1) % this.count; }, getPreviousIndex: function getPreviousIndex() { return this.active <= 0 ? this.count - 1 : this.active - 1; }, generateTabIds: function generateTabIds() { _.forEach(this.tabs, function generateTabId(el) { if (el.id) return false; // skip if an id has been provided for us el.id = generateHtmlId(el.textContent, 'tab'); }); }, generateAriaAttributes: function generateAriaAttributes() { for (var i = 0; i < this.count; i++) { // make sure each pane also has an id // if an id is not present, generate from the associated tab id if (this.tabs[i] && this.panes[i]) { if (!this.panes[i].id) { this.panes[i].id = this.tabs[i].id + '-pane'; } // make sure each tab is linked to its associated pane if (this.tabs[i].tagName.toLowerCase() == 'a') { this.tabs[i].href = '#' + this.panes[i].id; } this.tabs[i].setAttribute('aria-controls', this.panes[i].id); // make sure each pane is labeled by its associated tab this.panes[i].setAttribute('aria-labelledby', this.tabs[i].id); } } }, init: function init() { // default elements this.tabs = toArray(this.tabs || getElementsWithoutParent(this.tabSelector, this.containerSelector, this.container)); this.panes = toArray(this.panes || getElementsWithoutParent(this.paneSelector, this.containerSelector, this.container)); this.nextTriggers = toArray(this.nextTriggers || getElementsWithoutParent(this.nextSelector, this.containerSelector, this.container)); this.previousTriggers = toArray(this.previousTriggers || getElementsWithoutParent(this.previousSelector, this.containerSelector, this.container)); this.playTriggers = toArray(this.playTriggers || getElementsWithoutParent(this.playSelector, this.containerSelector, this.container)); this.pauseTriggers = toArray(this.pauseTriggers || getElementsWithoutParent(this.pauseSelector, this.containerSelector, this.container)); // get final tabs count this.count = Math.max(this.tabs.length, this.panes.length); // generate tab ids for a11y and fragment links this.generateTabIds(); // link tabs and panes in markup for screen reader benefit this.generateAriaAttributes(); // apply count as container class to help css sizing this.container.classList.add('tabs--' + String(this.count)); // attach event listeners _.forEach(this.tabs, function (tab, index) { tab.setAttribute('tabindex', '0'); tab.addEventListener('click', function (ev) { ev.preventDefault(); this.changeTo(index, true); }.bind(this)); tab.addEventListener('keydown', function (ev) { if (ev.keyCode === 13 || ev.keyCode === 32) { ev.preventDefault(); this.changeTo(index, true); } }.bind(this)); }.bind(this)); _.forEach(this.nextTriggers, function (el) { el.addEventListener('click', function (ev) { ev.preventDefault(); this.changeTo('next', true); }.bind(this)); }.bind(this)); _.forEach(this.previousTriggers, function (el) { el.addEventListener('click', function (ev) { ev.preventDefault(); this.changeTo('previous', true); }.bind(this)); }.bind(this)); _.forEach(this.pauseTriggers, function (el) { el.addEventListener('click', function (ev) { ev.preventDefault(); this.pause(); }.bind(this)); }.bind(this)); _.forEach(this.playTriggers, function (el) { el.addEventListener('click', function (ev) { ev.preventDefault(); this.play(); }.bind(this)); }.bind(this)); // automated slideshows get paused on mouseover if (this.automated) { this.container.addEventListener('mouseenter', this.pause.bind(this)); this.container.addEventListener('mouseleave', this.play.bind(this)); } // if we have a fragment specifier, use it; otherwise, the first tab is open by default if (this.useFragments && window.location.hash) { var fragment = decodeURIComponent(window.location.hash.substr(1)); for (var i = 0; i < this.tabs.length; i++) { if (this.tabs[i].id === fragment) { this.active = i; break; } } } this.changeTo(this.active, false, true); if (this.automated) { this.play(); } if (typeof this.onInit === 'function') { this.onInit(this); } this.container.classList.add(this.initClass); return this; }, // optional callbacks onChange: null, onPlay: null, onPause: null, onInit: null }; // public: make node or nodeList into tab groups function add(els, options) { options = options || {}; els = toArray(els); _.forEach(els, function (el) { var tabGroup = _.assign(Object.create(tabGroupPrototype), { container: el }, options); tabGroupList.push(tabGroup); tabGroup.init(); }); return list(); } // public: returns an array of all tab groups on the page function list() { return tabGroupList; } // public: returns all tab groups whose containers match a given css selector function find(selector) { var result = []; _.forEach(list(), function (tabGroup) { if (tabGroup.container.matches(selector)) { result.push(tabGroup); } }); return result; } // public: returns a single tab group whose container matches a given css selector function get(selector) { var result = null; _.forEach(list(), function (tabGroup) { if (tabGroup.container.matches(selector)) { result = tabGroup; return false; } }); return result; } // public: initialize by adding default elements function init() { _.forEach(toArray(document.getElementsByClassName('tabs')), function addTabsContainer(container) { add(container, { automated: container.matches('.tabs--automated'), useFragments: container.matches('.tabs--use-fragments'), }); }); } return { add: add, list: list, find: find, get: get, init: init }; }()); /* =shared height elements * ======================= * * match minimum heights across disparate elements * * usage: * <el data-height-group="groupname" /> */ var sharedHeights = (function () { var heightGroups = {}; // public: update all shared-height elements function update() { var g, thisGroup, heights, maxHeight; function resetHeight(el) { el.style.minHeight = 0; heights.push(el.offsetHeight); } function applyHeight(el) { el.style.minHeight = maxHeight + 'px'; } for (g in heightGroups) { if (heightGroups.hasOwnProperty(g)) { thisGroup = heightGroups[g]; heights = []; _.forEach(thisGroup, resetHeight); maxHeight = Math.max.apply(null, heights); _.forEach(thisGroup, applyHeight); } } } // public: add shared-height functionality to a node or nodelist function add(els, groupName) { _.forEach(toArray(els), function (el) { var group = groupName || el.getAttribute('data-height-group'); if (!group) { console.warn('No group specified for shared-height element'); return false; } heightGroups[group] = heightGroups[group] || []; heightGroups[group].push(el); }); return list(); } // public: return heightGroups object function list() { return heightGroups; } // public: initialize with default elements function init() { add(document.querySelectorAll('[data-height-group]')); update(); } var debouncedUpdate = _.debounce(update, 75); window.addEventListener('resize', debouncedUpdate); window.addEventListener('load', debouncedUpdate); return { add: add, list: list, update: update, init: init }; }()); /* =waypoints * ========== * * a scrolling waypoint-based class switcher, for when skrollr is overkill * * default elements: * <el data-waypoints="waypoint[ persist]?: class" /> * where waypoint is a number and a unit of measurement (%, px, em). * multiple waypoints may be separated by commas */ var waypoints = (function () { var waypointElementList = [], waypointElementPrototype = { el: null, waypoints: [], init: function () { var configString = this.el.getAttribute('data-waypoints'); if (!configString) { return false; } _.forEach(configString.split(','), function (config) { var configParts = config.split(':'), val, cl, unit, persist = false, waypoint; try { val = configParts[0].trim(); cl = configParts[1].trim(); if (val.substr(-7) === 'persist') { persist = true; val = val.slice(0, -7).trim(); } unit = val.replace(/\d|,/g, '') || '%'; val = parseFloat(val); if (!cl || isNaN(val) || typeof val !== 'number') { throw 'Bad config'; } waypoint = _.assign(Object.create(waypointPrototype), { unit: unit, val: val, cl: cl, persistent: persist }); this.waypoints.push(waypoint); } catch (e) { console.warn('Bad inline configuration provided to waypoints in element ', this.el, ' at waypoint ', configParts[0]); } }.bind(this)); } }, waypointPrototype = { val: 50, unit: '%', cl: '', persistent: false }; function scrollListener() { var viewportHeight = document.documentElement.clientHeight; _.forEachRight(waypointElementList, function (waypointElement, elementIndex) { var offset = waypointElement.el.getBoundingClientRect().top - viewportHeight, scroll = window.scrollY; if (offset < 0 && window.scrollY > 0) { _.forEachRight(waypointElement.waypoints, function (waypoint, waypointIndex) { var test = false; switch (waypoint.unit) { case '%': var percentage = -offset / waypointElement.el.offsetHeight * 100; test = percentage > waypoint.val; break; case 'em': var elementFontSize = parseFloat(getComputedStyle(waypointElement.el).fontSize); test = -offset > elementFontSize * waypoint.val; break; case 'rem': var documentFontSize = parseFloat(getComputedStyle(document.body).fontSize); test = -offset > documentFontSize * waypoint.val; break; case 'vh': test = -offset > viewportHeight / 100 * waypoint.val; break; default: // px test = -offset > waypoint.val; break; } if (test) { waypointElement.el.classList.add(waypoint.cl); // no need to continue tracking persistent elements after activation if (waypoint.persistent) { waypointElement.waypoints.splice(waypointIndex, 1); } } else { waypointElement.el.classList.remove(waypoint.cl); } }); } else { _.forEach(waypointElement.waypoints, function (waypoint) { waypointElement.el.classList.remove(waypoint.cl); }); } // prune inactive waypoint elements if (waypointElement.waypoints.length === 0) { waypointElementList.splice(elementIndex, 1); } }); } // public: add elements to scroll tracking function add(els, options) { options = options || {}; els = toArray(els); _.forEach(els, function (el) { var waypointElement = _.assign(Object.create(waypointElementPrototype), { el: el, waypoints: [] }, options); waypointElementList.push(waypointElement); waypointElement.init(); }); return list(); } // public: returns an array of all elements currently tracked by waypoints function list() { return waypointElementList; } // public: track default elements and add scroll listener function init() { _.forEach(document.querySelectorAll('[data-waypoints]'), add); // do initial pass scrollListener(); // debounce function and listen window.addEventListener('scroll', _.throttle(scrollListener, 150)); } return { init: init, list: list, add: add }; }()); /* =social share links * =================== * * unobtrusive 'share' buttons that don't use too much bandwidth or create * privacy concerns * * default elements: * <div data-share-to="facebook twitter google linkedin reddit pinterest tumblr email"></div> */ var sharing = (function () { // glean some default parameters from the page var defaultOptions = { services: 'facebook twitter linkedin email', url: (function () { var link = document.querySelector('link[rel="canonical"]'), og = document.querySelector('meta[property="og:url"]'); if (link) { return link.getAttribute('href'); } else if (og) { return og.getAttribute('content'); } return window.location.href; })(), title: (function () { var og = document.querySelector('meta[property="og:title"]'); if (og) { return og.getAttribute('content'); } return document.title; })(), abstract: (function () { var og = document.querySelector('meta[property="og:description"]'), meta = document.querySelector('meta[name="description"]'); if (og) { return og.getAttribute('content'); } else if (meta) { return meta.getAttribute('content'); } return null; })(), thumbnail: (function () { var og = document.querySelector('meta[property="og:image"]'), apple = document.querySelector('link[rel="apple-touch-icon-precomposed"]'); if (og) { return og.getAttribute('content'); } else if (apple) { return apple.getAttribute('href'); } return null; })(), cite: (function () { var og = document.querySelector('meta[property="og:site_name"]'), link = document.querySelector('link[rel="start"][title]'); if (og) { return og.getAttribute('content'); } else if (link) { return link.getAttribute('title'); } return null; })() }; // generate services and their params using passed-in options data function generateServiceData(options) { options = options || {}; return { facebook: { name: 'Facebook', icon: 'fab fa-facebook-square', url: 'https://www.facebook.com/sharer/sharer.php', params: [ { name: 'u', value: options.url }, { name: 'title', value: options.title }, { name: 'quote', value: options.text }, { name: 'description', value: options.abstract }, { name: 'caption', value: options.cite }, { name: 'picture', value: options.thumbnail } ] }, twitter: { name: 'Twitter', icon: 'fab fa-twitter-square', url: 'https://twitter.com/intent/tweet', params: [ { name: 'url', value: options.url }, { name: 'text', value: options.text } ] }, google: { name: 'Google Plus', icon: 'fab fa-google-plus-square', url: 'https://plus.google.com/share', params: [ { name: 'url', value: options.url } ] }, linkedin: { name: 'LinkedIn', icon: 'fab fa-linkedin', url: 'https://www.linkedin.com/shareArticle', params: [ { name: 'url', value: options.url }, { name: 'mini', value: 'true' }, { name: 'title', value: options.title }, { name: 'summary', value: options.abstract }, { name: 'source', value: options.cite } ] }, reddit: { name: 'Reddit', icon: 'fab fa-reddit-square', url: 'https://www.reddit.com/submit', params: [ { name: 'url', value: options.url }, { name: 'title', value: options.title } ] }, pinterest: { name: 'Pinterest', icon: 'fab fa-pinterest-square', url: 'https://pinterest.com/pin/create/button/', params: [ { name: 'url', value: options.url }, { name: 'media', value: options.thumbnail }, { name: 'description', value: options.title } ] }, tumblr: { name: 'Tumblr', icon: 'fab fa-tumblr-square', url: 'https://www.tumblr.com/widgets/share/tool', params: [ { name: 'canonicalUrl', value: options.url }, { name: 'title', value: options.title }, { name: 'caption', value: options.abstract } ] }, email: { name: 'Email', icon: 'fas fa-envelope-square', url: 'mailto:', params: [ { name: 'subject', value: options.title }, { name: 'body', value: options.url + '\n' + (options.text || '') }, ] } }; } // populate our container with share buttons function generateMarkup(el, options) { var serviceData = generateServiceData(options), button = document.createElement('a'); button.setAttribute('target', '_blank'); button.className = 'share-buttons__button'; _.forEach(options.services.split(/\s+/), function (service) { if (!service) return false; var thisButton = button.cloneNode(true), thisData = serviceData[service]; if (!thisData) return false; thisButton.innerHTML = '<span class="' + thisData.icon + '"></span>'; thisButton.setAttribute('title', 'Share via ' + thisData.name); thisButton.href = thisData.url + '?' + thisData.params.map(function (param) { if (param.value) { return encodeURIComponent(param.name) + '=' + encodeURIComponent(param.value); } return null; }).filter(function (param) { return !!param; }).join('&'); el.appendChild(thisButton); }); } // add share buttons to a container function add(els, options) { els = toArray(els); options = options || {}; _.forEach(els, function (el) { // look for 'data-share-to' attribute on container if no services are passed var declaredServices = {}; if (!options.services && el.getAttribute('data-share-to')) { declaredServices.services = el.getAttribute('data-share-to'); } generateMarkup(el, _.assign(defaultOptions, options, declaredServices)); }); } // initialize with default elements function init() { add(document.querySelector('[data-share-to]')); } return { init: init, add: add }; })(); /* =truncators * =========== * * truncate containers to number of lines, fixed height, and so on * * usage: * <div data-truncate-to="5 lines" data-truncate-text="Show More"></div> * <div data-truncate-to="100px"></div> * <div data-truncate-to="2em"></div> * <div data-truncate-to="3 items"></div> * etc. */ var truncators = (function () { var buttonPrototype = document.createElement('button'), truncatorList = [], truncatorPrototype = { container: null, button: null, buttonText: "Show More", expandedButtonText: "Show Less", limit: null, limitUnit: null, isRepeatable: false, isTruncated: false, init: function () { var configString = this.container.getAttribute('data-truncate-to'); // parse units if ((!this.limit || !this.limitUnit) && configString) { this.limit = parseInt((configString.match(/^\d+/) || [''])[0], 10); this.limitUnit = (configString.match(/[a-z]+$/i) || [''])[0].trim(); } if (!this.limit || isNaN(this.limit) || !this.limitUnit) { console.error("Bad limit or unit config provided to following truncator:", this.container); return; } if (!this.button) { this.button = buttonPrototype.cloneNode(true); } this.truncate(); this.button.addEventListener('click', function (ev) { if (this.isTruncated) { this.expand(); } else { this.truncate(); } }.bind(this)); }, truncate: function () { var normalizedLimit, buttonSuffix = ''; // if we're limiting by items, we can hide items instead of limiting pixel height if (this.limitUnit === 'item' || this.limitUnit === 'items') { var items = this.container.children, hideCount = items.length - this.limit; // do no truncation if there aren't enough items if (hideCount <= 0) { return; } for (var i = this.limit; i < items.length; i++) { items[i].style.display = 'none'; } if (hideCount > 0) { buttonSuffix = ' (' + hideCount + (hideCount > 1 ? ' items' : ' item') + ')'; } // if we're not limiting by items, we'll need to calculate a max-height } else { this.container.style.overflow = 'hidden'; switch (this.limitUnit) { case '%': normalizedLimit = this.container.clientHeight * this.limit / 100; break; case 'em': // compute font size of element in px and multiply normalizedLimit = parseFloat(getComputedStyle(this.container).fontSize) * this.limit; break; case 'rem': // compute font size of body in px and multiply normalizedLimit = parseFloat(getComputedStyle(document.body).fontSize) * this.limit; break; case 'vh': // take a percentage of viewport height normalizedLimit = document.documentElement.clientHeight * this.limit / 100; break; case 'vw': // take a percentage of viewport width normalizedLimit = document.documentElement.clientWidth * this.limit / 100; break; case 'line': case 'lines': // calculate pixel height of a line and multiply (function (container, limit) { var testEl = document.createElement('div'), lineHeight; testEl.textContent = 'A'; container.insertBefore(testEl, container.firstElementChild); lineHeight = testEl.offsetHeight; container.removeChild(testEl); normalizedLimit = lineHeight * limit; })(this.container, this.limit); break; default: // px normalizedLimit = this.limit; break; } this.container.style.maxHeight = normalizedLimit + 'px'; } this.button.textContent = this.buttonText + buttonSuffix; this.container.parentNode.insertBefore(this.button, this.container.nextElementSibling); this.isTruncated = true; }, expand: function () { if (this.limitUnit === 'item' || this.limitUnit === 'items') { _.forEach(this.container.children, function (item) { item.style.display = ''; }); } else { this.container.style.overflow = ''; this.container.style.maxHeight = ''; } if (this.isRepeatable) { this.button.textContent = this.expandedButtonText; } else { this.button.parentNode.removeChild(this.button); } this.isTruncated = false; } }; buttonPrototype.setAttribute('type', 'button'); buttonPrototype.className = 'truncator-expand'; function add(els, options) { els = toArray(els); options = options || {}; _.forEach(els, function (el) { var truncator = _.assign(Object.create(truncatorPrototype), {container: el}, options); truncatorList.push(truncator); truncator.init(); }); } function init() { add(document.querySelectorAll('[data-truncate-to]')); } return { init: init, add: add }; })(); /* =horizontal scrollers * ===================== * * Add controls for horizontal scrollers * * <section class="horizontal [horizontal--loop]?"> * <div class="horizontal__scroller"> * <div class="horizontal__contents"> * <div class="horizontal__item"> ... </div> * ... * </div> * </div> * </setion> */ var horizontalScrollers = (function () { var scrollers = [], scrollerPrototype = { loop: false, el: null, scrollEl: null, contentWrapper: null, contentEls: null, leftButton: null, rightButton: null, atStartClass: 'horizontal--is-at-start', atEndClass: 'horizontal--is-at-end', margin: 20, /* * Initialize this scroller, create buttons, and bind listeners */ init: function init(container) { this.el = container; this.scrollEl = container.querySelector('.horizontal__scroller'); if (!this.scrollEl) { throw new Error('Expected scroller wrapper for horizontal scroller'); } this.contentWrapper = container.querySelector('.horizontal__content'); if (!this.contentWrapper) { throw new Error('Expected inner container for horizontal scroller'); } this.contentEls = toArray(this.contentWrapper.children); if (this.contentEls.length === 0) { throw new Error('Expected inner contents for horizontal scroller'); } this.leftButton = this.createButton('left'); this.leftButton.addEventListener('click', this.pageLeft.bind(this)); this.rightButton = this.createButton('right'); this.rightButton.addEventListener('click', this.pageRight.bind(this)); if (!this.loop) { const throttledDetectEdges = _.throttle(this.detectEdges.bind(this), 150); this.scrollEl.addEventListener('scroll', throttledDetectEdges); window.addEventListener('resize', throttledDetectEdges); this.detectEdges(); setTimeout(this.detectEdges.bind(this), 1000); window.addEventListener('load', this.detectEdges.bind(this)); } }, /* * Detects whether the scrollable area is at its very start or end * and applies css classes to match * * Throttle this function and use it as an event handler */ detectEdges: function detectEdges(ev) { if (this.loop) return; const pageSize = this.scrollEl.clientWidth; const contentSize = this.contentWrapper.scrollWidth; if (this.scrollEl.scrollLeft < this.margin) { this.el.classList.add(this.atStartClass); } else { this.el.classList.remove(this.atStartClass); } if (this.scrollEl.scrollLeft > contentSize - pageSize - this.margin) { this.el.classList.add(this.atEndClass); } else { this.el.classList.remove(this.atEndClass); } }, /* * Scroll this horizontal scroller to the very start */ scrollToStart: function scrollToStart() { this.scrollEl.scrollLeft = 0; }, /* * Scroll this horizontal scroller to the far end */ scrollToEnd: function scrollToEnd() { const pageSize = this.scrollEl.clientWidth; const contentSize = this.contentWrapper.scrollWidth; this.scrollEl.scrollLeft = contentSize - pageSize; }, /* * Scroll this area one page left, where a "page" is the width of * the visible area */ pageLeft: function pageLeft() { const pageSize = this.scrollEl.clientWidth; const currentOffset = this.scrollEl.scrollLeft; const targetOffset = Math.max(currentOffset - pageSize, 0); const nearestEl = this.getNearestContentEl(targetOffset); if (this.loop && currentOffset < this.margin) { this.scrollToEnd(); } else { this.scrollEl.scrollLeft = this.contentEls[nearestEl].offsetLeft; } }, /* * Scroll this area one page right, where a "page" is the width of * the visible area */ pageRight: function pageRight() { var pageSize = this.scrollEl.clientWidth; const contentSize = this.contentWrapper.scrollWidth; const currentOffset = this.scrollEl.scrollLeft; const maxOffset = contentSize - pageSize; const targetOffset = Math.min(currentOffset + pageSize, maxOffset); const nearestEl = this.getNearestContentEl(targetOffset); if (this.loop && currentOffset > maxOffset - this.margin) { this.scrollToStart(); } else if (targetOffset === maxOffset || this.contentEls.length <= nearestEl + 1) { this.scrollEl.scrollLeft = targetOffset; } else { this.scrollEl.scrollLeft = this.contentEls[nearestEl + 1].offsetLeft; } }, /* * Create a left or right control button and append it to this * scroller's container */ createButton: function createButton(dir) { const result = document.createElement('button'); result.setAttribute('type', 'button'); result.className = 'horizontal__control horizontal__control--' + dir; result.innerHTML = `<i class="fa-light fa-chevron-${dir}" title="Scroll ${dir}"></i>`; this.el.appendChild(result); return result; }, /* * Given a pixel offset from the left side of this scroller, returns * the element that lies directly underneath it. If that offset would * lie on a gap instead, returns the element to the left of the gap */ getNearestContentEl: function getNearestContentEl(scrollDistance) { for (let i = 0; i < this.contentEls.length; ++i) { if (this.contentEls[i].offsetLeft > scrollDistance) { return i > 0 ? i - 1 : 0; } } return 0; }, }; // public: return a list of scrolling sections tracked by this module function list() { return scrollers; } // public: add this module's functionality to a container element // see module comment for expected structure function add(container, options) { try { const scroller = Object.assign(Object.create(scrollerPrototype), (options || {})); scroller.init(container); scrollers.push(scroller); } catch (e) { console.error(e); } } // public: initialize this module function init() { _.forEach(document.querySelectorAll('.horizontal'), function (container) { add(container, { loop: container.classList.contains('horizontal--loop'), }); }); } return { add: add, list: list, init: init, }; }()); /* =misc * ===== * * miscellaneous enhancements that aren't large enough to justify a module */ var misc = (function () { var exports = Object.create(null); // mobile menu toggle exports.addMobileMenuToggle = function addMobileMenuToggle() { var inactiveClass = 'mobile-menu-was-open'; toggles.add(document.getElementsByClassName('page-header__toggle'), { targets: toArray(document.querySelectorAll('body, .page-header__content')), activeClass: 'mobile-menu-is-open', deactivateOnEsc: true, onActivate: function (toggle) { // add an inactive class only after the menu has been opened and then closed if (!toggle.origin.classList.contains(toggle.activeClass)) { _.forEach([toggle.origin].concat(toggle.targets), function (el) { el.classList.add(inactiveClass); }); } else { _.forEach([toggle.origin].concat(toggle.targets), function (el) { el.classList.remove(inactiveClass); }); } } }); }; // subnav toggles for mobile drilldown exports.addNavDrilldownButtons = function addNavDrilldownButtons() { var toggle = document.createElement('button'); toggle.className = 'header-nav__toggle'; toggle.setAttribute('type', 'button'); toggle.setAttribute('data-toggle-target', 'next'); toggle.innerHTML = 'Expand subnavigation for previous item'; _.forEach(document.querySelectorAll('.header-nav a + ul'), function (sublist) { sublist.parentNode.insertBefore(toggle.cloneNode(true), sublist); }); }; // allow visual focus and selection indicators of input labels exports.focusInputLabels = function focusInputLabels() { _.forEach(document.querySelectorAll('label[for]'), function (label) { var input = document.getElementById(label.getAttribute('for')); // track search container for disclosure search only var searchContainer = null; if (label.classList.contains('header-search__label')) { searchContainer = document.querySelector('.header-search'); } if (input) { input.addEventListener('focus', function (ev) { label.classList.add('is-focused'); if (searchContainer) { searchContainer.classList.add('is-focused'); } }); input.addEventListener('blur', function (ev) { label.classList.remove('is-focused'); if (searchContainer) { searchContainer.classList.remove('is-focused'); } }); if (input.type.toLowerCase() === 'radio' || input.type.toLowerCase() === 'checkbox') { input.addEventListener('change', function (ev) { if (input.checked) { label.classList.add('is-selected'); } else { label.classList.remove('is-selected'); } }); } // trigger 'change' event manually in order to populate highlight states on page load if ("createEvent" in document) { var ev = document.createEvent("HTMLEvents"); ev.initEvent("change", false, true); input.dispatchEvent(ev); } else { input.fireEvent("onchange"); } } }); }; // add utility classes to form inputs // this makes dynamic labels possible, for example exports.addInputUtilityClasses = function addInputUtilityClasses() { var inputs = toArray(document.getElementsByTagName('input')) .filter(isTextInput) .concat(toArray(document.getElementsByTagName('textarea'))); var currentContentClass = 'has-content'; var pastContentClass = 'did-have-content'; _.forEach(inputs, function addClassesToInput(input) { var hasContainedContent = false; // initial state if (input.value) { input.classList.add(currentContentClass); hasContainedContent = true; } // changes input.addEventListener('input', function (ev) { if (input.value) { hasContainedContent = true; input.classList.remove(pastContentClass); input.classList.add(currentContentClass); } else { input.classList.remove(currentContentClass); if (hasContainedContent) { input.classList.add(pastContentClass); } } }); }); }; var isTextInput = (function () { var textInputTypes = ['color', 'date', 'email', 'number', 'password', 'search', 'tel', 'text', 'time', 'url']; return function isTextInput(el) { return textInputTypes.includes(el.getAttribute('type')); }; })(); /* * Keyboard submenu accessibility */ exports.dropdownKeyboardNav = function dropdownKeyboardNav() { const activeClass = 'is-focused'; const mainNavLinks = Array.from(document.querySelectorAll('.header-nav > ul > li > a')); let currentDropdown; // open dropdowns on spacebar/downarrow mainNavLinks.forEach(function (link) { link.addEventListener('keydown', function (ev) { if (['ArrowDown', 'Space'].indexOf(ev.code) > -1) { ev.preventDefault(); const dropdown = this.parentNode.querySelector('ul'); if (!dropdown) return; dropdown.classList.add(activeClass); dropdown.querySelector('a').focus(); currentDropdown = dropdown; document.body.addEventListener('click', handleClickOutside); document.body.addEventListener('keyup', handleEsc); Array.from(dropdown.querySelectorAll('a')) .forEach(link => link.addEventListener('blur', handleFocusOutside)); } }); }); // handle clicking outside a focused dropdown function handleClickOutside(ev) { if (currentDropdown.contains(ev.target)) return; closeDropdown(false); } function handleEsc(ev) { if (ev.code === 'Escape') closeDropdown(true); } // handle tabbing away from a focused dropdown function handleFocusOutside(ev) { const links = Array.from(currentDropdown.querySelectorAll('a')); // since this is on the blur event of each dropdown link, we need to give // the browser time to actually focus the next element setTimeout(function () { if (links.indexOf(document.activeElement) > -1) return; closeDropdown(true); }, 0); } function closeDropdown(focus) { currentDropdown.classList.remove(activeClass); document.body.removeEventListener('click', handleClickOutside); document.body.removeEventListener('keyup', handleEsc); Array.from(currentDropdown.querySelectorAll('a')) .forEach(link => link.removeEventListener('blur', handleFocusOutside)); if (focus) currentDropdown.parentNode.firstElementChild.focus(); currentDropdown = null; } }; // automatically create slideshow tab indicators exports.createHomeSlideshowTabs = function createHomeSlideshowTabs() { var tab = document.createElement('button'); tab.className = 'home-feature__tab tabs__tab'; tab.setAttribute('type', 'button'); _.forEach(document.getElementsByClassName('home-feature'), function (feature) { var nav = feature.querySelector('.home-feature__nav'); if (!nav) { nav = document.createElement('div'); nav.className = 'home-feature__nav'; feature.appendChild(nav); } _.forEach(feature.querySelectorAll('.tabs__pane'), function (pane) { nav.appendChild(tab.cloneNode(true)); }); }); }; // initialize ukiyo for parallax effects exports.initializeParallax = function initializeParallax() { if (typeof Ukiyo === 'function') { _.forEach(document.querySelectorAll('.use-parallax'), function (el) { new Ukiyo(el, { scale: 1.25, speed: 1.5, willChange: true, wrapperClass: 'use-parallax__wrapper', }); }); } }; // combine adjacent tabs modules when placed in Sitefinity exports.combineTabs = function combineTabs() { // combine under the first parent var containers = toArray(document.querySelectorAll('.sf_cols.tabs')), currentContainer, currentType, children; if (containers.length > 0 && !document.body.classList.contains('sfPageEditor')) { for (var i = 0; i < containers.length; i++) { currentContainer = containers[i]; currentType = currentContainer.className; while (currentContainer.nextElementSibling && currentContainer.nextElementSibling.className === currentType) { children = toArray(currentContainer.nextElementSibling.querySelectorAll('.tabs__tab, .tabs__pane')); while (children.length) { currentContainer.appendChild(children.shift()); } currentContainer.parentNode.removeChild(currentContainer.nextElementSibling); } } } // reorder and count children _.forEach(document.querySelectorAll('.sf_cols.tabs'), function (container) { _.forEach(container.querySelectorAll('.tabs__tab'), function (tab) { container.appendChild(tab); }); _.forEach(container.querySelectorAll('.tabs__pane'), function (pane) { container.appendChild(pane); }); }); }; // add body waypoint for sticky header exports.addHeaderWaypoint = function addHeaderWaypoint() { document.body.setAttribute('data-waypoints', '1px: is-scrolled'); }; return exports; }()); /* =initialize modules * =================== */ var init = function () { // functions that must run before large modules // e.g. functions that output toggles that must then be initialized misc.combineTabs(); misc.addHeaderWaypoint(); misc.addNavDrilldownButtons(); misc.createHomeSlideshowTabs(); // large modules toggles.init(); tabs.init(); sharedHeights.init(); waypoints.init(); truncators.init(); horizontalScrollers.init(); sharing.init(); // misc modules misc.addMobileMenuToggle(); misc.focusInputLabels(); misc.dropdownKeyboardNav(); misc.addInputUtilityClasses(); misc.initializeParallax(); document.documentElement.classList.remove('no-js'); document.documentElement.classList.add('js'); }; /* =public * ======= */ return { xhr: xhr, toggles: toggles, tabs: tabs, sharedHeights: sharedHeights, waypoints: waypoints, sharing: sharing, horizontalScrollers: horizontalScrollers, init: init, }; }(window, document)); RDJS.init(); </script><script type="text/javascript" src="/Scripts/Annual2023-scripts/ukiyo.min.js"></script><script type="text/javascript">document.addEventListener('DOMContentLoaded', function () { var docExts = [".pdf", ".doc", ".xls", ".ppt", ".txt", "/docs/"]; docExts.forEach(function (index) { document.querySelectorAll('a[href*="' + index + '"]').forEach( function (e) { e.onclick = function () { // old ga('send', 'event', 'Document', 'Download', this.href); // new dataLayer.push({ 'event': 'gaEvent', 'eventCategory': 'Document', 'eventAction': 'Download', 'eventLabel': this.href }); };});});});</script> <script type="text/javascript"> //<![CDATA[ ;(function() { function loadHandler() { var hf = $get('ctl05_TSSM'); if (!hf._RSSM_init) { hf._RSSM_init = true; hf.value = ''; } hf.value += ';Telerik.Sitefinity.Resources, Version=13.3.7649.0, Culture=neutral, PublicKeyToken=b28c218413bdf563:en:04d52e12-2411-4be3-a9b1-e2f5f38b19e1:7a90d6a;Telerik.Web.UI, Version=2021.1.119.45, Culture=neutral, PublicKeyToken=121fae78165ba3d4:en:a0d12491-c9c2-4851-b575-66251a466dfe:580b2269:eb8d8a8e'; Sys.Application.remove_load(loadHandler); }; Sys.Application.add_load(loadHandler); })();Sys.Application.add_init(function() { $create(Telerik.Web.UI.RadSiteMap, null, null, null, $get("ctl00_ContentPlaceholder_T76CE7C69006_ctl00_ctl00_Breadcrumb")); }); //]]> </script> </form> </body> </html>

Pages: 1 2 3 4 5 6 7 8 9 10