@@ -39,7 +39,7 @@ export const Positionable = (superclass) => {
3939 this . addEventListener ( 'close' , this . __onClose ) ;
4040
4141 if ( this . open ) {
42- this . __addOpenListeners ( ) ;
42+ this . $emit ( 'open' ) ;
4343 }
4444 }
4545
@@ -100,8 +100,12 @@ export const Positionable = (superclass) => {
100100 * @type {HTMLElement }
101101 */
102102 get relativeElement ( ) {
103+ if ( ! this . isConnected ) {
104+ return ;
105+ }
106+
103107 if ( this . relativeTo ) {
104- return this . getRootNode ( ) . getElementById ( this . relativeTo ) ;
108+ return this . getRootNode ( ) . querySelector ( `# ${ this . relativeTo } ` ) ;
105109 } else {
106110 return this . controlElement ;
107111 }
@@ -119,28 +123,14 @@ export const Positionable = (superclass) => {
119123 this . setAttribute ( 'relative-to' , value ) ;
120124 }
121125
122- /**
123- * Calculate fixed {x,y} coordinates relative to another HTML element.
124- *
125- * @returns {Object } Coordinate object with `x` and `y` properties.
126- */
127- getCoordinates ( ) {
128- let posRect = this . getBoundingClientRect ( ) ;
129- let relRect = this . relativeElement . getBoundingClientRect ( ) ;
130- let calculate = offsetFunctionMap [ this . position ] ;
131- let opts = this . __getDeltas ( ) ;
132-
133- return calculate ( posRect , relRect , opts ) ;
134- }
135-
136126 /**
137127 * Calculate and apply new (x,y) coordinates.
138128 *
139129 * Requires the element to be open with a `relativeElement`.
140130 */
141131 reposition ( ) {
142132 if ( this . open && this . relativeElement ) {
143- let { x, y } = this . getCoordinates ( ) ;
133+ let { x, y } = this . __getCoordinates ( ) ;
144134
145135 this . style . top = `${ y } px` ;
146136 this . style . left = `${ x } px` ;
@@ -153,11 +143,33 @@ export const Positionable = (superclass) => {
153143 * Add event listeners that only apply when open.
154144 */
155145 __addOpenListeners ( ) {
146+ if ( ! this . controlElement ) {
147+ return ;
148+ }
149+
156150 document . addEventListener ( 'click' , this . __onDocumentClick ) ;
157151 document . addEventListener ( 'scroll' , this . __onDocumentScroll , { passive : true } ) ;
158152 window . addEventListener ( 'resize' , this . __onWindowResize , { passive : true } ) ;
159153 }
160154
155+ /**
156+ * Calculate fixed {x,y} coordinates relative to another HTML element.
157+ *
158+ * @returns {Object } Coordinate object with `x` and `y` properties.
159+ */
160+ __getCoordinates ( ) {
161+ if ( ! this . relativeElement ) {
162+ return { x : 0 , y : 0 } ;
163+ }
164+
165+ let posRect = this . getBoundingClientRect ( ) ;
166+ let relRect = this . relativeElement . getBoundingClientRect ( ) ;
167+ let calculate = offsetFunctionMap [ this . position ] ;
168+ let opts = this . __getDeltas ( ) ;
169+
170+ return calculate ( posRect , relRect , opts ) ;
171+ }
172+
161173 /**
162174 * Calculate X and Y adjustments based on configuration via the following attributes.
163175 * * `data-margin`
@@ -220,6 +232,10 @@ export const Positionable = (superclass) => {
220232 * @param {Event } evt
221233 */
222234 __onDocumentClick ( evt ) {
235+ if ( ! this . controlElement ) {
236+ return ;
237+ }
238+
223239 let inComponent = this . contains ( evt . target ) ;
224240 let inControl = this . controlElement . contains ( evt . target ) ;
225241 let isBackground = ( ! inComponent && ! inControl ) ;
@@ -240,9 +256,7 @@ export const Positionable = (superclass) => {
240256 * Positionable 'open' event listener.
241257 */
242258 __onOpen ( ) {
243- if ( this . relativeElement ) {
244- this . __addOpenListeners ( ) ;
245- }
259+ this . __addOpenListeners ( ) ;
246260 this . reposition ( ) ;
247261 }
248262
0 commit comments