11/* eslint-disable class-methods-use-this */
2- import { unsafeHTML } from ' lit/directives/unsafe-html.js' ;
3- import { css , html , LitElement , nothing } from ' lit' ;
4- import ' @internetarchive/ia-activity-indicator/ia-activity-indicator.js' ;
5- import checkmarkIconTemplate from ' ../../css/icon_checkmark.js' ;
6- import closeIconTemplate from ' @internetarchive/icon-close/index.js' ;
7- import buttonCSS from ' ../../css/button-base.js' ;
8- import { ifDefined } from ' lit/directives/if-defined.js' ;
9- import { sharedStyles } from ' ../../css/sharedStyles.js' ;
10- import { svgToDataUrl } from ' ../../util/lit.js' ;
2+ import { unsafeHTML } from " lit/directives/unsafe-html.js" ;
3+ import { css , html , LitElement , nothing } from " lit" ;
4+ import " @internetarchive/ia-activity-indicator/ia-activity-indicator.js" ;
5+ import checkmarkIconTemplate from " ../../css/icon_checkmark.js" ;
6+ import closeIconTemplate from " @internetarchive/icon-close/index.js" ;
7+ import buttonCSS from " ../../css/button-base.js" ;
8+ import { ifDefined } from " lit/directives/if-defined.js" ;
9+ import { sharedStyles } from " ../../css/sharedStyles.js" ;
10+ import { svgToDataUrl } from " ../../util/lit.js" ;
1111/** @typedef {import('@/src/plugins/search/plugin.search.js').SearchInsideMatch } SearchInsideMatch */
1212
1313const checkmarkIconData = svgToDataUrl ( checkmarkIconTemplate . strings [ 0 ] ) ;
@@ -30,11 +30,11 @@ export class IABookSearchResults extends LitElement {
3030
3131 /** @type {SearchInsideMatch[] } */
3232 this . results = [ ] ;
33- this . query = '' ;
33+ this . query = "" ;
3434 this . queryInProgress = false ;
3535 this . renderHeader = false ;
3636 this . renderSearchAllFiles = false ;
37- this . errorMessage = '' ;
37+ this . errorMessage = "" ;
3838
3939 this . bindBookReaderListeners ( ) ;
4040 }
@@ -45,7 +45,10 @@ export class IABookSearchResults extends LitElement {
4545 }
4646
4747 bindBookReaderListeners ( ) {
48- document . addEventListener ( 'BookReader:SearchCallback' , this . setResults . bind ( this ) ) ;
48+ document . addEventListener (
49+ "BookReader:SearchCallback" ,
50+ this . setResults . bind ( this ) ,
51+ ) ;
4952 }
5053
5154 /**
@@ -55,7 +58,7 @@ export class IABookSearchResults extends LitElement {
5558 if ( this . results . length ) {
5659 return ;
5760 }
58- const searchInput = this . shadowRoot . querySelector ( ' input[type=\ 'search\']' ) ;
61+ const searchInput = this . shadowRoot . querySelector ( " input[type='search']" ) ;
5962 searchInput . focus ( ) ;
6063 }
6164
@@ -76,28 +79,34 @@ export class IABookSearchResults extends LitElement {
7679 if ( ! input || ! input . value ) {
7780 return ;
7881 }
79- this . dispatchEvent ( new CustomEvent ( 'bookSearchInitiated' , {
80- bubbles : true ,
81- composed : true ,
82- detail : {
83- query : this . query ,
84- } ,
85- } ) ) ;
82+ this . dispatchEvent (
83+ new CustomEvent ( "bookSearchInitiated" , {
84+ bubbles : true ,
85+ composed : true ,
86+ detail : {
87+ query : this . query ,
88+ } ,
89+ } ) ,
90+ ) ;
8691 }
8792
8893 /**
8994 * @param {SearchInsideMatch } match
9095 */
9196 selectResult ( match ) {
92- this . dispatchEvent ( new CustomEvent ( 'resultSelected' , {
93- bubbles : true ,
94- composed : true ,
95- detail : { match } ,
96- } ) ) ;
97- this . dispatchEvent ( new CustomEvent ( 'closeMenu' , {
98- bubbles : true ,
99- composed : true ,
100- } ) ) ;
97+ this . dispatchEvent (
98+ new CustomEvent ( "resultSelected" , {
99+ bubbles : true ,
100+ composed : true ,
101+ detail : { match } ,
102+ } ) ,
103+ ) ;
104+ this . dispatchEvent (
105+ new CustomEvent ( "closeMenu" , {
106+ bubbles : true ,
107+ composed : true ,
108+ } ) ,
109+ ) ;
101110 }
102111
103112 cancelSearch ( ) {
@@ -106,12 +115,12 @@ export class IABookSearchResults extends LitElement {
106115 }
107116
108117 dispatchSearchCanceled ( ) {
109- this . dispatchEvent ( new Event ( ' bookSearchCanceled' ) ) ;
118+ this . dispatchEvent ( new Event ( " bookSearchCanceled" ) ) ;
110119 }
111120
112121 get resultsCount ( ) {
113122 const count = this . results . length ;
114- return count ? `${ count } result${ count > 1 ? 's' : '' } ` : nothing ;
123+ return count ? `${ count } result${ count > 1 ? "s" : "" } ` : nothing ;
115124 }
116125
117126 get headerSection ( ) {
@@ -133,57 +142,82 @@ export class IABookSearchResults extends LitElement {
133142 get loadingIndicator ( ) {
134143 return html `
135144 <div class= "loading" >
136- <ia- activity- indicato r mode= "processing" aria-hidden = "true" role = "presentation" > </ ia- activity- indicato r>
145+ <ia- activity- indicato r
146+ mode= "processing"
147+ aria-hidden = "true"
148+ role = "presentation"
149+ > </ ia- activity- indicato r>
137150 <p> Searching </ p>
138- <butto n class= "ia-button external cancel-search" @click = ${ this . cancelSearch } > Cancel </ butto n>
151+ <butto n
152+ class= "ia-button external cancel-search"
153+ @click = ${ this . cancelSearch }
154+ >
155+ Cancel
156+ </ butto n>
139157 </ div>
140158 ` ;
141159 }
142160
143161 get resultsSet ( ) {
144162 return html `
145- <nav aria- label= "Search results" >
146- <div>
147- ${ this . resultsCount }
163+ <nav aria- label= "Search results" >
164+ <div>
165+ ${ this . resultsCount }
166+ <a
167+ href= "#"
168+ class = "skip- link"
169+ @click = ${ ( e ) => {
170+ e . preventDefault ( ) ;
171+ this . shadowRoot
172+ . querySelector ( ".results li:last-child .result-item" )
173+ . focus ( ) ;
174+ } }
175+ > Skip to last result </ a
176+ >
177+ </ div>
178+ <ul class= "results" >
179+ ${ this . results . map (
180+ ( match ) => html `
181+ <li>
182+ <butto n
183+ class= "result-item"
184+ @click = ${ this . selectResult . bind ( this , match ) }
185+ >
186+ <span class= "page-num" > Page ${ match . displayPageNumber } </ span>
187+ —
188+ <span lang= ${ ifDefined ( match . lang ) }
189+ > ${ unsafeHTML ( match . html ) } </ span
190+ >
191+ </ butto n>
192+ </ li>
193+ ` ,
194+ ) }
195+ </ ul>
148196 <a
149197 href= "#"
150198 class = "skip- link"
151199 @click = ${ ( e ) => {
152- e . preventDefault ( ) ;
153- this . shadowRoot . querySelector ( '.results li:last-child .result-item' ) . focus ( ) ;
154- } }
155- > Skip to last result </ a>
156- </ div>
157- <ul class= "results" >
158- ${ this . results . map ( match => html `
159- <li>
160- <butto n class= "result-item" @click = ${ this . selectResult . bind ( this , match ) } >
161- <span class= "page-num" > Page ${ match . displayPageNumber } </ span> — <span lang= ${ ifDefined ( match . lang ) } > ${ unsafeHTML ( match . html ) } </ span>
162- </ butto n>
163- </ li>
164- ` ) }
165- </ ul>
166- <a
167- href= "#"
168- class = "skip- link"
169- @click = ${ ( e ) => {
170- e . preventDefault ( ) ;
171- this . shadowRoot . querySelector ( '.results li:first-child .result-item' ) . focus ( ) ;
172- } }
173- > Skip to first result </ a>
174- </ nav>
200+ e . preventDefault ( ) ;
201+ this . shadowRoot
202+ . querySelector ( ".results li:first-child .result-item" )
203+ . focus ( ) ;
204+ } }
205+ > Skip to first result </ a
206+ >
207+ </ nav>
175208 ` ;
176209 }
177210
178211 get setErrorMessage ( ) {
179- return html `
180- <p class= "error-message" > ${ this . errorMessage } </ p>
181- ` ;
212+ return html ` <p class= "error-message" > ${ this . errorMessage } </ p> ` ;
182213 }
183214
184215 render ( ) {
185- const showSearchCTA = ( ! this . queryInProgress && ! this . errorMessage )
186- && ( ! this . queryInProgress && ! this . results . length ) ;
216+ const showSearchCTA =
217+ ! this . queryInProgress &&
218+ ! this . errorMessage &&
219+ ! this . queryInProgress &&
220+ ! this . results . length ;
187221 return html `
188222 ${ this . headerSection }
189223 <for m action= "" method = "get" @submit = ${ this . performSearch } >
@@ -196,7 +230,10 @@ export class IABookSearchResults extends LitElement {
196230 @search = ${ this . setQuery }
197231 .value = ${ this . query }
198232 / >
199- <label class= "search-cta ${ showSearchCTA ? '' : 'sr-only' } " for = "br- search- input">
233+ <label
234+ class= "search-cta ${ showSearchCTA ? "" : "sr-only" } "
235+ for = "br- search- input"
236+ >
200237 Please enter text to search for
201238 </ label>
202239 </ for m>
@@ -234,7 +271,7 @@ export class IABookSearchResults extends LitElement {
234271 }
235272
236273 mark {
237- padding : 0 .2rem ;
274+ padding : 0 0 .2rem ;
238275 color : ${ searchResultText } ;
239276 background : ${ searchResultBg } ;
240277 border : 1px solid ${ searchResultBorder } ;
@@ -274,7 +311,7 @@ export class IABookSearchResults extends LitElement {
274311 }
275312
276313 label .checkbox {
277- padding-bottom : .5rem ;
314+ padding-bottom : 0 .5rem ;
278315 font-size : 1.6rem ;
279316 line-height : 150% ;
280317 vertical-align : middle;
@@ -284,12 +321,12 @@ export class IABookSearchResults extends LitElement {
284321 display : inline-block;
285322 width : 14px ;
286323 height : 14px ;
287- margin-left : .7rem ;
324+ margin-left : 0 .7rem ;
288325 content : "" ;
289326 border-radius : 2px ;
290327 }
291328 : checked + label .checkbox : after {
292- background-image : url (' ${ checkmarkIconData } ' );
329+ background-image : url (" ${ checkmarkIconData } " );
293330 }
294331
295332 label .checkbox [for = "all_files" ]: after {
@@ -305,7 +342,11 @@ export class IABookSearchResults extends LitElement {
305342 height : 3rem ;
306343 padding : 0 10px ;
307344 box-sizing : border-box;
308- font : normal 1.6rem "Helvetica qNeue" , Helvetica, Arial, sans-serif;
345+ font :
346+ normal 1.6rem "Helvetica qNeue" ,
347+ Helvetica,
348+ Arial,
349+ sans-serif;
309350 border-radius : 1.5rem ;
310351 background : transparent;
311352 }
@@ -318,8 +359,8 @@ export class IABookSearchResults extends LitElement {
318359 margin-right : -5px ;
319360 -webkit-appearance : none;
320361 appearance : none;
321- -webkit-mask : url (' ${ closeIconData } ' ) 0 0 no-repeat;
322- mask : url (' ${ closeIconData } ' ) 0 0 no-repeat;
362+ -webkit-mask : url (" ${ closeIconData } " ) 0 0 no-repeat;
363+ mask : url (" ${ closeIconData } " ) 0 0 no-repeat;
323364 -webkit-mask-size : 100% ;
324365 mask-size : 100% ;
325366 background : # fff ;
@@ -360,6 +401,12 @@ export class IABookSearchResults extends LitElement {
360401 text-align : left;
361402 font-family : inherit;
362403 transition : background-color 0.2s ;
404+ /* Allow users to select and copy search snippet text inside result buttons. */
405+ -webkit-user-select : text;
406+ -moz-user-select : text;
407+ -ms-user-select : text;
408+ -o-user-select : text;
409+ user-select : text;
363410 }
364411
365412 .result-item : hover {
@@ -386,4 +433,4 @@ export class IABookSearchResults extends LitElement {
386433 return [ sharedStyles , buttonCSS , mainCSS ] ;
387434 }
388435}
389- customElements . define ( ' ia-book-search-results' , IABookSearchResults ) ;
436+ customElements . define ( " ia-book-search-results" , IABookSearchResults ) ;
0 commit comments