【问题标题】:How to reload jquery dropkick object如何重新加载 jquery dropkick 对象
【发布时间】:2012-02-01 16:12:14
【问题描述】:

我使用了一个简单的选择列表和 jquery.dropkick 库来使其美观。 现在我想在更改相应的选择元素后更改该 dropkick 内容(出现了一个新选项)。但只是调用 $('#select').dropkick();没用。

而且它看起来不受支持。 从头开始重建那个dropkick就足够了。是否有可能“销毁”该 dropkick 对象,然后通过调用 .dropkick() 方法重建它?

【问题讨论】:

    标签: jquery select reload jquery-dropkick


    【解决方案1】:
    $('#select').html('<option>a</option>').dropkick('refresh');
    

    【讨论】:

    • 请简单介绍一下
    • 谢谢。这是官方文档中没有的更简洁明了的方式。
    【解决方案2】:

    我利用 Diode 的回答修改了 Dropkick 代码,使其更简洁:

    // Reload the dropkick select widget after options have changed
    // usage: $("...").dropkick('reload');
    methods.reload = function () {
        var $select = $(this);
        var data = $select.data('dropkick');
        $select.removeData("dropkick");
        $("#dk_container_"+ data.id).remove();
        $select.dropkick(data.settings);
    };
    

    在 dropkick.js 中的以下 sn-p 之后添加上面的代码:

    methods.reset = function () {
      ...
    };
    

    然后您可以通过编程方式使用它:

        $('#my-select').html("<option>new options</option>");
        $('#my-select').dropkick('reload');
    

    【讨论】:

    • 如下面其他 cmets 所述,您现在可以调用 $(selector).dropkick('reset') 而无需修改核心;
    【解决方案3】:

    我遇到了同样的问题,我对 jquery-dropkick-1.0.0 脚本做了一些补丁来解决这个问题。我向 dropkick 对象添加了 forceSyncWithSelect 方法。

    这是我所做的更改列表:

    • 添加对标签的支持
    • 添加 autoWidth 设置以将宽度留给 css
    • 为打开、关闭、forceSyncWithSelect 和 isDropkicked 添加方法
    • 保持默认tabindex 0
    • 在 optgroup 元素上添加带有 data-dkgroupclass 属性的 optgroup 类选项
    • 修复 forceSyncWithSelect 方法,如果值多次出现,则仅采用第一次出现
    • 点击菜单选择切换
    • 防止 IE 在滚动条交互时关闭菜单(滚动条交互时会启动模糊事件,这种行为非常错误)

    您可能不希望所有这些更改,但您可以制作一个差异补丁并获取您需要的内容(如果您让更改日志或将其源添加到标题中会很高兴,我想向 Jamie 提出这些更改抽奖,但我需要创建一个 git hub 帐户才能这样做。

    /**
     * DropKick
     *
     * Highly customizable <select> lists
     * https://github.com/JamieLottering/DropKick
     *
     * &copy; 2011 Jamie Lottering <http://github.com/JamieLottering>
     *                        <http://twitter.com/JamieLottering>
     *
     * Patch:
     *  - 2012-03-30 godboutj, add support for <optgroup> tag
     *  - 2012-03-30 godboutj, add autoWidth settings to leave width to css
     *  - 2012-05-25 godboutj, add method for open, close, forceSyncWithSelect and isDropkicked
     *  - 2012-05-25 godboutj, keep default tabindex 0
     *  - 2012-08-09 godboutj, add optgroup class option with the data-dkgroupclass attribute on optgroup element
     *  - 2012-08-15 godboutj, fix forceSyncWithSelect method if value appear multiple of time, take the first occurrence only
     *  - 2012-09-07 godboutj, toggle on click on the menu selection
     *  - 2012-09-25 godboutj, prevent IE from closing the menu on scroll bar interaction (a blur event is launched on scroll bar interaction, this behavior is so wrong)
     */
    (function ($, window, document)
    {
    
        var ie6 = false;
    
        // Help prevent flashes of unstyled content
        if ($.browser.msie && $.browser.version.substr(0, 1) < 7)
        {
            ie6 = true;
        } else
        {
            document.documentElement.className = document.documentElement.className + ' dk_fouc';
        }
    
        var 
        // Public methods exposed to $.fn.dropkick()
        methods = {},
    
        // Cache every <select> element that gets dropkicked
        lists = [],
    
        // Convenience keys for keyboard navigation
        keyMap = {
            'left': 37,
            'up': 38,
            'right': 39,
            'down': 40,
            'enter': 13
        },
    
        // HTML template for the dropdowns
        dropdownTemplate = [
          '<div class="dk_container" id="dk_container_{{ id }}" tabindex="{{ tabindex }}">',
            '<a class="dk_toggle">',
              '<span class="dk_label">{{ label }}</span>',
            '</a>',
            '<div class="dk_options">',
              '<ul class="dk_options_inner">',
              '</ul>',
            '</div>',
          '</div>'
        ].join(''),
    
        // HTML template for dropdown options
        optionTemplate = '<li class="{{ current }}"><a data-dk-dropdown-value="{{ value }}">{{ text }}</a></li>',
        optionGroupTemplate = '<li class="dk_option_group {{ dataclass }}"><div class="dk_option_group_text">{{ text }}</div></li>',
    
        // Some nice default values
        defaults = {
            startSpeed: 1000,  // I recommend a high value here, I feel it makes the changes less noticeable to the user
            theme: false,
            change: false,
            autoWidth: true
        },
    
        // Make sure we only bind keydown on the document once
        keysBound = false
      ;
    
        // Called by using $('foo').dropkick();
        methods.init = function (settings)
        {
            settings = $.extend({}, defaults, settings);
    
            return this.each(function ()
            {
                var 
                // The current <select> element
                $select = $(this),
    
                // Store a reference to the originally selected <option> element
                $original = $select.find(':selected').first(),
    
                // Save all of the <option> and <optgroup> elements
                $options = $select.children('option,optgroup'),
    
                // We store lots of great stuff using jQuery data
                data = $select.data('dropkick') || {},
    
                // This gets applied to the 'dk_container' element
                id = $select.attr('id') || $select.attr('name'),
    
                // This gets updated to be equal to the longest <option> element
                width = settings.width || $select.outerWidth(),
    
                // Keep tabindex, even default value
                tabindex = ($select.attr('tabindex') != null && $select.attr('tabindex') != undefined) ? $select.attr('tabindex') : '',
    
                // The completed dk_container element
                $dk = false,
    
                theme
          ;
    
                // Dont do anything if we've already setup dropkick on this element
                if (data.id)
                {
                    return $select;
                }
                else
                {
                    data.settings = settings;
                    data.tabindex = tabindex;
                    data.id = id;
                    data.$original = $original;
                    data.$select = $select;
                    data.value = _notBlank($select.val()) || _notBlank($original.attr('value'));
                    data.label = $original.text();
                    data.options = $options;
                }
    
                // Build the dropdown HTML
                $dk = _build(dropdownTemplate, data);
    
                // Make the dropdown fixed width if desired
                if (settings.autoWidth)
                {
                    $dk.find('.dk_toggle').css({
                        'width': width + 'px'
                    });
                }
                // Hide the <select> list and place our new one in front of it
                $select.before($dk);
    
                // Update the reference to $dk
                $dk = $('#dk_container_' + id).fadeIn(settings.startSpeed);
    
                // Save the current theme
                theme = settings.theme ? settings.theme : 'default';
                $dk.addClass('dk_theme_' + theme);
                data.theme = theme;
    
                // Save the updated $dk reference into our data object
                data.$dk = $dk;
    
                // Save the dropkick data onto the <select> element
                $select.data('dropkick', data);
    
                // Do the same for the dropdown, but add a few helpers
                $dk.data('dropkick', data);
    
                lists[lists.length] = $select;
    
                // Focus events
                $dk.bind('focus.dropkick', function (e)
                {
                    $dk.addClass('dk_focus');
                }).bind('blur.dropkick', function (e)
                {
                    // Prevent IE from closing the menu on focus loose, 
                    // this make the menu close all the time when using the scroll bar
                    if (!$.browser.msie)
                    {
                        $dk.removeClass('dk_open');
                    }
                    $dk.removeClass('dk_focus');
                });
    
                setTimeout(function ()
                {
                    $select.hide();
                }, 0);
            });
        };
    
        // Allows dynamic theme changes
        methods.theme = function (newTheme)
        {
            var 
          $select = $(this),
          list = $select.data('dropkick'),
          $dk = list.$dk,
          oldtheme = 'dk_theme_' + list.theme
        ;
    
            $dk.removeClass(oldtheme).addClass('dk_theme_' + newTheme);
    
            list.theme = newTheme;
        };
    
        // Force Value sync
        methods.forceSyncWithSelect = function ()
        {
            var 
                $select = $(this),
                $dk = $select.data('dropkick').$dk,
                $current = $dk.find("li [data-dk-dropdown-value='" + $select.val() + "']").first()
            ;
            _updateFields($current, $dk, true);
        };
    
        // Reset all <selects and dropdowns in our lists array
        methods.reset = function ()
        {
            for (var i = 0, l = lists.length; i < l; i++)
            {
                var 
            listData = lists[i].data('dropkick'),
            $dk = listData.$dk,
            $current = $dk.find('li').first()
          ;
    
                $dk.find('.dk_label').text(listData.label);
                $dk.find('.dk_options_inner').animate({ scrollTop: 0 }, 0);
    
                _setCurrent($current, $dk);
                _updateFields($current, $dk, true);
            }
        };
    
        methods.close = function ()
        {
            var 
                $select = $(this),
                $dk = $select.data('dropkick').$dk
            ;
            _closeDropdown($dk);
        }
    
        methods.open = function ()
        {
            var 
                $select = $(this),
                $dk = $select.data('dropkick').$dk
            ;
            _openDropdown($dk);
        }
    
        methods.isOpen = function ()
        {
            var 
                $select = $(this),
                $dk = $select.data('dropkick').$dk
            ;
            return _isDropdownOpenned($dk);
        }
    
        methods.toggleOpen = function ()
        {
            var 
                $select = $(this),
                $dk = $select.data('dropkick').$dk
            ;
            _toggleOpenCloseDropDown($dk);
        }
    
        methods.isDropkicked = function ()
        {
            var $select = $(this);
            return $select.data('dropkick') != undefined;
        }
    
        // Expose the plugin
        $.fn.dropkick = function (method)
        {
            if (!ie6)
            {
                if (methods[method])
                {
                    return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
                } else if (typeof method === 'object' || !method)
                {
                    return methods.init.apply(this, arguments);
                }
            }
        };
    
        // private
        function _handleKeyBoardNav(e, $dk)
        {
            var 
          code = e.keyCode,
          data = $dk.data('dropkick'),
          options = $dk.find('.dk_options'),
          open = $dk.hasClass('dk_open'),
          current = $dk.find('.dk_option_current'),
          first = options.find('li').first(),
          last = options.find('li').last(),
          next,
          prev
        ;
    
            switch (code)
            {
                case keyMap.enter:
                    if (open)
                    {
                        _updateFields(current.find('a'), $dk);
                        _closeDropdown($dk);
                    } else
                    {
                        _openDropdown($dk);
                    }
                    e.preventDefault();
                    break;
    
                case keyMap.up:
                    prev = current.prev('li');
                    if (open)
                    {
                        if (prev.length)
                        {
                            _setCurrent(prev, $dk);
                        } else
                        {
                            _setCurrent(last, $dk);
                        }
                    } else
                    {
                        _openDropdown($dk);
                    }
                    e.preventDefault();
                    break;
    
                case keyMap.down:
                    if (open)
                    {
                        next = current.next('li').first();
                        if (next.length)
                        {
                            _setCurrent(next, $dk);
                        } else
                        {
                            _setCurrent(first, $dk);
                        }
                    } else
                    {
                        _openDropdown($dk);
                    }
                    e.preventDefault();
                    break;
    
                default:
                    break;
            }
        }
    
        // Update the <select> value, and the dropdown label
        function _updateFields(option, $dk, reset)
        {
            var value, label, data;
    
            value = option.attr('data-dk-dropdown-value');
            label = option.text();
            data = $dk.data('dropkick');
    
            $select = data.$select;
            $select.val(value);
    
            $dk.find('.dk_label').text(label);
    
            reset = reset || false;
    
            if (data.settings.change && !reset)
            {
                data.settings.change.call($select, value, label);
            }
        }
    
        // Set the currently selected option
        function _setCurrent($current, $dk)
        {
            $dk.find('.dk_option_current').removeClass('dk_option_current');
            $current.addClass('dk_option_current');
    
            _setScrollPos($dk, $current);
        }
    
        function _setScrollPos($dk, anchor)
        {
            var height = anchor.prevAll('li').outerHeight() * anchor.prevAll('li').length;
            $dk.find('.dk_options_inner').animate({ scrollTop: height + 'px' }, 0);
        }
    
        // Is dropdown openned function 
        function _isDropdownOpenned($dk)
        {
            return $dk.hasClass('dk_open');
        }
    
        // Close a dropdown
        function _closeDropdown($dk)
        {
            $dk.removeClass('dk_open');
        }
    
        // Open a dropdown
        function _openDropdown($dk)
        {
            var data = $dk.data('dropkick');
            $dk.find('.dk_options').css({ top: $dk.find('.dk_toggle').outerHeight() - 1 });
            if (!$dk.hasClass('dk_open'))
            {
                $dk.addClass('dk_open');
            }
        }
    
        // Toggle dropdown
        function _toggleOpenCloseDropDown($dk)
        {
            if (_isDropdownOpenned($dk))
            {
                _closeDropdown($dk);
            }
            else
            {
                _openDropdown($dk);
            }
        }
    
        /**
        * Turn the dropdownTemplate into a jQuery object and fill in the variables.
        */
        function _build(tpl, view)
        {
            var 
            // Template for the dropdown
                template = tpl,
            // Holder of the dropdowns options
                options = [],
                $dk
            ;
    
            template = template.replace('{{ id }}', view.id);
            template = template.replace('{{ label }}', view.label);
            template = template.replace('{{ tabindex }}', view.tabindex);
    
            if (view.options && view.options.length)
            {
                for (var i = 0, l = view.options.length; i < l; i++)
                {
                    var 
                      $option = $(view.options[i]),
                      current = 'dk_option_current',
                      oTemplate = optionTemplate,
                      gTemplate = optionGroupTemplate
                    ;
    
                    if ($option.is('optgroup'))
                    {
                        gTemplate = gTemplate.replace('{{ text }}', $option.attr('label'));
                        if ($option.attr('data-dkgroupclass') != undefined)
                        {
                            gTemplate = gTemplate.replace('{{ dataclass }}', $option.attr('data-dkgroupclass'));
                        }
                        // Support only one level as per W3C standard
                        $option.children('option').each(
                            function (index, element)
                            {
                                oTemplate = optionTemplate,
                                oTemplate = oTemplate.replace('{{ value }}', $(element).val());
                                oTemplate = oTemplate.replace('{{ current }}', (_notBlank($(element).val()) === view.value) ? current : '');
                                oTemplate = oTemplate.replace('{{ text }}', $(element).text());
                                gTemplate += oTemplate;
                            }
                        );
    
                        options[options.length] = gTemplate;
                    }
                    else
                    {
                        oTemplate = oTemplate.replace('{{ value }}', $option.val());
                        oTemplate = oTemplate.replace('{{ current }}', (_notBlank($option.val()) === view.value) ? current : '');
                        oTemplate = oTemplate.replace('{{ text }}', $option.text());
    
                        options[options.length] = oTemplate;
                    }
                }
            }
    
            $dk = $(template);
            $dk.find('.dk_options_inner').html(options.join(''));
    
            return $dk;
        }
    
        function _notBlank(text)
        {
            return ($.trim(text).length > 0) ? text : false;
        }
    
        $(function ()
        {
    
            // Handle click events on the dropdown toggler
            $('.dk_toggle').live('click', function (e)
            {
                var $dk = $(this).parents('.dk_container').first();
    
                _toggleOpenCloseDropDown($dk);
    
                if ("ontouchstart" in window)
                {
                    $dk.addClass('dk_touch');
                    $dk.find('.dk_options_inner').addClass('scrollable vertical');
                }
    
                e.preventDefault();
                return false;
            });
    
            // Handle click events on individual dropdown options
            $('.dk_options a').live(($.browser.msie ? 'mousedown' : 'click'), function (e)
            {
                var 
            $option = $(this),
            $dk = $option.parents('.dk_container').first(),
            data = $dk.data('dropkick')
          ;
    
                _closeDropdown($dk);
                _updateFields($option, $dk);
                _setCurrent($option.parent(), $dk);
    
                e.preventDefault();
                return false;
            });
    
            // Setup keyboard nav
            $(document).bind('keydown.dk_nav', function (e)
            {
                var 
                // Look for an open dropdown...
            $open = $('.dk_container.dk_open'),
    
                // Look for a focused dropdown
            $focused = $('.dk_container.dk_focus'),
    
                // Will be either $open, $focused, or null
            $dk = null
          ;
    
                // If we have an open dropdown, key events should get sent to that one
                if ($open.length)
                {
                    $dk = $open;
                } else if ($focused.length && !$open.length)
                {
                    // But if we have no open dropdowns, use the focused dropdown instead
                    $dk = $focused;
                }
    
                if ($dk)
                {
                    _handleKeyBoardNav(e, $dk);
                }
            });
        });
    })(jQuery, window, document);
    

    【讨论】:

    • 您能否将您的代码缩减为理解问题所必需的内容?
    【解决方案4】:

    对于新的访问者。 Dropkick 使用重置方法...而不是重绘。

    $("select").dropkick('reset');
    

    【讨论】:

    • 或者更好$("select").dropkick('refresh');
    【解决方案5】:

    对于新访问者。 Dropkick 添加了重绘方法。

    $("select").dropkick('redraw');
    

    【讨论】:

    • 如上所述,这个方法实际上是在 Dropkick 1.4 中“重置”的。
    【解决方案6】:

    我遇到了同样的问题,找不到解决方案,但最终成功地完成了这个 hack 工作。

    $select = $("#select1");
    $select.removeData("dropkick");
    $("#dk_container_select1").remove();
    
    $select.append("<option>opt4</option>");
    $select.append("<option>opt5</option>");
    
    $select.dropkick();
    

    【讨论】:

    • 谢谢!正是我需要的;)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多