1414 * @property {string[] } fields
1515 */
1616
17+ // Let user customize the css file name
18+ const CSS_FILE_NAME = "@@file/classhelper.css" ;
19+
1720class ClassHelper extends HTMLElement {
1821 /** @type {Window } */
1922 popupRef = null ;
@@ -84,10 +87,7 @@ class ClassHelper extends HTMLElement {
8487 this . addEventListener ( "prevPage" , prevPageClosure ) ;
8588
8689 const valueSelectedClosure = ( event ) => {
87- this . valueSelected ( properties , event . detail . value ) . catch ( error => {
88- // Top level error handling for valueSelected method.
89- this . removeEventListener ( "click" , valueSelectedClosure ) ;
90- } ) ;
90+ this . valueSelected ( properties , event . detail . value ) ;
9191 }
9292 this . addEventListener ( "valueSelected" , valueSelectedClosure ) ;
9393
@@ -132,25 +132,27 @@ class ClassHelper extends HTMLElement {
132132 "Next" : "Next" ,
133133 "Prev" : "Prev" ,
134134 "Search" : "Search" ,
135- "Reset" : "Reset" ,
136- "Out" : "Out"
135+ "Reset" : "Reset"
137136 } ;
138137
139138 let tracker = window . location . pathname . split ( '/' ) [ 1 ] ;
140139 let url = new URL ( window . location . origin + "/" + tracker ) ;
141140 url . searchParams . append ( "@template" , "json" ) ;
142141 url . searchParams . append ( "properties" , Object . keys ( translations ) . join ( ',' ) ) ;
143142
144- let resp = await fetch ( url ) ;
145- if ( ! resp . ok ) {
143+ let resp ;
144+ try {
145+ resp = await fetch ( url ) ;
146+ if ( ! resp . ok ) throw new Error ( ) ;
147+ } catch ( error ) {
148+ console . error ( error ) ;
146149 throw new Error ( "error fetching translations from roundup rest api" ) ;
147- } else {
148- ClassHelper . translations = translations ;
149150 }
150151
151152 try {
152153 ClassHelper . translations = await resp . json ( ) ;
153154 } catch ( error ) {
155+ // Default to english translations
154156 ClassHelper . translations = translations ;
155157 throw new Error ( "error parsing translation json from roundup rest api" ) ;
156158 }
@@ -549,10 +551,9 @@ class ClassHelper extends HTMLElement {
549551
550552 /**
551553 * main method called when classhelper is clicked
552- * @param {Object } props
553- * @param {string } props.width
554- * @param {string } props.height
555- * @param {string[] } props.fields
554+ * @param {URL | string } apiURL
555+ * @param {ClassHelperProps } props
556+ * @throws {Error } when fetching or parsing data from roundup rest api fails
556557 */
557558 async openPopUp ( apiURL , props ) {
558559 // Find preselected values
@@ -601,7 +602,7 @@ class ClassHelper extends HTMLElement {
601602 const css = popupDocument . createElement ( "link" ) ;
602603 css . rel = "stylesheet" ;
603604 css . type = "text/css" ;
604- css . href = props . origin + '/' + props . tracker + '/' + "@@file/classhelper.css" ;
605+ css . href = props . origin + '/' + props . tracker + '/' + CSS_FILE_NAME ;
605606 popupHead . appendChild ( css ) ;
606607
607608 popupBody . classList . add ( "flex-container" ) ;
@@ -616,59 +617,134 @@ class ClassHelper extends HTMLElement {
616617
617618 const tableFrag = this . getTableFragment ( props . fields , data . collection , preSelectedValues ) ;
618619 popupBody . appendChild ( tableFrag ) ;
619-
620- const separator = document . createElement ( "div" ) ;
620+
621+ const separator = popupDocument . createElement ( "div" ) ;
621622 separator . classList . add ( "separator" ) ;
622623 popupBody . appendChild ( separator ) ;
623624
624625 const accumulatorFrag = this . getAccumulatorFragment ( preSelectedValues ) ;
625626 popupBody . appendChild ( accumulatorFrag ) ;
626627 }
627628
628- /** method when next or previous button is clicked */
629+ /** method when next or previous button is clicked
630+ * @param {URL | string } apiURL
631+ * @param {ClassHelperProps } props
632+ * @throws {Error } when fetching or parsing data from roundup rest api fails
633+ */
629634 async pageChange ( apiURL , props ) {
630- let preSelectedValues = this . popupRef . document . getElementsByClassName ( "popup-preview" ) . item ( 0 ) . value . split ( "," ) ;
635+ let accumulatorValues = this . popupRef . document . getElementsByClassName ( "popup-preview" ) . item ( 0 ) . value . split ( "," ) ;
631636
632- fetch ( apiURL ) . then ( resp => resp . json ( ) ) . then ( ( { data } ) => {
633- const b = this . popupRef . document . body ;
634- let prevURL = data [ "@links" ] . prev ?? null ;
635- if ( prevURL ) {
636- prevURL = prevURL [ 0 ] . uri ;
637- }
638- let nextURL = data [ "@links" ] . next ?? null ;
639- if ( nextURL ) {
640- nextURL = nextURL [ 0 ] . uri ;
641- }
642- let selfUrl = new URL ( data [ "@links" ] . self [ 0 ] . uri ) ;
643- props . pageIndex = selfUrl . searchParams . get ( "@page_index" ) ;
644-
645- let oldPagination = this . popupRef . document . getElementsByClassName ( "popup-pagination" ) . item ( 0 ) ;
646- oldPagination . parentElement . replaceChild ( this . getPaginationFragment ( prevURL , nextURL , props . pageIndex , props . pageSize ) , oldPagination ) ;
647- let oldTable = this . popupRef . document . getElementsByClassName ( "popup-table" ) . item ( 0 ) ;
648- let ancestor = oldTable . parentElement . parentElement ;
649- ancestor . replaceChild ( this . getTableFragment ( props . fields , data . collection , preSelectedValues ) , oldTable . parentElement ) ;
650- } ) ;
637+ let resp ;
638+ try {
639+ resp = await fetch ( apiURL ) ;
640+ } catch ( error ) {
641+ // Show message fail to load data
642+ throw new Error ( "error fetching data from roundup rest api" ) ;
643+ }
644+
645+ let json ;
646+ try {
647+ json = await resp . json ( ) ;
648+ } catch ( error ) {
649+ // Show message fail to parse json
650+ throw new Error ( "error parsing json from roundup rest api" ) ;
651+ }
652+
653+ const data = json . data ;
654+ const links = json . data [ "@links" ] ;
655+
656+ let prevPageURL , nextPageURL , selfPageURL ;
657+
658+ if ( links . prev && links . prev . length > 0 ) {
659+ prevPageURL = links . prev [ 0 ] . uri ;
660+ }
661+ if ( links . next && links . next . length > 0 ) {
662+ nextPageURL = links . next [ 0 ] . uri ;
663+ }
664+ if ( links . self && links . self . length > 0 ) {
665+ selfPageURL = new URL ( links . self [ 0 ] . uri ) ;
666+ }
667+
668+ const popupBody = this . popupRef . document . body ;
669+ props . pageIndex = selfPageURL . searchParams . get ( "@page_index" ) ;
670+
671+ const oldPaginationFrag = popupBody . getElementsByClassName ( "popup-pagination" ) . item ( 0 ) ;
672+ const newPaginationFrag = this . getPaginationFragment ( prevPageURL , nextPageURL , props . pageIndex , props . pageSize ) ;
673+ popupBody . replaceChild ( newPaginationFrag , oldPaginationFrag ) ;
674+
675+ let oldTableFrag = popupBody . getElementsByClassName ( "popup-divtable" ) . item ( 0 ) ;
676+ let newTableFrag = this . getTableFragment ( props . fields , data . collection , accumulatorValues ) ;
677+ popupBody . replaceChild ( newTableFrag , oldTableFrag ) ;
651678 }
652679
653- /** method when a value is selected in */
654- async valueSelected ( props , value ) {
655- const input = window . document . querySelector ( `form[name="${ props . formName } "] input[name="${ props . formProperty } "]` ) ;
680+ /** method when a value is selected in
681+ * @param {ClassHelperProps } props
682+ * @param {string } value
683+ */
684+ valueSelected ( props , value ) {
685+ const input = document . getElementsByName ( props . formProperty ) . item ( 0 ) ;
656686 input . value = value ;
657687 this . popupRef . close ( ) ;
658688 }
659689
660- /** method when search is performed within classhelper, here we need to update the classhelper table with search results */
690+ /** method when search is performed within classhelper, here we need to update the classhelper table with search results
691+ * @param {URL | string } apiURL
692+ * @param {ClassHelperProps } props
693+ * @throws {Error } when fetching or parsing data from roundup rest api fails
694+ */
661695 async searchEvent ( apiURL , props ) {
662- fetch ( apiURL ) . then ( resp => resp . json ( ) ) . then ( ( { data } ) => {
663- const b = this . popupRef . document . body ;
664- let oldTable = this . popupRef . document . getElementById ( "popup-table" ) ;
665- b . replaceChild ( this . getTableFragment ( props . fields , data . collection ) , oldTable ) ;
666- } ) ;
696+ let accumulatorValues = this . popupRef . document . getElementsByClassName ( "popup-preview" ) . item ( 0 ) . value . split ( "," ) ;
697+
698+ let resp ;
699+ try {
700+ resp = await fetch ( apiURL ) ;
701+ } catch ( error ) {
702+ // Show message fail to load data
703+ throw new Error ( "error fetching data from roundup rest api" ) ;
704+ }
705+
706+ let json ;
707+ try {
708+ json = await resp . json ( ) ;
709+ } catch ( error ) {
710+ // Show message fail to parse json
711+ throw new Error ( "error parsing json from roundup rest api" ) ;
712+ }
713+
714+ const data = json . data ;
715+ const links = json . data [ "@links" ] ;
716+
717+ let prevPageURL , nextPageURL , selfPageURL ;
718+
719+ if ( links . prev && links . prev . length > 0 ) {
720+ prevPageURL = links . prev [ 0 ] . uri ;
721+ }
722+ if ( links . next && links . next . length > 0 ) {
723+ nextPageURL = links . next [ 0 ] . uri ;
724+ }
725+ if ( links . self && links . self . length > 0 ) {
726+ selfPageURL = new URL ( links . self [ 0 ] . uri ) ;
727+ }
728+
729+ const popupBody = this . popupRef . document . body ;
730+ props . pageIndex = selfPageURL . searchParams . get ( "@page_index" ) ;
731+
732+ if ( prevPageURL || nextPageURL ) {
733+ const oldPaginationFrag = popupBody . getElementsByClassName ( "popup-pagination" ) . item ( 0 ) ;
734+ const newPaginationFrag = this . getPaginationFragment ( prevPageURL , nextPageURL , props . pageIndex , props . pageSize ) ;
735+ popupBody . replaceChild ( newPaginationFrag , oldPaginationFrag ) ;
736+ }
737+
738+ let oldTableFrag = popupBody . getElementsByClassName ( "popup-divtable" ) . item ( 0 ) ;
739+ let newTableFrag = this . getTableFragment ( props . fields , data . collection , accumulatorValues ) ;
740+ popupBody . replaceChild ( newTableFrag , oldTableFrag ) ;
667741 }
668742
669- /** method when an entry in classhelper table is selected */
670- async selectionEvent ( value ) {
671- const preview = this . popupRef . document . getElementById ( "popup-preview" ) ;
743+ /** method when an entry in classhelper table is selected
744+ * @param {string } value
745+ */
746+ selectionEvent ( value ) {
747+ const preview = this . popupRef . document . getElementsByClassName ( "popup-preview" ) . item ( 0 ) ;
672748 if ( preview . value == "" || preview . value == null ) {
673749 preview . value = value
674750 } else {
0 commit comments