Skip to content

Commit

Permalink
show remove button on selection, new condition for location removal wip
Browse files Browse the repository at this point in the history
  • Loading branch information
davidcam-src committed Feb 12, 2024
1 parent 8d560bb commit 3d57af7
Show file tree
Hide file tree
Showing 3 changed files with 210 additions and 10 deletions.
66 changes: 66 additions & 0 deletions app/assets/javascripts/hyrax/autocomplete/linked_data.es6
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// Autocomplete for linked data elements using a select2 autocomplete widget
// After selecting something, the seleted item is immutable
export default class LinkedData {
constructor(element, url) {
this.url = url
this.element = element
this.activate()
}

activate() {
this.element
.select2(this.options(this.element))
.on("change", (e) => { this.selected(e) })
}

// Called when a choice is made
selected(e) {
let result = this.element.select2("data")
this.element.select2("destroy")
this.element.val(result.label).attr("readonly", "readonly")
let removeButton = this.element.closest('.field-wrapper').find('.input-group-btn.field-controls .remove');
removeButton.addClass('show');
this.setIdentifier(result.id)
}

// Store the uri in the associated hidden id field
setIdentifier(uri) {
this.element.closest('.field-wrapper').find('[data-id]').val(uri);
}

options(element) {
return {
// placeholder: $(this).attr("value") || "Search for a location",
minimumInputLength: 2,
id: function(object) {
return object.id;
},
text: function(object) {
return object.label;
},
initSelection: function(element, callback) {
// Called when Select2 is created to allow the user to initialize the
// selection based on the value of the element select2 is attached to.
// Essentially this is an id->object mapping function.
var data = {
id: element.val(),
label: element[0].dataset.label || element.val()
};
callback(data);
},
ajax: { // Use the jQuery.ajax wrapper provided by Select2
url: this.url,
dataType: "json",
data: function (term, page) {
return {
q: term // Search term
};
},
results: function(data, page) {
return { results: data };
}
}
}
}
}

141 changes: 141 additions & 0 deletions app/assets/javascripts/hyrax/editor/controlled_vocabulary.es6
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
//= require handlebars

import { FieldManager } from 'hydra-editor/field_manager'
import Handlebars from 'handlebars'
import Autocomplete from 'hyrax/autocomplete'

export default class ControlledVocabulary extends FieldManager {

constructor(element, paramKey) {
let options = {
/* callback to run after add is called */
add: null,
/* callback to run after remove is called */
remove: null,

controlsHtml: '<span class=\"input-group-btn field-controls\">',
fieldWrapperClass: '.field-wrapper',
warningClass: '.has-warning',
listClass: '.listing',
inputTypeClass: '.controlled_vocabulary',

addHtml: '<button type=\"button\" class=\"btn btn-link add\"><span class=\"fa fa-plus\"></span><span class="controls-add-text"></span></button>',
addText: 'Add another',

removeHtml: '<button type=\"button\" class=\"btn btn-link remove\"><span class=\"fa fa-minus\"></span><span class="controls-remove-text"></span> <span class=\"sr-only\"> previous <span class="controls-field-name-text">field</span></span></button>',
removeText: 'Remove',

labelControls: true,
}
super(element, $.extend({}, options, $(element).data()))
this.paramKey = paramKey
this.fieldName = this.element.data('fieldName')
this.searchUrl = this.element.data('autocompleteUrl')
}

// Overrides FieldManager, because field manager uses the wrong selector
// addToList( event ) {
// event.preventDefault();
// let $listing = $(event.target).closest('.multi_value').find(this.listClass)
// let $activeField = $listing.children('li').last()
//
// if (this.inputIsEmpty($activeField)) {
// this.displayEmptyWarning();
// } else {
// this.clearEmptyWarning();
// $listing.append(this._newField($activeField));
// }
//
// this._manageFocus()
// }

// Overrides FieldManager in order to avoid doing a clone of the existing field
createNewField($activeField) {
// Using querySelector to find elements with data-attribute="based_near"
const basedNearElements = document.querySelectorAll('[data-attribute="based_near"]');

// Log the count of found elements to the console
console.log('Count of elements with data-attribute="based_near":', basedNearElements.length);
let $newField = this._newFieldTemplate()
this._addBehaviorsToInput($newField)
this.element.trigger("managed_field:add", $newField);
return $newField
}

/* This gives the index for the editor */
_maxIndex() {
return $(this.fieldWrapperClass, this.element).length
}

// Overridden because we always want to permit adding another row
inputIsEmpty(activeField) {
return false
}

_newFieldTemplate() {
let index = this._maxIndex()
let rowTemplate = this._template()
let controls = this.controls.clone()//.append(this.remover)
let row = $(rowTemplate({ "paramKey": this.paramKey,
"name": this.fieldName,
"index": index,
"class": "controlled_vocabulary" }))
.append(controls)
return row
}

get _source() {
return "<li class=\"field-wrapper input-group input-append\">" +
"<input class=\"string {{class}} optional form-control {{paramKey}}_{{name}} form-control multi-text-field\" name=\"{{paramKey}}[{{name}}_attributes][{{index}}][hidden_label]\" value=\"\" id=\"{{paramKey}}_{{name}}_attributes_{{index}}_hidden_label\" data-attribute=\"{{name}}\" type=\"text\">" +
"<input name=\"{{paramKey}}[{{name}}_attributes][{{index}}][id]\" value=\"\" id=\"{{paramKey}}_{{name}}_attributes_{{index}}_id\" type=\"hidden\" data-id=\"remote\">" +
"<input name=\"{{paramKey}}[{{name}}_attributes][{{index}}][_destroy]\" id=\"{{paramKey}}_{{name}}_attributes_{{index}}__destroy\" value=\"\" data-destroy=\"true\" type=\"hidden\"></li>"
}

_template() {
return Handlebars.compile(this._source)
}

/**
* @param {jQuery} $newField - The <li> tag
*/
_addBehaviorsToInput($newField) {
let $newInput = $('input.multi-text-field', $newField)
$newInput.focus()
this.addAutocompleteToEditor($newInput)
this.element.trigger("managed_field:add", $newInput)
}

/**
* Make new element have autocomplete behavior
* @param {jQuery} input - The <input type="text"> tag
*/
addAutocompleteToEditor(input) {
var autocomplete = new Autocomplete()
autocomplete.setup(input, this.fieldName, this.searchUrl)
}

// Overrides FieldManager
// Instead of removing the line, we override this method to add a
// '_destroy' hidden parameter
removeFromList( event ) {
event.preventDefault()

let field = $(event.target).parents(this.fieldWrapperClass)
field.find('[data-destroy]').val('true')
field.hide()
this.element.trigger("managed_field:remove", field)

// Changing behavior of the remove button to add a new field if the last field is removed
// Using querySelector to find elements with data-attribute="based_near"
const basedNearElements = document.querySelectorAll('[data-attribute="based_near"]');
const parentsArray = Array.from(basedNearElements).map(element => element.parentElement);
const nonHiddenElements = parentsArray.filter(element => element.style.display !== 'none');
const nonHiddenCount = nonHiddenElements.length;

console.log(nonHiddenCount);
if (nonHiddenCount < 1){
console.log('You cannot remove the last element, replacing');
this._newFieldTemplate()
}
}
}
13 changes: 3 additions & 10 deletions app/assets/stylesheets/hyrax.scss
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,7 @@
@import "hyrax/blacklight_gallery";
@import 'hyrax/hyrax';

// [hyc-override] Custom CSS to show Remove button for first of type Location controlled vocabulary
.controlled_vocabulary {
.listing {
li:first-of-type {
.remove {
display: block;
}
}
}
}
.show {
display: block !important;
}

0 comments on commit 3d57af7

Please sign in to comment.