Files
Plataforma-de-desarrolladores/SIG.Web/Scripts/UcBuscadorCatalogo.js
Jorge Luis caudillo esparza 6685ef63fb Initial commit
2026-07-14 11:15:57 -07:00

2406 lines
68 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

(function (window, document) {
'use strict';
var instances = {};
var documentClickBound = false;
function getElement(id) {
return id ? document.getElementById(id) : null;
}
function toArray(value) {
return Array.isArray(value) ? value : [];
}
function asBoolean(value) {
return value === true || value === 'true' || value === 1 || value === '1';
}
function normalizeText(value) {
return value === null || value === undefined ? '' : String(value);
}
function getProperty(source, propertyName) {
if (!source || !propertyName) {
return undefined;
}
if (Object.prototype.hasOwnProperty.call(source, propertyName)) {
return source[propertyName];
}
var requestedName = String(propertyName).toLowerCase();
var keys = Object.keys(source);
for (var index = 0; index < keys.length; index += 1) {
if (keys[index].toLowerCase() === requestedName) {
return source[keys[index]];
}
}
return undefined;
}
function getColumnName(column) {
return normalizeText(
getProperty(column, 'ColumnName') ||
getProperty(column, 'Name')
);
}
function getColumnTitle(column) {
return normalizeText(
getProperty(column, 'DisplayName') ||
getProperty(column, 'Title') ||
getProperty(column, 'HeaderText') ||
getColumnName(column)
);
}
function normalizeSortOrders(config, value) {
var rawValue = value;
if (typeof rawValue === 'string') {
try {
rawValue = rawValue
? JSON.parse(rawValue)
: [];
} catch (error) {
rawValue = [];
}
}
var allowedColumns = {};
toArray(config.resultColumns).forEach(function (column) {
var columnName = getColumnName(column);
if (columnName) {
allowedColumns[columnName.toLowerCase()] =
columnName;
}
});
var addedColumns = {};
var result = [];
toArray(rawValue).forEach(function (order) {
var requestedColumn = normalizeText(
getProperty(order, 'Columna')
);
var normalizedColumn =
allowedColumns[
requestedColumn.toLowerCase()
];
if (
!normalizedColumn ||
addedColumns[
normalizedColumn.toLowerCase()
]
) {
return;
}
addedColumns[
normalizedColumn.toLowerCase()
] = true;
result.push({
Columna: normalizedColumn,
Descendente: asBoolean(
getProperty(
order,
'Descendente'
)
)
});
});
return result;
}
function saveSortOrders(instance) {
if (!instance.elements.sortOrders) {
return;
}
instance.elements.sortOrders.value =
JSON.stringify(
instance.sortOrders
);
}
function findSortOrderIndex(
instance,
columnName
) {
var requestedColumn =
normalizeText(
columnName
).toLowerCase();
for (
var index = 0;
index < instance.sortOrders.length;
index += 1
) {
if (
normalizeText(
instance.sortOrders[index].Columna
).toLowerCase() ===
requestedColumn
) {
return index;
}
}
return -1;
}
function refreshSortHeaders(instance) {
var headers =
instance.elements.results.
querySelectorAll(
'.ucbc-sortable-header'
);
for (
var index = 0;
index < headers.length;
index += 1
) {
var header = headers[index];
var columnName =
normalizeText(
header.getAttribute(
'data-column'
)
);
var orderIndex =
findSortOrderIndex(
instance,
columnName
);
var active =
orderIndex >= 0;
var order =
active
? instance.sortOrders[
orderIndex
]
: null;
var titleButton =
header.querySelector(
'.ucbc-sort-title'
);
var direction =
header.querySelector(
'.ucbc-sort-direction'
);
var priority =
header.querySelector(
'.ucbc-sort-priority'
);
var removeButton =
header.querySelector(
'.ucbc-sort-remove'
);
header.classList.toggle(
'ucbc-sortable-header-active',
active
);
header.setAttribute(
'aria-sort',
!active
? 'none'
: order.Descendente
? 'descending'
: 'ascending'
);
if (direction) {
direction.textContent =
!active
? ''
: order.Descendente
? '▼'
: '▲';
}
if (priority) {
priority.textContent =
active
? String(orderIndex + 1)
: '';
priority.hidden = !active;
}
if (removeButton) {
removeButton.hidden = !active;
removeButton.title =
active
? 'Quitar este orden'
: '';
}
if (titleButton) {
titleButton.disabled =
instance.loading;
titleButton.title =
!active
? 'Ordenar ascendente'
: order.Descendente
? 'Cambiar a orden ascendente'
: 'Cambiar a orden descendente';
}
if (removeButton) {
removeButton.disabled =
instance.loading;
}
}
}
function toggleSortOrder(
instance,
columnName
) {
if (instance.loading) {
return;
}
var orderIndex =
findSortOrderIndex(
instance,
columnName
);
if (orderIndex < 0) {
instance.sortOrders.push({
Columna: columnName,
Descendente: false
});
} else {
instance.sortOrders[
orderIndex
].Descendente =
!instance.sortOrders[
orderIndex
].Descendente;
}
saveSortOrders(instance);
refreshSortHeaders(instance);
executeSearch(
instance,
1,
'top'
);
}
function removeSortOrder(
instance,
columnName
) {
if (instance.loading) {
return;
}
var orderIndex =
findSortOrderIndex(
instance,
columnName
);
if (orderIndex < 0) {
return;
}
instance.sortOrders.splice(
orderIndex,
1
);
saveSortOrders(instance);
refreshSortHeaders(instance);
executeSearch(
instance,
1,
'top'
);
}
function createSortHeader(
instance,
column
) {
var columnName =
getColumnName(column);
var header =
document.createElement('th');
header.scope = 'col';
header.className =
'ucbc-sortable-header';
header.setAttribute(
'data-column',
columnName
);
var content =
createElement(
'div',
'ucbc-sort-header-content'
);
var titleButton =
createElement(
'button',
'ucbc-sort-title'
);
titleButton.type = 'button';
titleButton.textContent =
getColumnTitle(column);
titleButton.addEventListener(
'click',
function (event) {
event.preventDefault();
event.stopPropagation();
toggleSortOrder(
instance,
columnName
);
}
);
var indicators =
createElement(
'span',
'ucbc-sort-indicators'
);
var direction =
createElement(
'span',
'ucbc-sort-direction'
);
direction.setAttribute(
'aria-hidden',
'true'
);
var priority =
createElement(
'span',
'ucbc-sort-priority'
);
priority.setAttribute(
'aria-label',
'Prioridad de orden'
);
priority.hidden = true;
var removeButton =
createElement(
'button',
'ucbc-sort-remove'
);
removeButton.type = 'button';
removeButton.textContent = '×';
removeButton.hidden = true;
removeButton.setAttribute(
'aria-label',
'Quitar orden de ' +
getColumnTitle(column)
);
removeButton.addEventListener(
'click',
function (event) {
event.preventDefault();
event.stopPropagation();
removeSortOrder(
instance,
columnName
);
}
);
indicators.appendChild(
direction
);
indicators.appendChild(
priority
);
content.appendChild(
titleButton
);
content.appendChild(
indicators
);
content.appendChild(
removeButton
);
header.appendChild(
content
);
return header;
}
function isSearchColumn(column) {
var value = getProperty(column, 'ForSearch');
return value === undefined ? true : asBoolean(value);
}
function clearChildren(element) {
if (!element) {
return;
}
while (element.firstChild) {
element.removeChild(element.firstChild);
}
}
function setVisible(element, visible) {
if (!element) {
return;
}
element.hidden = !visible;
}
function createElement(tagName, className) {
var element = document.createElement(tagName);
if (className) {
element.className = className;
}
return element;
}
function ensureClientElements(instance) {
var root = instance.root;
var clearButton = root.querySelector('[data-ucbc-role="clear"]');
if (!clearButton) {
clearButton = createElement('button', 'ucbc-button ucbc-clear-button');
clearButton.type = 'button';
clearButton.setAttribute('data-ucbc-role', 'clear');
clearButton.setAttribute('aria-label', 'Quitar selección');
clearButton.title = 'Quitar selección';
clearButton.textContent = '×';
if (instance.elements.selectedText &&
instance.elements.selectedText.parentNode === root) {
root.insertBefore(
clearButton,
instance.elements.selectedText.nextSibling
);
} else {
root.appendChild(clearButton);
}
}
var selectedColumnLabel = root.querySelector('[data-ucbc-role="selected-column-label"]');
if (!selectedColumnLabel) {
selectedColumnLabel = createElement('span', 'ucbc-selected-column-label');
selectedColumnLabel.setAttribute('data-ucbc-role', 'selected-column-label');
selectedColumnLabel.hidden = true;
root.appendChild(selectedColumnLabel);
}
var panel = root.querySelector('[data-ucbc-role="panel"]');
if (!panel) {
panel = createElement('div', 'ucbc-panel');
panel.setAttribute('data-ucbc-role', 'panel');
panel.hidden = true;
root.appendChild(panel);
}
var columnMenu = panel.querySelector('[data-ucbc-role="column-menu"]');
if (!columnMenu) {
columnMenu = createElement('div', 'ucbc-column-menu');
columnMenu.setAttribute('data-ucbc-role', 'column-menu');
columnMenu.hidden = true;
panel.appendChild(columnMenu);
}
var status = panel.querySelector('[data-ucbc-role="status"]');
if (!status) {
status = createElement('div', 'ucbc-status');
status.setAttribute('data-ucbc-role', 'status');
status.setAttribute('aria-live', 'polite');
status.hidden = true;
panel.appendChild(status);
}
var results = panel.querySelector('[data-ucbc-role="results"]');
if (!results) {
results = createElement('div', 'ucbc-results');
results.setAttribute('data-ucbc-role', 'results');
panel.appendChild(results);
}
var footer = panel.querySelector('[data-ucbc-role="footer"]');
if (!footer) {
footer = createElement('div', 'ucbc-footer');
footer.setAttribute('data-ucbc-role', 'footer');
footer.hidden = true;
panel.appendChild(footer);
}
var firstButton = footer.querySelector('[data-ucbc-role="first"]');
if (!firstButton) {
firstButton = createElement('button', 'ucbc-button ucbc-page-button');
firstButton.type = 'button';
firstButton.setAttribute('data-ucbc-role', 'first');
firstButton.textContent = 'Inicio';
footer.appendChild(firstButton);
}
var previousButton = footer.querySelector('[data-ucbc-role="previous"]');
if (!previousButton) {
previousButton = createElement('button', 'ucbc-button ucbc-page-button');
previousButton.type = 'button';
previousButton.setAttribute('data-ucbc-role', 'previous');
previousButton.textContent = 'Anterior';
footer.appendChild(previousButton);
}
var pageLabel = footer.querySelector('[data-ucbc-role="page-label"]');
if (!pageLabel) {
pageLabel = createElement('span', 'ucbc-page-label');
pageLabel.setAttribute('data-ucbc-role', 'page-label');
footer.appendChild(pageLabel);
}
var nextButton = footer.querySelector('[data-ucbc-role="next"]');
if (!nextButton) {
nextButton = createElement('button', 'ucbc-button ucbc-page-button');
nextButton.type = 'button';
nextButton.setAttribute('data-ucbc-role', 'next');
nextButton.textContent = 'Siguiente';
footer.appendChild(nextButton);
}
var lastButton = footer.querySelector('[data-ucbc-role="last"]');
if (!lastButton) {
lastButton = createElement('button', 'ucbc-button ucbc-page-button');
lastButton.type = 'button';
lastButton.setAttribute('data-ucbc-role', 'last');
lastButton.textContent = 'Final';
footer.appendChild(lastButton);
}
instance.elements.clearButton = clearButton;
instance.elements.selectedColumnLabel = selectedColumnLabel;
instance.elements.panel = panel;
instance.elements.columnMenu = columnMenu;
instance.elements.status = status;
instance.elements.results = results;
instance.elements.footer = footer;
instance.elements.firstButton = firstButton;
instance.elements.previousButton = previousButton;
instance.elements.pageLabel = pageLabel;
var pageIntentIndicator = panel.querySelector(
'[data-ucbc-role="page-intent"]'
);
if (!pageIntentIndicator) {
pageIntentIndicator = createElement(
'div',
'ucbc-page-intent'
);
pageIntentIndicator.setAttribute(
'data-ucbc-role',
'page-intent'
);
pageIntentIndicator.setAttribute(
'aria-live',
'polite'
);
pageIntentIndicator.setAttribute(
'aria-atomic',
'true'
);
pageIntentIndicator.hidden = true;
var pageIntentArrow = createElement(
'span',
'ucbc-page-intent-arrow'
);
pageIntentArrow.setAttribute(
'data-ucbc-role',
'page-intent-arrow'
);
var pageIntentLabel = createElement(
'span',
'ucbc-page-intent-label'
);
pageIntentLabel.setAttribute(
'data-ucbc-role',
'page-intent-label'
);
var pageIntentDots = createElement(
'span',
'ucbc-page-intent-dots'
);
pageIntentDots.setAttribute(
'data-ucbc-role',
'page-intent-dots'
);
pageIntentIndicator.appendChild(
pageIntentArrow
);
pageIntentIndicator.appendChild(
pageIntentLabel
);
pageIntentIndicator.appendChild(
pageIntentDots
);
panel.appendChild(
pageIntentIndicator
);
}
instance.elements.clearButton = clearButton;
instance.elements.selectedColumnLabel = selectedColumnLabel;
instance.elements.panel = panel;
instance.elements.columnMenu = columnMenu;
instance.elements.status = status;
instance.elements.results = results;
instance.elements.footer = footer;
instance.elements.firstButton = firstButton;
instance.elements.previousButton = previousButton;
instance.elements.pageLabel = pageLabel;
instance.elements.nextButton = nextButton;
instance.elements.lastButton = lastButton;
instance.elements.pageIntentIndicator =
pageIntentIndicator;
instance.elements.pageIntentArrow =
pageIntentIndicator.querySelector(
'[data-ucbc-role="page-intent-arrow"]'
);
instance.elements.pageIntentLabel =
pageIntentIndicator.querySelector(
'[data-ucbc-role="page-intent-label"]'
);
instance.elements.pageIntentDots =
pageIntentIndicator.querySelector(
'[data-ucbc-role="page-intent-dots"]'
);
}
function getPageTurnSteps(instance) {
return Math.max(
1,
Number(instance.config.pageTurnSteps) || 3
);
}
function ensurePageIntentDots(instance) {
var dotsContainer =
instance.elements.pageIntentDots;
if (!dotsContainer) {
return;
}
var requiredSteps =
getPageTurnSteps(instance);
if (
dotsContainer.children.length ===
requiredSteps
) {
return;
}
clearChildren(dotsContainer);
for (
var index = 0;
index < requiredSteps;
index += 1
) {
dotsContainer.appendChild(
createElement(
'span',
'ucbc-page-intent-dot'
)
);
}
}
function hidePageTurnIndicator(instance) {
var indicator =
instance.elements.pageIntentIndicator;
if (!indicator) {
return;
}
indicator.classList.remove(
'ucbc-page-intent-visible',
'ucbc-page-intent-next',
'ucbc-page-intent-previous',
'ucbc-page-intent-complete'
);
indicator.hidden = true;
}
function updatePageTurnIndicator(
instance,
completed
) {
var state = instance.pageTurnIntent;
var indicator =
instance.elements.pageIntentIndicator;
if (
!state ||
!indicator ||
state.direction === 0
) {
return;
}
ensurePageIntentDots(instance);
var isNext =
state.direction === 1;
indicator.hidden = false;
indicator.classList.remove(
'ucbc-page-intent-next',
'ucbc-page-intent-previous',
'ucbc-page-intent-complete'
);
indicator.classList.add(
isNext
? 'ucbc-page-intent-next'
: 'ucbc-page-intent-previous'
);
indicator.classList.add(
'ucbc-page-intent-visible'
);
if (completed) {
indicator.classList.add(
'ucbc-page-intent-complete'
);
}
instance.elements.pageIntentArrow.textContent =
isNext ? '↓' : '↑';
if (completed) {
instance.elements.pageIntentLabel.textContent =
isNext
? 'Cambiando a la siguiente página...'
: 'Cambiando a la página anterior...';
} else {
instance.elements.pageIntentLabel.textContent =
(
isNext
? 'Siguiente página'
: 'Página anterior'
) +
' · ' +
state.steps +
' de ' +
getPageTurnSteps(instance);
}
var dots =
instance.elements.pageIntentDots.children;
for (
var index = 0;
index < dots.length;
index += 1
) {
dots[index].classList.toggle(
'ucbc-page-intent-dot-active',
completed || index < state.steps
);
}
}
function resetPageTurnState(
instance,
keepChangingPage
) {
var state = instance.pageTurnIntent;
if (!state) {
return;
}
if (state.resetTimer) {
window.clearTimeout(
state.resetTimer
);
state.resetTimer = null;
}
state.direction = 0;
state.steps = 0;
state.accumulatedDelta = 0;
state.lastStepAt = 0;
if (!keepChangingPage) {
state.changingPage = false;
}
}
function cancelPageTurnIntent(instance) {
if (!instance.pageTurnIntent) {
return;
}
resetPageTurnState(
instance,
false
);
hidePageTurnIndicator(instance);
}
function restartPageTurnResetTimer(instance) {
var state = instance.pageTurnIntent;
if (!state) {
return;
}
if (state.resetTimer) {
window.clearTimeout(
state.resetTimer
);
}
state.resetTimer =
window.setTimeout(
function () {
cancelPageTurnIntent(instance);
},
instance.config
.pageTurnResetMilliseconds
);
}
function normalizePageTurnDelta(
event,
resultsElement
) {
var delta = Number(event.deltaY) || 0;
if (event.deltaMode === 1) {
delta *= 16;
} else if (event.deltaMode === 2) {
delta *= resultsElement.clientHeight;
}
return delta;
}
function executePageTurn(
instance,
direction
) {
var state = instance.pageTurnIntent;
if (
!state ||
state.changingPage ||
instance.loading
) {
return;
}
state.changingPage = true;
if (state.resetTimer) {
window.clearTimeout(
state.resetTimer
);
state.resetTimer = null;
}
updatePageTurnIndicator(
instance,
true
);
window.setTimeout(
function () {
var targetPage =
direction === 1
? instance.page + 1
: instance.page - 1;
var restoreScroll =
direction === 1
? 'top'
: 'bottom';
resetPageTurnState(
instance,
true
);
hidePageTurnIndicator(instance);
executeSearch(
instance,
targetPage,
restoreScroll
);
},
220
);
}
function handlePageTurnWheel(
instance,
event
) {
var state = instance.pageTurnIntent;
var results = instance.elements.results;
if (
!state ||
instance.loading ||
state.changingPage ||
getTotalPages(instance) <= 1
) {
return;
}
var delta =
normalizePageTurnDelta(
event,
results
);
if (delta === 0) {
return;
}
var direction =
delta > 0 ? 1 : -1;
var edgeTolerance = 2;
var atTop =
results.scrollTop <=
edgeTolerance;
var atBottom =
results.scrollTop +
results.clientHeight >=
results.scrollHeight -
edgeTolerance;
var canGoNext =
direction === 1 &&
atBottom &&
instance.hasMore;
var canGoPrevious =
direction === -1 &&
atTop &&
instance.page > 1;
if (
state.direction !== 0 &&
state.direction !== direction
) {
cancelPageTurnIntent(instance);
return;
}
if (!canGoNext && !canGoPrevious) {
if (state.direction !== 0) {
cancelPageTurnIntent(instance);
}
return;
}
event.preventDefault();
if (state.direction === 0) {
state.direction = direction;
state.steps = 0;
state.accumulatedDelta = 0;
state.lastStepAt = 0;
}
restartPageTurnResetTimer(instance);
state.accumulatedDelta +=
Math.abs(delta);
updatePageTurnIndicator(
instance,
false
);
var now = Date.now();
if (
state.accumulatedDelta <
instance.config.pageTurnDeltaThreshold
) {
return;
}
if (
state.lastStepAt > 0 &&
now - state.lastStepAt <
instance.config.pageTurnStepDelay
) {
return;
}
state.accumulatedDelta = 0;
state.lastStepAt = now;
state.steps += 1;
updatePageTurnIndicator(
instance,
false
);
if (
state.steps >=
getPageTurnSteps(instance)
) {
executePageTurn(
instance,
direction
);
}
}
function setStatus(instance, message, statusType) {
var status = instance.elements.status;
status.textContent = normalizeText(message);
status.className = 'ucbc-status';
if (statusType) {
status.className += ' ucbc-status-' + statusType;
}
setVisible(status, Boolean(message));
}
function showPanel(instance) {
setVisible(instance.elements.panel, true);
}
function hidePanel(instance) {
cancelPageTurnIntent(instance);
setVisible(instance.elements.panel, false);
setVisible(instance.elements.columnMenu, false);
}
function updateSelectedState(instance) {
var selectedValue = normalizeText(instance.elements.selectedValue.value);
var hasSelection = selectedValue.length > 0;
setVisible(instance.elements.clearButton, hasSelection && instance.enabled);
instance.root.classList.toggle('ucbc-has-selection', hasSelection);
}
function getSelectedColumn(instance) {
var column = normalizeText(instance.elements.selectedColumn.value);
if (!column) {
column = instance.config.allColumnsValue;
instance.elements.selectedColumn.value = column;
}
return column;
}
function findConfiguredColumn(instance, columnName) {
var columns = toArray(instance.config.columns);
for (var index = 0; index < columns.length; index += 1) {
if (getColumnName(columns[index]).toLowerCase() === normalizeText(columnName).toLowerCase()) {
return columns[index];
}
}
return null;
}
function updateSelectedColumnPresentation(instance) {
var selectedColumn = getSelectedColumn(instance);
var isAllColumns = selectedColumn.toLowerCase() === normalizeText(instance.config.allColumnsValue).toLowerCase();
var title = 'Todos los campos';
if (!isAllColumns) {
var column = findConfiguredColumn(instance, selectedColumn);
title = column ? getColumnTitle(column) : selectedColumn;
}
instance.elements.columnsButton.title = 'Buscar por: ' + title;
instance.elements.columnsButton.setAttribute('aria-label', 'Buscar por: ' + title);
instance.elements.selectedColumnLabel.textContent = title;
}
function positionColumnMenu(instance) {
var menu = instance.elements.columnMenu;
var button = instance.elements.columnsButton;
var panel = instance.elements.panel;
if (!menu || !button || !panel || menu.hidden || panel.hidden) {
return;
}
var buttonRect = button.getBoundingClientRect();
var panelRect = panel.getBoundingClientRect();
var requestedLeft = buttonRect.left - panelRect.left;
var maximumLeft = Math.max(0, panel.clientWidth - menu.offsetWidth);
var left = Math.max(0, Math.min(requestedLeft, maximumLeft));
menu.style.right = 'auto';
menu.style.left = Math.round(left) + 'px';
menu.style.top = '0px';
}
function positionUserFilterPanel(instance) {
var panel = instance.root.querySelector(
'.ucbc-user-filter-panel'
);
var button = instance.elements.userFiltersButton;
var root = instance.root;
if (!panel || !button || !root) {
return;
}
if (window.innerWidth <= 720) {
panel.style.removeProperty('top');
panel.style.removeProperty('right');
panel.style.removeProperty('left');
return;
}
var rootRect = root.getBoundingClientRect();
var buttonRect = button.getBoundingClientRect();
var requestedLeft = buttonRect.left - rootRect.left;
var maximumLeft = Math.max(
0,
root.clientWidth - panel.offsetWidth
);
var left = Math.max(
0,
Math.min(requestedLeft, maximumLeft)
);
var top = buttonRect.bottom - rootRect.top + 5;
panel.style.right = 'auto';
panel.style.left = Math.round(left) + 'px';
panel.style.top = Math.round(top) + 'px';
}
function renderColumnMenu(instance) {
var menu = instance.elements.columnMenu;
clearChildren(menu);
var list = createElement('div', 'ucbc-column-options');
var selectedColumn = getSelectedColumn(instance);
function appendOption(value, text) {
var button = createElement('button', 'ucbc-column-option');
button.type = 'button';
button.textContent = text;
button.setAttribute('data-column', value);
if (normalizeText(value).toLowerCase() === selectedColumn.toLowerCase()) {
button.classList.add('ucbc-column-option-selected');
button.setAttribute('aria-pressed', 'true');
} else {
button.setAttribute('aria-pressed', 'false');
}
button.addEventListener('click', function (event) {
event.preventDefault();
instance.elements.selectedColumn.value = value;
updateSelectedColumnPresentation(instance);
renderColumnMenu(instance);
setVisible(menu, false);
if (instance.elements.searchInput.value.trim().length >= instance.config.minimumCharacters) {
executeSearch(instance, 1);
}
});
list.appendChild(button);
}
appendOption(instance.config.allColumnsValue, 'Todos los campos');
toArray(instance.config.columns)
.filter(isSearchColumn)
.forEach(function (column) {
appendOption(getColumnName(column), getColumnTitle(column));
});
menu.appendChild(list);
}
function getTotalPages(instance) {
return instance.totalRecords > 0
? Math.ceil(instance.totalRecords / instance.config.pageSize)
: 0;
}
function setLoading(instance, isLoading) {
instance.loading = isLoading;
instance.root.classList.toggle('ucbc-loading', isLoading);
instance.elements.searchInput.setAttribute('aria-busy', isLoading ? 'true' : 'false');
instance.elements.searchButton.disabled = !instance.enabled || isLoading;
instance.elements.columnsButton.disabled = !instance.enabled || isLoading;
var totalPages = getTotalPages(instance);
instance.elements.firstButton.disabled = isLoading || instance.page <= 1;
instance.elements.previousButton.disabled = isLoading || instance.page <= 1;
instance.elements.nextButton.disabled = isLoading || !instance.hasMore;
instance.elements.lastButton.disabled = isLoading || totalPages <= 1 || instance.page >= totalPages;
if (isLoading) {
setStatus(instance, 'Buscando...', 'loading');
} else if (instance.pageTurnIntent) {
instance.pageTurnIntent.changingPage = false;
}
refreshSortHeaders(instance);
}
function resetResults(instance) {
cancelPageTurnIntent(instance);
instance.items = [];
instance.page = 1;
instance.totalRecords = 0;
instance.hasMore = false;
instance.restoreScroll = null;
clearChildren(instance.elements.results);
setVisible(instance.elements.footer, false);
}
function updatePager(instance) {
var totalPages = getTotalPages(instance);
var showFooter = instance.page > 1 || instance.hasMore || instance.totalRecords > 0;
setVisible(instance.elements.footer, showFooter);
instance.elements.firstButton.disabled = instance.loading || instance.page <= 1;
instance.elements.previousButton.disabled = instance.loading || instance.page <= 1;
instance.elements.nextButton.disabled = instance.loading || !instance.hasMore;
instance.elements.lastButton.disabled = instance.loading || totalPages <= 1 || instance.page >= totalPages;
if (totalPages > 0) {
instance.elements.pageLabel.textContent =
'Página ' + instance.page + ' de ' + totalPages +
' · ' + instance.totalRecords + ' registro(s)';
} else {
instance.elements.pageLabel.textContent = '';
}
}
function createCell(value) {
var cell = document.createElement('td');
cell.textContent = normalizeText(value);
return cell;
}
function selectItem(instance, item) {
var selectedValue = normalizeText(getProperty(item, '__SelectedValue'));
var displayText = normalizeText(getProperty(item, '__DisplayText'));
instance.elements.selectedValue.value = selectedValue;
instance.elements.selectedJson.value = JSON.stringify(item || {});
instance.elements.selectedText.value = displayText || selectedValue;
updateSelectedState(instance);
hidePanel(instance);
resetResults(instance);
setStatus(instance, '', null);
if (typeof instance.postBack === 'function') {
instance.postBack('select');
}
}
function getVisibleResultColumns(instance) {
var resultColumns = toArray(instance.config.resultColumns);
var displayColumns = toArray(instance.config.displayColumns);
if (!displayColumns.length) {
return resultColumns;
}
return displayColumns
.map(function (displayColumn) {
if (typeof displayColumn !== 'string') {
return displayColumn;
}
var requestedName = normalizeText(displayColumn).toLowerCase();
for (var index = 0; index < resultColumns.length; index += 1) {
if (getColumnName(resultColumns[index]).toLowerCase() === requestedName) {
return resultColumns[index];
}
}
return {
ColumnName: displayColumn,
DisplayName: displayColumn
};
})
.filter(function (column) {
return Boolean(getColumnName(column));
});
}
function renderResults(instance) {
var container = instance.elements.results;
clearChildren(container);
if (!instance.items.length) {
setStatus(
instance,
'No se encontraron resultados.',
'empty'
);
updatePager(instance);
return;
}
setStatus(instance, '', null);
var visibleColumns =
getVisibleResultColumns(instance);
var table =
createElement(
'table',
'ucbc-results-table'
);
table.setAttribute('role', 'grid');
var thead =
document.createElement('thead');
var headerRow =
document.createElement('tr');
visibleColumns.forEach(function (column) {
headerRow.appendChild(
createSortHeader(
instance,
column
)
);
});
thead.appendChild(headerRow);
table.appendChild(thead);
var tbody =
document.createElement('tbody');
instance.items.forEach(
function (item, itemIndex) {
var row =
document.createElement('tr');
row.className =
'ucbc-result-row';
row.tabIndex = 0;
row.setAttribute(
'data-index',
String(itemIndex)
);
visibleColumns.forEach(
function (column) {
row.appendChild(
createCell(
getProperty(
item,
getColumnName(column)
)
)
);
}
);
row.addEventListener(
'click',
function () {
selectItem(
instance,
item
);
}
);
row.addEventListener(
'keydown',
function (event) {
if (
event.key === 'Enter' ||
event.key === ' '
) {
event.preventDefault();
selectItem(
instance,
item
);
return;
}
if (
event.key !== 'ArrowDown' &&
event.key !== 'ArrowUp'
) {
return;
}
var rows =
container.querySelectorAll(
'.ucbc-result-row'
);
var currentIndex =
Number(
row.getAttribute(
'data-index'
)
);
var nextIndex =
event.key === 'ArrowDown'
? currentIndex + 1
: currentIndex - 1;
if (
nextIndex >= 0 &&
nextIndex < rows.length
) {
event.preventDefault();
rows[nextIndex].focus();
}
}
);
tbody.appendChild(row);
}
);
table.appendChild(tbody);
container.appendChild(table);
refreshSortHeaders(instance);
updatePager(instance);
if (instance.restoreScroll === 'bottom') {
container.scrollTop =
container.scrollHeight;
} else {
container.scrollTop = 0;
}
instance.restoreScroll = null;
}
function clearSearchTimeout(instance) {
if (!instance.requestTimeoutTimer) {
return;
}
window.clearTimeout(
instance.requestTimeoutTimer
);
instance.requestTimeoutTimer = null;
}
function startSearchTimeout(
instance,
requestId
) {
clearSearchTimeout(instance);
instance.requestTimeoutTimer =
window.setTimeout(
function () {
if (
requestId !==
instance.requestId
) {
return;
}
instance.requestTimeoutTimer = null;
// Invalidate the request so a late server
// response cannot replace the timeout message.
instance.requestId += 1;
setLoading(instance, false);
resetResults(instance);
showPanel(instance);
setStatus(
instance,
'La búsqueda tardó más de ' +
Math.round(
instance.config
.searchTimeoutMilliseconds /
1000
) +
' segundos. Intente nuevamente.',
'error'
);
},
instance.config
.searchTimeoutMilliseconds
);
}
function executeSearch(instance, page, restoreScroll) {
if (!instance.enabled || instance.loading || typeof instance.callback !== 'function') {
return;
}
if (
instance.pageTurnIntent &&
!instance.pageTurnIntent.changingPage
) {
cancelPageTurnIntent(instance);
}
var text = instance.elements.searchInput.value.trim();
if (text.length < instance.config.minimumCharacters) {
resetResults(instance);
showPanel(instance);
setStatus(
instance,
'Escriba al menos ' + instance.config.minimumCharacters + ' carácter(es) para buscar.',
'info'
);
return;
}
if (instance.timer) {
window.clearTimeout(instance.timer);
instance.timer = null;
}
instance.requestId += 1;
var currentRequestId =
instance.requestId;
var requestedPage = Math.max(1, Number(page) || 1);
var totalPages = getTotalPages(instance);
if (totalPages > 0) {
requestedPage = Math.min(requestedPage, totalPages);
}
instance.page = requestedPage;
instance.restoreScroll = restoreScroll || 'top';
var request = {
Texto: text,
Columna: getSelectedColumn(instance),
Pagina: instance.page,
Ordenes: instance.sortOrders.map(
function (order) {
return {
Columna: order.Columna,
Descendente:
order.Descendente
};
}
)
};
showPanel(instance);
setVisible(instance.elements.columnMenu, false);
setLoading(instance, true);
startSearchTimeout(
instance,
currentRequestId
);
try {
instance.callback(
JSON.stringify(request),
{
clientId: instance.config.clientId,
requestId: currentRequestId
}
);
} catch (error) {
clearSearchTimeout(instance);
setLoading(instance, false);
setStatus(
instance,
error && error.message
? error.message
: 'No fue posible iniciar la búsqueda.',
'error'
);
}
}
function scheduleSearch(instance) {
if (!instance.enabled) {
return;
}
if (instance.timer) {
window.clearTimeout(instance.timer);
}
instance.timer = window.setTimeout(function () {
executeSearch(instance, 1);
}, instance.config.delayMilliseconds);
}
function clearSelection(instance) {
instance.elements.selectedValue.value = '';
instance.elements.selectedJson.value = '';
instance.elements.selectedText.value = '';
updateSelectedState(instance);
hidePanel(instance);
if (typeof instance.postBack === 'function') {
instance.postBack('clear');
}
}
function findUserFilterActionElement(root, target) {
var current = target;
while (current && current !== root) {
if (current.getAttribute &&
current.getAttribute('data-ucbc-filter-action')) {
return current;
}
current = current.parentNode;
}
return null;
}
function applyUserFilterEditor(instance) {
var editor = instance.root.querySelector(
'[data-ucbc-filter-editor-key]'
);
if (!editor || typeof instance.postBack !== 'function') {
return;
}
var operatorControl = editor.querySelector(
'[data-ucbc-filter-editor-operator]'
);
var valueControl = editor.querySelector(
'[data-ucbc-filter-editor-value]'
);
if (!valueControl) {
return;
}
var filterKey = normalizeText(
editor.getAttribute('data-ucbc-filter-editor-key')
);
var operatorValue = operatorControl
? normalizeText(operatorControl.value)
: 'Igual';
var value = normalizeText(valueControl.value);
var text = value;
if (valueControl.tagName &&
valueControl.tagName.toLowerCase() === 'select') {
var selectedOption = valueControl.options[
valueControl.selectedIndex
];
text = selectedOption
? normalizeText(selectedOption.text)
: value;
}
instance.elements.userFilterEditorKey.value = filterKey;
instance.elements.userFilterEditorOperator.value = operatorValue;
instance.elements.userFilterEditorValue.value = value;
instance.elements.userFilterEditorText.value = text;
instance.postBack('filters:apply');
}
function applyUserFilterListItem(instance, actionElement) {
if (!actionElement || typeof instance.postBack !== 'function') {
return;
}
var filterKey = normalizeText(
actionElement.getAttribute('data-ucbc-filter-key')
);
var value = normalizeText(
actionElement.getAttribute('data-ucbc-filter-value')
);
var text = normalizeText(
actionElement.getAttribute('data-ucbc-filter-text')
);
instance.elements.userFilterEditorKey.value = filterKey;
instance.elements.userFilterEditorOperator.value = 'Igual';
instance.elements.userFilterEditorValue.value = value;
instance.elements.userFilterEditorText.value = text;
instance.postBack('filters:apply');
}
function normalizeUserFilterSearchText(value) {
var normalized = normalizeText(value).toLocaleLowerCase();
if (typeof normalized.normalize === 'function') {
normalized = normalized
.normalize('NFD')
.replace(/[\u0300-\u036f]/g, '');
}
return normalized;
}
function filterUserFilterMenu(searchInput) {
if (!searchInput) {
return;
}
var editor = searchInput.closest(
'[data-ucbc-filter-editor-key]'
);
if (!editor) {
return;
}
var searchValue = normalizeUserFilterSearchText(
searchInput.value
);
var items = editor.querySelectorAll(
'[data-ucbc-filter-item]'
);
var visibleCount = 0;
Array.prototype.forEach.call(items, function (item) {
var itemText = normalizeUserFilterSearchText(
item.getAttribute('data-ucbc-filter-search-text')
);
var visible =
!searchValue || itemText.indexOf(searchValue) >= 0;
item.hidden = !visible;
if (visible) {
visibleCount += 1;
}
});
var noMatches = editor.querySelector(
'[data-ucbc-filter-no-matches]'
);
if (noMatches) {
noMatches.hidden = visibleCount > 0;
}
}
function handleUserFilterAction(instance, actionElement) {
var action = normalizeText(
actionElement.getAttribute('data-ucbc-filter-action')
).toLowerCase();
var filterKey = normalizeText(
actionElement.getAttribute('data-ucbc-filter-key')
);
if (typeof instance.postBack !== 'function') {
return;
}
switch (action) {
case 'edit':
instance.postBack(
'filters:edit:' + encodeURIComponent(filterKey)
);
break;
case 'remove':
instance.postBack(
'filters:remove:' + encodeURIComponent(filterKey)
);
break;
case 'close':
instance.postBack('filters:close');
break;
case 'back':
instance.postBack('filters:back');
break;
case 'apply':
applyUserFilterEditor(instance);
break;
case 'select-list-item':
applyUserFilterListItem(instance, actionElement);
break;
}
}
function bindEvents(instance) {
if (instance.root.__ucbcEventsBound) {
return;
}
instance.root.__ucbcEventsBound = true;
instance.elements.searchInput.addEventListener('input', function () {
scheduleSearch(instance);
});
instance.elements.searchInput.addEventListener('keydown', function (event) {
if (event.key === 'Enter') {
event.preventDefault();
executeSearch(instance, 1);
} else if (event.key === 'Escape') {
hidePanel(instance);
}
});
instance.elements.searchButton.addEventListener('click', function (event) {
event.preventDefault();
executeSearch(instance, 1);
});
instance.elements.columnsButton.addEventListener('click', function (event) {
event.preventDefault();
event.stopPropagation();
var shouldShow = instance.elements.columnMenu.hidden;
renderColumnMenu(instance);
showPanel(instance);
setVisible(instance.elements.columnMenu, shouldShow);
if (shouldShow) {
positionColumnMenu(instance);
}
});
if (instance.elements.userFiltersButton) {
instance.elements.userFiltersButton.addEventListener(
'click',
function (event) {
event.preventDefault();
event.stopPropagation();
if (typeof instance.postBack === 'function') {
instance.postBack('filters:open');
}
}
);
}
instance.root.addEventListener('click', function (event) {
var actionElement = findUserFilterActionElement(
instance.root,
event.target
);
if (!actionElement) {
return;
}
event.preventDefault();
event.stopPropagation();
handleUserFilterAction(instance, actionElement);
});
instance.root.addEventListener('input', function (event) {
var target = event.target;
if (!target || !target.getAttribute ||
!target.getAttribute('data-ucbc-filter-search')) {
return;
}
filterUserFilterMenu(target);
});
window.addEventListener('resize', function () {
if (!instance.elements.columnMenu.hidden) {
positionColumnMenu(instance);
}
positionUserFilterPanel(instance);
});
instance.elements.clearButton.addEventListener('click', function (event) {
event.preventDefault();
clearSelection(instance);
});
instance.elements.firstButton.addEventListener('click', function (event) {
event.preventDefault();
if (instance.page > 1) {
executeSearch(instance, 1, 'top');
}
});
instance.elements.previousButton.addEventListener('click', function (event) {
event.preventDefault();
if (instance.page > 1) {
executeSearch(instance, instance.page - 1, 'bottom');
}
});
instance.elements.nextButton.addEventListener('click', function (event) {
event.preventDefault();
if (instance.hasMore) {
executeSearch(instance, instance.page + 1, 'top');
}
});
instance.elements.lastButton.addEventListener('click', function (event) {
event.preventDefault();
var totalPages = getTotalPages(instance);
if (totalPages > 0 && instance.page < totalPages) {
executeSearch(instance, totalPages, 'top');
}
});
instance.elements.results.addEventListener(
'wheel',
function (event) {
handlePageTurnWheel(
instance,
event
);
},
{
passive: false
}
);
instance.elements.results.addEventListener(
'scroll',
function () {
var state =
instance.pageTurnIntent;
if (
!state ||
state.direction === 0 ||
state.changingPage
) {
return;
}
var results =
instance.elements.results;
var edgeTolerance = 2;
var remainsAtRequestedEdge =
state.direction === 1
? results.scrollTop +
results.clientHeight >=
results.scrollHeight -
edgeTolerance
: results.scrollTop <=
edgeTolerance;
if (!remainsAtRequestedEdge) {
cancelPageTurnIntent(instance);
}
}
);
}
function bindDocumentClick() {
if (documentClickBound) {
return;
}
documentClickBound = true;
document.addEventListener('click', function (event) {
Object.keys(instances).forEach(function (key) {
var instance = instances[key];
if (instance && instance.root && !instance.root.contains(event.target)) {
hidePanel(instance);
}
});
});
}
function normalizeConfiguration(configuration) {
var config = configuration || {};
config.clientId = normalizeText(config.clientId || config.rootId);
config.rootId = normalizeText(config.rootId || config.clientId);
config.minimumCharacters = Math.max(0, Number(config.minimumCharacters) || 0);
config.delayMilliseconds = Math.max(0, Number(config.delayMilliseconds) || 0);
config.searchTimeoutMilliseconds = Math.max(
1000,
Number(config.searchTimeoutMilliseconds) ||
15000
);
config.pageSize = Math.max(1, Number(config.pageSize) || 50);
config.pageTurnSteps = Math.max(
1,
Number(config.pageTurnSteps) || 3
);
config.pageTurnResetMilliseconds = Math.max(
200,
Number(config.pageTurnResetMilliseconds) || 900
);
config.pageTurnDeltaThreshold = Math.max(
1,
Number(config.pageTurnDeltaThreshold) || 40
);
config.pageTurnStepDelay = Math.max(
0,
Number(config.pageTurnStepDelay) || 90
);
config.allColumnsValue = normalizeText(config.allColumnsValue || '__ALL__');
config.columns = toArray(config.columns);
config.resultColumns = toArray(config.resultColumns);
config.displayColumns = toArray(config.displayColumns);
config.enabled = config.enabled === undefined ? true : asBoolean(config.enabled);
config.hasUserFilters = asBoolean(config.hasUserFilters);
config.refreshAfterUserFilterChange =
asBoolean(config.refreshAfterUserFilterChange);
return config;
}
function init(configuration, callback, postBack) {
var config = normalizeConfiguration(configuration);
var root = getElement(config.rootId);
if (!root) {
return;
}
var existing = instances[config.clientId];
if (existing && existing.root === root) {
existing.config = config;
existing.callback = callback;
existing.postBack = postBack;
existing.enabled = config.enabled;
existing.elements.sortOrders =
getElement(
config.sortOrdersId
);
existing.elements.userFiltersButton =
getElement(config.userFiltersButtonId);
existing.elements.userFiltersJson =
getElement(config.userFiltersJsonId);
existing.elements.userFilterEditorKey =
getElement(config.userFilterEditorKeyId);
existing.elements.userFilterEditorOperator =
getElement(config.userFilterEditorOperatorId);
existing.elements.userFilterEditorValue =
getElement(config.userFilterEditorValueId);
existing.elements.userFilterEditorText =
getElement(config.userFilterEditorTextId);
existing.sortOrders =
normalizeSortOrders(
config,
existing.sortOrders
);
saveSortOrders(existing);
updateSelectedState(existing);
updateSelectedColumnPresentation(existing);
refreshSortHeaders(existing);
window.setTimeout(function () {
positionUserFilterPanel(existing);
}, 0);
if (config.refreshAfterUserFilterChange) {
window.setTimeout(function () {
executeSearch(existing, 1);
}, 0);
}
return;
}
var instance = {
config: config,
root: root,
callback: callback,
postBack: postBack,
enabled: config.enabled,
elements: {
searchInput: getElement(config.searchInputId),
searchButton: getElement(config.searchButtonId),
columnsButton: getElement(config.columnsButtonId),
selectedText: getElement(config.selectedTextId),
selectedValue: getElement(config.selectedValueId),
selectedJson: getElement(config.selectedJsonId),
selectedColumn: getElement(config.selectedColumnId),
sortOrders: getElement(config.sortOrdersId),
userFiltersButton: getElement(config.userFiltersButtonId),
userFiltersJson: getElement(config.userFiltersJsonId),
userFilterEditorKey: getElement(config.userFilterEditorKeyId),
userFilterEditorOperator: getElement(config.userFilterEditorOperatorId),
userFilterEditorValue: getElement(config.userFilterEditorValueId),
userFilterEditorText: getElement(config.userFilterEditorTextId)
},
sortOrders: [],
items: [],
page: 1,
totalRecords: 0,
hasMore: false,
loading: false,
requestId: 0,
timer: null,
requestTimeoutTimer: null,
restoreScroll: null,
pageTurnIntent: {
direction: 0,
steps: 0,
accumulatedDelta: 0,
lastStepAt: 0,
resetTimer: null,
changingPage: false
}
};
if (!instance.elements.searchInput ||
!instance.elements.searchButton ||
!instance.elements.columnsButton ||
!instance.elements.selectedText ||
!instance.elements.selectedValue ||
!instance.elements.selectedJson ||
!instance.elements.selectedColumn ||
!instance.elements.sortOrders ||
!instance.elements.userFiltersJson ||
!instance.elements.userFilterEditorKey ||
!instance.elements.userFilterEditorOperator ||
!instance.elements.userFilterEditorValue ||
!instance.elements.userFilterEditorText ||
(config.hasUserFilters && !instance.elements.userFiltersButton)) {
return;
}
instance.sortOrders =
normalizeSortOrders(
config,
instance.elements.sortOrders.value
);
saveSortOrders(instance);
root.classList.add('ucbc');
ensureClientElements(instance);
bindEvents(instance);
bindDocumentClick();
updateSelectedState(instance);
updateSelectedColumnPresentation(instance);
instance.elements.searchInput.disabled = !instance.enabled;
instance.elements.searchButton.disabled = !instance.enabled;
instance.elements.columnsButton.disabled = !instance.enabled;
if (instance.elements.userFiltersButton) {
instance.elements.userFiltersButton.disabled = !instance.enabled;
}
instances[config.clientId] = instance;
window.setTimeout(function () {
positionUserFilterPanel(instance);
}, 0);
if (config.refreshAfterUserFilterChange) {
window.setTimeout(function () {
executeSearch(instance, 1);
}, 0);
}
}
function callbackSuccess(rawResponse, context) {
var clientId = context && context.clientId
? context.clientId
: '';
var instance = instances[clientId];
if (!instance) {
return;
}
if (context.requestId !== instance.requestId) {
return;
}
clearSearchTimeout(instance);
var response;
try {
response = typeof rawResponse === 'string'
? JSON.parse(rawResponse)
: rawResponse;
} catch (error) {
setLoading(instance, false);
setStatus(instance, 'La respuesta del servidor no contiene JSON válido.', 'error');
return;
}
setLoading(instance, false);
if (!response || !asBoolean(getProperty(response, 'Ok'))) {
resetResults(instance);
showPanel(instance);
setStatus(
instance,
normalizeText(getProperty(response, 'Mensaje')) || 'Ocurrió un error al buscar.',
'error'
);
return;
}
instance.items = toArray(getProperty(response, 'Items'));
instance.page = Math.max(1, Number(getProperty(response, 'Pagina')) || 1);
instance.totalRecords = Math.max(0, Number(getProperty(response, 'TotalRegistros')) || 0);
instance.hasMore = asBoolean(getProperty(response, 'TieneMas'));
showPanel(instance);
renderResults(instance);
}
function callbackError(errorMessage, context) {
var clientId = context && context.clientId
? context.clientId
: '';
var instance = instances[clientId];
if (!instance) {
return;
}
if (context.requestId !== instance.requestId) {
return;
}
clearSearchTimeout(instance);
setLoading(instance, false);
resetResults(instance);
showPanel(instance);
setStatus(
instance,
normalizeText(errorMessage) || 'No fue posible completar la búsqueda.',
'error'
);
}
window.UcBuscadorCatalogo = {
init: init,
callbackSuccess: callbackSuccess,
callbackError: callbackError
};
}(window, document));