Universal search input
This commit is contained in:
parent
3303d157fa
commit
d703ddffdf
@ -6,6 +6,7 @@ import "./shared/rich-text-editor.js";
|
||||
import "./shared/form-navigation.js";
|
||||
import "./shared/image-popup.js";
|
||||
import "./shared/facebook-button.js";
|
||||
import "./shared/search-input.js";
|
||||
import "./shared/nav/ow-nav.js";
|
||||
import "./shared/nav/ow-path.js";
|
||||
import "./shared/price/price-input.js";
|
||||
|
@ -1,16 +1,13 @@
|
||||
import { Component } from "../shared";
|
||||
import { Component } from "../shared.js";
|
||||
import "../shared/search-input.js";
|
||||
|
||||
customElements.define('local-business-list', class extends Component {
|
||||
static get observedAttributes() {
|
||||
return ['filter']
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super(`
|
||||
<style>
|
||||
:host { display: block; }
|
||||
* { font-family: 'Cardo', sans-serif; }
|
||||
::slotted(local-business[local-business-visible="invisible"]) {
|
||||
::slotted([search-visible='invisible']) {
|
||||
display: none;
|
||||
}
|
||||
input {
|
||||
@ -38,62 +35,12 @@ customElements.define('local-business-list', class extends Component {
|
||||
</style>
|
||||
<article>
|
||||
<section>
|
||||
<input type="text" id="filter" placeholder="Znajdź (wyrażenia regularne są wspierane)" />
|
||||
<search-input target="local-business"></search-input>
|
||||
</section>
|
||||
<section id="items">
|
||||
<slot name="business"></slot>
|
||||
</section>
|
||||
</article>
|
||||
`);
|
||||
{
|
||||
const filter = this.shadowRoot.querySelector('#filter');
|
||||
let t = null;
|
||||
filter.addEventListener('change', ev => {
|
||||
ev.stopPropagation();
|
||||
this.filter = ev.target.value;
|
||||
});
|
||||
filter.addEventListener('keyup', ev => {
|
||||
ev.stopPropagation();
|
||||
const value = ev.target.value;
|
||||
|
||||
if (t) clearTimeout(t);
|
||||
t = setTimeout(() => {
|
||||
this.filter = value;
|
||||
t = null;
|
||||
}, 1000 / 3);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
this.filter = this.getAttribute('filter');
|
||||
}
|
||||
|
||||
attributeChangedCallback(name, oldV, newV) {
|
||||
super.attributeChangedCallback(name, oldV, newV);
|
||||
}
|
||||
|
||||
get filter() {
|
||||
return this.getAttribute('filter');
|
||||
}
|
||||
|
||||
set filter(value) {
|
||||
if (!value || value === '') {
|
||||
this.removeAttribute('filter');
|
||||
for (const el of this.querySelectorAll('local-business')) {
|
||||
el.removeAttribute('local-business-visible');
|
||||
}
|
||||
} else {
|
||||
this.setAttribute('filter', value);
|
||||
value = value.split(' ').filter(s => s && s.length).map(s => `(${s})`).join('|');
|
||||
const businesses = this.querySelectorAll('local-business');
|
||||
for (const el of businesses) {
|
||||
if (el.matches(new RegExp(value, 'ig'))) {
|
||||
el.setAttribute('local-business-visible', 'visible');
|
||||
} else {
|
||||
el.setAttribute('local-business-visible', 'invisible');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { Component, BUTTON_STYLE } from "../shared";
|
||||
import { Component, BUTTON_STYLE } from "../shared.js";
|
||||
import "../shared/search-input.js";
|
||||
|
||||
customElements.define('marketplace-offers', class extends Component {
|
||||
static get observedAttributes() {
|
||||
@ -28,6 +29,9 @@ customElements.define('marketplace-offers', class extends Component {
|
||||
::slotted(marketplace-offer), ::slotted(user-edit-offer) {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
::slotted([search-visible='invisible']) {
|
||||
display: none;
|
||||
}
|
||||
@media only screen and (min-device-width: 1000px) {
|
||||
#offers {
|
||||
display: flex;
|
||||
@ -47,6 +51,9 @@ customElements.define('marketplace-offers', class extends Component {
|
||||
<button id="publish" class="btn">Dodaj ogłoszenie</button>
|
||||
</section>
|
||||
<section><slot></slot></section>
|
||||
<section>
|
||||
<search-input target="user-edit-offer, marketplace-offer"></search-input>
|
||||
</section>
|
||||
<section id="offers">
|
||||
<slot name="offer"></slot>
|
||||
</section>
|
||||
|
@ -147,4 +147,8 @@ customElements.define('user-edit-offer', class extends Component {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
matches(regex) {
|
||||
return !!this.description.match(regex)
|
||||
}
|
||||
});
|
||||
|
101
client/src/shared/search-input.js
Normal file
101
client/src/shared/search-input.js
Normal file
@ -0,0 +1,101 @@
|
||||
import { Component } from "../shared.js";
|
||||
|
||||
customElements.define('search-input', class extends Component {
|
||||
#host;
|
||||
|
||||
static get observedAttributes() {
|
||||
return ['filter', 'target']
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super(`
|
||||
<style>
|
||||
:host { display: block; }
|
||||
input {
|
||||
font-size: 1rem;
|
||||
line-height: 2.6em;
|
||||
height: 2.6em;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
border:none;
|
||||
outline:none;
|
||||
display: block;
|
||||
background: transparent;
|
||||
border-bottom: 1px solid #ccc;
|
||||
text-indent: 20px;
|
||||
}
|
||||
</style>
|
||||
<section>
|
||||
<input type="text" id="filter" placeholder="Znajdź (wyrażenia regularne są wspierane)" />
|
||||
</section>
|
||||
`);
|
||||
const filter = this.shadowRoot.querySelector('#filter');
|
||||
let t = null;
|
||||
filter.addEventListener('change', ev => {
|
||||
ev.stopPropagation();
|
||||
this.filter = ev.target.value;
|
||||
});
|
||||
filter.addEventListener('keyup', ev => {
|
||||
ev.stopPropagation();
|
||||
const value = ev.target.value;
|
||||
|
||||
if (t) clearTimeout(t);
|
||||
t = setTimeout(() => {
|
||||
this.filter = value;
|
||||
t = null;
|
||||
}, 1000 / 3);
|
||||
});
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
let node = this;
|
||||
while (node) {
|
||||
console.warn(node)
|
||||
if (node == null) return console.warn('no parent node', node);
|
||||
if (node instanceof ShadowRoot) {
|
||||
console.warn('node is shadow')
|
||||
this.#host = node.host;
|
||||
break;
|
||||
}
|
||||
node = node.parentNode;
|
||||
}
|
||||
}
|
||||
|
||||
get target() {
|
||||
return this.getAttribute('target');
|
||||
}
|
||||
|
||||
set target(tagName) {
|
||||
this.setAttribute('target', tagName);
|
||||
}
|
||||
|
||||
get filter() {
|
||||
return this.getAttribute('filter');
|
||||
}
|
||||
|
||||
set filter(value) {
|
||||
console.warn(this.#host, value);
|
||||
if (!this.#host) return;
|
||||
const v = this.#host.querySelectorAll(this.target);
|
||||
|
||||
if (!value || value === '') {
|
||||
this.removeAttribute('filter');
|
||||
for (const el of v) {
|
||||
el.removeAttribute('search-visible');
|
||||
}
|
||||
} else {
|
||||
this.setAttribute('filter', value);
|
||||
value = value.split(' ').filter(s => s && s.length).map(s => `(${ s })`).join('|');
|
||||
for (const el of v) {
|
||||
if (!el.matches) continue;
|
||||
if (el.matches(new RegExp(value, 'ig'))) {
|
||||
el.setAttribute('search-visible', 'visible');
|
||||
} else {
|
||||
el.setAttribute('search-visible', 'invisible');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
Loading…
Reference in New Issue
Block a user