<% end %>
<% end %>
diff --git a/app/components/blacklight/system/modal_component.html.erb b/app/components/blacklight/system/modal_component.html.erb
index c6a32a222c..6b28512ee9 100644
--- a/app/components/blacklight/system/modal_component.html.erb
+++ b/app/components/blacklight/system/modal_component.html.erb
@@ -1,25 +1,27 @@
-
- <%= prefix %>
+
+
+ <%= prefix %>
-
- <%= header || (capture do %>
-
<%= title %>
- <% end) %>
-
-
-
+
+ <%= header || (capture do %>
+
<%= title %>
+ <% end) %>
- <%= body || (capture do %>
-
- <%= content %>
+
- <% end) %>
- <% if footer.present? %>
-
- <% end %>
+ <%= body || (capture do %>
+
+ <%= content %>
+
+ <% end) %>
+
+ <% if footer.present? %>
+
+ <% end %>
+
diff --git a/app/javascript/blacklight/index.js b/app/javascript/blacklight/index.js
index 0fe8e22724..6c07389ef5 100644
--- a/app/javascript/blacklight/index.js
+++ b/app/javascript/blacklight/index.js
@@ -1,13 +1,11 @@
import BookmarkToggle from 'blacklight/bookmark_toggle'
import ButtonFocus from 'blacklight/button_focus'
-import Modal from 'blacklight/modal'
import SearchContext from 'blacklight/search_context'
import Core from 'blacklight/core'
export default {
BookmarkToggle,
ButtonFocus,
- Modal,
SearchContext,
Core,
onLoad: Core.onLoad
diff --git a/app/javascript/blacklight/modal.js b/app/javascript/blacklight/modal.js
deleted file mode 100644
index 19754ca6cf..0000000000
--- a/app/javascript/blacklight/modal.js
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- The blacklight modal plugin can display some interactions inside a Bootstrap
- modal window, including some multi-page interactions.
-
- It supports unobtrusive Javascript, where a link or form that would have caused
- a new page load is changed to display it's results inside a modal dialog,
- by this plugin. The plugin assumes there is a Bootstrap modal div
- on the page with id #blacklight-modal to use as the modal -- the standard Blacklight
- layout provides this.
-
- To make a link or form have their results display inside a modal, add
- `data-blacklight-modal="trigger"` to the link or form. (Note, form itself not submit input)
- With Rails link_to helper, you'd do that like:
-
- link_to something, link, data: { blacklight_modal: "trigger" }
-
- The results of the link href or form submit will be displayed inside
- a modal -- they should include the proper HTML markup for a bootstrap modal's
- contents. Also, you ordinarily won't want the Rails template with wrapping
- navigational elements to be used. The Rails controller could suppress
- the layout when a JS AJAX request is detected, OR the response
- can include a `
` -- only the contents
- of the container will be placed inside the modal, the rest of the
- page will be ignored.
-
- Link or forms inside the modal will ordinarily cause page loads
- when they are triggered. However, if you'd like their results
- to stay within the modal, just add `data-blacklight-modal="preserve"`
- to the link or form.
-
- Here's an example of what might be returned, demonstrating most of the devices available:
-
-
-
-
-
Request Placed
-
-
-
-
Some message
- <%= link_to "This result will still be within modal", some_link, data: { blacklight_modal: "preserve" } %>
-
-
-
-
-
-
-
- One additional feature. If the content returned from the AJAX form submission
- can be a turbo-stream that defines some HTML fragementsand where on the page to put them:
- https://turbo.hotwired.dev/handbook/streams
-*/
-import Blacklight from 'blacklight/core'
-import ModalForm from 'blacklight/modalForm'
-
-const Modal = (() => {
- // We keep all our data in Blacklight.modal object.
- // Create lazily if someone else created first.
- if (Blacklight.modal === undefined) {
- Blacklight.modal = {};
- }
-
- const modal = Blacklight.modal
-
- // a Bootstrap modal div that should be already on the page hidden
- modal.modalSelector = '#blacklight-modal';
-
- // Trigger selectors identify forms or hyperlinks that should open
- // inside a modal dialog.
- modal.triggerLinkSelector = 'a[data-blacklight-modal~=trigger]';
-
- // preserve selectors identify forms or hyperlinks that, if activated already
- // inside a modal dialog, should have destinations remain inside the modal -- but
- // won't trigger a modal if not already in one.
- //
- // No need to repeat selectors from trigger selectors, those will already
- // be preserved. MUST be manually prefixed with the modal selector,
- // so they only apply to things inside a modal.
- modal.preserveLinkSelector = modal.modalSelector + ' a[data-blacklight-modal~=preserve]';
-
- modal.containerSelector = '[data-blacklight-modal~=container]';
-
- // Called on fatal failure of ajax load, function returns content
- // to show to user in modal. Right now called only for network errors.
- modal.onFailure = function (error) {
- console.error('Server error:', this.url, error);
-
- const contents = `
-
There was a problem with your request.
-
-
-
-
Expected a successful response from the server, but got an error
-
${this.url}\n${error}
-
`
-
- document.querySelector(`${modal.modalSelector} .modal-content`).innerHTML = contents
-
- modal.show();
- }
-
- // Add the passed in contents to the modal and display it.
- modal.receiveAjax = function (contents) {
- const domparser = new DOMParser();
- const dom = domparser.parseFromString(contents, "text/html")
- // If there is a containerSelector on the document, use its children.
- let elements = dom.querySelectorAll(`${modal.containerSelector} > *`)
- if (elements.length == 0) {
- // If the containerSelector wasn't found, use the whole document
- elements = dom.body.childNodes
- }
-
- document.querySelector(`${modal.modalSelector} .modal-content`).replaceChildren(...elements)
-
- modal.show();
- };
-
-
- modal.modalAjaxLinkClick = function(e) {
- e.preventDefault();
- const href = e.target.getAttribute('href')
- fetch(href)
- .then(response => {
- if (!response.ok) {
- throw new TypeError("Request failed");
- }
- return response.text();
- })
- .then(data => modal.receiveAjax(data))
- .catch(error => modal.onFailure(error))
- };
-
- modal.setupModal = function() {
- // Register both trigger and preserve selectors in ONE event handler, combining
- // into one selector with a comma, so if something matches BOTH selectors, it
- // still only gets the event handler called once.
- document.addEventListener('click', (e) => {
- if (e.target.closest(`${modal.triggerLinkSelector}, ${modal.preserveLinkSelector}`))
- modal.modalAjaxLinkClick(e)
- else if (e.target.closest('[data-bl-dismiss="modal"]'))
- modal.hide()
- })
- };
-
- modal.hide = function (el) {
- const dom = document.querySelector(Blacklight.modal.modalSelector)
-
- if (!dom.open) return
- dom.close()
- }
-
- modal.show = function(el) {
- const dom = document.querySelector(Blacklight.modal.modalSelector)
-
- if (dom.open) return
- dom.showModal()
- }
-
- modal.setupModal()
-})()
-
-export default Modal
diff --git a/app/javascript/blacklight/modalForm.js b/app/javascript/blacklight/modalForm.js
deleted file mode 100644
index d68db1d1b1..0000000000
--- a/app/javascript/blacklight/modalForm.js
+++ /dev/null
@@ -1,60 +0,0 @@
-// The email and sms forms are displayed inside a modal. When the form is submitted,
-// this script closes the modal and puts the output on the main part of the page.
-// By default it is rendering catalog/sms_success and catalog/email_succcess.
-// These templates deliver a payload of the format used by turbo-streams.
-// See https://turbo.hotwired.dev/handbook/streams
-// That format allows a downstream application to override the template to define
-// multiple customizable areas of the page to get updated.
-export default class {
- constructor(errorHandler, badRequestHandler, hideModal) {
- this.errorHandler = errorHandler
- this.badRequestHandler = badRequestHandler
- this.hideModal = hideModal
- }
-
- get triggerFormSelector() {
- return 'form[data-blacklight-modal~=trigger]'
- }
-
- bind() {
- document.addEventListener('submit', (e) => {
- if (e.target.matches(this.triggerFormSelector))
- this.onSubmit(e)
- })
- }
-
- // This is like a light-weight version of turbo that only supports append presently.
- updateTurboStream(data) {
- this.hideModal()
- const domparser = new DOMParser();
- const dom = domparser.parseFromString(data, "text/html")
- dom.querySelectorAll("turbo-stream[action='append']").forEach((node) => {
- const target = node.getAttribute('target')
- const element = document.getElementById(target)
- if (element)
- element.append(node.querySelector('template').content.cloneNode(true))
- else
- console.error(`Unable to find an element on the page with and ID of "${target}""`)
- })
- }
-
- onSubmit(e) {
- e.preventDefault();
- const form = e.target
- fetch(form.action, {
- body: new FormData(form),
- headers: { "X-Requested-With": "XMLHttpRequest" }, // Ensures rails will return true when checking request.xhr?
- method: form.method,
- })
- .then(response => {
- if (response.status === 422) {
- return response.text().then(content => this.badRequestHandler(content) )
- }
- if (!response.ok) {
- throw new TypeError("Request failed");
- }
- response.text().then(content => this.updateTurboStream(content))
- })
- .catch(error => this.errorHandler(error))
- }
-}
diff --git a/app/javascript/controllers/blacklight/modal_controller.js b/app/javascript/controllers/blacklight/modal_controller.js
new file mode 100644
index 0000000000..e46b08638a
--- /dev/null
+++ b/app/javascript/controllers/blacklight/modal_controller.js
@@ -0,0 +1,17 @@
+import { Controller } from "@hotwired/stimulus"
+
+export default class extends Controller {
+ static targets = ['content', 'modal']
+
+ connect() {
+ this.contentTarget.innerHTML = '';
+ }
+
+ open() {
+ this.modalTarget.showModal();
+ }
+
+ close() {
+ this.modalTarget.close();
+ }
+}
diff --git a/app/views/catalog/facet.html.erb b/app/views/catalog/facet.html.erb
index 0d0745c83e..2d10a61bae 100644
--- a/app/views/catalog/facet.html.erb
+++ b/app/views/catalog/facet.html.erb
@@ -9,7 +9,7 @@
<%= render partial: 'facet_index_navigation' if @facet.index_range && @display_facet.index? %>
-