1(function(context) { 2 var version = { 3 "TWO": "2.1", 4 "THREE": "3.0", 5 "FOUR": "4.0" 6 } 7 8 var vCard = { 9 Version: version, 10 Entry: { 11 "ADDRESS": {"version": [version.TWO, version.THREE, version.FOUR], "key": "ADR", "format": ";;{0};{2};{4};{1};{3}", "@comment": "usage: addAdr(street, code, city, country, state)"}, 12 "AGENT": {"version": [version.TWO, version.THREE], "key": "AGENT"}, 13 "ANNIVERSARY": {"version": [version.FOUR], "key": "ANNIVERSARY"}, 14 "BIRTHDAY": {"version": [version.TWO, version.THREE, version.FOUR], "key": "BDAY"}, 15 "CALENDARADDURI": {"version": [version.FOUR], "key": "CALADRURI"}, 16 "CALENDARURI": {"version": [version.FOUR], "key": "CALURI"}, 17 "CATEGORIES": {"version": [version.TWO, version.THREE, version.FOUR], "key": "CATEGORIES"}, 18 "CLASS": {"version": [version.THREE], "key": "CLASS"}, 19 "CLIENTPIDMAP": {"version": [version.FOUR], "key": "CLIENTPIDMAP"}, 20 "EMAIL": {"version": [version.TWO, version.THREE, version.FOUR], "key": "EMAIL"}, 21 "FBURL": {"version": [version.FOUR], "key": "FBURL"}, 22 "FORMATTEDNAME": {"version": [version.TWO, version.THREE, version.FOUR], "key": "FN"}, 23 "GENDER": {"version": [version.FOUR], "key": "GENDER"}, 24 "GEO": {"version": [version.TWO, version.THREE, version.FOUR], "key": "GEO"}, // FIXME two differents formats 25 "IMPP": {"version": [version.THREE, version.FOUR], "key": "IMPP"}, 26 // TODO: KEY 27 "KIND": {"version": [version.FOUR], "key": "KIND"}, 28 "LABEL": {"version": [version.TWO, version.THREE], "key": "LABEL"}, 29 // TODO: LOGO 30 "MAILER": {"version": [version.TWO, version.THREE], "key": "MAILER"}, 31 "MEMBER": {"version": [version.FOUR], "key": "MEMBER"}, 32 "NAME": {"version": [version.TWO, version.THREE, version.FOUR], "key": "N", "format": "{1};{0};;{2}", "@comment": "usage: addName(firstname, lastname, title)"}, 33 "NICKNAME": {"version": [version.THREE, version.FOUR], "key": "NICKNAME"}, 34 "NOTE": {"version": [version.TWO, version.THREE, version.FOUR], "key": "NOTE"}, 35 "ORGANIZATION": {"version": [version.TWO, version.THREE, version.FOUR], "key": "ORG"}, 36 // TODO: PHOTO 37 "PRODID": {"version": [version.THREE, version.FOUR], "key": "PRODID"}, 38 "PROFILE": {"version": [version.TWO, version.THREE], "key": "PROFILE"}, 39 "RELATED": {"version": [version.FOUR], "key": "RELATED"}, 40 "REVISION": {"version": [version.TWO, version.THREE, version.FOUR], "key": "REV"}, 41 "ROLE": {"version": [version.TWO, version.THREE, version.FOUR], "key": "ROLE"}, 42 "SORTSTRING": {"version": [version.TWO, version.THREE, version.FOUR], "key": "SORT-STRING"}, 43 // TODO: SOUND 44 "SOURCE": {"version": [version.TWO, version.THREE, version.FOUR], "key": "SOURCE"}, 45 "PHONE": {"version": [version.TWO, version.THREE, version.FOUR], "key": "TEL"}, 46 "TITLE": {"version": [version.TWO, version.THREE, version.FOUR], "key": "TITLE"}, 47 "TIMEZONE": {"version": [version.TWO, version.THREE, version.FOUR], "key": "TZ"}, // FIXME: two differents formats 48 "UID": {"version": [version.TWO, version.THREE, version.FOUR], "key": "UID"}, 49 "URL": {"version": [version.TWO, version.THREE, version.FOUR], "key": "URL"}, 50 "WEBPAGE": {"version": [version.TWO, version.THREE, version.FOUR], "key": "WEBPAGE"}, 51 "XML": {"version": [version.FOUR], "key": "XML"} 52 }, 53 Type: { 54 "HOME": "HOME", 55 "WORK": "WORK", 56 "CELL": "CELL", 57 "MAIN": "MAIN", 58 "OTHER":"OTHER" 59 }, 60 create: function(version) { 61 for(var key in this.Version) { 62 if(this.Version[key] === version) 63 return new Card(version) 64 } 65 throw new Error("Unknown vCard version") 66 }, 67 dump: function(card) { 68 var str = "BEGIN:VCARD\n" 69 70 for(var key in card) { 71 var entry = card[key] 72 73 if(typeof entry === "function") 74 continue 75 76 if(Object.prototype.toString.call(entry) === "[object Array]") { 77 for(var i = 0, l = entry.length; i < l; i++) { 78 var e = entry[i] 79 str += key.toUpperCase() + (e.type ? ";TYPE=" + e.type.toUpperCase() + ":" : ":") + e.value + "\n" 80 } 81 } else if(typeof entry === "object") { 82 str += key.toUpperCase() + (entry.type ? ";TYPE=" + entry.type.toUpperCase() + ":" : ":") + entry.value + "\n" 83 } else { 84 str += key.toUpperCase() + ":" + entry + "\n" 85 } 86 } 87 88 str += "END:VCARD"
89 90 return str 91 }, 92 export: function(card, name, force) { 93 var a = document.createElement('a') 94 a.download = name + ".vcf" 95 a.textContent = name 96 97 if(Blob) { 98 var blob = new Blob([this.dump(card)], {"type": "text/vcard"}) 99 a.href = URL.createObjectURL(blob) 100 } else { 101 a.href = "data:text/vcard;base64," + this.btoa(this.dump(card)) 102 } 103 104 force && a.click() 105 106 return a 107 }, 108 btoa: function(str) { 109 str = unescape(encodeURIComponent(str)) 110 111 if(!btoa) { 112 var b64c = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 113 114 var i, res = "", length = str.length; 115 for (i = 0; i < length - 2; i += 3) { 116 res += b64c[str.charCodeAt(i) >>> 2]; 117 res += b64c[((str.charCodeAt(i) & 3) << 4) | (str.charCodeAt(i + 1) >>> 4)]; 118 res += b64c[((str.charCodeAt(i + 1) & 15) << 2) | (str.charCodeAt(i + 2) >>> 6)]; 119 res += b64c[str.charCodeAt(i + 2) & 63]; 120 } 121 122 if (length % 3 === 2) { 123 res += b64c[str.charCodeAt(i) >>> 2]; 124 res += b64c[((str.charCodeAt(i) & 3) << 4) | (str.charCodeAt(i + 1) >>> 4)]; 125 res += b64c[((str.charCodeAt(i + 1) & 15) << 2)]; 126 res += "="; 127 } else if (length % 3 === 1) { 128 res += b64c[str.charCodeAt(i) >>> 2]; 129 res += b64c[((str.charCodeAt(i) & 3) << 4)]; 130 res += "=="; 131 } 132 133 return res; 134 } else { 135 return btoa(str) 136 } 137 } 138 } 139 140 var Card = function(version) { 141 this.version = version 142 143 for(var key in vCard.Entry) { 144 var property = vCard.Entry[key] 145 146 if(!property.version || property.version.indexOf(version) < 0) 147 continue 148 149 var fn = "add" + key[0].toUpperCase() + key.slice(1).toLowerCase() 150 151 Card.prototype[fn] = (function(key, format) { 152 return (function() { 153 var args = Array.prototype.slice.call(arguments) 154 var lastArg = args.length > 0 ? args[args.length - 1] : undefined 155 156 var model = vCard.Type.hasOwnProperty(lastArg) ? args.slice(0, args.length - 1) : args 157 var value = format && format.replace(/\{([0-9]*)\}/g, function(match, parameter) { 158 return model[parseInt(parameter)] || '' 159 }) || model[0] 160 161 this.add(key, value, vCard.Type.hasOwnProperty(lastArg) && lastArg) 162 }) 163 })(property.key, property.format) 164 } 165 166 this.add = function(entry, value, type) { 167 var key = (typeof entry === "object" && entry.key) ? entry.key : entry 168 169 !this[key] && (this[key] = []) 170 var e = {"value": value} 171 type && (e.type = type) 172 173 this[key].push(e) 174 } 175 } 176
177 context.vCard = vCard 178})(this)
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.