Как настроить смартфоны и ПК. Информационный портал
  • Главная
  • Windows 8
  • Пользовательские атрибуты html. Что можно хранить? Классы в виде объекта: classList

Пользовательские атрибуты html. Что можно хранить? Классы в виде объекта: classList

Влад Мержевич

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

  • Создание всплывающих подсказок без применения скриптов.
  • Определение стиля элемента на основе значения атрибута.
  • Получение и изменение значений через скрипты.

В HTML5 появился новый универсальный атрибут, который можно добавлять к любому тегу. Правила написания атрибута простые:

  • всегда начинаем с data-;
  • используем только латинские буквы, дефис (-), двоеточие (:) и подчёркивание (_).

CSS и JavaScript немного по разному обращаются к таким атрибутам, так что разберём примеры для них отдельно.

CSS

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

Содержимое

Теперь можем в стилях обратиться к этому элементу как div и установить для него нужное оформление. В общем, это напоминает работу классов, поэтому не является какой-то уникальной или необходимой фичей. Так что полезнее задавать значения.

Содержимое

В CSS после этого можем задавать разный стиль при различных значениях нашего атрибута data-columns.

Div { width: 480px; } div { width: 720px; }

Опять же, это в какой-то мере является заменой классам, ничего ведь не мешает сделать классы с именами column-2, column-3 и добавлять их при необходимости.

Более изящной областью применения выступает включение функции attr() . Она получает значение заданного атрибута и вставляет его в стиль. Удобно это использовать для создания всплывающих подсказок. Текст пишем прямо внутри элемента, а вывод и оформление подсказки реализуем с помощью CSS.

Всплывающая подсказка meter { position: relative; } meter:hover::after { content: attr(data-description); background: #ffe; padding: 5px; border: 1px solid #666; position: absolute; top: 20px; }

Температура воды

В данном примере к элементу добавляется атрибут data-description содержащий необходимый текст для вывода. Само отображение происходит с помощью псевдоэлемента ::after и свойства content , значением которого как раз и выступает функция attr() .

JavaScript

Если в CSS мы обращаемся к имени атрибута напрямую, указывая его полностью, то в JavaScript это делается через метод dataset. Само имя атрибута преобразовывается в переменную по следующим правилам:

  • data- отбрасывается;
  • любой дефис идущий перед буквой отбрасывается, а буква за ним становится заглавной.

На практике это выглядит так.

data-description превращается в description.
data-full-description превращается fullDescription.
data-description-of-tag превращается descriptionOfTag.

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

dataset Пользователь var el = document.getElementById("user"); id = el.dataset.id; // Получаем значение атрибута data-id user = el.dataset.user; dob = el.dataset.dateOfBirth; // Получаем значение атрибута data-date-of-birth el.dataset.ban = "Нет"; // Назначаем новый атрибут data-ban и его значение console.log(user); // Выводим в консоль значение переменной user console.log(dob); // Выводим в консоль значение переменной dob

Вначале добавляем к элементу идентификатор с уникальным значением. Затем получаем доступ к элементу через getElementById . Теперь мы можем обращаться к любым атрибутам data через метод dataset , причём не только получать, но и устанавливать значения. Храниться они будут до перезагрузки страницы или до установки нового значения.

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

Поэтому большинство разработчиков завязывались на атрибуты class или rel так как они были единственным разумным способом хранить дополнительные строки. К примеру, предположим, что мы создаем виджет для отображения сообщений типа временной линии сообщений в Twitter. В идеале JavaScript должен иметь возможность конфигурирования без необходимости переписывать код, так что мы определяем идентификатор пользователя в атрибуте class, например:

Наш JavaScript код будет искать элемент с ID msglist . С помощью скрипта мы будем искать классы, начинающиеся с user_ , а “bob” в нашем случае будет идентификатором пользователя, и мы отобразим все сообщения этого пользователя.

Скажем, мы бы хотели также задать максимальное количество сообщений, и пропускать сообщения старше шести месяцев (180 дней):

Наш атрибут class очень быстро загромождается - проще допустить ошибку, а разбор строк на JavaScript становится все сложнее.

Data-атрибуты HTML5

К счастью, в HTML5 была введена возможность использовать пользовательские атрибуты. Вы можете использовать любое имя в нижнем регистре с префиксом data- , например:

Пользовательские data-атрибуты:

  • это строки - в них вы можете хранить любую информацию, которая может быть представлена или закодирована в виде строки, например JSON. Приведение типов должно осуществляться с помощью JavaScript
  • должны использоваться в тех случаях, когда нет подходящих элементов HTML5 или атрибутов
  • относятся только к странице. В отличие от микроформатов они должны игнорироваться внешними системами, типа поисковых систем и поисковых роботов
Пример №1 обработки на JavaScript: getAttribute и setAttribute

Все браузеры позволяют вам получить и изменить data-атрибуты с использованием методов getAttribute и setAttribute:

Var msglist = document.getElementById("msglist"); var show = msglist.getAttribute("data-list-size"); msglist.setAttribute("data-list-size", +show+3);

Это работает, но должно использоваться только для поддержания совместимости со старыми браузерами.

Пример №2 обработки на JavaScript: метод data() библиотеки jQuery

Начиная с версии jQuery 1.4.3 метод data() обрабатывает data-атрибуты HTML5. Вам нет необходимости явно указывать префикс data- , так что подобный код будет работать:

Var msglist = $("#msglist"); var show = msglist.data("list-size"); msglist.data("list-size", show+3);

Но как бы то ни было, имейте в виду, что jQuery пытается конвертировать значения таких атрибутов в подхдящие типы (булевы значения, числа, объекты, массивы или null) и затронет DOM. В отличие от setAttribute , метод data() физически не заменит атрибут data-list-size - если вы проверите его значение вне jQuery - оно все еще останется равным 5.

Пример №3 обработки на JavaScript: API для работы с наборами данных

И, наконец, у нас есть API для работы с наборами данных HTML5, которое возвращает объект DOMStringMap. Необходимо помнить, что data-атрибуты отображаются в объект без префиксов data- , из названий убираются знаки дефиса, а сами названия конвертируются в camelCase, например:

Имя атрибута Имя в API набора данных
data-user user
data-maxage maxage
data-list-size listSize

Наш новый код:

Var msglist = document.getElementById("msglist"); var show = msglist.dataset.listSize; msglist.dataset.listSize = +show+3;

Данный API поддерживается всеми современными браузерами, но не IE10 и ниже. Для таких браузеров существует обходной путь , но, наверное, куда практичнее использовать jQuery, если вы пишете для старых браузеров.

Have you ever found yourself using element class names or rel attributes to store arbitrary snippets of metadata for the sole purpose of making your JavaScript simpler? If you have, then I have some exciting news for you! If you haven"t and you"re thinking, Wow, that"s a great idea! I implore you to rid your mind of that thought immediately and continue reading.

Thanks to HTML 5, we now have the ability to embed custom data attributes on all HTML elements. These new custom data attributes consist of two parts:

Attribute Name The data attribute name must be at least one character long and must be prefixed with " data- ". It should not contain any uppercase letters. Attribute Value The attribute value can be any string.

Using this syntax, we can add application data to our markup as shown below:

  • Carrots
  • Celery
  • Radishes

We can now use this stored data in our site’s JavaScript to create a richer, more engaging user experience. Imagine that when a user clicks on a vegetable a new layer opens up in the browser displaying the additional seed spacing and sowing instructions. Thanks to the data- attributes we’ve added to our

  • elements, we can now display this information instantly without having to worry about making any Ajax calls and without having to make any server-side database queries.

    Prefixing the custom attributes with data- ensures that they will be completely ignored by the user agent. As far as the browser and indeed the website’s end user are concerned, this data does not exist.

    The spec says (emphasis ours):

    Custom data attributes are intended to store custom data private to the page or application, for which there are no more appropriate attributes or elements.

    These attributes are not intended for use by software that is independent of the site that uses the attributes.

    Every HTML element may have any number of custom data attributes specified, with any value.

    W3C Specification How can I use data attributes?

    As custom data attributes are valid HTML 5, they can be used in any browser that supports HTML 5 doctypes. Thankfully, this is pretty much all of them. In addition to aiding backwards compatibility, this also ensures that custom data attributes will remain a scalable, cross-platform solution well into the future.

    Now that we have a broad understanding of what data attributes are, let"s take a look at how they can be used:

    • To store the initial height or opacity of an element which might be required in later JavaScript animation calculations
    • To store parameters for a Flash movie that’s loaded via JavaScript
    • To store custom web analytics tagging data as demonstrated by Jason Karns
    • To store data about the health, ammo, or lives of an element in a JavaScript game
    • To power accessible JavaScript subtitles as demonstrated by Bruce Lawson
    What shouldn’t I use data attributes for?

    Although flexible, data attributes aren’t an appropriate solution for all problems.

    • Data attributes should not be used if there is a existing attribute or element which is more appropriate for storing your data. For example, date/time data should probably be presented semantically in a time element instead rather than stored in custom data attributes.
    • Custom data attributes are not intended to compete with microformats. It is clearly stated in the spec that the data is not intended to be publicly usable. External software should not interact with it. Marking up contact details or event details using custom data attributes would be wrong, unless of course it is only intended to be used by your own internal scripts.
    • The presence/absence of a particular data attribute should not be used as a CSS hook for any styling. Doing so would suggest that the data you are storing is of immediate importance to the user and should be marked up in a more semantic and accessible manner.
    Using data- attributes with JavaScript

    Now that we understand what custom data- attributes are and when we can use them, we should probably take a look at how we can interact with them using JavaScript.

    If we wanted to retrieve or update these attributes using existing, native JavaScript, then we can do so using the getAttribute and setAttribute methods as shown below:

    // "Getting" data-attributes using getAttribute var plant = document.getElementById("strawberry-plant"); var fruitCount = plant.getAttribute("data-fruit"); // fruitCount = "12" // "Setting" data-attributes using setAttribute plant.setAttribute("data-fruit","7"); // Pesky birds

    This method will work in all modern browsers, but it is not how data- attributes are intended to be used. The second (new and improved) way to achieve the same thing is by accessing an element’s dataset property. This dataset property - part of the new HTML 5 JavaScript API s - will return a DOMStringMap object of all the selected element"s data- attributes. When using this approach, rather than using the full attribute name, you can ditch the data- prefix and refer to the custom data directly using the name you have assigned to it. Data attribute names which contain hyphens will be stripped of their hyphens and converted to CamelCase .

    // "Getting" data-attributes using dataset var plant = document.getElementById("sunflower"); var leaves = plant.dataset.leaves; // leaves = 47; // "Setting" data-attributes using dataset var tallness = plant.dataset.plantHeight; // "plant-height" -> "plantHeight" plant.dataset.plantHeight = "3.6m"; // Cracking fertiliser

    If, at some point in your script, a specific data- attribute becomes redundant and is no longer needed, it is also possible to completely remove that attribute from the DOM element by setting it to a value of null .

    Plant.dataset.leaves = null; // Caterpillars attack!

    Unfortunately, the new dataset property has not yet been implemented in any browser, so in the meantime it’s best to use getAttribute and setAttribute as demonstrated earlier.

    While developing your application, you may find it useful to be able to select elements based on the presence of - or indeed the specific values of - their custom data- attributes. This can be achieved quickly and easily using querySelectorAll as shown below:

    // Select all elements with a "data-flowering" attribute document.querySelectorAll(""); // Select all elements with red leaves document.querySelectorAll("");

    A word of warning

    As data attributes become more widely used, the potential for clashes in naming conventions becomes much greater. If you use an unimaginative attribute name such as data-height , then it is likely you will eventually come across a library or plugin that uses the same attribute name. Multiple scripts getting and setting a common data- attribute will probably cause chaos. In order to avoid this, I encourage people to choose a standard string (perhaps the site/plugin name) to prefix all their data- attributes - e.g. data-html5doctor-height or data-my-plugin-height .

    Summary

    Custom data- attributes are a great way to simplify the storage of application data in your web pages. Although you can’t utilise the new JavaScript API s just yet, you can enjoy great success using getAttribute and setAttribute safe in the knowledge that they will work in all major browsers.

    Homework

    If you’re super keen to have a play with the new dataset property but disappointed that it hasn’t been implemented, fear not!, for there is a light at the end of the tunnel. You might be interested in looking at Dr Remy’s experimental code , which partially enables the dataset functionality in some browsers by editing the Element.prototype .

    The code supports the retrieval of data- attributes in the latest versions of Firefox, Safari, Opera, and Chrome, but sadly will not work in any version of IE (since IE does not expose the Element object). This code also partially supports the setting of data attributes, but it will only store the new attribute values within the JavaScript and will not update the DOM element as a full, native implementation of the dataset property would. Although this code is mainly a proof of concept, it may be useful for mobile application or intranet development in closed environments where cross-browser (IE) compatibility is not an issue.

    • Category
    45 Responses on the article “HTML5 Custom Data Attributes (data-*)”

    I firmly do not see why it is inappropriate to use custom data attributes for external applications provided that these external applications are not a requirement for viewing the page.

    I don’t understand why this article quotes the part of the spec saying data-* attributes are site-specific, and then gives a warning promoting namespacing. If you follow the spec, you’re creating all of the attribute names, so there’s zero reason for namespacing. That’s exactly why that’s in the spec.

    @Scott – the namespacing isn’t to create “site-specific” data attributes, but in-application namespacing.

    For example (and IIRC the spec mentions this) a widget’s controls (like a tree view) may have data attributes, but the data attributes may have been created using a specific library, such as jQuery or Dojo – so to avoid data attribute collisions the application module may want to namespace it.

    I can’t see where Chris referred to the data attribute being site-specific (but it’s late and I may have missed it).

    There’s a lot of cases where you won’t want or need to use namespacing, but there are some cases where it makes sense. But since this just builds on existing content attributes rules – you’re free to decide how you use them.

    I’m using the data-* with getAttribute and setAttribute since I saw a post about that 2 years ago by Jon Resig, so I can confirm that this way of using it works for all browsers/platforms, starting with IE6.
    I just hope that any browser implementing data-* natively won’t break the getAttribute method (it shouldnt but we never know)

    From a performance point of view, accessing the DOM via getAttribute() is obviously slower than accessing to a JS variable, event stored in an array, so the use case you give of a JS game using it to store values will probably never happen: developers will use it to transmit info from server to client, but once the DOM has been harvested, it’s best to keep all the values in JS for quicker access

    @jpvincent – Yeah, I totally agree with you.

    I guess the initial health and ammo data could be stored in a database and using a data-attribute would be a valid mechanism to transfer this information to the game’s javascript. But once this initialisation task is complete there is very little point in continuing to make costly DOM updates with the latest health/ammo stats.

    Thanks for your comment.

    Your article mentions that you shouldn’t use data-* for CSS hooks. What if the data-* attribute was used in the JS but you also wanted to apply styles to it. Wouldn’t it make sense to target the attribute rather than add a secondary class.

    Take this form for example:



    Title *is required

    Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.





    data-field_type=”text” could be used for both validation and styling layout.

    Pretty cool feature, although no browsers support it yet. This little bit of code works to add support for the dataset property to any browser that supports __defineGetter__. I wrote it before I realized you linked some code that does pretty much the same thing. My code, on the other hand, has support for actually udpating the attribute values, but it does not support adding new attributes.

    Element.prototype.__defineGetter__(‘dataset’, function(){
    var dataset = {};
    for (var i=0, l=this.attributes.length; i < / div >

    Как видите, можно указывать любые имена и любые значения. Но ведь эти параметры ничего не делают с элементом, зачем тогда они вообще нужны? Есть как минимум несколько способов применения data-атрибутов в сайтостроении, и давайте рассмотрим их.

    Способ применения 1 – обращение к элементам в css

    Если вы знаете, что такое селекторы атрибутов, то наверняка уже догадываетесь, как могут быть использованы новые возможности. Указывая для тега уникальный data-атрибут, вы сможете соответствующим образом обратиться к нему в стилях. Давайте рассмотрим пример:

    div{}

    < div data - css = "css" > < / div >

    div [ data - css = "css" ] { }

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

    Способ применения 2 – хранение значений и их использование

    С первого взгляда, значения data-атрибутов ничего не меняют и вообще никак не влияют на веб-страницу. Так зачем они вообще нужны? На самом деле применение им найти можно, если вспомнить про функцию attr() в css.

    < img src = "foto.jpg" data - img = "Фотография" >

    Давайте поставим задачу: нужно вывести на страницу поясняющий текст к фотографиям, который появлялся бы либо сразу с загрузкой картинки, либо при наведении на нее, не важно как. Стандартная подсказка реализуется с помощью атрибута title.

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

    Итак, выше в коде мы вставили картинку, указали путь к ней и дополнительно записали произвольный data-параметр. Реализовать вывод пояснения к фото теперь можно таким образом:

    img{ display: inline-block; } img:after{ content: attr(data-img); }

    img {

    display : inline - block ;

    img : after {

    content : attr (data - img ) ;

    Что мы сделали? Теперь у всех изображений будет псевдоэлемент, в котором будет находиться значение атрибута data-img, если оно есть у тега img. Таким нехитрым способом вы смогли вывести поясняющий текст к фотографии.

    Я не буду в этой статье приводить инструкцию, как оформить подсказку. Скажу только, что по умолчанию она будет отображаться после загрузки страницы. Зачастую ее нужно изначально скрыть, а выводить при наведении на картинку. Чтобы это реализовать, вам нужно воспользоваться селектором img:hover:after.

    Ну а какие есть еще html5 атрибуты, появившиеся только в этой спецификации? К таковым можно отнести, например, controls – атрибут для новых элементов audio и video, который позволяет вывести элементы управления видеороликом или аудиозаписью.

    У видео с помощью параметра poster можно указать путь к изображению, которое будет фоном до начала просмотра видео. В общем, вот таких вот мелких атрибутов появилось не так уж и мало.

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

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

  • Лучшие статьи по теме