kopia lustrzana https://github.com/wagtail/wagtail
Add the option to set images as decorative
If an image is decorative, the alt text will be set to be empty. If an image is not decorative, then alt text must be supplied for screen readers.pull/6740/head
rodzic
bf33842f45
commit
5682aea460
|
@ -138,7 +138,8 @@ li.focused > .help {
|
|||
opacity: 1;
|
||||
}
|
||||
|
||||
.required .field > label:after {
|
||||
.required .field > label:after,
|
||||
label.required:after {
|
||||
content: '*';
|
||||
color: $color-red;
|
||||
font-weight: bold;
|
||||
|
|
|
@ -12,7 +12,10 @@ const ImageBlock = props => {
|
|||
const { blockProps } = props;
|
||||
const { entity, onEditEntity, onRemoveEntity } = blockProps;
|
||||
const { src, alt } = entity.getData();
|
||||
const altLabel = `${STRINGS.ALT_TEXT}: “${alt || ''}”`;
|
||||
let altLabel = STRINGS.DECORATIVE_IMAGE;
|
||||
if (alt) {
|
||||
altLabel = `${STRINGS.ALT_TEXT}: “${alt}”`;
|
||||
}
|
||||
|
||||
return (
|
||||
<MediaBlock {...props} src={src} alt="">
|
||||
|
|
|
@ -54,7 +54,7 @@ exports[`ImageBlock no data 1`] = `
|
|||
<p
|
||||
className="ImageBlock__alt"
|
||||
>
|
||||
Alt text: “”
|
||||
Decorative image
|
||||
</p>
|
||||
<button
|
||||
className="button Tooltip__button"
|
||||
|
@ -89,7 +89,7 @@ exports[`ImageBlock renders 1`] = `
|
|||
<p
|
||||
className="ImageBlock__alt"
|
||||
>
|
||||
Alt text: “”
|
||||
Decorative image
|
||||
</p>
|
||||
<button
|
||||
className="button Tooltip__button"
|
||||
|
|
|
@ -30,6 +30,7 @@ global.wagtailConfig = {
|
|||
SEE_ALL: 'See all',
|
||||
CLOSE_EXPLORER: 'Close explorer',
|
||||
ALT_TEXT: 'Alt text',
|
||||
DECORATIVE_IMAGE: 'Decorative image',
|
||||
WRITE_HERE: 'Write here…',
|
||||
HORIZONTAL_LINE: 'Horizontal line',
|
||||
LINE_BREAK: 'Line break',
|
||||
|
|
Plik binarny nie jest wyświetlany.
Przed Szerokość: | Wysokość: | Rozmiar: 216 KiB Po Szerokość: | Wysokość: | Rozmiar: 179 KiB |
|
@ -53,7 +53,8 @@ In addition, Wagtail allows you to choose the format of your image.
|
|||
.. image:: ../../_static/images/screen18_image_format.png
|
||||
|
||||
#. You can select how the image is displayed by selecting one of the format options.
|
||||
#. You must provide specific `alt text <https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Images_in_HTML#Alternative_text>`_ for your image.
|
||||
#. You can choose if the image is `decorative <https://www.w3.org/WAI/tutorials/images/decorative/>`_, in which case you will not need to enter alt text for your image.
|
||||
#. If you do not choose for the image to be decorative, you must provide specific `alt text <https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Images_in_HTML#Alternative_text>`_ for your image.
|
||||
|
||||
The format options available are described below:
|
||||
|
||||
|
|
|
@ -62,6 +62,7 @@ def get_js_translation_strings():
|
|||
'SEE_ALL': _('See all'),
|
||||
'CLOSE_EXPLORER': _('Close explorer'),
|
||||
'ALT_TEXT': _('Alt text'),
|
||||
'DECORATIVE_IMAGE': _('Decorative image'),
|
||||
'WRITE_HERE': _('Write here…'),
|
||||
'HORIZONTAL_LINE': _('Horizontal line'),
|
||||
'LINE_BREAK': _('Line break'),
|
||||
|
|
|
@ -98,7 +98,22 @@ class ImageInsertionForm(forms.Form):
|
|||
choices=[(format.name, format.label) for format in get_image_formats()],
|
||||
widget=forms.RadioSelect
|
||||
)
|
||||
alt_text = forms.CharField()
|
||||
image_is_decorative = forms.BooleanField(required=False)
|
||||
alt_text = forms.CharField(required=False)
|
||||
|
||||
def clean_alt_text(self):
|
||||
alt_text = self.cleaned_data['alt_text']
|
||||
image_is_decorative = self.cleaned_data['image_is_decorative']
|
||||
|
||||
# Empty the alt text value if the image is set to be decorative
|
||||
if image_is_decorative:
|
||||
return ''
|
||||
else:
|
||||
# Alt text is required if image is not decorative.
|
||||
if not alt_text:
|
||||
msg = _("Please add some alt text for your image or mark it as decorative")
|
||||
self.add_error('alt_text', msg)
|
||||
return alt_text
|
||||
|
||||
|
||||
class URLGeneratorForm(forms.Form):
|
||||
|
|
|
@ -134,6 +134,35 @@ IMAGE_CHOOSER_MODAL_ONLOAD_HANDLERS = {
|
|||
modal.close();
|
||||
},
|
||||
'select_format': function(modal) {
|
||||
|
||||
var decorativeImage = document.querySelector('#id_image-chooser-insertion-image_is_decorative');
|
||||
var altText = document.querySelector('#id_image-chooser-insertion-alt_text');
|
||||
var altTextLabel = document.querySelector('[for="id_image-chooser-insertion-alt_text"]');
|
||||
|
||||
if (decorativeImage.checked) {
|
||||
disableAltText();
|
||||
} else {
|
||||
enableAltText();
|
||||
}
|
||||
|
||||
decorativeImage.addEventListener('change', function(event){
|
||||
if (event.target.checked) {
|
||||
disableAltText();
|
||||
} else {
|
||||
enableAltText();
|
||||
}
|
||||
});
|
||||
|
||||
function disableAltText() {
|
||||
altText.setAttribute('disabled', 'disabled');
|
||||
altTextLabel.classList.remove('required');
|
||||
}
|
||||
|
||||
function enableAltText() {
|
||||
altText.removeAttribute('disabled');
|
||||
altTextLabel.classList.add('required');
|
||||
}
|
||||
|
||||
$('form', modal.body).on('submit', function() {
|
||||
$.post(this.action, $(this).serialize(), modal.loadResponseText, 'text');
|
||||
|
||||
|
|
|
@ -1034,9 +1034,19 @@ class TestImageChooserSelectFormatView(TestCase, WagtailTestUtils):
|
|||
response = self.get(params={'alt_text': "some previous alt text"})
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(response, 'value=\\"some previous alt text\\"')
|
||||
self.assertNotContains(response, 'id=\\"id_image-chooser-insertion-image_is_decorative\\" checked')
|
||||
|
||||
def test_with_edit_params_no_alt_text_marks_as_decorative(self):
|
||||
response = self.get(params={'alt_text': ""})
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(response, 'id=\\"id_image-chooser-insertion-image_is_decorative\\" checked')
|
||||
|
||||
def test_post_response(self):
|
||||
response = self.post({'image-chooser-insertion-format': 'left', 'image-chooser-insertion-alt_text': 'Arthur "two sheds" Jackson'})
|
||||
response = self.post({
|
||||
'image-chooser-insertion-format': 'left',
|
||||
'image-chooser-insertion-image_is_decorative': False,
|
||||
'image-chooser-insertion-alt_text': 'Arthur "two sheds" Jackson',
|
||||
})
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(response['Content-Type'], 'application/json')
|
||||
|
@ -1051,6 +1061,27 @@ class TestImageChooserSelectFormatView(TestCase, WagtailTestUtils):
|
|||
self.assertEqual(result['alt'], 'Arthur "two sheds" Jackson')
|
||||
self.assertIn('alt="Arthur "two sheds" Jackson"', result['html'])
|
||||
|
||||
def test_post_response_image_is_decorative_discards_alt_text(self):
|
||||
response = self.post({
|
||||
'image-chooser-insertion-format': 'left',
|
||||
'image-chooser-insertion-alt_text': 'Arthur "two sheds" Jackson',
|
||||
'image-chooser-insertion-image_is_decorative': True,
|
||||
})
|
||||
response_json = json.loads(response.content.decode())
|
||||
result = response_json['result']
|
||||
|
||||
self.assertEqual(result['alt'], '')
|
||||
self.assertIn('alt=""', result['html'])
|
||||
|
||||
def test_post_response_image_is_not_decorative_missing_alt_text(self):
|
||||
response = self.post({
|
||||
'image-chooser-insertion-format': 'left',
|
||||
'image-chooser-insertion-alt_text': '',
|
||||
'image-chooser-insertion-image_is_decorative': False,
|
||||
})
|
||||
response_json = json.loads(response.content.decode())
|
||||
self.assertIn('Please add some alt text for your image or mark it as decorative', response_json['html'])
|
||||
|
||||
|
||||
class TestImageChooserUploadView(TestCase, WagtailTestUtils):
|
||||
def setUp(self):
|
||||
|
|
|
@ -241,6 +241,7 @@ def chooser_select_format(request, image_id):
|
|||
else:
|
||||
initial = {'alt_text': image.default_alt_text}
|
||||
initial.update(request.GET.dict())
|
||||
initial['image_is_decorative'] = initial['alt_text'] == ''
|
||||
form = ImageInsertionForm(initial=initial, prefix='image-chooser-insertion')
|
||||
|
||||
return render_modal_workflow(
|
||||
|
|
Ładowanie…
Reference in New Issue