<div id="one" class="url-container">
<input class="url" type="text" value=''/>
<style></style>
<div class="results"></div>
</div>
.url-container {
position: relative;
width: 50%;
overflow: hidden;
border: 1px solid black;
}
.url-container .result {
font-family: sans-serif;
padding: 10px;
}
.url-container .selected {
background: #efefef;
}
.url-container input {
padding: 10px;
width: 100%;
font-size: 16px;
font-family: sans-serif;
color: black;
background: transparent;
-webkit-appearance: none;
outline: none;
border: none;
}
.url-container:before {
position: absolute;
z-index: -1;
font-size: 16px;
font-family: sans-serif;
color: gray;
left: 0;
top: 0;
padding: 10px;
display: block;
width: 100%;
height: 100%;
pointer-events: none;
}
function SmartInput(el, params) {
this.el = el;
this.id = el.attr('id');
this.input = el.find('input');
this.input
.on('change', this.onChange.bind(this))
.on('input', this.onInput.bind(this))
.on('keydown', this.onKeyDown.bind(this));
this.style = el.find('style');
this.resultList = el.find('.results');
this.predict = '';
this.prefix = params.prefix || '$$$';
this.index = -1;
this.results = [];
}
SmartInput.prototype = {
beforeRule() {
return `#${this.id}:before{ content: '${this.predict}' !important; }`;
},
onKeyDown(e) {
if (e.which === 13) { // enter
this.onChange();
} if (e.which === 39) { // right arrow
this.input.val(this.predict);
} else if (this.results.length > 0) {
if (e.which === 40) { // down arrow
this.index++;
if (this.index > this.results.length - 1) this.index = 0;
} else if (e.which === 38) { // up arrow
this.index--;
if (this.index < -1) this.index = this.results.length - 1;
}
let results = this.resultList
.find('.result')
.removeClass('selected');
this.predictedVal = null;
if (this.index !== -1) {
this.predictedVal = results
.eq(this.index)
.addClass('selected')
.text();
}
}
},
onChange(e) {
let inputVal = this.predictedVal || this.input.val(),
key = this.prefix + inputVal;
if (!localStorage[key]) {
localStorage[key] = 0;
} else {
let val = localStorage[key];
localStorage[key] = parseFloat(val) + 1;
}
console.log('send:', inputVal);
this.input.val(inputVal);
this.clearPredictions();
},
sortResults(a, b) {
let valA = parseFloat(a.rank),
valB = parseFloat(b.rank);
return valB - valA;
},
clearPredictions() {
this.index = -1;
this.resultList.html('');
this.style.html('');
},
onInput(e) {
let results = [],
leng = localStorage.length,
val = this.input.val().trim(),
regex = new RegExp('^' + val);
this.clearPredictions();
if (val.length === 0) { return; }
for (var i = 0; i < leng; i++){
let key = localStorage.key(i), cleanKey;
if (key.indexOf(this.prefix) !== -1) {
cleanKey = key.replace(this.prefix, '');
if (regex.test(cleanKey)) {
results.push({key: cleanKey, rank: localStorage[key]});
}
}
}
if (results.length > 0) {
this.results = results;
results.sort(this.sortResults);
this.predict = results.shift().key;
this.style.html(this.beforeRule());
for (let i = 0; i < results.length; i++) {
if (results[i]) {
let r = $('<div class="result">').html(results[i].key);
r.appendTo(this.resultList);
}
}
} else {
this.style.html('');
}
}
};
let smarty = new SmartInput($('#one'), { prefix: '$$one_' });
View Compiled
This Pen doesn't use any external CSS resources.