Как я могу синхронизировать порядок строк в нескольких таблицах данных, не вызывая бесконечную повторную сортировку?Jquery

Программирование на jquery
Ответить
Anonymous
 Как я могу синхронизировать порядок строк в нескольких таблицах данных, не вызывая бесконечную повторную сортировку?

Сообщение Anonymous »

У меня есть четыре таблицы данных на странице, каждая из которых отображает разные финансовые показатели одного и того же набора акций. Каждая таблица имеет общий столбец «Тикер», и каждая таблица имеет одинаковое количество строк и одинаковые тикеры в одном и том же порядке.
Когда пользователь щелкает заголовок столбца, таблица сортируется правильно (по возрастанию/убыванию).

Однако, когда пользователь переключается на другую вкладку, порядок сортировки теряется.

Чтобы обеспечить визуальную согласованность, я хочу, чтобы один и тот же порядок тикеров применялся ко всем таблицы.
Ожидаемое поведение
  • Когда пользователь сортирует таблицу A, новый порядок должен быть зафиксирован.
  • Затем этот порядок следует применить к таблицам B, C и D.
  • Следовательно, если они сортируют что-то в таблице C, порядок строк должен быть обновлен, чтобы соответствовать таблицам A, B и D.
Проблема
Моя текущая реализация работает при первой сортировке, но после этого она входит в бесконечный цикл.
/>
Цикл возникает, потому что, когда новый порядок применяется к другим таблицам, он запускает свои собственные события сортировки, которые затем рекурсивно повторно применяют порядок снова и снова.
Вопрос
Как лучше всего:
  • Применить отсортированный порядок строк из одной DataTable для других, чтобы обеспечить визуальную синхронизацию всех таблиц?
  • Предотвратить рекурсивное срабатывание события изменения
Вот моя текущая реализация

Код: Выделить всё

(function($) {
'use strict';

// Configuration
const TABLE_IDS = [
'tablepress-daily_performance',
'tablepress-annualized_performance',
'tablepress-historical_performance',
];

const TICKER_COLUMN = 0;
const MAX_INIT_ATTEMPTS = 50;
const INIT_CHECK_INTERVAL = 100;

// State management
let isSyncing = false;
let dataTables = {};
let initAttempts = 0;

/**
* Check if all DataTables are initialized
*/
function areAllTablesReady() {
for (let tableId of TABLE_IDS) {
const table = $('#' + tableId);
if (table.length === 0 || !$.fn.DataTable.isDataTable('#' + tableId)) {
return false;
}
}
return true;
}

/**
* Initialize DataTable references
*/
function initializeDataTables() {
TABLE_IDS.forEach(tableId => {
// Get the API instance
dataTables[tableId] = $('#' + tableId).DataTable();
});
console.log('All DataTables initialized successfully');
}

/**
* Get the current order of Tickers from a sorted table
* @param {string} sourceTableId - The ID of the table that was just sorted
* @returns {Array} The list of Tickers in the new display order
*/
function getTickerOrder(sourceTableId) {
const table = dataTables[sourceTableId];

// Use DataTables API to get data in the 'current' display order
const tickerOrder = table.rows({
order: 'current',
search: 'applied'
}).data().map(function(row) {
return row[TICKER_COLUMN];
}).toArray();

console.log(`Captured ${tickerOrder.length} Tickers from ${sourceTableId}`);
return tickerOrder;
}

/**
* Apply ticker order to a target table by re-positioning rows
* This is more reliable than clearing and re-adding rows.
* @param {string} targetTableId - The ID of the table to be reordered
* @param {Array} tickerOrder - The master order of Tickers
*/
function applyTickerOrder(targetTableId, tickerOrder) {
const table = dataTables[targetTableId];

// 1. Map Ticker to the actual DataTables row node
const tickerToRowNodeMap = new Map();
table.rows().every(function() {
const rowData = this.data();
const rowNode = this.node();
if (rowData && rowNode) {
tickerToRowNodeMap.set(rowData[TICKER_COLUMN], rowNode);
}
});

// 2.  Iterate through the master order and move each row to its new index
tickerOrder.forEach((ticker, newIndex) => {
const rowNode = tickerToRowNodeMap.get(ticker);

if (rowNode) {
// Use row().index(newIndex) to manually set the new position of the row
// This is the core of the synchronization
table.row(rowNode).index(newIndex);
}
});

// 3. Redraw the table to display the new order.
// We set order([]) to clear any previous sorting visual and only show the manual reorder.
table.order([]).draw(false);

console.log(`Applied and drew table ${targetTableId} to sync order.`);
}

/**
* Sync all tables to match the source table's order
* @param {string} sourceTableId - The ID of the table that triggered the sort
*/
function syncTables(sourceTableId) {
// Prevent recursive syncing
if (isSyncing) {
return;
}

isSyncing = true;
console.log('Syncing tables based on:', sourceTableId);

try {
// Get the master ticker order from the source table
const tickerOrder = getTickerOrder(sourceTableId);

// Apply to all other tables
TABLE_IDS.forEach(tableId => {
if (tableId !== sourceTableId) {
applyTickerOrder(tableId, tickerOrder);
}
});

console.log('Sync completed successfully');

} catch (error) {
console.error('Error during sync:', error);
} finally {
// Reset the flag
isSyncing = false;
}
}

/**
* Attach event listeners to all tables
*/
function attachEventListeners() {
TABLE_IDS.forEach(tableId => {
const table = dataTables[tableId];

// Listen for order event (triggered when user sorts)
// The 'order.dt' event fires *after* the sort has been applied.
table.on('order.dt', function() {
console.log('User Sorted table:', tableId);

// Use a small delay to ensure DataTables' internal state is fully stable
// after the 'order.dt' event fires.
setTimeout(function() {
syncTables(tableId);
}, 50);
});
});

console.log('Event listeners attached to all tables');
}

/**
* Main initialization function
*/
function init() {
const checkInterval = setInterval(function() {
initAttempts++;

if (areAllTablesReady()) {
clearInterval(checkInterval);
initializeDataTables();
attachEventListeners();
console.log('TablePress sync initialization complete');
} else if (initAttempts >= MAX_INIT_ATTEMPTS) {
clearInterval(checkInterval);
console.error('TablePress sync failed to initialize - tables not ready after 5 seconds');
}
}, INIT_CHECK_INTERVAL);
}

// Start initialization when DOM is ready
$(document).ready(function() {
init();
});

})(jQuery);
Я попробовал временно отключить прослушиватели событий при применении нового порядка, вот так:

Код: Выделить всё

isSyncing = true;
// apply order to other tables
isSyncing = false;
и проверка возврата (isSyncing); внутри обработчика сортировки.
Это частично помогает, но иногда нарушает сортировку или пропускает обновления.
Я также пробовал динамически удалять и повторно подключать прослушиватели событий щелчка после синхронизации, но этот подход показался хакерским и все равно вызывал непредсказуемое поведение.
Есть ли лучший способ реализовать мою функциональность или что-нибудь, что я могу сделать, чтобы предотвратить бесконечный цикл?

Подробнее здесь: https://stackoverflow.com/questions/797 ... g-infinite
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Jquery»