diff --git a/core/includes/theme.inc b/core/includes/theme.inc index 5d14f31..afa58c3 100644 --- a/core/includes/theme.inc +++ b/core/includes/theme.inc @@ -492,8 +492,8 @@ function template_preprocess_datetime_wrapper(&$variables) { } $variables['required'] = FALSE; - // For required datetime fields a 'form-required' class is appended to the - // label attributes. + // For required datetime fields 'form-required' & 'js-form-required' classes + // are appended to the label attributes. if (!empty($element['#required'])) { $variables['required'] = TRUE; } @@ -1604,6 +1604,7 @@ function template_preprocess_field_multiple_value_form(&$variables) { $order_class = $element['#field_name'] . '-delta-order'; $header_attributes = new Attribute(array('class' => array('label'))); if (!empty($element['#required'])) { + $header_attributes['class'][] = 'js-form-required'; $header_attributes['class'][] = 'form-required'; } $header = array( diff --git a/core/lib/Drupal/Core/Render/Element/Button.php b/core/lib/Drupal/Core/Render/Element/Button.php index c305e22..ac34e42 100644 --- a/core/lib/Drupal/Core/Render/Element/Button.php +++ b/core/lib/Drupal/Core/Render/Element/Button.php @@ -77,6 +77,7 @@ public static function preRenderButton($element) { $element['#attributes']['class'][] = 'button--' . $element['#button_type']; } // @todo Various JavaScript depends on this button class. + $element['#attributes']['class'][] = 'js-form-submit'; $element['#attributes']['class'][] = 'form-submit'; if (!empty($element['#attributes']['disabled'])) { diff --git a/core/lib/Drupal/Core/Render/Element/Details.php b/core/lib/Drupal/Core/Render/Element/Details.php index c45810e..cf57bc7 100644 --- a/core/lib/Drupal/Core/Render/Element/Details.php +++ b/core/lib/Drupal/Core/Render/Element/Details.php @@ -54,9 +54,9 @@ public function getInfo() { public static function preRenderDetails($element) { Element::setAttributes($element, array('id')); - // The .form-wrapper class is required for #states to treat details like + // The .js-form-wrapper class is required for #states to treat details like // containers. - static::setAttributes($element, array('form-wrapper')); + static::setAttributes($element, array('js-form-wrapper', 'form-wrapper')); // Collapsible details. $element['#attached']['library'][] = 'core/drupal.collapse'; diff --git a/core/lib/Drupal/Core/Render/Element/File.php b/core/lib/Drupal/Core/Render/Element/File.php index 5f72c8d..c8b3c7f 100644 --- a/core/lib/Drupal/Core/Render/Element/File.php +++ b/core/lib/Drupal/Core/Render/Element/File.php @@ -65,7 +65,7 @@ public static function processFile(&$element, FormStateInterface $form_state, &$ public static function preRenderFile($element) { $element['#attributes']['type'] = 'file'; Element::setAttributes($element, array('id', 'name', 'size')); - static::setAttributes($element, array('form-file')); + static::setAttributes($element, array('js-form-file', 'form-file')); return $element; } diff --git a/core/misc/machine-name.js b/core/misc/machine-name.js index b9e87a6..cccfdfe 100644 --- a/core/misc/machine-name.js +++ b/core/misc/machine-name.js @@ -81,7 +81,7 @@ var $source = $context.find(source_id).addClass('machine-name-source').once('machine-name'); var $target = $context.find(options.target).addClass('machine-name-target'); var $suffix = $context.find(options.suffix); - var $wrapper = $target.closest('.form-item'); + var $wrapper = $target.closest('.js-form-item'); // All elements have to exist. if (!$source.length || !$target.length || !$suffix.length || !$wrapper.length) { return; diff --git a/core/misc/states.js b/core/misc/states.js index 680e86e..c520d7c 100644 --- a/core/misc/states.js +++ b/core/misc/states.js @@ -509,7 +509,7 @@ if (e.trigger) { $(e.target) .prop('disabled', e.value) - .closest('.form-item, .form-submit, .form-wrapper').toggleClass('form-disabled', e.value) + .closest('.js-form-item, .js-form-submit, .js-form-wrapper').toggleClass('form-disabled', e.value) .find('select, input, textarea').prop('disabled', e.value); // Note: WebKit nightlies don't reflect that change correctly. @@ -520,21 +520,21 @@ $(document).on('state:required', function (e) { if (e.trigger) { if (e.value) { - var $label = $(e.target).attr({'required': 'required', 'aria-required': 'aria-required'}).closest('.form-item, .form-wrapper').find('label'); + var $label = $(e.target).attr({'required': 'required', 'aria-required': 'aria-required'}).closest('.js-form-item, .js-form-wrapper').find('label'); // Avoids duplicate required markers on initialization. - if (!$label.hasClass('form-required').length) { - $label.addClass('form-required'); + if (!$label.hasClass('js-form-required').length) { + $label.addClass('js-form-required form-required'); } } else { - $(e.target).removeAttr('required aria-required').closest('.form-item, .form-wrapper').find('label.form-required').removeClass('form-required'); + $(e.target).removeAttr('required aria-required').closest('.js-form-item, .js-form-wrapper').find('label.js-form-required').removeClass('js-form-required form-required'); } } }); $(document).on('state:visible', function (e) { if (e.trigger) { - $(e.target).closest('.form-item, .form-submit, .form-wrapper').toggle(e.value); + $(e.target).closest('.js-form-item, .js-form-submit, .js-form-wrapper').toggle(e.value); } }); diff --git a/core/misc/vertical-tabs.js b/core/misc/vertical-tabs.js index 11fca70..9e841f5 100644 --- a/core/misc/vertical-tabs.js +++ b/core/misc/vertical-tabs.js @@ -149,7 +149,7 @@ // Display the tab. this.item.show(); // Show the vertical tabs. - this.item.closest('.form-type-vertical-tabs').show(); + this.item.closest('.js-form-type-vertical-tabs').show(); // Update .first marker for items. We need recurse from parent to retain the // actual DOM element order as jQuery implements sortOrder, but not as public // method. @@ -182,7 +182,7 @@ } // Hide the vertical tabs (if no tabs remain). else { - this.item.closest('.form-type-vertical-tabs').hide(); + this.item.closest('.js-form-type-vertical-tabs').hide(); } return this; } diff --git a/core/modules/block_content/js/block_content.js b/core/modules/block_content/js/block_content.js index de36d4b..8d4c47b 100644 --- a/core/modules/block_content/js/block_content.js +++ b/core/modules/block_content/js/block_content.js @@ -12,13 +12,13 @@ var $context = $(context); $context.find('.block-content-form-revision-information').drupalSetSummary(function (context) { var $revisionContext = $(context); - var revisionCheckbox = $revisionContext.find('.form-item-revision input'); + var revisionCheckbox = $revisionContext.find('.js-form-item-revision input'); // Return 'New revision' if the 'Create new revision' checkbox is checked, // or if the checkbox doesn't exist, but the revision log does. For users // without the "Administer content" permission the checkbox won't appear, // but the revision log will if the content type is set to auto-revision. - if (revisionCheckbox.is(':checked') || (!revisionCheckbox.length && $revisionContext.find('.form-item-revision-log textarea').length)) { + if (revisionCheckbox.is(':checked') || (!revisionCheckbox.length && $revisionContext.find('.js-form-item-revision-log textarea').length)) { return Drupal.t('New revision'); } @@ -28,13 +28,13 @@ $context.find('fieldset.block-content-translation-options').drupalSetSummary(function (context) { var $translationContext = $(context); var translate; - var $checkbox = $translationContext.find('.form-item-translation-translate input'); + var $checkbox = $translationContext.find('.js-form-item-translation-translate input'); if ($checkbox.size()) { translate = $checkbox.is(':checked') ? Drupal.t('Needs to be updated') : Drupal.t('Does not need to be updated'); } else { - $checkbox = $translationContext.find('.form-item-translation-retranslate input'); + $checkbox = $translationContext.find('.js-form-item-translation-retranslate input'); translate = $checkbox.is(':checked') ? Drupal.t('Flag other translations as outdated') : Drupal.t('Do not flag other translations as outdated'); } diff --git a/core/modules/ckeditor/js/ckeditor.admin.js b/core/modules/ckeditor/js/ckeditor.admin.js index e3dbf2b..462e90a 100644 --- a/core/modules/ckeditor/js/ckeditor.admin.js +++ b/core/modules/ckeditor/js/ckeditor.admin.js @@ -16,7 +16,7 @@ var $textarea = $configurationForm // Hide the textarea that contains the serialized representation of the // CKEditor configuration. - .find('.form-item-editor-settings-toolbar-button-groups') + .find('.js-form-item-editor-settings-toolbar-button-groups') .hide() // Return the textarea child node from this expression. .find('textarea'); diff --git a/core/modules/comment/comment-entity-form.js b/core/modules/comment/comment-entity-form.js index b41ab84..6e639bc 100644 --- a/core/modules/comment/comment-entity-form.js +++ b/core/modules/comment/comment-entity-form.js @@ -11,7 +11,7 @@ attach: function (context) { var $context = $(context); $context.find('fieldset.comment-entity-settings-form').drupalSetSummary(function (context) { - return Drupal.checkPlain($(context).find('.form-item-comment input:checked').next('label').text()); + return Drupal.checkPlain($(context).find('.js-form-item-comment input:checked').next('label').text()); }); } }; diff --git a/core/modules/datetime/src/Tests/DateTimeFieldTest.php b/core/modules/datetime/src/Tests/DateTimeFieldTest.php index e2223dc..b7a2988 100644 --- a/core/modules/datetime/src/Tests/DateTimeFieldTest.php +++ b/core/modules/datetime/src/Tests/DateTimeFieldTest.php @@ -100,7 +100,7 @@ function testDateField() { // Display creation form. $this->drupalGet('entity_test/add'); $this->assertFieldByName("{$field_name}[0][value][date]", '', 'Date element found.'); - $this->assertFieldByXPath('//*[@id="edit-' . $field_name . '-wrapper"]/h4[contains(@class, "form-required")]', TRUE, 'Required markup found'); + $this->assertFieldByXPath('//*[@id="edit-' . $field_name . '-wrapper"]/h4[contains(@class, "js-form-required")]', TRUE, 'Required markup found'); $this->assertNoFieldByName("{$field_name}[0][value][time]", '', 'Time element not found.'); // Submit a valid date and ensure it is accepted. diff --git a/core/modules/field_ui/field_ui.js b/core/modules/field_ui/field_ui.js index 1167fcc..1c90be1 100644 --- a/core/modules/field_ui/field_ui.js +++ b/core/modules/field_ui/field_ui.js @@ -11,15 +11,16 @@ attach: function (context) { var $form = $(context).find('#field-ui-field-storage-add-form').once('field_ui_add'); if ($form.length) { - // Add a few 'form-required' css classes here. We can not use the Form API - // '#required' property because both label elements for "add new" and - // "re-use existing" can never be filled and submitted at the same time. + // Add a few 'js-form-required' and 'form-required 'css classes here. We + // can not use the Form API '#required' property because both label + // elements for "add new" and "re-use existing" can never be filled and + // submitted at the same time. // The actual validation will happen server-side. $form.find( - '.form-item-label label,' + - '.form-item-field-name label,' + - '.form-item-existing-storage-label label') - .addClass('form-required'); + '.js-form-item-label label,' + + '.js-form-item-field-name label,' + + '.js-form-item-existing-storage-label label') + .addClass('js-form-required form-required'); var $newFieldType = $form.find('select[name="new_storage_type"]'); var $existingStorageName = $form.find('select[name="existing_storage_name"]'); diff --git a/core/modules/field_ui/src/Form/EntityDisplayFormBase.php b/core/modules/field_ui/src/Form/EntityDisplayFormBase.php index 94feeff..c411683 100644 --- a/core/modules/field_ui/src/Form/EntityDisplayFormBase.php +++ b/core/modules/field_ui/src/Form/EntityDisplayFormBase.php @@ -307,7 +307,7 @@ protected function buildFieldRow(FieldDefinitionInterface $field_definition, arr '#title_display' => 'invisible', '#options' => array_combine($regions, $regions), '#empty_value' => '', - '#attributes' => array('class' => array('field-parent')), + '#attributes' => array('class' => array('js-field-parent', 'field-parent')), '#parents' => array('fields', $field_name, 'parent'), ), 'hidden_name' => array( @@ -486,7 +486,7 @@ protected function buildExtraFieldRow($field_id, $extra_field) { '#title_display' => 'invisible', '#options' => array_combine($regions, $regions), '#empty_value' => '', - '#attributes' => array('class' => array('field-parent')), + '#attributes' => array('class' => array('js-field-parent', 'field-parent')), '#parents' => array('fields', $field_id, 'parent'), ), 'hidden_name' => array( diff --git a/core/modules/file/file.js b/core/modules/file/file.js index fcefad1..e005e94 100644 --- a/core/modules/file/file.js +++ b/core/modules/file/file.js @@ -67,13 +67,13 @@ Drupal.behaviors.fileButtons = { attach: function (context) { var $context = $(context); - $context.find('.form-submit').on('mousedown', Drupal.file.disableFields); - $context.find('.form-managed-file .form-submit').on('mousedown', Drupal.file.progressBar); + $context.find('.js-form-submit').on('mousedown', Drupal.file.disableFields); + $context.find('.form-managed-file .js-form-submit').on('mousedown', Drupal.file.progressBar); }, detach: function (context) { var $context = $(context); - $context.find('.form-submit').off('mousedown', Drupal.file.disableFields); - $context.find('.form-managed-file .form-submit').off('mousedown', Drupal.file.progressBar); + $context.find('.js-form-submit').off('mousedown', Drupal.file.disableFields); + $context.find('.form-managed-file .js-form-submit').off('mousedown', Drupal.file.progressBar); } }; @@ -128,7 +128,7 @@ * Trigger the upload_button mouse event to auto-upload as a managed file. */ triggerUploadButton: function (event) { - $(event.target).closest('.form-managed-file').find('.form-submit').trigger('mousedown'); + $(event.target).closest('.form-managed-file').find('.js-form-submit').trigger('mousedown'); }, /** * Prevent file uploads when using buttons not intended to upload. @@ -144,7 +144,7 @@ // Check if we're working with an "Upload" button. var $enabledFields = []; if ($clickedButton.closest('div.form-managed-file').length > 0) { - $enabledFields = $clickedButton.closest('div.form-managed-file').find('input.form-file'); + $enabledFields = $clickedButton.closest('div.form-managed-file').find('input.js-form-file'); } // Temporarily disable upload fields other than the one we're currently diff --git a/core/modules/filter/filter.filter_html.admin.js b/core/modules/filter/filter.filter_html.admin.js index a11fca5..8223116 100644 --- a/core/modules/filter/filter.filter_html.admin.js +++ b/core/modules/filter/filter.filter_html.admin.js @@ -57,7 +57,7 @@ var that = this; $(context).find('[name="filters[filter_html][settings][allowed_html]"]').once('filter-filter_html-updating', function () { that.$allowedHTMLFormItem = $(this); - that.$allowedHTMLDescription = that.$allowedHTMLFormItem.closest('.form-item').find('.description'); + that.$allowedHTMLDescription = that.$allowedHTMLFormItem.closest('.js-form-item').find('.description'); that.userTags = that._parseSetting(this.value); // Update the new allowed tags based on added text editor features. diff --git a/core/modules/image/src/Tests/ImageFieldDisplayTest.php b/core/modules/image/src/Tests/ImageFieldDisplayTest.php index 4fef5f5..a4897ee 100644 --- a/core/modules/image/src/Tests/ImageFieldDisplayTest.php +++ b/core/modules/image/src/Tests/ImageFieldDisplayTest.php @@ -290,8 +290,8 @@ function testImageFieldSettings() { $edit = array(); $edit['files[' . $field_name . '_2][]'] = drupal_realpath($test_image->uri); $this->drupalPostAjaxForm(NULL, $edit, $field_name . '_2_upload_button'); - $this->assertNoRaw(''); - $this->assertRaw(''); + $this->assertNoRaw(''); + $this->assertRaw(''); } /** diff --git a/core/modules/image/src/Tests/ImageFieldValidateTest.php b/core/modules/image/src/Tests/ImageFieldValidateTest.php index e6afc32..f803b4b 100644 --- a/core/modules/image/src/Tests/ImageFieldValidateTest.php +++ b/core/modules/image/src/Tests/ImageFieldValidateTest.php @@ -68,11 +68,11 @@ function testRequiredAttributes() { $this->uploadNodeImage($image, $field_name, 'article'); // Look for form-required for the alt text. - $elements = $this->xpath('//label[@for="edit-' . $field_name . '-0-alt" and @class="form-required"]/following-sibling::input[@id="edit-' . $field_name . '-0-alt"]'); + $elements = $this->xpath('//label[@for="edit-' . $field_name . '-0-alt" and @class="js-form-required form-required"]/following-sibling::input[@id="edit-' . $field_name . '-0-alt"]'); $this->assertTrue(isset($elements[0]),'Required marker is shown for the required alt text.'); - $elements = $this->xpath('//label[@for="edit-' . $field_name . '-0-title" and @class="form-required"]/following-sibling::input[@id="edit-' . $field_name . '-0-title"]'); + $elements = $this->xpath('//label[@for="edit-' . $field_name . '-0-title" and @class="js-form-required form-required"]/following-sibling::input[@id="edit-' . $field_name . '-0-title"]'); $this->assertTrue(isset($elements[0]), 'Required marker is shown for the required title text.'); diff --git a/core/modules/language/templates/language-negotiation-configure-form.html.twig b/core/modules/language/templates/language-negotiation-configure-form.html.twig index 8e1c8f5..46a0f3d 100644 --- a/core/modules/language/templates/language-negotiation-configure-form.html.twig +++ b/core/modules/language/templates/language-negotiation-configure-form.html.twig @@ -23,6 +23,7 @@ {% for language_type in language_types %} {% set language_classes = [ + 'js-form-item', 'form-item', 'table-language-group', 'table-' ~ language_type.type ~ '-wrapper', diff --git a/core/modules/locale/locale.admin.js b/core/modules/locale/locale.admin.js index 550e40e..5efd13b 100644 --- a/core/modules/locale/locale.admin.js +++ b/core/modules/locale/locale.admin.js @@ -25,7 +25,7 @@ $row.addClass('changed'); // Add an asterisk only once if row changed. if ($rowToMark.length) { - $rowToMark.find('td:first-child .form-item').append(marker); + $rowToMark.find('td:first-child .js-form-item').append(marker); } }); } diff --git a/core/modules/menu_ui/menu_ui.js b/core/modules/menu_ui/menu_ui.js index 36fb1d6..87d443e 100644 --- a/core/modules/menu_ui/menu_ui.js +++ b/core/modules/menu_ui/menu_ui.js @@ -6,8 +6,8 @@ attach: function (context) { $(context).find('.menu-link-form').drupalSetSummary(function (context) { var $context = $(context); - if ($context.find('.form-item-menu-enabled input').is(':checked')) { - return Drupal.checkPlain($context.find('.form-item-menu-title input').val()); + if ($context.find('.js-form-item-menu-enabled input').is(':checked')) { + return Drupal.checkPlain($context.find('.js-form-item-menu-title input').val()); } else { return Drupal.t('Not in menu'); @@ -26,9 +26,9 @@ var $this = $(this); // Try to find menu settings widget elements as well as a 'title' field in // the form, but play nicely with user permissions and form alterations. - var $checkbox = $this.find('.form-item-menu-enabled input'); - var $link_title = $context.find('.form-item-menu-title input'); - var $title = $this.closest('form').find('.form-item-title-0-value input'); + var $checkbox = $this.find('.js-form-item-menu-enabled input'); + var $link_title = $context.find('.js-form-item-menu-title input'); + var $title = $this.closest('form').find('.js-form-item-title-0-value input'); // Bail out if we do not have all required fields. if (!($checkbox.length && $link_title.length && $title.length)) { return; diff --git a/core/modules/node/content_types.js b/core/modules/node/content_types.js index c77a2c3..6c4e3dd 100644 --- a/core/modules/node/content_types.js +++ b/core/modules/node/content_types.js @@ -29,7 +29,7 @@ $('#edit-language', context).drupalSetSummary(function (context) { var vals = []; - vals.push($(".form-item-language-configuration-langcode select option:selected", context).text()); + vals.push($(".js-form-item-language-configuration-langcode select option:selected", context).text()); $('input:checked', context).next('label').each(function () { vals.push(Drupal.checkPlain($(this).text())); diff --git a/core/modules/node/node.js b/core/modules/node/node.js index 60db08f..67f350e 100644 --- a/core/modules/node/node.js +++ b/core/modules/node/node.js @@ -12,13 +12,13 @@ var $context = $(context); $context.find('.node-form-revision-information').drupalSetSummary(function (context) { var $revisionContext = $(context); - var revisionCheckbox = $revisionContext.find('.form-item-revision input'); + var revisionCheckbox = $revisionContext.find('.js-form-item-revision input'); // Return 'New revision' if the 'Create new revision' checkbox is checked, // or if the checkbox doesn't exist, but the revision log does. For users // without the "Administer content" permission the checkbox won't appear, // but the revision log will if the content type is set to auto-revision. - if (revisionCheckbox.is(':checked') || (!revisionCheckbox.length && $revisionContext.find('.form-item-revision-log textarea').length)) { + if (revisionCheckbox.is(':checked') || (!revisionCheckbox.length && $revisionContext.find('.js-form-item-revision-log textarea').length)) { return Drupal.t('New revision'); } @@ -52,13 +52,13 @@ $context.find('fieldset.node-translation-options').drupalSetSummary(function (context) { var $translationContext = $(context); var translate; - var $checkbox = $translationContext.find('.form-item-translation-translate input'); + var $checkbox = $translationContext.find('.js-form-item-translation-translate input'); if ($checkbox.size()) { translate = $checkbox.is(':checked') ? Drupal.t('Needs to be updated') : Drupal.t('Does not need to be updated'); } else { - $checkbox = $translationContext.find('.form-item-translation-retranslate input'); + $checkbox = $translationContext.find('.js-form-item-translation-retranslate input'); translate = $checkbox.is(':checked') ? Drupal.t('Flag other translations as outdated') : Drupal.t('Do not flag other translations as outdated'); } diff --git a/core/modules/path/path.js b/core/modules/path/path.js index aa91bb2..29a8543 100644 --- a/core/modules/path/path.js +++ b/core/modules/path/path.js @@ -9,7 +9,7 @@ Drupal.behaviors.pathDetailsSummaries = { attach: function (context) { $(context).find('.path-form').drupalSetSummary(function (context) { - var path = $('.form-item-path-0-alias input').val(); + var path = $('.js-form-item-path-0-alias input').val(); return path ? Drupal.t('Alias: @alias', {'@alias': path}) : diff --git a/core/modules/system/src/Tests/Form/ElementsLabelsTest.php b/core/modules/system/src/Tests/Form/ElementsLabelsTest.php index dbf13d2..3d217b6 100644 --- a/core/modules/system/src/Tests/Form/ElementsLabelsTest.php +++ b/core/modules/system/src/Tests/Form/ElementsLabelsTest.php @@ -53,16 +53,16 @@ function testFormLabels() { // Exercise various defaults for textboxes and modifications to ensure // appropriate override and correct behavior. - $elements = $this->xpath('//label[@for="edit-form-textfield-test-title-and-required" and @class="form-required"]/following-sibling::input[@id="edit-form-textfield-test-title-and-required"]'); + $elements = $this->xpath('//label[@for="edit-form-textfield-test-title-and-required" and @class="js-form-required form-required"]/following-sibling::input[@id="edit-form-textfield-test-title-and-required"]'); $this->assertTrue(isset($elements[0]), 'Label precedes textfield, with required marker inside label.'); - $elements = $this->xpath('//input[@id="edit-form-textfield-test-no-title-required"]/preceding-sibling::label[@for="edit-form-textfield-test-no-title-required" and @class="form-required"]'); + $elements = $this->xpath('//input[@id="edit-form-textfield-test-no-title-required"]/preceding-sibling::label[@for="edit-form-textfield-test-no-title-required" and @class="js-form-required form-required"]'); $this->assertTrue(isset($elements[0]), 'Label tag with required marker precedes required textfield with no title.'); $elements = $this->xpath('//input[@id="edit-form-textfield-test-title-invisible"]/preceding-sibling::label[@for="edit-form-textfield-test-title-invisible" and @class="visually-hidden"]'); $this->assertTrue(isset($elements[0]), 'Label preceding field and label class is visually-hidden.'); - $elements = $this->xpath('//input[@id="edit-form-textfield-test-title"]/preceding-sibling::span[@class="form-required"]'); + $elements = $this->xpath('//input[@id="edit-form-textfield-test-title"]/preceding-sibling::span[@class="js-form-required form-required"]'); $this->assertFalse(isset($elements[0]), 'No required marker on non-required field.'); $elements = $this->xpath('//input[@id="edit-form-textfield-test-title-after"]/following-sibling::label[@for="edit-form-textfield-test-title-after" and @class="option"]'); @@ -71,7 +71,7 @@ function testFormLabels() { $elements = $this->xpath('//label[@for="edit-form-textfield-test-title-no-show"]'); $this->assertFalse(isset($elements[0]), 'No label tag when title set not to display.'); - $elements = $this->xpath('//div[contains(@class, "form-item-form-textfield-test-title-invisible") and contains(@class, "form-no-label")]'); + $elements = $this->xpath('//div[contains(@class, "js-form-item-form-textfield-test-title-invisible") and contains(@class, "form-no-label")]'); $this->assertTrue(isset($elements[0]), 'Field class is form-no-label when there is no label.'); // Check #field_prefix and #field_suffix placement. @@ -82,10 +82,10 @@ function testFormLabels() { $this->assertTrue(isset($elements[0]), 'Properly places the #field_suffix element immediately after the form field.'); // Check #prefix and #suffix placement. - $elements = $this->xpath('//div[@id="form-test-textfield-title-prefix"]/following-sibling::div[contains(@class, \'form-item-form-textfield-test-title\')]'); + $elements = $this->xpath('//div[@id="js-form-test-textfield-title-prefix"]/following-sibling::div[contains(@class, \'js-form-item-form-textfield-test-title\')]'); $this->assertTrue(isset($elements[0]), 'Properly places the #prefix element before the form item.'); - $elements = $this->xpath('//div[@id="form-test-textfield-title-suffix"]/preceding-sibling::div[contains(@class, \'form-item-form-textfield-test-title\')]'); + $elements = $this->xpath('//div[@id="js-form-test-textfield-title-suffix"]/preceding-sibling::div[contains(@class, \'js-form-item-form-textfield-test-title\')]'); $this->assertTrue(isset($elements[0]), 'Properly places the #suffix element before the form item.'); // Check title attribute for radios and checkboxes. diff --git a/core/modules/system/src/Tests/Form/FormTest.php b/core/modules/system/src/Tests/Form/FormTest.php index e82002b..b824dcf 100644 --- a/core/modules/system/src/Tests/Form/FormTest.php +++ b/core/modules/system/src/Tests/Form/FormTest.php @@ -96,7 +96,7 @@ function testRequiredFields() { $elements['file']['empty_values'] = $empty_strings; // Regular expression to find the expected marker on required elements. - $required_marker_preg = '@<.*?class=".*?form-required.*?">@'; + $required_marker_preg = '@<.*?class=".*?js-form-required.*form-required.*?">@'; // Go through all the elements and all the empty values for them. foreach ($elements as $type => $data) { foreach ($data['empty_values'] as $key => $empty) { diff --git a/core/modules/system/src/Tests/Form/RebuildTest.php b/core/modules/system/src/Tests/Form/RebuildTest.php index 76de748..b6593b8 100644 --- a/core/modules/system/src/Tests/Form/RebuildTest.php +++ b/core/modules/system/src/Tests/Form/RebuildTest.php @@ -102,7 +102,7 @@ function testPreserveFormActionAfterAJAX() { // Ensure that the form contains two items in the multi-valued field, so we // know we're testing a form that was correctly retrieved from cache. - $this->assert(count($this->xpath('//form[contains(@id, "page-node-form")]//div[contains(@class, "form-item-field-ajax-test")]//input[@type="text"]')) == 2, 'Form retained its state from cache.'); + $this->assert(count($this->xpath('//form[contains(@id, "page-node-form")]//div[contains(@class, "js-form-item-field-ajax-test")]//input[@type="text"]')) == 2, 'Form retained its state from cache.'); // Ensure that the form's action is correct. $forms = $this->xpath('//form[contains(@class, "node-page-form")]'); diff --git a/core/modules/system/src/Tests/System/ThemeTest.php b/core/modules/system/src/Tests/System/ThemeTest.php index ccfc727..f68a7fe 100644 --- a/core/modules/system/src/Tests/System/ThemeTest.php +++ b/core/modules/system/src/Tests/System/ThemeTest.php @@ -88,7 +88,7 @@ function testThemeSettings() { // Verify logo path examples. $elements = $this->xpath('//div[contains(@class, :item)]/div[@class=:description]/code', array( - ':item' => 'form-item-logo-path', + ':item' => 'js-form-item-logo-path', ':description' => 'description', )); // Expected default values (if all else fails). diff --git a/core/modules/system/templates/container.html.twig b/core/modules/system/templates/container.html.twig index 6fb8159..2f71632 100644 --- a/core/modules/system/templates/container.html.twig +++ b/core/modules/system/templates/container.html.twig @@ -17,4 +17,9 @@ * @ingroup themeable */ #} -{{ children }} +{% + set classes = [ + has_parent ? 'js-form-wrapper', + ] +%} +{{ children }} diff --git a/core/modules/system/templates/datetime-wrapper.html.twig b/core/modules/system/templates/datetime-wrapper.html.twig index 443b5b3..62a4b9d 100644 --- a/core/modules/system/templates/datetime-wrapper.html.twig +++ b/core/modules/system/templates/datetime-wrapper.html.twig @@ -17,7 +17,7 @@ #} {% set title_classes = [ - required ? 'form-required', + required ? 'js-form-required', ] %} {% if title %} diff --git a/core/modules/system/templates/field-multiple-value-form.html.twig b/core/modules/system/templates/field-multiple-value-form.html.twig index f18a853..a2cbeba 100644 --- a/core/modules/system/templates/field-multiple-value-form.html.twig +++ b/core/modules/system/templates/field-multiple-value-form.html.twig @@ -20,7 +20,7 @@ */ #} {% if multiple %} -
+
{{ table }} {% if description %}
{{ description }}
diff --git a/core/modules/system/templates/fieldset.html.twig b/core/modules/system/templates/fieldset.html.twig index ab6796c..cb8b41b 100644 --- a/core/modules/system/templates/fieldset.html.twig +++ b/core/modules/system/templates/fieldset.html.twig @@ -21,24 +21,29 @@ * @ingroup themeable */ #} - +{% + set classes = [ + 'js-form-item', + 'js-form-wrapper', + ] +%} + {% set legend_span_classes = [ - 'fieldset-legend', - required ? 'form-required', + required ? 'js-form-required', ] %} {# Always wrap fieldset legends in a SPAN for CSS positioning. #} {{ legend.title }} -
+
{% if prefix %} - {{ prefix }} + {{ prefix }} {% endif %} {{ children }} {% if suffix %} - {{ suffix }} + {{ suffix }} {% endif %} {% if description.content %} {{ description.content }}
diff --git a/core/modules/system/templates/form-element-label.html.twig b/core/modules/system/templates/form-element-label.html.twig index 6ececd9..a86ade4 100644 --- a/core/modules/system/templates/form-element-label.html.twig +++ b/core/modules/system/templates/form-element-label.html.twig @@ -16,9 +16,8 @@ #} {% set classes = [ - title_display == 'after' ? 'option', title_display == 'invisible' ? 'visually-hidden', - required ? 'form-required', + required ? 'js-form-required', ] %} {% if title is not empty or required -%} diff --git a/core/modules/system/templates/form-element.html.twig b/core/modules/system/templates/form-element.html.twig index a961801..693c8cf 100644 --- a/core/modules/system/templates/form-element.html.twig +++ b/core/modules/system/templates/form-element.html.twig @@ -47,16 +47,15 @@ #} {% set classes = [ - 'form-item', - 'form-type-' ~ type|clean_class, - 'form-item-' ~ name|clean_class, + 'js-form-item', + 'js-form-type-' ~ type|clean_class, + 'js-form-item-' ~ name|clean_class, title_display not in ['after', 'before'] ? 'form-no-label', disabled == 'disabled' ? 'form-disabled', ] %} {% set description_classes = [ - 'description', description_display == 'invisible' ? 'visually-hidden', ] %} diff --git a/core/modules/taxonomy/src/Plugin/views/filter/TaxonomyIndexTid.php b/core/modules/taxonomy/src/Plugin/views/filter/TaxonomyIndexTid.php index 573448d..02e81ae 100644 --- a/core/modules/taxonomy/src/Plugin/views/filter/TaxonomyIndexTid.php +++ b/core/modules/taxonomy/src/Plugin/views/filter/TaxonomyIndexTid.php @@ -154,7 +154,7 @@ protected function valueForm(&$form, FormStateInterface $form_state) { $vocabulary = $this->vocabularyStorage->load($this->options['vid']); if (empty($vocabulary) && $this->options['limit']) { $form['markup'] = array( - '#markup' => '
' . $this->t('An invalid vocabulary is selected. Please change it in the options.') . '
', + '#markup' => '
' . $this->t('An invalid vocabulary is selected. Please change it in the options.') . '
', ); return; } diff --git a/core/modules/text/text.js b/core/modules/text/text.js index 10aed14..2d092c0 100644 --- a/core/modules/text/text.js +++ b/core/modules/text/text.js @@ -12,7 +12,7 @@ var $summary = $widget.find('.text-summary-wrapper'); var $summaryLabel = $summary.find('label').first(); - var $full = $widget.find('.text-full').closest('.form-item'); + var $full = $widget.find('.text-full').closest('.js-form-item'); var $fullLabel = $full.find('label').first(); // Create a placeholder label when the field cardinality is greater diff --git a/core/modules/views/src/Plugin/views/BrokenHandlerTrait.php b/core/modules/views/src/Plugin/views/BrokenHandlerTrait.php index c579c2b..1c6b280 100644 --- a/core/modules/views/src/Plugin/views/BrokenHandlerTrait.php +++ b/core/modules/views/src/Plugin/views/BrokenHandlerTrait.php @@ -69,7 +69,7 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) { $form['description'] = array( '#type' => 'container', '#attributes' => array( - 'class' => array('form-item', 'description'), + 'class' => array('js-form-item', 'form-item', 'description'), ), 'description_top' => array( '#markup' => '

' . $description_top . '

', diff --git a/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php b/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php index 1e5d894..d5eff8c 100644 --- a/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php +++ b/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php @@ -1543,7 +1543,7 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) { $access_plugin = $this->getPlugin('access'); if ($access_plugin->usesOptions()) { $form['markup'] = array( - '#prefix' => '
', + '#prefix' => '
', '#markup' => $this->t('You may also adjust the !settings for the currently selected access restriction.', array('!settings' => $this->optionLink(t('settings'), 'access_options'))), '#suffix' => '
', ); @@ -1580,7 +1580,7 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) { $cache_plugin = $this->getPlugin('cache'); if ($cache_plugin->usesOptions()) { $form['markup'] = array( - '#prefix' => '
', + '#prefix' => '
', '#suffix' => '
', '#markup' => $this->t('You may also adjust the !settings for the currently selected cache mechanism.', array('!settings' => $this->optionLink(t('settings'), 'cache_options'))), ); @@ -1652,7 +1652,7 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) { if ($style_plugin->usesOptions()) { $form['markup'] = array( - '#prefix' => '
', + '#prefix' => '
', '#suffix' => '
', '#markup' => $this->t('You may also adjust the !settings for the currently selected style.', array('!settings' => $this->optionLink(t('settings'), 'style_options'))), ); @@ -1700,7 +1700,7 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) { if ($row_plugin_instance->usesOptions()) { $form['markup'] = array( - '#prefix' => '
', + '#prefix' => '
', '#suffix' => '
', '#markup' => $this->t('You may also adjust the !settings for the currently selected row style.', array('!settings' => $this->optionLink(t('settings'), 'row_options'))), ); @@ -1767,7 +1767,7 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) { case 'exposed_block': $form['#title'] .= $this->t('Put the exposed form in a block'); $form['description'] = array( - '#markup' => '
' . $this->t('If set, any exposed widgets will not appear with this view. Instead, a block will be made available to the Drupal block administration system, and the exposed form will appear there. Note that this block must be enabled manually, Views will not enable it for you.') . '
', + '#markup' => '
' . $this->t('If set, any exposed widgets will not appear with this view. Instead, a block will be made available to the Drupal block administration system, and the exposed form will appear there. Note that this block must be enabled manually, Views will not enable it for you.') . '
', ); $form['exposed_block'] = array( '#type' => 'radios', @@ -1795,7 +1795,7 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) { $exposed_form_plugin = $this->getPlugin('exposed_form'); if ($exposed_form_plugin->usesOptions()) { $form['markup'] = array( - '#prefix' => '
', + '#prefix' => '
', '#suffix' => '
', '#markup' => $this->t('You may also adjust the !settings for the currently selected style.', array('!settings' => $this->optionLink(t('settings'), 'exposed_form_options'))), ); @@ -1831,7 +1831,7 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) { $pager_plugin = $this->getPlugin('pager'); if ($pager_plugin->usesOptions()) { $form['markup'] = array( - '#prefix' => '
', + '#prefix' => '
', '#suffix' => '
', '#markup' => $this->t('You may also adjust the !settings for the currently selected pager.', array('!settings' => $this->optionLink(t('settings'), 'pager_options'))), ); diff --git a/core/modules/views/src/Plugin/views/display/Page.php b/core/modules/views/src/Plugin/views/display/Page.php index 27905b8..62da060 100644 --- a/core/modules/views/src/Plugin/views/display/Page.php +++ b/core/modules/views/src/Plugin/views/display/Page.php @@ -315,7 +315,7 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) { } $form['tab_markup'] = array( - '#markup' => '
' . $this->t('When providing a menu item as a tab, Drupal needs to know what the parent menu item of that tab will be. Sometimes the parent will already exist, but other times you will need to have one created. The path of a parent item will always be the same path with the last part left off. i.e, if the path to this view is foo/bar/baz, the parent path would be foo/bar.') . '
', + '#markup' => '
' . $this->t('When providing a menu item as a tab, Drupal needs to know what the parent menu item of that tab will be. Sometimes the parent will already exist, but other times you will need to have one created. The path of a parent item will always be the same path with the last part left off. i.e, if the path to this view is foo/bar/baz, the parent path would be foo/bar.') . '
', ); $form['tab_options'] = array( diff --git a/core/modules/views/src/Plugin/views/style/Table.php b/core/modules/views/src/Plugin/views/style/Table.php index dea6f0f..6783f88 100644 --- a/core/modules/views/src/Plugin/views/style/Table.php +++ b/core/modules/views/src/Plugin/views/style/Table.php @@ -412,7 +412,7 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) { ); $form['description_markup'] = array( - '#markup' => '
' . $this->t('Place fields into columns; you may combine multiple fields into the same column. If you do, the separator in the column specified will be used to separate the fields. Check the sortable box to make that column click sortable, and check the default sort radio to determine which column will be sorted by default, if any. You may control column order and field labels in the fields section.') . '
', + '#markup' => '
' . $this->t('Place fields into columns; you may combine multiple fields into the same column. If you do, the separator in the column specified will be used to separate the fields. Check the sortable box to make that column click sortable, and check the default sort radio to determine which column will be sorted by default, if any. You may control column order and field labels in the fields section.') . '
', ); } diff --git a/core/modules/views/src/Tests/ViewElementTest.php b/core/modules/views/src/Tests/ViewElementTest.php index e9c8105..bd17747 100644 --- a/core/modules/views/src/Tests/ViewElementTest.php +++ b/core/modules/views/src/Tests/ViewElementTest.php @@ -71,7 +71,7 @@ public function testViewElement() { // Test a form. $this->drupalGet('views_test_data_element_form'); - $xpath = $this->xpath('//div[@class="views-element-container form-wrapper"]'); + $xpath = $this->xpath('//div[@class="views-element-container js-form-wrapper form-wrapper"]'); $this->assertTrue($xpath, 'The view container has been found on the form.'); $xpath = $this->xpath('//div[@class="view-content"]'); @@ -138,7 +138,7 @@ public function testViewElementEmbed() { // Test a form. $this->drupalGet('views_test_data_element_embed_form'); - $xpath = $this->xpath('//div[@class="views-element-container form-wrapper"]'); + $xpath = $this->xpath('//div[@class="views-element-container js-form-wrapper form-wrapper"]'); $this->assertTrue($xpath, 'The view container has been found on the form.'); $xpath = $this->xpath('//div[@class="view-content"]'); diff --git a/core/modules/views_ui/js/views-admin.js b/core/modules/views_ui/js/views-admin.js index 5310062..4ea32ba 100644 --- a/core/modules/views_ui/js/views-admin.js +++ b/core/modules/views_ui/js/views-admin.js @@ -426,7 +426,7 @@ } var $context = $(context); var $table = $context.find('#views-rearrange-filters').once('views-rearrange-filters'); - var $operator = $context.find('.form-item-filter-groups-operator').once('views-rearrange-filters'); + var $operator = $context.find('.js-form-item-filter-groups-operator').once('views-rearrange-filters'); if ($table.length) { new Drupal.viewsUi.RearrangeFilterHandler($table, $operator); } @@ -769,7 +769,7 @@ Drupal.behaviors.viewsFilterConfigSelectAll = { attach: function (context) { // Show the select all checkbox. - $(context).find('#views-ui-handler-form div.form-item-options-value-all').once('filterConfigSelectAll') + $(context).find('#views-ui-handler-form div.js-form-item-options-value-all').once('filterConfigSelectAll') .show() .find('input[type=checkbox]') .on('click', function () { @@ -780,7 +780,7 @@ }); }); // Uncheck the select all checkbox if any of the others are unchecked. - $('#views-ui-handler-form').find('div.form-type-checkbox').not($('.form-item-options-value-all')) + $('#views-ui-handler-form').find('div.js-form-type-checkbox').not($('.js-form-item-options-value-all')) .find('input[type=checkbox]') .on('click', function () { if ($(this).is('checked') === false) { diff --git a/core/modules/views_ui/src/Form/Ajax/AddHandler.php b/core/modules/views_ui/src/Form/Ajax/AddHandler.php index 8cc2e8c..31af86d 100644 --- a/core/modules/views_ui/src/Form/Ajax/AddHandler.php +++ b/core/modules/views_ui/src/Form/Ajax/AddHandler.php @@ -162,7 +162,7 @@ public function buildForm(array $form, FormStateInterface $form_state) { } else { $form['options']['markup'] = array( - '#markup' => '
' . $this->t('There are no @types available to add.', array('@types' => $ltitle)) . '
', + '#markup' => '
' . $this->t('There are no @types available to add.', array('@types' => $ltitle)) . '
', ); } // Add a div to show the selected items diff --git a/core/modules/views_ui/src/Form/Ajax/Analyze.php b/core/modules/views_ui/src/Form/Ajax/Analyze.php index 95e126a..b53800d 100644 --- a/core/modules/views_ui/src/Form/Ajax/Analyze.php +++ b/core/modules/views_ui/src/Form/Ajax/Analyze.php @@ -44,7 +44,7 @@ public function buildForm(array $form, FormStateInterface $form_state) { $messages = $analyzer->getMessages($view->getExecutable()); $form['analysis'] = array( - '#prefix' => '
', + '#prefix' => '
', '#suffix' => '
', '#markup' => $analyzer->formatMessages($messages), ); diff --git a/core/modules/views_ui/src/Form/Ajax/ConfigHandler.php b/core/modules/views_ui/src/Form/Ajax/ConfigHandler.php index 28a7323..9ffe542 100644 --- a/core/modules/views_ui/src/Form/Ajax/ConfigHandler.php +++ b/core/modules/views_ui/src/Form/Ajax/ConfigHandler.php @@ -160,7 +160,7 @@ public function buildForm(array $form, FormStateInterface $form_state, Request $ $form['options']['form_description'] = array( '#markup' => $handler->definition['help'], '#theme_wrappers' => array('container'), - '#attributes' => array('class' => array('form-item description')), + '#attributes' => array('class' => array('js-form-item form-item description')), '#weight' => -1000, ); } diff --git a/core/themes/classy/templates/content-edit/text-format-wrapper.html.twig b/core/themes/classy/templates/content-edit/text-format-wrapper.html.twig index 4e5ff6d..f380ad7 100644 --- a/core/themes/classy/templates/content-edit/text-format-wrapper.html.twig +++ b/core/themes/classy/templates/content-edit/text-format-wrapper.html.twig @@ -15,7 +15,7 @@ * @ingroup themeable */ #} -
+
{{ children }} {% if description %} {% diff --git a/core/themes/classy/templates/form/container.html.twig b/core/themes/classy/templates/form/container.html.twig index 6fb8159..167965c 100644 --- a/core/themes/classy/templates/form/container.html.twig +++ b/core/themes/classy/templates/form/container.html.twig @@ -17,4 +17,10 @@ * @ingroup themeable */ #} -{{ children }}
+{% + set classes = [ + has_parent ? 'js-form-wrapper', + has_parent ? 'form-wrapper', + ] +%} +{{ children }}
diff --git a/core/themes/classy/templates/form/datetime-wrapper.html.twig b/core/themes/classy/templates/form/datetime-wrapper.html.twig index 45ba069..fbf6bb2 100644 --- a/core/themes/classy/templates/form/datetime-wrapper.html.twig +++ b/core/themes/classy/templates/form/datetime-wrapper.html.twig @@ -18,6 +18,7 @@ {% set title_classes = [ 'label', + required ? 'js-form-required', required ? 'form-required', ] %} diff --git a/core/themes/classy/templates/form/field-multiple-value-form.html.twig b/core/themes/classy/templates/form/field-multiple-value-form.html.twig index f18a853..348621c 100644 --- a/core/themes/classy/templates/form/field-multiple-value-form.html.twig +++ b/core/themes/classy/templates/form/field-multiple-value-form.html.twig @@ -20,7 +20,7 @@ */ #} {% if multiple %} -
+
{{ table }} {% if description %}
{{ description }}
diff --git a/core/themes/classy/templates/form/fieldset.html.twig b/core/themes/classy/templates/form/fieldset.html.twig index ab6796c..65533ec 100644 --- a/core/themes/classy/templates/form/fieldset.html.twig +++ b/core/themes/classy/templates/form/fieldset.html.twig @@ -21,10 +21,19 @@ * @ingroup themeable */ #} - +{% + set classes = [ + 'js-form-item', + 'form-item', + 'js-form-wrapper', + 'form-wrapper', + ] +%} + {% set legend_span_classes = [ 'fieldset-legend', + required ? 'js-form-required', required ? 'form-required', ] %} diff --git a/core/themes/classy/templates/form/form-element-label.html.twig b/core/themes/classy/templates/form/form-element-label.html.twig index 6ececd9..7696609 100644 --- a/core/themes/classy/templates/form/form-element-label.html.twig +++ b/core/themes/classy/templates/form/form-element-label.html.twig @@ -18,6 +18,7 @@ set classes = [ title_display == 'after' ? 'option', title_display == 'invisible' ? 'visually-hidden', + required ? 'js-form-required', required ? 'form-required', ] %} diff --git a/core/themes/classy/templates/form/form-element.html.twig b/core/themes/classy/templates/form/form-element.html.twig index a961801..f2c8a7f 100644 --- a/core/themes/classy/templates/form/form-element.html.twig +++ b/core/themes/classy/templates/form/form-element.html.twig @@ -47,8 +47,11 @@ #} {% set classes = [ + 'js-form-item', 'form-item', + 'js-form-type-' ~ type|clean_class, 'form-type-' ~ type|clean_class, + 'js-form-item-' ~ name|clean_class, 'form-item-' ~ name|clean_class, title_display not in ['after', 'before'] ? 'form-no-label', disabled == 'disabled' ? 'form-disabled',