Simple autocomplete

by volter9

HTML

<div id="wrapper">
    <div id="autocomplete"></div>
    <textarea id="editor"></textarea>
    <div id="mirror"></div>
</div>

CSS

#wrapper {
    position: relative;
    top: 0px;
    left: 0px;
    
    height: 200px;
    width: 400px;
}

#editor,
#mirror {
    font-family: monospace;
    font-size: 12px;
    line-height: 100%;
    white-space: pre;
    
    padding: 8px;
    height: 200px;
    width: 400px;
}

#mirror {
    visibility: hidden;
}

#autocomplete {
	background-color: #fff;
	border: 1px solid #ccc;
	font-size: 14px;
	
    position: absolute;
    top: 0px;
    left: 0px;
    
    display: none;
    padding: 4px;
}

JavaScript

function $ (id) {
	return document.getElementById(id);
}

var autocomplete = $('autocomplete'),
	editor = $('editor'),
    mirror = $('mirror');

var words = [
		'str_replace',
		'strstr',
		'die',
		'true',
		'false',
		'exit',
        'md5'
	],
	match = '';

function reflect (textarea, position) {
    var text = textarea.value,
        span = document.createElement('span');
    
    span.innerHTML = text.substr(position);
    text = text.substr(0, position);
    
    mirror.innerHTML = '';
    mirror.appendChild(document.createTextNode(text));
    mirror.appendChild(span);
    
    return {
        x: span.offsetLeft - mirror.offsetLeft,
        y: span.offsetTop - mirror.offsetTop
    };
}

function getMatched (match) {
    if (!match) {
        return [];
    }
    
	return words.filter(function (value) {
        return value.indexOf(match) === 0;
	});
}

function count (occurence, string) {
	return string.split(occurence).length - 1;
}

editor.addEventListener('keyup', function (e) {
	var character = String.fromCharCode(e.keyCode).toLowerCase();
    
    if (e.keyCode === 16) {
        return;
    }
    
    if (e.keyCode === 189) {
        character = '_';
    }
    
	if (e.keyCode === 8) {
		match = match.substr(0, match.length - 1);
	}
	else if (character.match(/[^a-z\_0-9]+/i)) {
		match = '';
	}
	else {
		match += character;
	}
    
	var matches = getMatched(match);
	
	if (matches.length) {
		autocomplete.innerHTML = matches.join('<br/>');
		autocomplete.style.display = 'block';
	
		var position = reflect(this, this.selectionStart - match.length);
        
		autocomplete.style.left = editor.offsetLeft + position.x + 'px';
		autocomplete.style.top = editor.offsetTop + 14 + position.y + 'px';
	}
	else {
		autocomplete.style.display = 'none';
	}
});