[tabbed-changeform] Improve tabbed changeform feature.

master
Fabio Caccamo 2022-11-30 19:06:52 +01:00
parent f2b800d9ca
commit 967f5827f2
4 changed files with 185 additions and 106 deletions

View File

@ -1,43 +1,56 @@
.admin-interface .tabbed-changeform-tab {
.admin-interface .tabbed-changeform-tabs {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
overflow-x: auto;
padding-bottom: 8px;
scrollbar-width: 4px;
overflow-y: hidden;
scrollbar-width: thin;
padding-bottom: 15px;
}
.admin-interface .tabbed-changeform-tab::-webkit-scrollbar {
height: 4px;
background-color: var(--border-color);
@-moz-document url-prefix() {
.admin-interface .tabbed-changeform-tabs {
padding-bottom: 13px;
}
.admin-interface .tabbed-changeform-tab::-webkit-scrollbar-thumb {
background: #aaa;
}
.admin-interface .tabbed-changeform-tab button {
.admin-interface .tabbed-changeform-tabs .tabbed-changeform-tablink {
appearance: none;
-webkit-appearance: none;
border: none;
border-radius: 0;
border: 1px solid transparent;
border-bottom: 1px solid var(--border-color);
flex-shrink: 0;
flex-grow: 0;
cursor: pointer;
padding: 8px 12px;
margin: 0;
background-color: var(--admin-interface-module-header-text-color);
color: var(--admin-interface-module-background-color);
}
.admin-interface .tabbed-changeform-tab button.active {
outline: none;
font-weight: bold;
border: 1px solid var(--border-color);
border-bottom: none;
border-radius: var(--admin-interface-module-border-radius);
border-bottom-left-radius: 0px;
border-bottom-right-radius: 0px;
flex-shrink: 0;
flex-grow: 0;
cursor: pointer;
padding: 10px 15px;
margin: 0;
background-color: var(--admin-interface-module-header-text-color);
color: var(--admin-interface-generic-link-color);
font-size: 13px;
font-weight: bold;
outline: none !important;
}
.admin-interface .tabbed-changeform-tabs .tabbed-changeform-tablink + .tabbed-changeform-tablink {
margin-left: -1px;
}
.admin-interface .tabbed-changeform-tabs .tabbed-changeform-tablink:hover {
color: var(--admin-interface-generic-link-hover-color);
}
.admin-interface .tabbed-changeform-tabs .tabbed-changeform-tablink.active {
border: 1px solid var(--border-color);
border-bottom: 1px solid transparent;
color: var(--admin-interface-module-background-color);
}
.admin-interface .tabbed-changeform-tabs-remaining-space {
flex: 1;
border-bottom: 1px solid var(--border-color);
}
.admin-interface .tabbed-changeform-tabcontent {
@ -48,8 +61,3 @@
.admin-interface .tabbed-changeform-tabcontent.active {
display: block;
}
.admin-interface .tabbed-changeform-tabs-remaining-space {
flex: 1;
border-bottom: 1px solid var(--border-color);
}

View File

@ -1,14 +0,0 @@
function openTab(evt, tabName) {
var tabcontents, tablinks;
tabcontents = document.getElementsByClassName("tabbed-changeform-tabcontent");
for (let tabcontent of tabcontents) {
tabcontent.classList.remove("active");
}
tablinks = document.getElementsByClassName("tabbed-changeform-tablinks");
for (let tablink of tablinks) {
tablink.classList.remove("active");
}
document.getElementById(tabName).classList.add("active");
evt.currentTarget.classList.add("active");
}

View File

@ -0,0 +1,73 @@
(function (AdminInterface) {
var scope = AdminInterface;
scope.tabbedChangeForm = {
openTab: function (event, tabName) {
this.openTabByName(tabName);
},
openTabByName: function(tabName) {
let tablinkEl = document.getElementById("tablink-" + tabName);
let tabcontentEl = document.getElementById("tabcontent-" + tabName);
if (!tablinkEl || !tabcontentEl) {
return false;
}
let tablinks = document.getElementsByClassName("tabbed-changeform-tablink");
let tabcontents = document.getElementsByClassName("tabbed-changeform-tabcontent");
// toggle tab link
for (let tablink of tablinks) {
tablink.classList.remove("active");
}
tablinkEl.classList.add("active");
// toggle tab content
for (let tabcontent of tabcontents) {
tabcontent.classList.remove("active");
}
tabcontentEl.classList.add("active");
// update location hash
let history = window.history;
if (history) {
history.replaceState(undefined, undefined, "#" + tabName);
}
return true;
},
openTabByLocationHash: function() {
let hash = window.location.hash;
if (hash && hash !== "#") {
let tabName = hash.substring(1);
if (this.openTabByName(tabName)) {
this.scrollTabsToTabByName(tabName);
}
}
},
scrollTabsToTabByName: function(tabName) {
let tabsEl = document.getElementById("tabbed-changeform-tabs");
let tablinkEl = document.getElementById("tablink-" + tabName);
if (!tabsEl || !tablinkEl) {
return;
}
let tablinkLeft = (tablinkEl.offsetLeft - tabsEl.offsetLeft);
let tabsScrollLeft = Math.ceil(tablinkLeft);
tabsEl.scrollTo({
top: 0,
left: tabsScrollLeft,
behavior: "instant"
});
}
};
// scope.tabbedChangeForm.openTabByLocationHash();
document.addEventListener('DOMContentLoaded', function() {
scope.tabbedChangeForm.openTabByLocationHash();
}, false);
}(window.AdminInterface = window.AdminInterface || {}));

View File

@ -1,7 +1,6 @@
{% extends "admin/change_form.html" %}
{% load static admin_interface_tags %}
{% block field_sets %}
{% get_admin_interface_setting "show_fieldsets_as_tabs" as show_fieldsets_as_tabs %}
@ -14,63 +13,76 @@
{% else %}
<div class="tabbed-changeform-tab">
<div id="tabbed-changeform-tabs" class="tabbed-changeform-tabs">
{% if show_fieldsets_as_tabs %}
{% for fieldset in adminform %}
<button type="button" class="tabbed-changeform-tablinks {{ forloop.counter0|default:"active" }}" onclick="openTab(event, 'tab-{{fieldset.name|slugify}}')">
{{ fieldset.name|default_if_none:opts.verbose_name|capfirst}}
{% with fieldset.name|default_if_none:opts.verbose_name as tab_name %}
<button type="button" id="tablink-{{ tab_name|slugify }}" class="tabbed-changeform-tablink {{ forloop.counter0|default:'active' }}" onclick="AdminInterface.tabbedChangeForm.openTab(event, '{{ tab_name|slugify }}')">
{{ tab_name|capfirst }}
</button>
{% endwith %}
{% endfor %}
{% else %}
<button type="button" class="tabbed-changeform-tablinks active" onclick="openTab(event, 'general')">
{{ opts.verbose_name|capfirst }}
{% with opts.verbose_name as tab_name %}
<button type="button" id="tablink-{{ tab_name|slugify }}" class="tabbed-changeform-tablink active" onclick="AdminInterface.tabbedChangeForm.openTab(event, '{{ tab_name|slugify }}')">
{{ tab_name|capfirst }}
</button>
{% endwith %}
{% endif %}
{% if show_inlines_as_tabs %}
{% for inline_admin_formset in inline_admin_formsets %}
<button type="button" class="tabbed-changeform-tablinks" onclick="openTab(event, 'tab-{{inline_admin_formset.opts.verbose_name_plural|slugify}}')">
{{inline_admin_formset.opts.verbose_name_plural|capfirst}}
{% with fieldset.name|default_if_none:opts.verbose_name as tab_name %}
<button type="button" id="tablink-{{ tab_name|slugify }}" class="tabbed-changeform-tablink" onclick="AdminInterface.tabbedChangeForm.openTab(event, '{{ tab_name|slugify }}')">
{{ tab_name|capfirst }}
</button>
{% endwith %}
{% endfor %}
{% endif %}
<div class="tabbed-changeform-tabs-remaining-space"></div>
<span class="tabbed-changeform-tabs-remaining-space"></span>
</div>
{% if show_fieldsets_as_tabs %}
{% for fieldset in adminform %}
<div id="tab-{{fieldset.name|slugify}}" class="tabbed-changeform-tabcontent {{ forloop.counter0|default:"active" }}">
{% with fieldset.name|default_if_none:opts.verbose_name as tab_name %}
<div id="tabcontent-{{ tab_name|slugify }}" class="tabbed-changeform-tabcontent {{ forloop.counter0|default:'active' }}">
{% include "admin/includes/headerless_fieldset.html" %}
</div>
{% endwith %}
{% endfor %}
{% else %}
<div id="general" class="tabbed-changeform-tabcontent active">
{% with opts.verbose_name as tab_name %}
<div id="tabcontent-{{ tab_name|slugify }}" class="tabbed-changeform-tabcontent active">
{% for fieldset in adminform %}
{% include "admin/includes/fieldset.html" %}
{% endfor %}
</div>
{% endwith %}
{% endif %}
{% for inline_admin_formset in inline_admin_formsets %}
<div id="tab-{{inline_admin_formset.opts.verbose_name_plural|slugify}}" class="tabbed-changeform-tabcontent">
{% with inline_admin_formset.opts.verbose_name_plural as tab_name %}
<div id="tabcontent-{{ tab_name|slugify }}" class="tabbed-changeform-tabcontent">
{% get_admin_interface_inline_template inline_admin_formset.opts.template as inline_template %}
{% include inline_template %}
</div>
{% endwith %}
{% endfor %}
<script
type="text/javascript"
id="tabbed-changeform-script"
src="{% static "admin_interface/js/tabbed_changeform.js" %}"
>
</script>
<script type="text/javascript" id="admin-interface-tabbed-changeform-script" src="{% static 'admin_interface/tabbed-changeform/tabbed-changeform.js' %}"></script>
{% endif %}
{% endblock %}
{% block inline_field_sets %}
{% get_admin_interface_setting "show_inlines_as_tabs" as show_inlines_as_tabs %}
{% if not show_inlines_as_tabs %}
{{ block.super }}
{% endif %}
{% endblock %}