Add 'insert' view for inserting ratings on paper
parent
bb7e7b5089
commit
d0694ed38a
@ -1,5 +1,11 @@
|
|||||||
from django import forms
|
from django import forms
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
|
class InsertForm(forms.Form):
|
||||||
|
name = forms.CharField()
|
||||||
|
rating = forms.ChoiceField(choices=settings.RATING_CHOICES, required=False, widget=forms.RadioSelect)
|
||||||
|
|
||||||
|
InsertFormSet = forms.formset_factory(InsertForm)
|
||||||
|
|
||||||
class RateArtistForm(forms.Form):
|
class RateArtistForm(forms.Form):
|
||||||
rating = forms.ChoiceField(choices=settings.RATING_CHOICES, required=False, widget=forms.RadioSelect)
|
rating = forms.ChoiceField(choices=settings.RATING_CHOICES, required=False, widget=forms.RadioSelect)
|
||||||
|
@ -0,0 +1,126 @@
|
|||||||
|
{% extends "core/base.html" %}
|
||||||
|
|
||||||
|
{% block title %}A/D-Wandler{% endblock %}
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
<form action="" method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
|
||||||
|
{{ formset.management_form }}
|
||||||
|
|
||||||
|
{% for form in formset %}
|
||||||
|
<div class="row">
|
||||||
|
{{ form.name }}
|
||||||
|
|
||||||
|
<div class="rating-container">
|
||||||
|
<div class="rating" style="--num-choices: {{ form.rating | length }}">
|
||||||
|
{% for radio in form.rating %}
|
||||||
|
{{ radio.tag }}
|
||||||
|
<label class="rating-point" for="{{ radio.id_for_label }}"></label>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button class="reset" type="button">Zurücksetzen</button>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
<button id="add" type="button">+</button>
|
||||||
|
|
||||||
|
<button type="submit">Speichern</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{{ playlist | json_script:"playlist" }}
|
||||||
|
<script>
|
||||||
|
const playlist = JSON.parse(document.getElementById('playlist').textContent);
|
||||||
|
|
||||||
|
const findBestMatch = value => playlist.find(name => name.toLowerCase().includes(value) || value.includes(name.toLowerCase())) || '';
|
||||||
|
|
||||||
|
const registerEvents = row => {
|
||||||
|
const input = row.querySelector('input[name$=name]');
|
||||||
|
input.addEventListener('input', () => {
|
||||||
|
const value = (input.dataset.value || '') + input.value.toLowerCase();
|
||||||
|
input.dataset.value = value;
|
||||||
|
|
||||||
|
const bestMatch = findBestMatch(value);
|
||||||
|
input.placeholder = bestMatch;
|
||||||
|
input.value = '';
|
||||||
|
input.dataset.bestMatch = bestMatch;
|
||||||
|
});
|
||||||
|
input.addEventListener('keydown', event => {
|
||||||
|
if (event.key === 'Backspace') {
|
||||||
|
if (input.value !== '') {
|
||||||
|
input.value = '';
|
||||||
|
} else {
|
||||||
|
const value = (input.dataset.value || '').slice(0, -1);
|
||||||
|
input.dataset.value = value;
|
||||||
|
|
||||||
|
if (value === '') {
|
||||||
|
input.placeholder = '';
|
||||||
|
input.dataset.bestMatch = '';
|
||||||
|
} else {
|
||||||
|
const bestMatch = findBestMatch(value);
|
||||||
|
input.placeholder = bestMatch;
|
||||||
|
input.dataset.bestMatch = bestMatch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
event.preventDefault();
|
||||||
|
} else if (event.key === 'Tab') {
|
||||||
|
input.placeholder = '';
|
||||||
|
input.value = input.dataset.bestMatch || '';
|
||||||
|
input.dataset.bestMatch = '';
|
||||||
|
input.dataset.value = '';
|
||||||
|
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
row.querySelector('.reset').addEventListener('click', event => {
|
||||||
|
event.target.parentElement.querySelectorAll('.rating-container > .rating > input').forEach(input => {
|
||||||
|
input.checked = false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
document.querySelectorAll('.row').forEach(registerEvents);
|
||||||
|
|
||||||
|
const totalForms = document.getElementById('id_form-TOTAL_FORMS');
|
||||||
|
|
||||||
|
let numForms = Number.parseInt(totalForms.value);
|
||||||
|
|
||||||
|
const replace = value => value.replace(/form-\d+-(.+)/, `form-${numForms}-$1`);
|
||||||
|
|
||||||
|
const addBtn = document.getElementById('add');
|
||||||
|
addBtn.addEventListener('click', () => {
|
||||||
|
const row = document.querySelector('.row').cloneNode(true);
|
||||||
|
|
||||||
|
row.querySelectorAll('[name^=form-]').forEach(input => {
|
||||||
|
const label = row.querySelector(`label[for=${input.id}]`);
|
||||||
|
if (label) {
|
||||||
|
label.htmlFor = replace(label.htmlFor);
|
||||||
|
}
|
||||||
|
|
||||||
|
input.id = replace(input.id);
|
||||||
|
input.name = replace(input.name);
|
||||||
|
});
|
||||||
|
|
||||||
|
const input = row.querySelector('input[name$=name]');
|
||||||
|
input.placeholder = '';
|
||||||
|
input.value = '';
|
||||||
|
input.dataset.bestMatch = '';
|
||||||
|
input.dataset.value = '';
|
||||||
|
|
||||||
|
row.querySelectorAll('.rating-container > .rating > input').forEach(input => {
|
||||||
|
input.checked = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
registerEvents(row);
|
||||||
|
|
||||||
|
addBtn.before(row);
|
||||||
|
|
||||||
|
numForms += 1;
|
||||||
|
totalForms.value = numForms;
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
||||||
|
|
Loading…
Reference in New Issue