Статьи

Воспроизведение с тегом Details / Summary

Одной из наиболее интересных вещей, которые я обнаружил в последнее время в HTML5, являются функции, которые копируют вещи, для которых разработчики использовали JavaScript в прошлом. Например, мне нравится, что вы можете выполнять базовую проверку формы только с помощью HTML-тегов и атрибутов. Недавно я обнаружил тег <details>.

И MDN, и официальная спецификация говорят об этом теге:


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

«Раскрытие виджета» — что это такое? Оказывается, это имеет больше смысла, если вы на самом деле видите это. Вот пример виджета:

Видишь маленькую стрелку? Нажатие на него открывает контент под ним:

Достаточно просто, и, как я уже сказал, я уверен, что вы уже видели это в JavaScript много раз. Так как же это сделать с тегом подробностей?

<details>
	<summary>This is the Title</summary>
	<p>
	This is my content.
	</p>
</details>

Довольно просто, правда? Весь контент обернут в тег детали. Браузер использовал содержимое в итоговом теге в качестве заголовка. Вот и все. Если вам интересно, вы можете по умолчанию открыть блок, добавив атрибут open:<details open>.


Обратите внимание, что простое присутствие атрибута open заставит диалог открываться по умолчанию.
Если вы попытаетесь проявить фантазию и использовать open = «false», он все равно откроет диалоговое окно.

Так насколько хорошо это поддерживается? На данный момент не очень хорошо

На мобильных устройствах поддержка довольно хорошая. На десктопе IE и Firefox больше не хватает Но вот отличная вещь. Когда он «ломается», у вас все тот же контент. Вот скриншот из Firefox прошлого примера.

Работает отлично, даже когда не работает — что для меня отличная вещь. Вот немного более полный пример. Я думаю, что FAQ — отличный способ использовать этот тег. Вместо огромной страницы контента вы можете использовать итоговый тег для вопросов, и конечный пользователь может выбирать, какие вопросы он хочет отобразить. Я создал следующее, используя свои невероятные дизайнерские навыки и некоторый контент из FAQ по PhoneGap:

<style>
	summary {
		font-weight: bold;
		font-size: 2em;
		font-family: 'adobe-clean','HelveticaNeue',Helvetica,Arial,sans-serif;
	}
	
	p {
		font-family: 'adobe-clean','HelveticaNeue',Helvetica,Arial,sans-serif;		
	}
	
	details {
		margin-bottom: 10px;	
	}
</style>

<details>
	<summary>Q: What is PhoneGap?</summary>
	<p>
	A: PhoneGap is an open source solution for building cross-platform mobile apps with standards-based Web technologies like HTML, JavaScript, CSS.
	</p>
</details>

<details>
	<summary>Q: How much does PhoneGap cost?</summary>
	<p>
		A: PhoneGap is an open source implementation of open standards and FREE. That means developers and companies can use PhoneGap for mobile applications that are free, commercial, open source, or any combination of these.
	</p>
</details>

<details>
	<summary>Q: What is the difference between PhoneGap and Cordova?</summary>
	<p>
	In October 2011, PhoneGap was donated to the Apache Software Foundation (ASF) under the name Apache Cordova. Through the ASF, future PhoneGap development will ensure open stewardship of the project. It will remain free and open source under the Apache License, Version 2.0.
	</p>
	<p>
	PhoneGap is an open source distribution of Cordova. Think about Cordova’s relationship to PhoneGap like WebKit’s relationship to Safari or Chrome.
	</p>
</details>

Вы можете запустить этот код
здесь , и, как я уже сказал, независимо от того, какой браузер вы используете, вы сможете читать содержимое.

В предыдущем примере я немного стилизовал текстовое содержимое, но как насчет «элемента управления», то есть стрелки? StackOverflow пришел на помощь с предложением стилизовать стрелку (или, в данном случае, скрыть ее):

details summary::-webkit-details-marker { 
	display:none; 
}

Мне также не понравилась рамка «фокус» вокруг сводки, поэтому вы тоже можете ее удалить:

details summary:focus {
	display: none;	
}

Наконец, вы можете заметить, что при наведении курсора на стрелку курсор не меняется. Вы тоже можете это исправить:

details summary {
	cursor:pointer;
	background-color: #0c9837;
}

Если вы хотите увидеть пример этого, посмотрите мою демонстрацию здесь:
http://www.raymondcamden.com/demos/2013/sep/17/test2.html Простите за выбор цвета — я должен был использовать Kuler.

Так, что если вы действительно хотите использовать некоторые JavaScript с тегами? Я построил простой пример, который просто сообщает, открыт ли блок подробностей или нет. Вот полный шаблон:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
		<title></title>
		<meta name="description" content="">
		<meta name="viewport" content="width=device-width">
	</head>
	<body>
		
		<details id="testDetails">
			<summary>This is the Title</summary>
			<p>
			This is my content.
			</p>
		</details>
		
		<script>
			document.addEventListener("DOMContentLoaded", init, false);
			
			var testD; 
			
			function init() {
				testD = document.querySelector("#testDetails");
				var summary = document.querySelector("#testDetails summary");

				summary.addEventListener("click", function(e) {
					var open = !testD.hasAttribute("open");
					console.log(open);
				}, false);
				
			}
		</script>
	</body>
</html>

Я предполагаю, что большая часть этого имеет смысл. У меня есть указатели как на блок деталей в целом, так и на резюме. На фактическом событии клика я вижу, присутствует ли атрибут open. Я отрицаю значение как — из того, что я могу сказать — событие сработало до того, как детальный блок открылся или закрылся. Вы можете запустить это самостоятельно в моей демонстрации здесь: http://www.raymondcamden.com/demos/2013/sep/17/test3.html

Наконец, я подумал, что было бы неплохо добавить поддержку отложенной загрузки подробного контента. Эта демонстрация не очень надежна (она всегда принимает атрибут data-url), но дает представление о том, как это можно сделать.

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
		<title></title>
		<meta name="description" content="">
		<meta name="viewport" content="width=device-width">
		<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>		
	</head>
	<body>
		
		<details id="testDetails" data-details="foo.html">
			<summary>This is the Title</summary>
		</details>
		
		<script>
			var testD; 
			var loaded = false;
			
			$(document).ready(function() {
				
				testD = $("#testDetails");
				$("#testDetails summary").on("click", function(e) {
					var that = this;
					var open = !testD.attr("open");
					if(open && !loaded) {
						/*
						Techincally we may NOT be loaded yet, but I only want the first one to start the request
						*/
						loaded = true;
						var url = testD.data("details");
						$.get(url).then(function(res) {
							$(that).after(res);
							console.dir(that);
						});
					}
				});
				
			});
		</script>
	</body>
</html>
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
		<title></title>
		<meta name="description" content="">
		<meta name="viewport" content="width=device-width">
		<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>		
	</head>
	<body>
		
		<details id="testDetails" data-details="foo.html">
			<summary>This is the Title</summary>
		</details>
		
		<script>
			var testD; 
			var loaded = false;
			
			$(document).ready(function() {
				
				testD = $("#testDetails");
				$("#testDetails summary").on("click", function(e) {
					var that = this;
					var open = !testD.attr("open");
					if(open && !loaded) {
						/*
						Techincally we may NOT be loaded yet, but I only want the first one to start the request
						*/
						loaded = true;
						var url = testD.data("details");
						$.get(url).then(function(res) {
							$(that).after(res);
							console.dir(that);
						});
					}
				});
				
			});
		</script>
	</body>
</html>

Вы можете просмотреть это демо здесь:
http://www.raymondcamden.com/demos/2013/sep/17/test4.html