@@ -28,168 +28,169 @@ String.prototype.ucfirst = function() {
2828} ;
2929
3030function NameParse ( ) {
31- var me = this ;
32-
33- // split full names into the following parts:
34- // - prefix / salutation (Mr., Mrs., etc)
35- // - given name / first name
36- // - middle initials
37- // - surname / last name
38- // - suffix (II, Phd, Jr, etc)
39- NameParse . prototype . parse = function ( fullastName ) {
40- fullastName = fullastName . trim ( ) ;
41- // split into words
42- var unfilteredNameParts = fullastName . split ( " " ) ;
43- var name = { } ;
44- var nameParts = [ ] ;
45- var lastName = "" ;
46- var firstName = "" ;
47- var initials = "" ;
48- var j = 0 ;
49- var i = 0 ;
50- // completely ignore any words in parentheses
51- for ( i = 0 ; i < unfilteredNameParts . length ; i ++ ) {
52- if ( unfilteredNameParts [ i ] . indexOf ( "(" ) == - 1 )
53- nameParts [ j ++ ] = unfilteredNameParts [ i ] ;
54- }
55- var numWords = nameParts . length ;
56-
57- // is the first word a title? (Mr. Mrs, etc)
58- var salutation = me . is_salutation ( nameParts [ 0 ] ) ;
59- var suffix = me . is_suffix ( nameParts [ nameParts . length - 1 ] ) ;
60- // set the range for the middle part of the name (trim prefixes & suffixes)
61- var start = ( salutation ) ? 1 : 0 ;
62- var end = ( suffix ) ? numWords - 1 : numWords ;
63-
64- // concat the first name
65- for ( i = start ; i < ( end - 1 ) ; i ++ ) {
66- word = nameParts [ i ] ;
67- // move on to parsing the last name if we find an indicator of a compound last name (Von, Van, etc)
68- // we use i != start to allow for rare cases where an indicator is actually the first name (like "Von Fabella")
69- if ( me . is_compound_lastName ( word ) && i != start ) {
70- break ;
71- }
72- // is it a middle initial or part of their first name?
73- // if we start off with an initial, we'll call it the first name
74- if ( me . is_initial ( word ) ) {
75- // is the initial the first word?
76- if ( i == start ) {
77- // if so, do a look-ahead to see if they go by their middle name
78- // for ex: "R. Jason Smith" => "Jason Smith" & "R." is stored as an initial
79- // but "R. J. Smith" => "R. Smith" and "J." is stored as an initial
80- if ( me . is_initial ( nameParts [ i + 1 ] ) ) {
81- firstName += " " + word . toUpperCase ( ) ;
82- } else {
83- initials += " " + word . toUpperCase ( ) ;
84- }
85- // otherwise, just go ahead and save the initial
86- } else {
87- initials += " " + word . toUpperCase ( ) ;
88- }
89- } else {
90- firstName += " " + me . fix_case ( word ) ;
91- }
92- }
93-
94- // check that we have more than 1 word in our string
95- if ( ( end - start ) > 1 ) {
96- // concat the last name
97- for ( i ; i < end ; i ++ ) {
98- lastName += " " + me . fix_case ( nameParts [ i ] ) ;
99- }
100- } else {
101- // otherwise, single word strings are assumed to be first names
102- firstName = me . fix_case ( nameParts [ i ] ) ;
103- }
104-
105- // return the various parts in an array
106- name . salutation = salutation ;
107- name . firstName = firstName . trim ( ) ;
108- name . initials = initials . trim ( ) ;
109- name . lastName = lastName . trim ( ) ;
110- name . suffix = suffix ;
111-
112- return name ;
113- }
114- // detect and format standard salutations
115- // I'm only considering english honorifics for now & not words like
116- this . is_salutation = function ( word ) {
117- // ignore periods
118- word = word . replace ( "." , "" ) . toLowerCase ( ) ;
119- // returns normalized values
120- if ( word == "mr" || word == "master" || word == "mister" ) {
121- return "Mr." ;
122- } else if ( word == "mrs" ) {
123- return "Mrs." ;
124- } else if ( word == "miss" || word == "ms" ) {
125- return "Ms." ;
126- } else if ( word == "dr" ) {
127- return "Dr." ;
128- } else if ( word == "rev" ) {
129- return "Rev." ;
130- } else if ( word == "fr" ) {
131- return "Fr." ;
132- } else {
133- return false ;
134- }
135- }
136-
137- // detect and format common suffixes
138- this . is_suffix = function ( word ) {
139- // ignore periods
140- word = word . replace ( "." , "" ) . toLowerCase ( ) ;
141- // these are some common suffixes - what am I missing?
142- var suffixArray = [ 'I' , 'II' , 'III' , 'IV' , 'V' , 'Senior' , 'Junior' , 'Jr' , 'Sr' , 'PhD' , 'APR' , 'RPh' , 'PE' , 'MD' , 'MA' , 'DMD' , 'CME' ] ;
143- for ( var i = 0 ; i < suffixArray . length ; i ++ ) {
144- if ( suffixArray [ i ] . toLowerCase ( ) == word ) {
145- return suffixArray [ i ] ;
146- }
147- }
148- return false ;
149- }
150-
151- // detect compound last names like "Von Fange"
152- this . is_compound_lastName = function ( word ) {
153- word = word . toLowerCase ( ) ;
154- // these are some common prefixes that identify a compound last names - what am I missing?
155- words = [ 'vere' , 'von' , 'van' , 'de' , 'del' , 'della' , 'di' , 'da' , 'pietro' , 'vanden' , 'du' , 'st.' , 'st' , 'la' , 'lo' , 'ter' ] ;
156- return words . in_array ( word ) ;
157- }
158-
159- // single letter, possibly followed by a period
160- this . is_initial = function ( word ) {
161- // ignore periods
162- word = word . replace ( "." , "" ) ;
163- return ( word . length == 1 ) ;
164- }
31+ var me = this ;
32+
33+ // split full names into the following parts:
34+ // - prefix / salutation (Mr., Mrs., etc)
35+ // - given name / first name
36+ // - middle initials
37+ // - surname / last name
38+ // - suffix (II, Phd, Jr, etc)
39+ NameParse . prototype . parse = function ( fullastName ) {
40+ fullastName = fullastName . trim ( ) ;
41+ // split into words
42+ var unfilteredNameParts = fullastName . split ( " " ) ;
43+ var name = { } ;
44+ var nameParts = [ ] ;
45+ var lastName = "" ;
46+ var firstName = "" ;
47+ var initials = "" ;
48+ var j = 0 ;
49+ var i = 0 ;
50+ // completely ignore any words in parentheses
51+ for ( i = 0 ; i < unfilteredNameParts . length ; i ++ ) {
52+ if ( unfilteredNameParts [ i ] . indexOf ( "(" ) == - 1 ) {
53+ nameParts [ j ++ ] = unfilteredNameParts [ i ] ;
54+ }
55+ }
56+ var numWords = nameParts . length ;
57+ // is the first word a title? (Mr. Mrs, etc)
58+ var salutation = me . is_salutation ( nameParts [ 0 ] ) ;
59+ var suffix = me . is_suffix ( nameParts [ nameParts . length - 1 ] ) ;
60+ // set the range for the middle part of the name (trim prefixes & suffixes)
61+ var start = ( salutation ) ? 1 : 0 ;
62+ var end = ( suffix ) ? numWords - 1 : numWords ;
63+
64+ // concat the first name
65+ for ( i = start ; i < ( end - 1 ) ; i ++ ) {
66+ word = nameParts [ i ] ;
67+ // move on to parsing the last name if we find an indicator of a compound last name (Von, Van, etc)
68+ // we use i != start to allow for rare cases where an indicator is actually the first name (like "Von Fabella")
69+ if ( me . is_compound_lastName ( word ) && i != start ) {
70+ break ;
71+ }
72+ // is it a middle initial or part of their first name?
73+ // if we start off with an initial, we'll call it the first name
74+ if ( me . is_initial ( word ) ) {
75+ // is the initial the first word?
76+ if ( i == start ) {
77+ // if so, do a look-ahead to see if they go by their middle name
78+ // for ex: "R. Jason Smith" => "Jason Smith" & "R." is stored as an initial
79+ // but "R. J. Smith" => "R. Smith" and "J." is stored as an initial
80+ if ( me . is_initial ( nameParts [ i + 1 ] ) ) {
81+ firstName += " " + word . toUpperCase ( ) ;
82+ } else {
83+ initials += " " + word . toUpperCase ( ) ;
84+ }
85+ // otherwise, just go ahead and save the initial
86+ } else {
87+ initials += " " + word . toUpperCase ( ) ;
88+ }
89+ } else {
90+ firstName += " " + me . fix_case ( word ) ;
91+ }
92+ }
93+
94+ // check that we have more than 1 word in our string
95+ if ( ( end - start ) > 1 ) {
96+ // concat the last name
97+ for ( j = i ; j < end ; j ++ ) {
98+ lastName += " " + me . fix_case ( nameParts [ j ] ) ;
99+ }
100+ } else {
101+ // otherwise, single word strings are assumed to be first names
102+ firstName = me . fix_case ( nameParts [ i ] ) ;
103+ }
104+
105+ // return the various parts in an array
106+ name . salutation = ( salutation != false ) ? salutation : "" ;
107+ name . firstName = ( firstName != "" ) ? firstName . trim ( ) : "" ;
108+ name . initials = ( initials != "" ) ? initials . trim ( ) : "" ;
109+ name . lastName = ( lastName != "" ) ? lastName . trim ( ) : "" ;
110+ name . suffix = ( suffix != false ) ? suffix : "" ;
111+
112+ return name ;
113+ } ;
114+
115+ // detect and format standard salutations
116+ // I'm only considering english honorifics for now & not words like
117+ this . is_salutation = function ( word ) {
118+ // ignore periods
119+ word = word . replace ( "." , "" ) . toLowerCase ( ) ;
120+ // returns normalized values
121+ if ( word == "mr" || word == "master" || word == "mister" ) {
122+ return "Mr." ;
123+ } else if ( word == "mrs" ) {
124+ return "Mrs." ;
125+ } else if ( word == "miss" || word == "ms" ) {
126+ return "Ms." ;
127+ } else if ( word == "dr" ) {
128+ return "Dr." ;
129+ } else if ( word == "rev" ) {
130+ return "Rev." ;
131+ } else if ( word == "fr" ) {
132+ return "Fr." ;
133+ } else {
134+ return false ;
135+ }
136+ } ;
137+
138+ // detect and format common suffixes
139+ this . is_suffix = function ( word ) {
140+ // ignore periods
141+ word = word . replace ( "." , "" ) . toLowerCase ( ) ;
142+ // these are some common suffixes - what am I missing?
143+ var suffixArray = [ 'I' , 'II' , 'III' , 'IV' , 'V' , 'Senior' , 'Junior' , 'Jr' , 'Sr' , 'PhD' , 'APR' , 'RPh' , 'PE' , 'MD' , 'MA' , 'DMD' , 'CME' ] ;
144+ for ( var i = 0 ; i < suffixArray . length ; i ++ ) {
145+ if ( suffixArray [ i ] . toLowerCase ( ) == word ) {
146+ return suffixArray [ i ] ;
147+ }
148+ }
149+ return false ;
150+ } ;
151+
152+ // detect compound last names like "Von Fange"
153+ this . is_compound_lastName = function ( word ) {
154+ word = word . toLowerCase ( ) ;
155+ // these are some common prefixes that identify a compound last names - what am I missing?
156+ var words = [ 'vere' , 'von' , 'van' , 'de' , 'del' , 'della' , 'di' , 'da' , 'pietro' , 'vanden' , 'du' , 'st.' , 'st' , 'la' , 'lo' , 'ter' ] ;
157+ return words . in_array ( word ) ;
158+ } ;
159+
160+ // single letter, possibly followed by a period
161+ this . is_initial = function ( word ) {
162+ // ignore periods
163+ word = word . replace ( "." , "" ) ;
164+ return ( word . length == 1 ) ;
165+ } ;
165166
166- // detect mixed case words like "McDonald"
167- // returns false if the string is all one case
168- this . is_camel_case = function ( word ) {
169- var ucReg = / | [ A - Z ] + | s / ;
170- var lcReg = / | [ a - z ] + | s / ;
171- return ( word . match ( ucReg ) != null && word . match ( lcReg ) != null ) ;
172- }
173-
174- // ucfirst words split by dashes or periods
175- // ucfirst all upper/lower strings, but leave camelcase words alone
176- this . fix_case = function ( word ) {
177- // uppercase words split by dashes, like "Kimura-Fay"
178- word = me . safe_ucfirst ( "-" , word ) ;
179- // uppercase words split by periods, like "J.P."
180- word = me . safe_ucfirst ( "." , word ) ;
181- return word ;
182- }
167+ // detect mixed case words like "McDonald"
168+ // returns false if the string is all one case
169+ this . is_camel_case = function ( word ) {
170+ var ucReg = / | [ A - Z ] + | s / ;
171+ var lcReg = / | [ a - z ] + | s / ;
172+ return ( word . match ( ucReg ) != null && word . match ( lcReg ) != null ) ;
173+ } ;
174+
175+ // ucfirst words split by dashes or periods
176+ // ucfirst all upper/lower strings, but leave camelcase words alone
177+ this . fix_case = function ( word ) {
178+ // uppercase words split by dashes, like "Kimura-Fay"
179+ word = me . safe_ucfirst ( "-" , word ) ;
180+ // uppercase words split by periods, like "J.P."
181+ word = me . safe_ucfirst ( "." , word ) ;
182+ return word ;
183+ } ;
183184
184- // helper this.for fix_case
185- this . safe_ucfirst = function ( seperator , word ) {
186- var words = [ ] ;
187- // uppercase words split by the seperator (ex. dashes or periods)
188- parts = word . split ( seperator ) ;
189- for ( var i = 0 ; i < parts . length ; i ++ ) {
190- var thisWord = parts [ i ] ;
191- words [ i ] = ( me . is_camel_case ( thisWord ) ) ? thisWord : thisWord . ucfirst . toLowerCase ( ) ;
192- }
193- return words . implode ( seperator ) ;
194- }
185+ // helper this.for fix_case
186+ this . safe_ucfirst = function ( seperator , word ) {
187+ var words = [ ] ;
188+ // uppercase words split by the seperator (ex. dashes or periods)
189+ parts = word . split ( seperator ) ;
190+ for ( var i = 0 ; i < parts . length ; i ++ ) {
191+ var thisWord = parts [ i ] ;
192+ words [ i ] = ( me . is_camel_case ( thisWord ) ) ? thisWord : thisWord . ucfirst . toLowerCase ( ) ;
193+ }
194+ return words . implode ( seperator ) ;
195+ } ;
195196}
0 commit comments