From 9261e4f25fd94c53f5ccce1bed2596b8ae2a4c76 Mon Sep 17 00:00:00 2001 From: Maxim Tsvyk <162802460+rand-06@users.noreply.github.com> Date: Tue, 25 Aug 2026 15:37:25 +0300 Subject: [PATCH 1/2] Added "Always in new tab" checkbox --- MainPage.cs | 7 +++++-- Resources/KtaneWeb.js | 22 ++++++++++++++++++++-- TranslationInfo.cs | 1 + 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/MainPage.cs b/MainPage.cs index d739c1b..9b39b9b 100644 --- a/MainPage.cs +++ b/MainPage.cs @@ -147,7 +147,7 @@ @media screen and (max-width: 1090px) and (min-width: 650.01px) {{ new TABLE { id = "main-table" }._( new TR { class_ = "header-row" }._( new TH { colspan = translation.Selectables.Length }._(translation.columnLinks), - new TH { class_ = "modlink" }._(new A { href = "#", class_ = "sort-header" }._(translation.columnName)), + new TH { class_ = "modlink" }._(new A { href = "#", class_ = "sort-header"}._(translation.columnName)), new TH { class_ = "infos" }._(new A { href = "#", class_ = "sort-header" }._(translation.columnInformation)))), // PERIODIC TABLE @@ -372,7 +372,10 @@ @media screen and (max-width: 1090px) and (min-width: 650.01px) {{ new H4(translation.linkOption), translation.Selectables.Select(sel => new DIV( new INPUT { type = itype.radio, class_ = "set-selectable", name = "selectable", id = $"selectable-{sel.PropName}" }.Data("selectable", sel.PropName), " ", - new LABEL { class_ = "set-selectable", id = $"selectable-label-{sel.PropName}", for_ = $"selectable-{sel.PropName}", accesskey = sel.Accel?.ToString().ToLowerInvariant() }._(sel.HumanReadable.Accel(sel.Accel))))), + new LABEL { class_ = "set-selectable", id = $"selectable-label-{sel.PropName}", for_ = $"selectable-{sel.PropName}", accesskey = sel.Accel?.ToString().ToLowerInvariant() }._(sel.HumanReadable.Accel(sel.Accel)))), + new INPUT { type = itype.checkbox, class_= "set-new-tab", id = "set-new-tab"}, + new LABEL {for_ = "set-new-tab"}._(translation.newTab) + ), new DIV { class_ = "option-group" }._(new H4(translation.languagesOption), new DIV { id = "languages-option" }), new BUTTON { class_ = "toggle-all-languages" }._(translation.languagesToggle)), diff --git a/Resources/KtaneWeb.js b/Resources/KtaneWeb.js index 96b0cc5..729b9de 100644 --- a/Resources/KtaneWeb.js +++ b/Resources/KtaneWeb.js @@ -126,6 +126,10 @@ function contributorSort(a, b) return p1 === p2 ? e1.localeCompare(e2) : p1 - p2; } +function readNewTabCheckbox(){ + return $('input.set-new-tab')[0].checked?"_blank":"_self"; +} + function initializePage(modules, initIcons, initDocDirs, initFilters, initSelectables, souvenirAttributes, moduleLoadExceptions, restrictedManuals, contactInfo) { for (let exception of moduleLoadExceptions) @@ -154,6 +158,7 @@ function initializePage(modules, initIcons, initDocDirs, initFilters, initSelect try { filter = JSON.parse(lStorage.getItem('filters') || '{}') || {}; } catch (exc) { } let selectable = lStorage.getItem('selectable') || 'manual'; + let currentTarget = lStorage.getItem('currentTarget') || '_self'; if (initSelectables.map(sel => sel.PropName).indexOf(selectable) === -1) selectable = 'manual'; let preferredManuals = {}; @@ -623,7 +628,7 @@ function initializePage(modules, initIcons, initDocDirs, initFilters, initSelect } let icon = el("img", "mod-icon", { src: `Icons/${mod.X === 0 && mod.Y === 0 ? 'blank' : encodeURIComponent(mod.FileName ?? mod.Name)}.png` }); - let modlink = el("a", "modlink", { href: mod.SelectableLinkUrl }, icon, el("span", "mod-name", mod.localName.replace(/'/g, "’"))); + let modlink = el("a", "modlink", { href: mod.SelectableLinkUrl}, icon, el("span", "mod-name", mod.localName.replace(/'/g, "’"))); setIssuesTooltip(modlink, mod); mod.ViewData.List.SelectableLink = modlink; let td1 = el("td", "infos-1", el("div", "modlink-wrap", modlink, mod.localName === mod.Name ? null : el("div", "inf-origname", mod.Name.replace(/'/g, "’")))); @@ -1605,8 +1610,21 @@ function initializePage(modules, initIcons, initDocDirs, initFilters, initSelect // This also calls updateFilter() setSelectable(selectable); - + + + $('input.set-selectable').click(function() { setSelectable($(this).data('selectable')); }); + $('input.set-new-tab').change(function(event){ + currentTarget = event.target.checked?"_blank":"_self"; + lStorage.setItem('currentTarget', currentTarget); + for (let el of document.getElementsByClassName("modlink")){ + el.setAttribute('target', currentTarget); + } + }); + $('input.set-new-tab')[0].checked = (lStorage.getItem('currentTarget') === "_blank"); + for (let el of document.getElementsByClassName("modlink")){ + el.setAttribute('target', currentTarget); + } $('input.filter').click(function() { updateFilter(); }); $("input.results-mode").click(function() { setResultsMode(this.value, resultsLimit); }); $("input#results-limit").change(function() { setResultsMode(resultsMode, this.value | 0); }); diff --git a/TranslationInfo.cs b/TranslationInfo.cs index 1cffbfa..c35fcad 100644 --- a/TranslationInfo.cs +++ b/TranslationInfo.cs @@ -232,6 +232,7 @@ private static TranslationInfo makeDefault() public string selectableSource = "Source code"; public string selectableSourceClone = "Source code (clone)"; public string selectableTutorial = "Tutorial videos"; + public string newTab = "Always open in new tab"; public string displayOption = "Display"; public string displayOriginalName = "Original name"; public string displayOriginalNameTooltip = "Displays the original (English-language) name in addition to the translated name."; From ff5b84ca077f66bf0e30e2af2dda09fe5ebd3c46 Mon Sep 17 00:00:00 2001 From: Maxim Tsvyk <162802460+rand-06@users.noreply.github.com> Date: Tue, 25 Aug 2026 15:41:20 +0300 Subject: [PATCH 2/2] cleanup of the prev commit --- MainPage.cs | 2 +- Resources/KtaneWeb.js | 8 +------- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/MainPage.cs b/MainPage.cs index 9b39b9b..f8acad3 100644 --- a/MainPage.cs +++ b/MainPage.cs @@ -147,7 +147,7 @@ @media screen and (max-width: 1090px) and (min-width: 650.01px) {{ new TABLE { id = "main-table" }._( new TR { class_ = "header-row" }._( new TH { colspan = translation.Selectables.Length }._(translation.columnLinks), - new TH { class_ = "modlink" }._(new A { href = "#", class_ = "sort-header"}._(translation.columnName)), + new TH { class_ = "modlink" }._(new A { href = "#", class_ = "sort-header" }._(translation.columnName)), new TH { class_ = "infos" }._(new A { href = "#", class_ = "sort-header" }._(translation.columnInformation)))), // PERIODIC TABLE diff --git a/Resources/KtaneWeb.js b/Resources/KtaneWeb.js index dd9b2e3..8dfa7a0 100644 --- a/Resources/KtaneWeb.js +++ b/Resources/KtaneWeb.js @@ -126,10 +126,6 @@ function contributorSort(a, b) return p1 === p2 ? e1.localeCompare(e2) : p1 - p2; } -function readNewTabCheckbox(){ - return $('input.set-new-tab')[0].checked?"_blank":"_self"; -} - function initializePage(modules, initIcons, initDocDirs, initFilters, initSelectables, souvenirAttributes, moduleLoadExceptions, restrictedManuals, contactInfo) { for (let exception of moduleLoadExceptions) @@ -628,7 +624,7 @@ function initializePage(modules, initIcons, initDocDirs, initFilters, initSelect } let icon = el("img", "mod-icon", { src: `Icons/${mod.X === 0 && mod.Y === 0 ? 'blank' : encodeURIComponent(mod.FileName ?? mod.Name)}.png` }); - let modlink = el("a", "modlink", { href: mod.SelectableLinkUrl}, icon, el("span", "mod-name", mod.localName.replace(/'/g, "’"))); + let modlink = el("a", "modlink", { href: mod.SelectableLinkUrl }, icon, el("span", "mod-name", mod.localName.replace(/'/g, "’"))); setIssuesTooltip(modlink, mod); mod.ViewData.List.SelectableLink = modlink; let td1 = el("td", "infos-1", el("div", "modlink-wrap", modlink, mod.localName === mod.Name ? null : el("div", "inf-origname", mod.Name.replace(/'/g, "’")))); @@ -1611,8 +1607,6 @@ function initializePage(modules, initIcons, initDocDirs, initFilters, initSelect // This also calls updateFilter() setSelectable(selectable); - - $('input.set-selectable').click(function() { setSelectable($(this).data('selectable')); }); $('input.set-new-tab').change(function(event){ currentTarget = event.target.checked?"_blank":"_self";