1String.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 // Exit early if either are empty. 8 if (s1.length === 0 || s2.length === 0) { 9 return 0; 10 } 11 12 // Convert to upper 13 s1 = s1.toUpperCase(); 14 s2 = s2.toUpperCase(); 15 // Exit early if they're an exact match. 16 if (s1 === s2) { 17 return 1; 18 } 19 20 var range = (Math.floor(Math.max(s1.length, s2.length) / 2)) - 1; 21 var s1Matches = new Array(s1.length); 22 var s2Matches = new Array(s2.length); 23 for (i = 0; i < s1.length; i++) { 24 var low = (i >= range) ? i - range : 0; 25 var high = (i + range <= (s2.length - 1)) ? (i + range) : (s2.length - 1); 26 for (j = low; j <= high; j++) { 27 if (s1Matches[i] !== true && s2Matches[j] !== true && s1[i] === s2[j]) { 28 ++m; 29 s1Matches[i] = s2Matches[j] = true; 30 break; 31 } 32 } 33 } 34 35 // Exit early if no matches were found. 36 if (m === 0) { 37 return 0; 38 } 39 40 // Count the transpositions. 41 var k = 0; 42 var numTrans = 0; 43 for (i = 0; i < s1.length; i++) { 44 if (s1Matches[i] === true) { 45 for (j = k; j < s2.length; j++) { 46 if (s2Matches[j] === true) { 47 k = j + 1; 48 break; 49 } 50 } 51 if (s1[i] !== s2[j]) { 52 ++numTrans; 53 } 54 } 55 } 56 57 var weight = (m / s1.length + m / s2.length + (m - (numTrans / 2)) / m) / 3; 58 var l = 0; 59 var p = 0.1; 60 if (weight > 0.7) { 61 while (s1[l] === s2[l] && l < 4) { 62 ++l; 63 } 64 weight = weight + l * p * (1 - weight); 65 } 66 return weight; 67} 68 69$(function() { 70 var $domain_hint_div; 71 $('input[type=email]').on('change', function() { 72 var $email_input = $(this); 73 var suggested_domains = $(this).data('suggested-domains').split(':'); 74 var val = $email_input.val(); 75 var val_domain = val.split('@')[1]; 76 var highest_ratio = 0; 77 var suggestion = null; 78 if (typeof val_domain !== 'undefined') { 79 for (var i=0; i < suggested_domains.length; i++) { 80 var domain = suggested_domains[i]; 81 var ratio = val_domain.similarity(domain); 82 if (ratio > highest_ratio) { 83 highest_ratio = ratio; 84 suggestion = domain; 85 } 86 } 87 } 88 if (highest_ratio > 0.80 && highest_ratio < 1) { 89 $domain_hint_div = $('div.field-live-hint') 90 $domain_hint_div.find('button.action').on('click', function() { 91 $email_input.val($email_input.val().replace(/@.*/, '@' + $(this).data('suggestion'))); 92 $email_input.trigger('change'); 93 $domain_hint_div.hide(); 94 return false; 95 }); 96 97 $domain_hint_div.find('button.close').on('click', function() { 98 $domain_hint_div.hide(); 99 return false; 100 }); 101 $domain_hint_div.find('> p').text($domain_hint_div.find('> p').data('hint-prefix') + ' @' + suggestion + ' ?'); 102 $domain_hint_div.find('button.action').data('suggestion', suggestion); 103 $domain_hint_div.show(); 104 } else if ($domain_hint_div) { 105 $domain_hint_div.hide(); 106 } 107 }); 108})
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.