feat(requests): don't spam requests, fixed results dropdown, don't request if there is no url

This commit is contained in:
Benjamin Wegener
2021-10-23 12:43:53 +02:00
parent b34642cd5e
commit 27e267f4ee
2 changed files with 102 additions and 47 deletions

View File

@@ -66,7 +66,6 @@
flex: 1; flex: 1;
background: white; background: white;
padding: $padding; padding: $padding;
overflow-x: auto;
white-space: nowrap; white-space: nowrap;
border: $border-default-transparent; border: $border-default-transparent;
border-radius: $border-radius * .8; border-radius: $border-radius * .8;
@@ -116,7 +115,16 @@
} }
&__value { &__value {
@extend .simplecomplete__input-field; border: $border-default-transparent;
border-radius: $border-radius * .8;
background: white;
flex: 1;
flex-flow: row wrap;
white-space: normal;
margin: .125em;
padding: 0;
padding-bottom: $spacer * .25;
outline: none;
&:not(.hide) { &:not(.hide) {
& ~ .simplecomplete__input { & ~ .simplecomplete__input {
display: none; display: none;
@@ -136,13 +144,7 @@
background: $gray; background: $gray;
color: $black; color: $black;
&:first-child { margin: $spacer * .25 $spacer * .25 0;
margin-left: -.25em;
}
&:last-child {
margin-right: -.25em;
}
} }
> .empty-item { > .empty-item {
@@ -154,15 +156,28 @@
&.is-empty { &.is-empty {
color: $text-secondary; color: $text-secondary;
} }
@media screen and (max-width: 992px) {
border-radius: 0;
}
}
&:not(.is-select) {
.simplecomplete__value.is-empty {
padding: $spacer * .75 $spacer * .5;
}
} }
&.is-multiple, &.is-blankable { &.is-multiple, &.is-blankable {
.simplecomplete__value > .selected-option { .simplecomplete__value {
&:after { position: relative;
content: "\00D7"; > .selected-option {
display: inline; &:after {
margin-left: .25em; content: "\00D7";
color: darken($text-secondary, 20); display: inline;
margin-left: .25em;
color: darken($text-secondary, 20);
}
} }
} }
@@ -172,6 +187,7 @@
} }
&__results { &__results {
display: none;
position: absolute; position: absolute;
top: 100%; top: 100%;
left: 0; left: 0;
@@ -286,6 +302,24 @@
display: none; display: none;
} }
&.is-select:not(.active) {
display: flex;
flex-flow: row nowrap;
align-items: center;
&:after {
content: "";
display: inline-block;
border: solid .25em $black;
border-top-color: transparent;
border-right-color: transparent;
transform: translateY(-40%) rotate(-45deg);
width: 0;
height: 0;
margin: 0 1em;
}
}
&.is-blankable:not(.active) { &.is-blankable:not(.active) {
.simplecomplete__value > .selected-option { .simplecomplete__value > .selected-option {
&:after { &:after {
@@ -302,7 +336,7 @@
&.active.is-select, &:not(.is-select) { &.active.is-select, &:not(.is-select) {
.simplecomplete__input-field { .simplecomplete__input-field {
padding: $spacer * 1.05; padding: $spacer * .85;
} }
} }
@@ -379,9 +413,9 @@
} }
} }
&:not(.has-results) { &.active {
.simplecomplete__results { .simplecomplete__results {
display: none; display: block;
} }
} }
} }

View File

@@ -148,8 +148,9 @@ export default class SimpleComplete {
} }
onInput (e) { onInput (e) {
if (this.launchedRequest) { if (this.launchedRequest !== null) {
window.clearTimeout(this.launchedRequest) window.clearTimeout(this.launchedRequest)
this.launchedRequest = null
} }
switch (e.keyCode) { switch (e.keyCode) {
@@ -161,18 +162,21 @@ export default class SimpleComplete {
} }
this.query = e.target.textContent.trim() this.query = e.target.textContent.trim()
this.launchedRequest = window.setTimeout(this.onSend.bind(this), this.options.delay || 300) if (this.options.url) {
this.launchedRequest = window.setTimeout(this.onSend.bind(this), this.options.delay || 300)
console.log(this.options.url)
}
this.onResults() this.onResults()
} }
finishRequest (xhr) { finishRequest (xhr) {
this.wrapper.classList.remove('is-busy') this.wrapper.classList.remove('is-busy')
this.queued = false
} }
sendRequest (_cb = null) { sendRequest () {
let headers = { let headers = {
Accept: 'application/json', Accept: 'application/json',
'Cache-Control': 'no-cache',
'X-Requested-With': 'XMLHttpRequest', 'X-Requested-With': 'XMLHttpRequest',
...(this.options.headers || {}) ...(this.options.headers || {})
} }
@@ -252,14 +256,17 @@ export default class SimpleComplete {
if (!(200 <= xhr.status && xhr.status < 300)) { if (!(200 <= xhr.status && xhr.status < 300)) {
this.onError('simplecomplete.errors.xhr_wrong_status') this.onError('simplecomplete.errors.xhr_wrong_status')
} else { } else {
let data =
this.options.onResponse (response, xhr) this.options.onResponse (response, xhr)
this.onResults(response.data || response) this.onResults(response.data || response)
} }
} }
onSend (e = null) { onSend (e = null) {
if(this.launchedRequest !== null) {
window.clearTimeout(this.launchedRequest)
this.launchedRequest = null
}
if (!this.query || (this.options.minLength > 0 && this.query.length < this.options.minLength)) { if (!this.query || (this.options.minLength > 0 && this.query.length < this.options.minLength)) {
this.onError('simplecomplete.errors.min-length') this.onError('simplecomplete.errors.min-length')
} else { } else {
@@ -267,18 +274,7 @@ export default class SimpleComplete {
this.queued = true this.queued = true
} else if (this.options.url) { } else if (this.options.url) {
this.wrapper.classList.add('is-busy') this.wrapper.classList.add('is-busy')
this.sendRequest()
this.sendRequest((xhr) => {
console.log('DONE', xhr)
})
/*window.setTimeout(() => {
this.wrapper.classList.remove('is-busy')
if(this.queued) {
this.queued = false
this.onSend ()
}
}, 3000)*/
} }
} }
} }
@@ -335,7 +331,7 @@ export default class SimpleComplete {
updateLabel () { updateLabel () {
this.currentValue.classList.remove('is-empty') this.currentValue.classList.remove('is-empty')
this.currentValue.innerHTML = '' this.currentValue.innerHTML = ''
if (this.isMultiple() || this.isSelectElement()) { if (this.isMultiple() && this.isSelectElement()) {
let _opts = Array.from(this.element.selectedOptions) let _opts = Array.from(this.element.selectedOptions)
for (let _key in _opts) { for (let _key in _opts) {
let o = _opts[_key] let o = _opts[_key]
@@ -360,21 +356,32 @@ export default class SimpleComplete {
} }
if(!this.currentValue.childNodes.length) { if(!this.currentValue.childNodes.length) {
let placeholder = this.element.value || this.element.getAttribute('placeholder') || this.element.dataset.placeholder || this.options.placeholder || 'Search' if (this.element.value) {
if (this.isSelectElement()) {
let badge = SimpleComplete.createElement('SPAN', { let badge = SimpleComplete.createElement('SPAN', {
classes: 'empty-item' classes: 'selected-option'
}) })
let label = this.results.filter(item => item.value == this.element.value).map(item => item.label || item.value).shift()
badge.textContent = placeholder badge.textContent = label || this.element.value
this.currentValue.appendChild(badge) this.currentValue.appendChild(badge)
} else { } else {
this.currentValue.textContent = placeholder let placeholder = this.element.getAttribute('placeholder') || this.element.dataset.placeholder || this.options.placeholder || 'Search'
} if (this.isSelectElement()) {
let badge = SimpleComplete.createElement('SPAN', {
classes: 'empty-item'
})
if (placeholder == this.options.placeholder) { badge.textContent = placeholder
this.currentValue.classList.add('is-empty')
this.currentValue.appendChild(badge)
} else {
this.currentValue.textContent = placeholder
}
if (placeholder == this.options.placeholder) {
this.currentValue.classList.add('is-empty')
}
} }
} }
} }
@@ -484,14 +491,14 @@ export default class SimpleComplete {
if(this.results && this.resultsList) { if(this.results && this.resultsList) {
this.resultsList.innerHTML = '' this.resultsList.innerHTML = ''
if (this.isSelectElement ()) { if (this.isSelectElement ()) {
[...this.element.options].forEach(option => { [...this.element.options].filter(this.filterResults.bind(this)).forEach(option => {
this.resultsList.appendChild(this.renderOption({ this.resultsList.appendChild(this.renderOption({
value: option.value, value: option.value,
label: option.textContent label: option.textContent
})) }))
}) })
} else { } else {
this.results.forEach( res => this.resultsList.appendChild(this.renderOption(res)) ) this.results.filter(this.filterResults.bind(this)).forEach( res => this.resultsList.appendChild(this.renderOption(res)) )
} }
if (!this.resultsList.childNodes.length) { if (!this.resultsList.childNodes.length) {
@@ -502,6 +509,9 @@ export default class SimpleComplete {
emptyNode.textContent = this.options.emptyText || 'No results' emptyNode.textContent = this.options.emptyText || 'No results'
this.resultsList.appendChild(emptyNode) this.resultsList.appendChild(emptyNode)
this.wrapper.classList.add('has-results')
} else {
this.wrapper.classList.remove('has-results')
} }
} }
} catch(err) { } catch(err) {
@@ -509,6 +519,17 @@ export default class SimpleComplete {
} }
} }
filterResults (option) {
if(!this.query) {
return true
}
let regexp = new RegExp(this.query,'gi')
let label = option.label || option.textContent
let check = label.matchAll(regexp)
return [...check].length > 0
}
isSelected (_val) { isSelected (_val) {
let opts = Array.from(this.element.selectedOptions || []) let opts = Array.from(this.element.selectedOptions || [])
for (let _index = 0; _index < opts.length; _index++) { for (let _index = 0; _index < opts.length; _index++) {