|
1 |
String.prototype.similarity = function(string) {
|
|
2 |
// adapted from https://github.com/jordanthomas/jaro-winkler (licensed as MIT)
|
|
3 |
var s1 = this, s2 = string;
|
|
4 |
var m = 0;
|
|
5 |
var i;
|
|
6 |
var j;
|
|
7 |
|
|
8 |
// Exit early if either are empty.
|
|
9 |
if (s1.length === 0 || s2.length === 0) {
|
|
10 |
return 0;
|
|
11 |
}
|
|
12 |
|
|
13 |
// Convert to upper
|
|
14 |
s1 = s1.toUpperCase();
|
|
15 |
s2 = s2.toUpperCase();
|
|
16 |
|
|
17 |
// Exit early if they're an exact match.
|
|
18 |
if (s1 === s2) {
|
|
19 |
return 1;
|
|
20 |
}
|
|
21 |
|
|
22 |
var range = (Math.floor(Math.max(s1.length, s2.length) / 2)) - 1;
|
|
23 |
var s1Matches = new Array(s1.length);
|
|
24 |
var s2Matches = new Array(s2.length);
|
|
25 |
|
|
26 |
for (i = 0; i < s1.length; i++) {
|
|
27 |
var low = (i >= range) ? i - range : 0;
|
|
28 |
var high = (i + range <= (s2.length - 1)) ? (i + range) : (s2.length - 1);
|
|
29 |
|
|
30 |
for (j = low; j <= high; j++) {
|
|
31 |
if (s1Matches[i] !== true && s2Matches[j] !== true && s1[i] === s2[j]) {
|
|
32 |
++m;
|
|
33 |
s1Matches[i] = s2Matches[j] = true;
|
|
34 |
break;
|
|
35 |
}
|
|
36 |
}
|
|
37 |
}
|
|
38 |
|
|
39 |
// Exit early if no matches were found.
|
|
40 |
if (m === 0) {
|
|
41 |
return 0;
|
|
42 |
}
|
|
43 |
|
|
44 |
// Count the transpositions.
|
|
45 |
var k = 0;
|
|
46 |
var numTrans = 0;
|
|
47 |
|
|
48 |
for (i = 0; i < s1.length; i++) {
|
|
49 |
if (s1Matches[i] === true) {
|
|
50 |
for (j = k; j < s2.length; j++) {
|
|
51 |
if (s2Matches[j] === true) {
|
|
52 |
k = j + 1;
|
|
53 |
break;
|
|
54 |
}
|
|
55 |
}
|
|
56 |
|
|
57 |
if (s1[i] !== s2[j]) {
|
|
58 |
++numTrans;
|
|
59 |
}
|
|
60 |
}
|
|
61 |
}
|
|
62 |
|
|
63 |
var weight = (m / s1.length + m / s2.length + (m - (numTrans / 2)) / m) / 3;
|
|
64 |
var l = 0;
|
|
65 |
var p = 0.1;
|
|
66 |
|
|
67 |
if (weight > 0.7) {
|
|
68 |
while (s1[l] === s2[l] && l < 4) {
|
|
69 |
++l;
|
|
70 |
}
|
|
71 |
|
|
72 |
weight = weight + l * p * (1 - weight);
|
|
73 |
}
|
|
74 |
|
|
75 |
return weight;
|
|
76 |
}
|
|
77 |
|
1 |
78 |
$(function() {
|
2 |
79 |
var autosave_timeout_id = null;
|
3 |
80 |
if ($('form[data-has-draft]').length == 1) {
|
... | ... | |
30 |
107 |
last_auto_save = $('form[data-has-draft]').serialize();
|
31 |
108 |
});
|
32 |
109 |
}
|
|
110 |
var well_known_domains = ['gmail.com', 'msn.com', 'hotmail.com', 'hotmail.fr', 'wanadoo.fr',
|
|
111 |
'free.fr', 'yahoo.fr', 'numericable.fr', "laposte.fr"];
|
|
112 |
$('input[type=email]').on('change wcs:change', function() {
|
|
113 |
var $email_input = $(this);
|
|
114 |
var val = $email_input.val();
|
|
115 |
var val_domain = val.split('@')[1];
|
|
116 |
var $domain_hint_div = this.domain_hint_div;
|
|
117 |
var highest_ratio = 0;
|
|
118 |
var suggestion = null;
|
|
119 |
for (var i=0; i < well_known_domains.length; i++) {
|
|
120 |
var domain = well_known_domains[i];
|
|
121 |
var ratio = val_domain.similarity(domain);
|
|
122 |
if (ratio > highest_ratio) {
|
|
123 |
highest_ratio = ratio;
|
|
124 |
suggestion = domain;
|
|
125 |
}
|
|
126 |
}
|
|
127 |
if (highest_ratio > 0.80 && highest_ratio < 1) {
|
|
128 |
if ($domain_hint_div === undefined) {
|
|
129 |
$domain_hint_div = $('<div class="field-live-hint"><span class="message"></span><button class="action"></button><button class="close"><span class="sr-only"></span></button></div>');
|
|
130 |
this.domain_hint_div = $domain_hint_div;
|
|
131 |
$(this).after($domain_hint_div);
|
|
132 |
$domain_hint_div.find('button.action').on('click', function() {
|
|
133 |
$email_input.val($email_input.val().replace(/@.*/, '@' + $(this).data('suggestion')));
|
|
134 |
$email_input.trigger('wcs:change');
|
|
135 |
$domain_hint_div.hide();
|
|
136 |
return false;
|
|
137 |
});
|
|
138 |
$domain_hint_div.find('button.close').on('click', function() {
|
|
139 |
$domain_hint_div.hide();
|
|
140 |
return false;
|
|
141 |
});
|
|
142 |
}
|
|
143 |
$domain_hint_div.find('span').text(WCS_I18N.email_domain_suggest + ' @' + suggestion + ' ?');
|
|
144 |
$domain_hint_div.find('button.action').text(WCS_I18N.email_domain_fix);
|
|
145 |
$domain_hint_div.find('button.action').data('suggestion', suggestion);
|
|
146 |
$domain_hint_div.find('button.close span.sr-only').text(WCS_I18N.close);
|
|
147 |
$domain_hint_div.show();
|
|
148 |
} else if ($domain_hint_div) {
|
|
149 |
$domain_hint_div.hide();
|
|
150 |
}
|
|
151 |
});
|
33 |
152 |
$('.date-pick').each(function() {
|
34 |
153 |
if (this.type == "date" || this.type == "time") {
|
35 |
154 |
return; // prefer native date/time widgets
|