blacklight 9.0.0.beta3 → 9.0.0.beta5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop_todo.yml +24 -25
  3. data/VERSION +1 -1
  4. data/app/assets/builds/blacklight.css +34 -20
  5. data/app/assets/javascripts/blacklight/blacklight.esm.js +4 -4
  6. data/app/assets/javascripts/blacklight/blacklight.esm.js.map +1 -1
  7. data/app/assets/javascripts/blacklight/blacklight.js +4 -4
  8. data/app/assets/javascripts/blacklight/blacklight.js.map +1 -1
  9. data/app/assets/stylesheets/blacklight/_facets.scss +35 -27
  10. data/app/components/blacklight/advanced_search_form_component.html.erb +4 -4
  11. data/app/components/blacklight/advanced_search_form_component.rb +2 -2
  12. data/app/components/blacklight/document/bookmark_component.html.erb +1 -1
  13. data/app/components/blacklight/document/bookmark_component.rb +9 -3
  14. data/app/components/blacklight/document/group_component.html.erb +1 -1
  15. data/app/components/blacklight/facet_item_pivot_component.rb +3 -3
  16. data/app/components/blacklight/facets/checkboxes_component.html.erb +4 -4
  17. data/app/components/blacklight/facets/field_component.html.erb +0 -2
  18. data/app/components/blacklight/facets/list_component.html.erb +2 -2
  19. data/app/components/blacklight/facets/list_component.rb +7 -2
  20. data/app/components/blacklight/facets/pivot_list_component.rb +14 -0
  21. data/app/components/blacklight/facets/suggest_component.html.erb +1 -1
  22. data/app/components/blacklight/search_bar_component.html.erb +1 -1
  23. data/app/components/blacklight/top_navbar_component.html.erb +1 -1
  24. data/app/controllers/concerns/blacklight/bookmarks.rb +10 -0
  25. data/app/controllers/concerns/blacklight/catalog.rb +6 -1
  26. data/app/javascript/blacklight-frontend/button_focus.js +1 -1
  27. data/app/javascript/blacklight-frontend/checkbox_submit.js +1 -1
  28. data/app/javascript/blacklight-frontend/modal.js +2 -2
  29. data/app/views/blacklight/nav/_bookmark.html.erb +1 -1
  30. data/app/views/catalog/_email_form.html.erb +4 -4
  31. data/app/views/catalog/_sms_form.html.erb +4 -4
  32. data/app/views/catalog/advanced_search.html.erb +1 -1
  33. data/app/views/layouts/blacklight/base.html.erb +1 -1
  34. data/config/locales/blacklight.it.yml +1 -1
  35. data/lib/blacklight/configuration/facet_field.rb +1 -0
  36. data/lib/blacklight/search_state.rb +2 -0
  37. data/lib/blacklight.rb +1 -1
  38. data/lib/generators/blacklight/templates/catalog_controller.rb +3 -1
  39. data/package.json +1 -1
  40. data/spec/components/blacklight/facet_item_pivot_component_spec.rb +1 -1
  41. data/spec/components/blacklight/facets/list_component_spec.rb +5 -0
  42. data/spec/components/blacklight/facets/pivot_list_component_spec.rb +47 -0
  43. data/spec/features/advanced_search_spec.rb +3 -1
  44. data/spec/features/facets_spec.rb +5 -5
  45. data/spec/features/search_filters_spec.rb +3 -1
  46. metadata +6 -4
  47. data/app/views/catalog/_facet_pivot.html.erb +0 -3
@@ -1 +1 @@
1
- {"version":3,"file":"blacklight.js","sources":["../../../javascript/blacklight-frontend/checkbox_submit.js","../../../javascript/blacklight-frontend/bookmark_toggle.js","../../../javascript/blacklight-frontend/button_focus.js","../../../javascript/blacklight-frontend/debounce.js","../../../javascript/blacklight-frontend/facet_suggest.js","../../../javascript/blacklight-frontend/modal.js","../../../javascript/blacklight-frontend/search_context.js","../../../javascript/blacklight-frontend/core.js","../../../javascript/blacklight-frontend/index.js"],"sourcesContent":["/* Converts a \"toggle\" form, with single submit button to add/remove\n something, like used for Bookmarks, into an AJAXy checkbox instead.\n Apply to a form. Does require certain assumption about the form:\n 1) The same form 'action' href must be used for both ADD and REMOVE\n actions, with the different being the hidden input name=\"_method\"\n being set to \"put\" or \"delete\" -- that's the Rails method to pretend\n to be doing a certain HTTP verb. So same URL, PUT to add, DELETE\n to remove. This plugin assumes that.\n Plus, the form this is applied to should provide a data-doc-id\n attribute (HTML5-style doc-*) that contains the id/primary key\n of the object in question -- used by plugin for a unique value for\n DOM id's.\n Uses HTML for a checkbox compatible with Bootstrap 4.\n new CheckboxSubmit(document.querySelector('form.something')).render()\n*/\nexport default class CheckboxSubmit {\n constructor(form) {\n this.form = form\n }\n\n clicked(evt) {\n this.spanTarget.innerHTML = this.form.getAttribute('data-inprogress')\n this.labelTarget.setAttribute('disabled', 'disabled');\n this.checkboxTarget.setAttribute('disabled', 'disabled');\n fetch(this.formTarget.getAttribute('action'), {\n body: new FormData(this.formTarget),\n method: this.formTarget.getAttribute('method').toUpperCase(),\n headers: {\n 'Accept': 'application/json',\n 'X-Requested-With': 'XMLHttpRequest',\n 'X-CSRF-Token': document.querySelector('meta[name=csrf-token]')?.content\n }\n }).then((response) => {\n if (response.ok) return response.json();\n return Promise.reject('response was not ok')\n }).then((json) => {\n this.labelTarget.removeAttribute('disabled')\n this.checkboxTarget.removeAttribute('disabled')\n // For accessibility return keyboard focus \n // back to the checkbox after form submission\n this.checkboxTarget.focus()\n this.updateStateFor(!this.checked)\n this.bookmarksCounter().forEach(counter => {\n counter.innerHTML = json.bookmarks.count;\n });\n\n var e = new CustomEvent('bookmark.blacklight', { detail: { checked: !this.checked } });\n window.dispatchEvent(e)\n }).catch((error) => {\n this.handleError(error)\n })\n }\n\n get checked() {\n return (this.form.querySelectorAll('input[name=_method][value=delete]').length != 0)\n }\n\n get formTarget() {\n return this.form\n }\n\n get labelTarget() {\n return this.form.querySelector('[data-checkboxsubmit-target=\"label\"]')\n }\n\n get checkboxTarget() {\n return this.form.querySelector('[data-checkboxsubmit-target=\"checkbox\"]')\n }\n\n get spanTarget() {\n return this.form.querySelector('[data-checkboxsubmit-target=\"span\"]')\n }\n\n bookmarksCounter() {\n return document.querySelectorAll('[data-role=\"bookmark-counter\"]')\n }\n\n handleError() {\n alert(\"Unable to save the bookmark at this time.\")\n }\n\n updateStateFor(state) {\n if (state) { this.checkboxTarget.setAttribute('checked', state) }\n else { this.checkboxTarget.removeAttribute('checked') }\n\n if (state) {\n this.labelTarget.classList.add('checked')\n //Set the Rails hidden field that fakes an HTTP verb\n //properly for current state action.\n this.formTarget.querySelector('input[name=_method]').value = 'delete'\n this.spanTarget.innerHTML = this.form.getAttribute('data-present')\n } else {\n this.labelTarget.classList.remove('checked')\n this.formTarget.querySelector('input[name=_method]').value = 'put'\n this.spanTarget.innerHTML = this.form.getAttribute('data-absent')\n }\n }\n}\n","import CheckboxSubmit from 'blacklight-frontend/checkbox_submit'\n\nconst BookmarkToggle = (e) => {\n const elementType = e.target.getAttribute('data-checkboxsubmit-target');\n if (elementType == 'checkbox' || elementType == 'label') {\n const form = e.target.closest('form');\n if (form) new CheckboxSubmit(form).clicked(e);\n if (e.code == 'Space') e.preventDefault();\n }\n};\n\ndocument.addEventListener('click', BookmarkToggle);\ndocument.addEventListener('keydown', function (e) {\n if (e.key === 'Enter' || e.code == 'Space') { BookmarkToggle(e); } }\n);\n\nexport default BookmarkToggle\n","const ButtonFocus = (e) => {\n // Button clicks should change focus. As of 10/3/19, Firefox for Mac and\n // Safari both do not set focus to a button on button click.\n // See https://zellwk.com/blog/inconsistent-button-behavior/ for background information\n if (e.target.matches('[data-toggle=\"collapse\"]') || e.target.matches('[data-bs-toggle=\"collapse\"]')) {\n e.target.focus()\n }\n}\n\ndocument.addEventListener('click', ButtonFocus)\n\nexport default ButtonFocus\n","// Usage:\n// ```\n// const basicFunction = (entry) => console.log(entry)\n// const debounced = debounce(basicFunction(\"I should only be called once\"));\n//\n// debounced // does NOT print to the screen because it is invoked again less than 200 milliseconds later\n// debounced // does print to the screen\n// ```\nexport default function debounce(func, timeout = 200) {\n let timer;\n return (...args) => {\n clearTimeout(timer);\n timer = setTimeout(() => { func.apply(this, args); }, timeout);\n };\n}\n","import debounce from \"blacklight-frontend/debounce\";\n\nconst FacetSuggest = async (e) => {\n if (e.target.matches('.facet-suggest')) {\n const queryFragment = e.target.value?.trim();\n const facetField = e.target.dataset.facetField;\n const facetArea = document.querySelector('.facet-extended-list');\n const prevNextLinks = document.querySelectorAll('.prev_next_links');\n\n if (!facetField) { return; }\n\n // Get the search params from the current query so the facet suggestions\n // can retain that context.\n const facetSearchContext = e.target.dataset.facetSearchContext;\n const url = new URL(facetSearchContext, window.location.origin);\n\n // Drop facet.page so a filtered suggestion list will always start on page 1\n url.searchParams.delete('facet.page');\n const facetSearchParams = url.searchParams.toString();\n\n const urlToFetch = `/catalog/facet_suggest/${facetField}/${queryFragment}?${facetSearchParams}`;\n\n const response = await fetch(urlToFetch);\n if (response.ok) {\n const blob = await response.blob()\n const text = await blob.text()\n\n if (text && facetArea) {\n facetArea.innerHTML = text\n }\n }\n\n // Hide the prev/next links when a user enters text in the facet\n // suggestion input. They don't work with a filtered list.\n prevNextLinks.forEach(element => {\n element.classList.toggle('invisible', !!queryFragment);\n });\n\n // Add a class to distinguish suggested facet values vs. regular.\n facetArea.classList.toggle('facet-suggestions', !!queryFragment);\n }\n};\n\ndocument.addEventListener('input', debounce(FacetSuggest));\n\nexport default FacetSuggest\n","/*\n The blacklight modal plugin can display some interactions inside a Bootstrap\n modal window, including some multi-page interactions.\n\n It supports unobtrusive Javascript, where a link or form that would have caused\n a new page load is changed to display it's results inside a modal dialog,\n by this plugin. The plugin assumes there is a Bootstrap modal div\n on the page with id #blacklight-modal to use as the modal -- the standard Blacklight\n layout provides this.\n\n To make a link or form have their results display inside a modal, add\n `data-blacklight-modal=\"trigger\"` to the link or form. (Note, form itself not submit input)\n With Rails link_to helper, you'd do that like:\n\n link_to something, link, data: { blacklight_modal: \"trigger\" }\n\n The results of the link href or form submit will be displayed inside\n a modal -- they should include the proper HTML markup for a bootstrap modal's\n contents. Also, you ordinarily won't want the Rails template with wrapping\n navigational elements to be used. The Rails controller could suppress\n the layout when a JS AJAX request is detected, OR the response\n can include a `<div data-blacklight-modal=\"container\">` -- only the contents\n of the container will be placed inside the modal, the rest of the\n page will be ignored.\n\n Link or forms inside the modal will ordinarily cause page loads\n when they are triggered. However, if you'd like their results\n to stay within the modal, just add `data-blacklight-modal=\"preserve\"`\n to the link or form.\n\n Here's an example of what might be returned, demonstrating most of the devices available:\n\n <div data-blacklight-modal=\"container\">\n <div class=\"modal-header\">\n <button type=\"button\" class=\"close\" data-bl-dismiss=\"modal\" aria-hidden=\"true\">×</button>\n <h3 class=\"modal-title\">Request Placed</h3>\n </div>\n\n <div class=\"modal-body\">\n <p>Some message</p>\n <%= link_to \"This result will still be within modal\", some_link, data: { blacklight_modal: \"preserve\" } %>\n </div>\n\n\n <div class=\"modal-footer\">\n <button type=\"button\" class=\"btn btn-secondary\" data-bl-dismiss=\"modal\">Close</button>\n </div>\n </div>\n\n\n One additional feature. If the content returned from the AJAX form submission\n can be a turbo-stream that defines some HTML fragementsand where on the page to put them:\n https://turbo.hotwired.dev/handbook/streams\n*/\n\nconst Modal = (() => {\n const modal = {}\n\n // a Bootstrap modal div that should be already on the page hidden\n modal.modalSelector = '#blacklight-modal';\n\n // Trigger selectors identify forms or hyperlinks that should open\n // inside a modal dialog.\n modal.triggerLinkSelector = 'a[data-blacklight-modal~=trigger]';\n\n // preserve selectors identify forms or hyperlinks that, if activated already\n // inside a modal dialog, should have destinations remain inside the modal -- but\n // won't trigger a modal if not already in one.\n //\n // No need to repeat selectors from trigger selectors, those will already\n // be preserved. MUST be manually prefixed with the modal selector,\n // so they only apply to things inside a modal.\n modal.preserveLinkSelector = modal.modalSelector + ' a[data-blacklight-modal~=preserve]';\n\n modal.containerSelector = '[data-blacklight-modal~=container]';\n\n // Called on fatal failure of ajax load, function returns content\n // to show to user in modal. Right now called only for network errors.\n modal.onFailure = function (error) {\n console.error('Server error:', this.url, error);\n\n const contents = `<div class=\"modal-header\">\n <div class=\"modal-title\">There was a problem with your request.</div>\n <button type=\"button\" class=\"blacklight-modal-close btn-close\" data-bl-dismiss=\"modal\" aria-label=\"Close\">\n </button>\n </div>\n <div class=\"modal-body\">\n <p>Expected a successful response from the server, but got an error</p>\n <pre>${this.url}\\n${error}</pre>\n </div>`\n\n modal.target().querySelector('.modal-content').innerHTML = contents\n\n modal.show();\n }\n\n // Add the passed in contents to the modal and display it.\n // We have specific handling so that scripts returned from the ajax call are executed.\n // This enables adding a script like recaptcha to prevent bots from sending emails.\n modal.receiveAjax = function (contents) {\n const domparser = new DOMParser();\n const dom = domparser.parseFromString(contents, \"text/html\")\n // If there is a containerSelector on the document, use its children.\n let elements = dom.querySelectorAll(`${modal.containerSelector} > *`)\n const frag = document.createDocumentFragment()\n if (elements.length == 0) {\n // If the containerSelector wasn't found, use the whole document\n elements = dom.body.childNodes\n }\n elements.forEach((el) => frag.appendChild(el))\n modal.activateScripts(frag)\n\n modal.target().querySelector('.modal-content').replaceChildren(frag)\n\n // send custom event with the modal dialog div as the target\n var e = new CustomEvent('loaded.blacklight.blacklight-modal', { bubbles: true, cancelable: true });\n modal.target().dispatchEvent(e)\n\n // if they did preventDefault, don't show the dialog\n if (e.defaultPrevented) return;\n modal.show();\n };\n\n // DOMParser doesn't allow scripts to be executed. This fixes that.\n modal.activateScripts = function (frag) {\n frag.querySelectorAll('script').forEach((script) => {\n const fixedScript = document.createElement('script')\n fixedScript.src = script.src\n fixedScript.async = false\n script.parentNode.replaceChild(fixedScript, script)\n })\n }\n\n modal.modalAjaxLinkClick = function(e) {\n e.preventDefault();\n const href = e.target.closest('a').getAttribute('href')\n fetch(href)\n .then(response => {\n if (!response.ok) {\n throw new TypeError(\"Request failed\");\n }\n return response.text();\n })\n .then(data => modal.receiveAjax(data))\n .catch(error => modal.onFailure(error))\n };\n\n modal.setupModal = function() {\n // Register several click handlers in ONE event handler for efficiency\n //\n // * close button OR click on backdrop (modal.modalSelector) closes modal\n // * trigger and preserve link in modal functionality -- if somethign matches both trigger and\n // preserve, still only called once.\n document.addEventListener('click', (e) => {\n if (e.target.closest(`${modal.triggerLinkSelector}, ${modal.preserveLinkSelector}`))\n modal.modalAjaxLinkClick(e)\n else if (e.target.matches(`${modal.modalSelector}`) || e.target.closest('[data-bl-dismiss=\"modal\"]'))\n modal.hide()\n })\n };\n\n modal.hide = function (el) {\n const dom = modal.target();\n\n if (!dom.open) return\n\n var e = new CustomEvent('hide.blacklight.blacklight-modal', { bubbles: true, cancelable: true });\n dom.dispatchEvent(e)\n\n dom.close()\n\n // Turn body scrolling back to what it was\n document.body.style[\"overflow\"] = modal.originalBodyOverflow;\n document.body.style[\"padding-right\"] = modal.originalBodyPaddingRight;\n modal.originalBodyOverflow = undefined;\n modal.originalBodyPaddingRight = undefined;\n }\n\n modal.show = function(el) {\n const dom = modal.target();\n\n if (dom.open) return\n\n var e = new CustomEvent('show.blacklight.blacklight-modal', { bubbles: true, cancelable: true });\n dom.dispatchEvent(e)\n\n dom.showModal()\n\n // Turn off body scrolling\n modal.originalBodyOverflow = document.body.style['overflow'];\n modal.originalBodyPaddingRight = document.body.style['padding-right'];\n document.body.style[\"overflow\"] = \"hidden\"\n document.body.style[\"padding-right\"] = \"0px\"\n }\n\n modal.target = function() {\n return document.querySelector(modal.modalSelector);\n }\n\n modal.setupModal()\n\n return modal;\n})()\n\nexport default Modal\n","const SearchContext = (e) => {\n const contextLink = e.target.closest('[data-context-href]')\n if (contextLink) {\n SearchContext.handleSearchContextMethod.call(contextLink, e)\n }\n}\n\nSearchContext.csrfToken = () => document.querySelector('meta[name=csrf-token]')?.content\nSearchContext.csrfParam = () => document.querySelector('meta[name=csrf-param]')?.content\n\n// this is the Rails.handleMethod with a couple adjustments, described inline:\n// first, we're attaching this directly to the event handler, so we can check for meta-keys\nSearchContext.handleSearchContextMethod = function(event) {\n const link = this\n\n // instead of using the normal href, we need to use the context href instead\n let href = link.getAttribute('data-context-href')\n let target = link.getAttribute('target')\n let csrfToken = SearchContext.csrfToken()\n let csrfParam = SearchContext.csrfParam()\n let form = document.createElement('form')\n form.method = 'post'\n form.action = href\n\n\n let formContent = `<input name=\"_method\" value=\"post\" type=\"hidden\" />\n <input name=\"redirect\" value=\"${link.getAttribute('href')}\" type=\"hidden\" />`\n\n // check for meta keys.. if set, we should open in a new tab\n if(event.metaKey || event.ctrlKey) {\n form.dataset.turbo = \"false\";\n target = '_blank';\n }\n\n if (csrfParam !== undefined && csrfToken !== undefined) {\n formContent += `<input name=\"${csrfParam}\" value=\"${csrfToken}\" type=\"hidden\" />`\n }\n\n // Must trigger submit by click on a button, else \"submit\" event handler won't work!\n // https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/submit\n formContent += '<input type=\"submit\" />'\n\n if (target) { form.setAttribute('target', target); }\n\n form.style.display = 'none'\n form.innerHTML = formContent\n document.body.appendChild(form)\n form.querySelector('[type=\"submit\"]').click()\n\n event.preventDefault()\n};\n\ndocument.addEventListener('click', SearchContext)\n\nexport default SearchContext\n","const Core = function() {\n const buffer = new Array;\n return {\n onLoad: function(func) {\n buffer.push(func);\n },\n\n activate: function() {\n for(let i = 0; i < buffer.length; i++) {\n buffer[i].call();\n }\n },\n\n listeners: function () {\n const listeners = [];\n if (typeof Turbo !== 'undefined') {\n listeners.push('turbo:load', 'turbo:frame-load');\n } else {\n listeners.push('DOMContentLoaded');\n }\n\n return listeners;\n }\n };\n}();\n\n// turbo triggers turbo:load events on page transition\n// If app isn't using turbo, this event will never be triggered, no prob.\nCore.listeners().forEach(function(listener) {\n document.addEventListener(listener, function() {\n Core.activate()\n })\n})\n\nCore.onLoad(function () {\n const elem = document.querySelector('.no-js');\n\n // The \"no-js\" class may already have been removed because this function is\n // run on every turbo:load event, in that case, it won't find an element.\n if (!elem) return;\n\n elem.classList.remove('no-js')\n elem.classList.add('js')\n})\n\n\nexport default Core\n","import BookmarkToggle from 'blacklight-frontend/bookmark_toggle'\nimport ButtonFocus from 'blacklight-frontend/button_focus'\nimport FacetSuggest from 'blacklight-frontend/facet_suggest'\nimport Modal from 'blacklight-frontend/modal'\nimport SearchContext from 'blacklight-frontend/search_context'\nimport Core from 'blacklight-frontend/core'\n\nexport default {\n BookmarkToggle,\n ButtonFocus,\n FacetSuggest,\n Modal,\n SearchContext,\n Core,\n onLoad: Core.onLoad\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"blacklight.js","sources":["../../../javascript/blacklight-frontend/checkbox_submit.js","../../../javascript/blacklight-frontend/bookmark_toggle.js","../../../javascript/blacklight-frontend/button_focus.js","../../../javascript/blacklight-frontend/debounce.js","../../../javascript/blacklight-frontend/facet_suggest.js","../../../javascript/blacklight-frontend/modal.js","../../../javascript/blacklight-frontend/search_context.js","../../../javascript/blacklight-frontend/core.js","../../../javascript/blacklight-frontend/index.js"],"sourcesContent":["/* Converts a \"toggle\" form, with single submit button to add/remove\n something, like used for Bookmarks, into an AJAXy checkbox instead.\n Apply to a form. Does require certain assumption about the form:\n 1) The same form 'action' href must be used for both ADD and REMOVE\n actions, with the different being the hidden input name=\"_method\"\n being set to \"put\" or \"delete\" -- that's the Rails method to pretend\n to be doing a certain HTTP verb. So same URL, PUT to add, DELETE\n to remove. This plugin assumes that.\n Plus, the form this is applied to should provide a data-doc-id\n attribute (HTML5-style doc-*) that contains the id/primary key\n of the object in question -- used by plugin for a unique value for\n DOM id's.\n Uses HTML for a checkbox compatible with Bootstrap 4.\n new CheckboxSubmit(document.querySelector('form.something')).render()\n*/\nexport default class CheckboxSubmit {\n constructor(form) {\n this.form = form\n }\n\n clicked(evt) {\n this.spanTarget.innerHTML = this.form.getAttribute('data-inprogress')\n this.labelTarget.setAttribute('disabled', 'disabled');\n this.checkboxTarget.setAttribute('disabled', 'disabled');\n fetch(this.formTarget.getAttribute('action'), {\n body: new FormData(this.formTarget),\n method: this.formTarget.getAttribute('method').toUpperCase(),\n headers: {\n 'Accept': 'application/json',\n 'X-Requested-With': 'XMLHttpRequest',\n 'X-CSRF-Token': document.querySelector('meta[name=csrf-token]')?.content\n }\n }).then((response) => {\n if (response.ok) return response.json();\n return Promise.reject('response was not ok')\n }).then((json) => {\n this.labelTarget.removeAttribute('disabled')\n this.checkboxTarget.removeAttribute('disabled')\n // For accessibility return keyboard focus \n // back to the checkbox after form submission\n this.checkboxTarget.focus()\n this.updateStateFor(!this.checked)\n this.bookmarksCounter().forEach(counter => {\n counter.innerHTML = json.bookmarks.count;\n });\n\n var e = new CustomEvent('bookmark.blacklight', { detail: { checked: this.checked } });\n window.dispatchEvent(e)\n }).catch((error) => {\n this.handleError(error)\n })\n }\n\n get checked() {\n return (this.form.querySelectorAll('input[name=_method][value=delete]').length != 0)\n }\n\n get formTarget() {\n return this.form\n }\n\n get labelTarget() {\n return this.form.querySelector('[data-checkboxsubmit-target=\"label\"]')\n }\n\n get checkboxTarget() {\n return this.form.querySelector('[data-checkboxsubmit-target=\"checkbox\"]')\n }\n\n get spanTarget() {\n return this.form.querySelector('[data-checkboxsubmit-target=\"span\"]')\n }\n\n bookmarksCounter() {\n return document.querySelectorAll('[data-role=\"bookmark-counter\"]')\n }\n\n handleError() {\n alert(\"Unable to save the bookmark at this time.\")\n }\n\n updateStateFor(state) {\n if (state) { this.checkboxTarget.setAttribute('checked', state) }\n else { this.checkboxTarget.removeAttribute('checked') }\n\n if (state) {\n this.labelTarget.classList.add('checked')\n //Set the Rails hidden field that fakes an HTTP verb\n //properly for current state action.\n this.formTarget.querySelector('input[name=_method]').value = 'delete'\n this.spanTarget.innerHTML = this.form.getAttribute('data-present')\n } else {\n this.labelTarget.classList.remove('checked')\n this.formTarget.querySelector('input[name=_method]').value = 'put'\n this.spanTarget.innerHTML = this.form.getAttribute('data-absent')\n }\n }\n}\n","import CheckboxSubmit from 'blacklight-frontend/checkbox_submit'\n\nconst BookmarkToggle = (e) => {\n const elementType = e.target.getAttribute('data-checkboxsubmit-target');\n if (elementType == 'checkbox' || elementType == 'label') {\n const form = e.target.closest('form');\n if (form) new CheckboxSubmit(form).clicked(e);\n if (e.code == 'Space') e.preventDefault();\n }\n};\n\ndocument.addEventListener('click', BookmarkToggle);\ndocument.addEventListener('keydown', function (e) {\n if (e.key === 'Enter' || e.code == 'Space') { BookmarkToggle(e); } }\n);\n\nexport default BookmarkToggle\n","const ButtonFocus = (e) => {\n // Button clicks should change focus. As of 10/3/19, Firefox for Mac and\n // Safari both do not set focus to a button on button click.\n // See https://zellwk.com/blog/inconsistent-button-behavior/ for background information\n if (e.target.matches('[data-bs-toggle=\"collapse\"]')) {\n e.target.focus()\n }\n}\n\ndocument.addEventListener('click', ButtonFocus)\n\nexport default ButtonFocus\n","// Usage:\n// ```\n// const basicFunction = (entry) => console.log(entry)\n// const debounced = debounce(basicFunction(\"I should only be called once\"));\n//\n// debounced // does NOT print to the screen because it is invoked again less than 200 milliseconds later\n// debounced // does print to the screen\n// ```\nexport default function debounce(func, timeout = 200) {\n let timer;\n return (...args) => {\n clearTimeout(timer);\n timer = setTimeout(() => { func.apply(this, args); }, timeout);\n };\n}\n","import debounce from \"blacklight-frontend/debounce\";\n\nconst FacetSuggest = async (e) => {\n if (e.target.matches('.facet-suggest')) {\n const queryFragment = e.target.value?.trim();\n const facetField = e.target.dataset.facetField;\n const facetArea = document.querySelector('.facet-extended-list');\n const prevNextLinks = document.querySelectorAll('.prev_next_links');\n\n if (!facetField) { return; }\n\n // Get the search params from the current query so the facet suggestions\n // can retain that context.\n const facetSearchContext = e.target.dataset.facetSearchContext;\n const url = new URL(facetSearchContext, window.location.origin);\n\n // Drop facet.page so a filtered suggestion list will always start on page 1\n url.searchParams.delete('facet.page');\n const facetSearchParams = url.searchParams.toString();\n\n const urlToFetch = `/catalog/facet_suggest/${facetField}/${queryFragment}?${facetSearchParams}`;\n\n const response = await fetch(urlToFetch);\n if (response.ok) {\n const blob = await response.blob()\n const text = await blob.text()\n\n if (text && facetArea) {\n facetArea.innerHTML = text\n }\n }\n\n // Hide the prev/next links when a user enters text in the facet\n // suggestion input. They don't work with a filtered list.\n prevNextLinks.forEach(element => {\n element.classList.toggle('invisible', !!queryFragment);\n });\n\n // Add a class to distinguish suggested facet values vs. regular.\n facetArea.classList.toggle('facet-suggestions', !!queryFragment);\n }\n};\n\ndocument.addEventListener('input', debounce(FacetSuggest));\n\nexport default FacetSuggest\n","/*\n The blacklight modal plugin can display some interactions inside a Bootstrap\n modal window, including some multi-page interactions.\n\n It supports unobtrusive Javascript, where a link or form that would have caused\n a new page load is changed to display it's results inside a modal dialog,\n by this plugin. The plugin assumes there is a Bootstrap modal div\n on the page with id #blacklight-modal to use as the modal -- the standard Blacklight\n layout provides this.\n\n To make a link or form have their results display inside a modal, add\n `data-blacklight-modal=\"trigger\"` to the link or form. (Note, form itself not submit input)\n With Rails link_to helper, you'd do that like:\n\n link_to something, link, data: { blacklight_modal: \"trigger\" }\n\n The results of the link href or form submit will be displayed inside\n a modal -- they should include the proper HTML markup for a bootstrap modal's\n contents. Also, you ordinarily won't want the Rails template with wrapping\n navigational elements to be used. The Rails controller could suppress\n the layout when a JS AJAX request is detected, OR the response\n can include a `<div data-blacklight-modal=\"container\">` -- only the contents\n of the container will be placed inside the modal, the rest of the\n page will be ignored.\n\n Link or forms inside the modal will ordinarily cause page loads\n when they are triggered. However, if you'd like their results\n to stay within the modal, just add `data-blacklight-modal=\"preserve\"`\n to the link or form.\n\n Here's an example of what might be returned, demonstrating most of the devices available:\n\n <div data-blacklight-modal=\"container\">\n <div class=\"modal-header\">\n <button type=\"button\" class=\"btn-close\" data-bl-dismiss=\"modal\" aria-hidden=\"true\">×</button>\n <h3 class=\"modal-title\">Request Placed</h3>\n </div>\n\n <div class=\"modal-body\">\n <p>Some message</p>\n <%= link_to \"This result will still be within modal\", some_link, data: { blacklight_modal: \"preserve\" } %>\n </div>\n\n\n <div class=\"modal-footer\">\n <button type=\"button\" class=\"btn btn-secondary\" data-bl-dismiss=\"modal\">Close</button>\n </div>\n </div>\n\n\n One additional feature. If the content returned from the AJAX form submission\n can be a turbo-stream that defines some HTML fragementsand where on the page to put them:\n https://turbo.hotwired.dev/handbook/streams\n*/\n\nconst Modal = (() => {\n const modal = {}\n\n // a Bootstrap modal div that should be already on the page hidden\n modal.modalSelector = '#blacklight-modal';\n\n // Trigger selectors identify forms or hyperlinks that should open\n // inside a modal dialog.\n modal.triggerLinkSelector = 'a[data-blacklight-modal~=trigger]';\n\n // preserve selectors identify forms or hyperlinks that, if activated already\n // inside a modal dialog, should have destinations remain inside the modal -- but\n // won't trigger a modal if not already in one.\n //\n // No need to repeat selectors from trigger selectors, those will already\n // be preserved. MUST be manually prefixed with the modal selector,\n // so they only apply to things inside a modal.\n modal.preserveLinkSelector = modal.modalSelector + ' a[data-blacklight-modal~=preserve]';\n\n modal.containerSelector = '[data-blacklight-modal~=container]';\n\n // Called on fatal failure of ajax load, function returns content\n // to show to user in modal. Right now called only for network errors.\n modal.onFailure = function (error) {\n console.error('Server error:', this.url, error);\n\n const contents = `<div class=\"modal-header\">\n <div class=\"modal-title\">There was a problem with your request.</div>\n <button type=\"button\" class=\"blacklight-modal-close btn-close\" data-bl-dismiss=\"modal\" aria-label=\"Close\">\n </button>\n </div>\n <div class=\"modal-body\">\n <p>Expected a successful response from the server, but got an error</p>\n <pre>${this.url}\\n${error}</pre>\n </div>`\n\n modal.target().querySelector('.modal-content').innerHTML = contents\n\n modal.show();\n }\n\n // Add the passed in contents to the modal and display it.\n // We have specific handling so that scripts returned from the ajax call are executed.\n // This enables adding a script like recaptcha to prevent bots from sending emails.\n modal.receiveAjax = function (contents) {\n const domparser = new DOMParser();\n const dom = domparser.parseFromString(contents, \"text/html\")\n // If there is a containerSelector on the document, use its children.\n let elements = dom.querySelectorAll(`${modal.containerSelector} > *`)\n const frag = document.createDocumentFragment()\n if (elements.length == 0) {\n // If the containerSelector wasn't found, use the whole document\n elements = dom.body.childNodes\n }\n elements.forEach((el) => frag.appendChild(el))\n modal.activateScripts(frag)\n\n modal.target().querySelector('.modal-content').replaceChildren(frag)\n\n // send custom event with the modal dialog div as the target\n var e = new CustomEvent('loaded.blacklight.blacklight-modal', { bubbles: true, cancelable: true });\n modal.target().dispatchEvent(e)\n\n // if they did preventDefault, don't show the dialog\n if (e.defaultPrevented) return;\n modal.show();\n };\n\n // DOMParser doesn't allow scripts to be executed. This fixes that.\n modal.activateScripts = function (frag) {\n frag.querySelectorAll('script').forEach((script) => {\n const fixedScript = document.createElement('script')\n fixedScript.src = script.src\n fixedScript.async = false\n script.parentNode.replaceChild(fixedScript, script)\n })\n }\n\n modal.modalAjaxLinkClick = function(e) {\n e.preventDefault();\n const href = e.target.closest('a').getAttribute('href')\n fetch(href, { headers: { 'X-Requested-With': 'XMLHttpRequest' }})\n .then(response => {\n if (!response.ok) {\n throw new TypeError(\"Request failed\");\n }\n return response.text();\n })\n .then(data => modal.receiveAjax(data))\n .catch(error => modal.onFailure(error))\n };\n\n modal.setupModal = function() {\n // Register several click handlers in ONE event handler for efficiency\n //\n // * close button OR click on backdrop (modal.modalSelector) closes modal\n // * trigger and preserve link in modal functionality -- if somethign matches both trigger and\n // preserve, still only called once.\n document.addEventListener('click', (e) => {\n if (e.target.closest(`${modal.triggerLinkSelector}, ${modal.preserveLinkSelector}`))\n modal.modalAjaxLinkClick(e)\n else if (e.target.matches(`${modal.modalSelector}`) || e.target.closest('[data-bl-dismiss=\"modal\"]'))\n modal.hide()\n })\n };\n\n modal.hide = function (el) {\n const dom = modal.target();\n\n if (!dom.open) return\n\n var e = new CustomEvent('hide.blacklight.blacklight-modal', { bubbles: true, cancelable: true });\n dom.dispatchEvent(e)\n\n dom.close()\n\n // Turn body scrolling back to what it was\n document.body.style[\"overflow\"] = modal.originalBodyOverflow;\n document.body.style[\"padding-right\"] = modal.originalBodyPaddingRight;\n modal.originalBodyOverflow = undefined;\n modal.originalBodyPaddingRight = undefined;\n }\n\n modal.show = function(el) {\n const dom = modal.target();\n\n if (dom.open) return\n\n var e = new CustomEvent('show.blacklight.blacklight-modal', { bubbles: true, cancelable: true });\n dom.dispatchEvent(e)\n\n dom.showModal()\n\n // Turn off body scrolling\n modal.originalBodyOverflow = document.body.style['overflow'];\n modal.originalBodyPaddingRight = document.body.style['padding-right'];\n document.body.style[\"overflow\"] = \"hidden\"\n document.body.style[\"padding-right\"] = \"0px\"\n }\n\n modal.target = function() {\n return document.querySelector(modal.modalSelector);\n }\n\n modal.setupModal()\n\n return modal;\n})()\n\nexport default Modal\n","const SearchContext = (e) => {\n const contextLink = e.target.closest('[data-context-href]')\n if (contextLink) {\n SearchContext.handleSearchContextMethod.call(contextLink, e)\n }\n}\n\nSearchContext.csrfToken = () => document.querySelector('meta[name=csrf-token]')?.content\nSearchContext.csrfParam = () => document.querySelector('meta[name=csrf-param]')?.content\n\n// this is the Rails.handleMethod with a couple adjustments, described inline:\n// first, we're attaching this directly to the event handler, so we can check for meta-keys\nSearchContext.handleSearchContextMethod = function(event) {\n const link = this\n\n // instead of using the normal href, we need to use the context href instead\n let href = link.getAttribute('data-context-href')\n let target = link.getAttribute('target')\n let csrfToken = SearchContext.csrfToken()\n let csrfParam = SearchContext.csrfParam()\n let form = document.createElement('form')\n form.method = 'post'\n form.action = href\n\n\n let formContent = `<input name=\"_method\" value=\"post\" type=\"hidden\" />\n <input name=\"redirect\" value=\"${link.getAttribute('href')}\" type=\"hidden\" />`\n\n // check for meta keys.. if set, we should open in a new tab\n if(event.metaKey || event.ctrlKey) {\n form.dataset.turbo = \"false\";\n target = '_blank';\n }\n\n if (csrfParam !== undefined && csrfToken !== undefined) {\n formContent += `<input name=\"${csrfParam}\" value=\"${csrfToken}\" type=\"hidden\" />`\n }\n\n // Must trigger submit by click on a button, else \"submit\" event handler won't work!\n // https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/submit\n formContent += '<input type=\"submit\" />'\n\n if (target) { form.setAttribute('target', target); }\n\n form.style.display = 'none'\n form.innerHTML = formContent\n document.body.appendChild(form)\n form.querySelector('[type=\"submit\"]').click()\n\n event.preventDefault()\n};\n\ndocument.addEventListener('click', SearchContext)\n\nexport default SearchContext\n","const Core = function() {\n const buffer = new Array;\n return {\n onLoad: function(func) {\n buffer.push(func);\n },\n\n activate: function() {\n for(let i = 0; i < buffer.length; i++) {\n buffer[i].call();\n }\n },\n\n listeners: function () {\n const listeners = [];\n if (typeof Turbo !== 'undefined') {\n listeners.push('turbo:load', 'turbo:frame-load');\n } else {\n listeners.push('DOMContentLoaded');\n }\n\n return listeners;\n }\n };\n}();\n\n// turbo triggers turbo:load events on page transition\n// If app isn't using turbo, this event will never be triggered, no prob.\nCore.listeners().forEach(function(listener) {\n document.addEventListener(listener, function() {\n Core.activate()\n })\n})\n\nCore.onLoad(function () {\n const elem = document.querySelector('.no-js');\n\n // The \"no-js\" class may already have been removed because this function is\n // run on every turbo:load event, in that case, it won't find an element.\n if (!elem) return;\n\n elem.classList.remove('no-js')\n elem.classList.add('js')\n})\n\n\nexport default Core\n","import BookmarkToggle from 'blacklight-frontend/bookmark_toggle'\nimport ButtonFocus from 'blacklight-frontend/button_focus'\nimport FacetSuggest from 'blacklight-frontend/facet_suggest'\nimport Modal from 'blacklight-frontend/modal'\nimport SearchContext from 'blacklight-frontend/search_context'\nimport Core from 'blacklight-frontend/core'\n\nexport default {\n BookmarkToggle,\n ButtonFocus,\n FacetSuggest,\n Modal,\n SearchContext,\n Core,\n onLoad: Core.onLoad\n}\n"],"names":[],"mappings":"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"}
@@ -1,5 +1,6 @@
1
- .sidenav {
1
+ .facets {
2
2
  --bl-facet-active-bg: var(--bs-success);
3
+ --bl-facet-active-color: var(--bs-white);
3
4
  --bl-facet-active-item-color: var(--bs-success);
4
5
  --bl-facet-remove-color: var(--bs-secondary-color);
5
6
  --bl-facet-remove-hover-color: var(--bs-danger);
@@ -63,16 +64,23 @@
63
64
 
64
65
  .facet-limit {
65
66
  --bs-accordion-btn-bg: var(--bs-gray-100);
66
- --bs-btn-hover-bg: var(--bs-gray-200);
67
+ --bs-btn-active-bg: var(--bs-accordion-btn-bg);
68
+ --bs-btn-hover-bg: var(--bs-accordion-btn-bg);
67
69
  --bs-accordion-active-bg: var(--bs-accordion-btn-bg);
68
70
  }
69
71
 
70
72
  .facet-limit-active {
71
73
  --bs-accordion-btn-bg: var(--bl-facet-active-bg);
72
74
  --bs-btn-hover-bg: var(--bs-accordion-btn-bg);
73
- --bs-accordion-btn-color: var(--bs-light);
75
+ --bs-btn-active-bg: var(--bl-facet-active-bg);
76
+ --bs-btn-active-color: var(--bl-facet-active-color);
77
+ --bs-accordion-btn-color: var(--bl-facet-active-color);
74
78
  --bs-btn-hover-color: var(--bs-accordion-btn-color);
75
79
  --bs-accordion-active-color: var(--bs-accordion-btn-color);
80
+
81
+ // Accordion icon stroke color can't be set without overriding the whole SVG
82
+ --bs-accordion-btn-icon: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='white' stroke-linecap='round' stroke-linejoin='round'><path d='m2 5 6 6 6-6'/></svg>");
83
+ --bs-accordion-btn-active-icon: var(--bs-accordion-btn-icon);
76
84
  }
77
85
 
78
86
  .facet-values {
@@ -143,32 +151,33 @@
143
151
  position: relative;
144
152
  }
145
153
 
146
- /* Sidenav
154
+ /* Pivot Facets
147
155
  -------------------------------------------------- */
148
156
 
149
157
  .pivot-facet {
150
- &.show {
151
- display: flex;
158
+ --bl-facet-toggle-width: 1em;
159
+ --bl-facet-toggle-height: var(--bl-facet-toggle-width);
160
+ --bl-facet-toggle-margin: 0.5em;
161
+ --bl-facet-toggle-show-icon: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-plus-square" viewBox="0 0 16 16"><path d="M14 1a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1h12zM2 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H2z" /><path d="M8 4a.5.5 0 0 1 .5.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3A.5.5 0 0 1 8 4z" /></svg>');
162
+ --bl-facet-toggle-hide-icon: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-dash-square" viewBox="0 0 16 16"><path d="M14 1a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1h12zM2 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H2z" /><path d="M4 8a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7A.5.5 0 0 1 4 8z" /></svg>');
163
+
164
+ // If the item has no expand button, we align it with its siblings that do
165
+ // by giving it left margin equal to the sum of the button's width & margin
166
+ li.treeitem:not(:has(button.facet-toggle-handle)) {
167
+ margin-left: calc(var(--bl-facet-toggle-width) + var(--bl-facet-toggle-margin));
152
168
  }
153
169
  }
154
170
 
155
- $facet-toggle-show-icon: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-plus-square" viewBox="0 0 16 16"><path d="M14 1a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1h12zM2 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H2z" /><path d="M8 4a.5.5 0 0 1 .5.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3A.5.5 0 0 1 8 4z" /></svg>') !default;
156
- $facet-toggle-hide-icon: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-dash-square" viewBox="0 0 16 16"><path d="M14 1a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1h12zM2 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H2z" /><path d="M4 8a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7A.5.5 0 0 1 4 8z" /></svg>') !default;
157
- $facet-toggle-width: 1em !default;
158
- $facet-toggle-height: $facet-toggle-width !default;
159
-
160
171
  .facet-toggle-handle {
172
+ --bs-btn-hover-bg: var(--bs-btn-hover-bg);
173
+ --bs-btn-active-bg: var(--bs-btn-active-bg);
161
174
  margin-block: 0;
162
175
  padding-block: 0;
163
- padding-inline: 0.5rem;
164
-
165
- // keep the icon span centered in the button, but shift to the left for equal spacing inside row
166
- margin-inline-start: -1 * $btn-padding-x;
167
-
168
- .pivot-facet & {
169
- // shift pivot values a little more aggressively for better compact display
170
- margin-inline-start: -2 * $btn-padding-x;
171
- }
176
+ padding: 0;
177
+ border: 0;
178
+ width: var(--bl-facet-toggle-width);
179
+ height: var(--bl-facet-toggle-height);
180
+ margin-right: var(--bl-facet-toggle-margin);
172
181
 
173
182
  &.collapsed {
174
183
  .show {
@@ -190,18 +199,17 @@ $facet-toggle-height: $facet-toggle-width !default;
190
199
 
191
200
  .show .icon,
192
201
  .hide .icon {
193
- width: $facet-toggle-width;
194
- height: $facet-toggle-height;
195
- padding: $btn-padding-y $btn-padding-x;
202
+ width: var(--bl-facet-toggle-width);
203
+ height: var(--bl-facet-toggle-height);
196
204
  }
197
205
 
198
206
  .show .icon {
199
- background: transparent escape-svg($facet-toggle-show-icon) center /
200
- $facet-toggle-width auto no-repeat;
207
+ background: transparent escape-svg(var(--bl-facet-toggle-show-icon)) center /
208
+ var(--bl-facet-toggle-width) auto no-repeat;
201
209
  }
202
210
 
203
211
  .hide .icon {
204
- background: transparent escape-svg($facet-toggle-hide-icon) center /
205
- $facet-toggle-width auto no-repeat;
212
+ background: transparent escape-svg(var(--bl-facet-toggle-hide-icon)) center /
213
+ var(--bl-facet-toggle-width) auto no-repeat;
206
214
  }
207
215
  }
@@ -27,8 +27,8 @@
27
27
  <div class="limit-criteria mb-4">
28
28
  <h2 class="limit-criteria-heading h3"><%= t('blacklight.advanced_search.form.limit_criteria_heading_html')%></h2>
29
29
 
30
- <div id="advanced_search_facets" class="limit_input row">
31
- <div class="advanced-facet-limits panel-group col-md-9 offset-md-3">
30
+ <div id="advanced_search_facets" class="facets limit_input row">
31
+ <div class="advanced-facet-limits accordion col-md-9 offset-md-3">
32
32
  <% search_filter_controls.each do |control| %>
33
33
  <%= control %>
34
34
  <% end %>
@@ -39,7 +39,7 @@
39
39
  </div>
40
40
 
41
41
  <% if sort_fields_select %>
42
- <div class="form-group row mb-4">
42
+ <div class="row mb-4">
43
43
  <%= content_tag :h2, t('blacklight.advanced_search.form.sort_label'), id: 'advanced-search-sort-label', class: 'col-md-3 text-md-right' %>
44
44
  <div class="col-md-9">
45
45
  <%= sort_fields_select %>
@@ -47,7 +47,7 @@
47
47
  </div>
48
48
  <% end %>
49
49
 
50
- <div class="form-group row">
50
+ <div class="row">
51
51
  <div class="submit-buttons col-md-9 offset-md-3">
52
52
  <%= submit_tag t('blacklight.advanced_search.form.search_btn_html'), class: 'btn btn-primary advanced-search-submit', id: "advanced-search-submit" %>
53
53
  <%= link_to t('blacklight.advanced_search.form.start_over_html'), request.path, :class =>"btn btn-link advanced-search-start-over" %>
@@ -31,7 +31,7 @@ module Blacklight
31
31
  options = sort_fields.values.map { |field_config| [helpers.sort_field_label(field_config.key), field_config.key] }
32
32
  return unless options.any?
33
33
 
34
- select_tag(:sort, options_for_select(options, params[:sort]), class: "form-select custom-select sort-select w-auto", aria: { labelledby: 'advanced-search-sort-label' })
34
+ select_tag(:sort, options_for_select(options, params[:sort]), class: "form-select sort-select w-auto", aria: { labelledby: 'advanced-search-sort-label' })
35
35
  end
36
36
 
37
37
  # Filtered params to pass to hidden search fields
@@ -46,7 +46,7 @@ module Blacklight
46
46
  search_fields.values.each.with_index do |field, i|
47
47
  with_search_field_control do
48
48
  fields_for('clause[]', i, include_id: false) do |f|
49
- content_tag(:div, class: 'form-group advanced-search-field row mb-3') do
49
+ content_tag(:div, class: 'advanced-search-field row mb-3') do
50
50
  f.label(:query, field.display_label('search'), class: "col-sm-3 col-form-label text-md-right") +
51
51
  content_tag(:div, class: 'col-sm-9') do
52
52
  f.hidden_field(:field, value: field.key) +
@@ -1,7 +1,7 @@
1
1
  <%- # we don't use the per-form csrf token -%>
2
2
  <%= form_tag(bookmark_path,
3
3
  authenticity_token: false,
4
- method: bookmarked? ? :delete : :put,
4
+ method: bookmarked? ? :delete : :put,
5
5
  class: "bookmark-toggle",
6
6
  data: {
7
7
  present: t('blacklight.search.bookmarks.present'),
@@ -3,16 +3,22 @@
3
3
  module Blacklight
4
4
  module Document
5
5
  # Render a bookmark widget to bookmark / unbookmark a document
6
- class BookmarkComponent < Blacklight::Document::ActionComponent
6
+ class BookmarkComponent < Blacklight::Component
7
7
  # @param [Blacklight::Document] document
8
- # @param [Blacklight::Configuration::ToolConfig] action
8
+ # @param [Blacklight::Configuration::ToolConfig] action - only used to pass a key for the wrapping action.
9
9
  # @param [Boolean] checked
10
10
  # @param [Object] bookmark_path the rails route to use for bookmarks
11
11
  def initialize(document:, action: nil, checked: nil, bookmark_path: nil, **)
12
12
  @document = document
13
13
  @checked = checked
14
14
  @bookmark_path = bookmark_path
15
- super(document: document, action: action, **)
15
+ @action = action
16
+ super
17
+ end
18
+
19
+ # Used by ActionsComponent
20
+ def key
21
+ @action&.key || :bookmark
16
22
  end
17
23
 
18
24
  def bookmarked?
@@ -4,6 +4,6 @@
4
4
  <%= grouped_documents %>
5
5
  </div>
6
6
  <%- if @group_limit > 0 && @group.total > @group_limit %>
7
- <%= helpers.link_to t('blacklight.search.group.more'), add_group_facet_params_and_redirect(@group), class: 'more-in-group float-right' %>
7
+ <%= helpers.link_to t('blacklight.search.group.more'), add_group_facet_params_and_redirect(@group), class: 'more-in-group float-end' %>
8
8
  <%- end %>
9
9
  </div>
@@ -32,13 +32,13 @@ module Blacklight
32
32
 
33
33
  id = "h-#{self.class.mint_id}" if @collapsing && has_items?
34
34
 
35
- content_tag @wrapping_element, class: 'treeitem' do
35
+ content_tag @wrapping_element, class: 'treeitem', role: 'treeitem' do
36
36
  concat(content_tag('span', class: "d-flex flex-row align-items-center") do
37
37
  concat facet_toggle_button(id) if has_items? && @collapsing
38
38
  concat content_tag('span', render(facet), class: "facet-values d-flex flex-row flex-grow-1 #{'facet-leaf-node' if has_items? && @collapsing}", id: id && "#{id}_label")
39
39
  end)
40
40
  if has_items?
41
- concat(content_tag('ul', class: "pivot-facet flex-column list-unstyled ps-4 #{'collapse' if @collapsing} #{'show' if expanded?}", id: id, role: 'group') do
41
+ concat(content_tag('ul', class: "list-unstyled ps-3 #{'collapse' if @collapsing} #{'show' if expanded?}", id: id, role: 'group') do
42
42
  render(
43
43
  self.class.with_collection(
44
44
  @facet_item.facet_item_presenters.to_a
@@ -64,7 +64,7 @@ module Blacklight
64
64
  end
65
65
 
66
66
  def facet_toggle_button(id)
67
- content_tag 'button', class: %w[btn facet-toggle-handle] + [('collapsed' unless expanded?)],
67
+ content_tag 'button', class: %w[btn focus-ring facet-toggle-handle] + [('collapsed' unless expanded?)],
68
68
  data: { toggle: 'collapse', 'bs-toggle': 'collapse', target: "##{id}", 'bs-target': "##{id}" },
69
69
  aria: { expanded: expanded?, controls: id, describedby: "#{id}_label" } do
70
70
  concat toggle_icon(:show)
@@ -7,13 +7,13 @@
7
7
  <ul class="facet-values list-unstyled blacklight-facet-checkboxes">
8
8
  <% presenters.each_with_index do |presenter, idx| -%>
9
9
  <li>
10
- <span class="facet-checkbox">
10
+ <span class="facet-checkbox flex-shrink-0">
11
11
  <%= check_box_tag "f_inclusive[#{@facet_field.key}][]", presenter.value, presenter.selected?, id: "f_inclusive_#{@facet_field.key}_#{idx}"%>
12
12
  </span>
13
13
 
14
- <span>
15
- <%= label_tag "f_inclusive_#{@facet_field.key}_#{idx}" do %>
16
- <span class="facet-label"><%= presenter.label %></span>
14
+ <span class="facet-label-and-count flex-grow-1">
15
+ <%= label_tag "f_inclusive_#{@facet_field.key}_#{idx}", class: 'd-flex' do %>
16
+ <span class="facet-label flex-grow-1"><%= presenter.label %></span>
17
17
  <span class="facet-count"><%= t('blacklight.search.facets.count', number: number_with_delimiter(presenter.hits)) %></span>
18
18
  <% end %>
19
19
  </span>
@@ -3,9 +3,7 @@
3
3
  <button
4
4
  type="button"
5
5
  class="btn accordion-button <%= "collapsed" if @facet_field.collapsed? %>"
6
- data-toggle="collapse"
7
6
  data-bs-toggle="collapse"
8
- data-target="#<%= html_id %>"
9
7
  data-bs-target="#<%= html_id %>"
10
8
  aria-expanded="<%= @facet_field.collapsed? ? 'false' : 'true' %>"
11
9
  aria-controls="<%= html_id %>"
@@ -4,8 +4,8 @@
4
4
  <% end %>
5
5
  <% component.with_body do %>
6
6
  <%= render(Blacklight::Facets::InclusiveConstraintComponent.new(facet_field: @facet_field)) %>
7
- <ul class="facet-values list-unstyled">
7
+ <%= content_tag :ul, class: @classes, role: @role do %>
8
8
  <%= render facet_items %>
9
- </ul>
9
+ <% end %>
10
10
  <% end %>
11
11
  <% end %>
@@ -3,12 +3,17 @@
3
3
  module Blacklight
4
4
  module Facets
5
5
  class ListComponent < Blacklight::Component
6
- def initialize(facet_field:, layout: nil)
6
+ def initialize(facet_field:,
7
+ classes: %w[facet-values list-unstyled],
8
+ role: nil,
9
+ layout: nil)
7
10
  @facet_field = facet_field
11
+ @classes = classes
12
+ @role = role
8
13
  @layout = layout == false ? Blacklight::Facets::NoLayoutComponent : Blacklight::Facets::FieldComponent
9
14
  end
10
15
 
11
- attr_accessor :layout
16
+ attr_accessor :layout, :classes, :role
12
17
 
13
18
  def facet_items(wrapping_element: :li, **item_args)
14
19
  facet_item_component_class.with_collection(facet_item_presenters, wrapping_element: wrapping_element, **item_args)
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Blacklight
4
+ module Facets
5
+ class PivotListComponent < Blacklight::Facets::ListComponent
6
+ def initialize(facet_field:,
7
+ classes: %w[pivot-facet facet-values list-unstyled],
8
+ role: 'tree',
9
+ layout: nil)
10
+ super
11
+ end
12
+ end
13
+ end
14
+ end
@@ -1,4 +1,4 @@
1
- <label for="facet_suggest_<%= key %>">
1
+ <label class="form-label" for="facet_suggest_<%= key %>">
2
2
  <%= I18n.t('blacklight.search.facets.suggest.label', field_label: label) %>
3
3
  </label>
4
4
  <%= text_field_tag "facet_suggest_#{key}",
@@ -15,7 +15,7 @@
15
15
  options_for_select(search_fields, h(@search_field)),
16
16
  {},
17
17
  title: scoped_t('search_field.title'),
18
- class: "custom-select form-select search-field") %>
18
+ class: "form-select search-field") %>
19
19
  <% elsif search_fields.length == 1 %>
20
20
  <%= f.hidden_field :search_field, value: search_fields.first.last %>
21
21
  <% end %>
@@ -1,7 +1,7 @@
1
1
  <nav class="navbar navbar-expand-md bg-dark topbar" aria-label="<%= aria_label %>">
2
2
  <div class="<%= container_classes %>">
3
3
  <%= logo_link %>
4
- <button class="navbar-toggler" type="button" data-toggle="collapse" data-bs-toggle="collapse" data-target="#user-util-collapse" data-bs-target="#user-util-collapse" aria-controls="user-util-collapse" aria-expanded="false" aria-label="Toggle navigation">
4
+ <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#user-util-collapse" aria-controls="user-util-collapse" aria-expanded="false" aria-label="Toggle navigation">
5
5
  <span class="navbar-toggler-icon"></span>
6
6
  </button>
7
7
 
@@ -85,6 +85,11 @@ module Blacklight::Bookmarks
85
85
  false
86
86
  end
87
87
 
88
+ create_response(success)
89
+ end
90
+
91
+ # Override the create_response method to handle the response appropriately.
92
+ def create_response(success)
88
93
  if request.xhr?
89
94
  success ? render(json: { bookmarks: { count: current_or_guest_user.bookmarks.count } }) : render(json: current_or_guest_user.errors.full_messages, status: :internal_server_error)
90
95
  else
@@ -113,6 +118,11 @@ module Blacklight::Bookmarks
113
118
  bookmark&.delete && bookmark.destroyed?
114
119
  end
115
120
 
121
+ destroy_response(success)
122
+ end
123
+
124
+ # Override the destroy_response method to handle the response appropriately.
125
+ def destroy_response(success)
116
126
  if success
117
127
  if request.xhr?
118
128
  render(json: { bookmarks: { count: current_or_guest_user.bookmarks.count } })
@@ -23,7 +23,7 @@ module Blacklight::Catalog
23
23
 
24
24
  # get search results from the solr index
25
25
  def index
26
- @response = search_service.search_results
26
+ @response = retrieve_search_results
27
27
 
28
28
  respond_to do |format|
29
29
  format.html { store_preferred_view }
@@ -143,6 +143,11 @@ module Blacklight::Catalog
143
143
 
144
144
  private
145
145
 
146
+ # This method may be overridden to customize search behavior.
147
+ def retrieve_search_results
148
+ search_service.search_results
149
+ end
150
+
146
151
  #
147
152
  # non-routable methods ->
148
153
  #
@@ -2,7 +2,7 @@ const ButtonFocus = (e) => {
2
2
  // Button clicks should change focus. As of 10/3/19, Firefox for Mac and
3
3
  // Safari both do not set focus to a button on button click.
4
4
  // See https://zellwk.com/blog/inconsistent-button-behavior/ for background information
5
- if (e.target.matches('[data-toggle="collapse"]') || e.target.matches('[data-bs-toggle="collapse"]')) {
5
+ if (e.target.matches('[data-bs-toggle="collapse"]')) {
6
6
  e.target.focus()
7
7
  }
8
8
  }
@@ -44,7 +44,7 @@ export default class CheckboxSubmit {
44
44
  counter.innerHTML = json.bookmarks.count;
45
45
  });
46
46
 
47
- var e = new CustomEvent('bookmark.blacklight', { detail: { checked: !this.checked } });
47
+ var e = new CustomEvent('bookmark.blacklight', { detail: { checked: this.checked } });
48
48
  window.dispatchEvent(e)
49
49
  }).catch((error) => {
50
50
  this.handleError(error)
@@ -32,7 +32,7 @@
32
32
 
33
33
  <div data-blacklight-modal="container">
34
34
  <div class="modal-header">
35
- <button type="button" class="close" data-bl-dismiss="modal" aria-hidden="true">×</button>
35
+ <button type="button" class="btn-close" data-bl-dismiss="modal" aria-hidden="true">×</button>
36
36
  <h3 class="modal-title">Request Placed</h3>
37
37
  </div>
38
38
 
@@ -134,7 +134,7 @@ const Modal = (() => {
134
134
  modal.modalAjaxLinkClick = function(e) {
135
135
  e.preventDefault();
136
136
  const href = e.target.closest('a').getAttribute('href')
137
- fetch(href)
137
+ fetch(href, { headers: { 'X-Requested-With': 'XMLHttpRequest' }})
138
138
  .then(response => {
139
139
  if (!response.ok) {
140
140
  throw new TypeError("Request failed");
@@ -1,4 +1,4 @@
1
1
  <%= link_to bookmarks_path, id:'bookmarks_nav', class: 'nav-link' do %>
2
2
  <%= t('blacklight.header_links.bookmarks') %>
3
- <span class="badge badge-secondary bg-secondary" data-role='bookmark-counter'><%= current_or_guest_user.bookmarks.count %></span>
3
+ <span class="badge rounded-pill text-bg-secondary bookmark-counter" data-role='bookmark-counter'><%= current_or_guest_user.bookmarks.count %></span>
4
4
  <% end %>
@@ -6,8 +6,8 @@
6
6
 
7
7
  <div class="modal-body">
8
8
  <%= render '/shared/flash_msg' %>
9
- <div class="form-group row">
10
- <label class="control-label col-sm-2" for="to">
9
+ <div class="row">
10
+ <label class="col-form-label col-sm-2" for="to">
11
11
  <%= t('blacklight.email.form.to') %>
12
12
  </label>
13
13
  <div class="col-sm-10">
@@ -15,8 +15,8 @@
15
15
  </div>
16
16
  </div>
17
17
 
18
- <div class="form-group row">
19
- <label class="control-label col-sm-2" for="message">
18
+ <div class="row">
19
+ <label class="col-form-label col-sm-2" for="message">
20
20
  <%= t('blacklight.email.form.message') %>
21
21
  </label>
22
22
  <div class="col-sm-10">