kopia lustrzana https://github.com/wagtail/wagtail
Add caption field to TableBlock
* Create caption field added to table block widget Caption allows for users users with screen readers to be able to understand the contents of a table. * Fixed bugs in javascript and typos * Updated documentation and change log * Fixed table caption bug and requested pr edits * Fixed table caption bug and request pr edits * Removed changes in changelog.txt * Fixed bug and requested PR editspull/5508/head
rodzic
0ee07dddff
commit
f7ff6d39c4
Plik binarny nie jest wyświetlany.
Przed Szerokość: | Wysokość: | Rozmiar: 56 KiB Po Szerokość: | Wysokość: | Rozmiar: 88 KiB |
|
@ -2,7 +2,7 @@
|
||||||
TableBlock
|
TableBlock
|
||||||
==========
|
==========
|
||||||
|
|
||||||
The TableBlock module provides an HTML table block type for StreamField. This module uses `handsontable 6.2.2 <https://handsontable.com/>`_ to provide users with the ability to create and edit HTML tables in Wagtail.
|
The TableBlock module provides an HTML table block type for StreamField. This module uses `handsontable 6.2.2 <https://handsontable.com/>`_ to provide users with the ability to create and edit HTML tables in Wagtail. Table blocks provides a caption field for accessibility.
|
||||||
|
|
||||||
.. image:: ../../_static/images/screen40_table_block.png
|
.. image:: ../../_static/images/screen40_table_block.png
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,12 @@ class TableInput(forms.HiddenInput):
|
||||||
|
|
||||||
def get_context(self, name, value, attrs=None):
|
def get_context(self, name, value, attrs=None):
|
||||||
context = super().get_context(name, value, attrs)
|
context = super().get_context(name, value, attrs)
|
||||||
|
table_caption = ''
|
||||||
|
if value and value != 'null':
|
||||||
|
table_caption = json.loads(value).get('table_caption', '')
|
||||||
context['widget']['table_options_json'] = json.dumps(self.table_options)
|
context['widget']['table_options_json'] = json.dumps(self.table_options)
|
||||||
|
context['widget']['table_caption'] = table_caption
|
||||||
|
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
|
@ -59,6 +64,7 @@ class TableBlock(FieldBlock):
|
||||||
"""
|
"""
|
||||||
self.table_options = self.get_table_options(table_options=table_options)
|
self.table_options = self.get_table_options(table_options=table_options)
|
||||||
self.field_options = {'required': required, 'help_text': help_text}
|
self.field_options = {'required': required, 'help_text': help_text}
|
||||||
|
|
||||||
super().__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
|
@ -97,6 +103,7 @@ class TableBlock(FieldBlock):
|
||||||
'table_header': table_header,
|
'table_header': table_header,
|
||||||
'first_col_is_header': first_col_is_header,
|
'first_col_is_header': first_col_is_header,
|
||||||
'html_renderer': self.is_html_renderer(),
|
'html_renderer': self.is_html_renderer(),
|
||||||
|
'table_caption': value.get('table_caption'),
|
||||||
'data': value['data'][1:] if table_header else value.get('data', [])
|
'data': value['data'][1:] if table_header else value.get('data', [])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -4,9 +4,11 @@ function initTable(id, tableOptions) {
|
||||||
var containerId = id + '-handsontable-container';
|
var containerId = id + '-handsontable-container';
|
||||||
var tableHeaderCheckboxId = id + '-handsontable-header';
|
var tableHeaderCheckboxId = id + '-handsontable-header';
|
||||||
var colHeaderCheckboxId = id + '-handsontable-col-header';
|
var colHeaderCheckboxId = id + '-handsontable-col-header';
|
||||||
|
var tableCaptionId = id + '-handsontable-col-caption';
|
||||||
var hiddenStreamInput = $('#' + id);
|
var hiddenStreamInput = $('#' + id);
|
||||||
var tableHeaderCheckbox = $('#' + tableHeaderCheckboxId);
|
var tableHeaderCheckbox = $('#' + tableHeaderCheckboxId);
|
||||||
var colHeaderCheckbox = $('#' + colHeaderCheckboxId);
|
var colHeaderCheckbox = $('#' + colHeaderCheckboxId);
|
||||||
|
var tableCaption = $('#' + tableCaptionId);
|
||||||
var hot;
|
var hot;
|
||||||
var defaultOptions;
|
var defaultOptions;
|
||||||
var finalOptions = {};
|
var finalOptions = {};
|
||||||
|
@ -18,6 +20,7 @@ function initTable(id, tableOptions) {
|
||||||
var structureEvent;
|
var structureEvent;
|
||||||
var dataForForm = null;
|
var dataForForm = null;
|
||||||
var isInitialized = false;
|
var isInitialized = false;
|
||||||
|
|
||||||
var getWidth = function() {
|
var getWidth = function() {
|
||||||
return $('.widget-table_input').closest('.sequence-member-inner').width();
|
return $('.widget-table_input').closest('.sequence-member-inner').width();
|
||||||
};
|
};
|
||||||
|
@ -55,6 +58,9 @@ function initTable(id, tableOptions) {
|
||||||
if (dataForForm.hasOwnProperty('first_col_is_header')) {
|
if (dataForForm.hasOwnProperty('first_col_is_header')) {
|
||||||
colHeaderCheckbox.prop('checked', dataForForm.first_col_is_header);
|
colHeaderCheckbox.prop('checked', dataForForm.first_col_is_header);
|
||||||
}
|
}
|
||||||
|
if (dataForForm.hasOwnProperty('table_caption')) {
|
||||||
|
tableCaption.prop('value', dataForForm.table_caption);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!tableOptions.hasOwnProperty('width') || !tableOptions.hasOwnProperty('height')) {
|
if (!tableOptions.hasOwnProperty('width') || !tableOptions.hasOwnProperty('height')) {
|
||||||
|
@ -88,7 +94,8 @@ function initTable(id, tableOptions) {
|
||||||
data: hot.getData(),
|
data: hot.getData(),
|
||||||
cell: getCellsClassnames(),
|
cell: getCellsClassnames(),
|
||||||
first_row_is_table_header: tableHeaderCheckbox.prop('checked'),
|
first_row_is_table_header: tableHeaderCheckbox.prop('checked'),
|
||||||
first_col_is_header: colHeaderCheckbox.prop('checked')
|
first_col_is_header: colHeaderCheckbox.prop('checked'),
|
||||||
|
table_caption: tableCaption.val()
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -123,6 +130,10 @@ function initTable(id, tableOptions) {
|
||||||
persist();
|
persist();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
tableCaption.on('change', function() {
|
||||||
|
persist();
|
||||||
|
});
|
||||||
|
|
||||||
defaultOptions = {
|
defaultOptions = {
|
||||||
afterChange: cellEvent,
|
afterChange: cellEvent,
|
||||||
afterCreateCol: structureEvent,
|
afterCreateCol: structureEvent,
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
{% load table_block_tags %}
|
{% load table_block_tags %}
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
|
{% if table_caption %}
|
||||||
|
<caption>{{ table_caption }}</caption>
|
||||||
|
{% endif %}
|
||||||
{% if table_header %}
|
{% if table_header %}
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
|
|
@ -19,6 +19,16 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<br/>
|
<br/>
|
||||||
|
<div class="field">
|
||||||
|
<label for="{{ widget.attrs.id }}-handsontable-col-caption">{% trans 'Table caption' %}</label>
|
||||||
|
<div class="field-content">
|
||||||
|
<div class="input">
|
||||||
|
<input type="text" id="{{ widget.attrs.id }}-handsontable-col-caption" name="handsontable-col-caption" value="{{ widget.table_caption }}"/>
|
||||||
|
</div>
|
||||||
|
<p class="help">{% trans 'A heading that identifies the overall topic of the table, and is useful for screen reader users' %}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<br/>
|
||||||
<div id="{{ widget.attrs.id }}-handsontable-container"></div>
|
<div id="{{ widget.attrs.id }}-handsontable-container"></div>
|
||||||
{% include 'django/forms/widgets/hidden.html' %}
|
{% include 'django/forms/widgets/hidden.html' %}
|
||||||
<script>initTable("{{ widget.attrs.id|escapejs }}", {{ widget.table_options_json|safe }});</script>
|
<script>initTable("{{ widget.attrs.id|escapejs }}", {{ widget.table_options_json|safe }});</script>
|
||||||
|
|
|
@ -241,6 +241,30 @@ class TestTableBlock(TestCase):
|
||||||
self.assertIn("<div>A fascinating table.</div>", result)
|
self.assertIn("<div>A fascinating table.</div>", result)
|
||||||
|
|
||||||
|
|
||||||
|
def test_table_block_caption_render(self):
|
||||||
|
"""
|
||||||
|
Test a generic render with caption.
|
||||||
|
"""
|
||||||
|
value = {'table_caption': 'caption', 'first_row_is_table_header': False,
|
||||||
|
'first_col_is_header': False,
|
||||||
|
'data': [['Test 1', 'Test 2', 'Test 3'], [None, None, None],
|
||||||
|
[None, None, None]]}
|
||||||
|
block = TableBlock()
|
||||||
|
result = block.render(value)
|
||||||
|
expected = """
|
||||||
|
<table>
|
||||||
|
<caption>caption</caption>
|
||||||
|
<tbody>
|
||||||
|
<tr><td>Test 1</td><td>Test 2</td><td>Test 3</td></tr>
|
||||||
|
<tr><td></td><td></td><td></td></tr>
|
||||||
|
<tr><td></td><td></td><td></td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
"""
|
||||||
|
self.assertHTMLEqual(result, expected)
|
||||||
|
self.assertIn('Test 2', result)
|
||||||
|
|
||||||
|
|
||||||
class TestTableBlockForm(WagtailTestUtils, SimpleTestCase):
|
class TestTableBlockForm(WagtailTestUtils, SimpleTestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
|
Ładowanie…
Reference in New Issue