Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion app/eventyay/base/configurations/default_setting.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
pgettext_lazy,
)
from i18nfield.forms import I18nFormField, I18nTextarea, I18nTextInput
from eventyay.base.forms import I18nAutoExpandingTextarea
from i18nfield.strings import LazyI18nString
from rest_framework import serializers

Expand Down Expand Up @@ -2230,7 +2231,7 @@ def primary_font_kwargs():
'type': LazyI18nString,
'serializer_class': I18nField,
'form_class': I18nFormField,
'form_kwargs': dict(label=_('Frontpage text'), widget=I18nTextarea),
'form_kwargs': dict(label=_('Frontpage text'), widget=I18nAutoExpandingTextarea),
},
'event_info_text': {
'default': '',
Expand Down
79 changes: 79 additions & 0 deletions app/eventyay/base/forms/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,85 @@ def format_output(self, rendered_widgets, id_) -> str:
return super().format_output(rendered_widgets, id_)


class I18nAutoExpandingTextarea(i18nfield.forms.I18nTextarea):
"""
An auto-expanding textarea widget for internationalized text fields.
Automatically adjusts height based on content with a maximum height limit.
"""

def __init__(self, attrs=None, **kwargs):
default_attrs = {
'class': 'form-control auto-expanding-textarea',
'data-auto-expand': 'true',
'style': 'min-height: 80px; max-height: 300px; overflow-y: hidden; resize: vertical; transition: height 0.2s ease-in-out;'
}
if attrs:
if 'class' in attrs:
default_attrs['class'] = default_attrs['class'] + ' ' + attrs['class']
default_attrs |= attrs
super().__init__(attrs=default_attrs, **kwargs)

def render(self, name, value, attrs=None, renderer=None):
html = super().render(name, value, attrs, renderer)

js_code = """
<script>
(function() {
if (window.autoExpandTextareaInitialized) {
return;
}
window.autoExpandTextareaInitialized = true;

function autoExpandTextarea(textarea) {
if (!textarea || textarea.hasAttribute('data-auto-expand-init')) return;
textarea.setAttribute('data-auto-expand-init', 'true');

function adjustHeight() {
textarea.style.height = 'auto';
var scrollHeight = textarea.scrollHeight;
var minHeight = 80;
var maxHeight = 300;
var newHeight = Math.max(minHeight, Math.min(scrollHeight, maxHeight));
textarea.style.height = newHeight + 'px';
textarea.style.overflowY = scrollHeight > maxHeight ? 'auto' : 'hidden';
}

textarea.addEventListener('input', adjustHeight);
textarea.addEventListener('paste', function() { setTimeout(adjustHeight, 10); });
adjustHeight();
}

function initializeAutoExpandTextareas() {
document.querySelectorAll('textarea[data-auto-expand="true"]').forEach(autoExpandTextarea);
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initializeAutoExpandTextareas);
} else {
initializeAutoExpandTextareas();
}

// Handle dynamically added textareas (for i18n tabs)
if (typeof MutationObserver !== 'undefined') {
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
mutation.addedNodes.forEach(function(node) {
if (node.nodeType === 1) {
var textareas = node.querySelectorAll ?
node.querySelectorAll('textarea[data-auto-expand="true"]') : [];
textareas.forEach(autoExpandTextarea);
}
});
});
});
observer.observe(document.body, { childList: true, subtree: true });
}
})();
</script>
"""

return html + js_code


class I18nURLFormField(i18nfield.forms.I18nFormField):
"""
Custom form field to handle internationalized URL inputs. It extends the I18nFormField
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{% extends "eventyay_common/event/settings_base.html" %}
{% load static %}
{% load i18n %}
{% load bootstrap3 %}
{% load static %}
Expand Down