2
Creative Commons License: Attribution-No Derivative Works 3.0 Unported
3
http://creativecommons.org/licenses/by-nd/3.0/
12
hilite_color: new Array(0,0,255),
13
hilite_bgcolor: new Array(255,255,0),
16
sc_nbsp: String.fromCharCode(0xa0),
18
// chars which look like dashes
20
String.fromCharCode(0x2013) +
21
String.fromCharCode(0x2014) +
22
String.fromCharCode(0x2212),
25
/^\d{2}\.\d{2} ?(-|–) ?\d{2}\.\d{2}$/, // time range e.g. 08.00 - 17.00
26
/^\d{2}\/\d{2}\/\d{2}$/, // date e.g. 09/03/09
27
/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/, // ip address
28
/^[0-3]?[0-9]\.[0-3]?[0-9]\.(19|20)\d{2} - \d{2}\.\d{2}$/, // date and time e.g. 09.03.2009 - 17.59
29
/^[0-3]?[0-9][\/\.-][0-3]?[0-9][\/\.-](19|20)\d{2}$/, // date e.g. 09/03/2009, 09.03.2009, 09-03-2009
30
/^[0-3]?[0-9][\/\.-][0-3]?[0-9][\/\.-]\d{2} ?(-|–) ?[0-3]?[0-9][\/\.-][0-3]?[0-9][\/\.-]\d{2}$/, // date range short
31
/^[0-3]?[0-9][\/\.-][0-3]?[0-9][\/\.-] ?(-|–) ?[0-3]?[0-9][\/\.-][0-3]?[0-9][\/\.-](19|20)\d{2}$/, // date range medium
32
/^[0-3]?[0-9][\/\.-][0-3]?[0-9][\/\.-](19|20)\d{2} ?(-|–) ?[0-3]?[0-9][\/\.-][0-3]?[0-9][\/\.-](19|20)\d{2}$/, // date range long
33
/^0\.\d+$/, // e.g. 0.12345678
37
[/^[1-9]\d{2}[\.-]\d{3}[\.-]\d{4}$/, "+1"], // US
40
token_trigger: "+(0123456789",
41
token_part: " -/()[].\r\n"
42
+ String.fromCharCode(0xa0) // sc_nbsp
43
+ String.fromCharCode(0x2013) + String.fromCharCode(0x2014) + String.fromCharCode(0x2212), // token_dash
46
token_disallowed_post: ":-",
47
token_disallowed_prev: "-,.",
49
dialHistory: new Array(objTelifyPrefs.maxHistory),
52
getDialHistory: function()
54
for (var i=0; i<objTelifyPrefs.maxHistory; i++) {
56
this.dialHistory[i] = objTelifyPrefs.telPrefs.getCharPref("history"+i);
58
this.dialHistory[i] = "";
64
saveDialHistory: function()
66
for (var i=0; i<objTelifyPrefs.maxHistory; i++) {
67
if (this.dialHistory[i] == null) this.dialHistory[i] = "";
68
objTelifyPrefs.telPrefs.setCharPref("history"+i, this.dialHistory[i]);
73
updateDialHistory: function(prefix)
75
//logmsg("updateDialHistory("+prefix+")");
76
var newList = new Array(objTelifyPrefs.maxHistory);
78
for (var i=0, j=1; i<objTelifyPrefs.maxHistory && j<objTelifyPrefs.maxHistory; i++) {
79
if (this.dialHistory[i] == null || this.dialHistory[i] == "" || this.dialHistory[i] == prefix) continue;
80
newList[j++] = this.dialHistory[i];
82
this.dialHistory = newList;
83
this.saveDialHistory();
89
var statusicon = document.getElementById("idTelify_statusicon");
90
if (objTelifyPrefs.fActive) {
91
statusicon.setAttribute("src", "chrome://telify/content/icon18_active.png");
92
var text = objTelifyPrefs.telStrings.getString("telify_active");
93
statusicon.setAttribute("tooltiptext", text);
95
statusicon.setAttribute("src", "chrome://telify/content/icon18_inactive.png");
96
var text = objTelifyPrefs.telStrings.getString("telify_inactive");
97
statusicon.setAttribute("tooltiptext", text);
102
toggleBlacklist: function()
104
var host = objTelifyUtil.getHost();
105
if (host == null) return;
106
if (objTelifyPrefs.excludedHosts.indexOf(host) >= 0) {
107
objTelifyUtil.arrayRemove(objTelifyPrefs.excludedHosts, host);
109
objTelifyPrefs.excludedHosts.push(host);
111
objTelifyPrefs.blacklist = objTelifyPrefs.excludedHosts.join(",");
112
objTelifyPrefs.telPrefs.setCharPref(objTelifyPrefs.PREF_BLACKLIST, objTelifyPrefs.blacklist);
116
toggleActive: function()
118
objTelifyPrefs.telPrefs.setBoolPref(objTelifyPrefs.PREF_ACTIVE, !objTelifyPrefs.fActive);
123
getSelectionNumber: function()
125
//var sel = content.window.getSelection().toString();
126
var sel = document.commandDispatcher.focusedWindow.getSelection().toString();
127
sel = this.convertVanityNr(sel);
128
sel = objTelifyUtil.stripNumber(sel);
133
dialNumber: function(nr)
135
var requ = new XMLHttpRequest();
136
var url = objTelifyUtil.createDialURL(nr);
138
if (objTelifyPrefs.hrefType == objTelifyPrefs.HREFTYPE_CUSTOM) {
139
if (objTelifyPrefs.custom_opentype == 1) {
140
window.open(url, "_blank");
143
if (objTelifyPrefs.custom_opentype == 2) {
144
var browser = top.document.getElementById("content");
145
var tab = browser.addTab(url);
148
if (objTelifyPrefs.custom_opentype == 3) {
149
var browser = top.document.getElementById("content");
150
var tab = browser.addTab(url);
151
browser.selectedTab = tab;
157
requ.open("GET", url, true);
160
// throws exception because answer is empty (or protocol is unknown)
161
if (e.name == "NS_ERROR_UNKNOWN_PROTOCOL") {
162
objTelifyUtil.showMessageBox("", objTelifyLocale.msgUnknownProtocol(), objTelifyUtil.MB_ICON_ERROR);
168
modifyPopup: function(event)
172
//var selText = content.window.getSelection().toString();
173
var selText = document.commandDispatcher.focusedWindow.getSelection().toString();
175
if (document.popupNode && document.popupNode.getAttribute("class") == "telified") {
176
var nr = document.popupNode.getAttribute("nr");
177
var nr_parts = objTelifyUtil.splitPhoneNr(nr);
178
objTelify.modifyDialPopup(nr_parts[0], nr_parts[1], "context");
179
objTelifyUtil.setIdAttr("collapsed", false, "idTelify_menu_context");
180
} else if (objTelifyPrefs.fActive && selText.length > 0 && objTelifyUtil.countDigits(selText) > 1) {
181
var nr = objTelify.getSelectionNumber();
182
var nr_parts = objTelifyUtil.splitPhoneNr(nr);
183
objTelify.modifyDialPopup(nr_parts[0], nr_parts[1], "context");
184
objTelifyUtil.setIdAttr("collapsed", false, "idTelify_menu_context");
186
objTelifyUtil.setIdAttr("collapsed", true, "idTelify_menu_context");
189
if (objTelifyPrefs.fActive) {
190
label = objTelifyPrefs.telStrings.getString("telify_deactivate");
192
label = objTelifyPrefs.telStrings.getString("telify_activate");
194
objTelifyUtil.setIdAttr("label", label, "idTelify_menu_activity", "idTelify_status_activity");
196
var host = objTelifyUtil.getHost();
198
objTelifyUtil.setIdAttr("disabled", !objTelifyPrefs.fActive, "idTelify_menu_blacklist", "idTelify_status_blacklist");
199
if (objTelifyPrefs.excludedHosts.indexOf(host) >= 0) key = "host_active_arg"; else key = "host_inactive_arg";
200
label = objTelifyUtil.substArgs(objTelifyPrefs.telStrings.getString(key), host);
201
objTelifyUtil.setIdAttr("label", label, "idTelify_menu_blacklist", "idTelify_status_blacklist");
203
objTelifyUtil.setIdAttr("label", "Kein Host aktiv", "idTelify_menu_blacklist", "idTelify_status_blacklist");
204
objTelifyUtil.setIdAttr("disabled", true, "idTelify_menu_blacklist", "idTelify_status_blacklist");
209
showEditNumberDialog: function(cc, nr)
211
var argObj = {cc: cc, nr: nr, fOK: false};
212
window.openDialog("chrome://telify/content/editNumber.xul", "dlgTelifyEditNumber", "centerscreen,chrome,modal", argObj);
214
this.updateDialHistory(argObj.cc);
215
var dial = objTelifyUtil.prefixNumber(argObj.cc, argObj.nr, "");
216
objTelify.dialNumber(dial);
221
dialMenuSelection: function(cc, nr)
223
this.updateDialHistory(cc);
224
var dial = objTelifyUtil.prefixNumber(cc, nr, "");
225
objTelify.dialNumber(dial);
229
createTargetCountryInfo: function(prefix)
231
var cstring = objTelifyUtil.getCountryListString(prefix);
232
if (cstring) return "\n" + objTelifyPrefs.telStrings.getString('country_code') + ": " + cstring;
237
setDialMenuItem: function(item, code, nr)
239
var label = objTelifyUtil.prefixNumber(code, nr, "-");
240
item.setAttribute("label", label);
241
var cmd = "objTelify.dialMenuSelection('"+code+"','"+nr+"');";
242
item.setAttribute("oncommand", cmd);
243
label = objTelifyUtil.substArgs(objTelifyPrefs.telStrings.getString('call_arg'), label);
244
label += objTelify.createTargetCountryInfo(code);
245
item.setAttribute("tooltiptext", label);
246
item.setAttribute("image", "chrome://telify/content/flag/"+code.substr(1)+".png");
250
modifyDialPopup: function(cc, nr, id)
252
var item = document.getElementById("idTelify_"+id);
253
var sep = document.getElementById("idTelify_sep_"+id);
257
this.setDialMenuItem(item, cc, nr);
259
item.setAttribute("label", nr);
260
var label = objTelifyUtil.substArgs(objTelifyPrefs.telStrings.getString('call_arg'), nr);
261
item.setAttribute("tooltiptext", label);
262
item.removeAttribute("image");
263
item.setAttribute("oncommand", "objTelify.dialNumber('"+nr+"')");
266
item = document.getElementById("idTelify_edit_"+id);
268
item.setAttribute("oncommand", "objTelify.showEditNumberDialog('"+cc+"','"+nr+"')");
270
item.setAttribute("oncommand", "objTelify.showEditNumberDialog(null,'"+nr+"')");
273
var tldcc = objTelifyUtil.tld2cc(objTelifyUtil.getHostTLD());
274
item = document.getElementById("idTelify_tld_"+id);
276
item.setAttribute("collapsed", false);
277
this.setDialMenuItem(item, tldcc, nr);
280
item.setAttribute("collapsed", true);
284
this.getDialHistory();
286
if (!cc && nr.charAt(0) != '+') {
287
var numLeft = objTelifyPrefs.numHistory;
288
if (tldcc) numLeft--;
289
for (var i=0; i<objTelifyPrefs.maxHistory; i++) {
290
item = document.getElementById("idTelify_"+id+i);
291
if (numLeft == 0 || this.dialHistory[i] == null || this.dialHistory[i].length == 0 || this.dialHistory[i] == cc || this.dialHistory[i] == tldcc) {
292
item.setAttribute("collapsed", true);
294
item.setAttribute("collapsed", false);
295
this.setDialMenuItem(item, this.dialHistory[i], nr);
301
for (var i=0; i<objTelifyPrefs.maxHistory; i++) {
302
item = document.getElementById("idTelify_"+id+i);
303
item.setAttribute("collapsed", true);
306
sep.setAttribute("collapsed", numShown == 0);
310
showDialPopup: function(target, cc, nr)
312
var menu = document.getElementById("idTelify_popup_dial");
313
var nr_parts = objTelifyUtil.splitPhoneNr(nr);
314
this.modifyDialPopup(cc, nr, "dial");
315
menu.openPopup(target, "after_start", 0, 0, true, false);
319
onClick: function(event)
321
if (event.button != 0) return;
322
var class = event.target.getAttribute("class");
323
if (class != "telified") return;
324
event.preventDefault();
325
var nr = event.target.getAttribute("nr");
326
var nr_parts = objTelifyUtil.splitPhoneNr(nr);
327
if (event.button == 0) {
328
if (nr_parts[0] && objTelifyPrefs.fDialCCDirect) {
329
objTelify.dialNumber(nr);
331
objTelify.showDialPopup(event.target, nr_parts[0], nr_parts[1]);
334
if (event.button == 2) {
335
objTelify.showDialPopup(event.target, nr_parts[0], nr_parts[1]);
340
getNodeBackgroundColor: function(node)
342
node = node.parentNode;
343
if (node == null) return null;
344
if (node.nodeType == Node.ELEMENT_NODE) {
345
var style = content.document.defaultView.getComputedStyle(node, "");
346
var image = style.getPropertyValue("background-image");
347
if (image && image != "none") return null;
348
var color = style.getPropertyValue("background-color");
349
if (color && color != "transparent") return color;
351
return this.getNodeBackgroundColor(node);
355
getNodeColor: function(node)
357
node = node.parentNode;
358
if (node == null) return null;
359
if (node.nodeType == Node.ELEMENT_NODE) {
360
var style = content.document.defaultView.getComputedStyle(node, "");
361
var color = style.getPropertyValue("color");
362
if (color && color != "transparent") return color;
364
return this.getNodeColor(node);
368
formatPhoneNr: function(phonenr)
371
[" ", " "], // double spaces to single space
372
[this.sc_nbsp, " "], // non-breaking space to plain old space
373
["+ ", "+"], // remove space after +
374
["--", "-"], // double dashes to single dash
375
["(0)", " "], // remove optional area code prefix
376
["[0]", " "], // remove optional area code prefix
385
// replace dash-like chars with dashes
386
for (var i=0; i<phonenr.length; i++) {
387
var c = phonenr.charAt(i);
388
if (this.token_dash.indexOf(c) >= 0) {
389
phonenr = phonenr.substr(0, i) + "-" + phonenr.substr(i+1);
393
const MAXLOOP = 100; // safety bailout
397
for (var j=0; nChanged > 0 && j < MAXLOOP; j++) {
399
for (var i=0; i<substList.length; i++) {
401
while ((index = phonenr.indexOf(substList[i][0])) >= 0) {
402
phonenr = phonenr.substr(0, index) + substList[i][1] + phonenr.substr(index+substList[i][0].length);
412
convertVanityNr: function(phonenr)
414
const tab_alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
415
const tab_digit = "22233344455566677778889999";
417
for (var i=0; i<phonenr.length; i++) {
418
var c = phonenr.charAt(i);
419
var index = tab_alpha.indexOf(c);
420
if (index >= 0) c = tab_digit.substr(index, 1);
427
reject: function(str, reason)
429
if (objTelifyPrefs.fDebug == false) return;
430
var msg = "Telify: reject '"+str+"' reason: "+reason;
431
objTelifyUtil.logmsg(msg);
436
String.fromCharCode(0xa0) +
437
String.fromCharCode(0x2013) +
438
String.fromCharCode(0x2014) +
439
String.fromCharCode(0x2212),
444
basechar: function(c)
446
var index = this.basechar_tab[0].indexOf(c);
447
if (index >= 0) c = this.basechar_tab[1].charAt(index);
452
telifyTextNode: function(node)
454
if (node == null) return 0;
455
var text = node.data;
456
var len = text.length;
457
if (len < this.digits_min) return 0;
458
var hlFactor = objTelifyPrefs.highlight/200.0;
460
for (var i=0; i<len; i++) {
461
var c = text.charAt(i);
463
if (this.token_trigger.indexOf(c) < 0) continue;
465
c = this.basechar(c);
470
var ndigits = (objTelifyUtil.isdigit(c) ? 1 : 0);
472
var fStartsWithCountryCode = false;
473
var CCfromPattern = null;
475
// gather allowed chars
476
while (strlen < len-i) {
477
c = text.charAt(i+strlen);
478
c = this.basechar(c);
479
if ((c == '+' && ndigits == 0) || (this.token_part.indexOf(c) >= 0)) {
480
if (c == last_c && c!=' ') break;
482
if (!objTelifyUtil.isdigit(c)) break;
490
// check against digit count min value
491
if (ndigits < this.digits_min) {
492
this.reject(str, "less than "+this.digits_min+" digits");
493
i += strlen - 1; continue;
496
// check allowed prev token
498
var prev_c = text.charAt(i-1);
499
if (this.token_disallowed_prev.indexOf(prev_c) >= 0) {
500
this.reject(str, "unallowed previous token (reject list)");
501
i += strlen - 1; continue;
503
if ((prev_c >= 'a' && prev_c <= "z") || (prev_c >= 'A' && prev_c <= "Z")) {
504
this.reject(str, "unallowed previous token (letter)");
505
i += strlen - 1; continue;
509
// check if phone number starts with country code
510
for (var j=0; j<telify_country_data.length; j++) {
511
var cclen = telify_country_data[j][0].length;
512
if (cclen < 2 || cclen > 4) continue;
513
var pattern = telify_country_data[j][0].substr(1);
514
var plen = pattern.length;
515
if (str.substr(0, plen) != pattern) continue;
516
var c = str.charAt(plen);
517
if (this.token_sep.indexOf(c) < 0) continue;
518
fStartsWithCountryCode = true;
522
// check against special local patterns
523
for (var j=0; j<this.inclLocalList.length; j++) {
524
var res = this.inclLocalList[j][0].exec(str);
525
if (res) {CCfromPattern = this.inclLocalList[j][1]; break;}
528
// check if phone number starts with allowed token
529
if (CCfromPattern == null && fStartsWithCountryCode == false && this.token_start.indexOf(str.charAt(0)) < 0) {
530
this.reject(str, "unallowed start token (reject list)");
531
i += strlen - 1; continue;
534
// trim chars at end of string up to an unmatched opening bracket
536
for (var j=strlen-1; j>=0; j--) {
539
if (c == '(') {index = j; break;}
541
if (index == 0) continue;
543
str = str.substr(0, index);
547
// check against digit count max value (after we have removed unnecessary digits)
548
if (objTelifyUtil.countDigits(str) > this.digits_max) {
549
this.reject(str, "more than "+this.digits_max+" digits");
550
i += strlen - 1; continue;
553
// trim non-digit chars at end of string
554
while (str.length > 0) {
555
c = str.charAt(str.length-1);
556
if (!objTelifyUtil.isdigit(c)) {
557
str = str.substr(0, str.length-1);
562
// check allowed post token
563
var post_c = text.charAt(i+strlen);
565
if (this.token_disallowed_post.indexOf(post_c) >= 0) {
566
this.reject(str, "unallowed post token (reject list)");
567
i += strlen - 1; continue;
569
if ((post_c >= 'a' && post_c <= "z") || (post_c >= 'A' && post_c <= "Z")) {
570
this.reject(str, "unallowed post token (letter)");
571
i += strlen - 1; continue;
575
// check if this is just a number in braces
576
// first check for unnecessary opening braces
577
if (str.substr(0, 1) == "(" && str.indexOf(")") < 0) {
581
// now check if it still starts with allowed token
582
if (this.token_start.indexOf(str.charAt(0)) < 0) {
583
this.reject(str, "unallowed start token (after brace removal)");
589
// check against blacklist patterns (date, time ranges etc.)
591
for (var j=0; j<this.exclPatternList.length; j++) {
592
var res = this.exclPatternList[j].exec(str);
593
if (res) {index = j; break;}
595
if (index >= 0) {this.reject(str, "blacklisted pattern #"+index); i += strlen - 1; continue;}
598
// ----------------------------------------------------------------
600
var display = this.formatPhoneNr(str);
601
var href = objTelifyUtil.stripNumber(display);
602
if (fStartsWithCountryCode) href = "+"+href;
603
//if (CCfromPattern) href = CCfromPattern + href;
605
// insert link into DOM
607
var node_prev = content.document.createTextNode(text.substr(0, i));
608
var node_after = content.document.createTextNode(text.substr(i+strlen));
610
//alert("match="+str);
612
var node_anchor = content.document.createElement("a");
614
if (hlFactor > 0.0) {
615
var color = objTelifyUtil.parseColor(this.getNodeColor(node));
616
if (color == null) color = new Array(0,0,0);
617
var bgcolor = objTelifyUtil.parseColor(this.getNodeBackgroundColor(node));
618
if (bgcolor == null) bgcolor = new Array(255,255,255);
619
for (var i=0; i<3; i++) {
620
color[i] = color[i] + hlFactor * (this.hilite_color[i] - color[i]);
621
bgcolor[i] = bgcolor[i] + hlFactor * (this.hilite_bgcolor[i] - bgcolor[i]);
623
var style = "color:#"+objTelifyUtil.color2hex(color)+";background-color:#"+objTelifyUtil.color2hex(bgcolor)+";-moz-border-radius:3px";
624
node_anchor.setAttribute("style", style);
627
node_anchor.setAttribute("title", objTelifyPrefs.telStrings.getString('link_title'));
628
node_anchor.setAttribute("class", "telified");
629
node_anchor.setAttribute("nr", href);
630
node_anchor.setAttribute("href", objTelifyUtil.createDialURL(href));
632
var node_text = content.document.createTextNode(str);
633
node_anchor.appendChild(node_text);
635
var parentNode = node.parentNode;
636
parentNode.replaceChild(node_after, node);
637
parentNode.insertBefore(node_anchor, node_after);
638
parentNode.insertBefore(node_prev, node_anchor);
647
recurseNode: function(node)
649
if (node == null) return 0; // safety
650
if (node.nodeType == Node.TEXT_NODE) {
651
return this.telifyTextNode(node);
654
//objTelifyUtil.logmsg("node type="+node.nodeType+" "+node.tagName+" (childs:"+node.childNodes.length+")");
655
if (node.nodeType == Node.ELEMENT_NODE) {
656
var tagName = node.tagName.toLowerCase();
657
if (objTelifyPrefs.excludedTags.indexOf(tagName) >= 0) return 0;
659
for (var i=0; i<node.childNodes.length; i++) {
660
nChanged += this.recurseNode(node.childNodes[i]);
662
if (node.contentDocument) {
663
nChanged += this.recurseNode(node.contentDocument.body);
664
node.contentDocument.addEventListener("click", objTelify.onClick, false);
671
parsePage: function(event)
673
if (!objTelifyPrefs.fActive) return;
674
//objTelifyUtil.logmsg("eventPhase: "+event.eventPhase+"\n"+content.document.URL);
675
if (content.document.body == null) return;
676
if (event && event.eventPhase != 1) return;
678
var host = objTelifyUtil.getHost();
679
if (host && objTelifyPrefs.excludedHosts.indexOf(host) >= 0) return;
681
//if (content.document.body.getAttribute('telified') == 1) return;
682
//content.document.body.setAttribute('telified', 1);
686
var duration = (new Date()).getTime();
687
nChanged = objTelify.recurseNode(content.document.body);
688
duration = (new Date()).getTime() - duration;
689
var label = "Telify\n" + objTelifyPrefs.telStrings.getString('converted') + ": " + nChanged + " (" + duration + " ms)";
690
document.getElementById("idTelify_statusicon").setAttribute("tooltiptext", label);
693
window.setTimeout("objTelify.recurseNode(content.document.body)", 0);
695
content.document.addEventListener("click", objTelify.onClick, false);
699
init: function(event)
701
window.addEventListener('load', objTelify.init, false);
702
objTelifyPrefs.initTelifyPrefs();
703
objTelify.setStatus();
704
getBrowser().addEventListener("load", objTelify.parsePage, true);
705
document.getElementById("contentAreaContextMenu").addEventListener("popupshowing", objTelify.modifyPopup, false);
706
objTelifyUtil.addScheme("tel");
707
objTelifyUtil.localizeCountryData();
708
objTelifyUtil.getAddonVersion();
714
window.addEventListener('load', objTelify.init, false);