在单击之前无法选择动态添加的列表项

时间:2013-12-16 20:37:35

标签: javascript jquery html ajax twitter-bootstrap

我编写了一个小的JQuery插件,它基于bootstrap创建了一个下拉框。我已将其写入数据属性提供生成列表项的URL的位置。在ajax调用之后,Jquery遍历列表项并将它们插入到下拉菜单中。这是我不明白的,插件使用.combobox类的div,并附加所需的html来制作组合框。它使用两个函数_create()_listItems()_create()实际上会在_listItems()上添加html和调用以进行ajax调用,并返回要追加的列表项。看起来像这样:

;(function ( $, window, document, undefined ) {

    var Combobox = function(element,options) {
        this.$element = $(element);
        this.$options = $.extend({}, $.fn.combobox.defaults, options);
        this.$html = {
            input: $('<input type="text" placeholder="[SELECT]" />').addClass('form-control'),
            button: $('<div id="test"/>').addClass('input-group-btn')
                .append($('<button />')
                .addClass('btn btn-default input-sm')
                .append('<span class="caret"></span>'))
        }
        this.$list_type = this.$element.attr('data-type');
        this.$url = this.$element.attr('data-url');
        this.$defaultValue = this.$element.attr('data-default');
        this._create();

        this.$input = this.$element.find('input');
        this.$button = this.$element.find('button');
        this.$list = this.$element.find('ul')

        this.$button.on('click',$.proxy(this._toggleList,this));
        this.$element.on('click','li',$.proxy(this._itemClicked,this));
        this.$element.on('mouseleave',$.proxy(this._toggleList,this));

        if(this.$defaultValue) {
            this.selectByValue(this.$defaultValue);
        }
    }


    Combobox.prototype = {
        constructor: Combobox, 

        _create: function() {
            this.$element.addClass('input-group input-group-sm')
                .append(this.$html.input)
                .append(this._listItems())
                .append(this.$html.button); 
        },
        _itemClicked: function(e){
            this.$selectedItem = $(e.target).parent();
            this.$input.val(this.$selectedItem.text());
            console.log(this.$element.find('[data-value="W"]'))
            this._toggleList(e);
            e.preventDefault();
        },
        _listItems: function() {
            var list = $('<ul />').addClass('dropdown-menu');
            $.ajax({
                url: this.$url,
                type: 'POST',
                data: {opt: this.$list_type},
                success:function(data){
                    $.each(data,function(key,text){
                        list.append($('<li class="listObjItem" data-value="'+text.id+'"><a href="#">'+text.value+'</a></li>'));
                    })
                }

            })
            return list
        },
        selectedItem: function() {
            var item = this.$selectedItem;
            var data = {};

            if (item) {
                var txt = this.$selectedItem.text();
                data = $.extend({ text: txt }, this.$selectedItem.data());
            }
            else {
                data = { text: this.$input.val()};
            }

            return data;
        },
        selectByValue: function(value) {
          var selector = '[data-value="'+value+'"]';
          this.selectBySelector(selector);
        },
        selectBySelector: function (selector) {
            var $item = this.$element.find(selector);
            if (typeof $item[0] !== 'undefined') {
                    this.$selectedItem = $item;
                    this.$input.val(this.$selectedItem.text());
            }
            else {
                    this.$selectedItem = null;
            }
        },
        enable: function () {
            this.$input.removeAttr('disabled');
            this.$button.children().removeClass('disabled');
            this.$button.on('click',$.proxy(this._toggleList,this));
        },

        disable: function () {
            this.$input.attr('disabled', true);
            this.$button.children().addClass('disabled');
            this.$button.off('click',$.proxy(this._toggleList,this));
        },
        _toggleList: function(e) {
            if(e.type == 'mouseleave') {
                if(this.$list.is(':hidden')) {
                    return false;
                } else {
                    this.$list.hide();
                }
            } else {
                this.$list.toggle();
                e.preventDefault();
            }

        }


    }

    $.fn.combobox = function (option) {
        return this.each(function () {
            if (!$.data(this, 'combobox')) {
                $.data(this, 'combobox', 
                new Combobox( this, option ));
            }
        });

    };

    $.fn.combobox.defaults = {};

    $.fn.combobox.Constructor = Combobox;

})( jQuery, window, document );

问题是,在将项目附加到DOM之后,一切都可以选择接受列表项目。我目前有一个.on()语句,它将click事件与列表项绑定在一起。为了测试这个,我使用了console.log(this.$element.find('[data-value="W"]')并且它没有返回一个元素,但是如果我将相同的控制台日志放在列表项的单击回调中,它将返回元素并且它是可选的。我做错了吗?

修改

我已粘贴整个插件以避免混淆。

0 个答案:

没有答案