autocomplete & form reset

This commit is contained in:
bkfox 2022-03-20 11:59:51 +01:00
parent 17512d14b8
commit 65a6c9f90c
3 changed files with 23 additions and 18 deletions

View File

@ -15,7 +15,7 @@
\***********************************************************************************************************************************************************************************************/ \***********************************************************************************************************************************************************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
eval("__webpack_require__.r(__webpack_exports__);\n// import debounce from 'lodash/debounce'\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n props: {\n url: String,\n model: Function,\n placeholder: String,\n name: String,\n labelField: String,\n valueField: {\n type: String,\n default: null\n },\n count: {\n type: Number,\n count: 10\n }\n },\n\n data() {\n return {\n value: '',\n items: [],\n selectedIndex: -1,\n cursor: -1,\n isFetching: false\n };\n },\n\n computed: {\n selected() {\n let index = this.selectedIndex;\n if (index < 0) return null;\n index = Math.min(index, this.items.length - 1);\n return this.items[index];\n },\n\n selectedValue() {\n const sel = this.selected;\n return sel && (this.valueField ? sel.data[this.valueField] : sel.id);\n },\n\n selectedLabel() {\n const sel = this.selected;\n return sel && sel.data[this.labelField];\n },\n\n dropdownClass() {\n const active = this.cursor > -1 && this.items.length;\n return ['dropdown', active ? 'is-active' : ''];\n }\n\n },\n methods: {\n move(index = -1, relative = false) {\n if (relative) index += this.cursor;\n this.cursor = Math.max(-1, Math.min(index, this.items.length - 1));\n },\n\n select(index = -1, relative = false, active = null) {\n if (relative) index += this.selectedIndex;else if (index == this.selectedIndex) return;\n this.selectedIndex = Math.max(-1, Math.min(index, this.items.length - 1));\n\n if (index >= 0) {\n this.$refs.input.value = this.selectedLabel;\n this.$refs.input.focus();\n }\n\n if (this.selectedIndex < 0) this.$emit('unselect');else this.$emit('select', index, this.selected, this.selectedValue);\n if (active !== null) active && this.move(0) || this.move(-1);\n },\n\n onKeyPress: function (event) {\n switch (event.keyCode) {\n case 13:\n this.select(this.cursor, false, false);\n break;\n\n case 27:\n this.select();\n break;\n\n case 38:\n this.move(-1, true);\n break;\n\n case 40:\n this.move(1, true);\n break;\n\n default:\n return;\n }\n\n event.preventDefault();\n event.stopPropagation();\n },\n onKeyUp: function (event) {\n const value = event.target.value;\n if (value === this.value) return;\n this.value = value;\n if (!value) return this.selected && this.select(-1);\n this.fetch(value);\n },\n fetch: function (query) {\n if (!query || this.isFetching) return;\n this.isFetching = true;\n return this.model.fetch(this.url.replace('${query}', query), {\n many: true\n }).then(items => {\n this.items = items || [];\n this.isFetching = false;\n this.move(0);\n return items;\n }, data => {\n this.isFetching = false;\n Promise.reject(data);\n });\n }\n }\n});\n\n//# sourceURL=webpack://aircox-assets/./src/components/AAutocomplete.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use%5B0%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D"); eval("__webpack_require__.r(__webpack_exports__);\n// import debounce from 'lodash/debounce'\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n props: {\n url: String,\n model: Function,\n placeholder: String,\n name: String,\n labelField: String,\n valueField: {\n type: String,\n default: null\n },\n count: {\n type: Number,\n count: 10\n }\n },\n\n data() {\n return {\n value: '',\n items: [],\n selectedIndex: -1,\n cursor: -1,\n isFetching: false\n };\n },\n\n computed: {\n selected() {\n let index = this.selectedIndex;\n if (index < 0) return null;\n index = Math.min(index, this.items.length - 1);\n return this.items[index];\n },\n\n selectedValue() {\n const sel = this.selected;\n return sel && (this.valueField ? sel.data[this.valueField] : sel.id);\n },\n\n selectedLabel() {\n const sel = this.selected;\n return sel && sel.data[this.labelField];\n },\n\n dropdownClass() {\n const active = this.cursor > -1 && this.items.length;\n return ['dropdown', active ? 'is-active' : ''];\n }\n\n },\n methods: {\n move(index = -1, relative = false) {\n if (relative) index += this.cursor;\n this.cursor = Math.max(-1, Math.min(index, this.items.length - 1));\n },\n\n select(index = -1, relative = false, active = null) {\n if (relative) index += this.selectedIndex;else if (index == this.selectedIndex) return;\n this.selectedIndex = Math.max(-1, Math.min(index, this.items.length - 1));\n\n if (index >= 0) {\n this.$refs.input.value = this.selectedLabel;\n this.$refs.input.focus();\n }\n\n if (this.selectedIndex < 0) this.$emit('unselect');else this.$emit('select', index, this.selected, this.selectedValue);\n if (active !== null) active && this.move(0) || this.move(-1);\n },\n\n onKeyPress: function (event) {\n switch (event.keyCode) {\n case 13:\n this.select(this.cursor, false, false);\n break;\n\n case 27:\n this.select();\n break;\n\n case 38:\n this.move(-1, true);\n break;\n\n case 40:\n this.move(1, true);\n break;\n\n default:\n return;\n }\n\n event.preventDefault();\n event.stopPropagation();\n },\n onKeyUp: function (event) {\n const value = event.target.value;\n if (value === this.value) return;\n this.value = value;\n if (!value) return this.selected && this.select(-1);\n this.fetch(value);\n },\n fetch: function (query) {\n if (!query || this.isFetching) return;\n this.isFetching = true;\n return this.model.fetch(this.url.replace('${query}', query), {\n many: true\n }).then(items => {\n this.items = items || [];\n this.isFetching = false;\n this.move(0);\n return items;\n }, data => {\n this.isFetching = false;\n Promise.reject(data);\n });\n }\n },\n\n mounted() {\n const form = this.$el.closest('form');\n form.addEventListener('reset', () => {\n this.value = '';\n this.select(-1);\n });\n }\n\n});\n\n//# sourceURL=webpack://aircox-assets/./src/components/AAutocomplete.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use%5B0%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D");
/***/ }), /***/ }),

View File

@ -47,11 +47,11 @@
<div v-if="source.isQueue"> <div v-if="source.isQueue">
<hr> <hr>
<h6 class="title is-6 is-marginless">{% trans "Add sound" %}</h6> <h6 class="title is-6">{% trans "Add sound" %}</h6>
<form class="columns" @submit.prevent="source.push($event.target.elements['sound_id'].value)"> <form @submit.prevent="source.push($event.target.elements['sound_id'].value); $event.target.reset()">
<div class="column field is-small"> <div class="field is-grouped">
{# TODO: select station => change the shit #} {# TODO: select station => change the shit #}
<a-autocomplete class="is-fullwidth" <a-autocomplete class="control is-expanded"
url="{% url "aircox:sound-list" %}?station={{ station.pk }}&search=${query}" url="{% url "aircox:sound-list" %}?station={{ station.pk }}&search=${query}"
name="sound_id" :model="Sound" label-field="name" name="sound_id" :model="Sound" label-field="name"
placeholder="{% trans "Select a sound" %}"> placeholder="{% trans "Select a sound" %}">
@ -59,20 +59,20 @@
[[ item.data.name ]] [[ item.data.name ]]
<span class="is-size-7 is-italic has-text-info">[[ item.data.file ]]</span> <span class="is-size-7 is-italic has-text-info">[[ item.data.file ]]</span>
</template> </template>
</a-autocomplete> </a-autocomplete>
<p class="help"> <div class="control">
{% trans "Add a sound to the queue (queue may start playing)" %} <button type="submit" class="button is-primary">
</p> <span class="icon">
{# TODO: help text about how it works #} <span class="fas fa-plus"></span>
</div> </span>
<div class="column control is-one-fifth"> <span>{% trans "Add" %}</span>
<button type="submit" class="button is-primary"> </button>
<span class="icon"> </div>
<span class="fas fa-plus"></span>
</span>
<span>{% trans "Add" %}</span>
</button>
</div> </div>
<p class="help">
{% trans "Add a sound to the queue (queue may start playing)" %}
</p>
{# TODO: help text about how it works #}
</form> </form>
<div v-if="source.queue.length"> <div v-if="source.queue.length">

View File

@ -155,6 +155,11 @@ export default {
data => {this.isFetching = false; Promise.reject(data)}) data => {this.isFetching = false; Promise.reject(data)})
}, },
}, },
mounted() {
const form = this.$el.closest('form')
form.addEventListener('reset', () => { this.value=''; this.select(-1) })
}
} }
</script> </script>