Fork me on GitHub.

Demo

Basic Usage

#textarea1
$('#textarea1').textcomplete([
    { // emoji strategy
        id: 'emoji',
        match: /\B:([\-+\w]*)$/,
        search: function (term, callback) {
            callback($.map(emojies, function (emoji) {
                return emoji.indexOf(term) === 0 ? emoji : null;
            }));
        },
        template: function (value) {
            return '<img src="media/images/emoji/' + value + '.png"></img>' + value;
        },
        replace: function (value) {
            return ':' + value + ': ';
        },
        index: 1
    },
    { // tech companies
        id: 'tech-companies',
        words: ['apple', 'google', 'facebook', 'github'],
        match: /\b(\w{2,})$/,
        search: function (term, callback) {
            callback($.map(this.words, function (word) {
                return word.indexOf(term) === 0 ? word : null;
            }));
        },
        index: 1,
        replace: function (word) {
            return word + ' ';
        }
    }
], {
    onKeydown: function (e, commands) {
        if (e.ctrlKey && e.keyCode === 74) { // CTRL-J
            return commands.KEY_ENTER;
        }
    }
});

Insert Cursor After Autocomplete

#textarea2
var elements = ['span', 'div', 'h1', 'h2', 'h3'];
$('#textarea2').textcomplete([
    { // html
        match: /<(\w*)$/,
        search: function (term, callback) {
            callback($.map(elements, function (element) {
                return element.indexOf(term) === 0 ? element : null;
            }));
        },
        index: 1,
        replace: function (element) {
            return ['<' + element + '>', '</' + element + '>'];
        }
    }
]);

Use with jQuery.overlay

#textarea3
$('#textarea3').textcomplete([
    { // html
        mentions: ['yuku_t'],
        match: /\B@(\w*)$/,
        search: function (term, callback) {
            callback($.map(this.mentions, function (mention) {
                return mention.indexOf(term) === 0 ? mention : null;
            }));
        },
        index: 1,
        replace: function (mention) {
            return '@' + mention + ' ';
        }
    }
], { appendTo: 'body' }).overlay([
    {
        match: /\B@\w+/g,
        css: {
            'background-color': '#d8dfea'
        }
    }
]);

Apply to Multiple Textareas

.textarea4
.textarea4
$('.textarea4').textcomplete([
    { // tech companies
        words: ['apple', 'google', 'facebook', 'github'],
        match: /\b(\w{2,})$/,
        search: function (term, callback) {
            callback($.map(this.words, function (word) {
                return word.indexOf(term) === 0 ? word : null;
            }));
        },
        index: 1,
        replace: function (word) {
            return word + ' ';
        }
    }
]);
#textarea5
$('#textarea5').textcomplete([
    { // emoji strategy
        match: /\B:([\-+\w]*)$/,
        search: function (term, callback) {
            callback($.map(emojies, function (emoji) {
                return emoji.indexOf(term) === 0 ? emoji : null;
            }));
        },
        template: function (value) {
            return '<img src="media/images/emoji/' + value + '.png"></img>' + value;
        },
        replace: function (value) {
            return ':' + value + ': ';
        },
        index: 1
    }
], {
    header: function (data) {
        return '<strong style="text-align: center; display: block;">' + data.length + '</strong>';
    },
    footer: '<strong style="text-align: center; display: block;">Footer</strong>'
});

Apply to Contenteditables

.contenteditable1
Look at this glorious contenteditable.
$('.contenteditable1').textcomplete([
    {
        words: ['stunning', 'amazing', 'incredible', 'fantastic', 'fantabulous'],
        match: /\b(\w{2,})$/,
        search: function (term, callback) {
            callback($.map(this.words, function (word) {
                return word.indexOf(term) === 0 ? word : null;
            }));
        },
        index: 1,
        replace: function (word) {
            return word + ' ';
        }
    }
]);

Simple Markdown editor

#textarea6
var isInCode = false
function check(text) {
    var match;
    match = text.match(/`{3,}/g);
    if (match && match.length % 2) {
        isInCode = true;
    } else {
        match = text.match(/`/g);
        if (match && match.length % 2) {
            isInCode = true;
        } else {
            isInCode = false;
        }
    }
}
$('#textarea6').textcomplete([
    { // emoji strategy
        match: /\B:([\-+\w]*)$/,
        search: function (term, callback) {
            callback($.map(emojies, function (emoji) {
                return emoji.indexOf(term) === 0 ? emoji : null;
            }));
        },
        template: function (value) {
            return '<img src="media/images/emoji/' + value + '.png"></img>' + value;
        },
        replace: function (value) {
            return ':' + value + ': ';
        },
        index: 1,
        context: function (text) {
            check(text);
            return !isInCode;
        }
    },
    { // Code block language strategy
        langs: ['js', 'rb', 'py', 'pl'],
        match: /(^|\n)```(\w*)$/,
        search: function (term, callback) {
            callback($.map(this.langs, function (lang) {
                return lang.indexOf(term) === 0 ? lang : null;
            }));
        },
        replace: function (lang) {
            return '$1```' + lang + '\n';
        },
        context: function () { return isInCode; }
    }
]);

Input element

$('#input1').textcomplete([
    { // tech companies
        words: ['apple', 'google', 'facebook', 'github'],
        match: /\b(\w{2,})$/,
        search: function (term, callback) {
            callback($.map(this.words, function (word) {
                return word.indexOf(term) === 0 ? word : null;
            }));
        },
        index: 1,
        replace: function (word) {
            return word + ' ';
        }
    }
]);

Input[type=search] element

$('#input2').textcomplete([
    {
        words: ['apple', 'google', 'facebook', 'github'],
        match: /\b(\w{2,})$/,
        search: function (term, callback) {
            callback($.map(this.words, function (word) {
                return word.indexOf(term) === 0 ? word : null;
            }));
        },
        index: 1,
        replace: function (word) {
            return word + ' ';
        }
    }
]);

Change dropdown class name

Use dropdownClassName option to change the class attribute of the dropdown element.

#textarea7
$('#textarea7').textcomplete([
    {
        words: ['apple', 'google', 'facebook', 'github'],
        match: /\b(\w{2,})$/,
        search: function (term, callback) {
            callback($.map(this.words, function (word) {
                return word.indexOf(term) === 0 ? word : null;
            }));
        },
        index: 1,
        replace: function (word) {
            return word + ' ';
        }
    }
], {
  dropdownClassName: 'dropdown-menu-textcomplete'
});

License

MIT