Skip to content

Commit

Permalink
Merge pull request #578 from OpenTreeOfLife/fix-multiword-and-duplica…
Browse files Browse the repository at this point in the history
…te-tags

Fix tag bugs in curation (dupes & multi-word bugs)
  • Loading branch information
jar398 committed Feb 5, 2015
2 parents a94fdd0 + d6f53a7 commit bffd07d
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 12 deletions.
72 changes: 63 additions & 9 deletions curator/static/js/study-editor.js
Expand Up @@ -61,8 +61,12 @@ var viewModel;

var tagsOptions = {
confirmKeys: [13, 9], // ENTER, TAB for next tag
allowDuplicates: false, // default, but added here for clarity
// using simple objects-as-tags, to avoid bugs with string + SELECT
itemValue: 'attrValue',
itemText: 'displayString',
typeahead: {
source: ['eenie', 'meanie', 'minie', 'moe']
//source: ['eenie', 'meanie', 'minie', 'moe']
/*
source: function(query) {
return $.get('/oti/existing_tags'); // TODO
Expand All @@ -82,11 +86,29 @@ function captureTagTextOnBlur( $tagsSelect ) {
if ($select.length === 0) {
console.warn("captureTagTextOnBlur(): No SELECT widget found!");
} else {
$select.tagsinput('add', $input.val());
var inputText = $.trim( $input.val() );
// reject whitespace-only tags!
if (inputText !== '') {
var tagInfo = makeTagObjFromString(inputText);
$select.tagsinput('add', tagInfo);
}
$input.val('');
}
});
}
function makeTagObjFromString( tagString ) {
// groom string value, and make it safe for HTML attributes
if (typeof tagString !== 'string') {
tagString = tagString.toString();
}
var displayString = $.trim(tagString);
var attrValue = encodeURIComponent(displayString);
var tagInfo = {
displayString: displayString,
attrValue: attrValue
};
return tagInfo;
}

/* Use history plugin to track moves from tab to tab, single-tree popup, others? */

Expand Down Expand Up @@ -800,6 +822,8 @@ function loadSelectedStudy() {
data.nexml['^ot:tag'] = [ ];
}

removeDuplicateTags( data.nexml );

// add study-level containers for annotations
if (['^ot:annotationEvents'] in data.nexml) {
data.nexml['^ot:annotationEvents'].annotation =
Expand Down Expand Up @@ -1349,6 +1373,10 @@ function loadSelectedStudy() {
$('#study-tags').tagsinput('destroy');
}
$('#study-tags').tagsinput( tagsOptions );
// add all tag values directly from nemxml
$.each( getTags( data.nexml, {FULL_TAG_INFO: true}), function(i, tagInfo) {
$('#study-tags').tagsinput('add', tagInfo);
});
captureTagTextOnBlur( $('#study-tags') );
studyTagsInitialized = true;
}
Expand Down Expand Up @@ -2081,6 +2109,8 @@ function normalizeTree( tree ) {
tree['^ot:tag'] = [ ];
}

removeDuplicateTags( tree );

// pre-select first node among conflicting siblings
resolveSiblingOnlyConflictsInTree(tree);
}
Expand Down Expand Up @@ -2895,6 +2925,10 @@ function showTreeViewer( tree, options ) {
}
updateInferenceMethodWidgets( tree );
$('#tree-tags').tagsinput( tagsOptions );
// add all tag values directly from nemxml
$.each( getTags( tree, {FULL_TAG_INFO: true}), function(i, tagInfo) {
$('#tree-tags').tagsinput('add', tagInfo);
});
captureTagTextOnBlur( $('#tree-tags') );
treeTagsInitialized = true;
}
Expand Down Expand Up @@ -5737,29 +5771,46 @@ function relocateLocalAnnotationMessages( nexml ) {
* metatags, with no duplicate values for the parent element.
*/

function getTags( parentElement ) {
function getTags( parentElement, options ) {
options = options || { FULL_TAG_INFO: false };
var tags = [];
var rawTagValues = parentElement['^ot:tag'] || [];
$.each(rawTagValues, function(i, tagText) {
var tagText = $.trim(tagText);
switch(tagText) { // non-empty points to a candidate tree
switch(tagText) {
case '':
break;
break; // discard empty tags
default:
tags.push( tagText );
if (options.FULL_TAG_INFO) {
var tagInfo = makeTagObjFromString( tagText );
tags.push( tagInfo );
} else {
tags.push( tagText );
}
}
});
return tags;
}
function addTag( parentElement, newTagText ) {
// ASSUMES that tag text is storage-ready (URI-decoded and trimmed)
if (!('^ot:tag' in parentElement)) {
parentElement['^ot:tag'] = [];
}
parentElement['^ot:tag'].push( newTagText );
// only add unique tags!
if ($.inArray(newTagText, parentElement['^ot:tag']) === -1) {
parentElement['^ot:tag'].push( newTagText );
}
}
function removeAllTags( parentElement ) {
parentElement['^ot:tag'] = [];
}
function removeDuplicateTags( parentElement ) {
var uniqueTags = [ ] ;
$.each(parentElement['^ot:tag'], function(i,tag){
if ($.inArray(tag, uniqueTags) === -1) { uniqueTags.push(tag) };
});
parentElement['^ot:tag'] = uniqueTags;
}
function updateElementTags( select ) {
var parentElement;
if ($(select).attr('id') === 'study-tags') {
Expand All @@ -5772,8 +5823,11 @@ function updateElementTags( select ) {
// read and apply the values in this tags-input SELECT element
// N.B. multiple-value select returns null if no values selected!
var values = $(select).val() || [];
$.each(values, function(i,v) {
addTag( parentElement, $.trim(v) );
$.each(values, function(i, encodedTag ) {
// convert as needed, e.g. 'delete%20me' => 'delete me'
var rawTagValue = decodeURIComponent( encodedTag );
// trim final string just to be safe
addTag( parentElement, $.trim(rawTagValue) );
});
}

Expand Down
4 changes: 1 addition & 3 deletions curator/views/study/edit.html
Expand Up @@ -373,8 +373,7 @@ <h4>{{=message}}</h4>
<div class="controls">
{{ if viewOrEdit == 'EDIT': }}
<select id="study-tags" multiple="multiple" placeholder="Add tags"
onchange="updateElementTags(this); nudge.GENERAL_METADATA();"
data-bind="options: getTags(viewModel.nexml)">
onchange="updateElementTags(this); nudge.GENERAL_METADATA();">
</select>
{{ else: }}
<!-- TODO: make all tags clickable (search in new window?) -->
Expand Down Expand Up @@ -2245,7 +2244,6 @@ <h3 id='dialog-heading'>
<select id="tree-tags" multiple="multiple" placeholder="Add tags"
onchange="updateElementTags(this);"
data-bind="attr: {'treeid': $data['@id'] },
options: getTags( getTreeByID($data['@id']) ),
event: { keyup: nudge.TREES, change: nudge.TREES },
css: viewModel.ticklers.TREES">
</select>
Expand Down

0 comments on commit bffd07d

Please sign in to comment.