├── .gitignore ├── Block ├── Adminhtml │ └── Form │ │ └── Field │ │ ├── OptionalFieldConfig.php │ │ └── SpecificFieldConfig.php └── Onepage │ └── PlaceholderProcessor.php ├── CODE_OF_CONDUCT.md ├── LICENSE ├── Model ├── FieldFilter.php ├── PlaceholderInterface.php └── System │ ├── Config.php │ └── ConfigInterface.php ├── README.md ├── ViewModel └── ConfigViewModel.php ├── composer.json ├── etc ├── acl.xml ├── adminhtml │ └── system.xml ├── config.xml ├── frontend │ └── di.xml └── module.xml ├── i18n └── de_DE.csv ├── registration.php └── view └── frontend ├── layout └── checkout_index_index.xml ├── requirejs-config.js ├── templates ├── css.phtml └── custom-required-mark.phtml └── web └── template └── form └── element ├── email-amasty-checkout.html ├── email-amazon-pay.html ├── email-amazon-payment.html └── email.html /.gitignore: -------------------------------------------------------------------------------- 1 | .idea -------------------------------------------------------------------------------- /Block/Adminhtml/Form/Field/OptionalFieldConfig.php: -------------------------------------------------------------------------------- 1 | 6 | */ 7 | 8 | declare(strict_types=1); 9 | 10 | namespace Checkout\Placeholder\Block\Adminhtml\Form\Field; 11 | 12 | use Checkout\Placeholder\Model\System\ConfigInterface; 13 | use Magento\Config\Block\System\Config\Form\Field\FieldArray\AbstractFieldArray; 14 | 15 | class OptionalFieldConfig extends AbstractFieldArray implements ConfigInterface 16 | { 17 | protected function _prepareToRender() 18 | { 19 | $this->addColumn( 20 | self::COLUMN_KEY_FIELD_ID, 21 | ['label' => __('Field ID')] 22 | ); 23 | $this->addColumn( 24 | self::COLUMN_KEY_FIELDSET_ID, 25 | ['label' => __('Fieldset ID')] 26 | ); 27 | $this->_addAfter = false; 28 | $this->_addButtonLabel = __('Add'); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Block/Adminhtml/Form/Field/SpecificFieldConfig.php: -------------------------------------------------------------------------------- 1 | 6 | */ 7 | 8 | declare(strict_types=1); 9 | 10 | namespace Checkout\Placeholder\Block\Adminhtml\Form\Field; 11 | 12 | use Checkout\Placeholder\Model\System\ConfigInterface; 13 | use Magento\Config\Block\System\Config\Form\Field\FieldArray\AbstractFieldArray; 14 | 15 | class SpecificFieldConfig extends AbstractFieldArray implements ConfigInterface 16 | { 17 | protected function _prepareToRender() 18 | { 19 | $this->addColumn( 20 | self::COLUMN_KEY_FIELD_ID, 21 | ['label' => __('Field ID')] 22 | ); 23 | $this->addColumn( 24 | self::COLUMN_KEY_PLACEHOLDER, 25 | ['label' => 'Placeholder'] 26 | ); 27 | $this->addColumn( 28 | self::COLUMN_KEY_FIELDSET_ID, 29 | ['label' => __('Fieldset ID')] 30 | ); 31 | $this->_addAfter = false; 32 | $this->_addButtonLabel = __('Add'); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Block/Onepage/PlaceholderProcessor.php: -------------------------------------------------------------------------------- 1 | arrayManager = $arrayManager; 29 | $this->fieldFilter = $fieldFilter; 30 | $this->config = $config; 31 | } 32 | 33 | /** 34 | * Search and convert all field lists. 35 | */ 36 | private function processFields(array $jsLayout): array 37 | { 38 | $nodes = $this->fieldFilter->getLabeledFields($jsLayout); 39 | foreach ($nodes as $node) { 40 | $this->addPlaceholder($node); 41 | $jsLayout = $this->arrayManager->merge($node[self::KEY_PATH], $jsLayout, $node); 42 | } 43 | return $jsLayout; 44 | } 45 | 46 | private function addPlaceholder(array &$node): void 47 | { 48 | $config = $this->config->getFieldConfig($node[self::KEY_ID], $node[self::KEY_PATH]); 49 | $override = $config[Config::COLUMN_KEY_PLACEHOLDER] ?? ''; 50 | $label = $override ?: $node[self::KEY_LABEL] ?? false; 51 | if ($label) { 52 | $label = ($label instanceof Phrase) ? (string)__($label) : $label; 53 | $customMark = $this->getRequiredEntryMark($node) ?: $this->getOptionalEntryMark($config); 54 | $placeholder = $label . ' ' . $customMark; 55 | $node['config'][Config::COLUMN_KEY_PLACEHOLDER] = trim($placeholder); 56 | } 57 | } 58 | 59 | private function getRequiredEntryMark(array &$field): string 60 | { 61 | $requiredChar = $this->config->getCustomRequiredMark() ?: '*'; 62 | $isRequiredEntry = isset($field['validation']['required-entry']) 63 | && $field['validation']['required-entry'] 64 | && $this->config->getEnableRequiredMark(); 65 | return $isRequiredEntry ? $requiredChar : ''; 66 | } 67 | 68 | private function getOptionalEntryMark($config): string 69 | { 70 | return $config[Config::SYSTEM_CONFIG_KEY_CUSTOM_OPTIONAL_MARK] ?? ''; 71 | } 72 | 73 | /** 74 | * Processor init. 75 | * 76 | * @param array $jsLayout 77 | * @return array 78 | */ 79 | public function process($jsLayout) 80 | { 81 | return $this->config->getEnable() ? $this->processFields($jsLayout) : $jsLayout; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | info@mediarox.de. 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series 86 | of actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or 93 | permanent ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within 113 | the community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 120 | 121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 122 | enforcement ladder](https://github.com/mozilla/diversity). 123 | 124 | [homepage]: https://www.contributor-covenant.org 125 | 126 | For answers to common questions about this code of conduct, see the FAQ at 127 | https://www.contributor-covenant.org/faq. Translations are available at 128 | https://www.contributor-covenant.org/translations. 129 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 mediarox 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Model/FieldFilter.php: -------------------------------------------------------------------------------- 1 | 6 | */ 7 | 8 | declare(strict_types=1); 9 | 10 | namespace Checkout\Placeholder\Model; 11 | 12 | use Magento\Framework\Stdlib\ArrayManager; 13 | 14 | class FieldFilter implements PlaceholderInterface 15 | { 16 | protected ArrayManager $arrayManager; 17 | 18 | public function __construct( 19 | ArrayManager $arrayManager 20 | ) { 21 | $this->arrayManager = $arrayManager; 22 | } 23 | 24 | private function getFieldId(string $path) 25 | { 26 | $elements = explode(ArrayManager::DEFAULT_PATH_DELIMITER, $path); 27 | return array_pop($elements); 28 | } 29 | 30 | public function getLabeledFields(array $jsLayout): array 31 | { 32 | $checkoutRoot = $this->arrayManager->get(self::START_PATH_CHECKOUT_COMPONENTS_CHILDREN, $jsLayout); 33 | $componentPaths = $this->arrayManager->findPaths( 34 | self::KEY_LABEL, 35 | $checkoutRoot 36 | ); 37 | 38 | $nodes = []; 39 | foreach ($componentPaths as $componentPath) { 40 | $componentPath = str_replace('/label', '', $componentPath); 41 | $node = $this->arrayManager->get($componentPath, $checkoutRoot); 42 | if ($node) { 43 | $node[self::KEY_ID] = $this->getFieldId($componentPath); 44 | $node[self::KEY_PATH] = self::START_PATH_CHECKOUT_COMPONENTS_CHILDREN . 45 | ArrayManager::DEFAULT_PATH_DELIMITER . 46 | $componentPath; 47 | $nodes[] = $node; 48 | } 49 | } 50 | return $nodes; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Model/PlaceholderInterface.php: -------------------------------------------------------------------------------- 1 | 6 | */ 7 | 8 | namespace Checkout\Placeholder\Model; 9 | 10 | interface PlaceholderInterface 11 | { 12 | const START_PATH_CHECKOUT_COMPONENTS_CHILDREN = 'components/checkout/children'; 13 | 14 | const KEY_ID = 'id'; 15 | const KEY_PATH = 'path'; 16 | const KEY_LABEL = 'label'; 17 | } 18 | -------------------------------------------------------------------------------- /Model/System/Config.php: -------------------------------------------------------------------------------- 1 | 6 | */ 7 | 8 | declare(strict_types=1); 9 | 10 | namespace Checkout\Placeholder\Model\System; 11 | 12 | use Magento\Framework\App\Config\ScopeConfigInterface; 13 | use Magento\Framework\Serialize\Serializer\Json; 14 | use Magento\Store\Model\ScopeInterface; 15 | use Magento\Store\Model\StoreManagerInterface; 16 | 17 | class Config implements ConfigInterface 18 | { 19 | protected StoreManagerInterface $storeManager; 20 | protected ScopeConfigInterface $scopeConfig; 21 | protected Json $json; 22 | 23 | public function __construct(StoreManagerInterface $storeManager, ScopeConfigInterface $scopeConfig, Json $json) 24 | { 25 | $this->storeManager = $storeManager; 26 | $this->scopeConfig = $scopeConfig; 27 | $this->json = $json; 28 | } 29 | 30 | public function getConfigValue(string $key, string $basePath = self::SYSTEM_CONFIG_BASE_PATH_GENERAL) 31 | { 32 | return $this->scopeConfig->getValue( 33 | $basePath . $key, 34 | ScopeInterface::SCOPE_STORE, 35 | $this->storeManager->getStore() 36 | ); 37 | } 38 | 39 | public function getEnable(): int 40 | { 41 | return (int)$this->getConfigValue(self::SYSTEM_CONFIG_KEY_ENABLE); 42 | } 43 | 44 | public function getCustomRequiredMark(): string 45 | { 46 | return $this->getConfigValue(self::SYSTEM_CONFIG_KEY_CUSTOM_REQUIRED_MARK) ?: 47 | self::DEFAULT_REQUIRED_MARK; 48 | } 49 | 50 | public function getEnableRequiredMark(): int 51 | { 52 | return (int)$this->getConfigValue(self::SYSTEM_CONFIG_KEY_ENABLE_REQUIRED_MARK); 53 | } 54 | 55 | public function getEnableOptionalMark() 56 | { 57 | return (int)$this->getConfigValue( 58 | self::SYSTEM_CONFIG_KEY_ENABLE, 59 | self::SYSTEM_CONFIG_BASE_PATH_OPTIONAL_MARKS 60 | ); 61 | } 62 | 63 | public function getOptionalMark(): string 64 | { 65 | $optionalMark = $this->getConfigValue( 66 | self::SYSTEM_CONFIG_KEY_CUSTOM_OPTIONAL_MARK, 67 | self::SYSTEM_CONFIG_BASE_PATH_OPTIONAL_MARKS 68 | ) ?: self::DEFAULT_OPTIONAL_MARK; 69 | 70 | return $this->getEnableOptionalMark() ? $optionalMark : ''; 71 | } 72 | 73 | public function getFieldConfig(string $fieldId, string $path): array 74 | { 75 | if (count(str_split($fieldId)) == 1) { 76 | $fieldId = self::COLUMN_KEY_STREET_PREFIX . $fieldId; 77 | } 78 | 79 | $configPaths = [ 80 | self::SYSTEM_CONFIG_BASE_PATH_GENERAL => self::SYSTEM_CONFIG_KEY_SPECIFIC_FIELDS, 81 | self::SYSTEM_CONFIG_BASE_PATH_OPTIONAL_MARKS => self::SYSTEM_CONFIG_KEY_OPTIONAL_FIELDS, 82 | ]; 83 | 84 | $config = []; 85 | foreach ($configPaths as $basePath => $configKey) { 86 | $systemValues = $this->getConfigValue($configKey, $basePath) ? 87 | $this->json->unserialize($this->getConfigValue($configKey, $basePath)) : []; 88 | 89 | foreach ($systemValues as $value) { 90 | if (array_shift($value) === $fieldId) { 91 | $isUnique = isset($value[self::COLUMN_KEY_FIELDSET_ID]) && !empty($value[self::COLUMN_KEY_FIELDSET_ID]); 92 | $correctPath = $isUnique ? strstr($path, $value[self::COLUMN_KEY_FIELDSET_ID]) : false; 93 | if ($isUnique && $correctPath) { 94 | $config = array_merge($config, $value); 95 | } elseif ($isUnique && !$correctPath) { 96 | continue; 97 | } else { 98 | $config = array_merge($config, $value); 99 | } 100 | if ($basePath == self::SYSTEM_CONFIG_BASE_PATH_OPTIONAL_MARKS) { 101 | $config[self::SYSTEM_CONFIG_KEY_CUSTOM_OPTIONAL_MARK] = $this->getOptionalMark(); 102 | } 103 | } 104 | } 105 | } 106 | return $config; 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /Model/System/ConfigInterface.php: -------------------------------------------------------------------------------- 1 | 6 | */ 7 | 8 | namespace Checkout\Placeholder\Model\System; 9 | 10 | interface ConfigInterface 11 | { 12 | const SYSTEM_CONFIG_BASE_PATH_GENERAL = 'checkout_placeholder/general/'; 13 | const SYSTEM_CONFIG_KEY_ENABLE = 'enable'; 14 | const SYSTEM_CONFIG_KEY_ENABLE_REQUIRED_MARK = 'enable_required_mark'; 15 | const SYSTEM_CONFIG_KEY_CUSTOM_REQUIRED_MARK = 'custom_required_mark'; 16 | const DEFAULT_REQUIRED_MARK = '*'; 17 | const SYSTEM_CONFIG_KEY_SPECIFIC_FIELDS = 'specific_fields'; 18 | 19 | const SYSTEM_CONFIG_BASE_PATH_OPTIONAL_MARKS = 'checkout_placeholder/optional_marks/'; 20 | const SYSTEM_CONFIG_KEY_OPTIONAL_FIELDS = 'optional_fields'; 21 | const SYSTEM_CONFIG_KEY_CUSTOM_OPTIONAL_MARK = 'custom_optional_mark'; 22 | const DEFAULT_OPTIONAL_MARK = '(optional)'; 23 | 24 | const COLUMN_KEY_STREET_PREFIX = 'street_'; 25 | const COLUMN_KEY_FIELD_ID = 'field_id'; 26 | const COLUMN_KEY_PLACEHOLDER = 'placeholder'; 27 | const COLUMN_KEY_FIELDSET_ID = 'fieldset_id'; 28 | const COLUMN_KEY_SEARCH_KEY = 'searchKey'; 29 | } 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Checkout placeholder 2 | 3 | ## Description 4 | This module is designed to visually change all field pairs (label + field) so that the label is placed inside the field (As HTML Placeholder incl. "required-entry" mark "*"). Additionally, you can decide if you want to hide labels, define a custom required mark, hide required marks, customize placeholder text and mark fields as 5 | optional. 6 | 7 | ## Good to know 8 | 9 | Most of the fields in the checkout are collected via PHP and rendered dynamically via templates. For example, all input fields via the template `vendor/magento/module-ui/view/frontend/web/templates/form/element/input.html`. 10 | For all these dynamic fields we have created a [LayoutProcessor](https://devdocs.magento.com/guides/v2.4/howdoi/checkout/checkout_custom_checkbox.html) that provides the features described below. 11 | 12 | However, there are also fields that cannot be influenced via a LayoutProcessor. 13 | In a standard checkout these would be the fields: 14 | * email 15 | * password 16 | * password confirmation (if available) 17 | 18 | These fields are created together in the knockout template `Magento_Checkout/template/form/element/email` and are also not prepared for HTML placeholders by default. 19 | For these fields we provide at the moment only knockout templates overrides, which ensure that always (after installation) the label is used as a placeholder. Including the static required mark "*". 20 | 21 | As soon as time or a customer order allows, we would provide these fields with full features as well. 22 | 23 | ## Features 24 | 25 | * display field label as placeholder 26 | * customize placeholder text 27 | * hide labels 28 | * define a custom required mark 29 | * hide required mark 30 | * mark fields as optional 31 | 32 | ## Installation 33 | ```bash 34 | composer require mediarox/module-checkout-placeholder 35 | bin/magento setup:upgrade 36 | ``` 37 | 38 | ## Configuration 39 | 40 | STORES > Configuration > MEDIAROX > Checkout Placeholder 41 | 42 | ### General 43 | 44 | #### Enable 45 | Enables the module. After activation, the field placeholders are filled with the label by default. 46 | * path: checkout_placeholder/general/enable 47 | * default: 0 48 | 49 | #### Hide Labels 50 | Enable this setting to hide labels. 51 | * path: checkout_placeholder/general/hide_labels 52 | * default: 0 53 | 54 | #### Show Required Mark 55 | Enable to display required marks. 56 | * path: checkout_placeholder/general/enable_required_mark 57 | * default: 1 58 | 59 | #### Custom Required Mark 60 | If you want to display a custom required mark enter it here. 61 | * path: checkout_placeholder/general/custom_required_mark 62 | * default: '*' 63 | * depends on: checkout_placeholder/general/enable_required_mark = 1 64 | 65 | #### Specific Fields 66 | To override placeholder content (label text) for specific fields enter the field_id and placeholder you want to display. If you need to customize a field that is used in multiple fieldsets (e.g. firstname is available in billing & shipping address) enter an additional, unique fieldset id (e.g. billing-address: 'form-fields', shipping-address: 'shipping-address-fieldset'). For street fields use the field_ids `street_0`, `street_1` and `street_2`. 67 | * path: checkout_placeholder/general/specific_fields 68 | * default: '' 69 | 70 | ### Optional Fields 71 | 72 | #### Enable: 73 | If enabled a custom optional mark will be applied to fields configured in *Optional Fields*. 74 | * path: checkout_placeholder/optional_marks/enable 75 | * default: 0 76 | 77 | #### Optional Mark: 78 | Enter your optional text/mark that you want to display here. 79 | * path: checkout_placeholder/optional_marks/custom_optional_mark 80 | * default: '' 81 | 82 | #### Mark Fields As Optional: 83 | Specify the fields you want to display an optional mark for here. If you need to customize a field that is used in multiple fieldsets (e.g. firstname is available in billing & shipping address) enter an additional, unique fieldset id (e.g. billing-address: 'form-fields', shipping-address: 'shipping-address-fieldset'). For street fields use the field_ids `street_0`, `street_1` and `street_2`. 84 | * path: checkout_placeholder/optional_marks/optional_fields 85 | * default: '' 86 | 87 | ## Compatible with 88 | 89 | * amzn/amazon-pay-module (deprecated core dependency), tested: 4.2.2 90 | * [amzn/amazon-pay-magento-2-module](https://marketplace.magento.com/amzn-amazon-pay-magento-2-module.html) (up-to-date amazon pay module), tested: 5.7.1, 5.9.1 91 | * [amasty/module-single-step-checkout](https://amasty.com/one-step-checkout-for-magento-2.html), tested: 3.1.2, 3.1.3, 4.0.0 92 | 93 | #### Wiki 94 | 95 | * [How do I add a custom checkout field ?](https://github.com/mediarox/module-checkout-placeholder/wiki/How-do-I-add-a-custom-checkout-field-%3F) 96 | * [What does the checkout look like with the Amasty Checkout module ?](https://github.com/mediarox/module-checkout-placeholder/wiki/What-does-the-checkout-look-like-with-the-Amasty-Checkout-module-%3F) 97 | * [What about Hyvä or the Hyvä Checkout ?](https://github.com/mediarox/module-checkout-placeholder/wiki/What-about-Hyv%C3%A4-or-the-Hyv%C3%A4-Checkout-%3F) 98 | 99 | #### Before 100 | 101 | ![without_extension](https://user-images.githubusercontent.com/32567473/144977948-00406294-dbf6-4951-9de9-e21c0fc8abc8.jpg) 102 | 103 | #### After 104 | 105 | ![with_extension](https://user-images.githubusercontent.com/32567473/144977092-26bc5720-49cd-4b7f-9a0f-c1329cb99322.jpg) 106 | -------------------------------------------------------------------------------- /ViewModel/ConfigViewModel.php: -------------------------------------------------------------------------------- 1 | 6 | */ 7 | 8 | declare(strict_types=1); 9 | 10 | namespace Checkout\Placeholder\ViewModel; 11 | 12 | use Checkout\Placeholder\Model\System\Config; 13 | use Magento\Framework\View\Element\Block\ArgumentInterface; 14 | 15 | class ConfigViewModel implements ArgumentInterface 16 | { 17 | protected Config $config; 18 | 19 | public function __construct(Config $config) 20 | { 21 | $this->config = $config; 22 | } 23 | 24 | public function getConfig(): Config 25 | { 26 | return $this->config; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mediarox/module-checkout-placeholder", 3 | "description": "Show placeholders instead of labels at common checkout field's (incl. required entry mark).", 4 | "type": "magento2-module", 5 | "version": "0.4.3", 6 | "license": [ 7 | "MIT" 8 | ], 9 | "require": { 10 | "php": "~7.4|~8.0|~8.1", 11 | "magento/framework": "103.0.*", 12 | "magento/module-checkout": "100.4.*" 13 | }, 14 | "autoload": { 15 | "files": [ 16 | "registration.php" 17 | ], 18 | "psr-4": { 19 | "Checkout\\Placeholder\\": "" 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /etc/acl.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /etc/adminhtml/system.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 11 | 12 | 13 | 14 | 15 |
16 | mediarox 17 | Checkout_Placeholder::config 18 | 19 | 20 | 21 | 22 | 23 | Magento\Config\Model\Config\Source\Enabledisable 24 | 25 | 26 | 27 | Magento\Config\Model\Config\Source\Yesno 28 | 29 | 1 30 | 31 | 32 | 33 | 34 | Magento\Config\Model\Config\Source\Yesno 35 | 36 | 1 37 | 38 | 39 | 40 | 41 | 42 | 1 43 | 1 44 | 45 | 46 | 47 | 48 | Checkout\Placeholder\Block\Adminhtml\Form\Field\SpecificFieldConfig 49 | Magento\Config\Model\Config\Backend\Serialized\ArraySerialized 50 | 51 | 1 52 | 53 | 54 | 55 | 56 | 57 | 58 | 1 59 | 60 | 61 | 62 | Magento\Config\Model\Config\Source\Enabledisable 63 | 64 | 65 | 66 | 67 | 1 68 | 69 | 70 | 71 | 72 | Checkout\Placeholder\Block\Adminhtml\Form\Field\OptionalFieldConfig 73 | Magento\Config\Model\Config\Backend\Serialized\ArraySerialized 74 | 75 | 1 76 | 77 | 78 | 79 |
80 |
81 |
-------------------------------------------------------------------------------- /etc/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 11 | 12 | 13 | 14 | 0 15 | 0 16 | 1 17 | * 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /etc/frontend/di.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 10 | 11 | 12 | 13 | Checkout\Placeholder\Block\Onepage\PlaceholderProcessor 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /etc/module.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /i18n/de_DE.csv: -------------------------------------------------------------------------------- 1 | "To register an account simply add a password.", "Falls Sie einen Konto anlegen möchten, tragen Sie bitte ein Passwort ein." -------------------------------------------------------------------------------- /registration.php: -------------------------------------------------------------------------------- 1 | 2 | 9 | 11 | 12 | 13 | 15 | 17 | 18 | Checkout\Placeholder\ViewModel\ConfigViewModel 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /view/frontend/requirejs-config.js: -------------------------------------------------------------------------------- 1 | var config = { 2 | map: { 3 | '*': { 4 | 'Magento_Checkout/template/form/element/email': 5 | 'Checkout_Placeholder/template/form/element/email', 6 | 'Amasty_Checkout/template/form/element/email': 7 | 'Checkout_Placeholder/template/form/element/email-amasty-checkout', 8 | 'Amasty_CheckoutCore/template/form/element/email': 9 | 'Checkout_Placeholder/template/form/element/email-amasty-checkout', 10 | 'Amazon_Pay/template/form/element/email': 11 | 'Checkout_Placeholder/template/form/element/email-amazon-pay', 12 | 'Amazon_Payment/template/form/element/email': 13 | 'Checkout_Placeholder/template/form/element/email-amazon-payment', 14 | } 15 | } 16 | }; -------------------------------------------------------------------------------- /view/frontend/templates/css.phtml: -------------------------------------------------------------------------------- 1 | 6 | */ 7 | ?> 8 | 25 | -------------------------------------------------------------------------------- /view/frontend/templates/custom-required-mark.phtml: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * @var Template $block 8 | */ 9 | 10 | use Magento\Framework\View\Element\Template; 11 | 12 | ?> 13 | getData('config_view_model')->getConfig(); ?> 14 | getEnableRequiredMark()): ?> 15 | getCustomRequiredMark(); ?> 16 | 21 | 22 | 27 | -------------------------------------------------------------------------------- /view/frontend/web/template/form/element/email-amasty-checkout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |
10 |
11 |
12 | 15 |
16 |
17 | 29 |
30 | 31 | 32 | 33 |
34 |
35 | 36 | 37 |
38 |
39 | 42 |
43 | 58 | 59 | 60 | 61 | 62 | 63 | 64 |
65 |
66 |
67 | 70 |
71 | 82 |
83 |
84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 |
93 | 94 |
95 | 96 |
97 |
98 | 99 | 100 | 101 |
102 |
103 |
104 | 105 |
106 |
107 | 108 | -------------------------------------------------------------------------------- /view/frontend/web/template/form/element/email-amazon-pay.html: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 |
30 |
31 |
32 | 33 |
34 | 47 | 48 | 49 |
50 |
51 | 52 | 53 |
54 |
55 | 56 |
57 | 66 | 67 |
68 | 69 |
70 | 71 | 72 | 73 |
74 | 75 |
76 | 77 |
78 |
79 | 80 | 81 | 82 |
83 |
84 |
85 | 86 |
87 |
88 | 89 | -------------------------------------------------------------------------------- /view/frontend/web/template/form/element/email-amazon-payment.html: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
29 |
30 |
31 | 34 |
35 | 46 | 47 | 48 |
49 |
50 | 51 | 52 |
53 |
54 | 57 |
58 | 67 | 68 |
69 | 70 |
71 | 72 | 73 | 74 |
75 | 76 |
77 | 78 |
79 |
80 | 81 | 82 | 83 |
84 |
85 |
86 | 87 |
88 |
89 | 90 | -------------------------------------------------------------------------------- /view/frontend/web/template/form/element/email.html: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | 11 | 12 |
15 |
16 |
17 | 18 |
19 | 32 | 33 | 34 |
35 |
36 | 37 | 38 |
39 |
40 | 41 |
42 | 51 | 52 |
53 | 54 |
55 | 56 | 57 | 58 |
59 | 60 |
61 | 62 |
63 |
64 | 65 | 66 | 67 |
68 |
69 |
70 | 71 |
72 |
73 | 74 | --------------------------------------------------------------------------------