mirror of
https://codeberg.org/catask-org/catask.git
synced 2025-04-19 13:23:41 -05:00
emoji picker + textarea footer for 'ask a question'
This commit is contained in:
parent
cadce98fc2
commit
f0e302b58a
2 changed files with 152 additions and 26 deletions
|
@ -24,6 +24,133 @@
|
|||
{% endblock %}
|
||||
{% block scripts %}
|
||||
<script src="{{ url_for('static', filename='js/toastify.min.js') }}"></script>
|
||||
<script src="{{ url_for('static', filename='js/emoji-mart.js') }}"></script>
|
||||
<script>
|
||||
{% if not cfg.lockInbox %}
|
||||
const input = document.getElementById('question');
|
||||
const charCount = document.getElementById('charCount');
|
||||
function updateCharCount() {
|
||||
const maxLength = input.getAttribute('maxlength');
|
||||
const currentLength = input.value.length;
|
||||
const remaining = maxLength - currentLength;
|
||||
charCount.textContent = remaining;
|
||||
if (remaining <= 50) {
|
||||
charCount.classList.add('text-warning');
|
||||
} else {
|
||||
charCount.classList.remove('text-warning');
|
||||
}
|
||||
if (remaining <= 10) {
|
||||
charCount.classList.add('text-danger');
|
||||
charCount.classList.remove('text-warning');
|
||||
} else {
|
||||
charCount.classList.remove('text-danger');
|
||||
}
|
||||
}
|
||||
input.addEventListener('input', updateCharCount);
|
||||
document.getElementById('question-form').reset();
|
||||
{% endif %}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", (event) => {
|
||||
const emoji_picker = document.querySelector('em-emoji-picker');
|
||||
const root_ = emoji_picker.shadowRoot;
|
||||
const sheet = new CSSStyleSheet();
|
||||
sheet.replaceSync(`
|
||||
/* custom css start */
|
||||
:host {
|
||||
--font-family: var(--bs-font-sans-serif) !important;
|
||||
--border-radius: var(--bs-border-radius) !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
#nav button[aria-selected] {
|
||||
color: var(--bs-primary) !important;
|
||||
}
|
||||
#nav .bar {
|
||||
background-color: var(--bs-primary) !important;
|
||||
}
|
||||
.search .icon {
|
||||
color: var(--bs-tertiary-color) !important;
|
||||
}
|
||||
.category button .background {
|
||||
background-color: var(--bs-basic-btn-hover-bg-strong);
|
||||
}
|
||||
:host, #root, input, button {
|
||||
color: var(--bs-body-color);
|
||||
}
|
||||
#root {
|
||||
--color-a: var(--bs-body-color) !important;
|
||||
--color-b: var(--bs-secondary-color) !important;
|
||||
--color-c: var(--bs-tertiary-color) !important;
|
||||
}
|
||||
#preview .emoji-mart-emoji {
|
||||
font-size: 16px;
|
||||
}
|
||||
[data-theme="dark"] {
|
||||
--em-rgb-background: !important;
|
||||
}
|
||||
.search input[type="search"] {
|
||||
border: 1px solid transparent !important;
|
||||
background-color: var(--bs-body-bg) !important;
|
||||
}
|
||||
.search input[type="search"]:focus {
|
||||
box-shadow: 0 0 0 .25rem color-mix(in srgb, var(--bs-primary) 25%, transparent) !important;
|
||||
border-color: color-mix(in srgb, var(--bs-primary) 80%, transparent) !important;
|
||||
outline: 0;
|
||||
}
|
||||
.category:first-child {
|
||||
margin-top: 1em;
|
||||
}
|
||||
/* custom css end */
|
||||
`);
|
||||
emoji_picker.shadowRoot.adoptedStyleSheets = [...root_.adoptedStyleSheets, sheet];
|
||||
});
|
||||
|
||||
const question_textarea = document.getElementById('question');
|
||||
function log_(a) {
|
||||
if (question_textarea.value != "") {
|
||||
question_textarea.value = a.native ? question_textarea.value + " " + a.native : question_textarea.value + " " + a.shortcodes;
|
||||
} else {
|
||||
question_textarea.value = a.native ? a.native : a.shortcodes;
|
||||
}
|
||||
updateCharCount();
|
||||
}
|
||||
const pickerOptions = {
|
||||
// document.getElementById('emoji-picker')
|
||||
onEmojiSelect: log_,
|
||||
parent: document.getElementById('emoji-picker'),
|
||||
custom: [
|
||||
{
|
||||
emojis: [
|
||||
{% for emoji in emojis %}
|
||||
{
|
||||
id: "{{ emoji.name }}",
|
||||
name: "{{ emoji.name }}",
|
||||
keywords: ["{{ emoji.name }}"],
|
||||
skins: [{ src: "{{ emoji.image }}" }],
|
||||
},
|
||||
{% endfor %}
|
||||
],
|
||||
},
|
||||
{% for pack in packs %}
|
||||
{
|
||||
id: "{{ pack.name }}",
|
||||
name: "{{ pack.name }}",
|
||||
emojis: [
|
||||
{% for emoji in pack.emojis %}
|
||||
{
|
||||
id: "{{ emoji.name }}",
|
||||
name: "{{ emoji.name }}",
|
||||
keywords: ["{{ emoji.name }}"],
|
||||
skins: [{ src: "/{{ pack.relative_path }}/{{ emoji.file_name }}" }],
|
||||
},
|
||||
{% endfor %}
|
||||
],
|
||||
},
|
||||
{% endfor %}
|
||||
]
|
||||
}
|
||||
const picker = new EmojiMart.Picker(pickerOptions)
|
||||
|
||||
</script>
|
||||
<script>
|
||||
// fix handling checkboxes
|
||||
document.querySelectorAll('.form-check-input').forEach(function(checkbox) {
|
||||
|
@ -132,30 +259,6 @@
|
|||
}).showToast();
|
||||
};
|
||||
|
||||
{% if not cfg.lockInbox %}
|
||||
const input = document.getElementById('question');
|
||||
const charCount = document.getElementById('charCount');
|
||||
function updateCharCount() {
|
||||
const maxLength = input.getAttribute('maxlength');
|
||||
const currentLength = input.value.length;
|
||||
const remaining = maxLength - currentLength;
|
||||
charCount.textContent = remaining;
|
||||
if (remaining <= 50) {
|
||||
charCount.classList.add('text-warning');
|
||||
} else {
|
||||
charCount.classList.remove('text-warning');
|
||||
}
|
||||
if (remaining <= 10) {
|
||||
charCount.classList.add('text-danger');
|
||||
charCount.classList.remove('text-warning');
|
||||
} else {
|
||||
charCount.classList.remove('text-danger');
|
||||
}
|
||||
}
|
||||
input.addEventListener('input', updateCharCount);
|
||||
document.getElementById('question-form').reset();
|
||||
{% endif %}
|
||||
|
||||
function shareOnFediverse(questionId, contentToShare) {
|
||||
const instanceDomain = document.getElementById(`fediInstance`).value.trim();
|
||||
const shareUrl = `https://${instanceDomain}/share?text=${contentToShare}`;
|
||||
|
@ -163,8 +266,11 @@
|
|||
window.open(shareUrl, '_blank');
|
||||
}
|
||||
|
||||
const tooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]');
|
||||
const tooltipList = [...tooltipTriggerList].map(tooltipTriggerEl => new bootstrap.Tooltip(tooltipTriggerEl));
|
||||
function initTooltips() {
|
||||
const tooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]');
|
||||
const tooltipList = [...tooltipTriggerList].map(tooltipTriggerEl => new bootstrap.Tooltip(tooltipTriggerEl));
|
||||
}
|
||||
initTooltips();
|
||||
|
||||
document.addEventListener('htmx:afterRequest', function(event) {
|
||||
const jsonResponse = event.detail.xhr.response;
|
||||
|
|
20
templates/snippets/q-input-footer.html
Normal file
20
templates/snippets/q-input-footer.html
Normal file
|
@ -0,0 +1,20 @@
|
|||
<div class="rounded-bottom border border-top-0 p-2 d-flex align-items-center justify-content-between" style="background-color: var(--bs-body-bg);">
|
||||
<div class="d-flex align-items-center gap-2">
|
||||
<button class="ms-1 btn btn-secondary" type="button" title="{{ _('Content warning') }}" data-bs-toggle="collapse" data-bs-target="{% if customCwTarget %}{{ customCwTarget}}{% else %}#cw-collapse{% endif %}" aria-expanded="false" aria-controls="cw-collapse">
|
||||
<i class="bi bi-exclamation-triangle"></i>
|
||||
</button>
|
||||
{% if not noEmojiPicker %}
|
||||
<div class="dropdown">
|
||||
<button class="btn btn-secondary dropdown-toggle no-arrow" type="button" data-bs-toggle="dropdown" data-bs-auto-close="outside" aria-expanded="false" title="{{ _('Add emoji') }}">
|
||||
<i class="bi bi-emoji-smile"></i>
|
||||
</button>
|
||||
<div class="dropdown-menu p-0">
|
||||
<div id="{% if customEmojiPickerId %}{{ customEmojiPickerId }}{% else %}emoji-picker{% endif %}" class="emoji-picker"></div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if includeCharLimit %}
|
||||
<span id="charCount" class="small" title="{{ _('Character limit') }}">{{ cfg.charLimit }}</span>
|
||||
{% endif %}
|
||||
</div>
|
Loading…
Add table
Reference in a new issue