diff --git a/app/assets/javascripts/spotlight/spotlight.esm.js b/app/assets/javascripts/spotlight/spotlight.esm.js index 3c41c1653..7cd927a8b 100644 --- a/app/assets/javascripts/spotlight/spotlight.esm.js +++ b/app/assets/javascripts/spotlight/spotlight.esm.js @@ -3609,38 +3609,136 @@ class Iiif { function addImageSelector(input, panel, manifestUrl, initialize) { if (!manifestUrl) { showNonIiifAlert(input); - return; + return } - var cropper = input.data('iiifCropper'); - $.ajax(manifestUrl).done( - function(manifest) { - var iiifManifest = new Iiif(manifestUrl, manifest); - var thumbs = iiifManifest.imagesArray(); + // Get the cropper from the input element's data + let cropper = input.dataset.iiifCropper; + if (typeof cropper === "string") { + try { + cropper = JSON.parse(cropper); + } catch (e) { + // Handle parsing error if needed + } + } + + // Use fetch instead of $.ajax + fetch(manifestUrl) + .then(response => { + if (!response.ok) { + throw new Error(`HTTP error! Status: ${response.status}`) + } + return response.json() + }) + .then(manifest => { + const iiifManifest = new Iiif(manifestUrl, manifest); + const thumbs = iiifManifest.imagesArray(); hideNonIiifAlert(input); if (initialize) { cropper.setIiifFields(thumbs[0]); - panel.multiImageSelector(); // Clears out existing selector + + // Assuming multiImageSelector is a custom function that needs to be called on panel + if (typeof panel.multiImageSelector === "function") { + panel.multiImageSelector(); // Clears out existing selector + } else { + // If panel is a DOM element and not a custom object + const multiImageSelector = panel.querySelector( + '[data-behavior="multi-image-selector"]' + ); + if (multiImageSelector) { + // Clear the selector + multiImageSelector.innerHTML = ""; + } + } } - if(thumbs.length > 1) { - panel.show(); - panel.multiImageSelector(thumbs, function(selectorImage) { - cropper.setIiifFields(selectorImage); - }, cropper.iiifImageField.val()); + if (thumbs.length > 1) { + // Show panel + panel.style.display = "block"; + + // Call multiImageSelector with parameters + if (typeof panel.multiImageSelector === "function") { + panel.multiImageSelector( + thumbs, + function (selectorImage) { + cropper.setIiifFields(selectorImage); + }, + cropper.iiifImageField.value + ); + } else { + // If panel is a DOM element, implement the selector functionality + const multiImageSelector = panel.querySelector( + '[data-behavior="multi-image-selector"]' + ); + if (multiImageSelector) { + createMultiImageSelector( + multiImageSelector, + thumbs, + function (selectorImage) { + cropper.setIiifFields(selectorImage); + }, + cropper.iiifImageField.value + ); + } + } } - } - ); + }) + .catch(error => { + console.error("Error fetching manifest:", error); + }); +} + +function showNonIiifAlert(input) { + const alert = input.parentNode.previousElementSibling; + if (alert && alert.dataset.behavior === "non-iiif-alert") { + alert.style.display = "block"; + } } -function showNonIiifAlert(input){ - input.parent().prev('[data-behavior="non-iiif-alert"]').show(); +function hideNonIiifAlert(input) { + const alert = input.parentNode.previousElementSibling; + if (alert && alert.dataset.behavior === "non-iiif-alert") { + alert.style.display = "none"; + } } -function hideNonIiifAlert(input){ - input.parent().prev('[data-behavior="non-iiif-alert"]').hide(); +// Helper function to implement multiImageSelector functionality +function createMultiImageSelector(container, thumbs, callback, selectedValue) { + // Clear existing content + container.innerHTML = ""; + + // Create image selector elements + thumbs.forEach(thumb => { + const imgElement = document.createElement("img"); + imgElement.src = thumb.thumbnail || thumb.url; + imgElement.alt = thumb.label || ""; + imgElement.classList.add("iiif-image"); + + // Add selected class if this is the selected value + if ( + selectedValue && + (selectedValue === thumb.id || selectedValue === thumb.url) + ) { + imgElement.classList.add("selected"); + } + + imgElement.addEventListener("click", function () { + // Remove selected class from all images + container.querySelectorAll(".iiif-image").forEach(img => { + img.classList.remove("selected"); + }); + + // Add selected class to clicked image + imgElement.classList.add("selected"); + + // Call the callback with the selected image data + callback(thumb); + }); + + container.appendChild(imgElement); + }); } const Spotlight$1 = function() { @@ -3674,33 +3772,56 @@ window.SirTrevor = SirTrevor$1; class Crop { constructor(cropArea, preserveAspectRatio = true) { this.cropArea = cropArea; - this.cropArea.data('iiifCropper', this); + this.cropArea.data("iiifCropper", this); // This element will also have the IIIF input elements contained // There may be multiple elements with data-cropper attributes, but // there should only one element with this data-cropper attribute value. - this.cropSelector = '[data-cropper="' + cropArea.data('cropperKey') + '"]'; + this.cropSelector = '[data-cropper="' + cropArea.data("cropperKey") + '"]'; this.cropTool = $(this.cropSelector); // Exhibit and masthead cropping requires the ratio between image width and height - // to be consistent, whereas item widget cropping allows any combination of + // to be consistent, whereas item widget cropping allows any combination of // image width and height. this.preserveAspectRatio = preserveAspectRatio; // Get the IIIF input elements used to store/reference IIIF information - this.inputPrefix = this.cropTool.data('input-prefix'); - this.iiifUrlField = this.iiifInputElement(this.inputPrefix, 'iiif_tilesource', this.cropTool); - this.iiifRegionField = this.iiifInputElement(this.inputPrefix, 'iiif_region', this.cropTool); - this.iiifManifestField = this.iiifInputElement(this.inputPrefix, 'iiif_manifest_url', this.cropTool); - this.iiifCanvasField = this.iiifInputElement(this.inputPrefix, 'iiif_canvas_id', this.cropTool); - this.iiifImageField = this.iiifInputElement(this.inputPrefix, 'iiif_image_id', this.cropTool); + this.inputPrefix = this.cropTool.data("input-prefix"); + this.iiifUrlField = this.iiifInputElement( + this.inputPrefix, + "iiif_tilesource", + this.cropTool + ); + this.iiifRegionField = this.iiifInputElement( + this.inputPrefix, + "iiif_region", + this.cropTool + ); + this.iiifManifestField = this.iiifInputElement( + this.inputPrefix, + "iiif_manifest_url", + this.cropTool + ); + this.iiifCanvasField = this.iiifInputElement( + this.inputPrefix, + "iiif_canvas_id", + this.cropTool + ); + this.iiifImageField = this.iiifInputElement( + this.inputPrefix, + "iiif_image_id", + this.cropTool + ); // Get the closest form element - this.form = cropArea.closest('form'); + this.form = cropArea.closest("form"); this.tileSource = null; } // Return the iiif input element based on the fieldname. - // Multiple input fields with the same name on the page may be related - // to a cropper. We thus need to pass in a parent element. + // Multiple input fields with the same name on the page may be related + // to a cropper. We thus need to pass in a parent element. iiifInputElement(inputPrefix, fieldName, inputParentElement) { - return $('input[name="' + inputPrefix + '[' + fieldName + ']"]', inputParentElement); + return $( + 'input[name="' + inputPrefix + "[" + fieldName + ']"]', + inputParentElement + ) } // Render the cropper environment and add hooks into the autocomplete and upload forms @@ -3713,8 +3834,8 @@ class Crop { // Setup the cropper on page load if the field // that holds the IIIF url is populated setupExistingIiifCropper() { - if(this.iiifUrlField.val() === '') { - return; + if (this.iiifUrlField.val() === "") { + return } this.addImageSelectorToExistingCropTool(); @@ -3731,8 +3852,8 @@ class Crop { // Force a broken layer's container to be an element before removing. // Code in leaflet-iiif land calls delete on the image layer's container when removing, // which errors if there is an issue fetching the info.json and stops further necessary steps to execute. - if(!this.imageLayer._container) { - this.imageLayer._container = $('
'); + if (!this.imageLayer._container) { + this.imageLayer._container = $("
"); } this.cropperMap.removeLayer(this.imageLayer); } @@ -3740,7 +3861,7 @@ class Crop { this.imageLayer = L.tileLayer.iiif(this.tileSource).addTo(this.cropperMap); var self = this; - this.imageLayer.on('load', function() { + this.imageLayer.on("load", function () { if (!self.loaded) { var region = self.getCropRegion(); self.positionIiifCropBox(region); @@ -3748,18 +3869,18 @@ class Crop { } }); - this.cropArea.data('initiallyVisible', this.cropArea.is(':visible')); + this.cropArea.data("initiallyVisible", this.cropArea.is(":visible")); } // Get (or initialize) the current crop region from the form data getCropRegion() { var regionFieldValue = this.iiifRegionField.val(); - if(!regionFieldValue || regionFieldValue === '') { + if (!regionFieldValue || regionFieldValue === "") { var region = this.defaultCropRegion(); this.iiifRegionField.val(region); - return region; + return region } else { - return regionFieldValue.split(','); + return regionFieldValue.split(",") } } @@ -3776,14 +3897,14 @@ class Crop { Math.floor((imageHeight - boxHeight) / 2), boxWidth, boxHeight - ]; + ] } // Calculate the required aspect ratio for the crop area aspectRatio() { - var cropWidth = parseInt(this.cropArea.data('crop-width')); - var cropHeight = parseInt(this.cropArea.data('crop-height')); - return cropWidth / cropHeight; + var cropWidth = parseInt(this.cropArea.data("crop-width")); + var cropHeight = parseInt(this.cropArea.data("crop-height")); + return cropWidth / cropHeight } // Position the IIIF Crop Box at the given IIIF region @@ -3815,12 +3936,12 @@ class Crop { // Set the Crop tileSource and setup the cropper setTileSource(source) { if (source == this.tileSource) { - return; + return } if (source === null || source === undefined) { - console.error('No tilesource provided when setting up IIIF Cropper'); - return; + console.error("No tilesource provided when setting up IIIF Cropper"); + return } if (this.cropBox) { @@ -3835,7 +3956,7 @@ class Crop { // Render the Leaflet Map into the crop area renderCropperMap() { if (this.cropperMap) { - return; + return } var cropperOptions = { @@ -3845,13 +3966,15 @@ class Crop { zoom: 0 }; - if(this.preserveAspectRatio) { - cropperOptions['editOptions'] = { - rectangleEditorClass: this.aspectRatioPreservingRectangleEditor(this.aspectRatio()) + if (this.preserveAspectRatio) { + cropperOptions["editOptions"] = { + rectangleEditorClass: this.aspectRatioPreservingRectangleEditor( + this.aspectRatio() + ) }; } - this.cropperMap = L.map(this.cropArea.attr('id'), cropperOptions); + this.cropperMap = L.map(this.cropArea.attr("id"), cropperOptions); this.invalidateMapSizeOnTabToggle(); } @@ -3860,21 +3983,26 @@ class Crop { this.cropBox = L.rectangle(initialBounds); this.cropBox.addTo(this.cropperMap); this.cropBox.enableEdit(); - this.cropBox.on('dblclick', L.DomEvent.stop).on('dblclick', this.cropBox.toggleEdit); + this.cropBox + .on("dblclick", L.DomEvent.stop) + .on("dblclick", this.cropBox.toggleEdit); var self = this; - this.cropperMap.on('editable:dragend editable:vertex:dragend', function(e) { - var bounds = e.layer.getBounds(); - var region = self.projectBoundsToIIIFRegion(bounds); + this.cropperMap.on( + "editable:dragend editable:vertex:dragend", + function (e) { + var bounds = e.layer.getBounds(); + var region = self.projectBoundsToIIIFRegion(bounds); - self.iiifRegionField.val(region.join(',')); - }); + self.iiifRegionField.val(region.join(",")); + } + ); } // Get the maximum zoom level for the IIIF Layer (always 1:1 image pixel to canvas?) maxZoom() { - if(this.imageLayer) { - return this.imageLayer.maxZoom; + if (this.imageLayer) { + return this.imageLayer.maxZoom } } @@ -3887,17 +4015,20 @@ class Crop { Math.max(Math.floor(min.y), 0), Math.floor(max.x - min.x), Math.floor(max.y - min.y) - ]; + ] } // Take a IIIF [x, y, w, h] region and transform it into a Leaflet LatLngBounds unprojectIIIFRegionToBounds(region) { var minPoint = L.point(parseInt(region[0]), parseInt(region[1])); - var maxPoint = L.point(parseInt(region[0]) + parseInt(region[2]), parseInt(region[1]) + parseInt(region[3])); + var maxPoint = L.point( + parseInt(region[0]) + parseInt(region[2]), + parseInt(region[1]) + parseInt(region[3]) + ); var min = this.cropperMap.unproject(minPoint, this.maxZoom()); var max = this.cropperMap.unproject(maxPoint, this.maxZoom()); - return L.latLngBounds(min, max); + return L.latLngBounds(min, max) } // TODO: Add accessors to update hidden inputs with IIIF uri/ids? @@ -3905,7 +4036,7 @@ class Crop { // Setup autocomplete inputs to have the iiif_cropper context setupAutoCompletes() { var input = $('[data-behavior="autocomplete"]', this.cropTool); - input.data('iiifCropper', this); + input.data("iiifCropper", this); } setupAjaxFileUpload() { @@ -3914,28 +4045,36 @@ class Crop { } addImageSelectorToExistingCropTool() { - if(this.iiifManifestField.val() === '') { - return; + if (this.iiifManifestField.val() === "") { + return } var input = $('[data-behavior="autocomplete"]', this.cropTool); - + // Not every page which uses this module has autocomplete linked directly to the cropping tool - if(input.length) { - var panel = $(input.data('target-panel')); - addImageSelector(input, panel, this.iiifManifestField.val(), !this.iiifImageField.val()); + if (input.length) { + var panel = $(input.data("target-panel")); + addImageSelector( + input[0], + panel[0], + this.iiifManifestField.val(), + !this.iiifImageField.val() + ); } } invalidateMapSizeOnTabToggle() { var tabs = $('[role="tablist"]', this.form); var self = this; - tabs.on('shown.bs.tab', function() { - if(self.cropArea.data('initiallyVisible') === false && self.cropArea.is(':visible')) { + tabs.on("shown.bs.tab", function () { + if ( + self.cropArea.data("initiallyVisible") === false && + self.cropArea.is(":visible") + ) { self.cropperMap.invalidateSize(); // Because the map size is 0,0 when image is loading (not visible) we need to refit the bounds of the layer self.imageLayer._fitBounds(); - self.cropArea.data('initiallyVisible', null); + self.cropArea.data("initiallyVisible", null); } }); } @@ -3943,23 +4082,23 @@ class Crop { // Get all the form data with the exception of the _method field. getData() { var data = new FormData(this.form[0]); - data.append('_method', null); - return data; + data.append("_method", null); + return data } uploadFile() { - var url = this.fileInput.data('endpoint'); + var url = this.fileInput.data("endpoint"); // Every post creates a new image/masthead. // Because they create IIIF urls which are heavily cached. $.ajax({ - url: url, //Server script to process data - type: 'POST', + url: url, //Server script to process data + type: "POST", success: (data, stat, xhr) => this.successHandler(data, stat, xhr), error: (xhr, stat, error) => this.errorHandler(xhr, stat, error), // Form data data: this.getData(), headers: { - 'X-CSRF-Token': Spotlight$1.csrfToken() || '' + "X-CSRF-Token": Spotlight$1.csrfToken() || "" }, //Options to tell jQuery not to process data or worry about content-type. cache: false, @@ -3978,7 +4117,7 @@ class Crop { let errorMessage = "Upload failed"; if (xhr.responseJSON) { if (xhr.responseJSON.errors) { - errorMessage = xhr.responseJSON.errors.join(', '); + errorMessage = xhr.responseJSON.errors.join(", "); } else if (xhr.responseJSON.error) { errorMessage = xhr.responseJSON.error; } @@ -4009,8 +4148,8 @@ class Crop { setUploadId(id) { // This input is currently used for exhibit masthead or thumbnail image upload. // The name should be sufficient in this case, as we don't use this part of the - // code for solr document widgets where we enable cropping. - // If we require more specificity, we can scope this to this.cropTool. + // code for solr document widgets where we enable cropping. + // If we require more specificity, we can scope this to this.cropTool. $('input[name="' + this.inputPrefix + '[upload_id]"]').val(id); } @@ -4018,17 +4157,23 @@ class Crop { return L.Editable.RectangleEditor.extend({ extendBounds: function (e) { var index = e.vertex.getIndex(), - next = e.vertex.getNext(), - previous = e.vertex.getPrevious(), - oppositeIndex = (index + 2) % 4, - opposite = e.vertex.latlngs[oppositeIndex]; + next = e.vertex.getNext(), + previous = e.vertex.getPrevious(), + oppositeIndex = (index + 2) % 4, + opposite = e.vertex.latlngs[oppositeIndex]; - if ((index % 2) == 1) { + if (index % 2 == 1) { // calculate horiz. displacement - e.latlng.update([opposite.lat + ((1 / aspect) * (opposite.lng - e.latlng.lng)), e.latlng.lng]); + e.latlng.update([ + opposite.lat + (1 / aspect) * (opposite.lng - e.latlng.lng), + e.latlng.lng + ]); } else { // calculate vert. displacement - e.latlng.update([e.latlng.lat, (opposite.lng - (aspect * (opposite.lat - e.latlng.lat)))]); + e.latlng.update([ + e.latlng.lat, + opposite.lng - aspect * (opposite.lat - e.latlng.lat) + ]); } var bounds = new L.LatLngBounds(e.latlng, opposite); // Update latlngs by hand to preserve order. @@ -4037,7 +4182,7 @@ class Crop { this.updateBounds(bounds); this.refreshVertexMarkers(); } - }); + }) } } @@ -4871,73 +5016,85 @@ class ReadonlyCheckbox { const docStore = new Map(); function highlight(value, query) { - if (query.trim() === '') return value; + if (query.trim() === "") return value const queryValue = query.trim(); - return queryValue ? value.replace(new RegExp(queryValue, 'gi'), '$&') : value; + return queryValue + ? value.replace(new RegExp(queryValue, "gi"), "$&") + : value } function templateFunc(obj, query) { - const thumbnail = obj.thumbnail ? `
` : ''; - const privateClass = obj.private ? ' blacklight-private' : ''; + const thumbnail = obj.thumbnail + ? `
` + : ""; + const privateClass = obj.private ? " blacklight-private" : ""; const title = highlight(obj.title, query); - const description = obj.description ? `  ${highlight(obj.description, query)}` : ''; + const description = obj.description + ? `  ${highlight(obj.description, query)}` + : ""; return `
${thumbnail} ${title}
${description} -
`; + ` } function autoCompleteElementTemplate(obj, query) { - return `
  • ${templateFunc(obj, query)}
  • `; + return `
  • ${templateFunc(obj, query)}
  • ` } function getAutoCompleteElementDataMap(autoCompleteElement) { if (!docStore.has(autoCompleteElement.id)) { docStore.set(autoCompleteElement.id, new Map()); } - return docStore.get(autoCompleteElement.id); + return docStore.get(autoCompleteElement.id) } async function fetchResult(url) { const result = await fetchAutocompleteJSON(url); const docs = result.docs || []; - const query = this.querySelector('input').value || ''; + const query = this.querySelector("input").value || ""; const autoCompleteElementDataMap = getAutoCompleteElementDataMap(this); - return docs.map(doc => { - autoCompleteElementDataMap.set(doc.id, doc); - return autoCompleteElementTemplate(doc, query); - }).join(''); + return docs + .map(doc => { + autoCompleteElementDataMap.set(doc.id, doc); + return autoCompleteElementTemplate(doc, query) + }) + .join("") } -function addAutocompletetoFeaturedImage(){ - const autocompletePath = $('form[data-autocomplete-exhibit-catalog-path]').data('autocomplete-exhibit-catalog-path'); - const featuredImageTypeaheads = $('[data-featured-image-typeahead]'); - if (featuredImageTypeaheads.length === 0) return; +function addAutocompletetoFeaturedImage() { + const autocompletePath = $( + "form[data-autocomplete-exhibit-catalog-path]" + ).data("autocomplete-exhibit-catalog-path"); + const featuredImageTypeaheads = $("[data-featured-image-typeahead]"); + if (featuredImageTypeaheads.length === 0) return - $.each(featuredImageTypeaheads, function(index, autoCompleteInput) { - const autoCompleteElement = autoCompleteInput.closest('auto-complete'); + $.each(featuredImageTypeaheads, function (index, autoCompleteInput) { + const autoCompleteElement = autoCompleteInput.closest("auto-complete"); - autoCompleteElement.setAttribute('src', autocompletePath); + autoCompleteElement.setAttribute("src", autocompletePath); autoCompleteElement.fetchResult = fetchResult; - autoCompleteElement.addEventListener('auto-complete-change', e => { - const data = getAutoCompleteElementDataMap(autoCompleteElement).get(e.relatedTarget.value); - if (!data) return; + autoCompleteElement.addEventListener("auto-complete-change", e => { + const data = getAutoCompleteElementDataMap(autoCompleteElement).get( + e.relatedTarget.value + ); + if (!data) return const inputElement = $(e.relatedTarget); const panel = document.querySelector(e.relatedTarget.dataset.targetPanel); e.relatedTarget.value = data.title; - addImageSelector(inputElement, $(panel), data.iiif_manifest, true); - $(inputElement.data('id-field')).val(data['global_id']); - inputElement.attr('type', 'text'); + addImageSelector(inputElement[0], panel, data.iiif_manifest, true); + $(inputElement.data("id-field")).val(data["global_id"]); + inputElement.attr("type", "text"); }); }); } async function fetchAutocompleteJSON(url) { - const res = await(fetch(url.toString())); + const res = await fetch(url.toString()); if (!res.ok) { - throw new Error(await res.text()); + throw new Error(await res.text()) } - return await res.json(); + return await res.json() } /* diff --git a/app/assets/javascripts/spotlight/spotlight.esm.js.map b/app/assets/javascripts/spotlight/spotlight.esm.js.map index 9e3e8f392..19986ba93 100644 --- a/app/assets/javascripts/spotlight/spotlight.esm.js.map +++ b/app/assets/javascripts/spotlight/spotlight.esm.js.map @@ -1 +1 @@ -{"version":3,"file":"spotlight.esm.js","sources":["../../../../vendor/assets/javascripts/tiny-slider.js","../../../javascript/spotlight/user/browse_group_categories.js","../../../javascript/spotlight/user/carousel.js","../../../javascript/spotlight/user/clear_form_button.js","../../../javascript/spotlight/user/zpr_links.js","../../../javascript/spotlight/user/index.js","../../../javascript/spotlight/admin/add_another.js","../../../javascript/spotlight/admin/add_new_button.js","../../../javascript/spotlight/admin/blacklight_configuration.js","../../../javascript/spotlight/admin/copy_email_addresses.js","../../../javascript/spotlight/admin/iiif.js","../../../javascript/spotlight/admin/add_image_selector.js","../../../javascript/spotlight/core.js","../../../javascript/spotlight/admin/crop.js","../../../javascript/spotlight/admin/croppable_modal.js","../../../javascript/spotlight/admin/croppable.js","../../../javascript/spotlight/admin/edit_in_place.js","../../../../vendor/assets/javascripts/parameterize.js","../../../javascript/spotlight/admin/exhibits.js","../../../javascript/spotlight/admin/form_observer.js","../../../javascript/spotlight/admin/locks.js","../../../javascript/spotlight/admin/multi_image_selector.js","../../../javascript/spotlight/admin/pages.js","../../../javascript/spotlight/admin/progress_monitor.js","../../../javascript/spotlight/admin/readonly_checkbox.js","../../../javascript/spotlight/admin/search_typeahead.js","../../../javascript/spotlight/admin/select_related_input.js","../../../javascript/spotlight/admin/spotlight_nestable.js","../../../javascript/spotlight/admin/tabs.js","../../../javascript/spotlight/admin/translation_progress.js","../../../javascript/spotlight/admin/visibility_toggle.js","../../../javascript/spotlight/admin/users.js","../../../javascript/spotlight/admin/block_mixins/autocompleteable.js","../../../javascript/spotlight/admin/block_mixins/formable.js","../../../javascript/spotlight/admin/block_mixins/plustextable.js","../../../javascript/spotlight/admin/blocks/block.js","../../../javascript/spotlight/admin/blocks/resources_block.js","../../../javascript/spotlight/admin/blocks/browse_block.js","../../../javascript/spotlight/admin/blocks/browse_group_categories_block.js","../../../javascript/spotlight/admin/blocks/iframe_block.js","../../../javascript/spotlight/admin/blocks/link_to_search_block.js","../../../javascript/spotlight/admin/blocks/oembed_block.js","../../../javascript/spotlight/admin/blocks/pages_block.js","../../../javascript/spotlight/admin/blocks/rule_block.js","../../../javascript/spotlight/admin/blocks/search_result_block.js","../../../javascript/spotlight/admin/blocks/solr_documents_base_block.js","../../../javascript/spotlight/admin/blocks/solr_documents_block.js","../../../javascript/spotlight/admin/blocks/solr_documents_carousel_block.js","../../../javascript/spotlight/admin/blocks/solr_documents_embed_block.js","../../../javascript/spotlight/admin/blocks/solr_documents_features_block.js","../../../javascript/spotlight/admin/blocks/solr_documents_grid_block.js","../../../javascript/spotlight/admin/blocks/uploaded_items_block.js","../../../javascript/spotlight/admin/sir-trevor/block_controls.js","../../../javascript/spotlight/admin/sir-trevor/block_limits.js","../../../javascript/spotlight/admin/sir-trevor/locales.js","../../../javascript/spotlight/admin/index.js","../../../javascript/spotlight/controllers/tag_selector_controller.js","../../../javascript/spotlight/controllers/index.js","../../../javascript/spotlight/index.js"],"sourcesContent":["// Includes an unreleased RTL support pull request: https://github.com/ganlanyuan/tiny-slider/pull/658\n// Includes \"export default tns\" at the end of the file for spotlight/user/browse_group_categories.js\nvar tns = (function (){\nvar win = window;\n\nvar raf = win.requestAnimationFrame\n || win.webkitRequestAnimationFrame\n || win.mozRequestAnimationFrame\n || win.msRequestAnimationFrame\n || function(cb) { return setTimeout(cb, 16); };\n\nvar win$1 = window;\n\nvar caf = win$1.cancelAnimationFrame\n || win$1.mozCancelAnimationFrame\n || function(id){ clearTimeout(id); };\n\nfunction extend() {\n var obj, name, copy,\n target = arguments[0] || {},\n i = 1,\n length = arguments.length;\n\n for (; i < length; i++) {\n if ((obj = arguments[i]) !== null) {\n for (name in obj) {\n copy = obj[name];\n\n if (target === copy) {\n continue;\n } else if (copy !== undefined) {\n target[name] = copy;\n }\n }\n }\n }\n return target;\n}\n\nfunction checkStorageValue (value) {\n return ['true', 'false'].indexOf(value) >= 0 ? JSON.parse(value) : value;\n}\n\nfunction setLocalStorage(storage, key, value, access) {\n if (access) {\n try { storage.setItem(key, value); } catch (e) {}\n }\n return value;\n}\n\nfunction getSlideId() {\n var id = window.tnsId;\n window.tnsId = !id ? 1 : id + 1;\n \n return 'tns' + window.tnsId;\n}\n\nfunction getBody () {\n var doc = document,\n body = doc.body;\n\n if (!body) {\n body = doc.createElement('body');\n body.fake = true;\n }\n\n return body;\n}\n\nvar docElement = document.documentElement;\n\nfunction setFakeBody (body) {\n var docOverflow = '';\n if (body.fake) {\n docOverflow = docElement.style.overflow;\n //avoid crashing IE8, if background image is used\n body.style.background = '';\n //Safari 5.13/5.1.4 OSX stops loading if ::-webkit-scrollbar is used and scrollbars are visible\n body.style.overflow = docElement.style.overflow = 'hidden';\n docElement.appendChild(body);\n }\n\n return docOverflow;\n}\n\nfunction resetFakeBody (body, docOverflow) {\n if (body.fake) {\n body.remove();\n docElement.style.overflow = docOverflow;\n // Trigger layout so kinetic scrolling isn't disabled in iOS6+\n // eslint-disable-next-line\n docElement.offsetHeight;\n }\n}\n\n// get css-calc \n\nfunction calc() {\n var doc = document, \n body = getBody(),\n docOverflow = setFakeBody(body),\n div = doc.createElement('div'), \n result = false;\n\n body.appendChild(div);\n try {\n var str = '(10px * 10)',\n vals = ['calc' + str, '-moz-calc' + str, '-webkit-calc' + str],\n val;\n for (var i = 0; i < 3; i++) {\n val = vals[i];\n div.style.width = val;\n if (div.offsetWidth === 100) { \n result = val.replace(str, ''); \n break;\n }\n }\n } catch (e) {}\n \n body.fake ? resetFakeBody(body, docOverflow) : div.remove();\n\n return result;\n}\n\n// get subpixel support value\n\nfunction percentageLayout() {\n // check subpixel layout supporting\n var doc = document,\n body = getBody(),\n docOverflow = setFakeBody(body),\n wrapper = doc.createElement('div'),\n outer = doc.createElement('div'),\n str = '',\n count = 70,\n perPage = 3,\n supported = false;\n\n wrapper.className = \"tns-t-subp2\";\n outer.className = \"tns-t-ct\";\n\n for (var i = 0; i < count; i++) {\n str += '
    ';\n }\n\n outer.innerHTML = str;\n wrapper.appendChild(outer);\n body.appendChild(wrapper);\n\n supported = Math.abs(wrapper.getBoundingClientRect().left - outer.children[count - perPage].getBoundingClientRect().left) < 2;\n\n body.fake ? resetFakeBody(body, docOverflow) : wrapper.remove();\n\n return supported;\n}\n\nfunction mediaquerySupport () {\n if (window.matchMedia || window.msMatchMedia) {\n return true;\n }\n \n var doc = document,\n body = getBody(),\n docOverflow = setFakeBody(body),\n div = doc.createElement('div'),\n style = doc.createElement('style'),\n rule = '@media all and (min-width:1px){.tns-mq-test{position:absolute}}',\n position;\n\n style.type = 'text/css';\n div.className = 'tns-mq-test';\n\n body.appendChild(style);\n body.appendChild(div);\n\n if (style.styleSheet) {\n style.styleSheet.cssText = rule;\n } else {\n style.appendChild(doc.createTextNode(rule));\n }\n\n position = window.getComputedStyle ? window.getComputedStyle(div).position : div.currentStyle['position'];\n\n body.fake ? resetFakeBody(body, docOverflow) : div.remove();\n\n return position === \"absolute\";\n}\n\n// create and append style sheet\nfunction createStyleSheet (media, nonce) {\n // Create the