{"id":28,"date":"2025-12-05T16:53:00","date_gmt":"2025-12-05T21:53:00","guid":{"rendered":"https:\/\/www.bu.edu\/research-administration-training\/?page_id=28"},"modified":"2026-02-05T10:00:42","modified_gmt":"2026-02-05T15:00:42","slug":"training","status":"publish","type":"page","link":"https:\/\/www.bu.edu\/research-administration-training\/training\/","title":{"rendered":"Training"},"content":{"rendered":"\n<p>Training courses and materials that are relevant to research administration will span many different parts of Boston University.  This page provides a gateway not only to materials offered by Sponsored Programs but also as a hub for relevant content across the University.<\/p>\n\n\n\n<h2>BU&#8217;s Training Library<\/h2>\n\n\n\n<p>The below repository tracks many different courses, tools, walkthroughs, and job aids.  Content in this library is created by different entities, not limited to just Boston University.  This aggregation is provided to make it easier to find resources across the broader Research Administration landscape.  Some content will only be available behind a Kerberos login, and those are tagged as &#8220;Login Required.&#8221;<\/p>\n\n\n\n<p>For all media found in MyMedia, please be sure to click the &#8220;Attachments&#8221; tab to see any handouts that are available for the video.  NCURA usually provides slides and\/or a handout.<\/p>\n\n\n\n<p>Resources are tagged with RACC exams if they are considered to be helpful for those studying a particular body of knowledge. For information on the Spring 2026 CRA Study Group, please see <a href=\"https:\/\/www.bu.edu\/research\/2025\/12\/11\/second-annual-certified-research-administrator-cra-study-and-support-group\/\" data-type=\"URL\" data-id=\"https:\/\/www.bu.edu\/research\/2025\/12\/11\/second-annual-certified-research-administrator-cra-study-and-support-group\/\">the announcement<\/a>.<\/p>\n\n\n\n<style>\n.training-finder {\n  font-family: 'Source Sans 3', -apple-system, BlinkMacSystemFont, sans-serif;\n  max-width: 100%;\n}\n\n.training-controls {\n  display: flex;\n  flex-wrap: wrap;\n  gap: 12px;\n  margin-bottom: 24px;\n  padding: 20px;\n  background: #f5f5f5;\n  border-radius: 6px;\n}\n\n.training-search {\n  flex: 1 1 100%;\n  min-width: 200px;\n  padding: 10px 14px;\n  font-size: 15px;\n  font-family: inherit;\n  border: 1px solid #ccc;\n  border-radius: 4px;\n  transition: border-color 0.15s ease;\n}\n\n.training-search:focus {\n  outline: none;\n  border-color: #1E3D3B;\n  box-shadow: 0 0 0 3px rgba(30, 61, 59, 0.1);\n}\n\n.training-filters-row {\n  display: flex;\n  flex-wrap: wrap;\n  gap: 12px;\n  width: 100%;\n}\n\n.training-filter {\n  padding: 10px 14px;\n  font-size: 15px;\n  font-family: inherit;\n  border: 1px solid #ccc;\n  border-radius: 4px;\n  background: #fff;\n  cursor: pointer;\n  flex: 1;\n  min-width: 140px;\n}\n\n.training-filter:focus {\n  outline: none;\n  border-color: #1E3D3B;\n  box-shadow: 0 0 0 3px rgba(30, 61, 59, 0.1);\n}\n\n.training-results-count {\n  font-size: 14px;\n  color: #666;\n  margin-bottom: 16px;\n}\n\n.training-list {\n  display: flex;\n  flex-direction: column;\n  gap: 12px;\n}\n\n.training-card {\n  padding: 20px;\n  background: #fff;\n  border: 1px solid #e0e0e0;\n  border-radius: 6px;\n  transition: border-color 0.15s ease, box-shadow 0.15s ease;\n}\n\n.training-card:hover {\n  border-color: #ccc;\n  box-shadow: 0 2px 8px rgba(0,0,0,0.06);\n}\n\n.training-card-header {\n  display: flex;\n  justify-content: space-between;\n  align-items: flex-start;\n  gap: 16px;\n  margin-bottom: 8px;\n}\n\n.training-title {\n  font-size: 17px;\n  font-weight: 600;\n  color: #1E7B7B;\n  text-decoration: none;\n  line-height: 1.3;\n}\n\n.training-title:hover {\n  color: #155a5a;\n  text-decoration: underline;\n}\n\n.training-format {\n  font-size: 12px;\n  font-weight: 600;\n  padding: 4px 10px;\n  border-radius: 3px;\n  white-space: nowrap;\n  text-transform: uppercase;\n  letter-spacing: 0.03em;\n}\n\n\/* Format tag styles - desaturated *\/\n.format-live {\n  background: #D7E4D7;\n  color: #3D5A3D;\n}\n\n.format-recording {\n  background: #D4DEE8;\n  color: #3D4F5F;\n}\n\n.format-self-paced {\n  background: #E8DFD0;\n  color: #6B5D4A;\n}\n\n.format-walkthrough {\n  background: #DDD8E4;\n  color: #4A4459;\n}\n\n.format-job-aid {\n  background: #E0E0E0;\n  color: #555;\n}\n\n.format-tool {\n  background: #D4E4E3;\n  color: #3D5553;\n}\n\n\/* Fallback for future formats *\/\n.training-format:not(.format-live):not(.format-recording):not(.format-self-paced):not(.format-walkthrough):not(.format-job-aid):not(.format-tool) {\n  background: #E8E8E8;\n  color: #555;\n}\n\n.training-description {\n  font-size: 15px;\n  color: #444;\n  line-height: 1.5;\n  margin-bottom: 12px;\n}\n\n.training-meta {\n  display: flex;\n  flex-wrap: wrap;\n  gap: 12px 16px;\n  font-size: 13px;\n  color: #666;\n  align-items: center;\n}\n\n.training-meta-item {\n  display: flex;\n  align-items: center;\n  gap: 6px;\n}\n\n.training-meta-label {\n  font-weight: 600;\n  color: #888;\n}\n\n.training-category {\n  display: inline-block;\n  font-size: 12px;\n  font-weight: 600;\n  padding: 3px 8px;\n  background: #1E3D3B;\n  color: #fff;\n  border-radius: 3px;\n}\n\n\/* Access indicator styling *\/\n.training-access {\n  display: inline-block;\n  font-size: 12px;\n  font-weight: 600;\n  padding: 3px 8px;\n  border-radius: 3px;\n}\n\n.access-open {\n  background: #E8F5E9;\n  color: #2E7D32;\n}\n\n.access-login {\n  background: #F5F5F5;\n  color: #666;\n}\n\n\/* Tags styling - bundled *\/\n.training-tags {\n  display: flex;\n  flex-wrap: wrap;\n  gap: 8px;\n  margin-top: 12px;\n  padding-top: 12px;\n  border-top: 1px solid #eee;\n}\n\n.training-tag-group {\n  display: inline-flex;\n  align-items: center;\n  font-size: 13px;\n  color: #555;\n}\n\n.training-tag-group-label {\n  font-weight: 600;\n  color: #666;\n  margin-right: 4px;\n}\n\n.training-tag-group-values {\n  color: #333;\n}\n\n.training-empty {\n  text-align: center;\n  padding: 48px 24px;\n  color: #666;\n}\n\n.training-empty-icon {\n  font-size: 48px;\n  margin-bottom: 16px;\n  opacity: 0.3;\n}\n\n.training-clear {\n  background: none;\n  border: none;\n  color: #1E7B7B;\n  font-size: 14px;\n  font-family: inherit;\n  cursor: pointer;\n  padding: 0;\n  text-decoration: underline;\n}\n\n.training-clear:hover {\n  color: #155a5a;\n}\n\n.training-loading {\n  text-align: center;\n  padding: 48px 24px;\n  color: #666;\n}\n\n.training-error {\n  text-align: center;\n  padding: 24px;\n  background: #FFF3F3;\n  border: 1px solid #E0B0B0;\n  border-radius: 6px;\n  color: #993333;\n}\n\n@media (max-width: 600px) {\n  .training-filters-row {\n    flex-direction: column;\n  }\n  \n  .training-filter {\n    width: 100%;\n  }\n\n  .training-card-header {\n    flex-direction: column-reverse;\n    gap: 8px;\n  }\n\n  .training-format {\n    align-self: flex-start;\n  }\n}\n<\/style>\n\n<!-- Papa Parse library for CSV parsing -->\n<script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/PapaParse\/5.4.1\/papaparse.min.js\"><\/script>\n\n<div class=\"training-finder\">\n  <div class=\"training-controls\">\n    <input type=\"text\" class=\"training-search\" placeholder=\"Search trainings...\" aria-label=\"Search trainings\">\n    <div class=\"training-filters-row\">\n      <select class=\"training-filter\" id=\"filter-category\" aria-label=\"Filter by category\">\n        <option value=\"\">All Categories<\/option>\n      <\/select>\n      <select class=\"training-filter\" id=\"filter-tag\" aria-label=\"Filter by topic\">\n        <option value=\"\">All Topics<\/option>\n      <\/select>\n      <select class=\"training-filter\" id=\"filter-certification\" aria-label=\"Filter by RACC certification\">\n        <option value=\"\">All RACC Certifications<\/option>\n      <\/select>\n    <\/div>\n    <div class=\"training-filters-row\">\n      <select class=\"training-filter\" id=\"filter-provider\" aria-label=\"Filter by provider\">\n        <option value=\"\">All Providers<\/option>\n      <\/select>\n      <select class=\"training-filter\" id=\"filter-format\" aria-label=\"Filter by format\">\n        <option value=\"\">All Formats<\/option>\n      <\/select>\n      <select class=\"training-filter\" id=\"filter-access\" aria-label=\"Filter by access\">\n        <option value=\"\">All Access Levels<\/option>\n        <option value=\"open\">No Login Required<\/option>\n        <option value=\"login\">Login Required<\/option>\n      <\/select>\n    <\/div>\n  <\/div>\n\n  <div class=\"training-results-count\"><\/div>\n  <div class=\"training-list\">\n    <div class=\"training-loading\">Loading trainings&#8230;<\/div>\n  <\/div>\n<\/div>\n\n<script>\n(function() {\n  \/\/ ============================================\n  \/\/ CSV URL - Replace with your media library URL\n  \/\/ ============================================\n  const CSV_URL = 'https:\/\/www.bu.edu\/research-administration-training\/files\/2025\/12\/training-library.csv';\n  \n  let trainings = [];\n\n  const searchInput = document.querySelector('.training-search');\n  const categoryFilter = document.getElementById('filter-category');\n  const providerFilter = document.getElementById('filter-provider');\n  const formatFilter = document.getElementById('filter-format');\n  const tagFilter = document.getElementById('filter-tag');\n  const certFilter = document.getElementById('filter-certification');\n  const accessFilter = document.getElementById('filter-access');\n  const listContainer = document.querySelector('.training-list');\n  const resultsCount = document.querySelector('.training-results-count');\n\n  \/\/ Parse CSV row into training object\n  function parseRow(row) {\n    const tags = [];\n    \n    \/\/ Parse pipe-separated tag fields\n    if (row.sponsors) {\n      row.sponsors.split('|').forEach(s => {\n        if (s.trim()) tags.push({ label: 'Sponsor', value: s.trim() });\n      });\n    }\n    if (row.systems) {\n      row.systems.split('|').forEach(s => {\n        if (s.trim()) tags.push({ label: 'System', value: s.trim() });\n      });\n    }\n    if (row.topics) {\n      row.topics.split('|').forEach(s => {\n        if (s.trim()) tags.push({ label: 'Topic', value: s.trim() });\n      });\n    }\n    if (row.certifications) {\n      row.certifications.split('|').forEach(s => {\n        if (s.trim()) tags.push({ label: 'Certification', value: s.trim() });\n      });\n    }\n\n    return {\n      title: row.title || '',\n      url: row.url || '#',\n      description: row.description || '',\n      category: row.category || '',\n      format: row.format || '',\n      provider: row.provider || '',\n      duration: row.duration || '',\n      loginRequired: row.loginRequired === 'true' || row.loginRequired === 'TRUE' || row.loginRequired === '1',\n      tags: tags\n    };\n  }\n\n  \/\/ Load and parse CSV\n  function loadCSV() {\n    Papa.parse(CSV_URL, {\n      download: true,\n      header: true,\n      skipEmptyLines: true,\n      complete: function(results) {\n        if (results.errors.length > 0) {\n          console.error('CSV parsing errors:', results.errors);\n        }\n        \n        trainings = results.data.map(parseRow).filter(t => t.title);\n        populateFilters();\n        renderTrainings(trainings);\n      },\n      error: function(error) {\n        console.error('CSV loading error:', error);\n        listContainer.innerHTML = \n          '<div class=\"training-error\">' +\n            '<p><strong>Unable to load trainings.<\/strong><\/p>' +\n            '<p>Please try refreshing the page.<\/p>' +\n          '<\/div>';\n      }\n    });\n  }\n\n  \/\/ Helper to pluralize labels\n  function pluralizeLabel(label, count) {\n    if (count <= 1) return label;\n    if (label.endsWith('y')) return label.slice(0, -1) + 'ies';\n    if (label.endsWith('s')) return label + 'es';\n    return label + 's';\n  }\n\n  \/\/ Group tags by label\n  function groupTags(tags) {\n    const groups = {};\n    tags.forEach(tag => {\n      if (!groups[tag.label]) {\n        groups[tag.label] = [];\n      }\n      groups[tag.label].push(tag.value);\n    });\n    return groups;\n  }\n\n  function populateFilters() {\n    const categories = [...new Set(trainings.map(t => t.category))].filter(Boolean).sort();\n    const providers = [...new Set(trainings.map(t => t.provider))].filter(Boolean).sort();\n    const formats = [...new Set(trainings.map(t => t.format))].filter(Boolean).sort();\n    \n    \/\/ Collect tag values, separating certifications from other topics\n    const certValues = [...new Set(\n      trainings.flatMap(t => t.tags.filter(tag => tag.label === 'Certification').map(tag => tag.value))\n    )].sort();\n    \n    const tagValues = [...new Set(\n      trainings.flatMap(t => t.tags.filter(tag => tag.label !== 'Certification').map(tag => tag.value))\n    )].sort();\n\n    categories.forEach(cat => {\n      const option = document.createElement('option');\n      option.value = cat;\n      option.textContent = cat;\n      categoryFilter.appendChild(option);\n    });\n\n    providers.forEach(prov => {\n      const option = document.createElement('option');\n      option.value = prov;\n      option.textContent = prov;\n      providerFilter.appendChild(option);\n    });\n\n    formats.forEach(fmt => {\n      const option = document.createElement('option');\n      option.value = fmt;\n      option.textContent = fmt;\n      formatFilter.appendChild(option);\n    });\n\n    tagValues.forEach(tag => {\n      const option = document.createElement('option');\n      option.value = tag;\n      option.textContent = tag;\n      tagFilter.appendChild(option);\n    });\n\n    certValues.forEach(cert => {\n      const option = document.createElement('option');\n      option.value = cert;\n      option.textContent = cert;\n      certFilter.appendChild(option);\n    });\n  }\n\n  function renderTrainings(filtered) {\n    if (filtered.length === 0) {\n      listContainer.innerHTML = \n        '<div class=\"training-empty\">' +\n          '<div class=\"training-empty-icon\">\ud83d\udcda<\/div>' +\n          '<p>No trainings match your search.<\/p>' +\n          '<button class=\"training-clear\" onclick=\"clearFilters()\">Clear filters<\/button>' +\n        '<\/div>';\n    } else {\n      listContainer.innerHTML = filtered.map(t => {\n        \/\/ Build bundled tags HTML\n        let tagsHtml = '';\n        if (t.tags && t.tags.length > 0) {\n          const grouped = groupTags(t.tags);\n          const tagGroups = Object.entries(grouped).map(([label, values]) => {\n            const pluralLabel = pluralizeLabel(label, values.length);\n            return '<span class=\"training-tag-group\">' +\n              '<span class=\"training-tag-group-label\">' + pluralLabel + ':<\/span>' +\n              '<span class=\"training-tag-group-values\">' + values.join(', ') + '<\/span>' +\n            '<\/span>';\n          }).join(' &nbsp;\u00b7&nbsp; ');\n\n          tagsHtml = '<div class=\"training-tags\">' + tagGroups + '<\/div>';\n        }\n\n        return '<div class=\"training-card\">' +\n          '<div class=\"training-card-header\">' +\n            '<a href=\"' + t.url + '\" class=\"training-title\">' + t.title + '<\/a>' +\n            '<span class=\"training-format format-' + t.format.toLowerCase().replace(' ', '-') + '\">' + t.format + '<\/span>' +\n          '<\/div>' +\n          '<p class=\"training-description\">' + t.description + '<\/p>' +\n          '<div class=\"training-meta\">' +\n            '<span class=\"training-category\">' + t.category + '<\/span>' +\n            '<span class=\"training-meta-item\">' +\n              '<span class=\"training-meta-label\">Provider:<\/span> ' + t.provider +\n            '<\/span>' +\n            '<span class=\"training-meta-item\">' +\n              '<span class=\"training-meta-label\">Duration:<\/span> ' + t.duration +\n            '<\/span>' +\n            '<span class=\"training-access ' + (t.loginRequired ? 'access-login' : 'access-open') + '\">' +\n              (t.loginRequired ? 'Login Required' : 'Open Access') +\n            '<\/span>' +\n          '<\/div>' +\n          tagsHtml +\n        '<\/div>';\n      }).join('');\n    }\n\n    const total = trainings.length;\n    const shown = filtered.length;\n    if (shown === total) {\n      resultsCount.textContent = 'Showing all ' + total + ' trainings';\n    } else {\n      resultsCount.textContent = 'Showing ' + shown + ' of ' + total + ' trainings';\n    }\n  }\n\n  function filterTrainings() {\n    const searchTerm = searchInput.value.toLowerCase();\n    const categoryValue = categoryFilter.value;\n    const providerValue = providerFilter.value;\n    const formatValue = formatFilter.value;\n    const tagValue = tagFilter.value;\n    const certValue = certFilter.value;\n    const accessValue = accessFilter.value;\n\n    const filtered = trainings.filter(t => {\n      const matchesSearch = !searchTerm || \n        t.title.toLowerCase().includes(searchTerm) ||\n        t.description.toLowerCase().includes(searchTerm) ||\n        t.provider.toLowerCase().includes(searchTerm) ||\n        t.category.toLowerCase().includes(searchTerm) ||\n        t.tags.some(tag => tag.value.toLowerCase().includes(searchTerm));\n      \n      const matchesCategory = !categoryValue || t.category === categoryValue;\n      const matchesProvider = !providerValue || t.provider === providerValue;\n      const matchesFormat = !formatValue || t.format === formatValue;\n      const matchesTag = !tagValue || t.tags.some(tag => tag.value === tagValue);\n      const matchesCert = !certValue || t.tags.some(tag => tag.label === 'Certification' && tag.value === certValue);\n      const matchesAccess = !accessValue || \n        (accessValue === 'open' && !t.loginRequired) || \n        (accessValue === 'login' && t.loginRequired);\n\n      return matchesSearch && matchesCategory && matchesProvider && matchesFormat && matchesTag && matchesCert && matchesAccess;\n    });\n\n    renderTrainings(filtered);\n  }\n\n  window.clearFilters = function() {\n    searchInput.value = '';\n    categoryFilter.value = '';\n    providerFilter.value = '';\n    formatFilter.value = '';\n    tagFilter.value = '';\n    certFilter.value = '';\n    accessFilter.value = '';\n    filterTrainings();\n  };\n\n  searchInput.addEventListener('input', filterTrainings);\n  categoryFilter.addEventListener('change', filterTrainings);\n  providerFilter.addEventListener('change', filterTrainings);\n  formatFilter.addEventListener('change', filterTrainings);\n  tagFilter.addEventListener('change', filterTrainings);\n  certFilter.addEventListener('change', filterTrainings);\n  accessFilter.addEventListener('change', filterTrainings);\n\n  \/\/ Initialize\n  loadCSV();\n})();\n<\/script>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Training courses and materials that are relevant to research administration will span many different parts of Boston University. This page provides a gateway not only to materials offered by Sponsored Programs but also as a hub for relevant content across the University. BU&#8217;s Training Library The below repository tracks many different courses, tools, walkthroughs, and [&hellip;]<\/p>\n","protected":false},"author":25620,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":[],"_links":{"self":[{"href":"https:\/\/www.bu.edu\/research-administration-training\/wp-json\/wp\/v2\/pages\/28"}],"collection":[{"href":"https:\/\/www.bu.edu\/research-administration-training\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.bu.edu\/research-administration-training\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.bu.edu\/research-administration-training\/wp-json\/wp\/v2\/users\/25620"}],"replies":[{"embeddable":true,"href":"https:\/\/www.bu.edu\/research-administration-training\/wp-json\/wp\/v2\/comments?post=28"}],"version-history":[{"count":10,"href":"https:\/\/www.bu.edu\/research-administration-training\/wp-json\/wp\/v2\/pages\/28\/revisions"}],"predecessor-version":[{"id":316,"href":"https:\/\/www.bu.edu\/research-administration-training\/wp-json\/wp\/v2\/pages\/28\/revisions\/316"}],"wp:attachment":[{"href":"https:\/\/www.bu.edu\/research-administration-training\/wp-json\/wp\/v2\/media?parent=28"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}