Kasse-, adresse- og loginfelter skal have etiketter, autocomplete og tilknyttede fejlbeskeder
Det er i kassen, webshoppen tjener sine penge. Uden etiketter ved skærmlæserbrugere ikke, hvad de skal skrive; uden automatisk udfyldning må folk med motoriske vanskeligheder eller hukommelsesvanskeligheder selv taste hele adressen; og når fejlbeskeder ikke er knyttet til deres felter, kan kunderne ikke finde ud af, hvad der gik galt, og opgiver ordren.
- Regel-id
- vs-forms-ecommerce
- Kilde
- Validiscan-kontrol
- Alvorlighed
- Kritisk
- Rettelsesniveau
- AUTO
- på Shopify, Shopware, WooCommerce og Magento
- Status
- køres
Hvad kontrollen gør
Kontrollerer felter i kassen samt adresse-, konto- og loginfelter for manglende autocomplete-værdier (1.3.5), manglende etiketter eller instruktioner og påkrævede felter, der ikke er markeret (3.3.2), samt fejlbeskeder, der ikke er knyttet til deres felter (3.3.1). Erstatter axe-reglerne label og autocomplete-valid.
På hver side ser kontrollen på hvert input, select og textarea, som hjælpemidler kan opfatte, bortset fra skjulte input og input af knaptype. Som etiket tæller <label>, aria-label, aria-labelledby eller title, men ikke en pladsholder. Om etikettens tekst beskriver feltet, testes ikke.
Et felts formål gættes ud fra dets type, name, id, etikettekst og placeholder. Et felt med et genkendt formål er et fund, når det ikke har noget autocomplete-token, eller når tokenet er on, off eller ugyldigt, bortset fra off på et adgangskodefelt. Et gyldigt, men andet token end det forventede giver intet fund.
En fejlbesked (role="alert" eller en fejlklasse, ved siden af ét felt) rapporteres, når den ikke står inde i et label, og hverken aria-describedby eller aria-errormessage henviser til den. Det samme gælder et felt med aria-invalid="true" uden en tilknyttet besked. Et påkrævet felt (required eller aria-required="true", bortset fra afkrydsningsfelter og radioknapper) rapporteres, når etiketten hverken viser en stjerne eller en tekst om, at feltet er påkrævet. Det gælder ikke, når formularen markerer de valgfrie felter, oplyser, at alle felter er påkrævede, eller gør hvert felt påkrævet. Et felt, der kun visuelt er markeret som påkrævet, rapporteres også.
Sådan retter du det
Giv hvert felt en synlig <label>, der er koblet til feltet med for og id, tilføj den passende autocomplete-værdi (given-name, family-name, street-address, postal-code, email, tel, current-password og så videre), markér påkrævede felter i etiketten og med required-attributten, og knyt fejlbeskeder til deres felter med aria-describedby og aria-invalid="true".
WCAG-succeskriterier
- 1.3.5 Identify Input Purpose, niveau AA
- 3.3.1 Error Identification, niveau A
- 3.3.2 Labels or Instructions, niveau A
Afsnit i EN 301 549
| WCAG-kriterium | Version 3.2.1 | Version 4.1.1 |
|---|---|---|
| 1.3.5 | 9.1.3.5 | 9.1.3.5 |
| 3.3.1 | 9.3.3.1 | 9.3.3.1 |
| 3.3.2 | 9.3.3.2 | 9.3.3.2 |
Hvor en opskrift retter det
Shopify: opskrift autocomplete-tokens
Vis før og efter (1)
sections/contact-form.liquid Ændringer i sections/contact-form.liquid: 1 tilføjet, 1 fjernet
| Linje før | Linje efter | Ændring | Kode |
|---|---|---|---|
| 14 | 14 | {%- form 'contact', id: 'ContactForm', class: 'contact__form' %} | |
| 15 | 15 | <div class="contact__fields"> | |
| 16 | 16 | <div class="field"> | |
| 17 | Fjernet | <input class="field__input" type="text" name="contact[name]" placeholder="{{ 'templates.contact.form.name' | t }}"> | |
| 17 | Tilføjet | <input class="field__input" type="text" name="contact[name]" placeholder="{{ 'templates.contact.form.name' | t }}" autocomplete="name"> | |
| 18 | 18 | </div> | |
| 19 | 19 | <div class="field"> | |
| 20 | 20 | <input class="field__input" type="email" name="contact[email]" placeholder="{{ 'templates.contact.form.email' | t }} *" required> |
sections/footer.liquid Ændringer i sections/footer.liquid: 1 tilføjet, 1 fjernet
| Linje før | Linje efter | Ændring | Kode |
|---|---|---|---|
| 11 | 11 | {%- form 'customer', id: 'ContactFooter', class: 'footer__newsletter newsletter-form' -%} | |
| 12 | 12 | <input type="hidden" name="contact[tags]" value="newsletter"> | |
| 13 | 13 | <div class="newsletter-form__field-wrapper"> | |
| 14 | Fjernet | <input type="email" name="contact[email]" class="field__input" placeholder="{{ 'newsletter.label' | t }}" autocorrect="off" autocapitalize="off"> | |
| 14 | Tilføjet | <input type="email" name="contact[email]" class="field__input" placeholder="{{ 'newsletter.label' | t }}" autocorrect="off" autocapitalize="off" autocomplete="email"> | |
| 15 | 15 | <button type="submit" class="button newsletter-form__button" name="commit">{{ 'newsletter.button' | t }}</button> | |
| 16 | 16 | </div> | |
| 17 | 17 | {%- endform -%} |
sections/main-login.liquid Ændringer i sections/main-login.liquid: 1 tilføjet, 1 fjernet
| Linje før | Linje efter | Ændring | Kode |
|---|---|---|---|
| 10 | 10 | {%- form 'customer_login', novalidate: 'novalidate' %} | |
| 11 | 11 | <div class="field"> | |
| 12 | 12 | <label class="field__label" for="CustomerEmail">{{ 'customer.login_page.email' | t }}</label> | |
| 13 | Fjernet | <input class="field__input" type="email" name="customer[email]" id="CustomerEmail" autocorrect="off" autocapitalize="off"> | |
| 13 | Tilføjet | <input class="field__input" type="email" name="customer[email]" id="CustomerEmail" autocorrect="off" autocapitalize="off" autocomplete="email"> | |
| 14 | 14 | </div> | |
| 15 | 15 | <div class="field"> | |
| 16 | 16 | <label class="field__label" for="CustomerPassword">{{ 'customer.login_page.password' | t }}</label> |
snippets/checkout-field.liquid Ændringer i snippets/checkout-field.liquid: 4 tilføjet, 4 fjernet
| Linje før | Linje efter | Ændring | Kode |
|---|---|---|---|
| 15 | 15 | <div class="field"> | |
| 16 | 16 | {%- case legacy %} | |
| 17 | 17 | {%- when 'placeholder' %} | |
| 18 | Fjernet | <input class="field__input" type="{{ field_type }}" id="{{ field_id }}" name="{{ field_name }}" placeholder="{{ label }}"{% if required %} required{% endif %}> | |
| 18 | Tilføjet | <input class="field__input" type="{{ field_type }}" id="{{ field_id }}" name="{{ field_name }}" placeholder="{{ label }}"{% if required %} required{% endif %} autocomplete="{{ autocomplete }}"> | |
| 19 | 19 | {%- when 'starred' %} | |
| 20 | 20 | <label class="field__label" for="{{ field_id }}">{{ label }} *</label> | |
| 21 | Fjernet | <input class="field__input" type="{{ field_type }}" id="{{ field_id }}" name="{{ field_name }}"> | |
| 21 | Tilføjet | <input class="field__input" type="{{ field_type }}" id="{{ field_id }}" name="{{ field_name }}" autocomplete="{{ autocomplete }}"> | |
| 22 | 22 | {%- when 'off' %} | |
| 23 | 23 | <label class="field__label" for="{{ field_id }}">{{ label }}</label> | |
| 24 | Fjernet | <input class="field__input" type="{{ field_type }}" id="{{ field_id }}" name="{{ field_name }}" autocomplete="off"{% if required %} required{% endif %}> | |
| 24 | Tilføjet | <input class="field__input" type="{{ field_type }}" id="{{ field_id }}" name="{{ field_name }}" autocomplete="{{ autocomplete }}"{% if required %} required{% endif %}> | |
| 25 | 25 | {%- else %} | |
| 26 | 26 | <label class="field__label" for="{{ field_id }}">{{ label }}</label> | |
| 27 | Fjernet | <input class="field__input" type="{{ field_type }}" id="{{ field_id }}" name="{{ field_name }}"{% if required %} required{% endif %}> | |
| 27 | Tilføjet | <input class="field__input" type="{{ field_type }}" id="{{ field_id }}" name="{{ field_name }}"{% if required %} required{% endif %} autocomplete="{{ autocomplete }}"> | |
| 28 | 28 | {%- endcase %} | |
| 29 | 29 | </div> |
Shopify: opskrift label-association
Vis før og efter (1)
sections/main-collection.liquid Ændringer i sections/main-collection.liquid: 2 tilføjet, 2 fjernet
| Linje før | Linje efter | Ændring | Kode |
|---|---|---|---|
| 64 | 64 | <div class="collection__products"> | |
| 65 | 65 | <div class="collection__toolbar"> | |
| 66 | 66 | <div class="collection__sort"> | |
| 67 | Fjernet | <label class="collection__sort-label">Sort by</label> | |
| 68 | Fjernet | <select name="sort_by" class="select__select" form="FacetFiltersForm"> | |
| 67 | Tilføjet | <label class="collection__sort-label" for="SortBy-{{ section.id }}">Sort by</label> | |
| 68 | Tilføjet | <select name="sort_by" class="select__select" form="FacetFiltersForm" id="SortBy-{{ section.id }}"> | |
| 69 | 69 | <option value="manual" selected>Featured</option> | |
| 70 | 70 | <option value="best-selling">Best selling</option> | |
| 71 | 71 | <option value="price-ascending">Price, low to high</option> |
sections/main-product.liquid Ændringer i sections/main-product.liquid: 2 tilføjet, 2 fjernet
| Linje før | Linje efter | Ændring | Kode |
|---|---|---|---|
| 94 | 94 | </div> | |
| 95 | 95 | {%- else %} | |
| 96 | 96 | <div class="product-form__input product-form__input--dropdown"> | |
| 97 | Fjernet | <p class="form__label">{{ option.name | escape }}</p> | |
| 97 | Tilføjet | <p class="form__label" id="Options-{{ section.id }}-{{ forloop.index0 }}-label">{{ option.name | escape }}</p> | |
| 98 | 98 | <div class="select"> | |
| 99 | Fjernet | <select class="select__select" name="options[{{ option.name | escape }}]" data-option-index="{{ option_index }}"> | |
| 99 | Tilføjet | <select class="select__select" name="options[{{ option.name | escape }}]" data-option-index="{{ option_index }}" aria-labelledby="Options-{{ section.id }}-{{ forloop.index0 }}-label"> | |
| 100 | 100 | {%- for value in option.values %} | |
| 101 | 101 | <option value="{{ value | escape }}"{% if value == option.selected_value %} selected{% endif %}>{{ value | escape }}</option> | |
| 102 | 102 | {%- endfor %} |
Shopware: opskrift autocomplete-tokens
Vis før og efter (1)
Resources/views/storefront/component/account/login.html.twig Ændringer i Resources/views/storefront/component/account/login.html.twig: 1 tilføjet, 1 fjernet
| Linje før | Linje efter | Ændring | Kode |
|---|---|---|---|
| 19 | 19 | name="username" | |
| 20 | 20 | placeholder="{{ 'account.loginMailPlaceholder'|trans }}" | |
| 21 | 21 | required | |
| 22 | Fjernet | autocomplete="off"> | |
| 22 | Tilføjet | autocomplete="email"> | |
| 23 | 23 | </div> | |
| 24 | 24 | ||
| 25 | 25 | <div class="form-group"> |
Resources/views/storefront/component/account/register.html.twig Ændringer i Resources/views/storefront/component/account/register.html.twig: 8 tilføjet, 4 fjernet
| Linje før | Linje efter | Ændring | Kode |
|---|---|---|---|
| 33 | 33 | id="{{ formId }}FirstName" | |
| 34 | 34 | name="firstName" | |
| 35 | 35 | placeholder="{{ 'account.firstNamePlaceholder'|trans }}" | |
| 36 | Fjernet | required> | |
| 36 | Tilføjet | required | |
| 37 | Tilføjet | autocomplete="given-name"> | |
| 37 | 38 | </div> | |
| 38 | 39 | <div class="form-group col-sm-6"> | |
| 39 | 40 | <input type="text" | |
| 41 | 42 | id="{{ formId }}LastName" | |
| 42 | 43 | name="lastName" | |
| 43 | 44 | placeholder="{{ 'account.lastNamePlaceholder'|trans }}" | |
| 44 | Fjernet | required> | |
| 45 | Tilføjet | required | |
| 46 | Tilføjet | autocomplete="family-name"> | |
| 45 | 47 | </div> | |
| 46 | 48 | </div> | |
| 47 | 49 | <div class="row g-2"> | |
| 52 | 54 | id="{{ formId }}Mail" | |
| 53 | 55 | name="email" | |
| 54 | 56 | placeholder="{{ 'account.emailPlaceholder'|trans }}" | |
| 55 | Fjernet | required> | |
| 57 | Tilføjet | required | |
| 58 | Tilføjet | autocomplete="email"> | |
| 56 | 59 | </div> | |
| 57 | 60 | <div class="form-group col-sm-6"> | |
| 58 | 61 | <label class="form-label" for="{{ formId }}Password">{{ 'account.passwordLabel'|trans }}</label> | |
| 62 | 65 | name="password" | |
| 63 | 66 | minlength="8" | |
| 64 | 67 | aria-describedby="{{ formId }}PasswordHint" | |
| 65 | Fjernet | required> | |
| 68 | Tilføjet | required | |
| 69 | Tilføjet | autocomplete="new-password"> | |
| 66 | 70 | <small class="form-text" id="{{ formId }}PasswordHint">{{ 'account.passwordHint'|trans }}</small> | |
| 67 | 71 | </div> | |
| 68 | 72 | </div> |
Resources/views/storefront/component/address/address-form.html.twig Ændringer i Resources/views/storefront/component/address/address-form.html.twig: 8 tilføjet, 4 fjernet
| Linje før | Linje efter | Ændring | Kode |
|---|---|---|---|
| 14 | 14 | id="{{ prefix }}AddressStreet" | |
| 15 | 15 | name="{{ prefix }}[street]" | |
| 16 | 16 | placeholder="{{ 'address.streetPlaceholder'|trans }}" | |
| 17 | Fjernet | required> | |
| 17 | Tilføjet | required | |
| 18 | Tilføjet | autocomplete="address-line1"> | |
| 18 | 19 | </div> | |
| 19 | 20 | {% endblock %} | |
| 20 | 21 | ||
| 26 | 27 | name="{{ prefix }}[zipcode]" | |
| 27 | 28 | placeholder="{{ 'address.zipcodePlaceholder'|trans }}" | |
| 28 | 29 | inputmode="numeric" | |
| 29 | Fjernet | required> | |
| 30 | Tilføjet | required | |
| 31 | Tilføjet | autocomplete="postal-code"> | |
| 30 | 32 | </div> | |
| 31 | 33 | {% endblock %} | |
| 32 | 34 | ||
| 37 | 39 | class="form-control" | |
| 38 | 40 | id="{{ prefix }}AddressCity" | |
| 39 | 41 | name="{{ prefix }}[city]" | |
| 40 | Fjernet | required> | |
| 42 | Tilføjet | required | |
| 43 | Tilføjet | autocomplete="address-level2"> | |
| 41 | 44 | </div> | |
| 42 | 45 | {% endblock %} | |
| 43 | 46 | ||
| 47 | 50 | <select class="form-select" | |
| 48 | 51 | id="{{ prefix }}AddressCountry" | |
| 49 | 52 | name="{{ prefix }}[countryId]" | |
| 50 | Fjernet | required> | |
| 53 | Tilføjet | required | |
| 54 | Tilføjet | autocomplete="country"> | |
| 51 | 55 | {% for country in countries %} | |
| 52 | 56 | <option value="{{ country.id }}"{% if loop.first %} selected{% endif %}>{{ country.name }}</option> | |
| 53 | 57 | {% endfor %} |
Resources/views/storefront/element/cms-element-form.html.twig Ændringer i Resources/views/storefront/element/cms-element-form.html.twig: 4 tilføjet, 4 fjernet
| Linje før | Linje efter | Ændring | Kode |
|---|---|---|---|
| 18 | 18 | </select> | |
| 19 | 19 | </div> | |
| 20 | 20 | <div class="form-group col-md-4"> | |
| 21 | Fjernet | <input type="text" class="form-control" id="contactFormFirstName" name="firstName" placeholder="{{ 'account.firstNamePlaceholder'|trans }}" required> | |
| 21 | Tilføjet | <input type="text" class="form-control" id="contactFormFirstName" name="firstName" placeholder="{{ 'account.firstNamePlaceholder'|trans }}" required autocomplete="given-name"> | |
| 22 | 22 | </div> | |
| 23 | 23 | <div class="form-group col-md-4"> | |
| 24 | Fjernet | <input type="text" class="form-control" id="contactFormLastName" name="lastName" placeholder="{{ 'account.lastNamePlaceholder'|trans }}" required> | |
| 24 | Tilføjet | <input type="text" class="form-control" id="contactFormLastName" name="lastName" placeholder="{{ 'account.lastNamePlaceholder'|trans }}" required autocomplete="family-name"> | |
| 25 | 25 | </div> | |
| 26 | 26 | </div> | |
| 27 | 27 | ||
| 28 | 28 | <div class="row g-2"> | |
| 29 | 29 | <div class="form-group col-md-6"> | |
| 30 | 30 | <label class="form-label" for="contactFormMail">{{ 'account.emailLabel'|trans }}</label> | |
| 31 | Fjernet | <input type="email" class="form-control" id="contactFormMail" name="email" placeholder="{{ 'account.emailPlaceholder'|trans }}" required> | |
| 31 | Tilføjet | <input type="email" class="form-control" id="contactFormMail" name="email" placeholder="{{ 'account.emailPlaceholder'|trans }}" required autocomplete="email"> | |
| 32 | 32 | </div> | |
| 33 | 33 | <div class="form-group col-md-6"> | |
| 34 | 34 | <label class="form-label" for="contactFormPhone">{{ 'contact.phoneLabel'|trans }}</label> | |
| 35 | Fjernet | <input type="tel" class="form-control" id="contactFormPhone" name="phone"> | |
| 35 | Tilføjet | <input type="tel" class="form-control" id="contactFormPhone" name="phone" autocomplete="tel"> | |
| 36 | 36 | </div> | |
| 37 | 37 | </div> | |
| 38 | 38 |
Resources/views/storefront/layout/footer/footer.html.twig Ændringer i Resources/views/storefront/layout/footer/footer.html.twig: 2 tilføjet, 1 fjernet
| Linje før | Linje efter | Ændring | Kode |
|---|---|---|---|
| 62 | 62 | id="footerNewsletterMail" | |
| 63 | 63 | class="form-control" | |
| 64 | 64 | placeholder="{{ 'footer.newsletterPlaceholder'|trans }}" | |
| 65 | Fjernet | required> | |
| 65 | Tilføjet | required | |
| 66 | Tilføjet | autocomplete="email"> | |
| 66 | 67 | <button type="submit" class="btn btn-primary newsletter-submit">{{ 'footer.newsletterSubmit'|trans }}</button> | |
| 67 | 68 | </div> | |
| 68 | 69 | <div class="form-check newsletter-privacy"> |
Shopware: opskrift label-association
Vis før og efter (1)
Resources/views/storefront/page/product-detail/configurator.html.twig Ændringer i Resources/views/storefront/page/product-detail/configurator.html.twig: 1 tilføjet, 1 fjernet
| Linje før | Linje efter | Ændring | Kode |
|---|---|---|---|
| 13 | 13 | {% for group in product.configurator %} | |
| 14 | 14 | {% if group.display == 'select' %} | |
| 15 | 15 | <div class="product-detail-configurator-group"> | |
| 16 | Fjernet | <div class="product-detail-configurator-group-title">{{ group.name }}</div> | |
| 16 | Tilføjet | <label class="product-detail-configurator-group-title" for="configurator-{{ group.id }}">{{ group.name }}</label> | |
| 17 | 17 | <select class="form-select product-detail-configurator-select-input" | |
| 18 | 18 | id="configurator-{{ group.id }}" | |
| 19 | 19 | name="{{ group.id }}"{% if group.price|default(false) %} |
WooCommerce: opskrift autocomplete-tokens
Vis før og efter (1)
functions.php Ændringer i functions.php: 44 tilføjet, 0 fjernet
| Linje før | Linje efter | Ændring | Kode |
|---|---|---|---|
| 308 | 308 | * here; the remediation adds one for pages with the _kb_content_language meta and marks the | |
| 309 | 309 | * English header and footer with lang="en-GB". | |
| 310 | 310 | */ | |
| 311 | Tilføjet | ||
| 312 | Tilføjet | /* validiscan:autocomplete-tokens */ | |
| 313 | Tilføjet | /** | |
| 314 | Tilføjet | * Autocomplete tokens for the WooCommerce address fields, so browsers and assistive | |
| 315 | Tilføjet | * technology know what each field asks for (WCAG 1.3.5). Runs after the theme's own | |
| 316 | Tilføjet | * field filters. | |
| 317 | Tilføjet | * | |
| 318 | Tilføjet | * @param array $fields Checkout fields (grouped by section) or one address section. | |
| 319 | Tilføjet | * @return array | |
| 320 | Tilføjet | */ | |
| 321 | Tilføjet | function kb_address_autocomplete( $fields ) { | |
| 322 | Tilføjet | $tokens = array( | |
| 323 | Tilføjet | 'first_name' => 'given-name', | |
| 324 | Tilføjet | 'last_name' => 'family-name', | |
| 325 | Tilføjet | 'company' => 'organization', | |
| 326 | Tilføjet | 'country' => 'country', | |
| 327 | Tilføjet | 'address_1' => 'address-line1', | |
| 328 | Tilføjet | 'address_2' => 'address-line2', | |
| 329 | Tilføjet | 'city' => 'address-level2', | |
| 330 | Tilføjet | 'state' => 'address-level1', | |
| 331 | Tilføjet | 'postcode' => 'postal-code', | |
| 332 | Tilføjet | 'phone' => 'tel', | |
| 333 | Tilføjet | 'email' => 'email', | |
| 334 | Tilføjet | ); | |
| 335 | Tilføjet | foreach ( $fields as $key => $field ) { | |
| 336 | Tilføjet | if ( ! is_array( $field ) ) { | |
| 337 | Tilføjet | continue; | |
| 338 | Tilføjet | } | |
| 339 | Tilføjet | if ( 'billing' === $key || 'shipping' === $key ) { | |
| 340 | Tilføjet | $fields[ $key ] = kb_address_autocomplete( $field ); | |
| 341 | Tilføjet | continue; | |
| 342 | Tilføjet | } | |
| 343 | Tilføjet | if ( ! preg_match( '/^(billing|shipping)_(.+)$/', (string) $key, $match ) || ! isset( $tokens[ $match[2] ] ) ) { | |
| 344 | Tilføjet | continue; | |
| 345 | Tilføjet | } | |
| 346 | Tilføjet | $fields[ $key ]['autocomplete'] = ( 'shipping' === $match[1] ? 'shipping ' : '' ) . $tokens[ $match[2] ]; | |
| 347 | Tilføjet | unset( $fields[ $key ]['custom_attributes']['autocomplete'] ); | |
| 348 | Tilføjet | } | |
| 349 | Tilføjet | return $fields; | |
| 350 | Tilføjet | } | |
| 351 | Tilføjet | add_filter( 'woocommerce_checkout_fields', 'kb_address_autocomplete', 99 ); | |
| 352 | Tilføjet | add_filter( 'woocommerce_billing_fields', 'kb_address_autocomplete', 99 ); | |
| 353 | Tilføjet | add_filter( 'woocommerce_shipping_fields', 'kb_address_autocomplete', 99 ); | |
| 354 | Tilføjet | /* /validiscan:autocomplete-tokens */ |
woocommerce/myaccount/form-login.php Ændringer i woocommerce/myaccount/form-login.php: 3 tilføjet, 3 fjernet
| Linje før | Linje efter | Ændring | Kode |
|---|---|---|---|
| 29 | 29 | ||
| 30 | 30 | <p class="woocommerce-form-row woocommerce-form-row--wide form-row form-row-wide"> | |
| 31 | 31 | <label for="username"><?php esc_html_e( 'Username or email address', 'woocommerce' ); ?> <span class="required">*</span></label> | |
| 32 | Fjernet | <input type="text" class="woocommerce-Input woocommerce-Input--text input-text" name="username" id="username" autocomplete="off" value="<?php echo ( ! empty( $_POST['username'] ) ) ? esc_attr( wp_unslash( $_POST['username'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized ?>"> | |
| 32 | Tilføjet | <input type="text" class="woocommerce-Input woocommerce-Input--text input-text" name="username" id="username" autocomplete="username" value="<?php echo ( ! empty( $_POST['username'] ) ) ? esc_attr( wp_unslash( $_POST['username'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized ?>"> | |
| 33 | 33 | </p> | |
| 34 | 34 | <p class="woocommerce-form-row woocommerce-form-row--wide form-row form-row-wide"> | |
| 35 | 35 | <label for="password"><?php esc_html_e( 'Password', 'woocommerce' ); ?> <span class="required">*</span></label> | |
| 36 | 36 | <span class="password-input"> | |
| 37 | Fjernet | <input class="woocommerce-Input woocommerce-Input--text input-text" type="password" name="password" id="password" autocomplete="off" onpaste="return false;"> | |
| 37 | Tilføjet | <input class="woocommerce-Input woocommerce-Input--text input-text" type="password" name="password" id="password" autocomplete="current-password" onpaste="return false;"> | |
| 38 | 38 | <button type="button" class="show-password-input"><?php kb_icon( 'eye' ); ?></button> | |
| 39 | 39 | </span> | |
| 40 | 40 | </p> | |
| 63 | 63 | <?php do_action( 'woocommerce_register_form_start' ); ?> | |
| 64 | 64 | ||
| 65 | 65 | <p class="woocommerce-form-row woocommerce-form-row--wide form-row form-row-wide"> | |
| 66 | Fjernet | <input type="email" class="woocommerce-Input woocommerce-Input--text input-text" name="email" id="reg_email" autocomplete="off" value="" placeholder="<?php esc_attr_e( 'Email address *', 'kestrel-birch' ); ?>"> | |
| 66 | Tilføjet | <input type="email" class="woocommerce-Input woocommerce-Input--text input-text" name="email" id="reg_email" autocomplete="email" value="" placeholder="<?php esc_attr_e( 'Email address *', 'kestrel-birch' ); ?>"> | |
| 67 | 67 | </p> | |
| 68 | 68 | <p><?php esc_html_e( 'A link to set a new password will be sent to your email address.', 'woocommerce' ); ?></p> | |
| 69 | 69 |
WooCommerce: opskrift label-association
Vis før og efter (1)
woocommerce/cart/cart.php Ændringer i woocommerce/cart/cart.php: 1 tilføjet, 1 fjernet
| Linje før | Linje efter | Ændring | Kode |
|---|---|---|---|
| 62 | 62 | <tr> | |
| 63 | 63 | <td colspan="6" class="actions"> | |
| 64 | 64 | <div class="coupon"> | |
| 65 | Fjernet | <label class="screen-reader-text"><?php esc_html_e( 'Coupon:', 'woocommerce' ); ?></label> | |
| 65 | Tilføjet | <label class="screen-reader-text" for="coupon_code"><?php esc_html_e( 'Coupon:', 'woocommerce' ); ?></label> | |
| 66 | 66 | <input type="text" name="coupon_code" class="input-text" id="coupon_code" value="" placeholder="<?php esc_attr_e( 'Coupon code', 'woocommerce' ); ?>"> | |
| 67 | 67 | <button type="submit" class="button" name="apply_coupon" value="<?php esc_attr_e( 'Apply coupon', 'woocommerce' ); ?>"><?php esc_html_e( 'Apply coupon', 'woocommerce' ); ?></button> | |
| 68 | 68 | </div> |
Magento: opskrift autocomplete-tokens
Vis før og efter (1)
app/design/frontend/Validiscan/fixture/Magento_Contact/templates/form.phtml Ændringer i app/design/frontend/Validiscan/fixture/Magento_Contact/templates/form.phtml: 3 tilføjet, 3 fjernet
| Linje før | Linje efter | Ændring | Kode |
|---|---|---|---|
| 21 | 21 | <!-- VALIDISCAN-SEEDED vs-forms-ecommerce: name, email and phone lack autocomplete; required only via the CSS asterisk --> | |
| 22 | 22 | <div class="field name required"> | |
| 23 | 23 | <label class="label" for="name"><span><?= $escaper->escapeHtml(__('Name')) ?></span></label> | |
| 24 | Fjernet | <div class="control"><input name="name" id="name" title="<?= $escaper->escapeHtmlAttr(__('Name')) ?>" value="<?= $escaper->escapeHtmlAttr($viewModel->getUserName()) ?>" class="input-text" type="text"></div> | |
| 24 | Tilføjet | <div class="control"><input name="name" id="name" title="<?= $escaper->escapeHtmlAttr(__('Name')) ?>" value="<?= $escaper->escapeHtmlAttr($viewModel->getUserName()) ?>" class="input-text" type="text" autocomplete="name"></div> | |
| 25 | 25 | </div> | |
| 26 | 26 | <div class="field email required"> | |
| 27 | 27 | <label class="label" for="email"><span><?= $escaper->escapeHtml(__('Email')) ?></span></label> | |
| 28 | Fjernet | <div class="control"><input name="email" id="email" title="<?= $escaper->escapeHtmlAttr(__('Email')) ?>" value="<?= $escaper->escapeHtmlAttr($viewModel->getUserEmail()) ?>" class="input-text" type="email"></div> | |
| 28 | Tilføjet | <div class="control"><input name="email" id="email" title="<?= $escaper->escapeHtmlAttr(__('Email')) ?>" value="<?= $escaper->escapeHtmlAttr($viewModel->getUserEmail()) ?>" class="input-text" type="email" autocomplete="email"></div> | |
| 29 | 29 | </div> | |
| 30 | 30 | <div class="field telephone"> | |
| 31 | 31 | <label class="label" for="telephone"><span><?= $escaper->escapeHtml(__('Phone Number')) ?></span></label> | |
| 32 | Fjernet | <div class="control"><input name="telephone" id="telephone" title="<?= $escaper->escapeHtmlAttr(__('Phone Number')) ?>" value="<?= $escaper->escapeHtmlAttr($viewModel->getUserTelephone()) ?>" class="input-text" type="tel"></div> | |
| 32 | Tilføjet | <div class="control"><input name="telephone" id="telephone" title="<?= $escaper->escapeHtmlAttr(__('Phone Number')) ?>" value="<?= $escaper->escapeHtmlAttr($viewModel->getUserTelephone()) ?>" class="input-text" type="tel" autocomplete="tel"></div> | |
| 33 | 33 | </div> | |
| 34 | 34 | <div class="field comment required"> | |
| 35 | 35 | <label class="label" for="comment"><span><?= $escaper->escapeHtml(__('What’s on your mind?')) ?></span></label> |
app/design/frontend/Validiscan/fixture/Magento_Customer/templates/form/login.phtml Ændringer i app/design/frontend/Validiscan/fixture/Magento_Customer/templates/form/login.phtml: 2 tilføjet, 2 fjernet
| Linje før | Linje efter | Ændring | Kode |
|---|---|---|---|
| 27 | 27 | <div class="field email required"> | |
| 28 | 28 | <label class="label" for="email"><span><?= $escaper->escapeHtml(__('Email')) ?></span></label> | |
| 29 | 29 | <div class="control"> | |
| 30 | Fjernet | <input name="login[username]" value="<?= $escaper->escapeHtmlAttr($username) ?>" autocomplete="off" id="email" type="email" class="input-text mage-error" title="<?= $escaper->escapeHtmlAttr(__('Email')) ?>" aria-invalid="true" tabindex="1" onpaste="return false;" data-mage-init='{"mage/trim-input":{}}'> | |
| 30 | Tilføjet | <input name="login[username]" value="<?= $escaper->escapeHtmlAttr($username) ?>" autocomplete="email" id="email" type="email" class="input-text mage-error" title="<?= $escaper->escapeHtmlAttr(__('Email')) ?>" aria-invalid="true" tabindex="1" onpaste="return false;" data-mage-init='{"mage/trim-input":{}}'> | |
| 31 | 31 | <div for="email" generated="true" class="mage-error" id="email-error"><?= $escaper->escapeHtml(__('Please enter a valid email address (Ex: johndoe@domain.com).')) ?></div> | |
| 32 | 32 | </div> | |
| 33 | 33 | </div> | |
| 35 | 35 | <div class="field password required"> | |
| 36 | 36 | <label for="pass" class="label"><span><?= $escaper->escapeHtml(__('Password')) ?></span></label> | |
| 37 | 37 | <div class="control"> | |
| 38 | Fjernet | <input name="login[password]" type="password" autocomplete="off" class="input-text" id="pass" title="<?= $escaper->escapeHtmlAttr(__('Password')) ?>" tabindex="2" onpaste="return false;" oncopy="return false;"> | |
| 38 | Tilføjet | <input name="login[password]" type="password" autocomplete="current-password" class="input-text" id="pass" title="<?= $escaper->escapeHtmlAttr(__('Password')) ?>" tabindex="2" onpaste="return false;" oncopy="return false;"> | |
| 39 | 39 | </div> | |
| 40 | 40 | </div> | |
| 41 | 41 | <!-- VALIDISCAN-SEEDED vs-accessible-auth: arithmetic CAPTCHA with no alternative --> |
app/design/frontend/Validiscan/fixture/Magento_Newsletter/templates/subscribe.phtml Ændringer i app/design/frontend/Validiscan/fixture/Magento_Newsletter/templates/subscribe.phtml: 1 tilføjet, 1 fjernet
| Linje før | Linje efter | Ændring | Kode |
|---|---|---|---|
| 18 | 18 | <!-- VALIDISCAN-SEEDED vs-forms-ecommerce (label): newsletter email only has a placeholder, no label and no autocomplete --> | |
| 19 | 19 | <div class="field newsletter"> | |
| 20 | 20 | <div class="control"> | |
| 21 | Fjernet | <input name="email" type="email" id="newsletter" placeholder="<?= $escaper->escapeHtmlAttr(__('Enter your email address')) ?>" data-mage-init='{"mage/trim-input":{}}' data-validate="{required:true, 'validate-email':true}"> | |
| 21 | Tilføjet | <input name="email" type="email" id="newsletter" placeholder="<?= $escaper->escapeHtmlAttr(__('Enter your email address')) ?>" data-mage-init='{"mage/trim-input":{}}' data-validate="{required:true, 'validate-email':true}" autocomplete="email"> | |
| 22 | 22 | </div> | |
| 23 | 23 | </div> | |
| 24 | 24 | <div class="actions"> |
Magento: opskrift label-association
Vis før og efter (1)
app/design/frontend/Validiscan/fixture/Magento_Catalog/templates/product/list/toolbar.phtml Ændringer i app/design/frontend/Validiscan/fixture/Magento_Catalog/templates/product/list/toolbar.phtml: 1 tilføjet, 1 fjernet
| Linje før | Linje efter | Ændring | Kode |
|---|---|---|---|
| 12 | 12 | <div class="toolbar-sorter sorter"> | |
| 13 | 13 | <!-- VALIDISCAN-SEEDED select-name + vs-forms-ecommerce: the "Sort By" text is a span, not a label for the select --> | |
| 14 | 14 | <?php /* Fixed variant: <label class="sorter-label" for="sorter">Sort By</label>. */ ?> | |
| 15 | Fjernet | <span class="sorter-label"><?= $escaper->escapeHtml(__('Sort By')) ?></span> | |
| 15 | Tilføjet | <label class="sorter-label" for="sorter"><?= $escaper->escapeHtml(__('Sort By')) ?></label> | |
| 16 | 16 | <select id="sorter" data-role="sorter" class="sorter-options"> | |
| 17 | 17 | <?php foreach ($block->getAvailableOrders() as $key => $order): ?> | |
| 18 | 18 | <option value="<?= $escaper->escapeHtmlAttr($key) ?>"<?= $block->isOrderCurrent($key) ? ' selected' : '' ?>><?= $escaper->escapeHtml(__($order)) ?></option> |
Begynd med et gratis tjek af din webshop.
Send din webshops adresse. Validiscan scanner den og svarer med hver fejl, scanningen kan påvise, med siden og koden.
Bestil et gratis tjekEller skriv til info@validiscan.com.
Hvad det gratis tjek omfatter, og hvad det udelader- Du sender
- din webshops adresse
- Sider, der scannes
- op til 15
- Du får
- hver fejl, scanningen kan påvise, med siden og koden
- På din webshop
- kun offentlige sider; intet login, intet købt, ingen formularer sendt
- Hvad det ikke er
- et fuldt audit