Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 19.03.2013, 08:57
Интересующийся
Отправить личное сообщение для cbone Посмотреть профиль Найти все сообщения от cbone
 
Регистрация: 19.11.2011
Сообщений: 11

jQuery ajax-плагин выпадающего дерева (нужна критика и советы)
Всем привет. Представляю вашему вниманию свой первый jQuery плагин (Демо) и хочу получить конструктивную критику и советы от гуру.

Суть заключается в следующем: пользователь выбирает из выпадающего списка услугу (в нашем случае взял услуги салонов красоты), которая может являться родительской для других услуг. При клике на услугу в случае если она всё-таки является родительской для списка - аяксом подгружается этот список услуг. И так до тех пор, пока скрипт не возвратит пустой массив.

(function($) {

	function isEmpty(obj) {
		for (var key in obj) {
			return false;
			// если цикл хоть раз сработал, то объект не пустой => false
		}
		// дошли до этой строки - значит цикл не нашёл ни одного свойства => true
		return true;
	}

	var defaults = {
		'url' : '/',
		'title' : '{ title : заголовок }',
		'name' : '{ name : заголовок }'
	};

	var methods = {
		init : function(params) {

			var $this = $(this);

			// актуальные настройки, будут индивидуальными при каждом запуске
			var options = $.extend({}, defaults, params);

			// инициализируем один раз
			var init = $(this).data('dropdown');

			if (init) {
				return this;
			} else {
				$(this).data('dropdown', true);

				//Украсили всё
				$(this).addClass('dropdown');
				$("<a/>", {
					'text' : options.title,
					'name' : options.name,
					'class' : 'das'
				}).appendTo($(this));

				//Добавили UL и заполнили нулевым уровнем
				$("<ul/>").appendTo($(this));
				$this.dropdown('getData', 0, options.url);

				//Показать/скрыть выпадающий список
				$(this).on("click", "a", function() {
					//Показали список
					$this.dropdown('toggle');
				});
				
				//Клик по пункту меню
				$(this).on('click', 'li', function() {
					$this.dropdown('getData', $(this).data('id'), options.url);
					if ($(this).data('id') == 0) {
						var text = options.title;
					} else {
						var text = $(this).text();
					}
					$this.find("a").text(text).attr('data-id', $(this).data('id'));
				});
				
				
				return this;

			}
		},
		toggle : function() {
			$(this).find("ul").toggle();
		},
		hide : function() {
			$(this).find("ul").hide();
		},
		getData : function(id, url) {
			
			var $this = $(this);
			
			$.ajax({
				type : 'POST',
				dataType : 'JSON',
				url : url,
				data : {
					id : id
				}
			}).done(function(data) {

				if (isEmpty(data)) {
					return $this.dropdown('hide');
				}

				$this.find("ul").html('');

				if (id != 0)
					$this.find("ul").append("<li data-id='0' class='red'>&larr; назад</li>");

				$.each(data, function(key, val) {
					$("<li/>", {
						'data-id' : key,
						text : val
					}).appendTo($this.find("ul"))
				});

				return this;

			}).fail(function(jqXHR, textStatus) {
				$.error("Ошибка загрузки: " + textStatus);
			});

		}
	};

	$.fn.dropdown = function(method) {
		
		if (this.length > 1) {
			$.error('Плагин можно применить только к одному элементу!');
			return this;
		}

		if (methods[method]) {
			// если запрашиваемый метод существует, мы его вызываем
			// все параметры, кроме имени метода прийдут в метод
			// this так же перекочует в метод
			return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
		} else if ( typeof method === 'object' || !method) {
			// если первым параметром идет объект, либо совсем пусто
			// выполняем метод init
			return methods.init.apply(this, arguments);
		} else {
			// если ничего не получилось
			$.error('Метод "' + method + '" не найден в плагине jQuery.dropdown');
		}

	};
})(jQuery);


Вызов плагина:
$("#service").dropdown({
	'url' : '/php/service.php', //JSON массив для текущего уровня
	'title' : 'выбрать услугу',
	'name' : 'service'
});


Логика работы PHP-скрипта который подтягивает из базы и возвращает JSON для текущего уровня:
if (isset($_POST['id']))
{
	$parent_id = $_POST['id'];
}
else
{
	$parent_id = 0;
}

$query = "SELECT * FROM services WHERE parent_id = $parent_id";
$res = mysql_query($query) or die(mysql_error());
$num = mysql_num_rows($res);

while ($row = mysql_fetch_array($res))
{
	$result[$row['id']] = $row['name'];
}

if($result == NULL)
	$result = array();

echo json_encode($result);

mysql_close();


Демо

Также остался ряд вопросов по реализации:
1. сейчас скрытие выпадающего меню происходит именно по клику на ссылку, а логичнее было бы сделать чтобы скрывалось при клике на любую часть страницы кроме .dropdown. Пробовал делать так:
$(document).on('click', function(){
	$this.dropdown('hide');
});
но он срабатывает первым независимо от того, в какой части вставить этот кусок и попросту не открывается выпадающее окно.
2. при выборе последнего уровня PHP-скрипт возвращает [] и мы скрываем наш блок. По хорошему нужно в наш <ul/> после скрытия подгрузить список с parent_id == 0, то есть выполнить
$this.dropdown('getData', 0, options.url);

Но options.url лежит в другой области видимости и недоступен в методе getData. По идее можно передать его как параметр в этот метод, но код будет дублироваться. Можно ли как то options после инициализации сделать глобальным в пределах нашего плагина и иметь доступ к нему из всех методов плагина?

Последний раз редактировалось cbone, 19.03.2013 в 19:24.
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
конфликтуют плагин стилизации с ajax запросом prohor.zotikov jQuery 15 30.10.2013 18:57
Какая разница между post запросами jquery и ajax? Rooner jQuery 2 18.06.2012 14:29
Не работает jQuery меню с AJAX eugene1986 jQuery 0 08.07.2010 18:49
jQuery Ajax Rater Plugin и массив POST - Нужна помощь TROODON jQuery 12 30.12.2009 22:44
jQuery, jsTree - обновление дерева через ajax extremum.func jQuery 2 09.11.2009 14:48