1<!DOCTYPE html> 2<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"><head> 3 4<meta charset="utf-8"> 5<meta name="generator" content="quarto-1.9.38"> 6 7<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes"> 8 9 10<title>Inland Northwest Nonprofit Sector Intelligence</title> 11<style> 12/* Default styles provided by pandoc. 13** See https://pandoc.org/MANUAL.html#variables-for-html for config info. 14*/ 15code{white-space: pre-wrap;} 16span.smallcaps{font-variant: small-caps;} 17div.columns{display: flex; gap: min(4vw, 1.5em);} 18div.column{flex: auto; overflow-x: auto;} 19div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;} 20ul.task-list{list-style: none;} 21ul.task-list li input[type="checkbox"] { 22 width: 0.8em; 23 margin: 0 0.8em 0.2em -1em; /* quarto-specific, see https://github.com/quarto-dev/quarto-cli/issues/4556 */ 24 vertical-align: middle; 25} 26</style> 27 28
29<script src="site_libs/quarto-nav/quarto-nav.js"></script>
vendor: 1 bytes, line 29
29
30<script src="site_libs/quarto-nav/headroom.min.js"></script>
vendor: 1 bytes, line 30
30
31<script src="site_libs/clipboard/clipboard.min.js"></script>
vendor: 1 bytes, line 31
31
32<script src="site_libs/quarto-search/autocomplete.umd.js"></script>
vendor: 1 bytes, line 32
32
33<script src="site_libs/quarto-search/fuse.min.js"></script>
vendor: 1 bytes, line 33
33
34<script src="site_libs/quarto-search/quarto-search.js"></script>
34 35<meta name="quarto:offset" content="./">
36<script src="site_libs/quarto-html/quarto.js" type="module"></script>
vendor: 1 bytes, line 36
36
37<script src="site_libs/quarto-html/tabsets/tabsets.js" type="module"></script>
vendor: 1 bytes, line 37
37
38<script src="site_libs/quarto-html/popper.min.js"></script>
vendor: 1 bytes, line 38
38
39<script src="site_libs/quarto-html/tippy.umd.min.js"></script>
vendor: 1 bytes, line 39
39
40<script src="site_libs/quarto-html/anchor.min.js"></script>
40 41<link href="site_libs/quarto-html/tippy.css" rel="stylesheet"> 42<link href="site_libs/quarto-html/quarto-syntax-highlighting-15634bcf2e68342d4ad2dfa704d543f6.css" rel="stylesheet" id="quarto-text-highlighting-styles">
43<script src="site_libs/bootstrap/bootstrap.min.js"></script>
43 44<link href="site_libs/bootstrap/bootstrap-icons.css" rel="stylesheet"> 45<link href="site_libs/bootstrap/bootstrap-c81d55332d48a6358ab6ce3d5cfa0db1.min.css" rel="stylesheet" append-hash="true" id="quarto-bootstrap" data-mode="light">
46<script id="quarto-search-options" type="application/json">{ 47 "location": "navbar", 48 "copy-button": false, 49 "collapse-after": 3, 50 "panel-placement": "end", 51 "type": "overlay", 52 "limit": 50, 53 "keyboard-shortcut": [ 54 "f", 55 "/", 56 "s" 57 ], 58 "show-item-context": false, 59 "language": { 60 "search-no-results-text": "No results", 61 "search-matching-documents-text": "matching documents", 62 "search-copy-link-title": "Copy link to search", 63 "search-hide-matches-text": "Hide additional matches", 64 "search-more-match-text": "more match in this document", 65 "search-more-matches-text": "more matches in this document", 66 "search-clear-button-title": "Clear", 67 "search-text-placeholder": "", 68 "search-detached-cancel-button-title": "Cancel", 69 "search-submit-button-title": "Submit", 70 "search-label": "Search" 71 } 72}</script>
72 73<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=" crossorigin=""> 74 75 76</head> 77 78<body class="nav-fixed fullcontent quarto-light"> 79 80<div id="quarto-search-results"></div> 81 <header id="quarto-header" class="headroom fixed-top"> 82 <nav class="navbar navbar-expand-lg " data-bs-theme="dark"> 83 <div class="navbar-container container-fluid"> 84 <div class="navbar-brand-container mx-auto"> 85 <a class="navbar-brand" href="./index.html"> 86 <span class="navbar-title">Inland Northwest Nonprofit Sector Intelligence</span> 87 </a> 88 </div> 89 <div id="quarto-search" class="" title="Search"></div> 90 <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarCollapse" aria-controls="navbarCollapse" role="menu" aria-expanded="false" aria-label="Toggle navigation" onclick="if (window.quartoToggleHeadroom) { window.quartoToggleHeadroom(); }"> 91 <span class="navbar-toggler-icon"></span> 92</button> 93 <div class="collapse navbar-collapse" id="navbarCollapse"> 94 <ul class="navbar-nav navbar-nav-scroll me-auto"> 95 <li class="nav-item"> 96 <a class="nav-link active" href="./index.html" aria-current="page"> 97<span class="menu-text">Home</span></a> 98 </li> 99 <li class="nav-item"> 100 <a class="nav-link" href="./sector-overview.html"> 101<span class="menu-text">Sector Overview</span></a> 102 </li> 103 <li class="nav-item"> 104 <a class="nav-link" href="./trends.html"> 105<span class="menu-text">Trends</span></a> 106 </li> 107 <li class="nav-item"> 108 <a class="nav-link" href="./geography.html"> 109<span class="menu-text">Geography</span></a> 110 </li> 111 <li class="nav-item"> 112 <a class="nav-link" href="./human-services.html"> 113<span class="menu-text">Human Services</span></a> 114 </li> 115 <li class="nav-item"> 116 <a class="nav-link" href="./financial-health.html"> 117<span class="menu-text">Financial Health</span></a> 118 </li> 119 <li class="nav-item"> 120 <a class="nav-link" href="./service-gaps.html"> 121<span class="menu-text">Service Gaps</span></a> 122 </li> 123 <li class="nav-item"> 124 <a class="nav-link" href="./methodology.html"> 125<span class="menu-text">Methodology</span></a> 126 </li> 127</ul> 128 </div> <!-- /navcollapse --> 129 <div class="quarto-navbar-tools"> 130</div> 131 </div> <!-- /container-fluid --> 132 </nav> 133</header> 134<!-- content --> 135<div id="quarto-content" class="quarto-container page-columns page-rows-contents page-layout-article page-navbar"> 136<!-- sidebar --> 137<!-- margin-sidebar --> 138 139<!-- main --> 140<main class="content" id="quarto-document-content"> 141 142<header id="title-block-header" class="quarto-title-block default"> 143<div class="quarto-title"> 144<h1 class="title">Inland Northwest Nonprofit Sector Intelligence</h1> 145<p class="subtitle lead">A public-data portrait of the nonprofit sector in Spokane County and the surrounding Inland Northwest</p> 146</div> 147 148 149 150<div class="quarto-title-meta"> 151 152 153 154 155 </div> 156 157 158 159</header> 160 161 162<div class="key-finding"> 163<p><span class="kf-label">Executive summary</span> The seven-county Inland Northwest is home to <strong>5,256 active nonprofits</strong> serving about 882,000 residents â roughly 60 organizations for every 10,000 people. The sector generates <strong>$6.5 billion in annual revenue</strong> and holds <strong>$26.2 billion in assets</strong>, but both are concentrated in a handful of large institutions. Formation activity is surging, finances are broadly stable but thin â a third of larger organizations ran a deficit in their most recent filing â and per-capita human-services coverage is weakest exactly where measured social vulnerability is highest: Spokane County.</p> 164</div> 165<div class="stat-row"> 166<div class="stat-tile"> 167<p><span class="stat-value">5,256</span> <span class="stat-label">Active nonprofits</span> <span class="stat-note">NCCS BMF, June 2026</span></p> 168</div> 169<div class="stat-tile"> 170<p><span class="stat-value">$6.5B</span> <span class="stat-label">Annual revenue</span> <span class="stat-note">most recent IRS filings</span></p> 171</div> 172<div class="stat-tile"> 173<p><span class="stat-value">$26.2B</span> <span class="stat-label">Total assets</span> <span class="stat-note">most recent IRS filings</span></p> 174</div> 175<div class="stat-tile accent"> 176<p><span class="stat-value">768</span> <span class="stat-label">Human services organizations</span> <span class="stat-note">NTEE I, J, K, L, O, P</span></p> 177</div> 178<div class="stat-tile accent"> 179<p><span class="stat-value">395</span> <span class="stat-label">New nonprofits in 2025</span> <span class="stat-note">strongest organic year on record</span></p> 180</div> 181</div> 182<section id="key-findings" class="level2"> 183<h2 class="anchored" data-anchor-id="key-findings">Key findings</h2> 184<p><strong>1. The sector is large, and growing faster than ever.</strong> New IRS tax-exempt rulings reached 310 in 2024 and 395 in 2025 â the strongest two-year run in the regionâs history, even counting the one-time IRS administrative spike of 2014, following a brief pandemic dip. The 2020s are on pace to out-produce the 2010s, the previous record decade. <a href="./trends.html">â Trends</a></p> 185<p><strong>
1852. Composition mirrors the states; scale does not.</strong> The regionâs category mix â human services first (23% of all registered organizations, a third of those with a classified category), then education and public benefit â tracks Washington and Idaho statewide averages closely. What distinguishes the region is concentration: 73 organizations with more than $10 million in revenue, led by Kootenai Health, Gonzaga University, and the regionâs community health systems, account for the large majority of all nonprofit dollars. <a href="./sector-overview.html">â Sector Overview</a></p> 186<p><strong>3. Density is highest where populations are smallest.</strong> Spokane and Kootenai counties host about three-quarters of the regionâs nonprofits, but rural and college counties (Lincoln, Latah, Whitman) sustain far more organizations per resident. Spokane County itself has the regionâs thinnest per-capita nonprofit coverage, with fast-growing Kootenai County next. <a href="./geography.html">â Geography</a></p> 187<p><strong>4. Finances are stable but thin.</strong> Among 502 larger organizations with current Form 990 filings, the median operating margin is +5.0% and median reserves are about 10.6 months of expenses â healthy on the surface. But <strong>one in three ran a deficit</strong> in the latest year, and <strong>one in five holds less than three months of reserves</strong>. Human services organizations hold thinner reserves than the sector overall. <a href="./financial-health.html">â Financial Health</a></p> 188<p><strong>5. Coverage is weakest where vulnerability is highest.</strong> Spokane County has the regionâs highest CDC Social Vulnerability Index score and 22 of its 38 high-vulnerability census tracts â yet the regionâs <em>lowest</em> rate of human-services nonprofits per resident. Twenty-seven ZIP c
188odes combine above-median poverty with below-median human-services coverage. <a href="./service-gaps.html">â Service Gaps</a></p> 189</section> 190<section id="why-this-exists-and-what-to-do-with-it" class="level2"> 191<h2 class="anchored" data-anchor-id="why-this-exists-and-what-to-do-with-it">Why this exists â and what to do with it</h2> 192<p>The Inland Northwestâs nonprofit sector is one of the regionâs largest economic and social forces â more than 5,200 organizations, $6.5 billion in annual revenue, and the primary safety net for food, housing, employment, and youth services. Yet decisions about it â where philanthropy goes, which services get funded, where new organizations form â are routinely made from anecdote, because the underlying facts sit scattered across IRS files, Census tables, and federal vulnerability indices that few people have time to assemble. And because the region spans a state line, no single state-level report has ever described it whole. This site assembles that picture from public data, documents every method, and keeps it reproducible.</p> 193<p><strong>Who itâs for.</strong> Funders can see where dollars concentrate and where coverage gaps persist. Nonprofit boards can benchmark their reserves and margins against 500 regional peers. Policymakers can overlay service coverage with poverty and social vulnerability at the neighborhood level. Researchers and students can build on an open, documented pipeline.</p> 194<p><strong>What the data suggest doing:</strong></p> 195<ol type="1"> 196<li><strong>Fund resilience, not just programs.</strong> One in five larger nonprofits holds less than three months of operating reserves. General operating support and multi-year grants matter as much as new initiatives.</li> 197<li><strong>Target the gap map.</strong>
197 Twenty-seven ZIP codes pair above-median poverty with below-median human-services coverage, and Spokane Countyâs most vulnerable neighborhoods have the regionâs thinnest per-capita coverage â addressable through siting decisions, satellite services, and capacity grants. <a href="./service-gaps.html">â Service Gaps</a></li> 198<li><strong>Plan for Kootenaiâs growth.</strong> The regionâs fastest-growing county has nearly its thinnest nonprofit infrastructure per resident â a gap that compounds if unaddressed.</li> 199</ol> 200</section> 201<section id="about-this-project" class="level2"> 202<h2 class="anchored" data-anchor-id="about-this-project">About this project</h2> 203<p>This site analyzes the nonprofit sector across seven counties: <strong>Spokane, Whitman, Stevens, Pend Oreille, and Lincoln</strong> in Washington, and <strong>Kootenai and Latah</strong> in Idaho â the greater Inland Northwest centered on Spokane and Coeur dâAlene.</p> 204<p>All data are public: the Urban Instituteâs <a href="https://urbaninstitute.github.io/nccs/datasets/bmf/">NCCS Business Master File</a>, IRS Form 990 extracts via the <a href="https://projects.propublica.org/nonprofits/api/">ProPublica Nonprofit Explorer API</a>, U.S. Census Bureau American Community Survey estimates, and the <a href="https://www.atsdr.cdc.gov/placeandhealth/svi/">CDC/ATSDR Social Vulnerability Index</a>. Methods, definitions, and limitations are documented on the <a href="./methodology.html">Methodology</a> page.</p> 205<p><em>Created by Vivek H. Patil, Ph.D., Professor of Marketing and Director of Graduate Business Programs, Gonzaga University School of Business Administration. Analyses run July 2026.</em></p> 206 207 208</section> 209 210</main> <!-- /main -->
211<script id="quarto-html-after-body" type="application/javascript"> 212 window.document.addEventListener("DOMContentLoaded", function (event) { 213 const icon = "î§"; 214 const anchorJS = new window.AnchorJS(); 215 anchorJS.options = { 216 placement: 'right', 217 icon: icon 218 }; 219 anchorJS.add('.anchored'); 220 const isCodeAnnotation = (el) => { 221 for (const clz of el.classList) { 222 if (clz.startsWith('code-annotation-')) { 223 return true; 224 } 225 } 226 return false; 227 } 228 const onCopySuccess = function(e) { 229 // button target 230 const button = e.trigger; 231 // don't keep focus 232 button.blur(); 233 // flash "checked" 234 button.classList.add('code-copy-button-checked'); 235 var currentTitle = button.getAttribute("title"); 236 button.setAttribute("title", "Copied!"); 237 let tooltip; 238 if (window.bootstrap) { 239 button.setAttribute("data-bs-toggle", "tooltip"); 240 button.setAttribute("data-bs-placement", "left"); 241 button.setAttribute("data-bs-title", "Copied!"); 242 tooltip = new bootstrap.Tooltip(button, 243 { trigger: "manual", 244 customClass: "code-copy-button-tooltip", 245 offset: [0, -8]}); 246 tooltip.show(); 247 } 248 setTimeout(function() { 249 if (tooltip) { 250 tooltip.hide(); 251 button.removeAttribute("data-bs-title"); 252 button.removeAttribute("data-bs-toggle"); 253 button.removeAttribute("data-bs-placement"); 254 } 255 button.setAttribute("title", currentTitle); 256 button.classList.remove('code-copy-button-checked'); 257 }, 1000); 258 // clear code selection 259 e.clearSelection(); 260 } 261 const getTextToCopy = function(trigger) { 262 const outerScaffold = trigger.parentElement.cloneNode(true); 263 const codeEl = outerScaffold.querySelector('code'); 264 for (const childEl of codeEl.children) { 265 if (isCodeAnnotation(childEl)) { 266 childEl.remove(); 267 } 268 } 269 return codeEl.innerText; 270 } 271 const clipboard = new window.ClipboardJS('.code-copy-button:not([data-in-quarto-modal])', { 272 text: getTextToCopy 273 }); 274 clipboard.on('success', onCopySuccess); 275 if (window.document.getElementById('quarto-embedded-source-code-modal')) { 276 const clipboardModal = new window.ClipboardJS('.code-copy-button[data-in-quarto-modal]', { 277 text: getTextToCopy, 278 container: window.document.getElementById('quarto-embedded-source-code-modal') 279 }); 280 clipboardModal.on('success', onCopySuccess); 281 } 282 var localhostRegex = new RegExp(/^(?:http|https):\/\/localhost\:?[0-9]*\//); 283 var mailtoRegex = new RegExp(/^mailto:/); 284 var filterRegex = new RegExp("https:\/\/patilv\.com\/spokane-nonprofits\/"); 285 var isInternal = (href) => { 286 return filterRegex.test(href) || localhostRegex.test(href) || mailtoRegex.test(href); 287 } 288 // Inspect non-navigation links and adorn them if external 289 var links = window.document.querySelectorAll('a[href]:not(.nav-link):not(.navbar-brand):not(.toc-action):not(.sidebar-link):not(.sidebar-item-toggle):not(.pagination-link):not(.no-external):not([aria-hidden]):not(.dropdown-item):not(.quarto-navigation-tool):not(.about-link)'); 290 for (var i=0; i<links.length; i++) { 291 const link = links[i]; 292 if (!isInternal(link.href)) { 293 // undo the damage that might have been done by quarto-nav.js in the case of 294 // links that we want to consider external 295 if (link.dataset.originalHref !== undefined) { 296 link.href = link.dataset.originalHref; 297 } 298 // target, if specified 299 link.setAttribute("target", "_blank"); 300 if (link.getAttribute("rel") === null) { 301 link.setAttribute("rel", "noopener"); 302 } 303 } 304 } 305 function tippyHover(el, contentFn, onTriggerFn, onUntriggerFn) { 306 const config = { 307 allowHTML: true, 308 maxWidth: 500, 309 delay: 100, 310 arrow: false, 311 appendTo: function(el) { 312 return el.parentElement; 313 }, 314 interactive: true, 315 interactiveBorder: 10, 316 theme: 'quarto', 317 placement: 'bottom-start', 318 }; 319 if (contentFn) { 320 config.content = contentFn; 321 } 322 if (onTriggerFn) { 323 config.onTrigger = onTriggerFn; 324 } 325 if (onUntriggerFn) { 326 config.onUntrigger = onUntriggerFn; 327 } 328 window.tippy(el, config); 329 } 330 const noterefs = window.document.querySelectorAll('a[role="doc-noteref"]'); 331 for (var i=0; i<noterefs.length; i++) { 332 const ref = noterefs[i]; 333 tippyHover(ref, function() { 334 // use id or data attribute instead here 335 let href = ref.getAttribute('data-footnote-href') || ref.getAttribute('href'); 336 try { href = new URL(href).hash; } catch {} 337 const id = href.replace(/^#\/?/, ""); 338 const note = window.document.getElementById(id); 339 if (note) { 340 return note.innerHTML; 341 } else { 342 return ""; 343 } 344 }); 345 } 346 const xrefs = window.document.querySelectorAll('a.quarto-xref'); 347 const processXRef = (id, note) => { 348 // Strip column container classes 349 const stripColumnClz = (el) => { 350 el.classList.remove("page-full", "page-columns"); 351 if (el.children) { 352 for (const child of el.children) {
353 stripColumnClz(child); 354 } 355 } 356 } 357 stripColumnClz(note) 358 if (id === null || id.startsWith('sec-')) { 359 // Special case sections, only their first couple elements 360 const container = document.createElement("div"); 361 if (note.children && note.children.length > 2) { 362 container.appendChild(note.children[0].cloneNode(true)); 363 for (let i = 1; i < note.children.length; i++) { 364 const child = note.children[i]; 365 if (child.tagName === "P" && child.innerText === "") { 366 continue; 367 } else { 368 container.appendChild(child.cloneNode(true)); 369 break; 370 } 371 } 372 if (window.Quarto?.typesetMath) { 373 window.Quarto.typesetMath(container); 374 } 375 return container.innerHTML 376 } else { 377 if (window.Quarto?.typesetMath) { 378 window.Quarto.typesetMath(note); 379 } 380 return note.innerHTML; 381 } 382 } else { 383 // Remove any anchor links if they are present 384 const anchorLink = note.querySelector('a.anchorjs-link'); 385 if (anchorLink) { 386 anchorLink.remove(); 387 } 388 if (window.Quarto?.typesetMath) { 389 window.Quarto.typesetMath(note); 390 } 391 if (note.classList.contains("callout")) { 392 return note.outerHTML; 393 } else { 394 return note.innerHTML; 395 } 396 } 397 } 398 for (var i=0; i<xrefs.length; i++) { 399 const xref = xrefs[i]; 400 tippyHover(xref, undefined, function(instance) { 401 instance.disable(); 402 let url = xref.getAttribute('href'); 403 let hash = undefined; 404 if (url.startsWith('#')) { 405 hash = url; 406 } else { 407 try { hash = new URL(url).hash; } catch {} 408 } 409 if (hash) { 410 const id = hash.replace(/^#\/?/, ""); 411 const note = window.document.getElementById(id); 412 if (note !== null) { 413 try { 414 const html = processXRef(id, note.cloneNode(true)); 415 instance.setContent(html); 416 } finally { 417 instance.enable(); 418 instance.show(); 419 } 420 } else { 421 // See if we can fetch this 422 fetch(url.split('#')[0]) 423 .then(res => res.text()) 424 .then(html => { 425 const parser = new DOMParser(); 426 const htmlDoc = parser.parseFromString(html, "text/html"); 427 const note = htmlDoc.getElementById(id); 428 if (note !== null) { 429 const html = processXRef(id, note); 430 instance.setContent(html); 431 } 432 }).finally(() => { 433 instance.enable(); 434 instance.show(); 435 }); 436 } 437 } else { 438 // See if we can fetch a full url (with no hash to target) 439 // This is a special case and we should probably do some content thinning / targeting 440 fetch(url) 441 .then(res => res.text()) 442 .then(html => { 443 const parser = new DOMParser(); 444 const htmlDoc = parser.parseFromString(html, "text/html"); 445 const note = htmlDoc.querySelector('main.content'); 446 if (note !== null) { 447 // This should only happen for chapter cross references 448 // (since there is no id in the URL) 449 // remove the first header 450 if (note.children.length > 0 && note.children[0].tagName === "HEADER") { 451 note.children[0].remove(); 452 } 453 const html = processXRef(null, note); 454 instance.setContent(html); 455 } 456 }).finally(() => { 457 instance.enable(); 458 instance.show(); 459 }); 460 } 461 }, function(instance) { 462 }); 463 } 464 let selectedAnnoteEl; 465 const selectorForAnnotation = ( cell, annotation) => { 466 let cellAttr = 'data-code-cell="' + cell + '"'; 467 let lineAttr = 'data-code-annotation="' + annotation + '"'; 468 const selector = 'span[' + cellAttr + '][' + lineAttr + ']'; 469 return selector; 470 } 471 const selectCodeLines = (annoteEl) => { 472 const doc = window.document; 473 const targetCell = annoteEl.getAttribute("data-target-cell"); 474 const targetAnnotation = annoteEl.getAttribute("data-target-annotation"); 475 const annoteSpan = window.document.querySelector(selectorForAnnotation(targetCell, targetAnnotation)); 476 const lines = annoteSpan.getAttribute("data-code-lines").split(","); 477 const lineIds = lines.map((line) => { 478 return targetCell + "-" + line; 479 }) 480 let top = null; 481 let height = null; 482 let parent = null; 483 if (lineIds.length > 0) { 484 //compute the position of the single el (top and bottom and make a div) 485 const el = window.document.getElementById(lineIds[0]); 486 top = el.offsetTop; 487 height = el.offsetHeight; 488 parent = el.parentElement.parentElement; 489 if (lineIds.length > 1) { 490 const lastEl = window.document.getElementById(lineIds[lineIds.length - 1]); 491 const bottom = lastEl.offsetTop + lastEl.offsetHeight; 492 height = bottom - top; 493 } 494 if (top !== null && height !== null && parent !== null) { 495 // cook up a div (if necessary) and position it 496 let div = window.document.getElementById("code-annotation-line-highlight"); 497 if (div === null) { 498 div = window.document.createElement("div"); 499 div.setAttribute("id", "code-annotation-line-highlight"); 500 div.style.position = 'absolute'; 501 parent.appendChild(div); 502 } 503 div.style.top = top - 2 + "px"; 504 div.style.height = height + 4 + "px"; 505 div.style.left = 0; 506 let gutterDiv = window.document.getElementById("code-annotation-line-highlight-gutter"); 507 if (gutterDiv === null) { 508 gutterDiv = window.document.createElement("div"); 509 gutterDiv.setAttribute("id", "code-annotation-line-highlight-gutter"); 510 gutterDiv.style.position = 'absolute'; 511 const codeCell = window.document.getElementById(targetCell); 512 const gutter = codeCell.querySelector('.code-annotation-gutter'); 513 gutter.appendChild(gutterDiv); 514 } 515 gutterDiv.style.top = top - 2 + "px"; 516 gutterDiv.style.height = height + 4 + "px"; 517 } 518 selectedAnnoteEl = annoteEl; 519 } 520 }; 521 const unselectCodeLines = () => { 522 const elementsIds = ["code-annotation-line-highlight", "code-annotation-line-highlight-gutter"]; 523 elementsIds.forEach((elId) => { 524 const div = window.document.getElementById(elId); 525 if (div) { 526 div.remove(); 527 } 528 }); 529 selectedAnnoteEl = undefined; 530 }; 531 // Handle positioning of the toggle 532 window.addEventListener( 533 "resize", 534 throttle(() => { 535 elRect = undefined; 536 if (selectedAnnoteEl) { 537 selectCodeLines(selectedAnnoteEl); 538 } 539 }, 10) 540 ); 541 function throttle(fn, ms) { 542 let throttle = false;
543 let timer; 544 return (...args) => { 545 if(!throttle) { // first call gets through 546 fn.apply(this, args); 547 throttle = true; 548 } else { // all the others get throttled 549 if(timer) clearTimeout(timer); // cancel #2 550 timer = setTimeout(() => { 551 fn.apply(this, args); 552 timer = throttle = false; 553 }, ms); 554 } 555 }; 556 } 557 // Attach click handler to the DT 558 const annoteDls = window.document.querySelectorAll('dt[data-target-cell]'); 559 for (const annoteDlNode of annoteDls) { 560 annoteDlNode.addEventListener('click', (event) => { 561 const clickedEl = event.target; 562 if (clickedEl !== selectedAnnoteEl) { 563 unselectCodeLines(); 564 const activeEl = window.document.querySelector('dt[data-target-cell].code-annotation-active'); 565 if (activeEl) { 566 activeEl.classList.remove('code-annotation-active'); 567 } 568 selectCodeLines(clickedEl); 569 clickedEl.classList.add('code-annotation-active'); 570 } else { 571 // Unselect the line 572 unselectCodeLines(); 573 clickedEl.classList.remove('code-annotation-active'); 574 } 575 }); 576 } 577 const findCites = (el) => { 578 const parentEl = el.parentElement; 579 if (parentEl) { 580 const cites = parentEl.dataset.cites; 581 if (cites) { 582 return { 583 el, 584 cites: cites.split(' ') 585 }; 586 } else { 587 return findCites(el.parentElement) 588 } 589 } else { 590 return undefined; 591 } 592 }; 593 var bibliorefs = window.document.querySelectorAll('a[role="doc-biblioref"]'); 594 for (var i=0; i<bibliorefs.length; i++) { 595 const ref = bibliorefs[i]; 596 const citeInfo = findCites(ref); 597 if (citeInfo) { 598 tippyHover(citeInfo.el, function() { 599 var popup = window.document.createElement('div'); 600 citeInfo.cites.forEach(function(cite) { 601 var citeDiv = window.document.createElement('div'); 602 citeDiv.classList.add('hanging-indent'); 603 citeDiv.classList.add('csl-entry'); 604 var biblioDiv = window.document.getElementById('ref-' + cite); 605 if (biblioDiv) { 606 citeDiv.innerHTML = biblioDiv.innerHTML; 607 } 608 popup.appendChild(citeDiv); 609 }); 610 return popup.innerHTML; 611 }); 612 } 613 } 614 }); 615 </script>
615 616</div> <!-- /content --> 617<footer class="footer"> 618 <div class="nav-footer"> 619 <div class="nav-footer-left"> 620<p>Created by <a href="https://www.gonzaga.edu/school-of-business-administration">Vivek H. Patil, Ph.D.</a>, Professor of Marketing and Director of Graduate Business Programs, Gonzaga University School of Business Administration.</p> 621</div> 622 <div class="nav-footer-center"> 623 624 </div> 625 <div class="nav-footer-right"> 626<p>Public data: NCCS · IRS 990 / ProPublica · Census ACS · CDC SVI</p> 627</div> 628 </div> 629</footer> 630 631 632 633 634</body></html>
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.