Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dynamic column #1144

Merged
merged 9 commits into from
Jan 20, 2025
3 changes: 3 additions & 0 deletions locales/template/en.po
Original file line number Diff line number Diff line change
Expand Up @@ -658,6 +658,9 @@ msgstr "Crop thumbnails"
msgid "Go to Page:"
msgstr "Go to Page:"

msgid "Select Columns:"
chu-shen marked this conversation as resolved.
Show resolved Hide resolved
msgstr "Select Columns:"

msgid "Switch to Compact Mode"
msgstr "Switch to Compact Mode"

Expand Down
3 changes: 3 additions & 0 deletions locales/template/zh.po
Original file line number Diff line number Diff line change
Expand Up @@ -658,6 +658,9 @@ msgstr "裁剪缩略图"
msgid "Go to Page:"
msgstr "跳转到页面:"

msgid "Select Columns:"
msgstr "选择列数:"

msgid "Switch to Compact Mode"
msgstr "切换到紧凑模式"

Expand Down
20 changes: 8 additions & 12 deletions public/css/lrr.css
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ td.title {
}

#customheader1,
td.custom1 {
max-width: 150px;
td.customheader1 {
max-width: 200px;
}

#customheader2,
td.custom2 {
[id^="customheader"],
td[id^="customheader"] {
max-width: 100px;
}

Expand Down Expand Up @@ -565,11 +565,9 @@ body.swal2-shown>[aria-hidden="true"] {
padding: 2px;
}

#customheader1,
#customheader2,
#tagsheader,
td.custom1,
td.custom2,
[id^="customheader"],
td[id^="customheader"],
td.tags {
max-width: 50px;
}
Expand Down Expand Up @@ -638,11 +636,9 @@ body.swal2-shown>[aria-hidden="true"] {
}

#i2,
#customheader1,
#customheader2,
[id^="customheader"],
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These changes seem to only collapse the headers, not the columns.
image

#tagsheader,
td.custom1,
td.custom2,
td[id^="customheader"],
td.tags {
display: none;
}
Expand Down
117 changes: 108 additions & 9 deletions public/js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,15 @@ Index.pageSize = 100;
*/
Index.initializeAll = function () {
// Bind events to DOM
$(document).on("click.edit-header-1", "#edit-header-1", () => Index.promptCustomColumn(1));
$(document).on("click.edit-header-2", "#edit-header-2", () => Index.promptCustomColumn(2));
$(document).on("click", "[id^=edit-header-]", function () {
const headerIndex = $(this).attr("id").split("-")[2];
Index.promptCustomColumn(headerIndex);
});
$(document).on("click.mode-toggle", ".mode-toggle", Index.toggleMode);
$(document).on("change.page-select", "#page-select", () => IndexTable.dataTable.page($("#page-select").val() - 1).draw("page"));
$(document).on("change.thumbnail-crop", "#thumbnail-crop", Index.toggleCrop);
$(document).on("change.namespace-sortby", "#namespace-sortby", Index.handleCustomSort);
$(document).on("change.columnCount", "#columnCount", Index.handleColumnNum);
$(document).on("click.order-sortby", "#order-sortby", Index.toggleOrder);
$(document).on("click.open-carousel", ".collapsible-title", Index.toggleCarousel);
$(document).on("click.reload-carousel", "#reload-carousel", Index.updateCarousel);
Expand Down Expand Up @@ -122,7 +125,12 @@ Index.initializeAll = function () {
IndexTable.initializeAll();
});

const columnCountSelect = document.getElementById("columnCount");
const storedColumnCount = localStorage.getItem("columnCount");
columnCountSelect.value = storedColumnCount ? storedColumnCount : 2;

Index.updateTableHeaders();
Index.resizableColumns();
};

Index.toggleMode = function () {
Expand Down Expand Up @@ -368,19 +376,52 @@ Index.updateCarousel = function (e) {
}
};

Index.handleColumnNum = function () {
const columnCountSelect = document.getElementById("columnCount");
const selectedCount = columnCountSelect.value;
localStorage.setItem("columnCount", selectedCount);
Index.updateTableHeaders();
document.location.reload(true);
};

/**
* Generate the Table Headers based on the custom namespaces set in localStorage.
*/
Index.generateTableHeaders = function (columnCount) {
const headerRow = $("#header-row");
headerRow.empty();
headerRow.append(`<th id="titleheader">
<a>Title</a>
</th>`);

for (let i = 1; i <= columnCount; i++) {
const customColumn = localStorage[`customColumn${i}`] || `Header ${i}`;
const headerHtml = `
<th id="customheader${i}">
<i id="edit-header-${i}" class="fas fa-pencil-alt edit-header-btn" title="Edit this column"></i>
<a id="header-${i}">${customColumn.charAt(0).toUpperCase() + customColumn.slice(1)}</a>
</th>`;
headerRow.append(headerHtml);
}
headerRow.append(`<th id="tagsheader">
<a>Tags</a>
</th>`);
};


/**
* Update the Table Headers based on the custom namespaces set in localStorage.
*/
Index.updateTableHeaders = function () {
const cc1 = localStorage.customColumn1;
const cc2 = localStorage.customColumn2;
let columnCount = localStorage.columnCount ? parseInt(localStorage.columnCount) : 2;
Index.generateTableHeaders(columnCount);

$("#customcol1").val(cc1);
$("#customcol2").val(cc2);
for (let i = 1; i <= columnCount; i++) {
const customColumn = localStorage[`customColumn${i}`] || `Header ${i}`;
$(`#customcol${i}`).val(customColumn);

// Modify text of <a> in headers
$("#header-1").html(cc1.charAt(0).toUpperCase() + cc1.slice(1));
$("#header-2").html(cc2.charAt(0).toUpperCase() + cc2.slice(1));
$(`#header-${i}`).html(customColumn.charAt(0).toUpperCase() + customColumn.slice(1) || `Header ${i}`);
}
};

/**
Expand Down Expand Up @@ -758,6 +799,64 @@ Index.migrateProgress = function () {
}
};

/**
* Restore and update column width, data store in localstorge.
*/
Index.resizableColumns = function () {
let currentHeader;
let startX;
let startWidth;

const headers = document.querySelectorAll("#header-row th");
headers.forEach((header, index) => {
// restore Column Width
const savedWidth = localStorage.getItem(`resizeColumn${index}`);
if (savedWidth) {
header.style.width = savedWidth;
}
// init
header.addEventListener('mousedown', function (event) {
if (event.offsetX > header.offsetWidth - 10) {
currentHeader = header;
startX = event.clientX;
startWidth = header.offsetWidth;

document.addEventListener('mousemove', resizeColumn);
document.addEventListener('mouseup', stopResize);

document.body.style.cursor = 'col-resize';
}
});
header.addEventListener('mousemove', function (event) {
if (event.offsetX > header.offsetWidth - 10) {
header.style.cursor = 'col-resize';
} else {
header.style.cursor = 'default';
}
});
});

function resizeColumn(event) {
if (currentHeader) {
const newWidth = startWidth + (event.clientX - startX);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This calculation is very inaccurate to me some times - I have to drag the mouse pretty far before the column width starts reacting (as seen in the screen recording in the other comment)

Some other times, it will violently snap the column width to a very different value as soon as I start sliding.

if (newWidth > 0) {
currentHeader.style.width = newWidth + 'px';
}
}
}

function stopResize() {
if (currentHeader) {
const index = Array.from(headers).indexOf(currentHeader);
localStorage.setItem(`resizeColumn${index}`, currentHeader.style.width);
currentHeader = null;
}
document.removeEventListener('mousemove', resizeColumn);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like this function needs a way to block the sort-on-click behavior that datatables has;

Currently if I drag to resize a column and release the mouse while in the column, it'll trigger a sort, which is very disorienting and resets the column width.

Screen.Recording.2024-12-31.043918.mp4

document.removeEventListener('mouseup', stopResize);
document.body.style.cursor = 'default';
}
};

jQuery(() => {
Index.initializeAll();
});
42 changes: 30 additions & 12 deletions public/js/index_datatables.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,20 @@ IndexTable.initializeAll = function () {
$.fn.dataTableExt.oStdClasses.sStripeOdd = "gtr0";
$.fn.dataTableExt.oStdClasses.sStripeEven = "gtr1";

// set custom columns
let columns = [];
let columnCount = localStorage.columnCount ? parseInt(localStorage.columnCount) : 2;
for (let i = 1; i <= columnCount; i++) {
columns.push({
data: "tags",
className: `customheader${i} itd`,
name: localStorage[`customColumn${i}`] || `defaultCol${i}`,
render: (data, type) => IndexTable.renderColumn(localStorage[`customColumn${i}`], type, data)
});
}
columns.unshift({ data: null, className: "title itd", name: "title", render: IndexTable.renderTitle });
chu-shen marked this conversation as resolved.
Show resolved Hide resolved
columns.push({ data: "tags", className: "tags itd", name: "tags", orderable: false, render: IndexTable.renderTags });

// Datatables configuration
IndexTable.dataTable = $(".datatables").DataTable({
serverSide: true,
Expand All @@ -67,13 +81,7 @@ IndexTable.initializeAll = function () {
preDrawCallback: IndexTable.initializeThumbView, // callbacks for thumbnail view
drawCallback: IndexTable.drawCallback,
rowCallback: IndexTable.buildThumbnailCell,
columns: [
/* eslint-disable object-curly-newline */
{ data: null, className: "title itd", name: "title", render: IndexTable.renderTitle },
{ data: "tags", className: "custom1 itd", name: localStorage.customColumn1, render: (data, type) => IndexTable.renderColumn(localStorage.customColumn1, type, data) },
{ data: "tags", className: "custom2 itd", name: localStorage.customColumn2, render: (data, type) => IndexTable.renderColumn(localStorage.customColumn2, type, data) },
{ data: "tags", className: "tags itd", name: "tags", orderable: false, render: IndexTable.renderTags },
],
columns: columns,
});

// If the url has parameters, handle them now by doing the matching search.
Expand Down Expand Up @@ -269,11 +277,14 @@ IndexTable.drawCallback = function () {

// Using double equals here since the sort column can be either a string or an int
// eslint-disable-next-line eqeqeq
if (currentSort == 1) {
currentSort = localStorage.customColumn1;
// eslint-disable-next-line eqeqeq
} else if (currentSort == 2) {
currentSort = localStorage.customColumn2;
// get current columns count, except title and tags
const currentCustomColumnCount = IndexTable.dataTable.columns().count() - 2;
// check currentSort, if out of range, back to use title
if (currentSort > currentCustomColumnCount) {
localStorage.indexSort = 0;
}
if (currentSort >= 1 && currentSort <= columnCount) {
currentSort = localStorage[`customColumn${currentSort}`] || `Header ${currentSort}`;
} else {
currentSort = "title";
}
Expand Down Expand Up @@ -320,6 +331,13 @@ IndexTable.consumeURLParameters = function () {
} else if (localStorage.indexSort) {
order[0][0] = localStorage.indexSort;
}
// get current columns count, except title and tags
const currentCustomColumnCount = IndexTable.dataTable.columns().count() - 2;
// check currentSort, if out of range, back to use title
if (localStorage.indexSort > currentCustomColumnCount) {
localStorage.indexSort = 0;
order[0][0] = localStorage.indexSort;
}

if (params.has("sortdir")) {
order[0][1] = params.get("sortdir");
Expand Down
27 changes: 10 additions & 17 deletions templates/index.html.tt2
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,14 @@
<div style="margin-left:auto">[% c.lh("Go to Page:") %]
<select class="favtag-btn" id="page-select">
</select>
<label for="columnCount">[% c.lh("Select Columns:") %]</label>
chu-shen marked this conversation as resolved.
Show resolved Hide resolved
<select class="favtag-btn" id="columnCount">
<script>
for (let i = 1; i <= 20; i++) {
document.write(`<option value="${i}">${i}</option>`);
}
</script>
</select>
<a class="fa fa-list fa-2x mode-toggle thumbnail-toggle table-option" href="#"
title="[% c.lh('Switch to Compact Mode') %]"></a>
<a class="fa fa-table fa-2x mode-toggle compact-toggle table-option" href="#"
Expand All @@ -152,23 +160,8 @@

<table class="itg datatables">
<thead class="list" style="display: none;">
<tr>
<th id="titleheader">
<a>[% c.lh("Title") %]</a>
</th>
<th id="customheader1">
<i id="edit-header-1" class="fas fa-pencil-alt edit-header-btn"
title="[% c.lh('Edit this column') %]"></i>
<a id="header-1">[% c.lh("Artist") %]</a>
</th>
<th id="customheader2">
<i id="edit-header-2" class="fas fa-pencil-alt edit-header-btn"
title="[% c.lh('Edit this column') %]"></i>
<a id="header-2">[% c.lh("Series") %]</a>
</th>
<th id="tagsheader">
<a>[% c.lh("Tags") %]</a>
</th>
<tr id="header-row">
<!--dynamic row-->
</tr>
</thead>
<tbody class="list" style="display: none;">
Expand Down
Loading