component for selecting a citation from search results

This commit is contained in:
Artur
2025-12-04 23:35:33 +03:00
parent e07e696dff
commit 6f67b27357
19 changed files with 547 additions and 349 deletions

View File

@ -51,6 +51,8 @@
<script defer src="scripts/shared/ui/selectbox.js"></script>
<script defer src="scripts/shared/ui/button.js"></script>
<script defer src="scripts/shared/ui/message.js"></script>
<script defer src="scripts/shared/components/search-filter.js"></script>
<script defer src="scripts/shared/components/select-citation.js"></script>
<script defer src="scripts/zotero/zotero-environment.js"></script>
<script defer src="scripts/zotero/zotero-api-checker.js"></script>
@ -118,6 +120,10 @@
<div id="selectedWrapper">
<div class="flexCol flexSize flexCenter">
<div id="selectedHolder"></div>
<div id="selectedInfo" class="hidden">
<span id="selectedCount">0 selected</span>
<span id="cancelBtn" class="i18n link">Cancel selection</span>
</div>
</div>
<div id="selectedThumb" class="scrollThumb hidden"></div>
</div>
@ -136,7 +142,6 @@
<button id="insertLinkBtn" class="button control i18n btn-text-default"
style="flex: 1; margin-left: 8px; margin-right: 0;" disabled>Insert Citation</button>
</div>
<button id="cancelBtn" class="button control i18n btn-text-default" disabled>Cancel select</button>
</div>
<div id="insertBibDiv" class="flex">
<button id="insertBibBtn" class="button control i18n btn-text-default">Insert Bibliography</button>

View File

@ -148,6 +148,12 @@ input[type="text"] {
margin-bottom: 14px;
}
#selectedInfo:not(.hidden) {
display: flex;
width: 100%;
justify-content: space-between;
}
#searchWrapper {
display: flex;
justify-content: space-between;

View File

@ -27,6 +27,8 @@
/// <reference path="./csl/locales/locales-manager.js" />
/// <reference path="./services/translate-service.js" />
/// <reference path="./services/citation-service.js" />
/// <reference path="./shared/components/search-filter.js" />
/// <reference path="./shared/components/select-citation.js" />
/// <reference path="./shared/ui/input.js" />
/// <reference path="./shared/ui/selectbox.js" />
/// <reference path="./shared/ui/button.js" />
@ -37,20 +39,11 @@
* @property {Function} onscroll
*/
/**
* @typedef {Object} Selected
* @property {Object<string|number, SearchResultItem>} items
* @property {Object<string|number, HTMLElement>} html
* @property {Object<string|number, HTMLInputElement>} checks
* @property {function(): number} count
*/
(function () {
var counter = 0; // счетчик отправленных запросов (используется чтобы знать показывать "not found" или нет)
var displayNoneClass = "hidden";
var blurClass = "blur";
/** @type {number} */
var loadTimeout;
//var loadingStyle = false;
//var loadingLocale = false;
var bNumFormat = false;
@ -68,18 +61,6 @@
// как документе (для этого нужно знать где именно в документе мы вставляем цитату,
// какая цитата сверху и снизу от текущего курсора)
/** @type {Selected} */
var selected = {
items: {},
html: {},
checks: {},
count: function () {
var k = 0;
for (var i in selected.items) k++;
return k;
},
};
/** @type {Router} */
var router;
/** @type {ZoteroSdk} */
@ -101,8 +82,10 @@
groupsHash: "",
};
/** @type {SearchFilter} */
/** @type {SearchFilterComponents} */
var searchFilter;
/** @type {SelectCitationsComponent} */
var selectCitation;
/** @type {Button} */
var saveAsTextBtn;
/** @type {Object.<string, HTMLElement | HTMLInputElement>} */
@ -124,14 +107,7 @@
if (!contentHolder) {
throw new Error("contentHolder not found");
}
const docsHolder = document.getElementById("docsHolder");
if (!docsHolder) {
throw new Error("docsHolder not found");
}
const docsThumb = document.getElementById("docsThumb");
if (!docsThumb) {
throw new Error("docsThumb not found");
}
const configState = document.getElementById("configState");
if (!configState) {
throw new Error("configState not found");
@ -140,18 +116,6 @@
if (!mainState) {
throw new Error("mainState not found");
}
const selectedWrapper = document.getElementById("selectedWrapper");
if (!selectedWrapper) {
throw new Error("selectedWrapper not found");
}
const selectedHolder = document.getElementById("selectedHolder");
if (!selectedHolder) {
throw new Error("selectedHolder not found");
}
const selectedThumb = document.getElementById("selectedThumb");
if (!selectedThumb) {
throw new Error("selectedThumb not found");
}
const buttonsWrapper = document.getElementById("buttonsWrapper");
if (!buttonsWrapper) {
throw new Error("buttonsWrapper not found");
@ -210,10 +174,6 @@
if (!insertLinkBtn) {
throw new Error("insertLinkBtn not found");
}
const cancelBtn = document.getElementById("cancelBtn");
if (!cancelBtn) {
throw new Error("cancelBtn not found");
}
const refreshBtn = document.getElementById("refreshBtn");
if (!refreshBtn) {
throw new Error("refreshBtn not found");
@ -227,7 +187,12 @@
if (!cslFileInput) {
throw new Error("cslFileInput not found");
}
searchFilter = new SearchFilter();
searchFilter = new SearchFilterComponents();
selectCitation = new SelectCitationsComponent(
displayNoneClass,
loadMore,
shouldLoadMore
);
saveAsTextBtn = new Button("saveAsTextBtn");
elements = {
@ -236,16 +201,10 @@
error: error,
contentHolder: contentHolder,
docsHolder: docsHolder,
docsThumb: docsThumb,
configState: configState,
mainState: mainState,
selectedWrapper: selectedWrapper,
selectedHolder: selectedHolder,
selectedThumb: selectedThumb,
buttonsWrapper: buttonsWrapper,
locatorLabel: locatorLabel,
@ -263,7 +222,6 @@
insertBibBtn: insertBibBtn,
insertLinkBtn: insertLinkBtn,
cancelBtn: cancelBtn,
refreshBtn: refreshBtn,
checkOmitAuthor: checkOmitAuthor,
@ -271,11 +229,6 @@
};
}
/** @type {Scroller} */
var selectedScroller;
/** @type {Scroller} */
var docsScroller;
window.Asc.plugin.init = function () {
initElements();
showLoader(true);
@ -321,16 +274,6 @@
});
window.Asc.plugin.onTranslate = applyTranslations;
selectedScroller = initScrollBox(
elements.selectedHolder,
elements.selectedThumb
);
docsScroller = initScrollBox(
elements.docsHolder,
elements.docsThumb,
checkDocsScroll
);
};
function preloadLastStyle() {
@ -516,6 +459,8 @@
}
function addEventListeners() {
selectCitation.subscribe(checkSelected);
elements.cslFileInput.onchange = function (e) {
if (!(e.target instanceof HTMLInputElement)) return;
/** @type {HTMLInputElement} */
@ -559,9 +504,9 @@
)
return Promise.resolve();
clearLibrary();
selectCitation.clearLibrary();
/** @type {Array<Promise<void>>} */
/** @type {Array<Promise<boolean>>} */
const promises = [];
return sdk
@ -622,16 +567,6 @@
searchFor(text, selectedGroups);
});
elements.cancelBtn.onclick = function (e) {
var ids = [];
for (var id in selected.items) {
ids.push(id);
}
for (var i = 0; i < ids.length; i++) {
removeSelected(ids[i]);
}
};
elements.refreshBtn.onclick = function () {
if (!cslStylesManager.getLastUsedStyleId()) {
showError(translate("Style is not selected"));
@ -706,7 +641,7 @@
}
return citationService.insertSelectedCitations(
selected.items,
selectCitation.getItems(),
prefix,
suffix,
locatorInfo,
@ -714,9 +649,7 @@
);
})
.then(function (keys) {
keys.forEach(function (key) {
removeSelected(key);
});
selectCitation.removeItems(keys);
})
.catch(function (error) {
console.error(error);
@ -1232,57 +1165,35 @@
};
}
/**
* @param {HTMLElement} holder - The element that contains the document list.
* @param {HTMLElement} [thumb]
*/
function checkDocsScroll(holder, thumb) {
if (shouldLoadMore(holder)) {
if (loadTimeout) {
clearTimeout(loadTimeout);
}
function loadMore() {
console.warn("Loading more...");
if (lastSearch.obj && lastSearch.obj.next) {
loadLibrary(
lastSearch.obj.next(),
true,
true,
!lastSearch.groups.length,
false,
false
);
}
if (
!lastSearch.obj &&
!lastSearch.text.trim() &&
!lastSearch.groups.length
)
return;
loadTimeout = setTimeout(function () {
if (shouldLoadMore(holder)) {
console.warn("Loading more...");
if (lastSearch.obj && lastSearch.obj.next) {
loadLibrary(
lastSearch.obj.next(),
true,
true,
!lastSearch.groups.length,
false,
false
);
}
for (
var i = 0;
i < lastSearch.groups.length &&
lastSearch.groups[i].next;
i++
) {
loadLibrary(
sdk.getGroupItems(
lastSearch.groups[i].next(),
lastSearch.groups[i].id
),
true,
false,
i == lastSearch.groups.length - 1,
true,
false
);
}
}
}, 500);
for (
var i = 0;
i < lastSearch.groups.length && lastSearch.groups[i].next;
i++
) {
loadLibrary(
sdk.getGroupItems(
lastSearch.groups[i].next(),
lastSearch.groups[i].id
),
true,
false,
i == lastSearch.groups.length - 1,
true,
false
);
}
}
@ -1301,19 +1212,16 @@
if (el.next) flag = false;
});
if (!lastSearch.obj || !lastSearch.obj.next || !flag) return false;
if (
!lastSearch.obj &&
!lastSearch.text.trim() &&
!lastSearch.groups.length
)
return false;
return true;
}
function clearLibrary() {
var holder = elements.docsHolder;
while (holder.lastChild) {
holder.removeChild(holder.lastChild);
}
holder.scrollTop = 0;
docsScroller.onscroll();
}
/**
* @param {Promise<SearchResult>} promise
* @param {boolean} append
@ -1321,7 +1229,7 @@
* @param {boolean} hideLoader
* @param {boolean} isGroup
* @param {boolean} bCount
* @returns {Promise<void>}
* @returns {Promise<boolean>}
*/
function loadLibrary(
promise,
@ -1335,9 +1243,9 @@
if (bCount) counter++;
return promise
.then(function (res) {
console.log(res);
console.warn(res);
if (bCount) counter--;
displaySearchItems(
return displaySearchItems(
append,
res,
null,
@ -1351,7 +1259,7 @@
if (err.message) {
showError(translate(err.message));
}
displaySearchItems(
return displaySearchItems(
append,
null,
err,
@ -1427,12 +1335,6 @@
* @param {boolean} showNotFound
*/
function displaySearchItems(append, res, err, isGroup, showNotFound) {
var holder = elements.docsHolder;
if (!append) {
clearLibrary();
}
var first = false;
if (!lastSearch.obj && res && res.items && !res.items.length)
first = true;
@ -1446,192 +1348,31 @@
if (isGroup && res && res.next) lastSearch.groups.push(res);
else lastSearch.obj = res && res.items.length ? res : null;
}
var page = document.createElement("div");
page.classList.add("page" + holder.children.length);
if (res && res.items && res.items.length > 0) {
for (let index = 0; index < res.items.length; index++) {
let item = res.items[index];
item[isGroup ? "groupID" : "userID"] = res.id;
citationService.fillUrisFromId(item);
page.appendChild(buildDocElement(item));
}
} else if (err || first) {
if (err) {
showError(err);
} else if (showNotFound) {
var notFound = document.createElement("div");
notFound.textContent = translate("Nothing found");
notFound.classList.add("searchInfo");
page.appendChild(notFound);
}
}
holder.appendChild(page);
docsScroller.onscroll();
return selectCitation.displaySearchItems(
append,
res,
err,
showNotFound,
first
);
}
/**
* @param {SearchResultItem} item
* @returns {HTMLElement}
* @param {number} numOfSelected
*/
function buildDocElement(item) {
var root = document.createElement("div");
root.classList.add("doc");
var checkHolder = document.createElement("div");
var checkWrapper = document.createElement("div");
checkWrapper.classList.add("checkbox");
var check = document.createElement("input");
check.setAttribute("type", "checkbox");
if (selected.items[item.id]) {
check.checked = true;
selected.checks[item.id] = check;
}
checkWrapper.appendChild(check);
checkWrapper.appendChild(document.createElement("span"));
checkHolder.appendChild(checkWrapper);
var docInfo = document.createElement("div");
docInfo.classList.add("docInfo");
var title = document.createElement("div");
title.textContent = item.title;
title.classList.add("truncate-text");
docInfo.appendChild(title);
if (item.author && item.author.length > 0) {
var authors = document.createElement("div");
authors.textContent = item.author
.map(function (a) {
return a.family + ", " + a.given;
})
.join("; ");
authors.setAttribute("title", authors.textContent);
authors.classList.add("secondary-text");
authors.classList.add("truncate-text");
authors.classList.add("nowrap");
docInfo.appendChild(authors);
}
var source = document.createElement("div");
if (item.publisher || item["publisher-place"]) {
source.textContent =
item.publisher || item["publisher-place"] || "";
}
if (item.issued && item.issued["date-parts"]) {
var date = item.issued["date-parts"][0];
if (source.textContent) {
source.textContent += " (" + date.join("-") + ")";
} else {
source.textContent = date.join("-");
}
}
source.setAttribute("title", source.textContent);
source.classList.add("secondary-text");
source.classList.add("truncate-text");
source.classList.add("nowrap");
docInfo.appendChild(source);
root.appendChild(checkHolder);
root.appendChild(docInfo);
/**
* @param {HTMLInputElement} input
* @param {SearchResultItem} item
* @returns
*/
function selectItem(input, item) {
return function () {
input.checked = !input.checked;
if (input.checked) {
addSelected(item, input);
} else {
removeSelected(item.id);
}
};
}
var f = selectItem(check, item);
checkWrapper.onclick = f;
docInfo.onclick = f;
return root;
}
/**
* @param {SearchResultItem} item
* @param {HTMLInputElement} input
*/
function addSelected(item, input) {
/** @type {HTMLElement} */
var el = buildSelectedElement(item);
selected.items[item.id] = item;
selected.html[item.id] = el;
selected.checks[item.id] = input;
elements.selectedHolder.appendChild(el);
docsScroller.onscroll();
selectedScroller.onscroll();
checkSelected();
}
/** @param {string|number} id */
function removeSelected(id) {
var el = selected.html[id];
delete selected.items[id];
delete selected.html[id];
if (selected.checks[id]) {
selected.checks[id].checked = false;
delete selected.checks[id];
}
elements.selectedHolder.removeChild(el);
docsScroller.onscroll();
selectedScroller.onscroll();
checkSelected();
}
/**
* @param {SearchResultItem} item
* @returns {HTMLElement}
*/
function buildSelectedElement(item) {
var root = document.createElement("div");
root.classList.add("selDoc");
var name = document.createElement("span");
name.textContent = item.title;
name.setAttribute("title", item.title);
var year = document.createElement("span");
if (item.issued && item.issued["date-parts"]) {
year.textContent = item.issued["date-parts"][0].join("-");
}
var remove = document.createElement("span");
remove.onclick = function () {
removeSelected(item.id);
};
remove.textContent = "×";
root.appendChild(name);
root.appendChild(year);
root.appendChild(remove);
return root;
}
function checkSelected() {
if (selected.count() <= 0) {
if (elements.insertLinkBtn)
elements.insertLinkBtn.setAttribute("disabled", "");
if (elements.cancelBtn)
elements.cancelBtn.setAttribute("disabled", "");
function checkSelected(numOfSelected) {
if (numOfSelected <= 0) {
elements.insertLinkBtn.setAttribute("disabled", "");
} else {
if (elements.insertLinkBtn)
elements.insertLinkBtn.removeAttribute("disabled");
if (elements.cancelBtn)
elements.cancelBtn.removeAttribute("disabled");
elements.insertLinkBtn.removeAttribute("disabled");
}
}
})();

View File

@ -5,7 +5,7 @@
/// <reference path="../ui/selectbox.js" />
/// <reference path="../ui/button.js" />
function SearchFilter() {
function SearchFilterComponents() {
this._searchField = new InputField("searchField", {
type: "text",
autofocus: true,
@ -22,9 +22,11 @@ function SearchFilter() {
});
/** @type {Function[]} */
this._subscribers = [];
this._addEventListeners();
}
SearchFilter.prototype._addEventListeners = function () {
SearchFilterComponents.prototype._addEventListeners = function () {
const self = this;
this._searchField.subscribe(function (e) {
if (e.type === "inputfield:blur" || e.type === "inputfield:submit") {
@ -49,7 +51,7 @@ SearchFilter.prototype._addEventListeners = function () {
/**
* @param {Array<UserGroupInfo>} groups
*/
SearchFilter.prototype.addGroups = function (groups) {
SearchFilterComponents.prototype.addGroups = function (groups) {
const self = this;
let selectedItem = localStorage.getItem("selectedGroup");
let hasSelected = false;
@ -114,7 +116,7 @@ SearchFilter.prototype.addGroups = function (groups) {
/**
* @return {Array<string|"my_library"|"group_libraries">}
*/
SearchFilter.prototype._getSelectedGroups = function () {
SearchFilterComponents.prototype._getSelectedGroups = function () {
const self = this;
const ids = this._librarySelectList.getSelectedValues();
if (Array.isArray(ids) === false || ids.length === 0) {
@ -132,7 +134,7 @@ SearchFilter.prototype._getSelectedGroups = function () {
* @param {function(string, Array<string|"my_library"|"group_libraries">): void} callback
* @returns {Object}
*/
SearchFilter.prototype.subscribe = function (callback) {
SearchFilterComponents.prototype.subscribe = function (callback) {
var self = this;
this._subscribers.push(callback);
@ -150,7 +152,7 @@ SearchFilter.prototype.subscribe = function (callback) {
* @param {Array<UserGroupInfo>} groups
* @returns
*/
SearchFilter.prototype._selectedGroupsWatcher = function (
SearchFilterComponents.prototype._selectedGroupsWatcher = function (
customGroups,
groups
) {

View File

@ -0,0 +1,444 @@
// @ts-check
/// <reference path="../../types-global.js" />
/**
* @param {string} displayNoneClass
* @param {function(): void} fLoadMore
* @param {function(HTMLElement): boolean} fShouldLoadMore
*/
function SelectCitationsComponent(
displayNoneClass,
fLoadMore,
fShouldLoadMore
) {
/** @type {Object<string|number, SearchResultItem>} */
this._items = {};
/** @type {Object<string|number, HTMLElement>} */
this._html = {};
/** @type {Object<string|number, HTMLInputElement>} */
this._checks = {};
this._cancelBtn = document.getElementById("cancelBtn");
this._docsHolder = document.getElementById("docsHolder");
this._docsThumb = document.getElementById("docsThumb");
this._selectedWrapper = document.getElementById("selectedWrapper");
this._selectedHolder = document.getElementById("selectedHolder");
this._selectedInfo = document.getElementById("selectedInfo");
this._selectedCount = document.getElementById("selectedCount");
this._selectedThumb = document.getElementById("selectedThumb");
if (this._selectedHolder && this._selectedThumb) {
/** @type {Scroller} */
this._selectedScroller = this._initScrollBox(
this._selectedHolder,
this._selectedThumb
);
}
if (this._docsHolder && this._docsThumb) {
/** @type {Scroller} */
this._docsScroller = this._initScrollBox(
this._docsHolder,
this._docsThumb,
this._checkDocsScroll.bind(this)
);
}
/** @type {Function[]} */
this._subscribers = [];
this._displayNoneClass = displayNoneClass;
this._fShouldLoadMore = fShouldLoadMore;
this._fLoadMore = fLoadMore;
/** @type {number} */
this._loadTimeout;
this._init();
}
SelectCitationsComponent.prototype._init = function () {
const self = this;
if (this._cancelBtn) {
this._cancelBtn.onclick = function (e) {
var ids = [];
for (var id in self._items) {
ids.push(id);
}
for (var i = 0; i < ids.length; i++) {
self._removeSelected(ids[i]);
}
};
}
};
SelectCitationsComponent.prototype.clearLibrary = function () {
var holder = this._docsHolder;
while (holder && holder.lastChild) {
holder.removeChild(holder.lastChild);
}
if (holder) holder.scrollTop = 0;
this._docsScroller.onscroll();
};
/**
* @param {boolean} append
* @param {SearchResult | null} res
* @param {Error | null} err
* @param {boolean} showNotFound
* @param {boolean} first
* @returns {Promise<boolean>}
*/
SelectCitationsComponent.prototype.displaySearchItems = function (
append,
res,
err,
showNotFound,
first
) {
const self = this;
var holder = this._docsHolder;
if (!append) {
this.clearLibrary();
}
var page = document.createElement("div");
if (holder) page.classList.add("page" + holder.children.length);
return new Promise((resolve, reject) => {
if (res && res.items && res.items.length > 0) {
for (let index = 0; index < res.items.length; index++) {
let item = res.items[index];
page.appendChild(self._buildDocElement(item));
}
} else if (err || first) {
if (err) {
reject(err);
} else if (showNotFound) {
var notFound = document.createElement("div");
notFound.textContent = translate("Nothing found");
notFound.classList.add("searchInfo");
page.appendChild(notFound);
}
}
if (holder) holder.appendChild(page);
this._docsScroller.onscroll();
resolve(true);
});
};
/** @returns {Object<string|number, SearchResultItem>} */
SelectCitationsComponent.prototype.getItems = function () {
return this._items;
};
/**
*
* @param {Array<string|number>} keys
*/
SelectCitationsComponent.prototype.removeItems = function (keys) {
const self = this;
keys.forEach(function (key) {
self._removeSelected(key);
});
};
/**
* @param {function(number): void} callback
* @returns {Object}
*/
SelectCitationsComponent.prototype.subscribe = function (callback) {
var self = this;
this._subscribers.push(callback);
return {
unsubscribe: function () {
self._subscribers = self._subscribers.filter(function (cb) {
return cb !== callback;
});
},
};
};
/**
* @param {SearchResultItem} item
* @returns {HTMLElement}
*/
SelectCitationsComponent.prototype._buildDocElement = function (item) {
const self = this;
var root = document.createElement("div");
root.classList.add("doc");
var checkHolder = document.createElement("div");
var checkWrapper = document.createElement("div");
checkWrapper.classList.add("checkbox");
var check = document.createElement("input");
check.setAttribute("type", "checkbox");
if (this._items[item.id]) {
check.checked = true;
this._checks[item.id] = check;
}
checkWrapper.appendChild(check);
checkWrapper.appendChild(document.createElement("span"));
checkHolder.appendChild(checkWrapper);
var docInfo = document.createElement("div");
docInfo.classList.add("docInfo");
var title = document.createElement("div");
title.textContent = item.title;
title.classList.add("truncate-text");
docInfo.appendChild(title);
if (item.author && item.author.length > 0) {
var authors = document.createElement("div");
authors.textContent = item.author
.map(function (a) {
return a.family + ", " + a.given;
})
.join("; ");
authors.setAttribute("title", authors.textContent);
authors.classList.add("secondary-text");
authors.classList.add("truncate-text");
authors.classList.add("nowrap");
docInfo.appendChild(authors);
}
var source = document.createElement("div");
if (item.publisher || item["publisher-place"]) {
source.textContent = item.publisher || item["publisher-place"] || "";
}
if (item.issued && item.issued["date-parts"]) {
var date = item.issued["date-parts"][0];
if (source.textContent) {
source.textContent += " (" + date.join("-") + ")";
} else {
source.textContent = date.join("-");
}
}
source.setAttribute("title", source.textContent);
source.classList.add("secondary-text");
source.classList.add("truncate-text");
source.classList.add("nowrap");
docInfo.appendChild(source);
root.appendChild(checkHolder);
root.appendChild(docInfo);
/**
* @param {HTMLInputElement} input
* @param {SearchResultItem} item
* @returns
*/
function selectItem(input, item) {
return function () {
input.checked = !input.checked;
if (input.checked) {
self._addSelected(item, input);
} else {
self._removeSelected(item.id);
}
};
}
var f = selectItem(check, item);
checkWrapper.onclick = f;
docInfo.onclick = f;
return root;
};
/**
* @param {SearchResultItem} item
* @returns {HTMLElement}
*/
SelectCitationsComponent.prototype._buildSelectedElement = function (item) {
const self = this;
var root = document.createElement("div");
root.classList.add("selDoc");
var name = document.createElement("span");
name.textContent = item.title;
name.setAttribute("title", item.title);
var year = document.createElement("span");
if (item.issued && item.issued["date-parts"]) {
year.textContent = item.issued["date-parts"][0].join("-");
}
var remove = document.createElement("span");
remove.onclick = function () {
self._removeSelected(item.id);
};
remove.textContent = "×";
root.appendChild(name);
root.appendChild(year);
root.appendChild(remove);
return root;
};
/**
* @param {SearchResultItem} item
* @param {HTMLInputElement} input
*/
SelectCitationsComponent.prototype._addSelected = function (item, input) {
/** @type {HTMLElement} */
var el = this._buildSelectedElement(item);
this._items[item.id] = item;
this._html[item.id] = el;
this._checks[item.id] = input;
if (this._selectedHolder) {
this._selectedHolder.appendChild(el);
}
this._docsScroller.onscroll();
this._selectedScroller.onscroll();
this._checkSelected();
};
/**
* @param {HTMLElement} holder - The element that contains the document list.
* @param {HTMLElement} [thumb]
*/
SelectCitationsComponent.prototype._checkDocsScroll = function (holder, thumb) {
const self = this;
if (this._fShouldLoadMore(holder)) {
if (this._loadTimeout) {
clearTimeout(this._loadTimeout);
}
if (
!lastSearch.obj &&
!lastSearch.text.trim() &&
!lastSearch.groups.length
)
return;
this._loadTimeout = setTimeout(function () {
if (self._fShouldLoadMore(holder)) {
self._fLoadMore();
}
}, 500);
}
};
/**
* @param {HTMLElement} holder
* @param {HTMLElement} thumb
* @param {function(HTMLElement): void} [onscroll]
* @returns {Scroller}
*/
SelectCitationsComponent.prototype._initScrollBox = function (
holder,
thumb,
onscroll
) {
var scroller = {};
scroller.onscroll = this._checkScroll(holder, thumb, onscroll);
holder.onwheel = function (e) {
holder.scrollTop +=
e.deltaY > 10 || e.deltaY < -10 ? e.deltaY : e.deltaY * 20;
scroller.onscroll();
};
thumb.onmousedown = function (e) {
thumb.classList.add("scrolling");
var y = e.clientY;
var initialPos = holder.scrollTop;
window.onmouseup = function (e) {
thumb.classList.remove("scrolling");
window.onmouseup = null;
window.onmousemove = null;
};
window.onmousemove = function (e) {
var delta = e.clientY - y;
var percMoved = delta / holder.clientHeight;
var deltaScroll = holder.scrollHeight * percMoved;
holder.scrollTop = initialPos + deltaScroll;
scroller.onscroll();
};
};
document.body.addEventListener("resize", function () {
scroller.onscroll();
});
return scroller;
};
/**
* @param {HTMLElement} holder
* @param {HTMLElement} thumb
* @param {function} [func] - an optional function to be called with the holder and thumb as arguments.
* @returns {function} - a function that checks the scroll state and updates the thumb accordingly.
* */
SelectCitationsComponent.prototype._checkScroll = function (
holder,
thumb,
func
) {
const displayNoneClass = this._displayNoneClass;
return function () {
if (holder.scrollHeight <= holder.clientHeight) {
thumb.classList.add(displayNoneClass);
} else {
thumb.classList.remove(displayNoneClass);
var height =
(holder.clientHeight / holder.scrollHeight) *
holder.clientHeight;
height = height < 40 ? 40 : height;
thumb.style.height = height + "px";
var scroll = holder.scrollHeight - holder.clientHeight;
var percScrolled = holder.scrollTop / scroll;
var margin = percScrolled * (holder.clientHeight - height);
thumb.style.marginTop = margin + "px";
}
if (func) func(holder, thumb);
};
};
/** @param {string|number} id */
SelectCitationsComponent.prototype._removeSelected = function (id) {
var el = this._html[id];
delete this._items[id];
delete this._html[id];
if (this._checks[id]) {
this._checks[id].checked = false;
delete this._checks[id];
}
if (this._selectedHolder) {
this._selectedHolder.removeChild(el);
}
this._docsScroller.onscroll();
this._selectedScroller.onscroll();
this._checkSelected();
};
SelectCitationsComponent.prototype._checkSelected = function () {
const numOfSelected = this._count();
if (!this._selectedInfo || !this._selectedCount) {
return;
}
if (numOfSelected <= 0) {
this._selectedInfo.classList.add(this._displayNoneClass);
} else {
this._selectedInfo.classList.remove(this._displayNoneClass);
this._selectedCount.textContent =
numOfSelected + " " + translate("selected");
}
this._subscribers.forEach(function (cb) {
cb(numOfSelected);
});
};
SelectCitationsComponent.prototype._count = function () {
var k = 0;
for (var i in this._items) k++;
return k;
};

View File

@ -22,7 +22,7 @@
"Learn more here.": "Více informací se dozvíte zde.",
"Save": "Uložit",
"Insert Citation": "Vložit Citaci",
"Cancel select": "Zrušit vybrat",
"Cancel selection": "Zrušit vybrat",
"Refresh": "Aktualizovat",
"Unlink citations": "Odpojit citace",
"Please insert some citation into the document.": "Vložte prosím do dokumentu nějakou citaci.",

View File

@ -22,7 +22,7 @@
"Learn more here.": "Erfahren Sie mehr hier.",
"Save": "Speichern",
"Insert Citation": "Zitat einfügen",
"Cancel select": "Abbrechen auswählen",
"Cancel selection": "Abbrechen auswählen",
"Refresh": "Aktualisieren",
"Unlink citations": "Zitate trennen",
"Please insert some citation into the document.": "Bitte fügen Sie ein Zitat in das Dokument ein.",

View File

@ -22,7 +22,7 @@
"Learn more here.": "Aprenda más aquí.",
"Save": "Salvar",
"Insert Citation": "Insertar Cita",
"Cancel select": "Cancelar seleccionar",
"Cancel selection": "Cancelar seleccionar",
"Refresh": "Actualizar",
"Unlink citations": "Desvincular citas",
"Please insert some citation into the document.": "Por favor, inserte alguna cita en el documento",

View File

@ -22,7 +22,7 @@
"Learn more here.": "En savoir plus ici.",
"Save": "Sauvegarder",
"Insert Citation": "Insérer une Citation",
"Cancel select": "Annuler sélectionner",
"Cancel selection": "Annuler sélectionner",
"Refresh": "Rafraîchir",
"Unlink citations": "Dissocier les citations",
"Please insert some citation into the document.": "Veuillez insérer une citation dans le document.",

View File

@ -22,7 +22,7 @@
"Learn more here.": "Ulteriori informazioni qui.",
"Save": "Salva",
"Insert Citation": "Inserisci citazione",
"Cancel select": "Annulla seleziona",
"Cancel selection": "Annulla seleziona",
"Refresh": "Aggiornare",
"Unlink citations": "Disconnetti citazioni",
"Please insert some citation into the document.": "Si prega di inserire qualche citazione nel documento.",

View File

@ -22,7 +22,7 @@
"Learn more here.": "詳しくはこちら",
"Save": "保存",
"Insert Citation": "引用を挿入",
"Cancel select": "キャンセル選択",
"Cancel selection": "キャンセル選択",
"Refresh": "リフレッシュ",
"Unlink citations": "引用を外す",
"Please insert some citation into the document.": "文書にいくつかの引用を挿入してください。",

View File

@ -22,7 +22,7 @@
"Learn more here.": "Lees hier meer.",
"Save": "Opslaan",
"Insert Citation": "Citaat Invoegen",
"Cancel select": "Annuleren selecteren",
"Cancel selection": "Annuleren selecteren",
"Refresh": "Vernieuwen",
"Unlink citations": "Citaat Verwijderen",
"Please insert some citation into the document.": "Voeg een citaat toe aan het document.",

View File

@ -22,7 +22,7 @@
"Learn more here.": "Saiba mais aqui.",
"Save": "Salvar",
"Insert Citation": "Inserir citação",
"Cancel select": "Cancelar seleção",
"Cancel selection": "Cancelar seleção",
"Refresh": "Atualizar",
"Unlink citations": "Desligar citações",
"Please insert some citation into the document.": "Por favor insira alguma citação no documento.",

View File

@ -22,7 +22,7 @@
"Learn more here.": "Saiba mais aqui.",
"Save": "Salve",
"Insert Citation": "Inserir Citação",
"Cancel select": "Cancelar seleccionar",
"Cancel selection": "Cancelar seleccionar",
"Refresh": "Actualizar",
"Unlink citations": "Desligar citações",
"Please insert some citation into the document.": "Por favor, insira alguma citação no documento.",

View File

@ -22,7 +22,7 @@
"Learn more here.": "Подробности здесь.",
"Save": "Сохранить",
"Insert Citation": "Вставить цитату",
"Cancel select": "Отменить выделение",
"Cancel selection": "Отменить выделение",
"Refresh": "Обновить",
"Unlink citations": "Открепить цитаты",
"Please insert some citation into the document.": "Пожалуйста, вставьте цитату в документ.",

View File

@ -22,7 +22,7 @@
"Learn more here.": "Mësoni më shumë këtu",
"Save": "Ruani",
"Insert Citation": "Shtoni citimin",
"Cancel select": "Anuloni selektimin",
"Cancel selection": "Anuloni selektimin",
"Refresh": "Rifreskoni",
"Unlink citations": "Hiqni citimet",
"Please insert some citation into the document.": "Ju lutem shtoni ndonjë citim në dokument",

View File

@ -22,7 +22,7 @@
"Learn more here.": "Сазнајте више овде.",
"Save": "Сачувај",
"Insert Citation": "Убаци цитат",
"Cancel select": "Откажи избор",
"Cancel selection": "Откажи избор",
"Refresh": "Освежи",
"Unlink citations": "Откажи цитате",
"Please insert some citation into the document.": "Молимо убаците неки цитат у документ.",

View File

@ -22,7 +22,7 @@
"Learn more here.": "Saznajte više ovde.",
"Save": "Sačuvaj",
"Insert Citation": "Ubaci citat",
"Cancel select": "Otkaži izbor",
"Cancel selection": "Otkaži izbor",
"Refresh": "Osveži",
"Unlink citations": "Otkazi citat",
"Please insert some citation into the document.": "Molimo ubacite neki citat u dokument.",

View File

@ -22,7 +22,7 @@
"Learn more here.": "点击此处了解更多信息。",
"Save": "保存",
"Insert Citation": "插入引用",
"Cancel select": "取消选择",
"Cancel selection": "取消选择",
"Refresh": "刷新",
"Unlink citations": "取消引用",
"Please insert some citation into the document.": "请插入一些引用到文档中。",