Skip to content

Commit a814194

Browse files
authored
Merge pull request #407 from rackerlabs/surf-1498-refactor-search-assist-use-mixins
refactor(hx-search-assistance): surf-1498 use positionable mixin
2 parents ff406ca + b4e8dba commit a814194

File tree

2 files changed

+11
-164
lines changed

2 files changed

+11
-164
lines changed

docs/elements/hx-search-assistance/index.html

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
<ul class="hxList">
3030
<li><code>close</code></li>
3131
<li><code>open</code></li>
32+
<li><code>reposition</code></li>
3233
<li>
3334
<code>scroll</code> (Emitted from <code>document</code> as a
3435
<code>CustomEvent</code> instance.)
@@ -42,10 +43,10 @@
4243

4344
{% block attributes %}
4445
<dl>
45-
<dt>open</dt>
46+
<dt>open <i>(optional)</i></dt>
4647
<dd>Opens the search assistance</dd>
4748

48-
<dt>position {String [bottom-start]}</dt>
49+
<dt>position <i>(optional)</i></dt>
4950
<dd>Positions the search assistance</dd>
5051

5152
<dt>relative-to <i>(optional)</i></dt>
Lines changed: 8 additions & 162 deletions
Original file line numberDiff line numberDiff line change
@@ -1,181 +1,27 @@
11
import { HXElement } from './HXElement';
2-
import { getPosition } from '../utils/position';
3-
import debounce from 'lodash/debounce';
42

5-
const DEFAULT_POSITION = 'bottom-start';
3+
import { mix } from '../utils';
4+
import { Positionable } from '../mixins/Positionable';
65

7-
/**
8-
* Fires when the element's contents are concealed.
9-
*
10-
* @event SearchAssistance:close
11-
* @since 0.6.0
12-
* @type {CustomEvent}
13-
*/
14-
15-
/**
16-
* Fires when the element's contents are revealed.
17-
*
18-
* @event SearchAssistance:open
19-
* @since 0.6.0
20-
* @type {CustomEvent}
21-
*/
6+
class _ProtoClass extends mix(HXElement, Positionable) {}
227

238
/**
249
* Defines behavior for the `<hx-search-assistance>` element.
2510
*
26-
* @emits SearchAssistance:close
27-
* @emits SearchAssistance:open
2811
* @extends HXElement
12+
* @extends Positionable
2913
* @hideconstructor
3014
* @see HXSearchElement
3115
* @since 0.6.0
3216
*/
33-
export class HXSearchAssistanceElement extends HXElement {
17+
export class HXSearchAssistanceElement extends _ProtoClass {
3418
static get is () {
3519
return 'hx-search-assistance';
3620
}
3721

22+
/** @override */
3823
$onCreate () {
39-
this._onDocumentScroll = this._onDocumentScroll.bind(this);
40-
this._reposition = this._reposition.bind(this);
41-
42-
this._onWindowResize = debounce(this._reposition, 50);
43-
}
44-
45-
$onConnect () {
46-
this.$upgradeProperty('open');
47-
this.$upgradeProperty('position');
48-
this.$upgradeProperty('relativeTo');
49-
50-
this.$defaultAttribute('position', DEFAULT_POSITION);
51-
this._initialPosition = this.position;
52-
53-
this.setAttribute('aria-hidden', !this.open);
54-
}
55-
56-
static get $observedAttributes () {
57-
return [ 'open' ];
58-
}
59-
60-
$onAttributeChange (attr, oldVal, newVal) {
61-
if (attr === 'open') {
62-
this._attrOpenChange(oldVal, newVal);
63-
}
64-
}
65-
66-
/**
67-
* External element that controls <hx-search-assistance> visibility.
68-
*
69-
* @readonly
70-
* @type {HTMLElement}
71-
*/
72-
get controlElement () {
73-
return this.getRootNode().querySelector(`[aria-controls="${this.id}"]`);
74-
}
75-
76-
/**
77-
* Determine if <hx-search-assistance> is visible.
78-
*
79-
* @default false
80-
* @type {Boolean}
81-
*/
82-
get open () {
83-
return this.hasAttribute('open');
84-
}
85-
set open (value) {
86-
if (value) {
87-
this.setAttribute('open', '');
88-
} else {
89-
this.removeAttribute('open');
90-
}
91-
}
92-
93-
/**
94-
* Where to position <hx-search-assistance> in relation to its reference element.
95-
*
96-
* @default 'bottom-start'
97-
* @type {PositionString}
98-
*/
99-
get position () {
100-
return this.getAttribute('position') || DEFAULT_POSITION;
101-
}
102-
set position (value) {
103-
if (value) {
104-
this.setAttribute('position', value);
105-
} else {
106-
this.removeAttribute('position');
107-
}
108-
}
109-
110-
/**
111-
* Reference element used to calculate <hx-search-assistance> position.
112-
*
113-
* @readonly
114-
* @type {HTMLElement}
115-
*/
116-
get relativeElement () {
117-
if (this.relativeTo) {
118-
return this.getRootNode().getElementById(this.relativeTo);
119-
} else {
120-
return this.controlElement;
121-
}
122-
}
123-
124-
/**
125-
* ID of an element relatively to <hx-search-assistance>.
126-
*
127-
* @type {String}
128-
*/
129-
get relativeTo () {
130-
return this.getAttribute('relative-to');
131-
}
132-
set relativeTo (value) {
133-
this.setAttribute('relative-to', value);
134-
}
135-
136-
/** @private */
137-
_addOpenListeners () {
138-
document.addEventListener('scroll', this._onDocumentScroll);
139-
window.addEventListener('resize', this._onWindowResize);
140-
}
141-
142-
/** @private */
143-
_attrOpenChange (oldVal, newVal) {
144-
let isOpen = (newVal !== null);
145-
this.setAttribute('aria-hidden', !isOpen);
146-
this.$emit(isOpen ? 'open' : 'close');
147-
148-
if (isOpen) {
149-
this._addOpenListeners();
150-
this._reposition();
151-
} else {
152-
this._removeOpenListeners();
153-
this.position = this._initialPosition;
154-
}
155-
}
156-
157-
/** @private */
158-
_onDocumentScroll () {
159-
this._reposition();
160-
}
161-
162-
/** @private */
163-
_removeOpenListeners () {
164-
document.removeEventListener('scroll', this._onDocumentScroll);
165-
window.removeEventListener('resize', this._onWindowResize);
166-
}
167-
168-
/** @private */
169-
_reposition () {
170-
if (this.relativeElement) {
171-
let { x, y } = getPosition({
172-
element: this,
173-
reference: this.relativeElement,
174-
position: this.position,
175-
});
176-
177-
this.style.top = `${y}px`;
178-
this.style.left = `${x}px`;
179-
}
24+
super.$onCreate();
25+
this.DEFAULT_POSITION = 'bottom-start';
18026
}
18127
}

0 commit comments

Comments
 (0)