diff --git a/app/assets/javascripts/request_viewer_state.js b/app/assets/javascripts/request_viewer_state.js new file mode 100644 index 000000000..05ad7c489 --- /dev/null +++ b/app/assets/javascripts/request_viewer_state.js @@ -0,0 +1,93 @@ +/* eslint-disable camelcase */ +/* global Blacklight */ + +(function (global) { + var RequestViewerState; + + RequestViewerState = { + init: function() { + this.setupIframeMessageListener(); + this.setupRequestButton(); + $('[data-embed-url]').oEmbed(); + }, + + setupRequestButton: function() { + $('#request-state').on('click', (event) => { + this.formId = event.target.dataset.formId; + this.itemId = event.target.dataset.itemId; + this.requestState(); + }); + }, + + setupIframeMessageListener: function() { + window.addEventListener('message', (event) => { + if (event && event.data) { + // avoid development issues + if (event.data == "recaptcha-setup" || event.data.source == "react-devtools-content-script") { return; } + let parsedData; + try { + parsedData = typeof event.data === 'string' ? JSON.parse(event.data) : event.data; + } catch (error) { + console.error('Failed to parse event data:', error); + return; // Exit if parsing fails + } + + if (parsedData.type === "stateResponse" && parsedData.source === "sul-embed-m3") { + + console.log('Exhibits: received state:', parsedData.data); + let { viewers, windows, iiif_images, canvas_index } = parsedData.data; + if (document.querySelector('#page-2-placeholder')) document.querySelector('#page-2-placeholder').remove(); + const viewer = Object.keys(viewers)[0]; + const canvas_id = windows[viewer]['canvasId']; + const iiif_initial_viewer_config = JSON.stringify(viewers[viewer]); + const canvasField = document.querySelector(`#${this.formId} > input[name="item[${this.itemId}][iiif_canvas_id]"]`) + const configInput = document.querySelector(`#${this.formId} > input[name="item[${this.itemId}][iiif_initial_viewer_config]"]`) + canvasField.value = canvas_id; + configInput.value = iiif_initial_viewer_config; + document.querySelector(`#${this.formId} > input[name="item[${this.itemId}][full_image_url]"]`).value = iiif_images[0]; + const thumbnail_size = iiif_images.length > 1 ? '!33,100' : '!100,100'; + const thumbnail = iiif_images.map(image => image.replace('full', thumbnail_size)) + document.querySelector(`#${this.formId} > input[name="item[${this.itemId}][thumbnail_image_url]"]`).value = thumbnail[0]; + document.querySelector(`#${this.formId} img`).src = `${thumbnail[0]}?${new Date().getTime()}`; + if (thumbnail.length > 1){ + if (!document.querySelector('#page-2')) { + document.querySelector(`#${this.formId} img`).insertAdjacentHTML('afterend', ``); + } else { + document.querySelector('#page-2').src = `${thumbnail[1]}?${new Date().getTime()}`; + } + } else if (document.querySelector('#page-2')) { + document.querySelector('#page-2').src = '' + } + let modal_link_element = document.querySelector(`#${this.formId} #select-image-area`); + let modal_link = this.updateQueryParameters(modal_link_element.href, canvas_id, iiif_initial_viewer_config); + const multi_page = document.querySelector('[data-current-image]'); + if (multi_page) multi_page.innerText = canvas_index; + modal_link_element.href = modal_link; + } + } + }); + }, + + updateQueryParameters: function(url, canvas_id, iiif_initial_viewer_config) { + const urlObj = new URL(url); + urlObj.searchParams.set('canvas_id', canvas_id); + urlObj.searchParams.set('iiif_initial_viewer_config', iiif_initial_viewer_config); + return urlObj.href; + }, + + requestState: function() { + const iframe = document.querySelector('.oembed-widget iframe, iframe.mirador-embed-wrapper'); + iframe.contentWindow.postMessage(JSON.stringify({ type: 'requestState' }), '*'); // Change '*' to a specific origin for security? + } + }; + + global.RequestViewerState = RequestViewerState; +}(this)); + + +Blacklight.onLoad(function () { + 'use strict'; + document.addEventListener('show.blacklight.blacklight-modal', function(event) { + RequestViewerState.init() + }) +}); \ No newline at end of file diff --git a/app/assets/javascripts/select_image_area.js b/app/assets/javascripts/select_image_area.js new file mode 100644 index 000000000..50677ca17 --- /dev/null +++ b/app/assets/javascripts/select_image_area.js @@ -0,0 +1,61 @@ +/* eslint-disable camelcase */ +/* global Blacklight */ + +(function (global) { + var SelectImageArea; + + SelectImageArea = { + init: function(el) { + this.panel = $(el); + this.addSelectImageAreaLink(); + }, + + addSelectImageAreaLink: function() { + const target = $('[data-panel-image-pagination]', this.panel); + + const resourceId = this.panel.data('resource-id'); + const itemId = this.panel.data('id'); + const exhibit_path = this.panel.closest('form')[0].dataset.exhibitPath; + const iiif_initial_viewer_config = $(`input[name="item[${itemId}][iiif_initial_viewer_config]"]`, this.panel)[0].value; + const canvas_id = $(`input[name="item[${itemId}][iiif_canvas_id]"]`, this.panel)[0].value; + let href = `${exhibit_path}/select_image_area/${resourceId}?form_id=${this.panel[0].id}&item_id=${itemId}&canvas_id=${canvas_id}` + if (iiif_initial_viewer_config && iiif_initial_viewer_config != "undefined") href += `&iiif_initial_viewer_config=${encodeURIComponent(iiif_initial_viewer_config)}` + const selectImageAreaHtml = $(`Select image area`); + const image_url = this.panel[0].querySelector('img'); + if (image_url.src.includes('!33')) { + image_url.insertAdjacentHTML('afterend', 'This section spans two pages, we can not display the thumbnail for page 2.'); + } + + target.before(selectImageAreaHtml); + } + }; + + global.SelectImageArea = SelectImageArea; +}(this)); + +Blacklight.onLoad(function () { + 'use strict'; + + $('[data-type="solr_documents_embed"] .panels li').each(function (i, element) { + SelectImageArea.init(element); + }); + + // for if another embed widget is added after page load + const callback = function(mutationsList, observer) { + for (let mutation of mutationsList) { + if (mutation.type === 'childList') { + mutation.addedNodes.forEach(node => { + if (node.nodeType === 1 && node.tagName === 'LI') { + SelectImageArea.init(node); + } + }); + } + } + }; + + document.querySelectorAll('[data-type="solr_documents_embed"]').forEach(function(element, i) { + const observer = new MutationObserver(callback); + observer.observe(element, {childList: true, subtree: true}); + }) +}); + diff --git a/app/assets/javascripts/sir_trevor_block_overrides.js b/app/assets/javascripts/sir_trevor_block_overrides.js index de264c4e3..558c97953 100644 --- a/app/assets/javascripts/sir_trevor_block_overrides.js +++ b/app/assets/javascripts/sir_trevor_block_overrides.js @@ -6,7 +6,18 @@ SirTrevor.Blocks.SolrDocumentsEmbed = (function(){ ``, `` ].join(' '); - } + }, + _itemPanelIiifFields: function(index, autocomplete_data) { + return [ + '', + '', + '', + '', + '', + "", + '', + ].join("\n"); + }, }); })(); diff --git a/app/assets/javascripts/spotlight.js b/app/assets/javascripts/spotlight.js index fcc621edf..1082b3c52 100644 --- a/app/assets/javascripts/spotlight.js +++ b/app/assets/javascripts/spotlight.js @@ -1,2 +1,4 @@ //= require spotlight/application //= require sir_trevor_block_overrides +//= require select_image_area +//= require request_viewer_state \ No newline at end of file diff --git a/app/components/custom_viewer_component.html.erb b/app/components/custom_viewer_component.html.erb index e566fa6eb..bb60a75a9 100644 --- a/app/components/custom_viewer_component.html.erb +++ b/app/components/custom_viewer_component.html.erb @@ -1,5 +1,5 @@ <% if document.external_iiif? %> - <%= render partial: "embedded_mirador3", locals: {document: document} %> + <%= render partial: "embedded_mirador3", locals: {document: document, block: block_context} %> <% elsif document.uploaded_resource? %> <%= render Blacklight::Gallery::OpenseadragonEmbedComponent.new(document: document, presenter: presenter, view_config: view_config) %> <% else %> diff --git a/app/controllers/catalog_controller.rb b/app/controllers/catalog_controller.rb index 9ad8dbdc7..5bc7baa6f 100644 --- a/app/controllers/catalog_controller.rb +++ b/app/controllers/catalog_controller.rb @@ -504,6 +504,25 @@ def search_tips end end + def select_image_area + begin + result = search_service.fetch params[:id] + @document = if result.is_a?(Array) + result.last + else + result + end + rescue StandardError + @document = nil + end + respond_to do |format| + format.html do + return render layout: false if request.xhr? + # Otherwise draw the full page + end + end + end + # Action for parker to fetch bibliography references by ID def documents_list search_service = Blacklight::SearchService.new(config: blacklight_config) diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 7d8f16889..0ab0e58ba 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -54,7 +54,8 @@ def custom_render_oembed_tag_async(document, canvas_id, block) content_tag :div, '', data: { embed_url: blacklight_oembed_engine.embed_url( url: url, - canvas_id: canvas_id, + iiif_initial_viewer_config: choose_initial_viewer_config(block) || params[:iiif_initial_viewer_config], + canvas_id: canvas_id || params[:canvas_id], search: params[:search], maxheight: block&.maxheight.presence || '600', suggested_search: (current_search_session&.query_params || {})[:q] @@ -70,6 +71,10 @@ def choose_canvas_id(sir_trevor_block) sir_trevor_block&.items&.dig(0, 'iiif_canvas_id') if sir_trevor_block.respond_to? :items end + def choose_initial_viewer_config(sir_trevor_block) + sir_trevor_block&.items&.dig(0, 'iiif_initial_viewer_config') if sir_trevor_block.respond_to? :items + end + def context_specific_oembed_url(document) if feature_flags.uat_embed? && document['druid'].present? format(Settings.purl.uat_url, druid: document['druid']) diff --git a/app/views/catalog/_embedded_mirador3.html.erb b/app/views/catalog/_embedded_mirador3.html.erb index fb9bcd905..9fd623ce0 100644 --- a/app/views/catalog/_embedded_mirador3.html.erb +++ b/app/views/catalog/_embedded_mirador3.html.erb @@ -1,7 +1,7 @@ <% if document.manifest_url.present? %> <% manifest_url = document.manifest_url.starts_with?('/') ? root_url + document.manifest_url.slice(1..-1) : document.manifest_url %> <%= content_tag :iframe, '', - src: "#{Settings.iiif_embed.url}?#{{ url: manifest_url }.to_query}", + src: "#{Settings.iiif_embed.url}?#{{ url: manifest_url, canvas_id: choose_canvas_id(block) || params[:canvas_id], iiif_initial_viewer_config: choose_initial_viewer_config(block) || params[:iiif_initial_viewer_config]}.to_query}", allowfullscreen: true, class: 'mirador-embed-wrapper', frameborder: 0, diff --git a/app/views/catalog/select_image_area.html.erb b/app/views/catalog/select_image_area.html.erb new file mode 100644 index 000000000..5cc5eebf0 --- /dev/null +++ b/app/views/catalog/select_image_area.html.erb @@ -0,0 +1,35 @@ +<%= render Blacklight::System::ModalComponent.new do |component| %> + <% component.with_title do %> +
+ Adjust the image so that the viewer contains the area you want to display to exhibit visitors. +
+ <%= link_to params[:id], spotlight.exhibit_solr_document_path(current_exhibit, params[:id]) %> does on exist in this exhibit. +
+ <% end %> +