/*global deparam, getUrlRoot, recaptchaOnLoad, resetCaptcha, syn_get_widget, userIsLoggedIn, VuFind, setupJumpMenus, escapeHtmlAttr */
/*exported ajaxTagUpdate, recordDocReady, refreshTagListCallback, addRecordRating */
/**
* Functions and event handlers specific to record pages.
*/
function checkRequestIsValid(element, requestType, icon = 'place-hold') {
var recordId = element.href.match(/\/Record\/([^/]+)\//)[1];
var vars = deparam(element.href);
vars.id = recordId;
var url = VuFind.path + '/AJAX/JSON?' + $.param({
method: 'checkRequestIsValid',
id: recordId,
requestType: requestType,
data: vars
});
$.ajax({
dataType: 'json',
cache: false,
url: url
})
.done(function checkValidDone(response) {
if (response.data.status) {
$(element).removeClass('disabled')
.removeClass('request-check')
.attr('title', response.data.msg)
.html(VuFind.icon(icon) + '' + VuFind.updateCspNonce(response.data.msg) + "");
} else {
$(element).remove();
}
})
.fail(function checkValidFail(/*response*/) {
$(element).remove();
});
}
function setUpCheckRequest() {
$('.checkRequest').each(function checkRequest() {
checkRequestIsValid(this, 'Hold', 'place-hold');
});
$('.checkStorageRetrievalRequest').each(function checkStorageRetrievalRequest() {
checkRequestIsValid(this, 'StorageRetrievalRequest', 'place-storage-retrieval');
});
$('.checkILLRequest').each(function checkILLRequest() {
checkRequestIsValid(this, 'ILLRequest', 'place-ill-request');
});
}
function deleteRecordComment(element, recordId, recordSource, commentId) {
var url = VuFind.path + '/AJAX/JSON?' + $.param({ method: 'deleteRecordComment', id: commentId });
$.ajax({
dataType: 'json',
url: url
})
.done(function deleteCommentDone(/*response*/) {
$($(element).closest('.comment')[0]).remove();
});
}
function refreshCommentList($target, recordId, recordSource) {
var url = VuFind.path + '/AJAX/JSON?' + $.param({
method: 'getRecordCommentsAsHTML',
id: recordId,
source: recordSource
});
$.ajax({
dataType: 'json',
url: url
})
.done(function refreshCommentListDone(response) {
// Update HTML
var $commentList = $target.find('.comment-list');
$commentList.empty();
$commentList.append(VuFind.updateCspNonce(response.data.html));
$commentList.find('.delete').off("click").on("click", function commentRefreshDeleteClick() {
var commentId = $(this).attr('id').substring('recordComment'.length);
deleteRecordComment(this, recordId, recordSource, commentId);
return false;
});
$target.find('.comment-form input[type="submit"]').button('reset');
resetCaptcha($target);
});
}
function refreshRecordRating(recordId, recordSource) {
let rating = document.querySelector('.media-left .rating');
if (!rating) {
return;
}
fetch(VuFind.path + '/AJAX/JSON?' + new URLSearchParams({
method: 'getRecordRating',
id: recordId,
source: recordSource
}))
.then(response => response.json())
.then(result => {
rating.outerHTML = result.data.html;
// Bind lightbox to the new content:
VuFind.lightbox.bind(document.querySelector('.media-left .rating'));
});
}
function registerAjaxCommentRecord(_context) {
var context = typeof _context === "undefined" ? document : _context;
// Form submission
$(context).find('form.comment-form').off("submit").on("submit", function commentFormSubmit() {
var form = this;
var id = form.id.value;
var recordSource = form.source.value;
var url = VuFind.path + '/AJAX/JSON?' + $.param({ method: 'commentRecord' });
var data = {};
$(form).find("input,textarea").each(function appendCaptchaData() {
var input = $(this);
if (input.attr('type') === 'radio' && !input.prop('checked')) {
return true;
}
data[input.attr('name')] = input.val();
});
$.ajax({
type: 'POST',
url: url,
data: data,
dataType: 'json'
})
.done(function addCommentDone(/*response, textStatus*/) {
var $form = $(form);
var $tab = $form.closest('.list-tab-content');
if (!$tab.length) {
$tab = $form.closest('.tab-pane');
}
refreshCommentList($tab, id, recordSource);
refreshRecordRating(id, recordSource);
$form.find('textarea[name="comment"]').val('');
$form.find('input[type="submit"]').button('loading');
if ($form.data('ratingRemoval') === false && Object.prototype.hasOwnProperty.call(data, 'rating') && '' !== data.rating) {
$form.find('a[data-click-set-checked]').remove();
}
resetCaptcha($form);
})
.fail(function addCommentFail(response, textStatus) {
if (textStatus === 'abort' || typeof response.responseJSON === 'undefined') { return; }
VuFind.lightbox.alert(response.responseJSON.data, 'danger');
});
return false;
});
// Delete links
$('.delete').on("click", function commentDeleteClick() {
var commentId = this.id.substr('recordComment'.length);
deleteRecordComment(this, $('.hiddenId').val(), $('.hiddenSource').val(), commentId);
return false;
});
// Prevent form submit
return false;
}
// Forward declaration
var ajaxLoadTab = function ajaxLoadTabForward() {
};
function handleAjaxTabLinks(_context) {
var context = typeof _context === "undefined" ? document : _context;
// Form submission
$(context).find('a').each(function handleLink() {
var $a = $(this);
var href = $a.attr('href');
if (typeof href !== 'undefined' && href.match(/\/AjaxTab[/?]/)) {
$a.off("click").on("click", function linkClick() {
var tabid = $('.record-tabs .nav-tabs li.active').data('tab');
var $tab = $('.' + tabid + '-tab');
$tab.html('
' + VuFind.loading() + '
');
ajaxLoadTab($tab, '', false, href);
return false;
});
}
});
}
function registerTabEvents() {
// Logged in AJAX
registerAjaxCommentRecord();
// Render recaptcha
recaptchaOnLoad();
setUpCheckRequest();
handleAjaxTabLinks();
VuFind.lightbox.bind('.tab-pane.active');
if (typeof VuFind.openurl !== 'undefined') {
VuFind.openurl.init($('.tab-pane.active'));
}
}
function removeHashFromLocation() {
if (window.history.replaceState) {
var href = window.location.href.split('#');
window.history.replaceState({}, document.title, href[0]);
} else {
window.location.hash = '#';
}
}
ajaxLoadTab = function ajaxLoadTabReal($newTab, tabid, setHash, tabUrl) {
// Request the tab via AJAX:
var url = '';
var postData = {};
// If tabUrl is defined, it overrides base URL and tabid
if (typeof tabUrl !== 'undefined') {
url = tabUrl;
} else {
url = VuFind.path + getUrlRoot(document.URL) + '/AjaxTab';
postData.tab = tabid;
postData.sid = VuFind.getCurrentSearchId();
}
$.ajax({
url: url,
type: 'POST',
data: postData
})
.always(function ajaxLoadTabDone(data) {
if (typeof data === 'object') {
$newTab.html(data.responseText ? VuFind.updateCspNonce(data.responseText) : VuFind.translate('error_occurred'));
} else {
$newTab.html(VuFind.updateCspNonce(data));
}
registerTabEvents();
if (typeof syn_get_widget === "function") {
syn_get_widget();
}
if (typeof setHash == 'undefined' || setHash) {
window.location.hash = tabid;
} else {
removeHashFromLocation();
}
setupJumpMenus($newTab);
});
return false;
};
function refreshTagList(_target, _loggedin) {
var loggedin = !!_loggedin || userIsLoggedIn;
var target = _target || document;
var recordId = $(target).find('.hiddenId').val();
var recordSource = $(target).find('.hiddenSource').val();
var $tagList = $(target).find('.tagList');
if ($tagList.length > 0) {
var url = VuFind.path + '/AJAX/JSON?' + $.param({
method: 'getRecordTags',
id: recordId,
source: recordSource
});
$.ajax({
dataType: 'json',
url: url
})
.done(function getRecordTagsDone(response) {
$tagList.empty();
$tagList.replaceWith(VuFind.updateCspNonce(response.data.html));
if (loggedin) {
$tagList.addClass('loggedin');
} else {
$tagList.removeClass('loggedin');
}
});
}
}
function refreshTagListCallback() {
refreshTagList(false, true);
}
function ajaxTagUpdate(_link, tag, _remove) {
var link = _link || document;
var remove = _remove || false;
var $target = $(link).closest('.record');
var recordId = $target.find('.hiddenId').val();
var recordSource = $target.find('.hiddenSource').val();
$.ajax({
url: VuFind.path + '/AJAX/JSON?method=tagRecord',
method: 'POST',
data: {
tag: '"' + tag.replace(/\+/g, ' ') + '"',
id: recordId,
source: recordSource,
remove: remove
}
})
.always(function tagRecordAlways() {
refreshTagList($target, false);
});
}
function getNewRecordTab(tabid) {
return $('' + VuFind.loading() + '
');
}
function backgroundLoadTab(tabid) {
if ($('.' + tabid + '-tab').length > 0) {
return;
}
var newTab = getNewRecordTab(tabid);
$('[data-tab="' + tabid + '"]').closest('.result,.record').find('.tab-content').append(newTab);
return ajaxLoadTab(newTab, tabid, false);
}
function applyRecordTabHash(scrollToTabs) {
var activeTab = $('.record-tabs li.active').attr('data-tab');
var $initiallyActiveTab = $('.record-tabs li.initiallyActive a');
var newTab = typeof window.location.hash !== 'undefined'
? window.location.hash.toLowerCase() : '';
// Open tab in url hash
if (newTab.length <= 1 || newTab === '#tabnav') {
$initiallyActiveTab.trigger("click");
} else if (newTab.length > 1 && '#' + activeTab !== newTab) {
var $tabLink = $('.record-tabs .' + newTab.substr(1) + ' a');
if ($tabLink.length > 0) {
$tabLink.trigger("click");
if (typeof scrollToTabs === 'undefined' || false !== scrollToTabs) {
$('html, body').animate({
scrollTop: $('.record-tabs').offset().top
}, 500);
}
}
}
}
$(window).on('hashchange', applyRecordTabHash);
function removeCheckRouteParam() {
if (window.location.search.indexOf('checkRoute=1') >= 0) {
var newHref = window.location.href.replace('?checkRoute=1&', '?').replace(/[?&]checkRoute=1/, '');
if (window.history && window.history.replaceState) {
window.history.replaceState({}, '', newHref);
}
}
}
function recordDocReady() {
removeCheckRouteParam();
$('.record-tabs .nav-tabs li').attr('aria-selected', 'false');
$('.record-tabs .nav-tabs .initiallyActive').attr('aria-selected', 'true');
// update aria-selected attributes after a tab has been shown
$('.record-tabs .nav-tabs a').on('shown.bs.tab', function shownTab(e) {
$('.record-tabs .nav-tabs li').attr('aria-selected', 'false');
$(e.target).parent().attr('aria-selected', 'true');
});
$('.record-tabs .nav-tabs a').on('click', function recordTabsClick() {
var $li = $(this).parent();
// If it's an active tab, click again to follow to a shareable link.
if ($li.hasClass('active')) {
return true;
}
var tabid = $li.attr('data-tab');
var $top = $(this).closest('.record-tabs');
// if we're flagged to skip AJAX for this tab, we need special behavior:
if ($li.hasClass('noajax')) {
// if this was the initially active tab, we have moved away from it and
// now need to return -- just switch it back on.
if ($li.hasClass('initiallyActive')) {
$(this).tab('show');
$top.find('.tab-pane.active').removeClass('active');
$top.find('.' + tabid + '-tab').addClass('active');
window.location.hash = 'tabnav';
return false;
}
// otherwise, we need to let the browser follow the link:
return true;
}
$top.find('.tab-pane.active').removeClass('active');
$(this).tab('show');
if ($top.find('.' + tabid + '-tab').length > 0) {
$top.find('.' + tabid + '-tab').addClass('active');
if ($(this).parent().hasClass('initiallyActive')) {
removeHashFromLocation();
} else {
window.location.hash = tabid;
}
return false;
} else {
var newTab = getNewRecordTab(tabid).addClass('active');
$top.find('.tab-content').append(newTab);
return ajaxLoadTab(newTab, tabid, !$(this).parent().hasClass('initiallyActive'));
}
});
$('[data-background]').each(function setupBackgroundTabs(index, el) {
backgroundLoadTab(el.dataset.tab);
});
VuFind.truncate.initTruncate('.truncate-subjects', '.subject-line');
VuFind.truncate.initTruncate('table.truncate-field', 'tr.holding-row', function createTd(m) { return '' + m + ' | '; });
registerTabEvents();
applyRecordTabHash(false);
}
function addRecordRating() {
document.querySelector('.rating-average a').click();
}