var TabCompletion = Class.create({ initialize: function(element) { this.element = $(element); this.matches = []; this.match_offset = 0; this.cycling = false; this.has_focus = true; document.observe('keydown', this.keyboardEvents.bindAsEventListener(this)); this.element.observe('focus', this.onFocus.bindAsEventListener(this)); this.element.observe('blur', this.onBlur.bindAsEventListener(this)); this.element.observe('click', this.onFocus.bindAsEventListener(this)); }, onBlur: function() { this.has_focus = false; this.reset(); }, onFocus: function() { this.has_focus = true; this.reset(); }, tabSearch: function(input) { var names = $$('#names li').collect(function(element) { return element.innerHTML }); return names.findAll(function(name) { return name.toLowerCase().match(input.toLowerCase()) }); }, textToLeft: function() { var text = this.element.value; var caret_position = FormHelpers.getCaretPosition(this.element); if (caret_position < text.length) { text = text.slice(0, caret_position); } text = text.split(' ').last(); return text; }, elementFocused: function(e) { if (typeof document.activeElement == 'undefined') { return this.has_focus; } else { return document.activeElement == this.element; } }, keyboardEvents: function(e) { if (this.elementFocused()) { switch (e.keyCode) { case Event.KEY_TAB: var caret_position = FormHelpers.getCaretPosition(this.element); if (this.element.value.length > 0) { var search_text = ''; var search_result = ''; var replace_inline = false; var editedText = this.element.value.match(/[^a-z0-9]/i); if (this.cycling) { if (this.element.value == '#{last_result}: '.interpolate({ last_result: this.last_result })) { editedText = false; } else { replace_inline = true; } search_text = this.last_result; } else if (editedText && this.matches.length == 0) { search_text = this.textToLeft(); replace_inline = true; } else { search_text = this.element.value; } if (this.matches.length == 0) { this.matches = this.tabSearch(search_text); search_result = this.matches.first(); this.cycling = true; } else { this.match_offset++; if (this.match_offset >= this.matches.length) { this.match_offset = 0; } search_result = this.matches[this.match_offset]; } if (search_result && search_result.length > 0) { if (this.cycling && this.last_result) { search_text = this.last_result; } this.last_result = search_result; if (replace_inline) { var slice_start = caret_position - search_text.length; if (slice_start > 0) { this.element.value = this.element.value.substr(0, slice_start) + search_result + this.element.value.substr(caret_position, this.element.value.length); FormHelpers.setCaretPosition(this.element, slice_start + search_result.length); } } else if (!editedText) { this.element.value = '#{search_result}: '.interpolate({ search_result: search_result }); } } } Event.stop(e); return false; break; default: this.reset(); break; } } }, reset: function() { this.matches = []; this.match_offset = 0; this.last_result = null; this.cycling = false; } });