CINXE.COM

ASPET | ASPET Committee and Board Meetings

<!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 | ASPET Committee and Board Meetings </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="ASPET Committee and Board Meetings" /><meta property="og:url" content="https://www.aspet.org/aspet/meetings-awards/meetingsannual-meeting/aspet-2025/program/aspet-committee-and-board-meetings" /><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/aspet-2025/program/aspet-committee-and-board-meetings" /><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=1b1d17f3-9998-6662-b1a8-ff0000ef3f42&amp;pageSiteNode=1A1D17F3-9998-6662-B1A8-FF0000EF3F42/284b0bd2-4837-459a-a1d4-e17303e917d8/SitefinitySiteMap" type="text/css" rel="stylesheet" /><style type="text/css" media="all">table { width: 100%; border-collapse:collapse; } tr:nth-of-type(odd){ background:#f7f8fd; } th { background:#e0f4f8; color:white: font-weight:bold; } td, th{ padding:6px; border:1px solid #ccc; text-align:left; } .page_banner{ max-width:100%; height:auto; margin-top:2%; padding-top:2%; } .accordion__label { padding: 3.125em 0 ; font-weight:400 !important; 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; } .highlight_b{ background: #fafdfe !important; color:#e73212 !important; padding:.09em 0.2em; border:1px solid #bababa; border-radius:3px; font-style:italic; } .highlight_a{ background: #915EA8 !important; color:#ffffff !important; padding:.09em 0.2em; border:1px solid #bababa; border-radius:3px; font-style:italic; font-weigh:400 !important; } .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; } .divider_1{ margin-top:2%; margin-bottom:5%; } .divider_2{ margin-top:2%; margin-bottom:2%; padding-top:2%; padding-bottom:2%; } h2{ font-weight:300; text-transform:uppercase; } .card{ border:0 !important; } @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; } .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; } } </style><link href="https://fonts.googleapis.com/css2?family=Jost:ital,wght@0,100..900;1,100..900&amp;display=swap" type="text/css" rel="stylesheet" media="all" /><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="./aspet-committee-and-board-meetings" 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="irvATJf40cAn7WGy4yMd6Gsgle26i5R8yHrJDg9FlBOf9R2WpjkGKG/bi7PBmgTwyaCuNN+OaTIbxkVETyokG2/yQM9BGONgJGsWiYC9G9tOztVIaQPh+X7CTcWm/7RzRmCbM3TxsUlbqAmZ5hTtuhip7YGZiQdphW71Hujp5DwIbe0XWSCXHHp8ZO5OOp/dCisJRrpvOSiONkV57WRj1kiHSFewYHimfIJZ4NZIMQA=" /> </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="2FBAF8E5" /> </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=m3XJUf927z5mV_kJ4fUdzSEcn6vb7C8ci0ROrgUhaed4VxLorWFY3XBnvc20R_2dR8NnDYVpTrTwKlZzBiTdMhKel4e_mEHeKP3qkdhQyDpT-fV357mH8Mr937u9S2iE0" style="display:none;"> </iframe> <header class="page-header" role="banner"> <h1 class="header-logo"> <link href="/Stylesheets/ASPETAnnual2025/ce2416f3-9998-6662-b1a8-ff0000ef3f42?version=30" 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="/aspet/meetings-awards/meetingsannual-meeting/aspet-2025" class="fade-in"><img src="https://www.aspet.org/images/default-source/meeting-and-event-images/aspet2025/284514_aspet_25_logo_final.jpg" alt="Full Color__ASPET2025_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/aspet-2025/abstracts">Abstracts</a> </li> <li class="is-current"> <a href="/aspet/meetings-awards/meetingsannual-meeting/aspet-2025/program">Program</a> <ul id="NavigationPlaceholder_T5EE3C0DE045_ctl00_ctl00_ctl00_ctl01_childNodesContainer"> <li> <a href="/aspet/meetings-awards/meetingsannual-meeting/aspet-2025/program/opportunities-for-students-postdocs">Opportunities for Students/Postdocs</a> </li> <li> <a href="/aspet/meetings-awards/meetingsannual-meeting/aspet-2025/program/aspet-town-halls">ASPET Town Halls</a> </li> <li> <a href="/aspet/meetings-awards/meetingsannual-meeting/aspet-2025/program/keynote-speakers">Keynote Speakers</a> </li> <li class="is-current"> <a href="/aspet/meetings-awards/meetingsannual-meeting/aspet-2025/program/aspet-committee-and-board-meetings">ASPET Committee and Board Meetings</a> </li> <li> <a href="/aspet/meetings-awards/meetingsannual-meeting/aspet-2025/program/explore-portland">Explore Portland</a> </li> <li> <a href="/aspet/meetings-awards/meetingsannual-meeting/aspet-2025/program/program-details" target="_blank">Program Details</a> </li> </ul> </li> <li> <a href="/aspet/meetings-awards/meetingsannual-meeting/aspet-2025/registration">Registration</a> </li> <li> <a href="/aspet/meetings-awards/meetingsannual-meeting/aspet-2025/hotel-travel">Hotel & Travel</a> </li> <li> <a href="/aspet/meetings-awards/meetingsannual-meeting/aspet-2025/policies">Policies</a> </li> <li> <a href="/aspet/meetings-awards/meetingsannual-meeting/aspet-2025/partnerships">Partnerships</a> <ul id="NavigationPlaceholder_T5EE3C0DE045_ctl00_ctl00_ctl00_ctl05_childNodesContainer"> <li> <a href="/aspet/meetings-awards/meetingsannual-meeting/aspet-2025/partnerships/partners">Partners</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="https://www.aspet.org/images/default-source/meeting-and-event-images/aspet2025/page-banners/committee-and-board-meetings.jpg?Status=Temp&amp;sfvrsn=fe8970d3_10" alt="ASPET Committee and Board Meetings" /></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>ASPET Committee and Board Meetings</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>ASPET Committee and Board Meetings </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/aspet-2025/program/opportunities-for-students-postdocs">Opportunities for Students/Postdocs</a> </li> <li> <a href="/aspet/meetings-awards/meetingsannual-meeting/aspet-2025/program/aspet-town-halls">ASPET Town Halls</a> </li> <li> <a href="/aspet/meetings-awards/meetingsannual-meeting/aspet-2025/program/keynote-speakers">Keynote Speakers</a> </li> <li class="is-current"> <a href="/aspet/meetings-awards/meetingsannual-meeting/aspet-2025/program/aspet-committee-and-board-meetings">ASPET Committee and Board Meetings</a> </li> <li> <a href="/aspet/meetings-awards/meetingsannual-meeting/aspet-2025/program/explore-portland">Explore Portland</a> </li> <li> <a href="/aspet/meetings-awards/meetingsannual-meeting/aspet-2025/program/program-details" target="_blank">Program Details</a> </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 class="divider_2"><p>The below events take place at the <strong><em>Hilton Downtown Portland and the Duniway Hotel </em></strong> in Portland, Ore., during the ASPET 2025 Annual Meeting unless otherwise specified. <strong><em>The events listed here are invitation-only. </em></strong></p></div></div> </div> <div > <div class="sfContentBlock sf-Long-text" ><!--<div class="divider_1"></div> <div class="accordion"> <div class="accordion__label" data-toggle-target="next">Wednesday, May 17, 2023 <em class="fa-regular fa-plus"></em><em class="fa-regular fa-minus"></em></div> <div class="accordion__content"> <p><strong>11:00 am &ndash; 2:00 pm</strong> | Mentoring Network: Prep for Facilitators and Coaches </p> <p><strong>2:00 pm &ndash; 5:30 pm</strong> | Mentoring Network: Coaching for Career Development (Day 1 of 2) </p> <p><strong>5:30 pm &ndash; 7:00 pm</strong> | Mentoring Network Reception </p> </div> <div class="accordion__label" data-toggle-target="next">Thursday, May 18, 2023 <em class="fa-regular fa-plus"></em><em class="fa-regular fa-minus"></em></div> <div class="accordion__content"> <p><strong>8:00 am &ndash; 11:00 am</strong> | Mentoring Network: Coaching for Career Development (Day 2 of 2) </p> <p><strong>10:00 am &ndash; 12:00 pm</strong> | Publications Committee Meeting </p> <p><strong>11:00 am &ndash; 12:00 pm</strong> | Division Communication Officers Meeting </p> <p><strong>12:30 pm &ndash; 1:30 pm</strong> </p> <ul> <li>Drug Metabolism and Disposition Editorial Board Meeting </li> <li>Executive Committee Meeting - Division for Pharmacology Education </li> <li>Executive Committee Meeting - Division for Drug Discovery and Development </li> <li>Executive Committee Meeting - Division for Molecular Pharmacology </li> </ul> </div> <div class="accordion__label" data-toggle-target="next">Friday, May 19, 2023 <em><span style="font-weight:300;"></span></em> <em class="fa-regular fa-plus"></em><em class="fa-regular fa-minus"></em></div> <div class="accordion__content"> <p><strong>7:00 am &ndash; 8:00 am</strong> | Pharmacological Reviews Editorial Board Meeting </p> <p><strong>12:00 pm &ndash; 1:00 pm</strong> </p> <ul> <li>JPET Editorial Board Meeting </li> <li>Executive Committee Meeting - Division for Cardiovascular Pharmacology </li> <li>Executive Committee Meeting - Division for Translational and Clinical Pharmacology </li> </ul> </div> <div class="accordion__label" data-toggle-target="next">Saturday, May 20, 2023<em class="fa-regular fa-plus"></em><em class="fa-regular fa-minus"></em></div> <div class="accordion__content"> <p><strong>7:00 am &ndash; 8:00 am</strong> | Pharmacological Reviews Editorial Board Meeting </p> <p><strong>12:00 pm &ndash; 1:00 pm</strong> </p> <ul> <li>JPET Editorial Board Meeting </li> <li>Executive Committee Meeting - Division for Cardiovascular Pharmacology </li> <li>Executive Committee Meeting - Division for Translational and Clinical Pharmacology </li> </ul> </div> <div class="accordion__label" data-toggle-target="next" id="guppytank2023">Sunday, May 21, 2023 <em class="fa-regular fa-plus"></em><em class="fa-regular fa-minus"></em></div> <div class="accordion__content"> <p><strong>2:30 pm &ndash; 3:30 pm</strong> </p> <ul> <li>Partnerships Committee Meeting </li> <li>Molecular Pharmacology Editorial Board Meeting </li> <li>Executive Committee Meeting - Division for Cancer Pharmacology </li> <li>Executive Committee Meeting - Division for Toxicology </li> </ul> <p><strong>3:30 pm &ndash; 5:30 pm</strong> | Program Committee Meeting </p> </div> <div class="accordion__label" data-toggle-target="next">Monday, May 22, 2023 <em class="fa-regular fa-plus"></em><em class="fa-regular fa-minus"></em></div> <div class="accordion__content"> <p><strong>8:30 am &ndash; 2:00 pm</strong> | Council Meeting </p> </div> </div>--></div> </div> <div > <div class="sfContentBlock sf-Long-text" ><div class="divider_2"><h6>Tentative Schedule as of 11/1/2024 (Subject to Change) </h6></div></div> </div><div id="ContentPlaceholder_C014_Col00" class="sf_colsIn container" data-sf-element="Container"> <div > <div class="sfContentBlock sf-Long-text" ><div class="divider_2"><div class="card"><div class="card__body"><h3>Wednesday, April 2, 2025 </h3><table><tbody><tr><td><p><strong>11:00 am &ndash; 2:00 pm</strong> </p></td><td><p>Mentoring Network: Prep for Facilitators and Coaches </p></td></tr><tr><td><strong>12:00 pm &ndash; 6:00 pm</strong></td><td>Council Meeting (followed by an off-site dinner)</td></tr><tr><td><p><strong>2:00 pm &ndash; 5:30 pm</strong> </p></td><td><p>Mentoring Network: Coaching for Career Development (Day 1 of 2)</p></td></tr><tr><td><p><strong>5:30 pm &ndash; 7:00 pm</strong> </p></td><td><p>Mentoring Network Reception (Current class)</p></td></tr></tbody></table><p>&nbsp;</p></div></div></div></div> </div> <div > <div class="sfContentBlock sf-Long-text" ><div class="divider_2"><div class="card"><div class="card__body"><h3>Thursday, April 3, 2025</h3><table><tbody><tr><td style="width:147.967px;"><p><strong>9:00 am &ndash; 11:00 am</strong><strong> </strong></p></td><td style="width:388.033px;"><p>Mentoring Network: Coaching for Career Development (Day 2 of 2)</p></td></tr><tr><td style="width:147.967px;"><p><strong>9:30 am &ndash; 11:30 am </strong></p></td><td style="width:388.033px;"><p>Publications Committee Meeting </p></td></tr><tr><td style="width:147.967px;">&nbsp;</td><td style="width:388.033px;">&nbsp;</td></tr><tr><td style="width:147.967px;"><p><strong>12:00 pm &ndash; 1:00 pm </strong></p></td><td style="width:388.033px;"><p><em>JPET </em>Editorial Board Meeting</p></td></tr><tr><td style="width:147.967px;">&nbsp;</td><td style="width:388.033px;">&nbsp;</td></tr><tr><td style="width:147.967px;"><p><strong>1:00 pm &ndash; 2:00 pm </strong></p></td><td style="width:388.033px;"><p><em>Pharmacological Reviews</em> Editorial Board Meeting</p></td></tr><tr><td style="width:147.967px;"><strong>1:00 pm &ndash; 2:00 pm </strong><br /></td><td style="width:388.033px;">Executive Committee Meeting - Division for Cardiovascular Pharmacology<br /></td></tr><tr><td style="width:147.967px;"><p><strong>1:00 pm &ndash; 2:00 pm </strong></p></td><td style="width:388.033px;"><p>Executive Committee Meeting - Division for Translational and Clinical Pharmacology</p></td></tr><tr><td style="width:147.967px;"><strong>1:00 pm &ndash; 2:00 pm</strong></td><td style="width:388.033px;">Executive Committee Meeting - Division for Drug Discovery and Development<br /></td></tr><tr><td style="width:147.967px;"><strong>1:00 pm &ndash; 2:00 pm</strong></td><td style="width:388.033px;">Executive Committee Meeting - Division for Cancer Pharmacology<br /></td></tr><tr><td style="width:147.967px;"><strong>1:00 pm &ndash; 2:00 pm </strong></td><td style="width:388.033px;">New Member Meet-and-Greet (invitation only)</td></tr><tr><td style="width:147.967px;">&nbsp;</td><td style="width:388.033px;">&nbsp;</td></tr><tr><td style="width:147.967px;"><strong>6:30 pm &ndash; 7:30 pm</strong></td><td style="width:388.033px;">Strengthening Divisions Task Force</td></tr></tbody></table><p>&nbsp;</p></div></div></div><!-- <ul> <li>Publications Committee Meeting (Midway Suite II)</li> <li>Nominating Committee Meeting (Midway Suite IV)</li> </ul> <p><strong>11:00 am &ndash; 12:00 pm</strong>&nbsp;</p> <ul> <li>Division Communication Officers Meeting (Midway Suite I)</li> </ul> <p><strong>12:30 pm &ndash; 1:30 pm</strong> </p> <ul> <li><em>Drug Metabolism and Disposition</em> Editorial Board Meeting (Midway Suite III)</li> <li>Executive Committee Meeting - Division for Pharmacology Education (Midway Suite II)</li> <li>Executive Committee Meeting - Division for Drug Discovery and Development (Midway Suite I)</li> <li>Executive Committee Meeting - Division for Molecular Pharmacology (Midway Suite IV)</li> </ul>--></div> </div> <div > <div class="sfContentBlock sf-Long-text" ><div class="divider_2"><div class="card"><div class="card__body"><h3>Friday, April 4, 2025 </h3><table><tbody><tr><td><p><strong>7:00 am &ndash; 8:00 am </strong></p></td><td><p>Inclusion, Diversity, Equity, and Accessibility (IDEA) Committee</p></td></tr><tr><td><p><strong>7:00 am &ndash; 8:00 am </strong> </p></td><td><p>Science Policy Committee Meeting</p></td></tr><tr><td><strong>7:00 am &ndash; 8:00 am </strong></td><td>Executive Committee Meeting - Division for Neuropharmacology</td></tr><tr><td><p><strong>7:00 am &ndash; 8:00 am </strong> </p></td><td><p><em>Drug Metabolism and Disposition</em> Editorial Board Meeting</p></td></tr><tr><td><p><strong></strong> </p></td><td><p>&nbsp;</p></td></tr><tr><td><strong>12:15 pm &ndash; 1:15 pm</strong><strong> </strong></td><td>Executive Committee Meeting - Division for Behavioral Pharmacology</td></tr><tr><td><strong>12:15 pm &ndash; 1:15 pm</strong><strong> </strong></td><td>Executive Committee Meeting - Division for Molecular Pharmacology</td></tr><tr><td><strong>12:15 pm &ndash; 1:15 pm</strong><strong> </strong></td><td>Executive Committee Meeting - Division for Toxicology<br /></td></tr><tr><td><strong>12:15 pm &ndash; 1:15 pm</strong></td><td>Executive Committee Meeting - Division for Pharmacology Education<br /></td></tr><tr><td><strong>12:15 pm &ndash; 1:15 pm</strong></td><td>ASPET Journals Editorial Board Member Lunch (invitation only)<br /></td></tr><tr><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td><strong>7:30 pm </strong><strong>&ndash;&nbsp;</strong><strong>9:30 pm</strong><br /></td><td>Volunteer Appreciation Reception (invitation only)<br /></td></tr></tbody></table><p><em>&nbsp;</em></p><p>&nbsp;</p><!-- <ul> <li><em>Pharmacological Reviews </em>Editorial Board Meeting (Midway Suite IV)</li> <li>Mentoring and Career Development Committee (Midway Suite II)<br /></li> </ul> <p><strong>12:00 pm &ndash; 1:00 pm</strong> </p> <ul> <li><em>JPET </em>Editorial Board Meeting (Midway Suite IV)</li> <li>Executive Committee Meeting - Division for Cardiovascular Pharmacology (Conductor Room)</li> <li>Executive Committee Meeting - Division for Translational and Clinical Pharmacology (Midway Suite II)</li> </ul>--> </div></div></div></div> </div> <div > <div class="sfContentBlock sf-Long-text" ><div class="divider_2"><div class="card"><div class="card__body"><h3>Saturday, April 5, 2025</h3><table><tbody><tr><td><p><strong>7:00 am &ndash; 8:00 am</strong><strong> </strong></p></td><td><p><em>Molecular Pharmacology</em> Editorial Board Meeting</p></td></tr><tr><td><p><strong>7:00 am &ndash; 8:00 am</strong></p></td><td><p>Young Scientists Committee Meeting</p></td></tr><tr><td><strong>7:00 am &ndash; 8:00 am</strong></td><td>Executive Committee Meeting - Division for Drug Metabolism and Disposition</td></tr><tr><td><br /></td><td><p>&nbsp;</p></td></tr><tr><td><strong>12:15 pm &ndash; 1:15 pm</strong></td><td><em></em><em>ASPET Discovery</em> Editorial Board Meeting</td></tr><tr><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td><strong>7:00 pm </strong><strong>&ndash;&nbsp;</strong><strong>9:00 pm</strong> (time tbd)<br /></td><td>Past Presidents Dinner<br /></td></tr></tbody></table><p>&nbsp;</p><!-- <ul> <li>Science Policy Committee Meeting (Midway Suite IV)</li> <li>Partnerships Committee Meeting (Midway Suite II)</li> </ul> <p><strong>12:30 pm &ndash; 1:30 pm</strong> </p> <ul> <li>Young Scientists Committee Meeting (Midway Suite IV)</li> <li>Executive Committee Meeting - Division for Behavioral Pharmacology (Conductor Room)</li> <li>Executive Committee Meeting - Division for Neuropharmacology (Midway Suite II)</li> <li>Executive Committee Meeting - Division for Drug Metabolism and Disposition (Midway Suite III)</li> </ul> <p><strong>7:00 pm &ndash; 8:00 pm</strong>&nbsp;</p> <ul> <li>Academy of Pharmacology Educators Reception (Midway Suite I)</li> </ul>--> </div></div></div></div> </div> <div > <div class="sfContentBlock sf-Long-text" ><em></em><div class="divider_2"><div class="card"><div class="card__body"><h3>Sunday, April 6, 2025 </h3><table><tbody><tr><td><p><strong>7:00 am &ndash; 8:00 am</strong></p></td><td><p>Council of Division Chairs </p></td></tr><tr><td><strong>7:00 am &ndash; 8:00 am</strong></td><td>Division Communications Officers</td></tr><tr><td><strong>7:00 am &ndash; 8:00 am</strong></td><td>Mentoring and Career Development Committee</td></tr><tr><td><strong>7:00 am &ndash; 8:00 am</strong></td><td>Partnerships Committee Meeting</td></tr><tr><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td><strong>2:30 pm </strong><strong>&ndash;&nbsp;</strong><strong>4:30 pm</strong></td><td>Program Committee</td></tr></tbody></table><p>&nbsp;</p><!-- <ul> <li><em>Molecular Pharmacology</em> Editorial Board Meeting (Midway Suite IV)</li> <li>Executive Committee Meeting - Division for Cancer Pharmacology (Midway Suite II)</li> <li>Executive Committee Meeting - Division for Toxicology (Midway Suite III) - <em>Cancelled</em><br /></li> </ul> <p><strong>3:30 pm &ndash; 5:30 pm</strong></p> <ul> <li><strong></strong>Program Committee Meeting (Midway Suite I)</li> </ul>--> </div></div></div></div> </div> <div > <div class="sfContentBlock sf-Long-text" ><div class="divider_2"><div class="card"><div class="card__body"><h3>Monday, April 7, 2025 </h3><p><strong><em></em></strong><em>No committee/board meetings planned at this time.</em></p></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" ></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>Aug</p> </div> <div class="date_box"> <p>29</p> </div> </div> <div style="flex-basis:80%;"> <p>Session Proposals Due</p> </div> </div> </div> <div style="margin-bottom:1em;"> <div class="date_container"> <div class="date_cover"> <div class="month_box"> <p>Sep</p> </div> <div class="date_box"> <p>3</p> </div> </div> <div style="flex-basis:80%;"> <p>Award Nominations Due </p> </div> </div> </div>--> <!-- <div style="margin-bottom:1em;"> <div class="date_container"> <div class="date_cover"> <div class="month_box"> <p>Nov</p> </div> <div class="date_box"> <p>7</p> </div> </div> <div style="flex-basis:80%;"> <p>Abstracts Due </p> </div> </div> </div> <div style="margin-bottom:1em;"> <div class="date_container"> <div class="date_cover"> <div class="month_box"> <p>Nov</p> </div> <div class="date_box"> <p>7</p> </div> </div> <div style="flex-basis:80%;"> <p>Travel Award Applications Due</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>Feb</p> </div> <div class="date_box"> <p>13</p> </div> </div> <div style="flex-basis:80%;"> <p>2<sup>nd</sup> Round Abstracts Due</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>13</p></div></div><div style="flex-basis:80%;"><p>Deepest 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>10-21</p></div></div><div style="flex-basis:80%;"><p>Online Town Halls </p></div></div></div><!--<div style="margin-bottom:1em;"> <div class="date_container"> <div class="date_cover"> <div class="month_box"> <p>Mar</p> </div> <div class="date_box"> <p>&nbsp;</p> </div> </div> <div style="flex-basis:80%;"> <p>Online Award Lecture Series </p> </div> </div> </div>--> <div style="margin-bottom:1em;"><div class="date_container"><div class="date_cover"><div class="month_box"><p>Mar</p></div><div class="date_box"><p>11</p></div></div><div style="flex-basis:80%;"><p>Regular 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>Apr</p></div><div class="date_box"><p>3-6</p></div></div><div style="flex-basis:80%;"><p>ASPET 2025 Annual Meeting | 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 | 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/aspet2025/284514_aspet_25_logo_final.jpg" 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://twitter.com/aspet" class="footer-social__icon"><em class="fa-brands fa-x-twitter"></em></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="/aspet/meetings-awards/meetingsannual-meeting/aspet-2025/annual-2025-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; 2025 American Society for Pharmacology and Experimental Therapeutics</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"> <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