Подтвердить что ты не робот

Объединение таблицы и иерархического списка в HTML

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

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

Seq     Item Name         Min  Max  - Anything under here isn't shown
 1      Identifier         1    1     (Required)
 2      Name               1    1
  2.1    First Name        1    1
  2.2    Middle Name       -    -     (Optional but unlimted)
  2.3    Last Name         1    1
 3      Age                -    1     (Optional)

На данный момент это одна целая таблица, а intdenting для номера Sequence (Seq) достигается путем вставки дополнительных ячеек таблицы в вид bump все поперек справа.

Задача, которую я имею, - выяснить, как эффективно отображать эту информацию.

Прежде всего это табличные данные? Я бы сказал "нет", поскольку иерархия важна, а "столбцы" - это просто атрибуты элемента в каждой строке.

Если это не табличное, что это такое и как это сделать? Я бы лично сказал, что это набор вложенных списков UL - порядковый номер является необязательным и не всегда число. Если его набор списков, который будет отступать подвыраживает правильно, но каков наилучший способ представления коротких атрибутов?

Если это таблица, каков наилучший способ представить семантическое существование иерархии в таблице?

4b9b3361

Ответ 1

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

К сожалению, нет никакого вложенного механизма группировки для строк таблицы в HTML: tbody можно использовать для группировки строк, но вложение это незаконно (за исключением промежуточного table внутри a td, что довольно ужасно).

Это оставляет вам два варианта:

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

  • Представляйте информацию в виде таблицы и полагайтесь на атрибуты какого-либо вида, чтобы представить свои иерархические отношения.

Вот несколько примеров того, как вы можете реализовать эти варианты:

Использование вложенных списков (наивный подход):

<ul>
  <li>
    <dl>
      <dt>Seq</dt> <dd>1</dd>
      <dt>Item Name</dt> <dd>Identifier</dd>
      <dt>Min</dt> <dd>1</dd>
      <dt>Max</dt> <dd>1</dd>
    </dl>
  </li>
  <li>
    <dl>
      <dt>Seq</dt> <dd>2</dd>
      <dt>Item Name</dt> <dd>Name</dd>
      <dt>Min</dt> <dd>1</dd>
      <dt>Max</dt> <dd>1</dd>
    </dl>
    <ul>
      <li>
        <dl>
          <dt>Seq</dt> <dd>2.1</dd>
          <dt>Item Name</dt> <dd>First Name</dd>
          <dt>Min</dt> <dd>1</dd>
          <dt>Max</dt> <dd>1</dd>
        </dl>
      </li>
      <li>
        <dl>
          <dt>Seq</dt> <dd>2.2</dd>
          <dt>Item Name</dt> <dd>Middle Name</dd>
          <dt>Min</dt> <dd>-</dd>
          <dt>Max</dt> <dd>-</dd>
        </dl>
      </li>
      <li>
        <dl>
          <dt>Seq</dt> <dd>2.3</dd>
          <dt>Item Name</dt> <dd>Last Name</dd>
          <dt>Min</dt> <dd>1</dd>
          <dt>Max</dt> <dd>1</dd>
        </dl>
      </li>
    </ul>
  </li>
  <li>
    <dl>
      <dt>Seq</dt> <dd>3</dd>
      <dt>Item Name</dt> <dd>Age</dd>
      <dt>Min</dt> <dd>-</dd>
      <dt>Max</dt> <dd>1</dd>
    </dl>
  </li>
<ul>

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

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

Использование вложенных списков ( "умный" подход):

<dl>
  <dt>
    <ul> <li>Seq</li> <li>Item Name</li> <li>Min</li> <li>Max</li> </ul>
  </dt>
  <dd>
    <ul> <li>1</li> <li>Identifier</li> <li>1</li> <li>1</li> </ul>
  </dd>
  <dd>
    <dl>
      <dt>
        <ul> <li>2</li> <li>Name</li> <li>1</li> <li>1</li> </ul>
      </dt>
      <dd>
        <ul> <li>2.1</li> <li>First Name</li> <li>1</li> <li>1</li> </ul>
      </dd>
      <dd>
        <ul> <li>2.2</li> <li>Middle Name</li> <li>-</li> <li>-</li> </ul>
      </dd>
      <dd>
        <ul> <li>2.3</li> <li>Last Name</li> <li>1</li> <li>1</li> </ul>
      </dd>
    </dl>
  </dd>
  <dd>
    <ul> <li>3</li> <li>Age</li> <li>-</li> <li>1</li> </ul>
  </dd>
</dl>

Здесь мы используем описания списков, чтобы описать две вещи:

  • Отношение заголовка/детали между, например, "Имя элемента" и "Идентификатор" и т.д.

  • Родительские/дочерние отношения между, например, блок "Имя" и "Имя".

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

Использование table:

<table>
  <thead>
    <tr>
      <th>Seq</th> <th>Item Name</th> <th>Min</th> <th>Max</th>
    </tr>
  </thead>
  <tbody>
    <tr id=100>
      <td>1</th> <th>Identifier</th> <td>1</td> <td>1</td>
    </tr>
    <tr id=200>
      <th>2</th> <th>Name</th> <td>1</td> <td>1</td>
    </tr>
    <tr id=210 data-parent=200 class=level-1>
      <th>2.1</th> <th>First Name</th> <td>1</td> <td>1</td>
    </tr>
    <tr id=220 data-parent=200 class=level-1>
      <th>2.2</th> <th>Middle Name</th> <td>-</td> <td>-</td>
    </tr>
    <tr id=230 data-parent=200 class=level-1>
      <th>2.3</th> <th>Last Name</th> <td>1</td> <td>1</td>
    </tr>
    <tr id=300>
      <th>3</th> <th>Age</th> <td>-</td> <td>1</td>
    </tr>
  </tbody>
</table>

Здесь отношения parent/child явно описываются атрибутом data-parent (к которому можно обращаться с помощью javascript, если это необходимо) и Атрибут class=level-{n} предоставляет крючок, который может использоваться CSS:

.level-1 > th {
  padding-left: 1em;
}

В конечном счете это вопрос личных предпочтений и удобства, но я думаю, что подход <table> лучше просто потому, что он удовлетворяет "выглядит ли он разумным без CSS?" эмпирическое правило намного лучше, чем один из вышеперечисленных подходов к вложенным спискам.

Ответ 2

Я бы представил его, используя таблицу и добавив атрибуты пользовательских данных в теги td:

<table id="myTable" class="table">
    <tr>
        <td data-indent="0">1</td>
        <td data-indent="0">Test</td>
        <td data-indent="0">Test 1</td>
    </tr>
    <tr>
        <td data-indent="1">1.1</td>
        <td data-indent="1">Another</td>
        <td data-indent="0">Test 1.1</td>
    </tr>
    <tr>
        <td data-indent="2">1.1.1</td>
        <td data-indent="3">Another</td>
        <td data-indent="0">Test 1.1.1</td>
    </tr>
        <tr>
        <td data-indent="2">1.1.2</td>
        <td data-indent="3">Another one</td>
        <td data-indent="0">Another test 1.1.2</td>
    </tr>
    <tr>
        <td data-indent="0">2</td>
        <td data-indent="0">Test</td>
        <td data-indent="0">Test 2</td>
    </tr>
</table>

Затем, с помощью jQuery, установите дополнение каждого значения ячейки в таблице:

$("td")
    .css("padding-left", function (index) {
    return 10 * parseInt($(this).data("indent")) + "px";
});

Посмотрите, как работает jsFiddle.

Ответ 3

Я думаю, что есть два разумных способа представления этого в HTML:

  • используйте table и сделайте ссылку/иерархию явным с естественным языком
  • используйте секционирующие элементы (соответственно заголовки, если вы используете HTML 4.01)

table с столбцом, объясняющим иерархию

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

В вашем случае вы можете добавить столбец, который объясняет взаимосвязь строк, которые являются "подпунктами":

<table>

  <tr>
    <th>Seq</th> 
    <th>Relation</th> <!-- or some clever better label -->
    <th>Item Name</th>
    <th>Min</th>
    <th>Max</th>
  </tr>

  <!-- … -->

  <tr id="2">
    <td>2</td>
    <td></td> <!-- "parent", "root", "container", empty -- whatever makes sense for your case -->
    <td>Name</td>
    <td>1</td>
    <td>1</td>
  </tr>

  <tr id="2.1">
    <td>2.1</td>
    <td>child of <a href="#2">Name</a></td>
    <td>First Name</td>
    <td>1</td>
    <td>1</td>
  </tr>

</table>

Каждая строка может получить id (со значением Seq или Item Name), чтобы связать эту строку {обратите внимание, что значения id, начинающиеся с цифры, не допускаются в HTML 4.01; вы можете использовать что-то вроде id = "seq-2.1" там}. Если элемент является дочерним элементом другого элемента, вы можете ссылаться на строку родительского элемента.

Таким образом, вы даете понять людям, и машины все еще видят, что эти строки связаны, хотя конкретная семантика этого отношения не является машиносчитываемой. Вы можете использовать тип ссылки (rel value) здесь, если явно указать значение отношения. В HTML 4.01 вы можете создать значение самостоятельно, в HTML5 сначала нужно зарегистрировать.

секционные элементы/заголовки

Вместо использования table вы можете использовать HTML-код, излагающий. {В следующем примере используются элементы раздела HTML5s. Если вы используете HTML 4.01, просто замените элементы секционирования на div (или вообще нет элемента) и используйте только заголовки.}

Каждый раздел (введенный заголовком) представляет элемент. Контур заголовков (или вложенность элементов секционирования) представляет собой иерархию ваших элементов.

Вот пример, чтобы увидеть всю структуру:

 <article>

   <h1><!-- heading for the whole data --></h1>

   <section class="item" id="1">
     <h2>Identifier</h2>
   </section>

   <section class="item" id="2">
     <h2>Name</h2>

     <section class="item" id="2.1">
       <h3>First Name</h3>
     </section>

     <section class="item" id="2.2">
       <h3>Middle Name</h3>
     </section>

     <section class="item" id="2.3">
       <h3>Last Name</h3>
     </section>

   </section>

   <section class="item" id="3">
     <h2>Age</h2>
   </section>

 </article>

Каждый section может содержать dl для свойств:

<section class="item" id="3">
  <h2>Age</h2>

  <dl>
    <dt>Min</dt>
    <dd>1</dd>
    <dt>Max</dt>
    <dd>1</dd>
  </dl>

</section>

В зависимости от фактического значения вашего контента вы можете использовать code element для имен элементов (например, если он описывает элементы например, язык разметки) и/или элемент dfn, если следующий контент является определением этого элемента.

Ответ 4

Я думаю, вы должны использовать таблицу. Правда, иерархия важнее, но ее также можно отобразить с помощью ручной записи первого столбца. Но атрибуты min, max и item не могут быть легко показаны в списке, как в таблице. Мое мнение: используйте таблицу и укажите столбец seq вручную.

Ответ 5

Мое предложение состояло в том, чтобы использовать вложенные упорядоченные списки, чтобы сохранить иерархическую структуру, а затем списки описания для представления столбцов для каждой строки.

Например, список описаний для первой строки может выглядеть примерно так:

<dl>
  <dt>Item Name</dt>
  <dd>Identifier</dd>
  <dt>Min</dt>
  <dd>1</dd>
  <dt>Max</dt>
  <dd>1</dd>
  <dt>Notes</dt>
  <dd>(Required)</dd>
</dl>

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

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

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

CodePen Link

Ответ 6

ОБНОВЛЕНИЕ: я добавил использование идентификаторов и атрибутов "заголовков", чтобы каким-то образом семантически выделить иерархию.

Это окончательно табличные данные (вы должны действительно толковать определение "списка", чтобы оправдать использование UL или DL здесь!).

Я думаю, что хороший подход будет использовать разные tbodys для группировки связанных между собой строк (что-то вроде этого он использовал здесь http://www.w3.org/TR/2012/WD-html5-20120329/the-table-element.html#the-table-element см. "таблица используется для обозначения головоломки Судоку" )

<table>
  <thead>
    <tr>
      <th id="seq">Seq</th>
      <th>Item Name</th>
      <th>Min</th>
      <th>Max</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th id="s1" headers="seq">1</th>
      <td>Identifier</td>
      <td>1</td>
      <td>1</td>
    </tr>
  </tbody>
  <tbody>
    <tr>
      <th id="s2" headers="seq">2</th>
      <td>Name</td>
      <td>1</td>
      <td>1</td>
    </tr>
    <tr class="sub">
      <th id="s2_1" headers="seq s2">2.1</th>
      <td>First Name</td>
      <td>1</td>
      <td>1</td>
    </tr>
    <tr class="sub">
      <th id="s2_2" headers="seq s2">2.2</th>
      <td>Middle Name</td>
      <td>-</td>
      <td>-</td>
    </tr>
    <tr class="sub">
      <th id="s2_3" headers="seq s2">2.3</th>
      <td>Last Name</td>
      <td>1</td>
      <td>1</td>
    </tr>
    <tr class="sub sub">
      <th id="s2_3_1" headers="seq s2 s2_3">2.3.1</th>
      <td>Last Name</td>
      <td>1</td>
      <td>1</td>
    </tr>
    <tr class="sub sub">
      <th id="s2_3_2" headers="seq s2 s2_3">2.3.2</th>
      <td>Last Name</td>
      <td>1</td>
      <td>1</td>
    </tr>
  </tbody>
  <tbody>
    <tr>
      <th id="s3" headers="seq">3</th>
      <td>Age</td>
      <td>-</td>
      <td>1</td>
    </tr>
  </tbody>
</table>

Тогда вы можете использовать что-то вроде этого:

table { border-collapse: collapse; }
tbody { border-bottom:1px solid #000; }
tbody .sub td { padding-left: 10px; }

Если факт, я думаю, вы можете использовать tbody только для группировки строк и оставить только одиночные строки

<tr>
  <td>1</td>
  <td>Identifier</td>
  <td>1</td>
  <td>1</td>
</tr>
<tbody>
  <tr>
    <td>2</td>
    <td>Name</td>
    <td>1</td>
    <td>1</td>
  </tr>
  <tr class="sub">
    <td>2.1</td>
    <td>First Name</td>
    <td>1</td>
    <td>1</td>
  </tr>
  ...
</tbody>
<tr>
  <td>3</td>
  <td>Age</td>
  <td>-</td>
  <td>1</td>
</tr>

Ответ 7

Почему бы и нет? Сетка дерева - хороший способ представления табличных данных, которые также соответствуют иерархии.

Это один такой пример.

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

Имейте в виду, что вы всегда должны спрашивать себя: "На какие вопросы мои пользователи пытаются ответить?" Затем спросите себя: "Какие графические устройства дают самый ясный и простой путь для ответа на этот вопрос?"

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

Надеюсь, что это поможет...