CINXE.COM
O'Reilly Newsletters - O'Reilly Media
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>O'Reilly Newsletters - O'Reilly Media</title> <meta name="description" content="Get news and insights, exclusive content, offers, and more." /> <meta name="date" content="2024-11-24" /> <meta name="search_date" content="2022-07-13" /> <meta name="search-title" content="O'Reilly Newsletters - O'Reilly Media" /> <meta name="pagename" content="O'Reilly Newsletters - O'Reilly Media" /> <meta name="site" content="O'Reilly" /> <meta name="twitter:title" content="O'Reilly Newsletters - O'Reilly Media" /> <meta name="twitter:description" content="Get news and insights, exclusive content, offers, and more." /> <meta name="twitter:site" content="@OReillyMedia" /> <meta property="og:type" content="website" /> <meta property="og:title" content="O'Reilly Newsletters - O'Reilly Media" /> <meta name="twitter:card" content="summary" /> <meta name="twitter:image" content="https://cdn.oreillystatic.com/oreilly/images/oreilly-social-200.png" /> <meta property="og:image" content="https://cdn.oreillystatic.com/oreilly/images/oreilly-social-200.png" /> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="language_name" content="English"> <meta name="native_language_name" content="English"> <meta name="format-detection" content="telephone=no"> <link rel="icon" type="image/png" href="//www.oreilly.com/favicon.ico"> <!--[if lte IE 9]> <script> 'article aside footer header main nav section time'.replace(/\w+/g,function(n){document.createElement(n)}) </script> <![endif]--> <link rel="stylesheet" type="text/css" href="https://cdn.oreillystatic.com/assets/css/2018_font_face.css" /> <link rel="stylesheet" type="text/css" href="https://cdn.oreillystatic.com/assets/css/odot-layout-20240226.css" /> <!--[if IE 9]> <style type="text/css"> #menu-toggle:checked ~ .mobile-nav { display:block; } .mobile-nav { display: none; } </style> <![endif]--> <!-- Initiate dataLayer for GA --> <script> loggedInObject = new Object(); var dataLayer = window.dataLayer || []; //Check for O'Reilly Unified logged-in status if (document.cookie.split(';').filter(function(item) { return item.indexOf('orm-jwt=') >= 0 }).length) { loggedInObject.unifiedLoggedIn = 'yes'; loggedInObject.loggedIn = 'yes'; dataLayer.push(loggedInObject); //Add 'loggedIn class to html tag const htmlTag = document.querySelector('html'); if (htmlTag !== null) { htmlTag.classList.add('loggedIn'); } } </script> <!-- Google Tag Manager --> <script>(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-5P4V6Z');</script> <!-- End Google Tag Manager --> <!-- Start VWO Async SmartCode --> <link rel="preconnect" href="https://dev.visualwebsiteoptimizer.com" /> <script type='text/javascript' id='vwoCode'> window._vwo_code || (function() { var account_id=27087, version=2.1, settings_tolerance=2000, hide_element='body', hide_element_style = 'opacity:0 !important;filter:alpha(opacity=0) !important;background:none !important', /* DO NOT EDIT BELOW THIS LINE */ f=false,w=window,d=document,v=d.querySelector('#vwoCode'),cK='_vwo_'+account_id+'_settings',cc={};try{var c=JSON.parse(localStorage.getItem('_vwo_'+account_id+'_config'));cc=c&&typeof c==='object'?c:{}}catch(e){}var stT=cc.stT==='session'?w.sessionStorage:w.localStorage;code={use_existing_jquery:function(){return typeof use_existing_jquery!=='undefined'?use_existing_jquery:undefined},library_tolerance:function(){return typeof library_tolerance!=='undefined'?library_tolerance:undefined},settings_tolerance:function(){return cc.sT||settings_tolerance},hide_element_style:function(){return'{'+(cc.hES||hide_element_style)+'}'},hide_element:function(){if(performance.getEntriesByName('first-contentful-paint')[0]){return''}return typeof cc.hE==='string'?cc.hE:hide_element},getVersion:function(){return version},finish:function(e){if(!f){f=true;var t=d.getElementById('_vis_opt_path_hides');if(t)t.parentNode.removeChild(t);if(e)(new Image).src='https://dev.visualwebsiteoptimizer.com/ee.gif?a='+account_id+e}},finished:function(){return f},addScript:function(e){var t=d.createElement('script');t.type='text/javascript';if(e.src){t.src=e.src}else{t.text=e.text}d.getElementsByTagName('head')[0].appendChild(t)},load:function(e,t){var i=this.getSettings(),n=d.createElement('script'),r=this;t=t||{};if(i){n.textContent=i;d.getElementsByTagName('head')[0].appendChild(n);if(!w.VWO||VWO.caE){stT.removeItem(cK);r.load(e)}}else{var o=new XMLHttpRequest;o.open('GET',e,true);o.withCredentials=!t.dSC;o.responseType=t.responseType||'text';o.onload=function(){if(t.onloadCb){return t.onloadCb(o,e)}if(o.status===200){_vwo_code.addScript({text:o.responseText})}else{_vwo_code.finish('&e=loading_failure:'+e)}};o.onerror=function(){if(t.onerrorCb){return t.onerrorCb(e)}_vwo_code.finish('&e=loading_failure:'+e)};o.send()}},getSettings:function(){try{var e=stT.getItem(cK);if(!e){return}e=JSON.parse(e);if(Date.now()>e.e){stT.removeItem(cK);return}return e.s}catch(e){return}},init:function(){if(d.URL.indexOf('__vwo_disable__')>-1)return;var e=this.settings_tolerance();w._vwo_settings_timer=setTimeout(function(){_vwo_code.finish();stT.removeItem(cK)},e);var t;if(this.hide_element()!=='body'){t=d.createElement('style');var i=this.hide_element(),n=i?i+this.hide_element_style():'',r=d.getElementsByTagName('head')[0];t.setAttribute('id','_vis_opt_path_hides');v&&t.setAttribute('nonce',v.nonce);t.setAttribute('type','text/css');if(t.styleSheet)t.styleSheet.cssText=n;else t.appendChild(d.createTextNode(n));r.appendChild(t)}else{t=d.getElementsByTagName('head')[0];var n=d.createElement('div');n.style.cssText='z-index: 2147483647 !important;position: fixed !important;left: 0 !important;top: 0 !important;width: 100% !important;height: 100% !important;background: white !important;';n.setAttribute('id','_vis_opt_path_hides');n.classList.add('_vis_hide_layer');t.parentNode.insertBefore(n,t.nextSibling)}var o='https://dev.visualwebsiteoptimizer.com/j.php?a='+account_id+'&u='+encodeURIComponent(d.URL)+'&vn='+version;if(w.location.search.indexOf('_vwo_xhr')!==-1){this.addScript({src:o})}else{this.load(o+'&x=true')}}};w._vwo_code=code;code.init();})(); </script> <!-- End VWO Async SmartCode --> </head> <body> <!-- Google Tag Manager (noscript) --> <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-5P4V6Z" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript> <!-- End Google Tag Manager (noscript) --> <div class="skipToMain" id="skipToMain"><a href="#maincontent"><span class="skipToMain-text">Skip to main content</span></a></div> <header role="banner"> <div class="content"> <nav role="navigation" aria-label="site sections"> <a href="https://www.oreilly.com" class="logo" title="home page"><img src="https://cdn.oreillystatic.com/images/sitewide-headers/oreilly_logo_mark_red.svg" onerror="this.src='https://cdn.oreillystatic.com/images/sitewide-headers/oreilly_logo_mark_red_@2x.png'; this.onerror=null;" alt="O'Reilly home"></a> <button id="mobileNavButton" class="mobileNavButton mobileNavButton--collapse mobileNavButton--3dx" type="button" aria-expanded="false" aria-controls="menuList"> <span class="mobileNavButton-box"> <span class="mobileNavButton-inner"></span> </span> </button> <ul id="menuList" class="menuList mobileHidden "> <li class="menuList-itemsP1"> <ul> <li class="menuList-item menuList-signIn"><a id="nav-signIn" href="https://www.oreilly.com/member/login/">Sign In</a></li> <li class="menuList-item menuList-tryNow"><a id="nav-tryNow" class="menuList-cta" href="https://www.oreilly.com/online-learning/try-now.html">Try Now</a></li> <li class="menuList-item menuList-platform"><a id="nav-platform" class="menuList-cta" href="https://www.oreilly.com/member/login/">O’Reilly Platform</a></li> </ul> </li> <li class="menuList-itemsP2"> <ul> <li class="menuList-item menuList-itemWithSub"><a href="https://www.oreilly.com/online-learning/teams.html">Teams</a> <ul class="menuList-subList"> <li class="menuList-subItem menuList-extra"><a href="https://www.oreilly.com/online-learning/teams.html">For business</a></li> <li class="menuList-subItem"><a href="https://www.oreilly.com/online-learning/government.html">For government</a></li> <li class="menuList-subItem"><a href="https://www.oreilly.com/online-learning/academic.html">For higher ed</a></li> </ul> </li> <li class="menuList-item"><a href="https://www.oreilly.com/online-learning/individuals.html">Individuals</a></li> <li class="menuList-item menuList-itemWithSub"><a href="https://www.oreilly.com/online-learning/features.html">Features</a> <ul class="menuList-subList"> <li class="menuList-subItem menuList-extra"><a href="https://www.oreilly.com/online-learning/features.html">All features</a></li> <li class="menuList-subItem"><a href="https://www.oreilly.com/online-learning/courses.html">Courses</a></li> <li class="menuList-subItem"><a href="https://www.oreilly.com/online-learning/feature-certification.html">Certifications</a></li> <li class="menuList-subItem"><a href="https://www.oreilly.com/online-learning/intro-interactive-learning.html">Interactive learning</a></li> <li class="menuList-subItem"><a href="https://www.oreilly.com/online-learning/live-events.html">Live events</a></li> <li class="menuList-subItem"><a href="https://www.oreilly.com/online-learning/feature-answers.html">Answers</a></li> <li class="menuList-subItem"><a href="https://www.oreilly.com/online-learning/insights-dashboard.html">Insights reporting</a></li> </ul> </li> <li class="menuList-item"><a href="https://www.oreilly.com/radar/">Blog</a></li> <li class="menuList-item" id="nav-forMarketers"><a href="https://www.oreilly.com/content-marketing-solutions.html">Content sponsorship</a></li> <li class="menuList-item menuList-item-search" id="nav-search"> <form id="js-searchForm" class="searchForm" action="https://www.oreilly.com/search/"><input id="search" type="search" name="query" placeholder="Explore our content" autocomplete="off" required=""><button id="js-searchCloseButton" class="navSearchCloseButton">Close</button></form> <button id="js-searchButton" class="navSearchButton">Search</button> </li> </ul> </li> </ul> </nav> </div> </header> <main role="main" id="maincontent"> <style> .hero.hero-general .content { min-height: 120px; display: flex; flex-direction: column; } .hero.hero-general .content > *:first-child { margin-top: auto; } .hero.hero-general .content > *:last-child { margin-bottom: 14px; } .hero.hero-general .content p { margin: 0; font-size: 24px; font-size: 1.5rem; line-height: 1.4em; font-family: 'gilroy', Arial, sans-serif; font-weight: 300; } @media (min-width: 40em) { .hero.hero-general .content p { margin: 0; max-width: 66%; font-size: 32px; font-size: 2rem; line-height: 1.3em; } } @media (min-width: 50em) { .hero.hero-general .content { min-height: 180px; } } .textSection { padding: 54px 0 50px; } @media (min-width: 40em) { .textSection { padding: 54px 0 50px; } } @media (min-width: 53em) { .textSection { padding: 54px 0 50px; } .textSection p { font-size: 1.25rem; line-height: 1.5em; } } .newsletterForm { margin-top: 40px; } .newsletterForm.hidden { display: none !important; } .newsletterSelection { display: flex; flex-direction: row; justify-content: space-between; align-items: top; margin-bottom: 40px; } .newsletterSelection input { width: 20px; height: 32px; height: 2rem; margin: 0; font-size: 2rem; line-height: 2rem; cursor: pointer; } .newsletterSelection-text { width: calc(100% - 2rem); } .newsletterSelection-text h3 { font-family: gilroy; font-size: 32px; font-size: 2rem; line-height: 1.2em; margin: 0 0 8px; } .newsletterSelection-period { margin: 0; font-size: 1.25rem; line-height: 1.5em; color: #666; } .newsletterSelection-text > p { font-size: 1.25rem; line-height: 1.5em; margin: 0 0 8px; color: #222; } .newsletterSelection-text > blockquote { font-size: 1.25rem; line-height: 1.5em; text-indent: -.4em; color: #222; } .newsletterSelection-text > cite { display: block; margin-bottom: 8px; color: #666; } .newsletterSelection-sample { display: inline-block; color: #ee0000; } @media (min-width: 50em) { /* 800px */ .newsletterForm { display: flex; flex-direction: row; justify-content: space-between; flex-wrap: wrap; align-items: top; margin-top: 60px; } .newsletterSelection { width: calc(50% - 40px); margin-bottom: 60px; } } .popoverWrapper { display: block; position: fixed; width: 100%; height: 100%; background-color: rgba(0,0,0,.5); left: 0; top: 0; z-index: 999; } .popoverWrapper:before { content: " "; background: url(//cdn.oreillystatic.com/oreilly/images/mobile-menu-close.png); background-size: 20px 20px; position: absolute; right: 10px; top: 10px; height: 20px; width: 20px; color: #fff; } .popoverWrapper:hover:before { cursor: pointer; } .popover { display: block; position: absolute; z-index: 999; width: 100%; max-width: 650px; height: 90%; left: 50%; margin-left: -325px; padding: 0; top: 5%; -webkit-overflow-scrolling: touch !important; overflow: scroll !important; } @media (max-width: 650px) { .popoverWrapper { -webkit-overflow-scrolling: touch !important; overflow: scroll; } .popover { margin-left: 0; left: 0; top: 50px; height: calc(100% - 50px); box-shadow: 0 10px 20px rgba(0,0,0,.1); } } /* mc-form */ .mc-form { opacity: .5; max-width: 800px; font-family: 'guardian-text-oreilly', Arial, sans-serif; transition: opacity .2s; } .mc-form.hidden { display: none !important; } .mc-form .mc-form-errorMessage p { color: #ff0000; margin-bottom: 20px; } .mc-form input, .mc-form label { display: block; font-family: inherit; } .mc-form label { margin-bottom: 4px; font-size: 1rem; line-height: 1.5em; } .mc-form p { font-size: 20px; font-size: 1rem; line-height: 1.5em; margin: 0; } .mc-form input[type="email"] { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; -webkit-appearance: none; -moz-appearance: none; appearance: none; margin: 0 0 20px; width: 100%; border: 1px solid #999; border-radius: 0; padding: 10px 10px 11px; color: #222; font-size: 1rem; line-height: 1.5rem; } .mc-form select { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; -webkit-appearance: none; -moz-appearance: none; appearance: none; margin: 0 0 20px; width: 100%; border: 1px solid #999; border-radius: 0; padding: 10px 10px 11px; background: transparent url(https://cdn.oreillystatic.com/oreilly/images/inbound-aisf-select-arrow.png) right center no-repeat; color: #222; font-size: 1rem; line-height: 1.5rem; cursor: pointer; } .mc-form .option-select input[type="radio"], .mc-form .option-select label { display: inline-block; margin-right: 8px; } .consentGroup { margin-bottom: 20px; } .consentGroup fieldset { display: flex; flex-wrap: wrap; align-items: center; } .consentGroup fieldset.error { padding: 10px; border: 1px solid #ff0000; } .consentGroup input { display: inline-block; margin: 0 4px 0 0; cursor: pointer; } .consentGroup label { display: inline-block; margin: 0 8px 0 0; } .consentGroup p { margin-left: .5rem; width: calc(100% - 7rem); } .mc-form button { display: block; margin: 0 0 8px; border: 0; border-radius: 2px; padding: 14px 20px 13px; background-color: rgb(0,113,235); font-family: 'gilroy', Arial, sans-serif; font-weight: 500; text-decoration: none; white-space: nowrap; cursor: pointer; font-size: 1.25rem; line-height: 1em; color: #fff; cursor: pointer; } .mc-form button:hover, .mc-form button:active { opacity: 0.9; text-decoration: none; box-shadow: 0 1px 4px rgba(0,0,0,.3); color: #fff; } .mc-form *:disabled { pointer-events: none; cursor: default; } .mc-form p.privacy { font-size: .875rem; line-height: 1.5em; color: #d30000; } .mc-form p.privacy a { color: #d30000; text-decoration: none; } .mc-form p.privacy a:hover { text-decoration: underline; } .mc-form-thankyou h2 { font-family: 'gilroy', Arial, sans-serif; font-size: 32px; font-size: 3.2rem; line-height: 1.2em; font-weight: 600; } .mc-form-thankyou p { font-size: 1rem; line-height: 1.5em; } @media (min-width: 50em) { .mc-form-thankyou p { font-size: 1rem; line-height: 1.5em; } .mc-form-group { display: grid; grid-template-columns: 1fr 1fr 10rem; column-gap: 8px; row-gap: 8px; } .mc-form-item { display: flex; flex-direction: column; } .mc-form-item:nth-of-type(1) { grid-column-start: 1; grid-column-end: 2; grid-row-start: 1; grid-row-end: 2; align-self: flex-end; } .mc-form-item:nth-of-type(2) { grid-column-start: 2; grid-column-end: 3; grid-row-start: 1; grid-row-end: 2; align-self: flex-end; } .mc-form-item:nth-of-type(3) { grid-column-start: 1; grid-column-end: 4; grid-row-start: 2; grid-row-end: 3; } .mc-form-item:nth-of-type(4) { grid-column-start: 3; grid-column-end: 4; grid-row-start: 1; grid-row-end: 2; align-self: flex-end; } .mc-form-item:nth-of-type(5) { grid-column-start: 1; grid-column-end: 4; grid-row-start: 3; grid-row-end: 4; } .mc-form input[type="email"], .mc-form select, .mc-form button, .consentGroup { margin: 0; } } /* mc-form error message styles */ .mc-form input[type="text"].error, .mc-form input[type="email"].error, .mc-form select.error, .mc-form input[type="radio"].error, .mc-form .option-select.error { border-width: 1px; border-color: #ff0000; } .mc-form select.error, .mc-form .option-select.error { background-color: #fae0de; } .mc-form label.error, .mc-form-errorMessage p, .mc-form .option-select.error legend { padding-left: 28px; color: #ff0000; position: relative; } .mc-form select.error { color: #d30000; } .mc-form noscript { font-weight: 600; color: #d30000; position: relative; } .mc-form noscript p { padding-left: 28px; } .mc-form label.error:before, .mc-form-errorMessage p:before, .mc-form noscript p:before, .mc-form .option-select.error legend:before { content: url('https://cdn.oreillystatic.com/images/icons/baseline-error_outline-24px.svg'); position: absolute; left: 0; } .mc-form button[disabled], .mc-form input[disabled], .mc-form textarea[disabled], .mc-form select[disabled] { opacity: 0.5; } /* end mc-form */ </style> <section class="hero hero-general"> <div class="content"> <h1>Newsletters</h1> <p>What matters now <span class="nowrap">and why</span></p> </div> </section> <section class="textSection"> <div class="content"> <p class="intro" id="intro"> Get news and insights—plus exclusive content, offers, and more. Make your selection, then fill out the <span class="nowrap">form below.</span><br /> <a class="blue-link privacy" href="http://oreilly.com/oreilly/privacy.html" target="_blank">We protect your privacy</a>. </p> <form class="newsletterForm" id="newsletterForm"> <label class="newsletterSelection" id="economy"> <input type="checkbox" name="newsletterSelection" value="NextEconomy" /> <div class="newsletterSelection-text"> <h3> Next Economy Newsletter <p class="newsletterSelection-period">Weekly</p> </h3> <blockquote> “This really helps me think about how to shape our company for the future—to be ahead of <span class="nowrap">the pack.</span>” </blockquote> <cite>—<strong>Sunny</strong>, Cocreator, Fin15</cite> <!--<a class="newsletterSelection-sample" id="show-full-newsletter" class="blue-link" href="#" data-source="https://cdn.oreillystatic.com/oreilly/email/share/nl-econ-20220715-share.html">View sample newsletter</a>--> </div> </label> <label class="newsletterSelection" id="radar"> <input type="checkbox" name="newsletterSelection" value="RadarTrends" /> <div class="newsletterSelection-text"> <h3> Radar Trends to Watch <p class="newsletterSelection-period">Monthly</p> </h3> <p>Tracking need-to-know trends at the intersection of business <span class="nowrap">and technology.</span></p> <!--<a class="newsletterSelection-sample" id="show-full-newsletter" class="blue-link" href="#" data-source="https://cdn.oreillystatic.com/oreilly/email/share/nl-radar-20220702-share.html">View sample <span class="screen-reader-text">Radar </span>newsletter</a>--> </div> </label> </form> <form id="marketingCloudForm" class="mc-form" action="https://cl.exct.net/DEManager.aspx" name="subscribeForm" method="post"> <input type="hidden" name="_clientID" value="7200351" /> <input type="hidden" name="_deExternalKey" value="3559B084-4962-47D6-AD05-DAA2DE51CF45" /> <input type="hidden" name="_action" value="add" /> <input type="hidden" name="_returnXML" value="0" /> <input type="hidden" name="_successURL" value="https://www.oreilly.com/emails/newsletters/?submit=true" /> <input type="hidden" name="_errorURL" value="https://www.oreilly.com/emails/newsletters/" /> <input type="hidden" name="NewsletterTopic" value=""> <input type="hidden" name="Marketing_Context" value="email signup at https://www.oreilly.com/emails/newsletters/"> <div id="marketingCloudForm-errorMessage" class="mc-form-errorMessage"> </div> <div class="mc-form-group"> <div class="mc-form-item"> <label for="emailaddress">Your email</label> <input type="email" name="emailaddress" id="emailaddress" data-text="email address" autocomplete="email" aria-required="true" disabled="disabled"> </div> <div class="mc-form-item"> <label for="country">Country</label> <select name="country" id="country" data-text="country" autocomplete="country-name" aria-required="true" disabled="disabled"> <option value="">- Select country -</option> <option value="United States">United States</option> <option value="Afghanistan">Afghanistan</option> <option value="Albania">Albania</option> <option value="Algeria">Algeria</option> <option value="Andorra">Andorra</option> <option value="Angola">Angola</option> <option value="Antigua and Barbuda">Antigua and Barbuda</option> <option value="Argentina">Argentina</option> <option value="Armenia">Armenia</option> <option value="Aruba">Aruba</option> <option value="Australia">Australia</option> <option value="Austria">Austria</option> <option value="Azerbaijan">Azerbaijan</option> <option value="Bahamas">The Bahamas</option> <option value="Bahrain">Bahrain</option> <option value="Bangladesh">Bangladesh</option> <option value="Barbados">Barbados</option> <option value="Belarus">Belarus</option> <option value="Belgium">Belgium</option> <option value="Belize">Belize</option> <option value="Benin">Benin</option> <option value="Bermuda">Bermuda</option> <option value="Bhutan">Bhutan</option> <option value="Bolivia, Plurinational State of">Bolivia</option> <option value="Bosnia and Herzegovina">Bosnia and Herzegovina</option> <option value="Botswana">Botswana</option> <option value="Brazil">Brazil</option> <option value="Brunei Darussalam">Brunei</option> <option value="Bulgaria">Bulgaria</option> <option value="Burkina Faso">Burkina Faso</option> <option value="Burundi">Burundi</option> <option value="Cambodia">Cambodia</option> <option value="Cameroon">Cameroon</option> <option value="Canada">Canada</option> <option value="Cape Verde">Cape Verde</option> <option value="Central African Republic">Central African Republic</option> <option value="Chad">Chad</option> <option value="Chile">Chile</option> <option value="China">People's Republic of China</option> <option value="Colombia">Colombia</option> <option value="Comoros">Comoros</option> <option value="Congo">Congo, Republic of the</option> <option value="Congo, the Democratic Republic of the">Congo, Democratic Republic of the</option> <option value="Cook Islands">Cook Islands</option> <option value="Costa Rica">Costa Rica</option> <option value="Cote d'Ivoire">Côte d'Ivoire (Ivory Coast)</option> <option value="Croatia">Croatia</option> <option value="Cuba">Cuba</option> <option value="Cyprus">Cyprus</option> <option value="Czech Republic">Czechia</option> <option value="Denmark">Denmark</option> <option value="Djibouti">Djibouti</option> <option value="Dominica">Dominica</option> <option value="Dominican Republic">Dominican Republic</option> <option value="Ecuador">Ecuador</option> <option value="Egypt">Egypt</option> <option value="El Salvador">El Salvador</option> <option value="Equatorial Guinea">Equatorial Guinea</option> <option value="Eritrea">Eritrea</option> <option value="Estonia">Estonia</option> <option value="Swaziland">Eswatini (formerly Swaziland)</option> <option value="Ethiopia">Ethiopia</option> <option value="Federated States of Micronesia">Federated States of Micronesia</option> <option value="Fiji">Fiji</option> <option value="Finland">Finland</option> <option value="France">France</option> <option value="Gabon">Gabon</option> <option value="Gambia">The Gambia</option> <option value="Georgia">Georgia</option> <option value="Germany">Germany</option> <option value="Ghana">Ghana</option> <option value="Greece">Greece</option> <option value="Grenada">Grenada</option> <option value="Guatemala">Guatemala</option> <option value="Guinea">Guinea</option> <option value="Guinea-Bissau">Guinea-Bissau</option> <option value="Guyana">Guyana</option> <option value="Haiti">Haiti</option> <option value="Honduras">Honduras</option> <option value="Hungary">Hungary</option> <option value="Iceland">Iceland</option> <option value="India">India</option> <option value="Indonesia">Indonesia</option> <option value="Iran, Islamic Republic of">Iran</option> <option value="Iraq">Iraq</option> <option value="Ireland">Ireland</option> <option value="Israel">Israel</option> <option value="Italy">Italy</option> <option value="Jamaica">Jamaica</option> <option value="Japan">Japan</option> <option value="Jordan">Jordan</option> <option value="Kazakhstan">Kazakhstan</option> <option value="Kenya">Kenya</option> <option value="Kiribati">Kiribati</option> <option value="Korea, Democratic People's Republic of">Korea, Democratic People's Republic of</option> <option value="Korea, Republic of">Korea, Republic of</option> <option value="Kuwait">Kuwait</option> <option value="Kyrgyzstan">Kyrgyzstan</option> <option value="Lao People's Democratic Republic">Laos</option> <option value="Latvia">Latvia</option> <option value="Lebanon">Lebanon</option> <option value="Lesotho">Lesotho</option> <option value="Liberia">Liberia</option> <option value="Libyan Arab Jamahiriya">Libya</option> <option value="Liechtenstein">Liechtenstein</option> <option value="Lithuania">Lithuania</option> <option value="Luxembourg">Luxembourg</option> <option value="Macedonia, the former Yugoslav Republic of">Macedonia, Republic of</option> <option value="Madagascar">Madagascar</option> <option value="Malawi">Malawi</option> <option value="Malaysia">Malaysia</option> <option value="Maldives">Maldives</option> <option value="Mali">Mali</option> <option value="Malta">Malta</option> <option value="Mauritania">Mauritania</option> <option value="Mauritius">Mauritius</option> <option value="Mexico">Mexico</option> <option value="Moldova, Republic of">Moldova</option> <option value="Monaco">Monaco</option> <option value="Mongolia">Mongolia</option> <option value="Montenegro">Montenegro</option> <option value="Morocco">Morocco</option> <option value="Mozambique">Mozambique</option> <option value="Myanmar">Myanmar</option> <option value="Namibia">Namibia</option> <option value="Nauru">Nauru</option> <option value="Nepal">Nepal</option> <option value="Netherlands">Netherlands</option> <option value="New Zealand">New Zealand</option> <option value="Nicaragua">Nicaragua</option> <option value="Niger">Niger</option> <option value="Nigeria">Nigeria</option> <option value="Niue">Niue</option> <option value="Norway">Norway</option> <option value="Oman">Oman</option> <option value="Pakistan">Pakistan</option> <option value="Palestinian Territory, Occupied">Palestine, State of</option> <option value="Panama">Panama</option> <option value="Papua New Guinea">Papua New Guinea</option> <option value="Paraguay">Paraguay</option> <option value="Peru">Peru</option> <option value="Philippines">Philippines</option> <option value="Poland">Poland</option> <option value="Portugal">Portugal</option> <option value="Qatar">Qatar</option> <option value="Romania">Romania</option> <option value="Russian Federation">Russia</option> <option value="Rwanda">Rwanda</option> <option value="Saint Kitts and Nevis">Saint Kitts and Nevis</option> <option value="Saint Lucia">Saint Lucia</option> <option value="Saint Vincent and the Grenadines">Saint Vincent and the Grenadines</option> <option value="Samoa">Samoa</option> <option value="San Marino">San Marino</option> <option value="Sao Tome and Principe">São Tomé and Príncipe</option> <option value="Saudi Arabia">Saudi Arabia</option> <option value="Senegal">Senegal</option> <option value="Serbia">Serbia</option> <option value="Seychelles">Seychelles</option> <option value="Sierra Leone">Sierra Leone</option> <option value="Singapore">Singapore</option> <option value="Slovakia">Slovakia</option> <option value="Slovenia">Slovenia</option> <option value="Solomon Islands">Solomon Islands</option> <option value="Somalia">Somalia</option> <option value="South Africa">South Africa</option> <option value="South Sudan">South Sudan</option> <option value="Spain">Spain</option> <option value="Sri Lanka">Sri Lanka</option> <option value="Sudan">Sudan</option> <option value="Suriname">Suriname</option> <option value="Sweden">Sweden</option> <option value="Switzerland">Switzerland</option> <option value="Syrian Arab Republic">Syria</option> <option value="Chinese Taipei">Taiwan</option> <option value="Tajikistan">Tajikistan</option> <option value="Tanzania, United Republic of">Tanzania</option> <option value="Thailand">Thailand</option> <option value="Timor-Leste">Timor-Leste (East Timor)</option> <option value="Togo">Togo</option> <option value="Tonga">Tonga</option> <option value="Trinidad and Tobago">Trinidad and Tobago</option> <option value="Tunisia">Tunisia</option> <option value="Turkey">Turkey</option> <option value="Turkmenistan">Turkmenistan</option> <option value="Tuvalu">Tuvalu</option> <option value="Uganda">Uganda</option> <option value="Ukraine">Ukraine</option> <option value="United Arab Emirates">United Arab Emirates</option> <option value="United Kingdom">United Kingdom</option> <option value="United States">United States</option> <option value="Uruguay">Uruguay</option> <option value="Uzbekistan">Uzbekistan</option> <option value="Vanuatu">Vanuatu</option> <option value="Holy See (Vatican City State)">Vatican City</option> <option value="Venezuela, Bolivarian Republic of">Venezuela</option> <option value="Viet Nam">Vietnam</option> <option value="Yemen">Yemen</option> <option value="Zambia">Zambia</option> <option value="Zimbabwe">Zimbabwe</option> </select> </div> <div class="mc-form-item"> <div class="consentGroup hidden" id="consentGroup"> </div> </div> <div class="mc-form-item"> <button type="submit" disabled="disabled" onclick="return verif();">Subscribe</button> </div> <div class="mc-form-item"> <p class="privacy"><a href="http://oreilly.com/oreilly/privacy.html" target="_blank">Please read our privacy policy</a>.</p> </div> </div> </form> <div id="marketingCloudForm-thankyou" class="marketingCloudForm-thankyou hidden"> <h2>Thank you for subscribing.</h2> </div> </div> </section> <div class="hidden" id="popoverWrapper"> <iframe id="nl-preview" ></iframe> </div> <script type="text/javascript"> document.addEventListener("DOMContentLoaded", function(event) { enableForm(); toggleFormThankYou(); }); function enableForm() { getCheckedTopics(); setTopicListener(); setCountryListener(); } function parseParams(name) { name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]"); var regexS = "[\\?&]"+name+"=([^&#]*)"; var regex = new RegExp( regexS ); var results = regex.exec( window.location.href ); if (results == null) { return ""; } else { return results[1]; } } function toggleHidden() { var targets = Array.prototype.slice.call(arguments); targets.forEach(function(target) { document.getElementById(target).classList.toggle('hidden'); }); } // Hide the forms and show the thankyou message depending on a URL parameter function toggleFormThankYou() { if (parseParams('submit') === 'true') { toggleHidden('intro', 'newsletterForm', 'marketingCloudForm', 'marketingCloudForm-thankyou'); history.pushState(null, "", location.href.split("?")[0]); } } function setTopicListener() { const newsletterTopics = document.querySelectorAll('#newsletterForm input[type=checkbox]'); newsletterTopics.forEach(function(topic) { topic.addEventListener('change', function (e) { getCheckedTopics(); }); }); } function getCheckedTopics() { const newsletterTopicsChecked = document.querySelectorAll('#newsletterForm input[type=checkbox]:checked'); var newsletterTopic = ""; newsletterTopicsChecked.forEach(function(checkedTopic) { //Add comma between topic each value if(newsletterTopic !== "") { newsletterTopic += ","; } newsletterTopic += checkedTopic.value; }); const marketingCloudForm = document.getElementById('marketingCloudForm'); //Set value of 'NewsletterTopic' hidden field marketingCloudForm.elements['NewsletterTopic'].value = newsletterTopic; const marketingCloudFormFields = document.querySelectorAll('#marketingCloudForm input, #marketingCloudForm select, #marketingCloudForm button'); if (newsletterTopic !== "") { //Make the marketing cloud form 100% opaque marketingCloudForm.style.opacity = '1'; //Remove disabled property from all fields in the marketing cloud form marketingCloudFormFields.forEach(function(field) { field.removeAttribute('disabled'); }); } else { //Make the marketing cloud form 50% opaque marketingCloudForm.style.opacity = '.5'; //Add disabled property to all fields in the marketing cloud form marketingCloudFormFields.forEach(function(field) { field.setAttribute('disabled','disabled'); }); } } function setCountryListener() { var countries = document.querySelectorAll('#marketingCloudForm [name="country"]'); for (i = 0; i < countries.length; i++ ) { countries[i].addEventListener('change', function (e) { var country = this.value; checkOptInStatus(country); }); } } function checkOptInStatus(country) { var gdprSelect = document.getElementById('consentGroup'); var optInHtml = '\n <fieldset role="radiogroup" aria-required="true" data-text="choice for receiving O’Reilly email updates"><input type="radio" name="Marketing_Consent" class="consent" id="consentYes" value="True"> \n <label for="consentYes">Yes</label> \n <input type="radio" name="Marketing_Consent" class="consent" id="consentNo" value="False"> \n <label for="consentNo">No</label> \n <p>I would like to receive email updates from O’Reilly on its latest ideas, events, <span class="nowrap">and offers.</span></p> \n </fieldset>'; if (requiresConsent(country) && gdprConsentHidden(gdprSelect)) { gdprSelect.classList.toggle('hidden'); gdprSelect.innerHTML = optInHtml; } else if (!requiresConsent(country) && !gdprConsentHidden(gdprSelect)) { gdprSelect.classList.toggle('hidden'); gdprSelect.innerHTML = ''; } } function requiresConsent(country) { var euCountries = ['Austria', 'Belgium', 'Bulgaria', 'China', 'Croatia', 'Republic of Cyprus', 'Czech Republic', 'Denmark', 'Estonia', 'Finland', 'France', 'Germany', 'Greece', 'Hungary', 'Iceland', 'Ireland', 'Italy', 'Latvia', 'Liechtenstein', 'Lithuania', 'Luxembourg', 'Malta', 'Netherlands', 'Norway', 'Poland', 'Portugal', 'Romania', 'Slovakia', 'Slovenia', 'Spain', 'Sweden', 'United Kingdom']; return(euCountries.indexOf(country) + 1); } function gdprConsentHidden(gdprSelect) { return gdprSelect.classList.contains('hidden') ? true : false; } function verif(formName) { const formId = '#marketingCloudForm'; const form = document.getElementById('marketingCloudForm'); //Loop through each previous error and remove the class and aria-invalid attribute const errorItems = document.querySelectorAll('#marketingCloudForm .error'); errorItems.forEach(function(item) { item.classList.remove('error'); item.removeAttribute('aria-invalid'); }); var errors = []; //Loop through each required field const requiredFields = document.querySelectorAll('#marketingCloudForm [aria-required$="true"]'); requiredFields.forEach(function(field) { if (fieldInvalid(field, form)) { createError(field, '#marketingCloudForm', 'marketingCloudForm', errors); }; }); // If errors found, display them and prevent submit if (errors.length > 0) { displayErrors(errors); return false; } // When no errors found continue... // Push dataLayer event for Goggle Analytics var emailTopic = ''; if (document.getElementById('marketingCloudForm').elements['NewsletterTopic'] != undefined) { emailTopic = document.getElementById('marketingCloudForm').elements['NewsletterTopic'].value.toLowerCase(); } dataLayer.push({ 'event': 'eventTracker', 'eventCat':'email sign up', 'eventAct':'topic sign up', 'eventLbl': emailTopic, 'eventVal':0, 'nonInteraction':0 }); return true; //return false; } function fieldInvalid(field, form) { if (field.tagName === 'FIELDSET') { return (consentInvalid(field, form)) ? true : false; } else if (field.name === "email") { return (emailInvalid(form)) ? true : false; } else { return (field.value.length < 1) ? true : false; } } function consentInvalid(field, form) { if (form.elements['Marketing_Consent'].value.length < 1) { //form.elements['Marketing_Consent'].value = form.elements['consent'].value; return true; } } function emailInvalid(form) { var mail = new RegExp('@+','g'); if ( (form.email.value.length < 1) || (!mail.test(form.email.value)) ) { return true; } } function createError(field, formId, formName, errors) { if (field.tagName === 'fieldset') { field.classList.add('error'); } else { field.classList.add('error'); field.setAttribute('aria-invalid','true'); } errors.push(field.dataset.text); } function displayErrors(errors) { var errorMessage = ''; if (errors.length > 3) { errorMessage = '<p>Please fill out all required fields.</p>'; } else { errorMessage = '<p>Please enter your '; for (i = 0; i < errors.length; i++) { errorMessage += errors[i]; if (i === errors.length - 2) { errorMessage += ', and ' } else if (i < errors.length - 1) { errorMessage += ', ' } else { errorMessage += '.</p>' } } } document.getElementById('marketingCloudForm-errorMessage').innerHTML = errorMessage; } </script> </main> <footer id="footer" class="footer"> <div class="content"> <div class="footer-main" aria-label="company info"> <div class="footer-mainLeft"> <div class="footer-mainLeftOne"> <div class="footer-approach"> <h2 class="footer-header"><a href="/about/">About O’Reilly</a></h2> <ul class="footer-links"> <li><a href="/work-with-us.html">Teach/write/train</a></li> <li><a href="/careers/">Careers</a></li> <li><a href="/press/">O’Reilly news</a></li> <li><a href="/press/media-coverage.html">Media coverage</a></li> <li><a href="/partner/signup.csp">Community partners</a></li> <li><a href="/affiliates/">Affiliate program</a></li> <li><a href="/online-learning/rfp.html">Submit an RFP</a></li> <li><a href="/diversity/">Diversity</a></li> <li><a href="/content-marketing-solutions.html" id="footerSponsorshipLink">O’Reilly for marketers</a></li> </ul> </div> </div> <div class="footer-mainLeftTwo"> <div class="footer-contact"> <h2 class="footer-header"><a href="/online-learning/support/">Support</a></h2> <ul class="footer-links"> <li><a href="/about/contact.html">Contact us</a></li> <li><a href="/emails/newsletters/">Newsletters</a></li> <li><a href="/privacy.html">Privacy policy</a></li> <li><a href="/about/oreilly-approach-to-generative-ai.html">AI policy</a></li> </ul> <a href="https://www.linkedin.com/company/oreilly-media" target="_blank"><svg data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32.25 32.25"><defs><style>.cls-1{fill:#d30000;fill-rule:evenodd;}</style></defs><title>linkedin-logo</title><path class="cls-1" d="M17.43,13.53v0l0,0ZM16.12,0A16.13,16.13,0,1,0,32.25,16.12,16.12,16.12,0,0,0,16.12,0ZM11.77,22.92H8.12v-11h3.65ZM9.94,10.44h0a1.89,1.89,0,0,1-2-1.89A1.91,1.91,0,0,1,10,6.65a1.9,1.9,0,1,1,0,3.79Zm15,12.48H21.28V17.05c0-1.48-.53-2.49-1.85-2.49a2,2,0,0,0-1.88,1.34,2.63,2.63,0,0,0-.12.89v6.13H13.79s.05-10,0-11h3.64V13.5a3.63,3.63,0,0,1,3.29-1.82c2.4,0,4.21,1.57,4.21,4.95Z"/></svg></a> <a href="https://www.youtube.com/user/OreillyMedia" target="_blank"><svg data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32.25 32.25"><defs><style>.cls-1{fill:#d30000;fill-rule:evenodd;}</style></defs><title>youtube-logo</title><path class="cls-1" d="M18.35,18.68a.89.89,0,0,0-.86.63V16.94h-1v7.59h1v-.59a.92.92,0,0,0,.89.74c.52,0,.86-.36,1-1.07a8.56,8.56,0,0,0,.14-1.9,10.47,10.47,0,0,0-.12-1.93C19.21,19.05,18.87,18.68,18.35,18.68Zm.09,4.14c-.05.52-.2.77-.45.77s-.43-.21-.49-.63a7.22,7.22,0,0,1,0-1c0-.72,0-1.14,0-1.26.07-.58.23-.88.51-.88s.4.27.46.79c0,.09,0,.47,0,1.13S18.46,22.71,18.44,22.82ZM8.61,18.19H9.86v6.34H11V18.19H12.2V16.94H8.61Zm7.71-6.12c.27,0,.43-.22.49-.66,0-.09,0-.45,0-1.07V9.78c0-.58,0-.93,0-1-.07-.43-.23-.65-.48-.65s-.41.19-.48.57a8.79,8.79,0,0,0,0,1v.53c0,.71,0,1.09,0,1.16C15.88,11.82,16.05,12.07,16.32,12.07Zm-1.74,10.4a2.92,2.92,0,0,1-.06.71c-.07.25-.2.37-.4.37s-.32-.11-.38-.34a2.63,2.63,0,0,1-.05-.66V18.83h-1v4.48c0,.91.33,1.37,1,1.37A1,1,0,0,0,14.6,24v.57h1v-5.7h-1Zm7.1-3.79a1.35,1.35,0,0,0-1.22.59,2.48,2.48,0,0,0-.3,1.07c0,.23,0,.61,0,1.16s0,1.13,0,1.37a2.93,2.93,0,0,0,.35,1.27,1.25,1.25,0,0,0,1.14.54,1.36,1.36,0,0,0,1.13-.45,2.29,2.29,0,0,0,.37-1.43s0-.07,0-.11v-.12h-1c0,.75-.17,1.12-.51,1.12s-.38-.18-.45-.56a4.68,4.68,0,0,1-.06-.9c0-.18,0-.31,0-.37h2v-.43a4.86,4.86,0,0,0-.3-2.11A1.28,1.28,0,0,0,21.68,18.68ZM22.15,21h-1c0-.05,0-.11,0-.16v-.08a1.64,1.64,0,0,1,.11-.8.39.39,0,0,1,.38-.23.42.42,0,0,1,.43.33,2.32,2.32,0,0,1,.07.7Zm-6-21A16.13,16.13,0,1,0,32.25,16.12,16.12,16.12,0,0,0,16.12,0Zm2.51,7.2h1V11a2.52,2.52,0,0,0,.06.66c.06.23.18.34.38.34s.34-.12.41-.37a3.76,3.76,0,0,0,.05-.71V7.2h1v5.74h-1v-.57a1,1,0,0,1-.93.72c-.66,0-1-.46-1-1.38ZM15,8a1.29,1.29,0,0,1,1.33-.92A1.3,1.3,0,0,1,17.65,8a6.77,6.77,0,0,1,.23,2.1,6.77,6.77,0,0,1-.23,2.1,1.3,1.3,0,0,1-1.32.92A1.29,1.29,0,0,1,15,12.17a6.77,6.77,0,0,1-.23-2.1A6.86,6.86,0,0,1,15,8ZM11.45,5.3l.89,2.87.88-2.87H14.4L12.88,9.7v3.24h-1.1V9.7L10.24,5.3ZM24.93,23.91a3,3,0,0,1-3,3h-12a3,3,0,0,1-3-3V18.05a3,3,0,0,1,3-3h12a3,3,0,0,1,3,3Z"/></svg></a> </div> <div class="footer-international"> <h2 class="footer-header">International</h2> <ul class="footer-links"> <li><a href="https://www.oreilly.com/anz/">Australia & New Zealand</a></li> <li><a href="https://oreilly.hk/">Hong Kong & Taiwan</a></li> <li><a href="https://oreillylearning.in/">India</a></li> <li><a href="https://oreilly.id/">Indonesia</a></li> <li><a href="https://www.oreilly.co.jp/index.shtml">Japan</a></li> </ul> </div> </div> </div> <div class="footer-download" id="download-info"> <h2 class="footer-header">Download the O’Reilly App</h2> <p>Take O’Reilly with you and learn anywhere, anytime on your phone <span class="nowrap">and tablet.</span></p> <div class="footer-downloadLinks"> <a href="https://itunes.apple.com/us/app/safari-to-go/id881697395"><img src="https://cdn.oreillystatic.com/oreilly/images/app-store-logo.png" alt="Apple app store" /></a> <a href="https://play.google.com/store/apps/details?id=com.safariflow.queue"><img src="https://cdn.oreillystatic.com/oreilly/images/google-play-logo.png" alt="Google play store" /></a> </div> </div> <div class="footer-download" id="tv-info"> <h2 class="footer-header">Watch on your big screen</h2> <p>View all O’Reilly videos, Superstream events, and Meet the Expert sessions on your <span class="nowrap">home TV.</span></p> <div class="footer-downloadLinks"> <a href="https://channelstore.roku.com/details/c8a2d0096693eb9455f6ac165003ee06/oreilly"><img src="https://cdn.oreillystatic.com/oreilly/images/roku-tv-logo.png" alt="Roku Players and TVs" /></a> <a href="https://www.amazon.com/OReilly-Media-Inc/dp/B087YYHL5C/ref=sr_1_2?dchild=1&keywords=oreilly&qid=1604964116&s=mobile-apps&sr=1-2"><img src="https://cdn.oreillystatic.com/oreilly/images/amazon-appstore-logo.png" alt="Amazon appstore" /></a> </div> </div> <div class="footer-donotsell" id="donotsell-info"> <h2 class="footer-header"><a href="https://www.oreilly.com/privacy.html?donotsell=show">Do not sell or share my personal information</a></h2> </div> </div> <div class="footer-subfooter"> <a href="https://www.oreilly.com" title="home page" aria-current="page"> <img class="footer-subfooterLogo" id="footer-subfooterLogo" src="https://cdn.oreillystatic.com/images/sitewide-headers/oreilly_logo_mark_red.svg" onerror="this.src='https://cdn.oreillystatic.com/images/sitewide-headers/oreilly_logo_mark_red_@2x.png'; this.onerror=null;" alt="O'Reilly home"> </a> <p>© 2024, O’Reilly Media, Inc. All trademarks and registered trademarks appearing on oreilly.com are the property of their respective owners.</p> <p><a href="/terms/">Terms of service</a> • <a href="/privacy.html">Privacy policy</a> • <a href="/about/editorial_independence.html">Editorial independence</a><span class="transparencyStatement" style="display:none;"> • <a href="/modern-slavery-act-transparency-statement.html">Modern Slavery Act Statement</a></span></p> </div> </div> </footer> <script src="https://cdn.oreillystatic.com/ajax/libs/jquery/3.7.0/jquery.min.js"></script> <script> $(function() { //Toggle isActive and mobileHidden classes for mobileNavButton $('nav #mobileNavButton').on('click', function() { var expanded = $(this).attr('aria-expanded') === 'true' || false; $(this).attr('aria-expanded', !expanded); $(this).toggleClass("isActive"); $(this).next().toggleClass("mobileHidden"); }); //Toggle isFocused class for keyboard navigation of submenus $('nav #menuList .menuList-subItem a').each(function(navItem) { $(this).on('focus', function() { $(this).parent().parent().toggleClass('isFocused'); }); $(this).on('blur', function() { $(this).parent().parent().toggleClass('isFocused'); }); }); //Toggle mobileHidden class accordian elements $('.mobileAccordian').each(function() { var $btn = $(this).find('button'); var $target = $(this).next(); $btn.on('click', function() { var expanded = $btn.attr('aria-expanded') === 'true' || false; $btn.attr('aria-expanded', !expanded); $target.toggleClass("mobileHidden"); }); }); //Search platform form action function searchSubmit(e) { e.preventDefault(); sParameter = searchForm.search.value; sParameter = encodeURIComponent(sParameter.trim()); sURL = searchForm.action + '?query=' + sParameter; window.location = sURL; //GA event for search dataLayer.push({ 'event': 'eventTracker', 'eventCat':'site search', 'eventAct':'search box', 'eventLbl':'explore our content', 'eventVal':0, 'nonInteraction': 0, }); } const searchForm = document.getElementById('js-searchForm'); searchForm.addEventListener('submit', searchSubmit); //Search button action function showNavSearch(e) { $('.menuList-item-search').addClass('overlay'); $('.menuList-item-search input#search').focus(); } const searchButton = document.getElementById('js-searchButton'); searchButton.addEventListener('click', showNavSearch); //Close search button action function hideNavSearch(e) { $('.menuList-item-search').removeClass('overlay'); } const searchCloseButton = document.getElementById('js-searchCloseButton'); searchCloseButton.addEventListener('click', hideNavSearch); //"Try Now" nav button tracking $('#nav-tryNow').on('click', function() { dataLayer.push({ 'event': 'eventTracker', 'eventCat':'marketing', 'eventAct':'nav', 'eventLbl':'try now', 'eventVal':0, 'nonInteraction': 0, }); }); //"Sign in" nav button tracking $('#nav-signIn').on('click', function() { dataLayer.push({ 'event': 'eventTracker', 'eventCat':'marketing', 'eventAct':'nav', 'eventLbl':'sign in', 'eventVal':0, 'nonInteraction': 0, }); }); //"O'Reilly Platform" nav button tracking $('#nav-platform').on('click', function() { dataLayer.push({ 'event': 'eventTracker', 'eventCat':'marketing', 'eventAct':'nav', 'eventLbl':'oreilly platform', 'eventVal':0, 'nonInteraction': 0, }); }); }); (function(document, history, location) { var HISTORY_SUPPORT = !!(history && history.pushState); FIXED_HEADER_HEIGHT = document.querySelector('body > header').offsetHeight; FIXED_HEADER_HEIGHT += 20; var anchorScrolls = { ANCHOR_REGEX: /^#[^ ]+$/, OFFSET_HEIGHT_PX: FIXED_HEADER_HEIGHT, /** * Establish events, and fix initial scroll position if a hash is provided. */ init: function() { this.scrollToCurrent(); window.addEventListener('hashchange', this.scrollToCurrent.bind(this)); document.body.addEventListener('click', this.delegateAnchors.bind(this)); }, /** * Return the offset amount to deduct from the normal scroll position. * Modify as appropriate to allow for dynamic calculations */ getFixedOffset: function() { return this.OFFSET_HEIGHT_PX; }, /** * If the provided href is an anchor which resolves to an element on the * page, scroll to it. * @param {String} href * @return {Boolean} - Was the href an anchor. */ scrollIfAnchor: function(href, pushToHistory) { var match, rect, anchorOffset; if(!this.ANCHOR_REGEX.test(href)) { return false; } match = document.getElementById(href.slice(1)); if(match) { rect = match.getBoundingClientRect(); anchorOffset = window.pageYOffset + rect.top - this.getFixedOffset(); // Wait 1ms and scroll. It wasn't consistently scrolling immediately. setTimeout(function(){ window.scroll(window.pageXOffset, anchorOffset); }, 1); // Add the state to history as-per normal anchor links if(HISTORY_SUPPORT && pushToHistory) { history.pushState({}, document.title, location.pathname + href); } } return !!match; }, /** * Attempt to scroll to the current location's hash. */ scrollToCurrent: function() { this.scrollIfAnchor(window.location.hash); }, /** * If the click event's target was an anchor, fix the scroll position. */ delegateAnchors: function(e) { var elem = e.target; if( elem.nodeName === 'A' && this.scrollIfAnchor(elem.getAttribute('href'), true) ) { e.preventDefault(); } } }; window.addEventListener( 'DOMContentLoaded', anchorScrolls.init.bind(anchorScrolls) ); })(window.document, window.history, window.location); </script><script type="text/javascript" src="/bdxdF5/wgY/XHI/Eb9JVw/aYLOwNS2r4zN/WRZ9AQ/HAN/pekpRbB4"></script><link rel="stylesheet" type="text/css" href="/bdxdF5/wgY/XHI/Eb9JVw/GG/clJdAQ/JHU/DIC4SMDVX"> <script src="/bdxdF5/wgY/XHI/Eb9JVw/GG/clJdAQ/WDg/cLU9Qdy4p" async defer></script> <div id="sec-overlay" style="display:none;"> <div id="sec-container"> </div> </div></body> </html>