Skip to content

Instantly share code, notes, and snippets.

@silentmatt
Created June 17, 2009 18:20
Show Gist options
  • Save silentmatt/131402 to your computer and use it in GitHub Desktop.
Save silentmatt/131402 to your computer and use it in GitHub Desktop.
JavaScript class to represent and format names
var Name = (function() {
function Name(prefix, first, middle, last, suffix, called) {
this.prefix = prefix || "";
this.first = first || "";
this.middle = middle || "";
this.last = last || "";
this.suffix = suffix || "";
this.called = called || "";
}
function capitalize(s) {
return s.charAt(0).toUpperCase() + s.substring(1);
}
function addSetter(cls, name, fn) {
cls.prototype["set" + capitalize(name)] = fn || function(value) {
this[name] = value;
return this;
};
// Define a JS setter if it's supported and needed
if (fn && cls.prototype.__defineGetter__) {
cls.prototype.__defineGetter__(name, fn);
}
}
function addGetter(cls, name, fn) {
cls.prototype["get" + capitalize(name)] = fn;
if (cls.prototype.__defineGetter__) {
cls.prototype.__defineGetter__(name, fn);
}
}
// Chainable setters
addSetter(Name, "prefix");
addSetter(Name, "prefix");
addSetter(Name, "first");
addSetter(Name, "middle");
addSetter(Name, "last");
addSetter(Name, "suffix");
addSetter(Name, "called");
// Common name formats
addGetter(Name, "fullName", function() {
return this.toString("PFMLS");
});
addGetter(Name, "lastFirst", function() {
return this.toString("L,F");
//return (this.last + ", " + this.first).replace(/(^, )|(, $)/, "");
});
addGetter(Name, "lastFirstMiddle", function() {
return this.toString("L,FM");
});
addGetter(Name, "firstLast", function() {
return this.toString("FL");
});
addGetter(Name, "firstMiddleLast", function() {
return this.toString("FML");
});
addGetter(Name, "informal", function() {
return this.toString("CL");
});
// Initials
addGetter(Name, "firstInitial", function() {
return (this.first || "").substring(0, 1);
});
addGetter(Name, "middleInitial", function() {
return (this.middle || "").substring(0, 1);
});
addGetter(Name, "lastInitial", function() {
return (this.last || "").substring(0, 1);
});
addGetter(Name, "monogram", function() {
return this.getFirstInitial() + this.getMiddleInitial() + this.getLastInitial();
});
// Names match if all the common parts match
Name.prototype.matches = function(other) {
if (this.prefix && other.prefix) {
if (this.prefix != other.prefix) {
return false;
}
}
if (this.first && other.first) {
if (this.first != other.first) {
return false;
}
}
if (this.middle && other.middle) {
if (this.middle != other.middle) {
return false;
}
}
if (this.last && other.last) {
if (this.last != other.last) {
return false;
}
}
if (this.suffix && other.suffix) {
if (this.suffix != other.suffix) {
return false;
}
}
return true;
}
// Spaces are automatically inserted between parts where it (hopefully) makes sense
// Leading and trailing spaces and commas, as well as empty quotes, braces, etc. are stripped.
// Multiple spaces are squeezed into a single space.
//
// Default format is "PFMLS" - the same as getFullName()
//
// Format characters:
// P - Prefix
// N - Nickname (called)
// C - Called By (called or first)
// F,f - First / first initial
// M,m - Middle / middle initial
// L,l - Last / last initial
// S - Suffix
// (,[,{," - Literal (no implied space after)
// ),],} - Literal
// .,comma - Literal (skipped if the last part was missing)
// space - Force a space (useful after an end quote)
Name.prototype.toString = function(fmt) {
fmt = fmt || "PFMLS";
var parts = [];
var sep = "";
var hadLast = false;
function pushPart(value) {
hadLast = false;
if (value) {
parts.push(sep + value);
sep = " ";
hadLast = true;
}
}
for (var i = 0; i < fmt.length; i++) {
var c = fmt.charAt(i);
switch (c) {
case ',':
case '.':
if (hadLast) {
parts.push(c);
sep = " ";
}
break;
case ' ':
parts.push(" ");
sep = "";
break;
case 'P':
pushPart(this.prefix);
break;
case 'N':
pushPart(this.called);
break;
case 'C':
pushPart(this.called || this.first);
break;
case 'F':
pushPart(this.first);
break;
case 'f':
pushPart(this.getFirstInitial());
break;
case 'M':
pushPart(this.middle);
break;
case 'm':
pushPart(this.getMiddleInitial());
break;
case 'L':
pushPart(this.last);
break;
case 'l':
pushPart(this.getLastInitial());
break;
case 'S':
pushPart(this.suffix);
break;
case '"':
parts.push('"');
sep = "";
break;
case '{':
case '[':
case '(':
parts.push(sep + c);
sep = "";
break;
case '}':
case ']':
case ')':
parts.push(c);
sep = " ";
break;
default:
throw new Error("Invalid format character: '" + c + "'");
}
}
return parts.join("").replace(/(^[, ]+)|([, ]+$)|(\(\))|("")|(\[\])|({})/g, "").replace(/ +/g, " ");
}
Name.test = function() {
function expect(actual, expected) {
if (expected !== actual) {
print("Expected <" + expected + "> but got <" + actual + ">");
return false;
}
return true;
}
var me = new Name();
me.setFirst("Matthew").setLast("Crumley").setCalled("M@");
expect(me.first, "Matthew");
expect(me.last, "Crumley");
expect(me.middle, "");
expect(me.firstInitial, "M");
expect(me.lastInitial, "C");
expect(me.monogram, "MC");
expect(me.toString(), "Matthew Crumley");
expect(me.toString('F "N" L'), 'Matthew "M@" Crumley');
expect(me.toString('L,F'), 'Crumley, Matthew');
me.called = "";
expect(me.toString('L,N'), 'Crumley');
expect(me.toString('L,C'), 'Crumley, Matthew');
}
return Name;
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment