diff --git a/client/src/app.js b/client/src/app.js index 786df7e..24d67f0 100644 --- a/client/src/app.js +++ b/client/src/app.js @@ -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"; diff --git a/client/src/local-businesses/local-businesses.js b/client/src/local-businesses/local-businesses.js index 647fba8..f3a08be 100644 --- a/client/src/local-businesses/local-businesses.js +++ b/client/src/local-businesses/local-businesses.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(`
- +
`); - { - 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'); - } - } - } } }); diff --git a/client/src/marketplace/marketplace-offers.js b/client/src/marketplace/marketplace-offers.js index 382345f..7de4704 100644 --- a/client/src/marketplace/marketplace-offers.js +++ b/client/src/marketplace/marketplace-offers.js @@ -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 {
+
+ +
diff --git a/client/src/marketplace/user-edit-offer.js b/client/src/marketplace/user-edit-offer.js index c1d818e..ac0f651 100644 --- a/client/src/marketplace/user-edit-offer.js +++ b/client/src/marketplace/user-edit-offer.js @@ -147,4 +147,8 @@ customElements.define('user-edit-offer', class extends Component { } } } + + matches(regex) { + return !!this.description.match(regex) + } }); diff --git a/client/src/shared/search-input.js b/client/src/shared/search-input.js new file mode 100644 index 0000000..bafb17c --- /dev/null +++ b/client/src/shared/search-input.js @@ -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(` + +
+ +
+ `); + 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'); + } + } + } + } +});