Открыть меню    

Оформляем красиво тег SELECT при помощи jQuery

красивый select на jQueryВ данной статье мы рассмотрим создание плагина jQuery, суть которого в замещение элемента select красиво оформленным неупорядоченным списком (ul).

Одним из важнейших способов эффективной организации jQuery кода служит превращение его частей в плагины. Такие превращения несут в себя ряд преимуществ: код становится проще модифицировать и сопровождать, руководство повторяющими задачами упрощается. Также увеличивается скорость разработки, так как организация плагина способствует повторному использованию кода.

Поэтому мы и продемонстрируем сегодня процесс конвертирования кода в плагин. Код мы возьмем из этого руководства jQuery& CSS3 замещаем элемент select и превратим его в готовый к использованию jQuery плагин.

Основная идея

оформляем красиво тег select при помощи jQuery

Написать jQuery плагин совсем не сложно. Для этого нужно расширить объект $.fn своей собственной функцией. Гораздо сложнее должным образом структурировать свой код, чтобы плагин можно было легко вставить и использовать (без зависимостей).

Вот, несколько проблем, которые нам надо решить при конвертировании кода руководства в jQuery плагин:


1. Пользователю нужно дать возможность решать, какая разметка будет генерироваться для dropdown (выпадающего списка). К примеру, код руководства сильно зависит от наличия data- атрибутов, которые содержат разметку HTML. Это слишком специфично, чтобы подключать в плагин, поэтому данную реализацию нужно исключить.

2. Из-за способа вызова плагина код нужно переписать, чтобы он использовал объект this, который передается плагину, вместо жестко заданного селектора. Это также позволяет конвертировать не один, а несколько элементов select одновременно;

3. Код JavaScript и CSS нужно поместить в разные файлы, чтобы их было проще подключать и редактировать.


Код

Как вы помните из руководства, наш jQuery код сканирует элементы option тега select и создает неупорядоченный список. Одновременно с этим он также ищет ряд data-атрибутов в тегах option, которые содержат URL на изображение и описание для использования в элементах списка.

Это слишком специфично для плагина. Пользователям нужно дать возможность переписать эту функциональность. Для решения этой проблемы можно позволить пользователям передавать плагину функцию в качестве параметра, которая и будет генерировать разметку. Если такой параметр не передается, будем обращаться к тому, который стоит по умолчанию, и который просто берет текст элемента option и превращает его в пункт списка.

Превратим вышесказанное в код:

JQuery

(function($){

	$.fn.tzSelect = function(options){
		options = $.extend({
			render : function(option){
				return $('<li>',{
					html : option.text()
				});
			},
			className : ''
		},options);

	// More code will be added here.

	}
})(jQuery);
 

Функция render берет элемент option (который находится в select) и возвращает элемент li, который подключается плагином к выпадающему списку. Это решает описанную выше проблему № 1.

Прежде чем обратиться к проблеме № 2, давайте посмотрим, как плагин будет вызываться:

JQuery

       $(document).ready(function(){ 	$('select').tzSelect(); }); 

В приведенном выше коде вы можете видеть, что плагин применяется к каждому элементу select. Получить доступ к этим элементам можно при помощи объекта this, который передается плагину.

JQuery

  return this.each(function(){
			
      
 // ключевое слово  "this" это текущий элемент select
      
 
 var select = $(this);
		
     // selectBoxContainer - блок обертка для ul
    
 var selectBoxContainer = $('<div>',{
 	width		: select.outerWidth(),
 	className	: 'tzSelect',
 	html		: '<div class="selectBox"></div>'
 });
		
    
    // dropDown - выпадающее меню
 var dropDown = $('<ul>',{className:'dropDown'});
 var selectBox = selectBoxContainer.find('.selectBox');
 
     // Цикл по тегам option оригинального тега select
		

 if(options.className){
 	dropDown.addClass(options.className);
 }
 
 select.find('option').each(function(i){
 	var option = $(this);
		
 	if(i==select.attr('selectedIndex')){
 		selectBox.html(option.text());
 	}
 	
 	// Так как  у нас jQuery 1.4.3 то получить доступ к атрибуту
        // HTML5 data  можно при помощи метода data())
        
 	
 	if(option.data('skip')){
 		return true;
 	}
 	
 	// создаем выпадающий список, согласно атрибутам HTML5
        // data-icon и data-html-text  
    
 	
 	var li = options.render(option);

 	li.click(function(){
 		
 		selectBox.html(option.text());
 		dropDown.trigger('hide');
 		
 		// При клике отражаем изменения на оригинальное 
          // элементе select
          
          
 		select.val(option.val());
 		
 		return false;
 	});
		
 	dropDown.append(li);
 });
 
 selectBoxContainer.append(dropDown.hide());
 select.hide().after(selectBoxContainer);
 
 // Связываем события show и hide 
      // с выпадающим меню dropDown:
 
 dropDown.bind('show',function(){
 	
 	if(dropDown.is(':animated')){
 		return false;
 	}
 	
 	selectBox.addClass('expanded');
 	dropDown.slideDown();
 	
 }).bind('hide',function(){
 	
 	if(dropDown.is(':animated')){
 		return false;
 	}
 	
 	selectBox.removeClass('expanded');
 	dropDown.slideUp();
 	
 }).bind('toggle',function(){
 	if(selectBox.hasClass('expanded')){
 		dropDown.trigger('hide');
 	}
 	else dropDown.trigger('show');
 });
 
 selectBox.click(function(){
 	dropDown.trigger('toggle');
 	return false;
 });
		
 // Если произошел клик где-нибудь на странице при
      // открытом выпадающем списке, то скрываем его:
 
 $(document).click(function(){
 	dropDown.trigger('hide');
 });

		});

Показанный выше фрагмент почти идентичен коду руководства, который мы сегодня конвертируем. Единственное заметное отличие – мы присваиваем $(this) переменной select (строка5), раньше же это был $('select.makeMeFancy') (жёстко запрограммированный селектор), что значительно сужало область действия кода.

Другое изменение – вместо непосредственного генерирования выпадающего списка (dropdown), мы вызываем функцию render, которую мы передали как параметр (строка51).

Собрав все воедино, мы получим полный исходный код плагина:

JQuery

       
(function($){
	
	$.fn.tzSelect = function(options){
	 
		options = $.extend({
			render : function(option){
 	return $('<li>',{
 		html : option.text()
 	});
 },
 className : ''
		},options);
		
		return this.each(function(){
 
      
 // ключевое слово  "this" это текущий элемент select
      
 
 var select = $(this);
		
     // selectBoxContainer - блок обертка для ul
    
 var selectBoxContainer = $('<div>',{
 	width		: select.outerWidth(),
 	className	: 'tzSelect',
 	html		: '<div class="selectBox"></div>'
 });
		
    
    // dropDown - выпадающее меню
 var dropDown = $('<ul>',{className:'dropDown'});
 var selectBox = selectBoxContainer.find('.selectBox');
 
     // Цикл по тегам option оригинального тега select
		

 if(options.className){
 	dropDown.addClass(options.className);
 }
 
 select.find('option').each(function(i){
 	var option = $(this);
		
 	if(i==select.attr('selectedIndex')){
 		selectBox.html(option.text());
 	}
 	
 	// Так как  у нас jQuery 1.4.3 то получить доступ к атрибуту
        // HTML5 data  можно при помощи метода data())
        
 	
 	if(option.data('skip')){
 		return true;
 	}
 	
 	// создаем выпадающий список, согласно атрибутам HTML5
        // data-icon и data-html-text  
    
 	
 	var li = options.render(option);

 	li.click(function(){
 		
 		selectBox.html(option.text());
 		dropDown.trigger('hide');
 		
 		// При клике отражаем изменения на оригинальное 
          // элементе select
          
          
 		select.val(option.val());
 		
 		return false;
 	});
		
 	dropDown.append(li);
 });
 
 selectBoxContainer.append(dropDown.hide());
 select.hide().after(selectBoxContainer);
 
 // Связываем события show и hide 
      // с выпадающим меню dropDown:
 
 dropDown.bind('show',function(){
 	
 	if(dropDown.is(':animated')){
 		return false;
 	}
 	
 	selectBox.addClass('expanded');
 	dropDown.slideDown();
 	
 }).bind('hide',function(){
 	
 	if(dropDown.is(':animated')){
 		return false;
 	}
 	
 	selectBox.removeClass('expanded');
 	dropDown.slideUp();
 	
 }).bind('toggle',function(){
 	if(selectBox.hasClass('expanded')){
 		dropDown.trigger('hide');
 	}
 	else dropDown.trigger('show');
 });
 
 selectBox.click(function(){
 	dropDown.trigger('toggle');
 	return false;
 });
		
 // Если произошел клик где-нибудь на странице при
 // открытом выпадающем списке, то скрываем его:
 
 $(document).click(function(){
 	dropDown.trigger('hide');
 });

		});
	}
	
})(jQuery);

Проблему № 3 решаем, поместив этот плагин в отдельный файл. Однако, как я упоминал ранее, мы сознательно не включили код, который содержит data-атрибуты, чтобы сделать плагин более мобильным. Чтобы компенсировать это, нужно при вызове плагина передавать пользовательскую функцию render, как вы можете увидеть ниже (этот код также используется в демо).

JQuery

       $(document).ready(function(){
	
	$('select.makeMeFancy').tzSelect({
 
		render : function(option){
			return $('<li>',{
			html:	'<img src="'+option.data('icon')+'" /><span>'+
				option.data('html-text')+'</span>'
			});
		},
		className : 'hasDetails'
	});
	
	// вызываем версию по умолчанию
	$('select.regularSelect').tzSelect();

});

Вы можете использовать этот плагин, бросив папку tzSelect в корневую директорию и включив jquery.tzSelect.css и jquery.tzSelect.js в свои HTML документы.

Источник

Комментарии к статье

аватарка пользователя
2013-03-12
Саша

демка понравилась, попробую себе поставить

Добавить комментарий