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/form-navigation.js";
|
||||||
import "./shared/image-popup.js";
|
import "./shared/image-popup.js";
|
||||||
import "./shared/facebook-button.js";
|
import "./shared/facebook-button.js";
|
||||||
|
import "./shared/search-input.js";
|
||||||
import "./shared/nav/ow-nav.js";
|
import "./shared/nav/ow-nav.js";
|
||||||
import "./shared/nav/ow-path.js";
|
import "./shared/nav/ow-path.js";
|
||||||
import "./shared/price/price-input.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 {
|
customElements.define('local-business-list', class extends Component {
|
||||||
static get observedAttributes() {
|
|
||||||
return ['filter']
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super(`
|
super(`
|
||||||
<style>
|
<style>
|
||||||
:host { display: block; }
|
:host { display: block; }
|
||||||
* { font-family: 'Cardo', sans-serif; }
|
* { font-family: 'Cardo', sans-serif; }
|
||||||
::slotted(local-business[local-business-visible="invisible"]) {
|
::slotted([search-visible='invisible']) {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
input {
|
input {
|
||||||
@ -38,62 +35,12 @@ customElements.define('local-business-list', class extends Component {
|
|||||||
</style>
|
</style>
|
||||||
<article>
|
<article>
|
||||||
<section>
|
<section>
|
||||||
<input type="text" id="filter" placeholder="Znajdź (wyrażenia regularne są wspierane)" />
|
<search-input target="local-business"></search-input>
|
||||||
</section>
|
</section>
|
||||||
<section id="items">
|
<section id="items">
|
||||||
<slot name="business"></slot>
|
<slot name="business"></slot>
|
||||||
</section>
|
</section>
|
||||||
</article>
|
</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 {
|
customElements.define('marketplace-offers', class extends Component {
|
||||||
static get observedAttributes() {
|
static get observedAttributes() {
|
||||||
@ -28,6 +29,9 @@ customElements.define('marketplace-offers', class extends Component {
|
|||||||
::slotted(marketplace-offer), ::slotted(user-edit-offer) {
|
::slotted(marketplace-offer), ::slotted(user-edit-offer) {
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
::slotted([search-visible='invisible']) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
@media only screen and (min-device-width: 1000px) {
|
@media only screen and (min-device-width: 1000px) {
|
||||||
#offers {
|
#offers {
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -47,6 +51,9 @@ customElements.define('marketplace-offers', class extends Component {
|
|||||||
<button id="publish" class="btn">Dodaj ogłoszenie</button>
|
<button id="publish" class="btn">Dodaj ogłoszenie</button>
|
||||||
</section>
|
</section>
|
||||||
<section><slot></slot></section>
|
<section><slot></slot></section>
|
||||||
|
<section>
|
||||||
|
<search-input target="user-edit-offer, marketplace-offer"></search-input>
|
||||||
|
</section>
|
||||||
<section id="offers">
|
<section id="offers">
|
||||||
<slot name="offer"></slot>
|
<slot name="offer"></slot>
|
||||||
</section>
|
</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