{% comment %} TomSelect Token widget template. Renders a single text input + container element, then attaches the per-instance init script. Mirrors the inline-init pattern used by tomselect.html so HTMX swaps and dynamic re-rendering work the same way. Context Variables: - widget.name, widget.attrs, widget.value: standard Django widget context. - widget.composite_view_url: resolved URL for the CompositeAutocompleteView. - widget.token_config: dict with allow_free_text, max_query_length, max_tokens. - widget.css_framework: "default" | "bootstrap4" | "bootstrap5". Blocks: - block token_input: the underlying ; override to change the form field markup. - block token_init: the JS init call; override to wrap with custom logic. {% endcomment %} {% load i18n %} {% block token_input %} {% endblock token_input %}
{% block token_init %} (function () { var inputName = '{{ widget.name|escapejs }}'; function attach() { if (!window.djangoTomSelectToken || typeof window.djangoTomSelectToken.init !== 'function') { // Bundle not yet ready; retry on next tick. return setTimeout(attach, 0); } var escName = (window.CSS && window.CSS.escape) ? window.CSS.escape(inputName) : inputName; var roots = document.querySelectorAll('[data-django-tomselect-token][data-target-name="' + escName + '"]'); roots.forEach(function (root) { if (root.dataset.djangoTomselectTokenInitialized === '1') return; window.djangoTomSelectToken.init(root); root.dataset.djangoTomselectTokenInitialized = '1'; }); } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', attach); } else { attach(); } })(); {% endblock token_init %}