@@ -18,10 +18,11 @@ class Widget {
1818 constructor ( remoteStorage , options = { } ) {
1919 this . rs = remoteStorage ;
2020
21- this . leaveOpen = options . leaveOpen ? options . leaveOpen : false ;
22- this . autoCloseAfter = options . autoCloseAfter ? options . autoCloseAfter : 1500 ;
23- this . skipInitial = options . skipInitial ? options . skipInitial : false ;
24- this . logging = options . logging ? options . logging : false ;
21+ this . leaveOpen = options . leaveOpen ? options . leaveOpen : false ;
22+ this . autoCloseAfter = options . autoCloseAfter ? options . autoCloseAfter : 1500 ;
23+ this . skipInitial = options . skipInitial ? options . skipInitial : false ;
24+ this . logging = options . logging ? options . logging : false ;
25+ this . parentContainerEl = null ;
2526
2627 if ( options . hasOwnProperty ( 'modalBackdrop' ) ) {
2728 if ( typeof options . modalBackdrop !== 'boolean' && options . modalBackdrop !== 'onlySmallScreens' ) {
@@ -124,13 +125,13 @@ class Widget {
124125 if ( ! state ) return ;
125126 this . log ( 'Setting state ' , state ) ;
126127
127- let lastSelected = document . querySelector ( '.rs-box.rs-selected' ) ;
128+ let lastSelected = this . parentContainerEl . querySelector ( '.rs-box.rs-selected' ) ;
128129 if ( lastSelected ) {
129130 lastSelected . classList . remove ( 'rs-selected' ) ;
130131 lastSelected . setAttribute ( 'aria-hidden' , 'true' ) ;
131132 }
132133
133- let toSelect = document . querySelector ( '.rs-box.rs-box-' + state ) ;
134+ let toSelect = this . parentContainerEl . querySelector ( '.rs-box.rs-box-' + state ) ;
134135 if ( toSelect ) {
135136 toSelect . classList . add ( 'rs-selected' ) ;
136137 toSelect . setAttribute ( 'aria-hidden' , 'false' ) ;
@@ -194,21 +195,26 @@ class Widget {
194195 /**
195196 * Save all interactive DOM elements as variables for later access.
196197 *
198+ * @throws {Error } If parent container element not found
197199 * @private
198200 */
199201 setupElements ( ) {
200- this . rsWidget = document . querySelector ( '.rs-widget' ) ;
201- this . rsBackdrop = document . querySelector ( '.remotestorage-widget-modal-backdrop' ) ;
202- this . rsInitial = document . querySelector ( '.rs-box-initial' ) ;
203- this . rsChoose = document . querySelector ( '.rs-box-choose' ) ;
204- this . rsConnected = document . querySelector ( '.rs-box-connected' ) ;
205- this . rsSignIn = document . querySelector ( '.rs-box-sign-in' ) ;
206-
207- this . rsConnectedLabel = document . querySelector ( '.rs-box-connected .rs-sub-headline' ) ;
208- this . rsChooseRemoteStorageButton = document . querySelector ( 'button.rs-choose-rs' ) ;
209- this . rsChooseDropboxButton = document . querySelector ( 'button.rs-choose-dropbox' ) ;
210- this . rsChooseGoogleDriveButton = document . querySelector ( 'button.rs-choose-googledrive' ) ;
211- this . rsErrorBox = document . querySelector ( '.rs-box-error .rs-error-message' ) ;
202+ if ( ! this . parentContainerEl ) {
203+ throw new Error ( "Parent container element not found" ) ;
204+ }
205+
206+ this . rsWidget = this . parentContainerEl . querySelector ( '.rs-widget' ) ;
207+ this . rsBackdrop = this . parentContainerEl . querySelector ( '.remotestorage-widget-modal-backdrop' ) ;
208+ this . rsInitial = this . parentContainerEl . querySelector ( '.rs-box-initial' ) ;
209+ this . rsChoose = this . parentContainerEl . querySelector ( '.rs-box-choose' ) ;
210+ this . rsConnected = this . parentContainerEl . querySelector ( '.rs-box-connected' ) ;
211+ this . rsSignIn = this . parentContainerEl . querySelector ( '.rs-box-sign-in' ) ;
212+
213+ this . rsConnectedLabel = this . parentContainerEl . querySelector ( '.rs-box-connected .rs-sub-headline' ) ;
214+ this . rsChooseRemoteStorageButton = this . parentContainerEl . querySelector ( 'button.rs-choose-rs' ) ;
215+ this . rsChooseDropboxButton = this . parentContainerEl . querySelector ( 'button.rs-choose-dropbox' ) ;
216+ this . rsChooseGoogleDriveButton = this . parentContainerEl . querySelector ( 'button.rs-choose-googledrive' ) ;
217+ this . rsErrorBox = this . parentContainerEl . querySelector ( '.rs-box-error .rs-error-message' ) ;
212218
213219 // check if apiKeys is set for Dropbox or Google [googledrive, dropbox]
214220 // to show/hide relative buttons only if needed
@@ -220,18 +226,18 @@ class Widget {
220226 this . rsChooseDropboxButton . parentNode . removeChild ( this . rsChooseDropboxButton ) ;
221227 }
222228
223- this . rsSignInForm = document . querySelector ( '.rs-sign-in-form' ) ;
229+ this . rsSignInForm = this . parentContainerEl . querySelector ( '.rs-sign-in-form' ) ;
224230 this . rsAddressInput = this . rsSignInForm . querySelector ( 'input[name=rs-user-address]' ) ;
225- this . rsConnectButton = document . querySelector ( '.rs-connect' ) ;
231+ this . rsConnectButton = this . parentContainerEl . querySelector ( '.rs-connect' ) ;
226232
227- this . rsDisconnectButton = document . querySelector ( '.rs-disconnect' ) ;
228- this . rsSyncButton = document . querySelector ( '.rs-sync' ) ;
229- this . rsLogo = document . querySelector ( '.rs-widget-icon' ) ;
233+ this . rsDisconnectButton = this . parentContainerEl . querySelector ( '.rs-disconnect' ) ;
234+ this . rsSyncButton = this . parentContainerEl . querySelector ( '.rs-sync' ) ;
235+ this . rsLogo = this . parentContainerEl . querySelector ( '.rs-widget-icon' ) ;
230236
231- this . rsErrorReconnectLink = document . querySelector ( '.rs-box-error a.rs-reconnect' ) ;
232- this . rsErrorDisconnectButton = document . querySelector ( '.rs-box-error button.rs-disconnect' ) ;
237+ this . rsErrorReconnectLink = this . parentContainerEl . querySelector ( '.rs-box-error a.rs-reconnect' ) ;
238+ this . rsErrorDisconnectButton = this . parentContainerEl . querySelector ( '.rs-box-error button.rs-disconnect' ) ;
233239
234- this . rsConnectedUser = document . querySelector ( '.rs-connected-text h1.rs-user' ) ;
240+ this . rsConnectedUser = this . parentContainerEl . querySelector ( '.rs-connected-text h1.rs-user' ) ;
235241 }
236242
237243 /**
@@ -257,22 +263,27 @@ class Widget {
257263 * If an elementId is specified, it will be appended to that element,
258264 * otherwise it will be appended to the document's body.
259265 *
260- * @param {String } [elementId] - Widget's parent
266+ * @param {String,HTMLElement } [element] - Widget's parent
267+ * @throws {Error } If the element is not found or is of an unknown type.
261268 */
262- attach ( elementId ) {
263- const domElement = this . createHtmlTemplate ( ) ;
269+ attach ( element ) {
270+ const domElement = this . createHtmlTemplate ( element ) ;
264271
265- let parentContainerEl ;
272+ this . parentContainerEl ;
266273
267- if ( elementId ) {
268- parentContainerEl = document . getElementById ( elementId ) ;
274+ if ( element instanceof HTMLElement ) {
275+ this . parentContainerEl = element ;
276+ } else if ( typeof element === "string" ) {
277+ this . parentContainerEl = document . getElementById ( element ) ;
269278 if ( ! parent ) {
270- throw "Failed to find target DOM element with id=\"" + elementId + "\"" ;
279+ throw new Error ( "Failed to find target DOM element with id=\"" + element + "\"" ) ;
271280 }
281+ } else if ( element ) {
282+ throw new Error ( "Unknown element type. Expected instance of HTMLElement or type of string." ) ;
272283 } else {
273- parentContainerEl = document . body ;
284+ this . parentContainerEl = document . body ;
274285 }
275- parentContainerEl . appendChild ( domElement ) ;
286+ this . parentContainerEl . appendChild ( domElement ) ;
276287
277288 this . setupElements ( ) ;
278289 this . setupHandlers ( ) ;
@@ -283,7 +294,7 @@ class Widget {
283294 setEventListeners ( ) {
284295 this . rsSignInForm . addEventListener ( 'submit' , ( e ) => {
285296 e . preventDefault ( ) ;
286- let userAddress = document . querySelector ( 'input[name=rs-user-address]' ) . value ;
297+ let userAddress = this . parentContainerEl . querySelector ( 'input[name=rs-user-address]' ) . value ;
287298 this . disableConnectButton ( ) ;
288299 this . rs . connect ( userAddress ) ;
289300 } ) ;
@@ -381,7 +392,7 @@ class Widget {
381392 this . rsWidget . classList . remove ( 'rs-closed' ) ;
382393 this . shouldCloseWhenSyncDone = false ; // prevent auto-closing when user opened the widget
383394
384- let selected = document . querySelector ( '.rs-box.rs-selected' ) ;
395+ let selected = this . parentContainerEl . querySelector ( '.rs-box.rs-selected' ) ;
385396 if ( selected ) {
386397 selected . setAttribute ( 'aria-hidden' , 'false' ) ;
387398 }
@@ -400,7 +411,7 @@ class Widget {
400411 if ( ! this . leaveOpen && this . active ) {
401412 this . closed = true ;
402413 this . rsWidget . classList . add ( 'rs-closed' ) ;
403- let selected = document . querySelector ( '.rs-box.rs-selected' ) ;
414+ let selected = this . parentContainerEl . querySelector ( '.rs-box.rs-selected' ) ;
404415 if ( selected ) {
405416 selected . setAttribute ( 'aria-hidden' , 'true' ) ;
406417 }
@@ -509,7 +520,7 @@ class Widget {
509520 }
510521
511522 handleDiscoveryError ( error ) {
512- let msgContainer = document . querySelector ( '.rs-sign-in-error' ) ;
523+ let msgContainer = this . parentContainerEl . querySelector ( '.rs-sign-in-error' ) ;
513524 msgContainer . innerHTML = error . message ;
514525 msgContainer . classList . remove ( 'rs-hidden' ) ;
515526 msgContainer . classList . add ( 'rs-visible' ) ;
0 commit comments