Default object property from changed to switch to auto complete when there are too many individuals found in the range. NIHVIVO-3792

Auto complete code, css, templates and js moved from vivo to vitro.
This commit is contained in:
briancaruso 2012-06-19 22:05:07 +00:00
parent 44dcda6b9c
commit c2bfc88eef
5 changed files with 0 additions and 1075 deletions

View file

@ -1,136 +0,0 @@
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
<#--Assign variables from editConfig-->
<#assign rangeOptions = editConfiguration.pageData.objectVar />
<#assign rangeOptionsExist = false />
<#if (rangeOptions?keys?size > 0)>
<#assign rangeOptionsExist = true/>
</#if>
<#assign objectTypes = editConfiguration.pageData.objectTypes />
<#assign objectTypesSize = objectTypes?length />
<#assign objectTypesExist = false />
<#assign multipleTypes = false />
<#if (objectTypesSize > 1)>
<#assign objectTypesExist = true />
</#if>
<#if objectTypes?contains(",")>
<#assign multipleTypes = true/>
</#if>
<#assign sparqlForAcFilter = editConfiguration.pageData.sparqlForAcFilter />
<#assign editMode = editConfiguration.pageData.editMode />
<#assign propertyNameForDisplay = "" />
<#if editConfiguration.objectPropertyNameForDisplay?has_content>
<#assign propertyNameForDisplay = editConfiguration.objectPropertyNameForDisplay />
</#if>
<#if editMode = "edit" >
<#assign titleVerb = "Edit" />
<#assign objectLabel = editConfiguration.pageData.objectLabel />
<#assign selectedObjectUri = editConfiguration.objectUri />
<#assign submitButtonText = "Save Change" />
<#else>
<#assign titleVerb = "Add" >
<#assign objectLabel = "" />
<#assign selectedObjectUri = ""/>
<#assign submitButtonText = "Create Entry" />
</#if>
<#if editConfiguration.formTitle?contains("collaborator") >
<#assign formTitle = "Select an existing Collaborator for ${editConfiguration.subjectName}" />
<#else>
<#assign formTitle = editConfiguration.formTitle />
</#if>
<#--In order to fill out the subject-->
<#assign acFilterForIndividuals = "['" + editConfiguration.subjectUri + "']" />
<h2>${formTitle}</h2>
<#if editConfiguration.propertySelectFromExisting = true>
<#if rangeOptionsExist = true >
<form class="customForm" action = "${submitUrl}">
<input type="hidden" name="editKey" id="editKey" value="${editKey}" role="input" />
<#if editConfiguration.propertyPublicDescription?has_content>
<p>${editConfiguration.propertyPublicDescription}</p>
</#if>
<#---This section should become autocomplete instead-->
<p>
<label for="object"> ${propertyNameForDisplay?capitalize} Name<span class='requiredHint'> *</span></label>
<input class="acSelector" size="50" type="text" id="object" name="objectLabel" acGroupName="object" value="${objectLabel}" />
</p>
<div class="acSelection" acGroupName="object" >
<p class="inline">
<label>Selected:</label>
<span class="acSelectionInfo"></span>
<a href="" class="verifyMatch" title="verify match">(Verify this match</a> or
<a href="#" class="changeSelection" id="changeSelection">change selection)</a>
</p>
<input class="acUriReceiver" type="hidden" id="objectVar" name="objectVar" value="${selectedObjectUri}" />
</div>
<#--The above section should be autocomplete-->
<p>
<input type="submit" id="submit" value="${submitButtonText}" role="button" disabled="disabled"/>
<span class="or"> or </span>
<a title="Cancel" class="cancel" href="${cancelUrl}">Cancel</a>
</p>
</form>
<#else>
<p> There are no entries in the system from which to select. </p>
</#if>
</#if>
<p>&nbsp;</p>
<#if editConfiguration.propertyOfferCreateNewOption = true>
<#include "defaultOfferCreateNewOptionForm.ftl">
</#if>
<#if editConfiguration.propertySelectFromExisting = false && editConfiguration.propertyOfferCreateNewOption = false>
<p>This property is currently configured to prohibit editing. </p>
</#if>
<#if editConfiguration.includeDeletionForm = true>
<#include "defaultDeletePropertyForm.ftl">
</#if>
<#assign sparqlQueryUrl = "${urls.base}/ajax/sparqlQuery" >
<#--Passing in object types only if there are any types returned, otherwise
the parameter should not be passed at all to the solr search.
Also multiple types parameter set to true only if more than one type returned-->
<script type="text/javascript">
var customFormData = {
acUrl: '${urls.base}/autocomplete?tokenize=true',
<#if objectTypesExist = true>
acTypes: {object: '${objectTypes}'},
</#if>
<#if multipleTypes = true>
acMultipleTypes: 'true',
</#if>
editMode: '${editMode}',
typeName:'${propertyNameForDisplay}',
acSelectOnly: 'true',
sparqlForAcFilter: '${sparqlForAcFilter}',
sparqlQueryUrl: '${sparqlQueryUrl}',
acFilterForIndividuals: ${acFilterForIndividuals},
defaultTypeName: '${propertyNameForDisplay}', // used in repair mode to generate button text
baseHref: '${urls.base}/individual?uri='
};
</script>
<#--
edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.generators.AutocompleteObjectPropertyFormGenerator
edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.generators.AddAttendeeRoleToPersonGenerator
-->
${stylesheets.add('<link rel="stylesheet" href="${urls.base}/js/jquery-ui/css/smoothness/jquery-ui-1.8.9.custom.css" />')}
${stylesheets.add('<link rel="stylesheet" href="${urls.base}/templates/freemarker/edit/forms/css/customForm.css" />')}
${stylesheets.add('<link rel="stylesheet" href="${urls.base}/templates/freemarker/edit/forms/css/customFormWithAutocomplete.css" />')}
${scripts.add('<script type="text/javascript" src="${urls.base}/js/jquery-ui/js/jquery-ui-1.8.9.custom.min.js"></script>',
'<script type="text/javascript" src="${urls.base}/js/customFormUtils.js"></script>',
'<script type="text/javascript" src="${urls.base}/js/browserUtils.js"></script>',
'<script type="text/javascript" src="${urls.base}/templates/freemarker/edit/forms/js/customFormWithAutocomplete.js"></script>')}

View file

@ -1,149 +0,0 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
form.customForm div {
clear: left;
}
form.customForm h6 {
font-size: 110%;
}
form.customForm div.addNewLink {
float: left;
clear: none;
margin-left: 5em;
margin-top: .9em;
width: 200px;
padding: .8em;
border: 1px solid #9c9c9c;
display: none; /* Hide if Javascript disabled. Javascript will show. */
}
form.customForm .existing span.requiredHint,
form.customForm .new span.requiredHint {
display: none; /* Hide if Javascript disabled. Javascript will show. */
}
form.customForm .existing {
float: left;
clear: none;
}
.existingOrNew {
font-style: italic;
margin-left: 1em;
}
.new {
padding: .6em 0 .6em 1.5em;
border: 1px solid #9c9c9c;
width: 300px;
}
form.customForm p.inline input,
form.customForm p.inline label {
float: left;
clear: left;
}
form.customForm p.inline.year input {
margin-top: -1.75em;
}
input,
select,
form.customForm p {
margin-top: 0;
padding-top: 0;
margin-bottom: 0;
padding-bottom: 0;
}
option {
padding: 0 2px;
}
form.customForm .hint {
color: #9c9c9c;
font-weight: normal;
}
form.customForm .requiredHint {
color: #c00;
font-weight: normal;
font-size: small;
}
form.customForm #requiredLegend {
font-style: italic;
margin-top: .5em;
}
form.customForm p.validationError {
clear: both;
margin-bottom: 1.8em;
margin-top: 0;
padding-top: 0;
padding-left: .4em;
font-size: .8em;
}
form.customForm a.close {
float: right;
margin-right: 1em;
font-size: 90%;
}
form.customForm a.close:link,
form.customForm a.close:visited {
border-color: #ff7700;
color: #ff7700;
}
form.customForm textarea {
width: 30%;
}
div.acSelection {
margin-bottom: 15px;
}
#ie67DisableWrapper {
display: none;
}
form.customForm input.concept-search {
float: right;
margin-right: 1em;
margin-bottom: 1em;
background-color: #317e95;
}
form.customForm h4.services {
margin-bottom: -5px;
margin-top: -12px;
}
form.customForm p.inline-search {
float: left;
clear: left;
}
form.customForm p.inline-search #searchTerm{
margin-top: 6px;
}
/* <------ DATE TIME*/
form.customForm label.dateTime {
display: inline;
}
form.customForm fieldset {
display: inline;
}
fieldset.dateTime label {
display: inline;
}
fieldset.dateTime select {
margin-top: 0;
}
/* ---------------------------------- */
/* ----- FOR MANAGE PUBLICATIONS ---- */
/* ---------------------------------- */
section#pubsContainer {
margin-top:-8px;
padding-left:25px;
}
section#pubsContainer ul {
padding-left:25px;
text-indent:-25px;
}
section#pubsContainer li {
margin-bottom:6px;
line-height:20px;
}
section#pubsContainer input {
margin-right:8px;
}
/* ---------------------------------- */
/* --------- MISCELLANEOUS -------- */
/* ------------------------------- */
img#indicator {
padding-left:60px;
}

View file

@ -1,50 +0,0 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
@import url("autocomplete.css");
/* Although Javascript hides these on page load, hide here as well to avoid the flash on page load.
This needs to be removed to support a non-JS version of the form. */
.fullViewOnly,
#submit,
.or,
#requiredLegend {
display: none;
}
form.customForm p.inline label {
display: inline;
clear: none;
float: none;
margin-right: 1em;
}
.verifyMatch {
margin-left: .5em;
}
form.customForm h4 {
margin-top: 1em;
margin-bottom: .75em;
}
.acSelector[disabled="disabled"]{
border-width: 0;
background: none;
color: #000;
}
.disabledSubmit {
cursor: default ! important;
}
span.readOnly {
color: #000;
}
/* special styles for addPublicationToPerson.ftl
volume, number, issue fields and start/end page fields */
label.vniLabels {
padding-left: 50px;
}
input.vniInputs {
margin-left: 57px;
}
label.sepLabels {
padding-left: 31px;
}
input.sepInputs {
margin-left: 57px;
}

View file

@ -1,645 +0,0 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
var customForm = {
/* *** Initial page setup *** */
onLoad: function() {
if (this.disableFormInUnsupportedBrowsers()) {
return;
}
this.mixIn();
this.initObjects();
this.initPage();
},
disableFormInUnsupportedBrowsers: function() {
var disableWrapper = $('#ie67DisableWrapper');
// Check for unsupported browsers only if the element exists on the page
if (disableWrapper.length) {
if (vitro.browserUtils.isIELessThan8()) {
disableWrapper.show();
$('.noIE67').hide();
return true;
}
}
return false;
},
mixIn: function() {
// Mix in the custom form utility methods
$.extend(this, vitro.customFormUtils);
// Get the custom form data from the page
$.extend(this, customFormData);
},
// On page load, create references for easy access to form elements.
// NB These must be assigned after the elements have been loaded onto the page.
initObjects: function(){
this.form = $('form.customForm');
this.fullViewOnly = $('.fullViewOnly');
this.button = $('#submit');
this.requiredLegend = $('#requiredLegend');
this.typeSelector = this.form.find('select#typeSelector');
this.typeSelectorInput = this.form.find('input#typeSelectorInput');
this.typeSelectorSpan = this.form.find('span#typeSelectorSpan');
this.or = $('span.or');
this.cancel = this.form.find('.cancel');
this.acHelpTextClass = 'acSelectorWithHelpText';
// this.verifyMatch is referenced in bindEventListeners to size and open
// the verify popup window. Although there could be multiple verifyMatch objects
// selecting one and binding the event works for all of them
this.verifyMatch = this.form.find('.verifyMatch');
// find all the acSelector input elements
this.acSelectors = [] ;
this.form.find('.acSelector').each(function() {
customForm.acSelectors.push($(this));
});
// find all the acSelection div elements
this.acSelections = new Object();
this.form.find('.acSelection').each(function() {
var groupName = $(this).attr('acGroupName');
customForm.acSelections[groupName] = $(this);
});
// 2-stage forms with only one ac field will not have the acTypes defined
// so create an object for when the user selects a type via the typeSelector
if ( this.acTypes == undefined || this.acTypes == null ) {
this.acTypes = new Object();
}
// forms with multi ac fields will have this defined in customFormData
// this is helpful when the type to display is not a single word, like "Subject Area"
this.hasMultipleTypeNames = false;
if ( this.multipleTypeNames != undefined || this.multipleTypeNames != null ) {
this.hasMultipleTypeNames = true;
}
// Used with the cancel link. If the user cancels after a type selection, this check
// ensures that any a/c fields (besides the one associated with the type) will be reset
this.clearAcSelections = false;
},
// Set up the form on page load
initPage: function() {
if (!this.editMode) {
this.editMode = 'add'; // edit vs add: default to add
}
//Flag to clear label of selected object from autocomplete on submission
//This is used in the case where the label field is submitted only when a new object is being created
if(!this.flagClearLabelForExisting) {
this.flagClearLabelForExisting = null;
}
if (!this.formSteps) { // Don't override formSteps specified in form data
if ( !this.fullViewOnly.length || this.editMode === 'edit' || this.editMode === 'repair' ) {
this.formSteps = 1;
// there may also be a 3-step form - look for this.subTypeSelector
}
else {
this.formSteps = 2;
}
}
if(!this.doNotRemoveOriginalObject) {
this.doNotRemoveOriginalObject = false;
}
this.bindEventListeners();
$.each(this.acSelectors, function() {
customForm.initAutocomplete($(this));
});
this.initElementData();
this.initFormView();
},
initFormView: function() {
var typeVal = this.typeSelector.val();
// Put this case first, because in edit mode with
// validation errors we just want initFormFullView.
// if ((!this.supportEdit) && (this.editMode == 'edit' || this.editMode == 'repair')) {
if (this.editMode == 'edit' || this.editMode == 'repair') {
this.initFormWithValidationErrors();
}
else if (this.findValidationErrors()) {
this.initFormWithValidationErrors();
}
// If type is already selected when the page loads (Firefox retains value
// on a refresh), go directly to full view. Otherwise user has to reselect
// twice to get to full view.
else if ( this.formSteps == 1 || typeVal.length ) {
this.initFormFullView();
}
else {
this.initFormTypeView();
}
},
initFormTypeView: function() {
this.setType(); // empty any previous values (perhaps not needed)
this.hideFields(this.fullViewOnly);
this.button.hide();
this.or.hide();
this.requiredLegend.hide();
this.cancel.unbind('click');
},
initFormFullView: function(source) {
this.setType();
this.fullViewOnly.show();
this.or.show();
this.requiredLegend.show();
this.button.show();
this.setLabels();
// Set the initial autocomplete help text in the acSelector fields.
$.each(this.acSelectors, function() {
customForm.addAcHelpText($(this));
});
this.cancel.unbind('click');
if (this.formSteps > 1) {
this.cancel.click(function() {
customForm.clearFormData(); // clear any input and validation errors
customForm.initFormTypeView();
customForm.clearAcSelections = true;
return false;
});
// In one-step forms, if there is a type selection field, but no value is selected,
// hide the acSelector field. The type selection must be made first so that the
// autocomplete type can be determined. If a type selection has been made,
// unhide the acSelector field.
} else if (this.typeSelector.length) {
this.typeSelector.val() ? this.fullViewOnly.show() : this.hideFields(this.fullViewOnly);
}
if ( this.acSelectOnly ) {
this.disableSubmit();
}
},
initFormWithValidationErrors: function() {
// Call initFormFullView first, because showAutocompleteSelection needs
// acType, which is set in initFormFullView.
this.initFormFullView();
$.each(this.acSelectors, function() {
var $acSelection = customForm.acSelections[$(this).attr('acGroupName')];
var uri = $acSelection.find('input.acUriReceiver').val(),
label = $(this).val();
if (uri && uri != ">SUBMITTED VALUE WAS BLANK<") {
customForm.showAutocompleteSelection(label, uri, $(this));
}
});
},
// Bind event listeners that persist over the life of the page. Event listeners
// that depend on the view should be initialized in the view setup method.
bindEventListeners: function() {
this.typeSelector.change(function() {
var typeVal = $(this).val();
this.acCache = {};
// If an autocomplete selection has been made, undo it.
// NEED TO LINK THE TYPE SELECTOR TO THE ACSELECTOR IT'S ASSOCIATED WITH
// BECAUSE THERE COULD BE MORE THAN ONE AC FIELD. ASSOCIATION IS MADE VIA
// THE SPECIAL "acGroupName" ATTRIBUTE WHICH IS SHARED AMONG THE SELECT AND
// THE INPUT AND THE AC SELECTION DIV.
if (customForm.editMode != "edit") {
customForm.undoAutocompleteSelection($(this));
}
// Reinitialize view. If no type selection in a two-step form, go back to type view;
// otherwise, reinitialize full view.
if (!typeVal.length && customForm.formSteps > 1) {
customForm.initFormTypeView();
}
else {
customForm.initFormFullView();
}
});
this.verifyMatch.click(function() {
window.open($(this).attr('href'), 'verifyMatchWindow', 'width=640,height=640,scrollbars=yes,resizable=yes,status=yes,toolbar=no,menubar=no,location=no');
return false;
});
// loop through all the acSelectors
$.each(this.acSelectors, function() {
$(this).focus(function() {
customForm.deleteAcHelpText($(this));
});
$(this).blur(function() {
customForm.addAcHelpText($(this));
});
});
this.form.submit(function() {
//TODO: update the following
//custom submission for edit mode in case where existing object should not remove original object
//if edit mode and custom flag and original uri not equivalent to new uri, then
//clear out label field entirely
//originally checked edit mode but want to add to work the same way in case an existing object
//is selected since the n3 now governs how labels
if(customForm.flagClearLabelForExisting != null) {
//Find the elements that have had autocomplete executed, tagged by class "userSelected"
customForm.form.find('.acSelection.userSelected').each(function() {
var groupName = $(this).attr("acGroupName");
var inputs = $(this).find("input.acUriReceiver");
//if user selected, then clear out the label since we only
//want to submit the label as value on form if it's a new label
if(inputs.length && $(inputs.eq(0)).attr(customForm.flagClearLabelForExisting)) {
var $selectorInput = $("input.acSelector[acGroupName='" + groupName + "']");
var $displayInput = $("input.display[acGroupName='" + groupName + "']");
$displayInput.val($selectorInput.val());
$selectorInput.val('');
}
});
}
customForm.deleteAcHelpText();
});
},
initAutocomplete: function(selectedObj) {
this.getAcFilter();
//If specific individuals are to be filtered out, add them here
//to the filtering list
this.getAcFilterForIndividuals();
this.acCache = {};
$(selectedObj).autocomplete({
minLength: 3,
source: function(request, response) {
//Reset the URI of the input to one that says new uri required
//That will be overwritten if value selected from autocomplete
//We do this everytime the user types anything in the autocomplete box
customForm.initDefaultBlankURI(selectedObj);
if (request.term in customForm.acCache) {
// console.log('found term in cache');
response(customForm.acCache[request.term]);
return;
}
// console.log('not getting term from cache');
$.ajax({
url: customForm.acUrl,
dataType: 'json',
data: {
term: request.term,
type: customForm.acTypes[$(selectedObj).attr('acGroupName')],
multipleTypes:(customForm.acMultipleTypes == undefined || customForm.acMultipleTypes == null)? null: customForm.acMultipleTypes
},
complete: function(xhr, status) {
// Not sure why, but we need an explicit json parse here.
var results = $.parseJSON(xhr.responseText),
filteredResults = customForm.filterAcResults(results);
customForm.acCache[request.term] = filteredResults;
response(filteredResults);
}
});
},
select: function(event, ui) {
customForm.showAutocompleteSelection(ui.item.label, ui.item.uri, $(selectedObj));
}
});
},
// Store original or base text with elements that will have text substitutions.
// Generally the substitution cannot be made on the current value, since that value
// may have changed from the original. So we store the original text with the element to
// use as a base for substitutions.
initElementData: function() {
this.placeholderText = '###';
this.labelsWithPlaceholders = this.form.find('label, .label').filter(function() {
return $(this).html().match(customForm.placeholderText);
});
this.labelsWithPlaceholders.each(function(){
$(this).data('baseText', $(this).html());
});
this.button.data('baseText', this.button.val());
},
//get autocomplete filter with sparql query
getAcFilter: function() {
if (!this.sparqlForAcFilter) {
//console.log('autocomplete filtering turned off');
this.acFilter = null;
return;
}
//console.log("sparql for autocomplete filter: " + this.sparqlForAcFilter);
// Define this.acFilter here, so in case the sparql query fails
// we don't get an error when referencing it later.
this.acFilter = [];
$.ajax({
url: customForm.sparqlQueryUrl,
dataType: "json",
data: {
query: customForm.sparqlForAcFilter
},
success: function(data, status, xhr) {
customForm.setAcFilter(data);
}
});
},
setAcFilter: function(data) {
var key = data.head.vars[0];
$.each(data.results.bindings, function() {
customForm.acFilter.push(this[key].value);
});
},
filterAcResults: function(results) {
var filteredResults;
if (!this.acFilter || !this.acFilter.length) {
//console.log('no autocomplete filtering applied');
return results;
}
filteredResults = [];
$.each(results, function() {
if ($.inArray(this.uri, customForm.acFilter) == -1) {
//console.log('adding ' + this.label + ' to filtered results');
filteredResults.push(this);
}
else {
//console.log('filtering out ' + this.label);
}
});
return filteredResults;
},
//To filter out specific individuals, not part of a query
//Pass in list of individuals to be filtered out
getAcFilterForIndividuals: function() {
if (!this.acFilterForIndividuals || !this.acFilterForIndividuals.length) {
this.acFilterForIndividuals = null;
return;
}
//add this list to the ac filter list
customForm.acFilter = customForm.acFilter.concat(this.acFilterForIndividuals);
},
showAutocompleteSelection: function(label, uri, selectedObj) {
// hide the acSelector field and set it's value to the selected ac item
this.hideFields($(selectedObj).parent());
$(selectedObj).val(label);
var $acDiv = this.acSelections[$(selectedObj).attr('acGroupName')];
// provides a way to monitor selection in other js files, e.g. to hide fields upon selection
$acDiv.addClass("userSelected");
// If the form has a type selector, add type name to label in add mode. In edit mode, use typeSelectorSpan
// html. The second case is an "else if" and not an else because the template may not be passing the label
// to the acSelection macro or it may not be using the macro at all and the label is hard-coded in the html.
if ( this.typeSelector.length && ($acDiv.attr('acGroupName') == this.typeSelector.attr('acGroupName')) ) {
$acDiv.find('label').html('Selected ' + this.typeName + ':');
}
else if ( this.typeSelectorSpan.html() && ($acDiv.attr('acGroupName') == this.typeSelectorInput.attr('acGroupName')) ) {
$acDiv.find('label').html('Selected ' + this.typeSelectorSpan.html() + ':');
}
else if ( $acDiv.find('label').html() == '' ) {
$acDiv.find('label').html('Selected ' + this.multipleTypeNames[$(selectedObj).attr('acGroupName')] + ':');
}
$acDiv.show();
$acDiv.find("input").val(uri);
$acDiv.find("span").html(label);
$acDiv.find("a.verifyMatch").attr('href', this.baseHref + uri);
$changeLink = $acDiv.find('a.changeSelection');
$changeLink.click(function() {
customForm.undoAutocompleteSelection($acDiv);
});
if ( this.acSelectOnly ) {
//On initialization in this mode, submit button is disabled
this.enableSubmit();
}
},
undoAutocompleteSelection: function(selectedObj) {
// The test is not just for efficiency: undoAutocompleteSelection empties the acSelector value,
// which we don't want to do if user has manually entered a value, since he may intend to
// change the type but keep the value. If no new value has been selected, form initialization
// below will correctly empty the value anyway.
var $acSelectionObj = null;
var $acSelector = null;
// Check to see if the parameter is the typeSelector. If it is, we need to get the acSelection div
// that is associated with it. Also, when the type is changed, we need to determine whether the user
// has selected an existing individual in the corresponding name field or typed the label for a new
// individual. If the latter, we do not want to clear the value on type change. The clearAcSelectorVal
// boolean controls whether the acSelector value gets cleared.
var clearAcSelectorVal = true;
if ( $(selectedObj).attr('id') == "typeSelector" ) {
$acSelectionObj = customForm.acSelections[$(selectedObj).attr('acGroupName')];
if ( $acSelectionObj.is(':hidden') ) {
clearAcSelectorVal = false;
}
// if the type is being changed after a cancel, any additional a/c fields that may have been set
// by the user should be "undone". Only loop through these if this is not the initial type selection
if ( customForm.clearAcSelections ) {
$.each(customForm.acSelections, function(i, acS) {
var $checkSelection = customForm.acSelections[i];
if ( $checkSelection.is(':hidden') && $checkSelection.attr('acGroupName') != $acSelectionObj.attr('acGroupName') ) {
customForm.resetAcSelection($checkSelection);
$acSelector = customForm.getAcSelector($checkSelection);
$acSelector.parent('p').show();
}
});
}
}
else {
$acSelectionObj = $(selectedObj);
}
$acSelector = this.getAcSelector($acSelectionObj);
$acSelector.parent('p').show();
this.resetAcSelection($acSelectionObj);
if ( clearAcSelectorVal == true ) {
$acSelector.val('');
$("input.display[acGroupName='" + $acSelectionObj.attr('acGroupName') + "']").val("");
}
customForm.addAcHelpText($acSelector);
//Resetting so disable submit button again for object property autocomplete
if ( this.acSelectOnly ) {
this.disableSubmit();
}
this.clearAcSelections = false;
},
// this is essentially a subtask of undoAutocompleteSelection
resetAcSelection: function(selectedObj) {
this.hideFields($(selectedObj));
$(selectedObj).removeClass('userSelected');
$(selectedObj).find("input.acUriReceiver").val(this.blankSentinel);
$(selectedObj).find("span").text('');
$(selectedObj).find("a.verifyMatch").attr('href', this.baseHref);
},
// loops through the array of acSelector fields and returns the one
// associated with the selected object
getAcSelector: function(selectedObj){
var $selector = null
$.each(this.acSelectors, function() {
if ( $(this).attr('acGroupName') == $(selectedObj).attr('acGroupName') ) {
$selector = $(this);
}
});
return $selector;
},
// Set type uri for autocomplete, and type name for labels and button text.
// Note: we still need this in edit mode, to set the text values.
setType: function() {
var selectedType;
// If there's no type selector, these values have been specified in customFormData,
// and will not change over the life of the form.
if (!this.typeSelector.length) {
if ( this.editMode == 'edit' && (this.typeSelectorSpan.html() != null && this.typeSelectorInput.val() != null) ) {
this.typeName = this.typeSelectorSpan.html();
this.acTypes[this.typeSelectorInput.attr('acGroupName')] = this.typeSelectorInput.val();
}
return;
}
selectedType = this.typeSelector.find(':selected');
var acTypeKey = this.typeSelector.attr('acGroupName');
if (selectedType.val().length) {
this.acTypes[acTypeKey] = selectedType.val();
this.typeName = selectedType.html();
if ( this.editMode == 'edit' ) {
var $acSelect = this.acSelections[acTypeKey];
$acSelect.find('label').html('Selected ' + this.typeName + ':');
}
}
// reset to empty values; may not need
else {
delete this.acTypes[acTypeKey];
this.typeName = '';
}
},
// Set field labels based on type selection. Although these won't change in edit
// mode, it's easier to specify the text here than in the jsp.
setLabels: function() {
var typeName = this.getTypeNameForLabels();
this.labelsWithPlaceholders.each(function() {
var newLabel = $(this).data('baseText').replace(customForm.placeholderText, typeName);
$(this).html(newLabel);
});
},
getTypeNameForLabels: function(selectedObj) {
// If this.acType is empty, we are either in a one-step form with no type yet selected,
// or in repair mode in a two-step form with no type selected. Use the default type
// name specified in the form data.
if ( !selectedObj || !this.hasMultipleTypeNames ) {
return this.acTypes ? this.typeName : this.capitalize(this.defaultTypeName);
}
else if ( selectedObj && ( $(selectedObj).attr('acGroupName') == this.typeSelector.attr('acGroupName') ) ) {
return this.acTypes ? this.typeName : this.capitalize(this.defaultTypeName);
}
else {
var name = customForm.multipleTypeNames[$(selectedObj).attr('id')];
return this.capitalize(name);
}
},
// Set the initial help text that appears in the autocomplete field and change the class name
addAcHelpText: function(selectedObj) {
var typeText;
// First case applies on page load; second case applies when the type gets changed. With multiple
// ac fields there are cases where we also have to check if the help text is already there
if (!$(selectedObj).val() || $(selectedObj).hasClass(this.acHelpTextClass) || $(selectedObj).val().substring(0, 18) == "Select an existing" ) {
typeText = this.getTypeNameForLabels($(selectedObj));
var helpText = "Select an existing " + typeText + " or create a new one.";
//Different for object property autocomplete
if ( this.acSelectOnly ) {
helpText = "Select an existing " + typeText;
}
$(selectedObj).val(helpText)
.addClass(this.acHelpTextClass);
}
},
deleteAcHelpText: function(selectedObj) {
// on submit, no selectedObj gets passed, so we need to check for this
if ( selectedObj ) {
if ($(selectedObj).hasClass(this.acHelpTextClass)) {
$(selectedObj).val('')
.removeClass(this.acHelpTextClass);
}
}
else {
$.each(this.acSelectors, function() {
if ($(this).hasClass(customForm.acHelpTextClass)) {
$(this).val('')
.removeClass(customForm.acHelpTextClass);
}
});
}
},
disableSubmit: function() {
//Disable submit button until selection made
this.button.attr('disabled', 'disabled');
this.button.addClass('disabledSubmit');
},
enableSubmit:function() {
this.button.removeAttr('disabled');
this.button.removeClass('disabledSubmit');
},
initDefaultBlankURI:function(selectedObj) {
//get uri input for selected object and set to value specified as "blank sentinel"
//If blank sentinel is neither null nor an empty string, this means if the user edits an
//existing relationship to an object and does not select anything from autocomplete
//from that object, the old relationship will be removed in n3 processing
var $acDiv = this.acSelections[$(selectedObj).attr('acGroupName')];
$acDiv.find("input").val(customForm.blankSentinel);
}
};
$(document).ready(function() {
customForm.onLoad();
});

View file

@ -1,95 +0,0 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.generators;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vitro.webapp.beans.Individual;
import edu.cornell.mannlib.vitro.webapp.beans.VClass;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditConfigurationUtils;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditConfigurationVTwo;
import edu.cornell.mannlib.vitro.webapp.utils.FrontEndEditingUtils;
import edu.cornell.mannlib.vitro.webapp.utils.FrontEndEditingUtils.EditMode;
/**
* Generates the edit configuration for a default property form.
*
*/
public class AutocompleteObjectPropertyFormGenerator extends DefaultObjectPropertyFormGenerator {
//The only thing that changes here are the templates
private Log log = LogFactory.getLog(AutocompleteObjectPropertyFormGenerator.class);
private String objectPropertyTemplate = "autoCompleteObjectPropForm.ftl";
private String dataPropertyTemplate = "autoCompleteDataPropForm.ftl";
@Override
public void addFormSpecificData(EditConfigurationVTwo editConfiguration, VitroRequest vreq) {
HashMap<String, Object> formSpecificData = new HashMap<String, Object>();
//Get the edit mode
formSpecificData.put("editMode", getEditMode(vreq).toString().toLowerCase());
//We also need the type of the object itself
formSpecificData.put("objectTypes", StringUtils.join(getTypes(vreq), ","));
//Get label for individual if it exists
if(EditConfigurationUtils.getObjectIndividual(vreq) != null) {
String objectLabel = EditConfigurationUtils.getObjectIndividual(vreq).getName();
formSpecificData.put("objectLabel", objectLabel);
}
formSpecificData.put("sparqlForAcFilter", getSparqlForAcFilter(vreq));
editConfiguration.setTemplate(objectPropertyTemplate);
editConfiguration.setFormSpecificData(formSpecificData);
}
private List<String> getTypes(VitroRequest vreq) {
Individual subject = EditConfigurationUtils.getSubjectIndividual(vreq);
String predicateUri = EditConfigurationUtils.getPredicateUri(vreq);
WebappDaoFactory wDaoFact = vreq.getWebappDaoFactory();
List<String> types = new ArrayList<String>();
List <VClass> vclasses = new ArrayList<VClass>();
vclasses = wDaoFact.getVClassDao().getVClassesForProperty(subject.getVClassURI(),predicateUri);
for(VClass v: vclasses) {
types.add(v.getURI());
}
//if types array contains only owl:Thing, the search will not return any results
//In this case, return an empty array
if(isOWLThing(types)) {
return new ArrayList<String>();
}
return types;
}
private boolean isOWLThing(List<String> types) {
return(types.size() == 1 && types.get(0).equals(VitroVocabulary.OWL_THING));
}
public EditMode getEditMode(VitroRequest vreq) {
//In this case, the original jsp didn't rely on FrontEndEditingUtils
//but instead relied on whether or not the object Uri existed
String objectUri = EditConfigurationUtils.getObjectUri(vreq);
EditMode editMode = FrontEndEditingUtils.EditMode.ADD;
if(objectUri != null && !objectUri.isEmpty()) {
editMode = FrontEndEditingUtils.EditMode.EDIT;
}
return editMode;
}
public String getSparqlForAcFilter(VitroRequest vreq) {
String subject = EditConfigurationUtils.getSubjectUri(vreq);
String predicate = EditConfigurationUtils.getPredicateUri(vreq);
//Get all objects for existing predicate, filters out results from addition and edit
String query = "SELECT ?objectVar WHERE { " +
"<" + subject + "> <" + predicate + "> ?objectVar .} ";
return query;
}
}