define([
    "hr/utils",
    "hr/dom",
    "hr/hr",
    "views/dialogs/input"
], function(_, $, hr, DialogInputView) {
    var ListItem = hr.List.Item.extend({
        className: "list-item",

        initialize: function(options) {
            ListItem.__super__.initialize.apply(this, arguments);

            this.dialogContent = this.list.parent;
        },

        template: function() {
            return this.dialogContent.options.template;
        },
        templateContext: function() {
            return {
                item: this.model
            };
        }
    });

    var ListView = hr.List.extend({
        Item: ListItem,
        className: "ui-content-list"
    });

    var DialogListView = DialogInputView.extend({
        className: "",
        defaults: {},
        className: "dialog-list",

        initialize: function() {
            DialogListView.__super__.initialize.apply(this, arguments);

            // Source for items
            this.results = new hr.Collection();
            this.source = _.constant([]);

            if (this.options.source instanceof hr.Collection) {
                // Source is a collection
                this.results = new this.options.source.constructor()
                this.source = function(q) {
                    return this.options.source.filter(function(model) {
                        return this.searchText(model, q);
                    }, this);
                }.bind(this);
            } else {
                this.source = Q(this.options.source);
            }

            // Filter for items
            this.$filterInput = $("<input>", {
                'type': "text",
                'placeholder': this.options.placeholder
            });
            this.keydownInterval = null;
            this.$filterInput.on("keydown", this.onFilterKeydown.bind(this));
            this.$filterInput.on("keyup", this.onFilterKeyup.bind(this));
            this.$filterInput.appendTo(this.$el);

            // Items list
            this.list = new ListView({
                collection: this.results
            }, this);
            this.list.appendTo(this.$el);

            // Focus input
            this.listenTo(this.parent, "open", function() {
                this.$filterInput.focus();
                this.doSearch("");
                this.selectItem(0);
            });
        },

        render: function() {
            return this.ready();
        },

        searchText: function(model, q) {
            var t = JSON.stringify(model.toJSON());

            t = t.toLowerCase();
            q = q.toLowerCase();
            return t.search(q) !== -1;
        },

        doSearch: function(query) {
            var that = this, toRemove = [];
            if (this.list.collection.query == query) return;

            if (this.list.collection.query && query
            && query.indexOf(this.list.collection.query) == 0) {
                // Continue current search
                this.list.collection.query = query;
                this.list.collection.each(function(model) {
                    if (!that.searchText(model, query)) {
                        toRemove.push(model);
                    }
                });
                this.list.collection.remove(toRemove);
                //this.list.collection.sort();
                this.selectItem(this.getSelectedItem());
            } else {
                // Different search
                this.list.collection.query = query;
                this.list.collection.reset([]);

                Q()
                .then(function() {
                    return that.source(query);
                })
                .then(function(result) {
                    that.list.collection.add(_.filter(result, that.options.filter));
                    that.selectItem(that.getSelectedItem());
                }, console.error.bind(console));
            }
        },

        selectItem: function(i) {
            var i, boxH = this.list.$el.height();

            this.selected = i;

            if (this.selected >= this.list.collection.size()) this.selected = this.list.collection.size() - 1;
            if (this.selected < 0) this.selected = 0;

            i = 0;
            this.list.collection.each(function(model) {
                var y, h, item = this.list.items[model.id];
                item.$el.toggleClass("active", i == this.selected);

                if (i == this.selected) {
                    h = item.$el.outerHeight();
                    y = item.$el.position().top;

                    if (y > (boxH-(h/2))) {
                        this.list.$el.scrollTop((i+1)*h - boxH)
                    } else if (y <= (h/2)) {
                        this.list.$el.scrollTop((i)*h)
                    }
                }

                i = i + 1;
            }, this);
        },

        getSelectedItem: function() {
            var _ret = 0;
            this.list.collection.each(function(model, i) {
                var item = this.list.items[model.id];
                if (item.$el.hasClass("active")) {
                    _ret = i;
                    return false;
                }
            }, this);
            return _ret;
        },

        getValue: function() {
            return this.list.collection.at(this.getSelectedItem());
        },

        onFilterKeydown: function(e) {
            var key = e.which || e.keyCode;

            if (key == 38 || key == 40 || key == 13) {
                e.preventDefault();
            }

            var interval = function() {
                var selected = this.getSelectedItem();
                var pSelected = selected;

                if (key == 38) {
                    /* UP */
                    selected = selected - 1;
                } else if (key == 40) {
                    /* DOWN */
                    selected = selected + 1;
                }
                if (selected != pSelected) this.selectItem(selected);
            }.bind(this);

            if (this.keydownInterval) {
                clearInterval(this.keydownInterval);
                this.keydownInterval = null;
            }
            interval();
            this.keydownInterval = setInterval(interval, 600);
        },
        onFilterKeyup: function(e) {
            var q = this.$filterInput.val().toLowerCase();

            this.doSearch(q);

            if (this.keydownInterval) {
                clearInterval(this.keydownInterval);
                this.keydownInterval = null;
            }
        }
    });

    return DialogListView;
});
@@ -1032,22 +1032,27 @@
 e = 
-_.constant(%5B%5D)
+this.options.source
 ;%0A%0A 
@@ -1476,83 +1476,8 @@
    %7D
- else %7B%0A                this.source = Q(this.options.source);%0A            %7D
 %0A%0A  

Fix dialog list when source is a function