diff --git a/core/includes/theme.inc b/core/includes/theme.inc index 2aef832c..0446703 100644 --- a/core/includes/theme.inc +++ b/core/includes/theme.inc @@ -1538,9 +1538,15 @@ function template_preprocess_field(&$variables, $hook) { // Creating variables for the template. $variables['entity_type'] = $element['#entity_type']; - $variables['field_name'] = $element['#field_name']; - $variables['field_type'] = $element['#field_type']; + $variables['field_name'] = strtr($element['#field_name'], '_', '-'); + $variables['field_type'] = strtr($element['#field_type'], '_', '-'); + $variables['field_label'] = strtr($element['#label_display'], '_', '-'); $variables['label_display'] = $element['#label_display']; + // Are there multiple field items. + $variables['multiple'] = FALSE; + if (isset($element['#items']) && is_callable($element['#items'], 'getFieldDefinition') && is_callable($element['#items']->getFieldDefinition(), 'isMultiple')) { + $variables['multiple'] = $element['#items']->getFieldDefinition()->isMultiple(); + } $variables['label_hidden'] = ($element['#label_display'] == 'hidden'); // Always set the field label - allow themes to decide whether to display it. @@ -1552,6 +1558,18 @@ function template_preprocess_field(&$variables, $hook) { if (!isset($default_attributes)) { $default_attributes = new Attribute; } + // Merge the attributes when its a multiple fields with hidden label + if ($element['#label_display'] == 'hidden' && $variables['multiple']) { + $variables['attributes'] = NestedArray::mergeDeep($variables['attributes'], $variables['content_attributes']); + } + // Merge the attributes when its a single field with a label + if ($element['#label_display'] != 'hidden' && !$variables['multiple'] && is_object($element['#items'][0])) { + $variables['content_attributes'] = NestedArray::mergeDeep($variables['content_attributes'], (array) $element['#items'][0]->_attributes); + } + // Merge the attributes when its a single field with hidden label + if ($element['#label_display'] == 'hidden' && !$variables['multiple'] && is_object($element['#items'][0])) { + $variables['attributes'] = NestedArray::mergeDeep($variables['attributes'], $variables['content_attributes'], (array) $element['#items'][0]->_attributes); + } // We want other preprocess functions and the theme implementation to have // fast access to the field item render arrays. The item render array keys diff --git a/core/lib/Drupal/Core/Field/WidgetBase.php b/core/lib/Drupal/Core/Field/WidgetBase.php index e333df3..fa5f1a3 100644 --- a/core/lib/Drupal/Core/Field/WidgetBase.php +++ b/core/lib/Drupal/Core/Field/WidgetBase.php @@ -127,9 +127,9 @@ public function form(FieldItemListInterface $items, array &$form, FormStateInter '#parents' => array_merge($parents, array($field_name . '_wrapper')), '#attributes' => array( 'class' => array( - 'field-type-' . Html::getClass($this->fieldDefinition->getType()), - 'field-name-' . Html::getClass($field_name), - 'field-widget-' . Html::getClass($this->getPluginId()), + 'field--type-' . Html::getClass($this->fieldDefinition->getType()), + 'field--name-' . Html::getClass($field_name), + 'field--widget-' . Html::getClass($this->getPluginId()), ), ), 'widget' => $elements, diff --git a/core/modules/field/src/Tests/EntityReference/EntityReferenceFormatterTest.php b/core/modules/field/src/Tests/EntityReference/EntityReferenceFormatterTest.php index 9979c0d..c485a22 100644 --- a/core/modules/field/src/Tests/EntityReference/EntityReferenceFormatterTest.php +++ b/core/modules/field/src/Tests/EntityReference/EntityReferenceFormatterTest.php @@ -183,17 +183,15 @@ public function testEntityFormatter() { // Test the first field item. $expected_rendered_name_field_1 = '
-
-
' . $this->referencedEntity->label() . '
-
-
+
+
' . $this->referencedEntity->label() . '
+
+ '; $expected_rendered_body_field_1 = '
-
Body
-
-

Hello, world!

-
-
+
Body:
+

Hello, world!

+ '; drupal_render($build[0]); $this->assertEqual($build[0]['#markup'], 'default | ' . $this->referencedEntity->label() . $expected_rendered_name_field_1 . $expected_rendered_body_field_1, sprintf('The markup returned by the %s formatter is correct for an item with a saved entity.', $formatter)); diff --git a/core/modules/image/src/Tests/ImageFieldDisplayTest.php b/core/modules/image/src/Tests/ImageFieldDisplayTest.php index 2679328..9c18611 100644 --- a/core/modules/image/src/Tests/ImageFieldDisplayTest.php +++ b/core/modules/image/src/Tests/ImageFieldDisplayTest.php @@ -336,7 +336,7 @@ function testImageFieldDefaultImage() { $this->drupalGet('node/' . $node->id()); // Verify that no image is displayed on the page by checking for the class // that would be used on the image field. - $this->assertNoPattern('
', 'No image displayed when no image is attached and no default image specified.'); + $this->assertNoPattern('
', 'No image displayed when no image is attached and no default image specified.'); $cache_tags_header = $this->drupalGetHeader('X-Drupal-Cache-Tags'); $this->assertTrue(!preg_match('/ image_style\:/', $cache_tags_header), 'No image style cache tag found.'); diff --git a/core/modules/rdf/src/Tests/Field/NumberFieldRdfaTest.php b/core/modules/rdf/src/Tests/Field/NumberFieldRdfaTest.php index f5974bb..8334a26 100644 --- a/core/modules/rdf/src/Tests/Field/NumberFieldRdfaTest.php +++ b/core/modules/rdf/src/Tests/Field/NumberFieldRdfaTest.php @@ -50,7 +50,7 @@ public function testIntegerFormatterWithSettings() { $this->assertFormatterRdfa($formatter, 'http://schema.org/baseSalary', array('value' => $testValue)); // Test that the content attribute is created. - $result = $this->xpathContent($this->getRawContent(), '//div[contains(@class, "field-item") and @content=:testValue]', array(':testValue' => $testValue)); + $result = $this->xpathContent($this->getRawContent(), '//div[contains(@class, "field__item") and @content=:testValue]', array(':testValue' => $testValue)); $this->assertTrue($result); } @@ -92,7 +92,7 @@ public function testFloatFormatterWithSettings() { $this->assertFormatterRdfa($formatter, 'http://schema.org/baseSalary', array('value' => $testValue)); // Test that the content attribute is created. - $result = $this->xpathContent($this->getRawContent(), '//div[contains(@class, "field-item") and @content=:testValue]', array(':testValue' => $testValue)); + $result = $this->xpathContent($this->getRawContent(), '//div[contains(@class, "field__item") and @content=:testValue]', array(':testValue' => $testValue)); $this->assertTrue($result); } @@ -113,7 +113,7 @@ public function testFloatFormatterWithScale() { $this->assertFormatterRdfa($formatter, 'http://schema.org/baseSalary', array('value' => $testValue)); // Test that the content attribute is not created. - $result = $this->xpathContent($this->getRawContent(), '//div[contains(@class, "field-item") and @content]'); + $result = $this->xpathContent($this->getRawContent(), '//div[contains(@class, "field__item") and @content]'); $this->assertFalse($result); } @@ -134,7 +134,7 @@ public function testFloatFormatterWithScaleExercised() { $this->assertFormatterRdfa($formatter, 'http://schema.org/baseSalary', array('value' => $testValue)); // Test that the content attribute is created. - $result = $this->xpathContent($this->getRawContent(), '//div[contains(@class, "field-item") and @content=:testValue]', array(':testValue' => $testValue)); + $result = $this->xpathContent($this->getRawContent(), '//div[contains(@class, "field__item") and @content=:testValue]', array(':testValue' => $testValue)); $this->assertTrue($result); } @@ -149,7 +149,7 @@ public function testDecimalFormatter() { $this->assertFormatterRdfa(array('type' => 'number_decimal'), 'http://schema.org/baseSalary', array('value' => $testValue)); // Test that the content attribute is not created. - $result = $this->xpathContent($this->getRawContent(), '//div[contains(@class, "field-item") and @content]'); + $result = $this->xpathContent($this->getRawContent(), '//div[contains(@class, "field__item") and @content]'); $this->assertFalse($result); } @@ -176,7 +176,7 @@ public function testDecimalFormatterWithSettings() { $this->assertFormatterRdfa($formatter, 'http://schema.org/baseSalary', array('value' => $testValue)); // Test that the content attribute is created. - $result = $this->xpathContent($this->getRawContent(), '//div[contains(@class, "field-item") and @content=:testValue]', array(':testValue' => $testValue)); + $result = $this->xpathContent($this->getRawContent(), '//div[contains(@class, "field__item") and @content=:testValue]', array(':testValue' => $testValue)); $this->assertTrue($result); } diff --git a/core/modules/search/src/Tests/SearchExcerptTest.php b/core/modules/search/src/Tests/SearchExcerptTest.php index 6bea2cb..96d5489 100644 --- a/core/modules/search/src/Tests/SearchExcerptTest.php +++ b/core/modules/search/src/Tests/SearchExcerptTest.php @@ -69,7 +69,7 @@ function testSearchExcerpt() { // The node body that will produce this rendered $text is: // 123456789 HTMLTest +123456789+‘ +‘ +‘ +‘ +12345678    +‘ +‘ +‘ ‘ - $text = "

123456789 HTMLTest +123456789+‘ +‘ +‘ +‘ +12345678    +‘ +‘ +‘ ‘

\n
"; + $text = "

123456789 HTMLTest +123456789+‘ +‘ +‘ +‘ +12345678 +‘ +‘ +‘ ‘

\n
"; $result = search_excerpt('HTMLTest', $text); $this->assertFalse(empty($result), 'Rendered Multi-byte HTML encodings are not corrupted in search excerpts'); } diff --git a/core/modules/system/css/system.theme.css b/core/modules/system/css/system.theme.css index 0f5b08f..84a774c 100644 --- a/core/modules/system/css/system.theme.css +++ b/core/modules/system/css/system.theme.css @@ -559,19 +559,20 @@ ul.tabs { } /* Field display */ -.field .field-label { +.field__label { font-weight: bold; + vertical-align: top; } -.field-label-inline .field-label, -.field-label-inline .field-items { - float:left; /*LTR*/ - margin-right: 0.5em; /*LTR*/ +.field--label-inline .field__label, +.field--label-inline > .field__item, +.field--label-inline .field__items { + display: inline-block; + padding-right: 0.5em; } -[dir="rtl"] .field-label-inline .field-label, -[dir="rtl"] .field-label-inline .field-items { - float: right; - margin-left: 0.5em; - margin-right: 0; +[dir="rtl"] .field--label-inline .field__label, +[dir="rtl"] .field--label-inline .field__items { + padding-left: 0.5em; + padding-right: 0; } .field-label-inline .field-label::after { content: ':'; diff --git a/core/modules/system/src/Tests/Ajax/MultiFormTest.php b/core/modules/system/src/Tests/Ajax/MultiFormTest.php index 449861c..7da7143 100644 --- a/core/modules/system/src/Tests/Ajax/MultiFormTest.php +++ b/core/modules/system/src/Tests/Ajax/MultiFormTest.php @@ -59,8 +59,8 @@ function testMultiForm() { // desired elements. $field_name = 'field_ajax_test'; $field_xpaths = array( - 'node-page-form' => '//form[@id="node-page-form"]//div[contains(@class, "field-name-field-ajax-test")]', - 'node-page-form--2' => '//form[@id="node-page-form--2"]//div[contains(@class, "field-name-field-ajax-test")]', + 'node-page-form' => '//form[@id="node-page-form"]//div[contains(@class, "field--name-field-ajax-test")]', + 'node-page-form--2' => '//form[@id="node-page-form--2"]//div[contains(@class, "field--name-field-ajax-test")]', ); $button_name = $field_name . '_add_more'; $button_value = t('Add another item'); diff --git a/core/modules/system/src/Tests/Form/RebuildTest.php b/core/modules/system/src/Tests/Form/RebuildTest.php index e993b49..b285be1 100644 --- a/core/modules/system/src/Tests/Form/RebuildTest.php +++ b/core/modules/system/src/Tests/Form/RebuildTest.php @@ -97,7 +97,7 @@ function testPreserveFormActionAfterAJAX() { // field items in the field for which we just added an item. $this->drupalGet('node/add/page'); $this->drupalPostAjaxForm(NULL, array(), array('field_ajax_test_add_more' => t('Add another item')), 'system/ajax', array(), array(), 'node-page-form'); - $this->assert(count($this->xpath('//div[contains(@class, "field-name-field-ajax-test")]//input[@type="text"]')) == 2, 'AJAX submission succeeded.'); + $this->assert(count($this->xpath('//div[contains(@class, "field--name-field-ajax-test")]//input[@type="text"]')) == 2, 'AJAX submission succeeded.'); // Submit the form with the non-Ajax "Save" button, leaving the title field // blank to trigger a validation error, and ensure that a validation error diff --git a/core/modules/system/templates/field.html.twig b/core/modules/system/templates/field.html.twig index 0745f84..0217a86 100644 --- a/core/modules/system/templates/field.html.twig +++ b/core/modules/system/templates/field.html.twig @@ -28,6 +28,9 @@ * - items: List of all the field items. Each item contains: * - attributes: List of HTML attributes for each item. * - content: The field item's content. + * - field_type: @todo: needs description + * - field_name: @todo: needs description + * - field_label: @todo: needs description * - entity_type: The entity type to which the field belongs. * - field_name: The name of the field. * - field_type: The type of the field. @@ -49,19 +52,38 @@ label_display == 'inline' ? 'clearfix', ] %} -{% - set title_classes = [ - 'field-label', - label_display == 'visually_hidden' ? 'visually-hidden', - ] -%} - {% if not label_hidden %} - {{ label }}
+{% if not label_hidden %} + {% + set title_classes = [ + 'field__label', + label_display == 'visually_hidden' ? 'visually-hidden', + ] + %} + {% if multiple %} + + {{ label }}:
+ {% for item in items %} + {{ item.content }} + {% endfor %} + + {% else %} + {{ label }}: + {% for item in items %} + {{ item.content }} + {% endfor %} {% endif %} - +{% else %} + {% if multiple %} {% for item in items %} - {{ item.content }} + {{ item.content }} {% endfor %} - + {% else %} + + {% for item in items %} + {{ item.content }} + {% endfor %} + + {% endif %} +{% endif %}