mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2025-02-09 08:24:25 +08:00
584 lines
17 KiB
Text
584 lines
17 KiB
Text
var SmartAnnotation = (function() {
|
|
'use strict';
|
|
|
|
// utilities
|
|
var Util = (function() {
|
|
// helper method that binds show/hidden action
|
|
function showHideBinding() {
|
|
$.each(['show', 'hide'], function (i, ev) {
|
|
var el = $.fn[ev];
|
|
$.fn[ev] = function () {
|
|
this.trigger(ev);
|
|
return el.apply(this, arguments);
|
|
};
|
|
});
|
|
}
|
|
|
|
var publicApi = {
|
|
showHideBinding: showHideBinding
|
|
};
|
|
|
|
return publicApi;
|
|
})();
|
|
|
|
function setAtWho(field) {
|
|
var dataUserUrl,
|
|
dataTaskUrl,
|
|
dataProjectUrl,
|
|
dataExperimentUrl,
|
|
dataSampleUrl,
|
|
dataMenuItemsUrl;
|
|
|
|
dataUserUrl = $(document.body).attr('data-atwho-users-url');
|
|
dataTaskUrl = $(document.body).attr('data-atwho-task-url');
|
|
dataProjectUrl = $(document.body).attr('data-atwho-project-url');
|
|
dataExperimentUrl = $(document.body).attr('data-atwho-experiment-url');
|
|
dataSampleUrl = $(document.body).attr('data-atwho-sample-url');
|
|
dataMenuItemsUrl = $(document.body).attr('data-atwho-menu-items');
|
|
|
|
// helper methods for AtWho callback
|
|
function _templateEval(_tpl, map) {
|
|
var res;
|
|
try {
|
|
res = generateTemplate(map);
|
|
} catch (_error) {
|
|
res = '';
|
|
}
|
|
return res;
|
|
}
|
|
|
|
function _matchHighlighter(li, query, search_filter) {
|
|
var $li, re;
|
|
|
|
function highlight(el, sel, re) {
|
|
var prevVal, newVal;
|
|
prevVal = el.find(sel).html();
|
|
newVal = prevVal.replace(re, '<strong>$&</strong>');
|
|
el.find(sel).html(newVal);
|
|
}
|
|
|
|
if (!query) {
|
|
return li;
|
|
}
|
|
|
|
$li = $(li);
|
|
re = new RegExp(query, 'gi');
|
|
// search_filter is not passed for the user
|
|
if(search_filter) {
|
|
highlight($li, '[data-val=name]', re);
|
|
} else {
|
|
highlight($li, '[data-val=full-name]', re);
|
|
highlight($li, '[data-val=email]', re);
|
|
}
|
|
|
|
return $li[0].outerHTML
|
|
}
|
|
|
|
function _generateInputTag(value, li) {
|
|
var res = '';
|
|
res += '[#' + li.attr('data-name');
|
|
res += '~' + li.attr('data-type');
|
|
res += '~' + li.attr('data-id') + ']';
|
|
return res;
|
|
}
|
|
|
|
// check if query has some hits and disables the buttons without it
|
|
function resourcesChecker(query, search_filter) {
|
|
var src_btn, $element;
|
|
|
|
switch (search_filter) {
|
|
case 'task#':
|
|
src_btn = 'tsk';
|
|
break;
|
|
case 'project#':
|
|
src_btn = 'prj';
|
|
break;
|
|
case 'experiment#':
|
|
src_btn = 'exp';
|
|
break;
|
|
default:
|
|
src_btn = 'sam';
|
|
break;
|
|
}
|
|
|
|
$.getJSON(
|
|
dataMenuItemsUrl,
|
|
{query: query},
|
|
function(data){
|
|
if(data) {
|
|
_.each($('.atwho-header-res .title .btn'), function(el) {
|
|
$element = $(el);
|
|
if(data[$element.data('filter')].length === 0) {
|
|
$element.prop('disabled', true);
|
|
$element
|
|
.removeClass('btn-primary')
|
|
.addClass('btn-default');
|
|
$('[data-filter="' + src_btn +'"]')
|
|
.removeClass('btn-default')
|
|
.addClass('btn-primary');
|
|
} else {
|
|
$element.prop('disabled', false);
|
|
if($element.data('filter') == src_btn) {
|
|
$element
|
|
.removeClass('btn-default')
|
|
.addClass('btn-primary');
|
|
} else {
|
|
$element
|
|
.removeClass('btn-primary')
|
|
.addClass('btn-default');
|
|
}
|
|
}
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
// reset the dropdown
|
|
function reinitializeOnListHide() {
|
|
Util.showHideBinding();
|
|
|
|
_.map($('.atwho-view'), function(el) {
|
|
$(el).off('hide');
|
|
$(el).on('hide', function() {
|
|
$(field).atwho('destroy');
|
|
init();
|
|
});
|
|
});
|
|
}
|
|
|
|
// initialise dropdown dismiss button
|
|
function initDismissButton() {
|
|
$('.atwho-header-res .dismiss').off('click');
|
|
$('.atwho-header-res .dismiss').on('click', function() {
|
|
$(field).atwho('destroy');
|
|
init();
|
|
});
|
|
}
|
|
|
|
// Initialize filter buttons
|
|
function initButtons(query, search_filter) {
|
|
$('.atwho-header-res .title button').off();
|
|
$('.atwho-header-res .dismiss').off('click');
|
|
|
|
initDismissButton();
|
|
|
|
resourcesChecker(query, search_filter);
|
|
$('.atwho-header-res .title button').on('click', function(e) {
|
|
var $button, $prevButton;
|
|
e.stopPropagation();
|
|
e.preventDefault();
|
|
|
|
$button = $(this);
|
|
$prevButton = $button.closest('.title').children('.btn-primary');
|
|
|
|
switch ($button.attr('data-filter')) {
|
|
case 'prj':
|
|
generateNewQuery(dataProjectUrl,
|
|
$prevButton,
|
|
$button);
|
|
break;
|
|
case 'exp':
|
|
generateNewQuery(dataExperimentUrl,
|
|
$prevButton,
|
|
$button);
|
|
break;
|
|
case 'tsk':
|
|
generateNewQuery(dataTaskUrl,
|
|
$prevButton,
|
|
$button);
|
|
break;
|
|
case 'sam':
|
|
generateNewQuery(dataSampleUrl,
|
|
$prevButton,
|
|
$button);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
});
|
|
}
|
|
|
|
// Generates new query when user filters the results
|
|
function generateNewQuery(link, prevBtn, selectedBtn) {
|
|
var regexp, _a, _y, new_query, query_obj, field_selected;
|
|
_a = decodeURI("%C3%80");
|
|
_y = decodeURI("%C3%BF");
|
|
regexp = new RegExp("(#|task#|project#|sample#|experiment#)([A-Za-z" +
|
|
_a + "-" + _y + "0-9_ \'\.\+\-]*)$|" +
|
|
"(#|task#|project#|sample#|experiment#)([^\\x00-\\xff]*)$", 'gi');
|
|
// filters field if multiple input fields on the page
|
|
_.each($(field), function(e) {
|
|
if($(e).atwho('isSelecting')){
|
|
field_selected = e;
|
|
}});
|
|
|
|
if(field_selected) {
|
|
query_obj = regexp.exec($(field_selected).val());
|
|
|
|
if(query_obj) {
|
|
$.getJSON(
|
|
link,
|
|
{query: query_obj[2]},
|
|
function(data) {
|
|
if(data.res.length > 0 && field_selected) {
|
|
$(field_selected)
|
|
.atwho('load', query_obj[0], data.res)
|
|
.atwho('run');
|
|
|
|
prevBtn
|
|
.removeClass('btn-primary')
|
|
.addClass('btn-default');
|
|
selectedBtn
|
|
.removeClass('btn-default')
|
|
.addClass('btn-primary');
|
|
|
|
reinitializeOnListHide();
|
|
initButtons(query_obj[2],
|
|
selectedBtn.html());
|
|
} else {
|
|
$(field).atwho('destroy');
|
|
init();
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
// Generates suggestion dropdown filter
|
|
function generateFilterMenu(active, res_data) {
|
|
var header = '<div class="atwho-header-res">' +
|
|
'<div class="title">' +
|
|
'<button data-filter="prj" class="btn btn-xs ' +
|
|
(active === 'prj' ? 'btn-primary' : 'btn-default') + '">project#</button>' +
|
|
'<button data-filter="exp" class="btn btn-xs ' +
|
|
(active === 'exp' ? 'btn-primary' : 'btn-default') + '">experiment#</button>' +
|
|
'<button data-filter="tsk" class="btn btn-xs ' +
|
|
(active === 'tsk' ? 'btn-primary' : 'btn-default') + '">task#</button>' +
|
|
'<button data-filter="sam" class="btn btn-xs ' +
|
|
(active === 'sam' ? 'btn-primary' : 'btn-default') + '">sample#</button>' +
|
|
'</div>' +
|
|
'<div class="help">' +
|
|
'<div>' +
|
|
'<strong><%= I18n.t("atwho.users.navigate_1") %></strong> ' +
|
|
'<%= I18n.t("atwho.users.navigate_2") %>' +
|
|
'</div>' +
|
|
'<div><strong><%= I18n.t("atwho.users.confirm_1") %></strong> ' +
|
|
'<%= I18n.t("atwho.users.confirm_2") %>' +
|
|
'</div>' +
|
|
'<div>' +
|
|
'<strong><%= I18n.t("atwho.users.dismiss_1") %></strong> ' +
|
|
'<%= I18n.t("atwho.users.dismiss_2") %>' +
|
|
'</div>' +
|
|
'<div class="dismiss">' +
|
|
'<span class="glyphicon glyphicon-remove"></span>' +
|
|
'</div>' +
|
|
'</div>' +
|
|
'</div>';
|
|
|
|
return header;
|
|
}
|
|
|
|
// Generates resources list items
|
|
function generateTemplate(map) {
|
|
var res = '';
|
|
res += '<li class="atwho-li atwho-li-res" data-name="' +
|
|
map.name + '" data-id="' + map.id + '" data-type="' +
|
|
map.type + '">';
|
|
switch(map.type) {
|
|
case 'tsk':
|
|
res += '<span data-type class="res-type">' + map.type + '</span>';
|
|
break;
|
|
case 'prj':
|
|
res += '<span data-type class="res-type">' + map.type + '</span>';
|
|
break;
|
|
case 'exp':
|
|
res += '<span data-type class="res-type">' + map.type + '</span>';
|
|
break;
|
|
case 'sam':
|
|
res += '<span class="glyphicon glyphicon-tint"></span>';
|
|
break;
|
|
}
|
|
|
|
res += ' ';
|
|
res += '<span data-val="name" class="res-name">';
|
|
res += map.name;
|
|
res += '</span>';
|
|
if(map.archived) {
|
|
res += '<%= I18n.t("atwho.res.archived") %></span>';
|
|
} else {
|
|
res += '</span>';
|
|
}
|
|
res += ' ';
|
|
|
|
switch (map.type) {
|
|
case 'tsk':
|
|
|
|
res += '<span class="res-description">< ' + map.experimentName +
|
|
' < ' + map.projectName + '</span>';
|
|
break;
|
|
case 'exp':
|
|
res += '<span class="res-description">< ' + map.projectName + '</span>';
|
|
break;
|
|
case 'sam':
|
|
res += '<span class="res-description">' + map.description + '</span>';
|
|
break;
|
|
}
|
|
|
|
res += '</li>';
|
|
return res;
|
|
}
|
|
|
|
function init() {
|
|
$(field)
|
|
.atwho({
|
|
at: '@',
|
|
callbacks: {
|
|
remoteFilter: function(query, callback) {
|
|
$.getJSON(
|
|
dataUserUrl,
|
|
{query: query},
|
|
function(data) {
|
|
callback(data.users);
|
|
initDismissButton();
|
|
}
|
|
);
|
|
},
|
|
sorter: function(query, items, _searchKey) {
|
|
// Sorting is already done on server-side
|
|
return items;
|
|
},
|
|
tplEval: function(_tpl, map) {
|
|
var res;
|
|
try {
|
|
res = '';
|
|
res += '<li class="atwho-li atwho-li-user" ';
|
|
res += 'data-id="' + map.id + '" ';
|
|
res += 'data-full-name="' + map.full_name + '">';
|
|
res += '<img src="' + map.img_url + '" class="avatar" />';
|
|
res += '<span data-val="full-name">';
|
|
res += map.full_name;
|
|
res += '</span>';
|
|
res += '<small>';
|
|
res += ' ';
|
|
res += '·';
|
|
res += ' ';
|
|
res += '<span data-val="email">';
|
|
res += map.email;
|
|
res += '</span>';
|
|
res += '</small>';
|
|
res += '</li>';
|
|
} catch (_error) {
|
|
res = '';
|
|
}
|
|
return res;
|
|
},
|
|
highlighter: function(li, query) {
|
|
return _matchHighlighter(li, query);
|
|
},
|
|
beforeInsert: function(value, li) {
|
|
var res = '';
|
|
res += '[@' + li.attr('data-full-name');
|
|
res += '~' + li.attr('data-id') + ']';
|
|
return res;
|
|
}
|
|
},
|
|
headerTpl:
|
|
'<div class="atwho-header-res">' +
|
|
'<div class="title title-user"><%= I18n.t("atwho.users.title") %></div>' +
|
|
'<div class="help">' +
|
|
'<div>' +
|
|
'<strong><%= I18n.t("atwho.users.navigate_1") %></strong> ' +
|
|
'<%= I18n.t("atwho.users.navigate_2") %>' +
|
|
'</div>' +
|
|
'<div>' +
|
|
'<strong><%= I18n.t("atwho.users.confirm_1") %></strong> ' +
|
|
'<%= I18n.t("atwho.users.confirm_2") %>' +
|
|
'</div>' +
|
|
'<div>' +
|
|
'<strong><%= I18n.t("atwho.users.dismiss_1") %></strong> ' +
|
|
'<%= I18n.t("atwho.users.dismiss_2") %>' +
|
|
'</div>' +
|
|
'<div class="dismiss">' +
|
|
'<span class="glyphicon glyphicon-remove"></span>' +
|
|
'</div>' +
|
|
'</div>' +
|
|
'</div>',
|
|
limit: <%= Constants::ATWHO_SEARCH_LIMIT %>,
|
|
startsWithSpace: true,
|
|
acceptSpaceBar: true,
|
|
displayTimeout: 120000
|
|
})
|
|
.atwho({
|
|
at: '#',
|
|
callbacks: {
|
|
remoteFilter: function(query, callback) {
|
|
$.getJSON(
|
|
dataSampleUrl,
|
|
{query: query},
|
|
function(data) {
|
|
callback(data.res);
|
|
initButtons(query);
|
|
}
|
|
);
|
|
},
|
|
tplEval: function(_tpl, map) {
|
|
return _templateEval(_tpl, map);
|
|
},
|
|
highlighter: function(li, query) {
|
|
return _matchHighlighter(li, query, true);
|
|
},
|
|
beforeInsert: function(value, li) {
|
|
return _generateInputTag(value, li);
|
|
}
|
|
},
|
|
headerTpl: generateFilterMenu('sam'),
|
|
limit: <%= Constants::ATWHO_SEARCH_LIMIT %>,
|
|
startWithSpace: true,
|
|
acceptSpaceBar: true,
|
|
displayTimeout: 120000
|
|
})
|
|
.atwho({
|
|
at: 'task#',
|
|
callbacks: {
|
|
remoteFilter: function(query, callback) {
|
|
$.getJSON(
|
|
dataTaskUrl,
|
|
{query: query},
|
|
function(data) {
|
|
callback(data.res);
|
|
initButtons(query, 'task#');
|
|
}
|
|
);
|
|
},
|
|
tplEval: function(_tpl, map) {
|
|
return _templateEval(_tpl, map);
|
|
},
|
|
highlighter: function(li, query) {
|
|
return _matchHighlighter(li, query, true);
|
|
},
|
|
beforeInsert: function(value, li) {
|
|
return _generateInputTag(value, li);
|
|
}
|
|
},
|
|
headerTpl: generateFilterMenu('tsk'),
|
|
limit: <%= Constants::ATWHO_SEARCH_LIMIT %>,
|
|
startWithSpace: true,
|
|
acceptSpaceBar: true,
|
|
displayTimeout: 120000
|
|
})
|
|
.atwho({
|
|
at: 'project#',
|
|
callbacks: {
|
|
remoteFilter: function(query, callback) {
|
|
$.getJSON(
|
|
dataProjectUrl,
|
|
{query: query},
|
|
function(data) {
|
|
callback(data.res);
|
|
initButtons(query, 'project#');
|
|
}
|
|
);
|
|
},
|
|
tplEval: function(_tpl, map) {
|
|
return _templateEval(_tpl, map);
|
|
},
|
|
highlighter: function(li, query) {
|
|
return _matchHighlighter(li, query, true);
|
|
},
|
|
beforeInsert: function(value, li) {
|
|
return _generateInputTag(value, li);
|
|
}
|
|
},
|
|
headerTpl: generateFilterMenu('prj'),
|
|
limit: <%= Constants::ATWHO_SEARCH_LIMIT %>,
|
|
startWithSpace: true,
|
|
acceptSpaceBar: true,
|
|
displayTimeout: 120000
|
|
})
|
|
.atwho({
|
|
at: 'experiment#',
|
|
callbacks: {
|
|
remoteFilter: function(query, callback) {
|
|
$.getJSON(
|
|
dataExperimentUrl,
|
|
{query: query},
|
|
function(data) {
|
|
callback(data.res);
|
|
initButtons(query, 'experiment#');
|
|
}
|
|
);
|
|
},
|
|
tplEval: function(_tpl, map) {
|
|
return _templateEval(_tpl, map);
|
|
},
|
|
highlighter: function(li, query) {
|
|
return _matchHighlighter(li, query, true);
|
|
},
|
|
beforeInsert: function(value, li) {
|
|
return _generateInputTag(value, li);
|
|
}
|
|
},
|
|
headerTpl: generateFilterMenu('exp'),
|
|
limit: <%= Constants::ATWHO_SEARCH_LIMIT %>,
|
|
startWithSpace: true,
|
|
acceptSpaceBar: true,
|
|
displayTimeout: 120000
|
|
})
|
|
.atwho({
|
|
at: 'sample#',
|
|
callbacks: {
|
|
remoteFilter: function(query, callback) {
|
|
$.getJSON(
|
|
dataSampleUrl,
|
|
{query: query},
|
|
function(data) {
|
|
callback(data.res);
|
|
initButtons(query);
|
|
}
|
|
);
|
|
},
|
|
tplEval: function(_tpl, map) {
|
|
return _templateEval(_tpl, map);
|
|
},
|
|
highlighter: function(li, query) {
|
|
return _matchHighlighter(li, query, true);
|
|
},
|
|
beforeInsert: function(value, li) {
|
|
return _generateInputTag(value, li);
|
|
}
|
|
},
|
|
headerTpl: generateFilterMenu('sam'),
|
|
limit: <%= Constants::ATWHO_SEARCH_LIMIT %>,
|
|
startWithSpace: true,
|
|
acceptSpaceBar: true,
|
|
displayTimeout: 120000
|
|
});
|
|
}
|
|
|
|
return {
|
|
init: init
|
|
};
|
|
}
|
|
|
|
function initialize(field) {
|
|
var atWho = new setAtWho(field);
|
|
atWho.init();
|
|
}
|
|
|
|
var publicApi = {
|
|
init: initialize
|
|
};
|
|
|
|
return publicApi;
|
|
|
|
})();
|
|
|
|
|
|
// initialize the smart annotations
|
|
(function initSmartAnnotation() {
|
|
$(document).on('focus', '[data-atwho-edit]', function() {
|
|
if(_.isUndefined($(this).data('atwho'))) {
|
|
SmartAnnotation.init(this);
|
|
}
|
|
});
|
|
})();
|