@@ -300,6 +300,12 @@ var pcminer = (function () {
300300 resetSelector ( ) ;
301301 }
302302
303+ var surnameSearch = true ;
304+ function surnameSearchChanged ( val ) {
305+ surnameSearch = val ;
306+ resetSelector ( ) ;
307+ }
308+
303309 /**
304310 * invoked when the conditionFilter has changed.
305311 */
@@ -400,6 +406,50 @@ var pcminer = (function () {
400406 '<span float="left">' + nrC + " committee records selected</span>" ;
401407 }
402408
409+ // Updated decodeHtml function using DOMParser
410+ function decodeHtml ( html ) {
411+ const parser = new DOMParser ( ) ;
412+ const doc = parser . parseFromString ( html , "text/html" ) ;
413+ return doc . documentElement . textContent ;
414+ }
415+
416+ // Updated normalization function with a fallback for browsers that lack normalize support
417+ function normalizeString ( str ) {
418+ // Convert to lowercase first so that explicit replacements catch both cases.
419+ str = str . toLowerCase ( ) ;
420+ // If normalization is available, use NFKD to break down characters.
421+ if ( typeof str . normalize === "function" ) {
422+ str = str . normalize ( "NFKD" ) ;
423+ }
424+ // Remove diacritical marks and explicitly replace the 'ø' character.
425+ return str . replace ( / [ \u0300 - \u036f ] / g, "" ) . replace ( / ø / g, "o" ) ;
426+ }
427+
428+ function nameStartsWith ( fullName , prefix ) {
429+ // Decode HTML entities (e.g. converting "ø" into "ø").
430+ fullName = fullName . replace ( "ø" , "o" ) ;
431+ const decodedFullName = decodeHtml ( fullName ) ;
432+
433+ // Split the decoded name into words and filter out any empty strings.
434+ const names = decodedFullName . split ( " " ) . filter ( Boolean ) ;
435+ if ( names . length === 0 ) return false ;
436+
437+ // Assume the first and last words are the first and last names.
438+ const firstName = names [ 0 ] ;
439+ const lastName = names [ names . length - 1 ] ;
440+
441+ // Normalize the first name, last name, and the prefix.
442+ const normalizedPrefix = normalizeString ( prefix ) ;
443+ const normalizedFirstName = normalizeString ( firstName ) ;
444+ const normalizedLastName = normalizeString ( lastName ) ;
445+
446+ // Check if either the first or last name starts with the normalized prefix.
447+ return (
448+ normalizedFirstName . startsWith ( normalizedPrefix ) ||
449+ ( surnameSearch && normalizedLastName . startsWith ( normalizedPrefix ) )
450+ ) ;
451+ }
452+
403453 /**
404454 * resets the selector to reflect the current filter settings
405455 */
@@ -411,7 +461,7 @@ var pcminer = (function () {
411461 clip . append ( "<p>" ) ;
412462 for ( var i = 0 ; i < list . length ; i ++ ) {
413463 var x = list [ i ] ;
414- if ( nameFilter == "" || x . author . indexOf ( nameFilter ) == 0 ) {
464+ if ( nameFilter == "" || nameStartsWith ( x . author , nameFilter ) ) {
415465 if ( nrPublicationsAndCommittees ( x ) > 0 && eval ( conditionFilter ) ) {
416466 // evil call to eval()
417467 selector . append ( "<option>" + x . author + "</option>" ) ;
@@ -874,6 +924,7 @@ var pcminer = (function () {
874924 nameFilterChanged : nameFilterChanged ,
875925 dateFilterChanged : dateFilterChanged ,
876926 conditionFilterChanged : conditionFilterChanged ,
927+ surnameSearchChanged : surnameSearchChanged ,
877928 confSelected : confSelected ,
878929 confsSelected : confsSelected ,
879930 copyToClipboard : copyToClipboard ,
0 commit comments