diff --git a/.rubocop.yml b/.rubocop.yml index a849dd007..f43923c7f 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -17,6 +17,7 @@ AllCops: - "config/**/*" - "vendor/**/*" - "spec/fixtures/**/*" + - "node_modules/**/*" Rails: Enabled: true diff --git a/Gemfile b/Gemfile index c0bc7809e..18e251b3b 100644 --- a/Gemfile +++ b/Gemfile @@ -136,3 +136,5 @@ gem 'recaptcha', '~> 5.17.1' gem 'rack-attack' gem 'cssbundling-rails', '~> 1.4' + +gem 'jsbundling-rails', '~> 1.3' diff --git a/Gemfile.lock b/Gemfile.lock index f0836b04b..fbe6f8876 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -450,6 +450,8 @@ GEM rails-dom-testing (>= 1, < 3) railties (>= 4.2.0) thor (>= 0.14, < 2.0) + jsbundling-rails (1.3.1) + railties (>= 6.0.0) json (2.9.0) jsonpath (1.1.5) multi_json @@ -931,6 +933,7 @@ DEPENDENCIES iiif-presentation jbuilder (~> 2.7) jquery-rails + jsbundling-rails (~> 1.3) jsonpath letter_opener listen (~> 3.3) diff --git a/Procfile.dev b/Procfile.dev index 18f64d232..6e11fb626 100644 --- a/Procfile.dev +++ b/Procfile.dev @@ -1,2 +1,3 @@ web: env RUBY_DEBUG_OPEN=true bin/rails server css: yarn watch:css +js: yarn build --watch diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js deleted file mode 100644 index 2661203dc..000000000 --- a/app/assets/javascripts/application.js +++ /dev/null @@ -1,39 +0,0 @@ -// This is a manifest file that'll be compiled into application.js, which will include all the files -// listed below. -// -// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts, -// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path. -// -// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the -// compiled file. -// -// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details -// about supported directives. -// -//= require jquery3 -//= require 'honeybadger' - -//= require rails-ujs -//= require turbolinks -// -// Required by Blacklight -//= require blacklight/blacklight - -//= require popper -//= require twitter/typeahead -//= require bootstrap - -//= require bibliography -//= require cited_documents -//= require blacklight_gallery -//= require blacklight_heatmaps -//= require blacklight_oembed -//= require full_text_collapse -//= require index_status_typeahead -//= require exhibit_search_typeahead -//= require nested_related_items -//= require openseadragon -//= require spotlight -//= require table_of_contents -//= require site_search_type_toggle -//= require blacklight_heatmaps_overrides diff --git a/app/assets/javascripts/bibliography.js b/app/assets/javascripts/bibliography.js deleted file mode 100644 index 3d0d80bbf..000000000 --- a/app/assets/javascripts/bibliography.js +++ /dev/null @@ -1,110 +0,0 @@ -/* eslint-disable camelcase */ -/* global Bibliography */ - -(function (global) { - var Bibliography; - - Bibliography = { - options: { toggleThreshold: 5, toggleIndex: 2 }, - - init: function (el) { - var _this = this; - var $el = $(el); - var data = $el.data(); - - if (el.dataset.initialized) { - const toggleButton = $el.find('.bibliography-button'); - if (toggleButton.length > 0) { - this.bindToggleButtonHandler(toggleButton); - } - return; - } - - $.getJSON(data.path, { - 'f[related_document_id_ssim][]': data.parentid, - 'f[format_main_ssim][]': 'Reference', - sort: data.sort, - format: 'json', - rows: '1000' - }, function (response) { - var docTotal = response.data.length; - if (docTotal > 0) { - el.dataset.initialized = true; - $el.show(); - var bibliographyList = $el.find('.bibliography-list'); - - for (var i = 0; i < docTotal; i++) { - var bibEntry = response.data[i]; - var html = _this.bibliographyItemTemplate( - bibEntry, data.path, i, docTotal - ); - bibliographyList.append(html); - } - - if (docTotal > _this.options.toggleThreshold) { - bibliographyList.append(_this.toggleButton()); - } - } - }); - }, - - bibliographyItemTemplate: function(bibEntry, path, index, total) { - var elClass = 'bibliography-body'; - var toggleIndex = this.options.toggleIndex; - var toggleThreshold = this.options.toggleThreshold; - - if (index > toggleIndex && total > toggleThreshold) { - elClass += ' hide-bibliography'; - } - - // This string contains the formatted bibliography for this item. - // This string can contain HTML elements as well which should be displayed correctly. - var formatted_bibliography = bibEntry.attributes.formatted_bibliography_ts.attributes.value; - - return '

' + - formatted_bibliography + - ' ' + - '[View full reference]' + - '' + - '

'; - }, - - bindToggleButtonHandler: function(button) { - button.on('click', function() { - var bibliosToToggle = button.parent().find('.hide-bibliography'); - var hidden = bibliosToToggle.first().is(':hidden'); - bibliosToToggle.toggle(); - - if(hidden) { - button.find('[data-behavior="text"]').text('Collapse bibliography'); - button.addClass('bibliography-expanded'); - } else { - button.find('[data-behavior="text"]').text('Expand bibliography'); - button.removeClass('bibliography-expanded'); - } - }); - }, - - toggleButton: function() { - var button = $( - '' - ); - - this.bindToggleButtonHandler(button); - return button; - } - }; - - global.Bibliography = Bibliography; -}(this)); - -Blacklight.onLoad(function () { - 'use strict'; - - $('[data-behavior="bibliography-contents"]').each(function (i, element) { - Bibliography.init(element); // eslint-disable-line no-undef - }); -}); diff --git a/app/assets/javascripts/blacklight_gallery.js b/app/assets/javascripts/blacklight_gallery.js deleted file mode 100644 index 992a7d4df..000000000 --- a/app/assets/javascripts/blacklight_gallery.js +++ /dev/null @@ -1 +0,0 @@ -//= require blacklight_gallery/default \ No newline at end of file diff --git a/app/assets/javascripts/blacklight_heatmaps.js b/app/assets/javascripts/blacklight_heatmaps.js deleted file mode 100644 index ab7416596..000000000 --- a/app/assets/javascripts/blacklight_heatmaps.js +++ /dev/null @@ -1 +0,0 @@ -//= require blacklight_heatmaps/default diff --git a/app/assets/javascripts/cited_documents.js b/app/assets/javascripts/cited_documents.js deleted file mode 100644 index 6c75eac58..000000000 --- a/app/assets/javascripts/cited_documents.js +++ /dev/null @@ -1,44 +0,0 @@ -/* eslint-disable camelcase */ -/* global CitedDocuments */ -/* global Blacklight */ - -(function (global) { - var CitedDocuments; - - CitedDocuments = { - init: function (el) { - var $el = $(el); - const citedDocList = $el.find('.cited-documents-list'); - // Prevent repeat script run on page back - if (citedDocList[0].innerHTML != '') return; - - var data = $el.data(); - var queryIds = data.documentids.join(' '); - - - $.post(data.path, { - ids: queryIds, - format: 'json', - }, function (response) { - response.forEach(function(citedDocEntry) { - var html = '
  • ' + - ' ' + - citedDocEntry['title_display'] + - '' + - '
  • '; - citedDocList.append(html); - }); - }); - } - }; - - global.CitedDocuments = CitedDocuments; -}(this)); - -Blacklight.onLoad(function () { - 'use strict'; - - $('[data-behavior="cited-documents-contents"]').each(function (i, element) { - CitedDocuments.init(element); // eslint-disable-line no-undef - }); -}); diff --git a/app/assets/javascripts/exhibit_search_typeahead.js b/app/assets/javascripts/exhibit_search_typeahead.js deleted file mode 100644 index c46002d26..000000000 --- a/app/assets/javascripts/exhibit_search_typeahead.js +++ /dev/null @@ -1,53 +0,0 @@ -/* global Blacklight */ -/* global Bloodhound */ -/* global ExhibitSearchTypeahead */ - -(function (global) { - var ExhibitSearchTypeahead; - - ExhibitSearchTypeahead = { - form: null, - typeaheadElement: null, - typeaheadElementInput: null, - - init: function (el) { - var _this = this; - _this.typeaheadElement = el.closest('auto-complete'); - _this.typeaheadElementInput = el; - _this.form = el.closest('form'); - _this.preventFormSubmitOnTypeahead(); - - _this.typeaheadElement.addEventListener('auto-complete-change', function(e) { - const slug = e.relatedTarget.value; - - if (!slug) return; - - e.relatedTarget.value = _this.getTitleFromSlug(slug); - window.location = '/' + slug; - }); - }, - - preventFormSubmitOnTypeahead: function() { - this.form.addEventListener('submit', (e) => { - if (document.activeElement === this.typeaheadElementInput) { - e.preventDefault(); - } - }); - }, - - getTitleFromSlug: function(slug) { - const option = this.typeaheadElement.querySelector(`[data-autocomplete-value="${slug}"][role="option"]`); - return option.dataset.autocompleteTitle; - } - }; - - global.ExhibitSearchTypeahead = ExhibitSearchTypeahead; -}(this)); - -Blacklight.onLoad(function () { - 'use strict'; - - document.querySelectorAll('[data-behavior="exhibit-search-typeahead"]').forEach((element) => { - ExhibitSearchTypeahead.init(element); - }); -}); diff --git a/app/assets/javascripts/index_status_typeahead.js b/app/assets/javascripts/index_status_typeahead.js deleted file mode 100644 index 12d32313c..000000000 --- a/app/assets/javascripts/index_status_typeahead.js +++ /dev/null @@ -1,86 +0,0 @@ -/* global Blacklight */ -/* global Bloodhound */ -/* global IndexStatusTypeahead */ - -(function (global) { - var IndexStatusTypeahead; - - IndexStatusTypeahead = { - itemStatusRemoteUrl: null, - - indexStatusTable: function() { - return $('[data-behavior="index-status-typeahead-table"]'); - }, - - init: function (el) { - var _this = this; - const completer = el.closest('auto-complete'); - _this.itemStatusRemoteUrl = completer.dataset.typeaheadRemoteUrl; - - completer.addEventListener('submit', function(e) { - e.preventDefault(); - }); - - completer.addEventListener('auto-complete-change', function(e) { - const option = completer.querySelector(`[data-autocomplete-value="${e.relatedTarget.value}"][role="option"]`); - if (option) { - _this.addIndexStatusRow(option.dataset.autocompleteValue); - } - }); - }, - - addIndexStatusRow: function(druid) { - if(this.indexStatusRow(druid).length > 0) { - return; // Return if there is already an index status row present - } - - this.indexStatusTable().show(); // Ensure the table is shown - this.indexStatusTable().find('tbody').append( - [ - '', - '' + druid + '', - '', - '' - ].join('\n') - ); - - this.updateItemIndexStatus(druid); - }, - - // Getter for an index status row given a druid - indexStatusRow: function(druid) { - return $('tr[data-index-status-id="' + druid + '"]'); - }, - - updateItemIndexStatus: function(druid) { - var _this = this; - $.ajax({ url: _this.itemStatusRemoteUrl + '/' + druid }) - .done(function(data) { - var row = _this.indexStatusRow(druid); - - if (!data.status.ok) { - row.addClass('danger'); - } - - var itemStatusCell = row.find('td[data-behavior="index-item-status"]'); - itemStatusCell.text( - data.status.ok ? 'Published' : data.status.message - ); - }); - }, - - druids: function() { - return $('[data-index-status-content]').data('index-status-content'); - }, - }; - - global.IndexStatusTypeahead = IndexStatusTypeahead; -}(this)); - -Blacklight.onLoad(function () { - 'use strict'; - - document.querySelectorAll('[data-behavior="index-status-typeahead"]').forEach((element) => { - IndexStatusTypeahead.init(element); // eslint-disable-line no-undef - }); -}); diff --git a/app/assets/javascripts/nested_related_items.js b/app/assets/javascripts/nested_related_items.js deleted file mode 100644 index 15b8219ee..000000000 --- a/app/assets/javascripts/nested_related_items.js +++ /dev/null @@ -1,103 +0,0 @@ -/* global Blacklight */ -/* global NestedRelatedItems */ - -(function (global) { - var NestedRelatedItems; - - NestedRelatedItems = { - options: { itemSelector: 'li.mods_display_nested_related_item' }, - init: function (el) { - var _this = this; - var listItems = _this.listItems(el); - listItems.each(function() { - $(this).removeClass('open'); - _this.addToggleLink($(this)); - }); - - if (listItems.has('dl').length > 0) { - _this.addToggleAll(el); - } - }, - - listItems: function(list) { - return list.find(this.options.itemSelector); - }, - - addToggleAll: function(content) { - // find the preceding
    - var title = $(content).parents('dd').prev(); - var el = $('Expand all'); - this.toggleAll(el, content); - title.append(el); - }, - - addToggleLink: function(content) { - var dl = content.find('dl'); - - if(dl.length > 0) { - // Hide and remove the dl (so we can deal with just the text below) - dl.hide(); - dl.detach(); - // Replace the content of the list item - // with the current text wrapped in a link - content.html(this.linkElement(content)); - // Add the dl back in - content.append(dl); - } - }, - - linkElement: function(content) { - var _this = this; - var link = $('' + content.text() + ''); - link.on('click', function() { - _this.toggleMetadata($(this)); - }); - - return link; - }, - - toggleAll: function(el, content) { - var _this = this; - el.on('click', function(){ - var toggleLink = $(this); - toggleLink.toggleClass('open'); - toggleLink.text((toggleLink.text() == 'Collapse all') ? 'Expand all' : 'Collapse all'); - var links = _this.listItems(content); - - // Handle mixed lists of open / closed items - if (toggleLink.hasClass('open')){ - links = links.not('.open').find('a'); - } else { - links = links.filter($('.open')).find('a'); - } - links.each(function(){ - _this.toggleMetadata($(this)); - }); - }); - }, - - toggleMetadata: function(item) { - var listItem = item.parent('li'); - listItem.toggleClass('open'); - listItem.find('dl').toggle(); - } - }; - - global.NestedRelatedItems = NestedRelatedItems; -}(this)); - -Blacklight.onLoad(function () { - 'use strict'; - - // Load JS in Bootstrap modal - document.querySelector('#blacklight-modal').addEventListener('loaded.blacklight.blacklight-modal', function (e) { - $('.mods_display_nested_related_items').each(function (i, element) { - NestedRelatedItems.init($(element)); // eslint-disable-line no-undef - }); - }); - - // Metadata page - $('.mods_display_nested_related_items').each(function (i, element) { - NestedRelatedItems.init($(element)); // eslint-disable-line no-undef - }); -}); diff --git a/app/assets/javascripts/openseadragon.js b/app/assets/javascripts/openseadragon.js deleted file mode 100644 index 2ab91a9f1..000000000 --- a/app/assets/javascripts/openseadragon.js +++ /dev/null @@ -1,2 +0,0 @@ -//= require openseadragon/openseadragon -//= require openseadragon/rails \ No newline at end of file diff --git a/app/assets/javascripts/site_search_type_toggle.js b/app/assets/javascripts/site_search_type_toggle.js deleted file mode 100644 index 9922ef123..000000000 --- a/app/assets/javascripts/site_search_type_toggle.js +++ /dev/null @@ -1,47 +0,0 @@ -/* global Blacklight */ -/* global SiteSearchTypeToggle */ - -(function (global) { - var SiteSearchTypeToggle; - - SiteSearchTypeToggle = { - menuOptions: [], - init: function (el) { - var _this = this; - var button = el.find('button.dropdown-toggle'); - var menuItems = el.find('.dropdown-menu .dropdown-item'); - _this.menuOptions = $('[data-behavior="site-search-type"]'); - _this.hideAllMenuOptions(); - el.show(); - - $(el.data('enabled')).show(); - - menuItems.each(function() { - $(this).on('click', function(e) { - e.preventDefault(); - - _this.hideAllMenuOptions(); - $($(this).data('bs-target')).show(); - - button.text($(this).data('buttonText')); - }); - }); - }, - - hideAllMenuOptions: function() { - this.menuOptions.each(function() { - $(this).hide(); - }); - } - }; - - global.SiteSearchTypeToggle = SiteSearchTypeToggle; -}(this)); - -Blacklight.onLoad(function () { - 'use strict'; - - $('[data-behavior="site-search-type-toggle"]').each(function (i, element) { - SiteSearchTypeToggle.init($(element)); // eslint-disable-line no-undef - }); -}); diff --git a/app/javascript/application.js b/app/javascript/application.js new file mode 100644 index 000000000..efb998c00 --- /dev/null +++ b/app/javascript/application.js @@ -0,0 +1,30 @@ +// Entry point for the build script in your package.json + +//= require rails-ujs +//= require turbolinks +// +// Required by Blacklight +import './blacklight' +import './sir_trevor' + +import "spotlight-frontend/app/assets/javascripts/spotlight/spotlight.esm.js"; +import githubAutoCompleteElement from "@github/auto-complete-element"; + +import './bibliography' +import './cited_documents' +import 'blacklight-gallery/vendor/assets/javascripts/imagesloaded.pkgd.js' +import 'blacklight-gallery/app/assets/javascripts/blacklight_gallery/slideshow' +import 'blacklight-gallery/app/assets/javascripts/blacklight_gallery/masonry' + +import './blacklight_heatmaps' + + +import 'blacklight-oembed' +import './full_text_collapse' +import './index_status_typeahead' +import './exhibit_search_typeahead' +import './nested_related_items' +import 'openseadragon-rails' +import './table_of_contents' +import './site_search_type_toggle' +import './blacklight_heatmaps_overrides' diff --git a/app/javascript/bibliography.js b/app/javascript/bibliography.js new file mode 100644 index 000000000..29ad27e6a --- /dev/null +++ b/app/javascript/bibliography.js @@ -0,0 +1,103 @@ +/* eslint-disable camelcase */ + +const Bibliography = { + options: { toggleThreshold: 5, toggleIndex: 2 }, + + init: function (el) { + var _this = this; + var $el = $(el); + var data = $el.data(); + + if (el.dataset.initialized) { + const toggleButton = $el.find('.bibliography-button'); + if (toggleButton.length > 0) { + this.bindToggleButtonHandler(toggleButton); + } + return; + } + + $.getJSON(data.path, { + 'f[related_document_id_ssim][]': data.parentid, + 'f[format_main_ssim][]': 'Reference', + sort: data.sort, + format: 'json', + rows: '1000' + }, function (response) { + var docTotal = response.data.length; + if (docTotal > 0) { + el.dataset.initialized = true; + $el.show(); + var bibliographyList = $el.find('.bibliography-list'); + + for (var i = 0; i < docTotal; i++) { + var bibEntry = response.data[i]; + var html = _this.bibliographyItemTemplate( + bibEntry, data.path, i, docTotal + ); + bibliographyList.append(html); + } + + if (docTotal > _this.options.toggleThreshold) { + bibliographyList.append(_this.toggleButton()); + } + } + }); + }, + + bibliographyItemTemplate: function(bibEntry, path, index, total) { + var elClass = 'bibliography-body'; + var toggleIndex = this.options.toggleIndex; + var toggleThreshold = this.options.toggleThreshold; + + if (index > toggleIndex && total > toggleThreshold) { + elClass += ' hide-bibliography'; + } + + // This string contains the formatted bibliography for this item. + // This string can contain HTML elements as well which should be displayed correctly. + var formatted_bibliography = bibEntry.attributes.formatted_bibliography_ts.attributes.value; + + return '

    ' + + formatted_bibliography + + ' ' + + '[View full reference]' + + '' + + '

    '; + }, + + bindToggleButtonHandler: function(button) { + button.on('click', function() { + var bibliosToToggle = button.parent().find('.hide-bibliography'); + var hidden = bibliosToToggle.first().is(':hidden'); + bibliosToToggle.toggle(); + + if(hidden) { + button.find('[data-behavior="text"]').text('Collapse bibliography'); + button.addClass('bibliography-expanded'); + } else { + button.find('[data-behavior="text"]').text('Expand bibliography'); + button.removeClass('bibliography-expanded'); + } + }); + }, + + toggleButton: function() { + var button = $( + '' + ); + + this.bindToggleButtonHandler(button); + return button; + } +}; + +Blacklight.onLoad(function () { + 'use strict'; + + $('[data-behavior="bibliography-contents"]').each(function (i, element) { + Bibliography.init(element); // eslint-disable-line no-undef + }); +}); diff --git a/app/javascript/blacklight.js b/app/javascript/blacklight.js new file mode 100644 index 000000000..71003e9d8 --- /dev/null +++ b/app/javascript/blacklight.js @@ -0,0 +1,2 @@ +import Blacklight from "blacklight-frontend"; +window.Blacklight = Blacklight diff --git a/app/javascript/blacklight_heatmaps.js b/app/javascript/blacklight_heatmaps.js new file mode 100644 index 000000000..a7d5ff076 --- /dev/null +++ b/app/javascript/blacklight_heatmaps.js @@ -0,0 +1,6 @@ +import 'blacklight-heatmaps/vendor/assets/javascripts/leaflet_solr_heatmap' +import BlacklightHeatmaps from 'blacklight-heatmaps/app/assets/javascripts/blacklight_heatmaps/blacklight_heatmaps' +import 'blacklight-heatmaps/app/assets/javascripts/blacklight_heatmaps/basemaps' +import 'blacklight-heatmaps/app/assets/javascripts/blacklight_heatmaps/icons' +import 'blacklight-heatmaps/app/assets/javascripts/blacklight_heatmaps/viewers/index' +import 'blacklight-heatmaps/app/assets/javascripts/blacklight_heatmaps/viewers/show' diff --git a/app/assets/javascripts/blacklight_heatmaps_overrides.js b/app/javascript/blacklight_heatmaps_overrides.js similarity index 100% rename from app/assets/javascripts/blacklight_heatmaps_overrides.js rename to app/javascript/blacklight_heatmaps_overrides.js diff --git a/app/assets/javascripts/blacklight_oembed.js b/app/javascript/blacklight_oembed.js similarity index 100% rename from app/assets/javascripts/blacklight_oembed.js rename to app/javascript/blacklight_oembed.js diff --git a/app/javascript/cited_documents.js b/app/javascript/cited_documents.js new file mode 100644 index 000000000..0336c2689 --- /dev/null +++ b/app/javascript/cited_documents.js @@ -0,0 +1,36 @@ +/* global Blacklight */ + +const CitedDocuments = { + init: function (el) { + var $el = $(el); + const citedDocList = $el.find('.cited-documents-list'); + // Prevent repeat script run on page back + if (citedDocList[0].innerHTML != '') return; + + var data = $el.data(); + var queryIds = data.documentids.join(' '); + + + $.post(data.path, { + ids: queryIds, + format: 'json', + }, function (response) { + response.forEach(function(citedDocEntry) { + var html = '
  • ' + + ' ' + + citedDocEntry['title_display'] + + '' + + '
  • '; + citedDocList.append(html); + }); + }); + } +}; + +Blacklight.onLoad(function () { + 'use strict'; + + $('[data-behavior="cited-documents-contents"]').each(function (i, element) { + CitedDocuments.init(element); // eslint-disable-line no-undef + }); +}); diff --git a/app/javascript/exhibit_search_typeahead.js b/app/javascript/exhibit_search_typeahead.js new file mode 100644 index 000000000..7b1fec40a --- /dev/null +++ b/app/javascript/exhibit_search_typeahead.js @@ -0,0 +1,45 @@ +/* global Blacklight */ + +const ExhibitSearchTypeahead = { + form: null, + typeaheadElement: null, + typeaheadElementInput: null, + + init: function (el) { + var _this = this; + _this.typeaheadElement = el.closest('auto-complete'); + _this.typeaheadElementInput = el; + _this.form = el.closest('form'); + _this.preventFormSubmitOnTypeahead(); + + _this.typeaheadElement.addEventListener('auto-complete-change', function(e) { + const slug = e.relatedTarget.value; + + if (!slug) return; + + e.relatedTarget.value = _this.getTitleFromSlug(slug); + window.location = '/' + slug; + }); + }, + + preventFormSubmitOnTypeahead: function() { + this.form.addEventListener('submit', (e) => { + if (document.activeElement === this.typeaheadElementInput) { + e.preventDefault(); + } + }); + }, + + getTitleFromSlug: function(slug) { + const option = this.typeaheadElement.querySelector(`[data-autocomplete-value="${slug}"][role="option"]`); + return option.dataset.autocompleteTitle; + } +}; + +Blacklight.onLoad(function () { + 'use strict'; + + document.querySelectorAll('[data-behavior="exhibit-search-typeahead"]').forEach((element) => { + ExhibitSearchTypeahead.init(element); + }); +}); diff --git a/app/assets/javascripts/full_text_collapse.js b/app/javascript/full_text_collapse.js similarity index 100% rename from app/assets/javascripts/full_text_collapse.js rename to app/javascript/full_text_collapse.js diff --git a/app/javascript/index_status_typeahead.js b/app/javascript/index_status_typeahead.js new file mode 100644 index 000000000..ea7623193 --- /dev/null +++ b/app/javascript/index_status_typeahead.js @@ -0,0 +1,78 @@ +/* global Blacklight */ + +const IndexStatusTypeahead = { + itemStatusRemoteUrl: null, + + indexStatusTable: function() { + return $('[data-behavior="index-status-typeahead-table"]'); + }, + + init: function (el) { + var _this = this; + const completer = el.closest('auto-complete'); + _this.itemStatusRemoteUrl = completer.dataset.typeaheadRemoteUrl; + + completer.addEventListener('submit', function(e) { + e.preventDefault(); + }); + + completer.addEventListener('auto-complete-change', function(e) { + const option = completer.querySelector(`[data-autocomplete-value="${e.relatedTarget.value}"][role="option"]`); + if (option) { + _this.addIndexStatusRow(option.dataset.autocompleteValue); + } + }); + }, + + addIndexStatusRow: function(druid) { + if(this.indexStatusRow(druid).length > 0) { + return; // Return if there is already an index status row present + } + + this.indexStatusTable().show(); // Ensure the table is shown + this.indexStatusTable().find('tbody').append( + [ + '', + '' + druid + '', + '', + '' + ].join('\n') + ); + + this.updateItemIndexStatus(druid); + }, + + // Getter for an index status row given a druid + indexStatusRow: function(druid) { + return $('tr[data-index-status-id="' + druid + '"]'); + }, + + updateItemIndexStatus: function(druid) { + var _this = this; + $.ajax({ url: _this.itemStatusRemoteUrl + '/' + druid }) + .done(function(data) { + var row = _this.indexStatusRow(druid); + + if (!data.status.ok) { + row.addClass('danger'); + } + + var itemStatusCell = row.find('td[data-behavior="index-item-status"]'); + itemStatusCell.text( + data.status.ok ? 'Published' : data.status.message + ); + }); + }, + + druids: function() { + return $('[data-index-status-content]').data('index-status-content'); + }, +}; + +Blacklight.onLoad(function () { + 'use strict'; + + document.querySelectorAll('[data-behavior="index-status-typeahead"]').forEach((element) => { + IndexStatusTypeahead.init(element); // eslint-disable-line no-undef + }); +}); diff --git a/app/javascript/nested_related_items.js b/app/javascript/nested_related_items.js new file mode 100644 index 000000000..c88e8e280 --- /dev/null +++ b/app/javascript/nested_related_items.js @@ -0,0 +1,96 @@ +/* global Blacklight */ + +const NestedRelatedItems = { + options: { itemSelector: 'li.mods_display_nested_related_item' }, + init: function (el) { + var _this = this; + var listItems = _this.listItems(el); + listItems.each(function() { + $(this).removeClass('open'); + _this.addToggleLink($(this)); + }); + + if (listItems.has('dl').length > 0) { + _this.addToggleAll(el); + } + }, + + listItems: function(list) { + return list.find(this.options.itemSelector); + }, + + addToggleAll: function(content) { + // find the preceding
    + var title = $(content).parents('dd').prev(); + var el = $('Expand all'); + this.toggleAll(el, content); + title.append(el); + }, + + addToggleLink: function(content) { + var dl = content.find('dl'); + + if(dl.length > 0) { + // Hide and remove the dl (so we can deal with just the text below) + dl.hide(); + dl.detach(); + // Replace the content of the list item + // with the current text wrapped in a link + content.html(this.linkElement(content)); + // Add the dl back in + content.append(dl); + } + }, + + linkElement: function(content) { + var _this = this; + var link = $('' + content.text() + ''); + link.on('click', function() { + _this.toggleMetadata($(this)); + }); + + return link; + }, + + toggleAll: function(el, content) { + var _this = this; + el.on('click', function(){ + var toggleLink = $(this); + toggleLink.toggleClass('open'); + toggleLink.text((toggleLink.text() == 'Collapse all') ? 'Expand all' : 'Collapse all'); + var links = _this.listItems(content); + + // Handle mixed lists of open / closed items + if (toggleLink.hasClass('open')){ + links = links.not('.open').find('a'); + } else { + links = links.filter($('.open')).find('a'); + } + links.each(function(){ + _this.toggleMetadata($(this)); + }); + }); + }, + + toggleMetadata: function(item) { + var listItem = item.parent('li'); + listItem.toggleClass('open'); + listItem.find('dl').toggle(); + } +}; + +Blacklight.onLoad(function () { + 'use strict'; + + // Load JS in Bootstrap modal + document.querySelector('#blacklight-modal').addEventListener('loaded.blacklight.blacklight-modal', function (e) { + $('.mods_display_nested_related_items').each(function (i, element) { + NestedRelatedItems.init($(element)); // eslint-disable-line no-undef + }); + }); + + // Metadata page + $('.mods_display_nested_related_items').each(function (i, element) { + NestedRelatedItems.init($(element)); // eslint-disable-line no-undef + }); +}); diff --git a/app/javascript/sir_trevor.js b/app/javascript/sir_trevor.js new file mode 100644 index 000000000..4946216c0 --- /dev/null +++ b/app/javascript/sir_trevor.js @@ -0,0 +1,2 @@ +import SirTrevor from 'sir-trevor' +window.SirTrevor = SirTrevor diff --git a/app/assets/javascripts/sir_trevor_block_overrides.js b/app/javascript/sir_trevor_block_overrides.js similarity index 100% rename from app/assets/javascripts/sir_trevor_block_overrides.js rename to app/javascript/sir_trevor_block_overrides.js diff --git a/app/javascript/site_search_type_toggle.js b/app/javascript/site_search_type_toggle.js new file mode 100644 index 000000000..a398f8d00 --- /dev/null +++ b/app/javascript/site_search_type_toggle.js @@ -0,0 +1,40 @@ +/* global Blacklight */ + +const SiteSearchTypeToggle = { + menuOptions: [], + init: function (el) { + var _this = this; + var button = el.find('button.dropdown-toggle'); + var menuItems = el.find('.dropdown-menu .dropdown-item'); + _this.menuOptions = $('[data-behavior="site-search-type"]'); + _this.hideAllMenuOptions(); + el.show(); + + $(el.data('enabled')).show(); + + menuItems.each(function() { + $(this).on('click', function(e) { + e.preventDefault(); + + _this.hideAllMenuOptions(); + $($(this).data('bs-target')).show(); + + button.text($(this).data('buttonText')); + }); + }); + }, + + hideAllMenuOptions: function() { + this.menuOptions.each(function() { + $(this).hide(); + }); + } +}; + +Blacklight.onLoad(function () { + 'use strict'; + + $('[data-behavior="site-search-type-toggle"]').each(function (i, element) { + SiteSearchTypeToggle.init($(element)); // eslint-disable-line no-undef + }); +}); diff --git a/app/assets/javascripts/spotlight.js b/app/javascript/spotlight.js similarity index 100% rename from app/assets/javascripts/spotlight.js rename to app/javascript/spotlight.js diff --git a/app/assets/javascripts/table_of_contents.js b/app/javascript/table_of_contents.js similarity index 100% rename from app/assets/javascripts/table_of_contents.js rename to app/javascript/table_of_contents.js diff --git a/app/views/layouts/spotlight/base.html.erb b/app/views/layouts/spotlight/base.html.erb index a3c1bb68c..fd1d6869a 100644 --- a/app/views/layouts/spotlight/base.html.erb +++ b/app/views/layouts/spotlight/base.html.erb @@ -18,7 +18,16 @@ <% end %> <%= stylesheet_link_tag "component_library_overrides" %> - <%= javascript_include_tag "application", async: Settings.async_javascript %> + + + <%= javascript_include_tag "application", "data-turbo-track": "reload", type: "module" %> +