(function() { var characters = "0123456789 AaÀÁÂÃàáâãBbCcÇçĆćČčDdÐðEeÈÉÊËèéêëFfGgHhIiÌÍÎÏìíîïJjKkLlŁłMmNnÑñŃńOoÒÓÔòóôPpQqRrŘřSsŚśšTtUuÙÚÛùúûVvWwXxYyÜÝüýZzÅåÄÆäæÖØöø!@#$%^&*()+-/"; var seNormalize = "0123456789 aaaaaaaaaabbccccccccddddeeeeeeeeeeffgghhiiiiiiiiiijjkkllllmmnnnnnnooooooooppqqrrrrsssssttuuuuuuuuvvwwxxyyyyyyzzååääääöööö!@#$%^&*()+-/" var sortable = "0123456789 AAAAAAAAAABBCCCCCCCCDDDDEEEEEEEEEEFFGGHHIIIIIIIIIIJJKKLLLLMMNNNNNNOOOOOOOOPPQQRRRRSSSSSTTUUUUUUUUVVWWXXYYYYYYZZaabbbbcccc "; function replaceCharacters(string, fromChars, toChars) { var t, r = []; for (var ix = 0; ix < string.length; ++ix) { t = fromChars.indexOf(string.charAt(ix)); if (t >= 0) { r.push(toChars.charAt(t)); } } return r.join(''); } function longestCommonSubstring(string1, string2) { // init max value var longestCommonSubstring = 0; // init 2D array with 0 var table = Array(string1.length); for(a = 0; a <= string1.length; a++){ table[a] = Array(string2.length); for(b = 0; b <= string2.length; b++){ table[a][b] = 0; } } // fill table for(var i = 0; i < string1.length; i++){ for(var j = 0; j < string2.length; j++){ if(string1[i]==string2[j]){ if(table[i][j] == 0){ table[i+1][j+1] = 1; } else { table[i+1][j+1] = table[i][j] + 1; } if(table[i+1][j+1] > longestCommonSubstring){ longestCommonSubstring = table[i+1][j+1]; } } else { table[i+1][j+1] = 0; } } } return longestCommonSubstring; } function prefixLength(string1, string2) { for (var ix = 0; ix < string1.length; ++ix) { if (string1[ix] != string2[ix]) { return ix; } } return ix; } String.prototype.seNormalize = function() { return replaceCharacters(this, characters, seNormalize); }; String.prototype.sortable = function() { return replaceCharacters(this.replace('&', '&'), characters, sortable); }; Array.prototype.autocompleteFilter = function(string) { if (string == null || string == '') { return []; } var maxResults = 9; string = string.seNormalize(); var parts = _.map(string.split(' '), function(p) { return p.trim(); }); var results = _.filter(this, function(s) { var n = s.seNormalize(); if (n.indexOf(parts[0]) >= 0) { var match = true; for (var ix = 1; ix < parts.length; ++ix) { if (n.indexOf(parts[ix]) < 0) { match = false; } } return match; } }); if (results.length < 1000) { results = _.sortBy(results, function(r) { return 0 - longestCommonSubstring(string, r.search) - 0.01 * prefixLength(r.seNormalize(), string) }); } var count = results.length; results = results.slice(0, maxResults); results.result_count = count; return results; } })(); var UhrApplication = React.createClass({ getInitialState: function() { autocomplete = new Promise(function(resolve, reject) { $.ajax({ url: '/api/autocomplete', success: function(data) { resolve(data); }.bind(this), error: function(xhr, status, err) { console.error("/api", status, err.toString()); reject(err); }.bind(this) }); }); window.autocomplete = autocomplete; String.prototype.autocomplete = function() { return []; } autocomplete.then(function(data) { String.prototype.autocomplete = function(field) { return data[field].autocompleteFilter(this); } }) return { recordId: null, view: 'list', search: {}, offset: 0, loggedIn: false, autocomplete: autocomplete } }, onNavigate: function(to) { console.debug("onNavigate()", to); this.setState(to); this.refs.nav.setState({ recordId: to.recordId }); }, onRecordClicked: function(record) { this.onNavigate({ view: 'show', recordId: record.Id }); }, render: function() { return (