Last active
January 9, 2023 16:06
-
-
Save benjamincharity/ac35ac288552feee349a to your computer and use it in GitHub Desktop.
Create a downloadable file of VCARD formatted address for iOS from a JSON array.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var contacts = | |
[ | |
{ | |
"notes": [ | |
{ | |
"description": "Fugiat aute pariatur excepteur elit." | |
} | |
], | |
"tels": [ | |
{ | |
"number": "(489) 555-8141", | |
"params": { | |
"types": [ | |
"cell" | |
] | |
} | |
}, | |
{ | |
"number": "(346) 555-2284", | |
"params": { | |
"types": [ | |
"work" | |
] | |
} | |
} | |
], | |
"urls": [ | |
{ | |
"uri": "http://www.dolorenon.com" | |
}, | |
{ | |
"uri": "http://www.laboreelit.com", | |
"group": "item1" | |
} | |
], | |
"emails": [ | |
{ | |
"address": "Mccarthy.Cash@gmail9999.com", | |
"params": { | |
"types": [ | |
"internet" | |
] | |
} | |
} | |
], | |
"n": { | |
"givens": "Abigail", | |
"families": "Harvey" | |
}, | |
"fn": { | |
"name": "Estrada Rutledge" | |
} | |
}, | |
{ | |
"notes": [ | |
{ | |
"description": "Fugiat aute pariatur excepteur elit." | |
} | |
], | |
"tels": [ | |
{ | |
"number": "(489) 555-8141", | |
"params": { | |
"types": [ | |
"cell" | |
] | |
} | |
}, | |
{ | |
"number": "(346) 555-2284", | |
"params": { | |
"types": [ | |
"work" | |
] | |
} | |
} | |
], | |
"urls": [ | |
{ | |
"uri": "http://www.dolorenon.com" | |
}, | |
{ | |
"uri": "http://www.laboreelit.com", | |
"group": "item1" | |
} | |
], | |
"emails": [ | |
{ | |
"address": "Mccarthy.Cash@gmail9999.com", | |
"params": { | |
"types": [ | |
"internet" | |
] | |
} | |
} | |
], | |
"n": { | |
"givens": "Janie", | |
"families": "Carrillo" | |
}, | |
"fn": { | |
"name": "Reilly Oneal" | |
} | |
} | |
] | |
; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<link rel="stylesheet" href="style.css"> | |
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.15/angular.min.js"></script> | |
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/3.7.0/lodash.min.js"></script> | |
<script src="contacts.js"></script> | |
<script src="jsontovcard.js"></script> | |
<script src="script.js"></script> | |
</head> | |
<body ng-app="app" ng-controller="MainCtrl"> | |
<h2>Create a downloadable vcf file.</h2> | |
<button data-ng-click="createLink()">Create Link</button> | |
<br> | |
<br> | |
<a download="contacts.vcf" id="downloadLink">Download</a> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var VCARD; | |
VCARD = (function() { | |
var generate_adr, generate_bday, generate_categories, generate_class, generate_email, generate_fn, generate_geo, generate_key, generate_label, generate_logo, generate_mailer, generate_n, generate_nickname, generate_note, generate_org, generate_photo, generate_prodid, generate_rev, generate_role, generate_sort_string, generate_sound, generate_tel, generate_title, generate_tz, generate_uid, generate_url, m, parse_adr, parse_bday, parse_categories, parse_class, parse_email, parse_fn, parse_geo, parse_key, parse_label, parse_line, parse_logo, parse_mailer, parse_n, parse_nickname, parse_note, parse_org, parse_params, parse_photo, parse_prodid, parse_rev, parse_role, parse_sort_string, parse_sound, parse_tel, parse_title, parse_tz, parse_uid, parse_url; | |
m = {}; | |
m.generate = function(json) { | |
var adr, email, i, j, k, klass, l, label, len, len1, len10, len11, len12, len2, len3, len4, len5, len6, len7, len8, len9, logo, note, o, org, p, photo, q, r, ref, ref1, ref10, ref11, ref12, ref2, ref3, ref4, ref5, ref6, ref7, ref8, ref9, role, s, sound, string, t, tel, title, u, url, v, w, x, y; | |
string = ""; | |
string += "BEGIN:VCARD\r\n"; | |
for (k in json) { | |
v = json[k]; | |
switch (k) { | |
case "version": | |
string += "VERSION:" + v + "\r\n"; | |
break; | |
case "fn": | |
string += generate_fn(json.fn); | |
break; | |
case "n": | |
string += generate_n(json.n); | |
break; | |
case "nickname": | |
string += generate_nickname(json.nickname); | |
break; | |
case "photos": | |
ref = json.photos; | |
for (i = 0, len = ref.length; i < len; i++) { | |
photo = ref[i]; | |
string += generate_photo(photo); | |
} | |
break; | |
case "bday": | |
string += generate_bday(json.bday); | |
break; | |
case "adrs": | |
ref1 = json.adrs; | |
for (j = 0, len1 = ref1.length; j < len1; j++) { | |
adr = ref1[j]; | |
string += generate_adr(adr); | |
} | |
break; | |
case "labels": | |
ref2 = json.labels; | |
for (l = 0, len2 = ref2.length; l < len2; l++) { | |
label = ref2[l]; | |
string += generate_label(label); | |
} | |
break; | |
case "tels": | |
ref3 = json.tels; | |
for (o = 0, len3 = ref3.length; o < len3; o++) { | |
tel = ref3[o]; | |
string += generate_tel(tel); | |
} | |
break; | |
case "emails": | |
ref4 = json.emails; | |
for (p = 0, len4 = ref4.length; p < len4; p++) { | |
email = ref4[p]; | |
string += generate_email(email); | |
} | |
break; | |
case "mailer": | |
string += generate_mailer(json.mailer); | |
break; | |
case "tz": | |
string += generate_tz(json.tz); | |
break; | |
case "geo": | |
string += generate_geo(json.geo); | |
break; | |
case "titles": | |
ref5 = json.titles; | |
for (q = 0, len5 = ref5.length; q < len5; q++) { | |
title = ref5[q]; | |
string += generate_title(title); | |
} | |
break; | |
case "roles": | |
ref6 = json.roles; | |
for (r = 0, len6 = ref6.length; r < len6; r++) { | |
role = ref6[r]; | |
string += generate_role(role); | |
} | |
break; | |
case "logos": | |
ref7 = json.logos; | |
for (s = 0, len7 = ref7.length; s < len7; s++) { | |
logo = ref7[s]; | |
string += generate_logo(logo); | |
} | |
break; | |
case "orgs": | |
ref8 = json.orgs; | |
for (t = 0, len8 = ref8.length; t < len8; t++) { | |
org = ref8[t]; | |
string += generate_org(org); | |
} | |
break; | |
case "categories": | |
string += generate_categories(json.categories); | |
break; | |
case "notes": | |
ref9 = json.notes; | |
for (u = 0, len9 = ref9.length; u < len9; u++) { | |
note = ref9[u]; | |
string += generate_note(note); | |
} | |
break; | |
case "prodid": | |
string += generate_prodid(json.prodid); | |
break; | |
case "rev": | |
string += generate_rev(json.rev); | |
break; | |
case "sort_string": | |
string += generate_sort_string(json.sort_string); | |
break; | |
case "sounds": | |
ref10 = json.sounds; | |
for (w = 0, len10 = ref10.length; w < len10; w++) { | |
sound = ref10[w]; | |
string += generate_sound(sound); | |
} | |
break; | |
case "uid": | |
string += generate_uid(json.uid); | |
break; | |
case "urls": | |
ref11 = json.urls; | |
for (x = 0, len11 = ref11.length; x < len11; x++) { | |
url = ref11[x]; | |
string += generate_url(url); | |
} | |
break; | |
case "classes": | |
ref12 = json.classes; | |
for (y = 0, len12 = ref12.length; y < len12; y++) { | |
klass = ref12[y]; | |
string += generate_class(klass); | |
} | |
break; | |
case "key": | |
string += generate_key(json.key); | |
} | |
} | |
return string += "END:VCARD"; | |
}; | |
m.parse = function(string) { | |
var i, j, len, len1, line, lines, newline, newlines, stringlines; | |
stringlines = string.split("\r\n"); | |
newlines = []; | |
for (i = 0, len = stringlines.length; i < len; i++) { | |
line = stringlines[i]; | |
if (!line.match(/BEGIN:VCARD|END:VCARD/)) { | |
newlines.push(parse_line(line)); | |
} | |
} | |
lines = {}; | |
for (j = 0, len1 = newlines.length; j < len1; j++) { | |
newline = newlines[j]; | |
switch (newline.name) { | |
case "VERSION": | |
lines.version = newline.value; | |
break; | |
case "FN": | |
lines.fn = parse_fn(newline); | |
break; | |
case "N": | |
lines.n = parse_n(newline); | |
break; | |
case "NICKNAME": | |
lines.nickname = parse_nickname(newline); | |
break; | |
case "PHOTO": | |
lines.photos || (lines.photos = []); | |
lines.photos.push(parse_photo(newline)); | |
break; | |
case "BDAY": | |
lines.bday = parse_bday(newline); | |
break; | |
case "ADR": | |
lines.adrs || (lines.adrs = []); | |
lines.adrs.push(parse_adr(newline)); | |
break; | |
case "LABEL": | |
lines.labels || (lines.labels = []); | |
lines.labels.push(parse_label(newline)); | |
break; | |
case "TEL": | |
lines.tels || (lines.tels = []); | |
lines.tels.push(parse_tel(newline)); | |
break; | |
case "EMAIL": | |
lines.emails || (lines.emails = []); | |
lines.emails.push(parse_email(newline)); | |
break; | |
case "MAILER": | |
lines.mailer = parse_mailer(newline); | |
break; | |
case "TZ": | |
lines.tz = parse_tz(newline); | |
break; | |
case "GEO": | |
lines.geo = parse_geo(newline); | |
break; | |
case "TITLE": | |
lines.titles || (lines.titles = []); | |
lines.titles.push(parse_title(newline)); | |
break; | |
case "ROLE": | |
lines.roles || (lines.roles = []); | |
lines.roles.push(parse_role(newline)); | |
break; | |
case "LOGO": | |
lines.logos || (lines.logos = []); | |
lines.logos.push(parse_logo(newline)); | |
break; | |
case "ORG": | |
lines.orgs || (lines.orgs = []); | |
lines.orgs.push(parse_org(newline)); | |
break; | |
case "CATEGORIES": | |
lines.categories = parse_categories(newline); | |
break; | |
case "NOTE": | |
lines.notes || (lines.notes = []); | |
lines.notes.push(parse_note(newline)); | |
break; | |
case "PRODID": | |
lines.prodid = parse_prodid(newline); | |
break; | |
case "REV": | |
lines.rev = parse_rev(newline); | |
break; | |
case "SORT-STRING": | |
lines.sort_string = parse_sort_string(newline); | |
break; | |
case "SOUND": | |
lines.sounds || (lines.sounds = []); | |
lines.sounds.push(parse_sound(newline)); | |
break; | |
case "UID": | |
lines.uid = parse_uid(newline); | |
break; | |
case "URL": | |
lines.urls || (lines.urls = []); | |
lines.urls.push(parse_url(newline)); | |
break; | |
case "CLASS": | |
lines.classes || (lines.classes = []); | |
lines.classes.push(parse_class(newline)); | |
break; | |
case "KEY": | |
lines.key = parse_key(newline); | |
} | |
} | |
return lines; | |
}; | |
parse_line = function(string) { | |
var json, res; | |
json = {}; | |
res = string.match(/^(?:(\w+)\.)?([a-zA-Z-_]+)((?:;[a-zA-Z0-9-_]+=[a-zA-Z0-9-,]+)+)?:((?:.|\n)+)$/); | |
if (res[1]) { | |
json.group = res[1]; | |
} | |
json.name = res[2]; | |
if (res[3]) { | |
json.params = parse_params(res[3]); | |
} | |
json.value = res[4]; | |
return json; | |
}; | |
parse_params = function(string) { | |
var i, json, k, len, param, params, v; | |
params = string.split(";"); | |
params.shift(); | |
json = {}; | |
for (i = 0, len = params.length; i < len; i++) { | |
param = params[i]; | |
k = param.split("=")[0]; | |
v = param.split("=")[1]; | |
json[k.toLowerCase()] = v.toLowerCase(); | |
} | |
return json; | |
}; | |
parse_fn = function(json) { | |
var fn, k, ref, v; | |
fn = {}; | |
if (json.group) { | |
fn.group = json.group; | |
} | |
if (json.params) { | |
ref = json.params; | |
for (k in ref) { | |
v = ref[k]; | |
fn.params || (fn.params = {}); | |
if (k.match(/value|language|x-\w+/i)) { | |
fn.params[k] = v; | |
} | |
} | |
} | |
fn.name = json.value; | |
return fn; | |
}; | |
parse_n = function(json) { | |
var k, n, names, ref, v; | |
n = {}; | |
if (json.group) { | |
n.group = json.group; | |
} | |
if (json.params) { | |
ref = json.params; | |
for (k in ref) { | |
v = ref[k]; | |
n.params || (n.params = {}); | |
if (k.match(/value|language|x-\w+/i)) { | |
n.params[k] = v; | |
} | |
} | |
} | |
names = json.value.split(';'); | |
if (names[0]) { | |
n.families = names[0].split(','); | |
} | |
if (names[1]) { | |
n.givens = names[1].split(','); | |
} | |
if (names[2]) { | |
n.middles = names[2].split(','); | |
} | |
if (names[3]) { | |
n.prefixes = names[3].split(','); | |
} | |
if (names[4]) { | |
n.suffixes = names[4].split(','); | |
} | |
return n; | |
}; | |
parse_nickname = function(json) { | |
var k, names, nickname, ref, v; | |
nickname = {}; | |
if (json.group) { | |
nickname.group = json.group; | |
} | |
if (json.params) { | |
ref = json.params; | |
for (k in ref) { | |
v = ref[k]; | |
nickname.params || (nickname.params = {}); | |
if (k.match(/value|language|x-\w+/i)) { | |
nickname.params[k] = v; | |
} | |
} | |
} | |
names = json.value.split(','); | |
nickname.names = names; | |
return nickname; | |
}; | |
parse_photo = function(json) { | |
var k, photo, ref, v; | |
photo = {}; | |
if (json.group) { | |
photo.group = json.group; | |
} | |
if (json.params) { | |
ref = json.params; | |
for (k in ref) { | |
v = ref[k]; | |
photo.params || (photo.params = {}); | |
if (k.match(/value|encoding|type/i)) { | |
photo.params[k] = v; | |
} | |
} | |
} | |
photo.image = json.value; | |
return photo; | |
}; | |
parse_bday = function(json) { | |
var bday, k, ref, res, v; | |
res = json.value.match(/^(\d{4})-(\d{2})-(\d{2})(?:T(\d{2}):(\d{2}):(\d{2})Z)?$/); | |
bday = {}; | |
if (json.group) { | |
bday.group = json.group; | |
} | |
if (json.params) { | |
ref = json.params; | |
for (k in ref) { | |
v = ref[k]; | |
bday.params || (bday.params = {}); | |
if (k.match(/value/i)) { | |
bday.params[k] = v; | |
} | |
} | |
} | |
bday.year = res[1]; | |
bday.month = res[2]; | |
bday.day = res[3]; | |
if (json.params && json.params.value && json.params.value.match(/date-time/i)) { | |
if (res[4]) { | |
bday.hour = res[4]; | |
} | |
if (res[5]) { | |
bday.minute = res[5]; | |
} | |
if (res[6]) { | |
bday.second = res[6]; | |
} | |
} | |
return bday; | |
}; | |
parse_adr = function(json) { | |
var a, adr, arr, i, k, len, ref, res, v; | |
adr = {}; | |
if (json.group) { | |
adr.group = json.group; | |
} | |
if (json.params) { | |
ref = json.params; | |
for (k in ref) { | |
v = ref[k]; | |
adr.params || (adr.params = {}); | |
if (k.match(/value|language|x-\w+/i)) { | |
adr.params[k] = v; | |
} | |
if (k.match("type")) { | |
adr.params.types || (adr.params.types = []); | |
if (v.match(/,/)) { | |
arr = v.split(','); | |
for (i = 0, len = arr.length; i < len; i++) { | |
a = arr[i]; | |
adr.params.types.push(a); | |
} | |
} else { | |
adr.params.types.push(v); | |
} | |
} | |
} | |
} | |
res = json.value.split(';'); | |
if (res[0]) { | |
adr.pobox = res[0]; | |
} | |
if (res[1]) { | |
adr.extended = res[1]; | |
} | |
if (res[2]) { | |
adr.street = res[2]; | |
} | |
if (res[3]) { | |
adr.locality = res[3]; | |
} | |
if (res[4]) { | |
adr.region = res[4]; | |
} | |
if (res[5]) { | |
adr.code = res[5]; | |
} | |
if (res[6]) { | |
adr.country = res[6]; | |
} | |
return adr; | |
}; | |
parse_label = function(json) { | |
var a, arr, i, k, label, len, ref, v; | |
label = {}; | |
if (json.group) { | |
label.group = json.group; | |
} | |
if (json.params) { | |
ref = json.params; | |
for (k in ref) { | |
v = ref[k]; | |
label.params || (label.params = {}); | |
if (k.match(/value|language|x-\w+/i)) { | |
label.params[k] = v; | |
} | |
if (k.match("type")) { | |
label.params.types || (label.params.types = []); | |
if (v.match(/,/)) { | |
arr = v.split(','); | |
for (i = 0, len = arr.length; i < len; i++) { | |
a = arr[i]; | |
label.params.types.push(a); | |
} | |
} else { | |
label.params.types.push(v); | |
} | |
} | |
} | |
} | |
label.address = json.value; | |
return label; | |
}; | |
parse_tel = function(json) { | |
var a, arr, i, k, len, ref, tel, v; | |
tel = {}; | |
if (json.group) { | |
tel.group = json.group; | |
} | |
if (json.params) { | |
ref = json.params; | |
for (k in ref) { | |
v = ref[k]; | |
if (k.match("type")) { | |
tel.params || (tel.params = {}); | |
tel.params.types || (tel.params.types = []); | |
if (v.match(/,/)) { | |
arr = v.split(','); | |
for (i = 0, len = arr.length; i < len; i++) { | |
a = arr[i]; | |
tel.params.types.push(a); | |
} | |
} else { | |
tel.params.types.push(v); | |
} | |
} | |
} | |
} | |
tel.number = json.value; | |
return tel; | |
}; | |
parse_email = function(json) { | |
var a, arr, email, i, k, len, ref, v; | |
email = {}; | |
if (json.group) { | |
email.group = json.group; | |
} | |
if (json.params) { | |
ref = json.params; | |
for (k in ref) { | |
v = ref[k]; | |
if (k.match("type")) { | |
email.params || (email.params = {}); | |
email.params.types || (email.params.types = []); | |
if (v.match(/,/)) { | |
arr = v.split(','); | |
for (i = 0, len = arr.length; i < len; i++) { | |
a = arr[i]; | |
email.params.types.push(a); | |
} | |
} else { | |
email.params.types.push(v); | |
} | |
} | |
} | |
} | |
email.address = json.value; | |
return email; | |
}; | |
parse_mailer = function(json) { | |
var k, mailer, ref, v; | |
mailer = {}; | |
if (json.group) { | |
mailer.group = json.group; | |
} | |
if (json.params) { | |
ref = json.params; | |
for (k in ref) { | |
v = ref[k]; | |
mailer.params || (mailer.params = {}); | |
if (k.match(/value|language|x-\w+/i)) { | |
mailer.params[k] = v; | |
} | |
} | |
} | |
mailer.name = json.value; | |
return mailer; | |
}; | |
parse_tz = function(json) { | |
var k, ref, tz, v; | |
tz = {}; | |
if (json.group) { | |
tz.group = json.group; | |
} | |
if (json.params) { | |
ref = json.params; | |
for (k in ref) { | |
v = ref[k]; | |
tz.params || (tz.params = {}); | |
if (k.match(/value/i)) { | |
tz.params[k] = v; | |
} | |
} | |
} | |
tz.zone = json.value; | |
return tz; | |
}; | |
parse_geo = function(json) { | |
var geo, res; | |
geo = {}; | |
if (json.group) { | |
geo.group = json.group; | |
} | |
res = json.value.split(';'); | |
geo.latitude = res[0]; | |
geo.longitude = res[1]; | |
return geo; | |
}; | |
parse_title = function(json) { | |
var k, ref, title, v; | |
title = {}; | |
if (json.group) { | |
title.group = json.group; | |
} | |
if (json.params) { | |
ref = json.params; | |
for (k in ref) { | |
v = ref[k]; | |
title.params || (title.params = {}); | |
if (k.match(/value|language|x-\w+/i)) { | |
title.params[k] = v; | |
} | |
} | |
} | |
title.name = json.value; | |
return title; | |
}; | |
parse_role = function(json) { | |
var k, ref, role, v; | |
role = {}; | |
if (json.group) { | |
role.group = json.group; | |
} | |
if (json.params) { | |
ref = json.params; | |
for (k in ref) { | |
v = ref[k]; | |
role.params || (role.params = {}); | |
if (k.match(/value|language|x-\w+/i)) { | |
role.params[k] = v; | |
} | |
} | |
} | |
role.name = json.value; | |
return role; | |
}; | |
parse_logo = function(json) { | |
var k, logo, ref, v; | |
logo = {}; | |
if (json.group) { | |
logo.group = json.group; | |
} | |
if (json.params) { | |
ref = json.params; | |
for (k in ref) { | |
v = ref[k]; | |
logo.params || (logo.params = {}); | |
if (k.match(/value|encoding|type/i)) { | |
logo.params[k] = v; | |
} | |
} | |
} | |
logo.image = json.value; | |
return logo; | |
}; | |
parse_org = function(json) { | |
var k, org, ref, res, v; | |
org = {}; | |
if (json.group) { | |
org.group = json.group; | |
} | |
if (json.params) { | |
ref = json.params; | |
for (k in ref) { | |
v = ref[k]; | |
org.params || (org.params = {}); | |
if (k.match(/value|language|x-\w+/i)) { | |
org.params[k] = v; | |
} | |
} | |
} | |
res = json.value.split(';'); | |
if (res[0]) { | |
org.name = res[0]; | |
} | |
if (res[1]) { | |
org.unit = res[1]; | |
} | |
if (res[2]) { | |
org.unit2 = res[2]; | |
} | |
return org; | |
}; | |
parse_categories = function(json) { | |
var categories, k, ref, v; | |
categories = {}; | |
if (json.group) { | |
categories.group = json.group; | |
} | |
if (json.params) { | |
ref = json.params; | |
for (k in ref) { | |
v = ref[k]; | |
categories.params || (categories.params = {}); | |
if (k.match(/value|language|x-\w+/i)) { | |
categories.params[k] = v; | |
} | |
} | |
} | |
categories.names = json.value.split(','); | |
return categories; | |
}; | |
parse_note = function(json) { | |
var k, note, ref, v; | |
note = {}; | |
if (json.group) { | |
note.group = json.group; | |
} | |
if (json.params) { | |
ref = json.params; | |
for (k in ref) { | |
v = ref[k]; | |
note.params || (note.params = {}); | |
if (k.match(/value|language|x-\w+/i)) { | |
note.params[k] = v; | |
} | |
} | |
} | |
note.description = json.value; | |
return note; | |
}; | |
parse_prodid = function(json) { | |
var prodid; | |
prodid = {}; | |
if (json.group) { | |
prodid.group = json.group; | |
} | |
prodid.id = json.value; | |
return prodid; | |
}; | |
parse_rev = function(json) { | |
var k, ref, res, rev, v; | |
res = json.value.match(/^(\d{4})-(\d{2})-(\d{2})(?:T(\d{2}):(\d{2}):(\d{2})Z)?$/); | |
rev = {}; | |
if (json.group) { | |
rev.group = json.group; | |
} | |
if (json.params) { | |
ref = json.params; | |
for (k in ref) { | |
v = ref[k]; | |
rev.params || (rev.params = {}); | |
if (k.match(/value/i)) { | |
rev.params[k] = v; | |
} | |
} | |
} | |
rev.year = res[1]; | |
rev.month = res[2]; | |
rev.day = res[3]; | |
if (res[4]) { | |
rev.hour = res[4]; | |
} | |
if (res[5]) { | |
rev.minute = res[5]; | |
} | |
if (res[6]) { | |
rev.second = res[6]; | |
} | |
return rev; | |
}; | |
parse_sort_string = function(json) { | |
var k, ref, sort_string, v; | |
sort_string = {}; | |
if (json.group) { | |
sort_string.group = json.group; | |
} | |
if (json.params) { | |
ref = json.params; | |
for (k in ref) { | |
v = ref[k]; | |
sort_string.params || (sort_string.params = {}); | |
if (k.match(/value|language|x-\w+/i)) { | |
sort_string.params[k] = v; | |
} | |
} | |
} | |
sort_string.name = json.value; | |
return sort_string; | |
}; | |
parse_sound = function(json) { | |
var k, ref, sound, v; | |
sound = {}; | |
if (json.group) { | |
sound.group = json.group; | |
} | |
if (json.params) { | |
ref = json.params; | |
for (k in ref) { | |
v = ref[k]; | |
sound.params || (sound.params = {}); | |
if (k.match(/value|encoding|type/i)) { | |
sound.params[k] = v; | |
} | |
} | |
} | |
sound.value = json.value; | |
return sound; | |
}; | |
parse_uid = function(json) { | |
var k, ref, uid, v; | |
uid = {}; | |
if (json.group) { | |
uid.group = json.group; | |
} | |
if (json.params) { | |
ref = json.params; | |
for (k in ref) { | |
v = ref[k]; | |
uid.params || (uid.params = {}); | |
if (k.match(/type/i)) { | |
uid.params[k] = v; | |
} | |
} | |
} | |
uid.id = json.value; | |
return uid; | |
}; | |
parse_url = function(json) { | |
var url; | |
url = {}; | |
if (json.group) { | |
url.group = json.group; | |
} | |
url.uri = json.value; | |
return url; | |
}; | |
parse_class = function(json) { | |
var klass; | |
klass = {}; | |
if (json.group) { | |
klass.group = json.group; | |
} | |
klass.name = json.value.toLowerCase(); | |
return klass; | |
}; | |
parse_key = function(json) { | |
var k, key, ref, v; | |
key = {}; | |
if (json.group) { | |
key.group = json.group; | |
} | |
if (json.params) { | |
ref = json.params; | |
for (k in ref) { | |
v = ref[k]; | |
key.params || (key.params = {}); | |
if (k.match(/value|encoding|type/i)) { | |
key.params[k] = v; | |
} | |
} | |
} | |
key.value = json.value; | |
return key; | |
}; | |
generate_fn = function(json) { | |
var k, ref, string, v; | |
string = ""; | |
if (json.group) { | |
string += json.group + "."; | |
} | |
string += "FN"; | |
if (json.params) { | |
ref = json.params; | |
for (k in ref) { | |
v = ref[k]; | |
if (k.match(/value|language|x-\w+/i)) { | |
string += ";" + (k.toUpperCase()) + "=" + (v.toUpperCase()); | |
} | |
} | |
} | |
string += ":" + json.name + "\r\n"; | |
return string; | |
}; | |
generate_n = function(json) { | |
var k, ref, string, v; | |
string = ""; | |
if (json.group) { | |
string += json.group + "."; | |
} | |
string += "N"; | |
if (json.params) { | |
ref = json.params; | |
for (k in ref) { | |
v = ref[k]; | |
if (k.match(/value|language|x-\w+/i)) { | |
string += ";" + (k.toUpperCase()) + "=" + (v.toUpperCase()); | |
} | |
} | |
} | |
string += json.families ? ":" + json.families + ";" : ":;"; | |
string += json.givens ? json.givens + ";" : ";"; | |
string += json.middles ? (json.middles.join(',')) + ";" : ";"; | |
string += json.prefixes ? (json.prefixes.join(',')) + ";" : ";"; | |
string += json.suffixes ? (json.suffixes.join(',')) + "\r\n" : "\r\n"; | |
return string; | |
}; | |
generate_nickname = function(json) { | |
var k, ref, string, v; | |
string = ""; | |
if (json.group) { | |
string += json.group + "."; | |
} | |
string += "NICKNAME"; | |
if (json.params) { | |
ref = json.params; | |
for (k in ref) { | |
v = ref[k]; | |
if (k.match(/value|language|x-\w+/i)) { | |
string += ";" + (k.toUpperCase()) + "=" + (v.toUpperCase()); | |
} | |
} | |
} | |
string += ":" + (json.names.join(',')) + "\r\n"; | |
return string; | |
}; | |
generate_photo = function(json) { | |
var k, ref, string, v; | |
string = ""; | |
if (json.group) { | |
string += json.group + "."; | |
} | |
string += "PHOTO"; | |
if (json.params) { | |
ref = json.params; | |
for (k in ref) { | |
v = ref[k]; | |
if (k.match(/value|encoding|type/i)) { | |
string += ";" + (k.toUpperCase()) + "=" + (v.toUpperCase()); | |
} | |
} | |
} | |
string += ":" + json.image + "\r\n"; | |
return string; | |
}; | |
generate_bday = function(json) { | |
var k, ref, string, v; | |
string = ""; | |
if (json.group) { | |
string += json.group + "."; | |
} | |
string += "BDAY"; | |
if (json.params) { | |
ref = json.params; | |
for (k in ref) { | |
v = ref[k]; | |
if (k.match(/value/i)) { | |
string += ";" + (k.toUpperCase()) + "=" + (v.toUpperCase()); | |
} | |
} | |
} | |
string += ":" + json.year + "-" + json.month + "-" + json.day; | |
if (json.params && json.params.value && (json.params.value === "date-time")) { | |
string += "T" + json.hour + ":" + json.minute + ":" + json.second + "Z"; | |
} | |
string += "\r\n"; | |
return string; | |
}; | |
generate_adr = function(json) { | |
var k, ref, string, v; | |
string = ""; | |
if (json.group) { | |
string += json.group + "."; | |
} | |
string += "ADR"; | |
if (json.params) { | |
ref = json.params; | |
for (k in ref) { | |
v = ref[k]; | |
if (k.match(/value|language|x-\w+/i)) { | |
string += ";" + (k.toUpperCase()) + "=" + (v.toUpperCase()); | |
} | |
if (k.match(/types/)) { | |
string += ";TYPE=" + (v.join(',').toUpperCase()); | |
} | |
} | |
} | |
if (json.pobox) { | |
string += ":" + json.pobox + ";"; | |
} else { | |
string += ":;"; | |
} | |
if (json.extended) { | |
string += json.extended + ";"; | |
} else { | |
string += ";"; | |
} | |
if (json.street) { | |
string += json.street + ";"; | |
} else { | |
string += ";"; | |
} | |
if (json.locality) { | |
string += json.locality + ";"; | |
} else { | |
string += ";"; | |
} | |
if (json.region) { | |
string += json.region + ";"; | |
} else { | |
string += ";"; | |
} | |
if (json.code) { | |
string += json.code + ";"; | |
} else { | |
string += ";"; | |
} | |
if (json.country) { | |
string += json.country + "\r\n"; | |
} else { | |
string += "\r\n"; | |
} | |
return string; | |
}; | |
generate_label = function(json) { | |
var k, ref, string, v; | |
string = ""; | |
if (json.group) { | |
string += json.group + "."; | |
} | |
string += "LABEL"; | |
if (json.params) { | |
ref = json.params; | |
for (k in ref) { | |
v = ref[k]; | |
if (k.match(/value|language|x-\w+/i)) { | |
string += ";" + (k.toUpperCase()) + "=" + (v.toUpperCase()); | |
} | |
if (k.match(/types/)) { | |
string += ";TYPE=" + (v.join(',').toUpperCase()); | |
} | |
} | |
} | |
string += ":" + json.address + "\r\n"; | |
return string; | |
}; | |
generate_tel = function(json) { | |
var k, ref, string, v; | |
string = ""; | |
if (json.group) { | |
string += json.group + "."; | |
} | |
string += "TEL"; | |
if (json.params) { | |
ref = json.params; | |
for (k in ref) { | |
v = ref[k]; | |
if (k.match(/types/)) { | |
string += ";TYPE=" + (v.join(',').toUpperCase()); | |
} | |
} | |
} | |
string += ":" + json.number + "\r\n"; | |
return string; | |
}; | |
generate_email = function(json) { | |
var k, ref, string, v; | |
string = ""; | |
if (json.group) { | |
string += json.group + "."; | |
} | |
string += "EMAIL"; | |
if (json.params) { | |
ref = json.params; | |
for (k in ref) { | |
v = ref[k]; | |
if (k.match(/types/)) { | |
string += ";TYPE=" + (v.join(',').toUpperCase()); | |
} | |
} | |
} | |
string += ":" + json.address + "\r\n"; | |
return string; | |
}; | |
generate_mailer = function(json) { | |
var k, ref, string, v; | |
string = ""; | |
if (json.group) { | |
string += json.group + "."; | |
} | |
string += "MAILER"; | |
if (json.params) { | |
ref = json.params; | |
for (k in ref) { | |
v = ref[k]; | |
if (k.match(/value|language|x-\w+/i)) { | |
string += ";" + (k.toUpperCase()) + "=" + (v.toUpperCase()); | |
} | |
} | |
} | |
string += ":" + json.name + "\r\n"; | |
return string; | |
}; | |
generate_tz = function(json) { | |
var k, ref, string, v; | |
string = ""; | |
if (json.group) { | |
string += json.group + "."; | |
} | |
string += "TZ"; | |
if (json.params) { | |
ref = json.params; | |
for (k in ref) { | |
v = ref[k]; | |
if (k.match(/value/i)) { | |
string += ";" + (k.toUpperCase()) + "=" + (v.toUpperCase()); | |
} | |
} | |
} | |
string += ":" + json.zone; | |
string += "\r\n"; | |
return string; | |
}; | |
generate_geo = function(json) { | |
var string; | |
string = ""; | |
if (json.group) { | |
string += json.group + "."; | |
} | |
string += "GEO"; | |
string += ":" + json.latitude + ";" + json.longitude + "\r\n"; | |
return string; | |
}; | |
generate_title = function(json) { | |
var k, ref, string, v; | |
string = ""; | |
if (json.group) { | |
string += json.group + "."; | |
} | |
string += "TITLE"; | |
if (json.params) { | |
ref = json.params; | |
for (k in ref) { | |
v = ref[k]; | |
if (k.match(/value|language|x-\w+/i)) { | |
string += ";" + (k.toUpperCase()) + "=" + (v.toUpperCase()); | |
} | |
} | |
} | |
string += ":" + json.name + "\r\n"; | |
return string; | |
}; | |
generate_role = function(json) { | |
var k, ref, string, v; | |
string = ""; | |
if (json.group) { | |
string += json.group + "."; | |
} | |
string += "ROLE"; | |
if (json.params) { | |
ref = json.params; | |
for (k in ref) { | |
v = ref[k]; | |
if (k.match(/value|language|x-\w+/i)) { | |
string += ";" + (k.toUpperCase()) + "=" + (v.toUpperCase()); | |
} | |
} | |
} | |
string += ":" + json.name + "\r\n"; | |
return string; | |
}; | |
generate_logo = function(json) { | |
var k, ref, string, v; | |
string = ""; | |
if (json.group) { | |
string += json.group + "."; | |
} | |
string += "LOGO"; | |
if (json.params) { | |
ref = json.params; | |
for (k in ref) { | |
v = ref[k]; | |
if (k.match(/value|encoding|type/i)) { | |
string += ";" + (k.toUpperCase()) + "=" + (v.toUpperCase()); | |
} | |
} | |
} | |
string += ":" + json.image + "\r\n"; | |
return string; | |
}; | |
generate_org = function(json) { | |
var k, ref, string, v; | |
string = ""; | |
if (json.group) { | |
string += json.group + "."; | |
} | |
string += "ORG"; | |
if (json.params) { | |
ref = json.params; | |
for (k in ref) { | |
v = ref[k]; | |
if (k.match(/value|language|x-\w+/i)) { | |
string += ";" + (k.toUpperCase()) + "=" + (v.toUpperCase()); | |
} | |
} | |
} | |
string += ":" + json.name; | |
string += ";" + json.unit; | |
string += ";" + json.unit2; | |
string += "\r\n"; | |
return string; | |
}; | |
generate_categories = function(json) { | |
var k, ref, string, v; | |
string = ""; | |
if (json.group) { | |
string += json.group + "."; | |
} | |
string += "CATEGORIES"; | |
if (json.params) { | |
ref = json.params; | |
for (k in ref) { | |
v = ref[k]; | |
if (k.match(/value|language|x-\w+/i)) { | |
string += ";" + (k.toUpperCase()) + "=" + (v.toUpperCase()); | |
} | |
} | |
} | |
string += ":" + (json.names.join(',')) + "\r\n"; | |
return string; | |
}; | |
generate_note = function(json) { | |
var k, ref, string, v; | |
string = ""; | |
if (json.group) { | |
string += json.group + "."; | |
} | |
string += "NOTE"; | |
if (json.params) { | |
ref = json.params; | |
for (k in ref) { | |
v = ref[k]; | |
if (k.match(/value|language|x-\w+/i)) { | |
string += ";" + (k.toUpperCase()) + "=" + (v.toUpperCase()); | |
} | |
} | |
} | |
string += ":" + json.description + "\r\n"; | |
return string; | |
}; | |
generate_prodid = function(json) { | |
var string; | |
string = ""; | |
if (json.group) { | |
string += json.group + "."; | |
} | |
string += "PRODID"; | |
string += ":" + json.id + "\r\n"; | |
return string; | |
}; | |
generate_rev = function(json) { | |
var k, ref, string, v; | |
string = ""; | |
if (json.group) { | |
string += json.group + "."; | |
} | |
string += "REV"; | |
if (json.params) { | |
ref = json.params; | |
for (k in ref) { | |
v = ref[k]; | |
if (k.match(/value/i)) { | |
string += ";" + (k.toUpperCase()) + "=" + (v.toUpperCase()); | |
} | |
} | |
} | |
string += ":" + json.year + "-" + json.month + "-" + json.day; | |
if (json.hour && json.minute && json.second) { | |
string += "T" + json.hour + ":" + json.minute + ":" + json.second + "Z"; | |
} | |
string += "\r\n"; | |
return string; | |
}; | |
generate_sort_string = function(json) { | |
var k, ref, string, v; | |
string = ""; | |
if (json.group) { | |
string += json.group + "."; | |
} | |
string += "SORT-STRING"; | |
if (json.params) { | |
ref = json.params; | |
for (k in ref) { | |
v = ref[k]; | |
if (k.match(/value|language|x-\w+/i)) { | |
string += ";" + (k.toUpperCase()) + "=" + (v.toUpperCase()); | |
} | |
} | |
} | |
string += ":" + json.name + "\r\n"; | |
return string; | |
}; | |
generate_sound = function(json) { | |
var k, ref, string, v; | |
string = ""; | |
if (json.group) { | |
string += json.group + "."; | |
} | |
string += "SOUND"; | |
if (json.params) { | |
ref = json.params; | |
for (k in ref) { | |
v = ref[k]; | |
if (k.match(/value|encoding|type/i)) { | |
string += ";" + (k.toUpperCase()) + "=" + (v.toUpperCase()); | |
} | |
} | |
} | |
string += ":" + json.value + "\r\n"; | |
return string; | |
}; | |
generate_uid = function(json) { | |
var k, ref, string, v; | |
string = ""; | |
if (json.group) { | |
string += json.group + "."; | |
} | |
string += "UID"; | |
if (json.params) { | |
ref = json.params; | |
for (k in ref) { | |
v = ref[k]; | |
if (k.match(/type/i)) { | |
string += ";" + (k.toUpperCase()) + "=" + (v.toUpperCase()); | |
} | |
} | |
} | |
string += ":" + json.id + "\r\n"; | |
return string; | |
}; | |
generate_url = function(json) { | |
var string; | |
string = ""; | |
if (json.group) { | |
string += json.group + "."; | |
} | |
string += "URL"; | |
string += ":" + json.uri + "\r\n"; | |
return string; | |
}; | |
generate_class = function(json) { | |
var string; | |
string = ""; | |
if (json.group) { | |
string += json.group + "."; | |
} | |
string += "CLASS"; | |
string += ":" + (json.name.toUpperCase()) + "\r\n"; | |
return string; | |
}; | |
generate_key = function(json) { | |
var k, ref, string, v; | |
string = ""; | |
if (json.group) { | |
string += json.group + "."; | |
} | |
string += "KEY"; | |
if (json.params) { | |
ref = json.params; | |
for (k in ref) { | |
v = ref[k]; | |
if (k.match(/value|encoding|type/i)) { | |
string += ";" + (k.toUpperCase()) + "=" + (v.toUpperCase()); | |
} | |
} | |
} | |
string += ":" + json.value + "\r\n"; | |
return string; | |
}; | |
return m; | |
})(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
angular.module('app', []).controller('MainCtrl', function($scope) { | |
var textFile = null; | |
var vCardContacts; | |
// Function to create a text file from a string | |
var makeTextFile = function( text ) { | |
var data = new Blob([text], {type: 'text/plain'}); | |
// If we are replacing a previously generated file we need to | |
// manually revoke the object URL to avoid memory leaks. | |
if (textFile !== null) { | |
window.URL.revokeObjectURL(textFile); | |
} | |
textFile = window.URL.createObjectURL(data); | |
return textFile; | |
}; | |
// Loop through each contact object to create the vCard formatted version and | |
// append it to the end of vCardContacts | |
_.forEach(contacts, function(contact) { | |
vCardContacts = vCardContacts + VCARD.generate(contact); | |
}); | |
// For some reason VCARD.generate outputs 'undefined' at the beginning of the | |
// file each time. So we will strip out the first 9 characters | |
vCardContacts = vCardContacts.substr(9); | |
// Create a file from the vCardContacts string | |
textFile = makeTextFile(vCardContacts); | |
// Wire up a button to create the file | |
$scope.createLink = function() { | |
var link = document.getElementById('downloadLink'); | |
link.href = textFile; | |
}; | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
*, | |
*:after, | |
*:before { | |
-webkit-box-sizing: border-box; | |
-moz-box-sizing: border-box; | |
-ms-box-sizing: border-box; | |
-o-box-sizing: border-box; | |
box-sizing: border-box; | |
} | |
article, aside, details, figcaption, figure, | |
footer, header, hgroup, menu, nav, section { | |
display: block; | |
} | |
audio, | |
canvas, | |
video { | |
display: inline-block; | |
} | |
audio:not([controls]) { | |
display: none; | |
height: 0; | |
} | |
[hidden] { | |
display: none; | |
} | |
a { | |
display: block; | |
text-decoration: none; | |
} | |
a:focus, a:hover, a:active { | |
outline: none; | |
} | |
html { | |
background: #fff; | |
/* 1 */ | |
color: #000; | |
/* 2 */ | |
font-family: sans-serif; | |
/* 3 */ | |
-ms-text-size-adjust: 100%; | |
/* 4 */ | |
-webkit-text-size-adjust: 100%; | |
/* 4 */ | |
} | |
body { | |
margin: 0; | |
} | |
figure { | |
margin: 0; | |
} | |
img { | |
border: 0; | |
max-width: 100%; | |
} | |
abbr[title] { | |
border-bottom: 1px dotted; | |
cursor: help; | |
} | |
code, | |
kbd, | |
pre, | |
samp { | |
font-family: monospace, serif; | |
font-size: 1em; | |
} | |
pre { | |
white-space: pre-wrap; | |
} | |
h1, h2, h3, h4, h5, h6 { | |
font-weight: normal; | |
margin: 0; | |
} | |
small { | |
font-size: 80%; | |
} | |
b, | |
strong { | |
font-weight: bold; | |
} | |
sub, | |
sup { | |
font-size: 75%; | |
line-height: 0; | |
position: relative; | |
vertical-align: baseline; | |
} | |
sup { | |
top: -0.5em; | |
} | |
sub { | |
bottom: -0.25em; | |
} | |
label { | |
cursor: pointer; | |
} | |
button, | |
input, | |
select, | |
textarea { | |
font-family: inherit; | |
font-size: 100%; | |
margin: 0; | |
} | |
button, | |
input { | |
line-height: normal; | |
} | |
button, | |
select { | |
text-transform: none; | |
} | |
button, | |
html input[type="button"], | |
input[type="reset"], | |
input[type="submit"] { | |
-webkit-appearance: button; | |
cursor: pointer; | |
} | |
button[disabled], | |
html input[disabled] { | |
cursor: default; | |
} | |
input[type="checkbox"], | |
input[type="radio"] { | |
box-sizing: border-box; | |
padding: 0; | |
} | |
input[type="text"], | |
input[type="search"] { | |
-webkit-appearance: textfield; | |
-moz-box-sizing: content-box; | |
-webkit-box-sizing: content-box; | |
box-sizing: content-box; | |
} | |
input[type="search"]::-webkit-search-cancel-button, | |
input[type="search"]::-webkit-search-decoration { | |
-webkit-appearance: none; | |
} | |
button::-moz-focus-inner, | |
input::-moz-focus-inner { | |
border: 0; | |
padding: 0; | |
} | |
textarea { | |
overflow: auto; | |
vertical-align: top; | |
} | |
input:invalid, | |
textarea:invalid { | |
box-shadow: none; | |
} | |
ul, | |
ol, | |
menu { | |
margin: 0; | |
padding: 0; | |
} | |
li { | |
list-style-type: none; | |
} | |
/* Demo styles */ | |
html { | |
text-align: center; | |
} | |
h2 { | |
margin: 20px 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment