Как перезагрузить объект jQuery dropkick
Я использую простой список выбора и jquery.библиотека dropkick, чтобы сделать его красивым. Теперь я хочу изменить это содержимое dropkick после того, как соответствующий элемент select был изменен (появилась новая опция). Но просто вызов $('#select').dropkick (); не работает.
И похоже, что он не поддерживается. Было бы достаточно просто восстановить этот дропкик с нуля. Есть ли возможность "уничтожить" этот объект dropkick, а затем восстановить его, вызвав .пнуть() метод?
6 ответов:
Я столкнулся с той же проблемой и не мог найти решение, но в конце концов преуспел в получении этой халтуры.
$select = $("#select1"); $select.removeData("dropkick"); $("#dk_container_select1").remove(); $select.append("<option>opt4</option>"); $select.append("<option>opt5</option>"); $select.dropkick();
Я воспользовался ответом диода, чтобы изменить код 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:
methods.reset = function () { ... };
Тогда вы можете использовать его программно:
$('#my-select').html("<option>new options</option>"); $('#my-select').dropkick('reload');
Для еще более новых посетителей. Dropkick использует метод reset...не перерисовывать.
$("select").dropkick('reset');
Я столкнулся с той же проблемой, я сделал некоторые исправления к сценарию jquery-dropkick-1.0.0, чтобы решить эту проблему. Я добавил метод forceSyncWithSelect к объекту dropkick.
Вот список изменений, которые я сделал:
- добавить поддержку тега
- Добавьте настройки autoWidth, чтобы оставить ширину css
- добавить метод для open, close, forceSyncWithSelect и isDropkicked
- сохранить табиндекс по умолчанию 0
- Добавьте опцию класса optgroup с помощью data-dkgroupclass атрибут элемента optgroup
- исправьте метод forceSyncWithSelect, если значение появляется кратным времени, возьмите только первое вхождение
- включение нажмите на кнопку выбора меню
- запретить IE закрывать меню при взаимодействии с полосой прокрутки (при взаимодействии с полосой прокрутки запускается событие размытия, это поведение настолько неправильно)
Вы можете не хотеть все эти изменения, но вы можете сделать diff патч и взять то, что вам нужно (был бы рад, если бы вы позволили журнал изменений или добавить источник это в заголовке, я хочу предложить эти изменения на Джейми Lottering, но мне нужно сделать аккаунт git-концентратор, чтобы сделать так.
/** * DropKick * * Highly customizable <select> lists * https://github.com/JamieLottering/DropKick * * © 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);