From 63619f5c642c641f3f0069f5285897c145b2273e Mon Sep 17 00:00:00 2001 From: webchick Date: Wed, 28 Nov 2012 23:26:16 -0800 Subject: [PATCH] Issue #1241938 by swentel, Niklas Fiekas, yched: Added support for #placeholder to relevant Field API widgets. --- .../field/widget/EmailDefaultWidget.php | 17 +++++++++ .../lib/Drupal/email/Tests/EmailFieldTest.php | 4 +++ .../lib/Drupal/link/Tests/LinkFieldTest.php | 12 +++++++ core/modules/field/modules/link/link.module | 35 +++++++++++++++++++ .../Plugin/field/widget/NumberWidget.php | 17 +++++++++ .../Drupal/number/Tests/NumberFieldTest.php | 4 +++ .../Plugin/field/widget/TextareaWidget.php | 10 +++++- .../widget/TextareaWithSummaryWidget.php | 3 +- .../Plugin/field/widget/TextfieldWidget.php | 10 +++++- .../lib/Drupal/text/Tests/TextFieldTest.php | 4 +++ .../Drupal/field_ui/Tests/FieldUiTestBase.php | 2 +- .../widget/TaxonomyAutocompleteWidget.php | 17 ++++++++- .../lib/Drupal/taxonomy/Tests/TermTest.php | 13 +++++-- 13 files changed, 141 insertions(+), 7 deletions(-) diff --git a/core/modules/field/modules/email/lib/Drupal/email/Plugin/field/widget/EmailDefaultWidget.php b/core/modules/field/modules/email/lib/Drupal/email/Plugin/field/widget/EmailDefaultWidget.php index bb4e8595ea7..de603582b4d 100644 --- a/core/modules/field/modules/email/lib/Drupal/email/Plugin/field/widget/EmailDefaultWidget.php +++ b/core/modules/field/modules/email/lib/Drupal/email/Plugin/field/widget/EmailDefaultWidget.php @@ -20,11 +20,27 @@ use Drupal\field\Plugin\Type\Widget\WidgetBase; * label = @Translation("E-mail"), * field_types = { * "email" + * }, + * settings = { + * "placeholder" = "" * } * ) */ class EmailDefaultWidget extends WidgetBase { + /** + * Implements Drupal\field\Plugin\Type\Widget\WidgetInterface::settingsForm(). + */ + public function settingsForm(array $form, array &$form_state) { + $element['placeholder'] = array( + '#type' => 'textfield', + '#title' => t('Placeholder'), + '#default_value' => $this->getSetting('placeholder'), + '#description' => t('The placeholder is a short hint (a word or short phrase) intended to aid the user with data entry. A hint could be a sample value or a brief description of the expected format.'), + ); + return $element; + } + /** * Implements Drupal\field\Plugin\Type\Widget\WidgetInterface::formElement(). */ @@ -32,6 +48,7 @@ class EmailDefaultWidget extends WidgetBase { $element['value'] = $element + array( '#type' => 'email', '#default_value' => isset($items[$delta]['value']) ? $items[$delta]['value'] : NULL, + '#placeholder' => $this->getSetting('placeholder'), ); return $element; } diff --git a/core/modules/field/modules/email/lib/Drupal/email/Tests/EmailFieldTest.php b/core/modules/field/modules/email/lib/Drupal/email/Tests/EmailFieldTest.php index 932708e24b2..c88f56342e5 100644 --- a/core/modules/field/modules/email/lib/Drupal/email/Tests/EmailFieldTest.php +++ b/core/modules/field/modules/email/lib/Drupal/email/Tests/EmailFieldTest.php @@ -56,6 +56,9 @@ class EmailFieldTest extends WebTestBase { 'bundle' => 'test_bundle', 'widget' => array( 'type' => 'email_default', + 'settings' => array( + 'placeholder' => 'example@example.com', + ), ), 'display' => array( 'full' => array( @@ -69,6 +72,7 @@ class EmailFieldTest extends WebTestBase { $this->drupalGet('test-entity/add/test_bundle'); $langcode = LANGUAGE_NOT_SPECIFIED; $this->assertFieldByName("{$this->field['field_name']}[$langcode][0][value]", '', 'Widget found.'); + $this->assertRaw('placeholder="example@example.com"'); // Submit a valid e-mail address and ensure it is accepted. $value = 'test@example.com'; diff --git a/core/modules/field/modules/link/lib/Drupal/link/Tests/LinkFieldTest.php b/core/modules/field/modules/link/lib/Drupal/link/Tests/LinkFieldTest.php index acca9883d56..a3366d2d885 100644 --- a/core/modules/field/modules/link/lib/Drupal/link/Tests/LinkFieldTest.php +++ b/core/modules/field/modules/link/lib/Drupal/link/Tests/LinkFieldTest.php @@ -58,6 +58,9 @@ class LinkFieldTest extends WebTestBase { ), 'widget' => array( 'type' => 'link_default', + 'settings' => array( + 'placeholder_url' => 'http://example.com', + ), ), 'display' => array( 'full' => array( @@ -71,6 +74,7 @@ class LinkFieldTest extends WebTestBase { // Display creation form. $this->drupalGet('test-entity/add/test_bundle'); $this->assertFieldByName("{$this->field['field_name']}[$langcode][0][url]", '', 'Link URL field is displayed'); + $this->assertRaw('placeholder="http://example.com"'); // Verify that a valid URL can be submitted. $value = 'http://www.example.com/'; @@ -121,6 +125,10 @@ class LinkFieldTest extends WebTestBase { ), 'widget' => array( 'type' => 'link_default', + 'settings' => array( + 'placeholder_url' => 'http://example.com', + 'placeholder_title' => 'Enter a title for this link', + ), ), 'display' => array( 'full' => array( @@ -141,11 +149,15 @@ class LinkFieldTest extends WebTestBase { // Display creation form. $this->drupalGet('test-entity/add/test_bundle'); $this->assertFieldByName("{$this->field['field_name']}[$langcode][0][url]", '', 'URL field found.'); + $this->assertRaw('placeholder="http://example.com"'); if ($title_setting === DRUPAL_DISABLED) { $this->assertNoFieldByName("{$this->field['field_name']}[$langcode][0][title]", '', 'Title field not found.'); + $this->assertNoRaw('placeholder="Enter a title for this link"'); } else { + $this->assertRaw('placeholder="Enter a title for this link"'); + $this->assertFieldByName("{$this->field['field_name']}[$langcode][0][title]", '', 'Title field found.'); if ($title_setting === DRUPAL_REQUIRED) { // Verify that the title is required, if the URL is non-empty. diff --git a/core/modules/field/modules/link/link.module b/core/modules/field/modules/link/link.module index 947c2e9ef39..0e204df5da1 100644 --- a/core/modules/field/modules/link/link.module +++ b/core/modules/field/modules/link/link.module @@ -97,19 +97,53 @@ function link_field_widget_info() { $widgets['link_default'] = array( 'label' => 'Link', 'field types' => array('link'), + 'settings' => array( + 'placeholder_title' => '', + 'placeholder_url' => '', + ), ); return $widgets; } +/** + * Implements hook_field_widget_settings_form(). + */ +function link_field_widget_settings_form($field, $instance) { + $widget = $instance['widget']; + $settings = $widget['settings']; + + $form['placeholder_url'] = array( + '#type' => 'textfield', + '#title' => t('Placeholder for URL'), + '#default_value' => $settings['placeholder_url'], + '#description' => t('The placeholder is a short hint (a word or short phrase) intended to aid the user with data entry. A hint could be a sample value or a brief description of the expected format.'), + ); + $form['placeholder_title'] = array( + '#type' => 'textfield', + '#title' => t('Placeholder for link title'), + '#default_value' => $settings['placeholder_title'], + '#description' => t('The placeholder is a short hint (a word or short phrase) intended to aid the user with data entry. A hint could be a sample value or a brief description of the expected format.'), + '#states' => array( + 'invisible' => array( + ':input[name="instance[settings][title]"]' => array('value' => DRUPAL_DISABLED), + ), + ), + ); + + return $form; +} + /** * Implements hook_field_widget_form(). */ function link_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) { $settings = $instance['settings']; + $widget_settings = $instance['widget']['settings']; $element['url'] = array( '#type' => 'url', '#title' => t('URL'), + '#placeholder' => isset($widget_settings['placeholder_url']) ? $widget_settings['placeholder_url'] : '', '#default_value' => isset($items[$delta]['url']) ? $items[$delta]['url'] : NULL, '#maxlength' => 2048, '#required' => $element['#required'], @@ -117,6 +151,7 @@ function link_field_widget_form(&$form, &$form_state, $field, $instance, $langco $element['title'] = array( '#type' => 'textfield', '#title' => t('Title'), + '#placeholder' => isset($widget_settings['placeholder_title']) ? $widget_settings['placeholder_title'] : '', '#default_value' => isset($items[$delta]['title']) ? $items[$delta]['title'] : NULL, '#maxlength' => 255, '#access' => $settings['title'] != DRUPAL_DISABLED, diff --git a/core/modules/field/modules/number/lib/Drupal/number/Plugin/field/widget/NumberWidget.php b/core/modules/field/modules/number/lib/Drupal/number/Plugin/field/widget/NumberWidget.php index ecaf2043e1b..ec9eaf664af 100644 --- a/core/modules/field/modules/number/lib/Drupal/number/Plugin/field/widget/NumberWidget.php +++ b/core/modules/field/modules/number/lib/Drupal/number/Plugin/field/widget/NumberWidget.php @@ -22,11 +22,27 @@ use Drupal\field\Plugin\Type\Widget\WidgetBase; * "number_integer", * "number_decimal", * "number_float" + * }, + * settings = { + * "placeholder" = "" * } * ) */ class NumberWidget extends WidgetBase { + /** + * Implements Drupal\field\Plugin\Type\Widget\WidgetInterface::settingsForm(). + */ + public function settingsForm(array $form, array &$form_state) { + $element['placeholder'] = array( + '#type' => 'textfield', + '#title' => t('Placeholder'), + '#default_value' => $this->getSetting('placeholder'), + '#description' => t('The placeholder is a short hint (a word or short phrase) intended to aid the user with data entry. A hint could be a sample value or a brief description of the expected format.'), + ); + return $element; + } + /** * Implements Drupal\field\Plugin\Type\Widget\WidgetInterface::formElement(). */ @@ -39,6 +55,7 @@ class NumberWidget extends WidgetBase { $element += array( '#type' => 'number', '#default_value' => $value, + '#placeholder' => $this->getSetting('placeholder'), ); // Set the step for floating point and decimal numbers. diff --git a/core/modules/field/modules/number/lib/Drupal/number/Tests/NumberFieldTest.php b/core/modules/field/modules/number/lib/Drupal/number/Tests/NumberFieldTest.php index 63bef1f474c..7588942136d 100644 --- a/core/modules/field/modules/number/lib/Drupal/number/Tests/NumberFieldTest.php +++ b/core/modules/field/modules/number/lib/Drupal/number/Tests/NumberFieldTest.php @@ -59,6 +59,9 @@ class NumberFieldTest extends WebTestBase { 'bundle' => 'test_bundle', 'widget' => array( 'type' => 'number', + 'settings' => array( + 'placeholder' => '0.00' + ), ), 'display' => array( 'default' => array( @@ -72,6 +75,7 @@ class NumberFieldTest extends WebTestBase { $this->drupalGet('test-entity/add/test_bundle'); $langcode = LANGUAGE_NOT_SPECIFIED; $this->assertFieldByName("{$this->field['field_name']}[$langcode][0][value]", '', 'Widget is displayed'); + $this->assertRaw('placeholder="0.00"'); // Submit a signed decimal value within the allowed precision and scale. $value = '-1234.5678'; diff --git a/core/modules/field/modules/text/lib/Drupal/text/Plugin/field/widget/TextareaWidget.php b/core/modules/field/modules/text/lib/Drupal/text/Plugin/field/widget/TextareaWidget.php index 17f80a03383..1ab41840bcc 100644 --- a/core/modules/field/modules/text/lib/Drupal/text/Plugin/field/widget/TextareaWidget.php +++ b/core/modules/field/modules/text/lib/Drupal/text/Plugin/field/widget/TextareaWidget.php @@ -22,7 +22,8 @@ use Drupal\field\Plugin\Type\Widget\WidgetBase; * "text_long" * }, * settings = { - * "rows" = "5" + * "rows" = "5", + * "placeholder" = "" * } * ) */ @@ -39,6 +40,12 @@ class TextareaWidget extends WidgetBase { '#required' => TRUE, '#min' => 1, ); + $element['placeholder'] = array( + '#type' => 'textfield', + '#title' => t('Placeholder'), + '#default_value' => $this->getSetting('placeholder'), + '#description' => t('The placeholder is a short hint (a word or short phrase) intended to aid the user with data entry. A hint could be a sample value or a brief description of the expected format.'), + ); return $element; } @@ -50,6 +57,7 @@ class TextareaWidget extends WidgetBase { '#type' => 'textarea', '#default_value' => isset($items[$delta]['value']) ? $items[$delta]['value'] : NULL, '#rows' => $this->getSetting('rows'), + '#placeholder' => $this->getSetting('placeholder'), '#attributes' => array('class' => array('text-full')), ); diff --git a/core/modules/field/modules/text/lib/Drupal/text/Plugin/field/widget/TextareaWithSummaryWidget.php b/core/modules/field/modules/text/lib/Drupal/text/Plugin/field/widget/TextareaWithSummaryWidget.php index 373f1ed2dbb..696cbe2ecec 100644 --- a/core/modules/field/modules/text/lib/Drupal/text/Plugin/field/widget/TextareaWithSummaryWidget.php +++ b/core/modules/field/modules/text/lib/Drupal/text/Plugin/field/widget/TextareaWithSummaryWidget.php @@ -22,7 +22,8 @@ use Drupal\Core\Annotation\Translation; * }, * settings = { * "rows" = "9", - * "summary_rows" = "3" + * "summary_rows" = "3", + * "placeholder" = "" * } * ) */ diff --git a/core/modules/field/modules/text/lib/Drupal/text/Plugin/field/widget/TextfieldWidget.php b/core/modules/field/modules/text/lib/Drupal/text/Plugin/field/widget/TextfieldWidget.php index e6b87b126f5..00396aea4a8 100644 --- a/core/modules/field/modules/text/lib/Drupal/text/Plugin/field/widget/TextfieldWidget.php +++ b/core/modules/field/modules/text/lib/Drupal/text/Plugin/field/widget/TextfieldWidget.php @@ -22,7 +22,8 @@ use Drupal\field\Plugin\Type\Widget\WidgetBase; * "text" * }, * settings = { - * "size" = "60" + * "size" = "60", + * "placeholder" = "" * } * ) */ @@ -39,6 +40,12 @@ class TextfieldWidget extends WidgetBase { '#required' => TRUE, '#min' => 1, ); + $element['placeholder'] = array( + '#type' => 'textfield', + '#title' => t('Placeholder'), + '#default_value' => $this->getSetting('placeholder'), + '#description' => t('The placeholder is a short hint (a word or short phrase) intended to aid the user with data entry. A hint could be a sample value or a brief description of the expected format.'), + ); return $element; } @@ -50,6 +57,7 @@ class TextfieldWidget extends WidgetBase { '#type' => 'textfield', '#default_value' => isset($items[$delta]['value']) ? $items[$delta]['value'] : NULL, '#size' => $this->getSetting('size'), + '#placeholder' => $this->getSetting('placeholder'), '#maxlength' => $this->field['settings']['max_length'], '#attributes' => array('class' => array('text-full')), ); diff --git a/core/modules/field/modules/text/lib/Drupal/text/Tests/TextFieldTest.php b/core/modules/field/modules/text/lib/Drupal/text/Tests/TextFieldTest.php index 1a415231868..8efc516b43b 100644 --- a/core/modules/field/modules/text/lib/Drupal/text/Tests/TextFieldTest.php +++ b/core/modules/field/modules/text/lib/Drupal/text/Tests/TextFieldTest.php @@ -114,6 +114,9 @@ class TextFieldTest extends WebTestBase { ), 'widget' => array( 'type' => $widget_type, + 'settings' => array( + 'placeholder' => 'A placeholder on ' . $widget_type, + ), ), 'display' => array( 'full' => array( @@ -128,6 +131,7 @@ class TextFieldTest extends WebTestBase { $this->drupalGet('test-entity/add/test_bundle'); $this->assertFieldByName("{$this->field_name}[$langcode][0][value]", '', 'Widget is displayed'); $this->assertNoFieldByName("{$this->field_name}[$langcode][0][format]", '1', 'Format selector is not displayed'); + $this->assertRaw(format_string('placeholder="A placeholder on !widget_type"', array('!widget_type' => $widget_type))); // Submit with some value. $value = $this->randomName(); diff --git a/core/modules/field_ui/lib/Drupal/field_ui/Tests/FieldUiTestBase.php b/core/modules/field_ui/lib/Drupal/field_ui/Tests/FieldUiTestBase.php index a67ad1f006e..68069dd2fb7 100644 --- a/core/modules/field_ui/lib/Drupal/field_ui/Tests/FieldUiTestBase.php +++ b/core/modules/field_ui/lib/Drupal/field_ui/Tests/FieldUiTestBase.php @@ -25,7 +25,7 @@ abstract class FieldUiTestBase extends WebTestBase { parent::setUp(); // Create test user. - $admin_user = $this->drupalCreateUser(array('access content', 'administer content types', 'administer taxonomy', 'administer users')); + $admin_user = $this->drupalCreateUser(array('access content', 'administer content types', 'administer taxonomy', 'administer users', 'bypass node access')); $this->drupalLogin($admin_user); // Create content type, with underscores. diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/field/widget/TaxonomyAutocompleteWidget.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/field/widget/TaxonomyAutocompleteWidget.php index 3f4d5109edd..096b689f502 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/field/widget/TaxonomyAutocompleteWidget.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/field/widget/TaxonomyAutocompleteWidget.php @@ -23,13 +23,27 @@ use Drupal\field\Plugin\Type\Widget\WidgetBase; * }, * settings = { * "size" = "60", - * "autocomplete_path" = "taxonomy/autocomplete" + * "autocomplete_path" = "taxonomy/autocomplete", + * "placeholder" = "" * }, * multiple_values = TRUE * ) */ class TaxonomyAutocompleteWidget extends WidgetBase { + /** + * Implements Drupal\field\Plugin\Type\Widget\WidgetInterface::settingsForm(). + */ + public function settingsForm(array $form, array &$form_state) { + $element['placeholder'] = array( + '#type' => 'textfield', + '#title' => t('Placeholder'), + '#default_value' => $this->getSetting('placeholder'), + '#description' => t('The placeholder is a short hint (a word or short phrase) intended to aid the user with data entry. A hint could be a sample value or a brief description of the expected format.'), + ); + return $element; + } + /** * Implements Drupal\field\Plugin\Type\Widget\WidgetInterface::formElement(). */ @@ -45,6 +59,7 @@ class TaxonomyAutocompleteWidget extends WidgetBase { '#default_value' => taxonomy_implode_tags($tags), '#autocomplete_path' => $this->getSetting('autocomplete_path') . '/' . $field['field_name'], '#size' => $this->getSetting('size'), + '#placeholder' => $this->getSetting('placeholder'), '#maxlength' => 1024, '#element_validate' => array('taxonomy_autocomplete_validate'), ); diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermTest.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermTest.php index b2603d68128..4abbf62d5f2 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermTest.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermTest.php @@ -142,7 +142,12 @@ class TermTest extends TaxonomyTestBase { function testNodeTermCreationAndDeletion() { // Enable tags in the vocabulary. $instance = $this->instance; - $instance['widget'] = array('type' => 'taxonomy_autocomplete'); + $instance['widget'] = array( + 'type' => 'taxonomy_autocomplete', + 'settings' => array( + 'placeholder' => 'Start typing here.', + ), + ); field_update_instance($instance); $terms = array( 'term1' => $this->randomName(), @@ -159,8 +164,12 @@ class TermTest extends TaxonomyTestBase { // free-tagging field created by the default profile. $edit[$instance['field_name'] . "[$langcode]"] = drupal_implode_tags($terms); + // Verify the placeholder is there. + $this->drupalGet('node/add/article'); + $this->assertRaw('placeholder="Start typing here."'); + // Preview and verify the terms appear but are not created. - $this->drupalPost('node/add/article', $edit, t('Preview')); + $this->drupalPost(NULL, $edit, t('Preview')); foreach ($terms as $term) { $this->assertText($term, 'The term appears on the node preview'); }