Статьи

Методы прогрессивного улучшения 3: JavaScript

веб-слои В моих предыдущих статьях мы создавали элемент управления вкладками с использованием простого старого семантического HTML с ненавязчивым стилем CSS . Это последняя статья из трех частей, в которой показано, как создать простое поле с вкладками, используя прогрессивные методы улучшения.

Шаткий сценарий

JavaScript — самый рискованный слой веб-страницы. Поддержка HTML гарантирована, вероятен CSS, но JavaScript может быть недоступен или отключен. Будет ли это влиять на ваш сайт, будет зависеть от вашей аудитории, но в целом вы можете ожидать, что 5% пользователей не имеют включенных сценариев. Это большой процент — безусловно, выше, чем доля рынка Safari, Chrome или Opera.

Существуют также различия в реализации браузера. К счастью, JavaScript — это универсальный язык, и мы можем исправить проблемы совместимости. Например, IE5 не предоставляет метод Array push (), но мы можем определить, когда он отсутствует, и добавить его самостоятельно:


if (!Array.prototype.push) {
	Array.prototype.push = function(item) { this[this.length] = item; };
}

Примечание: добавление новых свойств или методов к нативным объектам немного рискованно, но это тема другой статьи.

Многие платформы JavaScript предоставляют функции, которые преодолевают несоответствия браузера. Код элемента управления вкладки, показанный ниже, построен как плагин jQuery . Он предоставляет повторно используемый компонент, который может быть реализован на любой странице, и jQuery поможет с более приземленными аспектами кодирования на стороне клиента, такими как манипулирование DOM и делегирование событий.

Вы должны знать, что jQuery и другие библиотеки предлагают ограниченную поддержку браузера. Хотя наш блок вкладок может работать в IE5 и IE5.5, jQuery не поддерживает эти браузеры, и сценарии не будут работать. В этом примере это не является серьезной проблемой, потому что вкладка работает без JavaScript. Однако вы должны всегда проверять свои требования на соответствие ограничениям выбранной вами библиотеки, прежде чем использовать ее.

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

CSS с поддержкой JavaScript

Без JavaScript в нашей вкладке используется раздел с прокруткой содержимого. Наш сценарий должен удалить полосы прокрутки, но мы все равно можем указать это с помощью CSS, управляемого JavaScript:

 
/* tab control CSS: JavaScript progressive enhancements */
.tabcontent.active
{
	overflow: hidden;
}

Поэтому плагин будет применять класс «active» к внешнему содержимому div

Разработка плагина jQuery TabControl

Полный код доступен в jquery.tabcontrol.js . Когда страница загружена, JavaScript ищет любой тег с классом «вкладок» и создает новый экземпляр объекта TabControl для каждого найденного узла. Узлу назначается свойство TabControlInitialized, чтобы два или более объекта не могли указывать на один и тот же HTML-код.

Две важные переменные инициализируются:

  • (this.) Свойство Tab будет содержать узлы всех вкладок и их связанное содержимое.
  • (это.) Активное свойство хранит текущую выделенную вкладку.
 
// jQuery plugin definition
$.fn.TabControl = function() {

	// tab control object
	function TabControl(list) {

		if (list.TabControlInitialized) return;
		else list.TabControlInitialized = true;

		this.List = list;
		this.Tab = {};
		this.Active = null;

В следующем сегменте значение T установлено в this (текущий экземпляр объекта), поэтому на него можно ссылаться в следующем цикле. Каждая вкладка идентифицируется, и ID, на который она ссылается, извлекается (см. Метод LinkId ниже ). Вкладка и узлы содержимого затем сохраняются в объекте Tab:

 
		var T = this;

		// find and initialize all tabs
		$("li a[href^=#]", list).each(function() {

			var id = T.LinkId(this);
			var content = $("#"+id);
			content = (content.length > 0 ? content[0] : null);

			// link/content object
			T.Tab[id] = {
				link: this,
				content: content
			};

Последняя часть цикла выполняет следующие операции:

  1. Класс «активный» добавляется в контейнер содержимого ( div Это удалит полосы прокрутки, как описано выше .
  2. Обработчик события щелчка применяется ко всем ссылкам, которые ссылаются на содержимое вкладки, включая саму вкладку (см. Метод TabSwitch ниже ).
  3. Все вкладки и контент становятся неактивными (см. Метод Activate ниже ).
  4. Текущая активная вкладка определяется. Обычно это будет первая вкладка, если в URL страницы не указан другой идентификатор.

Активная вкладка активируется:

 
			// set content holder class
			if (content !== null) $(content.parentNode).addClass("active");

			// event delegation
			$("a[href=#"+id+"]").click(function(e) { T.TabSwitch(e) });

			// deactivate tab
			T.Activate(id, false);

			// is tab active?
			if (T.Active === null || "#"+id == location.hash) T.Active = id;

		});

		// show active tab/content
		this.Activate(this.Active);

	}

Наконец, у нас есть три метода. Первый, LinkId, возвращает идентификатор страницы, извлеченный из атрибута ссылки href («#» также удаляется):

 
	// returns linked ID
	TabControl.prototype.LinkId = function(link) {
		return link.href.replace(/.*#(.+)$/, "$1");
	};

Метод TabSwitch вызывается при нажатии на вкладку (или любую ссылку, указывающую на содержимое вкладки). Он останавливает действие браузера по умолчанию, деактивирует старую вкладку и снова активирует новую.

Последние несколько строк плавно прокручивают страницу в поле вкладок, если оно не отображается на экране при нажатии на ссылку на содержимое с вкладками. Ссылка переместилась на местоположение контента в обычном HTML, но наш код отменил это событие и заменил его более приятным эффектом.

 
	// tab click event handler
	TabControl.prototype.TabSwitch = function(e) {

		e.preventDefault();

		var id = this.LinkId(e.target);
		if (id != this.Active) {

			// hide old tab
			this.Activate(this.Active, false);

			// switch to new tab
			this.Active = id;
			this.Activate(this.Active);

		}

		// scroll to tab box if required
		var html = $('html,body');
		var lt = $(this.List).offset().top, lh = $(this.List).height();
		var st = Math.max(html.scrollTop(), $("body").scrollTop()), wh = $(window).height();
		if (lt < st || lt+lh > st+wh) html.animate({scrollTop: lt}, 500);

		return false;
	};

Наконец, метод Activate принимает два аргумента; идентификатор вкладки и true или false, чтобы активировать или деактивировать вкладку и ее содержимое:

 
	// activate or deactivate a tab
	TabControl.prototype.Activate = function(id, show) {

		if (this.Tab[id]) {
			if (show !== false) {
				$(this.Tab[id].link).addClass("active");
				if (this.Tab[id].content) this.Tab[id].content.style.display = "block";
			}
			else {
				$(this.Tab[id].link).removeClass("active");
				if (this.Tab[id].content) this.Tab[id].content.style.display = "none";
			}
		}

	};

Наш прогрессивно улучшенный блок вкладок теперь готов — посмотрите страницу примера . Он должен работать во всех браузерах, даже если CSS, JavaScript или оба отключены или не работают. Существует мало необходимости публиковать список поддержки браузера !

Скриншот HTML, CSS и JS

Ссылки на ресурсы:

Другие части в этой серии:

Связанное чтение: