diff --git a/select2.js b/select2.js
index c17781bb..e883641c 100755
--- a/select2.js
+++ b/select2.js
@@ -298,37 +298,63 @@
                 query.callback(data);
             });
         } else {
-            if (!("query" in opts) && opts.ajax) {
-                opts.query = (function () {
-                    var timeout, // current scheduled but not yet executed request
-                        requestSequence = 0, // sequence used to drop out-of-order responses
-                        quietMillis = opts.ajax.quietMillis || 100;
+            if (!("query" in opts)) {
+                if ("ajax" in opts) {
+                    opts.query = (function () {
+                        var timeout, // current scheduled but not yet executed request
+                            requestSequence = 0, // sequence used to drop out-of-order responses
+                            quietMillis = opts.ajax.quietMillis || 100;
 
-                    return function (query) {
-                        window.clearTimeout(timeout);
-                        timeout = window.setTimeout(function () {
-                            requestSequence += 1; // increment the sequence
-                            var requestNumber = requestSequence, // this request's sequence number
-                                options = opts.ajax, // ajax parameters
-                                data = options.data; // ajax data function
+                        return function (query) {
+                            window.clearTimeout(timeout);
+                            timeout = window.setTimeout(function () {
+                                requestSequence += 1; // increment the sequence
+                                var requestNumber = requestSequence, // this request's sequence number
+                                    options = opts.ajax, // ajax parameters
+                                    data = options.data; // ajax data function
 
-                            data = data.call(this, query.term, query.page);
+                                data = data.call(this, query.term, query.page);
 
-                            $.ajax({
-                                url: options.url,
-                                dataType: options.dataType,
-                                data: data
-                            }).success(
-                                function (data) {
-                                    if (requestNumber < requestSequence) {
-                                        return;
+                                $.ajax({
+                                    url: options.url,
+                                    dataType: options.dataType,
+                                    data: data
+                                }).success(
+                                    function (data) {
+                                        if (requestNumber < requestSequence) {
+                                            return;
+                                        }
+                                        query.callback(options.results(data, query.page));
                                     }
-                                    query.callback(options.results(data, query.page));
-                                }
-                            );
-                        }, quietMillis);
-                    };
-                }());
+                                );
+                            }, quietMillis);
+                        };
+                    }());
+                } else if ("data" in opts) {
+                    opts.query = (function () {
+                        var data = opts.data, // data elements
+                            text = function (item) { return item.text; }; // function used to retrieve the text portion of a data item that is matched against the search
+
+                        if (!$.isArray(data)) {
+                            text = data.text;
+                            // if text is not a function we assume it to be a key name
+                            if (!$.isFunction(text)) text = function (item) { return item[data.text]; };
+                            data = data.results;
+                        }
+
+                        return function (query) {
+                            var t = query.term.toUpperCase(), filtered = {};
+                            if (t === "") {
+                                query.callback({results: data});
+                                return;
+                            }
+                            filtered.result = $(data)
+                                .filter(function () {return text(this).toUpperCase().indexOf(t) >= 0;})
+                                .get();
+                            query.callback(filtered);
+                        };
+                    }());
+                }
             }
         }
         if (typeof(opts.query) !== "function") {